Also, performed major cleanup of core XSSF classes and test cases git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@700472 13f79535-47bb-0310-9956-ffa450edef68tags/ooxml_20081107
CreationHelper createHelper = wb.getCreationHelper(); | CreationHelper createHelper = wb.getCreationHelper(); | ||||
XSSFSheet s1 = wb.createSheet("Sheet One"); | XSSFSheet s1 = wb.createSheet("Sheet One"); | ||||
XSSFSheet s2 = wb.createSheet("Sheet One"); | |||||
XSSFSheet s2 = wb.createSheet("Sheet Two"); | |||||
// Create a few cells | // Create a few cells | ||||
s1.createRow(0); | s1.createRow(0); |
Palette getCustomPalette(); | Palette getCustomPalette(); | ||||
/** Test only. Do not use */ | |||||
void insertChartRecord(); | |||||
/** | /** | ||||
* Adds a picture to the workbook. | * Adds a picture to the workbook. | ||||
* | * | ||||
/** | /** | ||||
* Gets all pictures from the Workbook. | * Gets all pictures from the Workbook. | ||||
* | * | ||||
* @return the list of pictures (a list of {@link HSSFPictureData} objects.) | |||||
* @return the list of pictures (a list of {@link PictureData} objects.) | |||||
*/ | */ | ||||
List getAllPictures(); | List getAllPictures(); | ||||
==================================================================== */ | ==================================================================== */ | ||||
package org.apache.poi; | package org.apache.poi; | ||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.io.PushbackInputStream; | |||||
import java.io.*; | |||||
import java.util.LinkedList; | import java.util.LinkedList; | ||||
import java.util.List; | import java.util.List; | ||||
import org.apache.poi.poifs.common.POIFSConstants; | import org.apache.poi.poifs.common.POIFSConstants; | ||||
import org.apache.poi.util.IOUtils; | import org.apache.poi.util.IOUtils; | ||||
import org.apache.poi.util.PackageHelper; | |||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.openxml4j.exceptions.InvalidFormatException; | import org.openxml4j.exceptions.InvalidFormatException; | ||||
import org.openxml4j.exceptions.OpenXML4JException; | import org.openxml4j.exceptions.OpenXML4JException; | ||||
import org.openxml4j.opc.*; | |||||
import org.openxml4j.opc.Package; | import org.openxml4j.opc.Package; | ||||
import org.openxml4j.opc.PackagePart; | |||||
import org.openxml4j.opc.PackagePartName; | |||||
import org.openxml4j.opc.PackageRelationship; | |||||
import org.openxml4j.opc.PackageRelationshipCollection; | |||||
import org.openxml4j.opc.PackageRelationshipTypes; | |||||
import org.openxml4j.opc.PackagingURIHelper; | |||||
public abstract class POIXMLDocument { | |||||
public class POIXMLDocument extends POIXMLDocumentPart{ | |||||
public static final String CORE_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; | public static final String CORE_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties"; | ||||
public static final String EXTENDED_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; | public static final String EXTENDED_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties"; | ||||
public static final String CUSTOM_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"; | public static final String CUSTOM_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties"; | ||||
// OLE embeddings relation name | // OLE embeddings relation name | ||||
public static final String OLE_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject"; | public static final String OLE_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject"; | ||||
// Embedded OPC documents relation name | // Embedded OPC documents relation name | ||||
public static final String PACK_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package"; | public static final String PACK_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package"; | ||||
/** The OPC Package */ | /** The OPC Package */ | ||||
private Package pkg; | private Package pkg; | ||||
/** The OPC core Package Part */ | /** The OPC core Package Part */ | ||||
private PackagePart corePart; | private PackagePart corePart; | ||||
/** | /** | ||||
* The properties of the OPC package, opened as needed | * The properties of the OPC package, opened as needed | ||||
*/ | */ | ||||
private POIXMLProperties properties; | private POIXMLProperties properties; | ||||
/** | |||||
* The embedded OLE2 files in the OPC package | |||||
*/ | |||||
protected List<PackagePart> embedds = new LinkedList<PackagePart>(); | |||||
protected POIXMLDocument() {} | |||||
/** | |||||
* The embedded OLE2 files in the OPC package | |||||
*/ | |||||
protected List<PackagePart> embedds; | |||||
protected POIXMLDocument() { | |||||
super(null, null); | |||||
embedds = new LinkedList<PackagePart>(); | |||||
} | |||||
protected POIXMLDocument(Package pkg) throws IOException { | protected POIXMLDocument(Package pkg) throws IOException { | ||||
try { | |||||
this.pkg = pkg; | |||||
PackageRelationship coreDocRelationship = this.pkg.getRelationshipsByType( | |||||
PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0); | |||||
// Get core part | |||||
this.corePart = this.pkg.getPart(coreDocRelationship); | |||||
// Verify it's there | |||||
if(corePart == null) { | |||||
throw new IllegalArgumentException("No core part found for this document! Nothing with " + coreDocRelationship.getRelationshipType() + " present as a relation."); | |||||
} | |||||
} catch (OpenXML4JException e) { | |||||
throw new IOException(e.toString()); | |||||
} | |||||
this(); | |||||
initialize(pkg); | |||||
} | } | ||||
protected POIXMLDocument(String path) throws IOException { | protected POIXMLDocument(String path) throws IOException { | ||||
this(openPackage(path)); | |||||
this(openPackage(path)); | |||||
} | } | ||||
/** | /** | ||||
* Wrapper to open a package, returning an IOException | * Wrapper to open a package, returning an IOException | ||||
* in the event of a problem. | * in the event of a problem. | ||||
throw new IOException(e.toString()); | throw new IOException(e.toString()); | ||||
} | } | ||||
} | } | ||||
public static Package openPackage(InputStream is) throws IOException { | |||||
protected void initialize(Package pkg) throws IOException { | |||||
try { | try { | ||||
return Package.open(is); | |||||
} catch (InvalidFormatException e) { | |||||
this.pkg = pkg; | |||||
PackageRelationship coreDocRelationship = this.pkg.getRelationshipsByType( | |||||
PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0); | |||||
// Get core part | |||||
this.corePart = super.packagePart = this.pkg.getPart(coreDocRelationship); | |||||
// Verify it's there | |||||
if(corePart == null) { | |||||
throw new IllegalArgumentException("No core part found for this document! Nothing with " + coreDocRelationship.getRelationshipType() + " present as a relation."); | |||||
} | |||||
} catch (OpenXML4JException e) { | |||||
throw new IOException(e.toString()); | throw new IOException(e.toString()); | ||||
} | } | ||||
} | } | ||||
protected Package getPackage() { | |||||
public Package getPackage() { | |||||
return this.pkg; | return this.pkg; | ||||
} | } | ||||
protected PackagePart getCorePart() { | protected PackagePart getCorePart() { | ||||
return this.corePart; | return this.corePart; | ||||
} | } | ||||
/** | /** | ||||
* Get the PackagePart that is the target of a relationship. | * Get the PackagePart that is the target of a relationship. | ||||
* | |||||
* | |||||
* @param rel The relationship | * @param rel The relationship | ||||
* @return The target part | * @return The target part | ||||
* @throws InvalidFormatException | * @throws InvalidFormatException | ||||
} | } | ||||
/** | /** | ||||
* Get the PackagePart that is the target of a relationship. | * Get the PackagePart that is the target of a relationship. | ||||
* | |||||
* | |||||
* @param rel The relationship | * @param rel The relationship | ||||
* @param pkg The package to fetch from | * @param pkg The package to fetch from | ||||
* @return The target part | * @return The target part | ||||
return part; | return part; | ||||
} | } | ||||
/** | |||||
* Fetches the (single) PackagePart which is defined as | |||||
* the supplied relation content type of the base | |||||
* package/container, or null if none found. | |||||
* @param relationType The relation content type to search for | |||||
* @throws IllegalArgumentException If we find more than one part of that type | |||||
*/ | |||||
protected PackagePart getSinglePartByRelationType(String relationType) throws IllegalArgumentException, OpenXML4JException { | |||||
PackageRelationshipCollection rels = | |||||
pkg.getRelationshipsByType(relationType); | |||||
if(rels.size() == 0) { | |||||
return null; | |||||
} | |||||
if(rels.size() > 1) { | |||||
throw new IllegalArgumentException("Found " + rels.size() + " relations for the type " + relationType + ", should only ever be one!"); | |||||
} | |||||
PackageRelationship rel = rels.getRelationship(0); | |||||
return getTargetPart(rel); | |||||
} | |||||
/** | |||||
* Retrieves all the PackageParts which are defined as | |||||
* relationships of the base document with the | |||||
* specified content type. | |||||
*/ | |||||
protected PackagePart[] getRelatedByType(String contentType) throws InvalidFormatException { | |||||
PackageRelationshipCollection partsC = | |||||
getCorePart().getRelationshipsByType(contentType); | |||||
PackagePart[] parts = new PackagePart[partsC.size()]; | |||||
int count = 0; | |||||
for (PackageRelationship rel : partsC) { | |||||
parts[count] = getTargetPart(rel); | |||||
count++; | |||||
} | |||||
return parts; | |||||
} | |||||
/** | |||||
* Fetches the (single) PackagePart which is defined as | |||||
* the supplied relation content type of the base | |||||
* package/container, or null if none found. | |||||
* @param relationType The relation content type to search for | |||||
* @throws IllegalArgumentException If we find more than one part of that type | |||||
*/ | |||||
protected PackagePart getSinglePartByRelationType(String relationType) throws IllegalArgumentException, OpenXML4JException { | |||||
PackageRelationshipCollection rels = | |||||
pkg.getRelationshipsByType(relationType); | |||||
if(rels.size() == 0) { | |||||
return null; | |||||
} | |||||
if(rels.size() > 1) { | |||||
throw new IllegalArgumentException("Found " + rels.size() + " relations for the type " + relationType + ", should only ever be one!"); | |||||
} | |||||
PackageRelationship rel = rels.getRelationship(0); | |||||
return getTargetPart(rel); | |||||
} | |||||
/** | |||||
* Retrieves all the PackageParts which are defined as | |||||
* relationships of the base document with the | |||||
* specified content type. | |||||
*/ | |||||
protected PackagePart[] getRelatedByType(String contentType) throws InvalidFormatException { | |||||
PackageRelationshipCollection partsC = | |||||
getCorePart().getRelationshipsByType(contentType); | |||||
PackagePart[] parts = new PackagePart[partsC.size()]; | |||||
int count = 0; | |||||
for (PackageRelationship rel : partsC) { | |||||
parts[count] = getTargetPart(rel); | |||||
count++; | |||||
} | |||||
return parts; | |||||
} | |||||
/** | /** | ||||
* Checks that the supplied InputStream (which MUST | * Checks that the supplied InputStream (which MUST | ||||
* support mark and reset, or be a PushbackInputStream) | |||||
* support mark and reset, or be a PushbackInputStream) | |||||
* has a OOXML (zip) header at the start of it. | * has a OOXML (zip) header at the start of it. | ||||
* If your InputStream does not support mark / reset, | * If your InputStream does not support mark / reset, | ||||
* then wrap it in a PushBackInputStream, then be | * then wrap it in a PushBackInputStream, then be | ||||
* sure to always use that, and not the original! | * sure to always use that, and not the original! | ||||
* @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream | |||||
* @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream | |||||
*/ | */ | ||||
public static boolean hasOOXMLHeader(InputStream inp) throws IOException { | public static boolean hasOOXMLHeader(InputStream inp) throws IOException { | ||||
// We want to peek at the first 4 bytes | |||||
inp.mark(4); | |||||
// We want to peek at the first 4 bytes | |||||
inp.mark(4); | |||||
byte[] header = new byte[4]; | |||||
IOUtils.readFully(inp, header); | |||||
byte[] header = new byte[4]; | |||||
IOUtils.readFully(inp, header); | |||||
// Wind back those 4 bytes | // Wind back those 4 bytes | ||||
if(inp instanceof PushbackInputStream) { | if(inp instanceof PushbackInputStream) { | ||||
PushbackInputStream pin = (PushbackInputStream)inp; | |||||
pin.unread(header); | |||||
PushbackInputStream pin = (PushbackInputStream)inp; | |||||
pin.unread(header); | |||||
} else { | } else { | ||||
inp.reset(); | |||||
inp.reset(); | |||||
} | } | ||||
// Did it match the ooxml zip signature? | |||||
// Did it match the ooxml zip signature? | |||||
return ( | return ( | ||||
header[0] == POIFSConstants.OOXML_FILE_HEADER[0] && | |||||
header[1] == POIFSConstants.OOXML_FILE_HEADER[1] && | |||||
header[2] == POIFSConstants.OOXML_FILE_HEADER[2] && | |||||
header[3] == POIFSConstants.OOXML_FILE_HEADER[3] | |||||
); | |||||
header[0] == POIFSConstants.OOXML_FILE_HEADER[0] && | |||||
header[1] == POIFSConstants.OOXML_FILE_HEADER[1] && | |||||
header[2] == POIFSConstants.OOXML_FILE_HEADER[2] && | |||||
header[3] == POIFSConstants.OOXML_FILE_HEADER[3] | |||||
); | |||||
} | |||||
/** | |||||
* Get the document properties. This gives you access to the | |||||
* core ooxml properties, and the extended ooxml properties. | |||||
*/ | |||||
public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException { | |||||
if(properties == null) { | |||||
properties = new POIXMLProperties(pkg); | |||||
} | |||||
return properties; | |||||
} | } | ||||
/** | |||||
* Get the document properties. This gives you access to the | |||||
* core ooxml properties, and the extended ooxml properties. | |||||
*/ | |||||
public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException { | |||||
if(properties == null) { | |||||
properties = new POIXMLProperties(pkg); | |||||
} | |||||
return properties; | |||||
} | |||||
/** | /** | ||||
* Get the document's embedded files. | * Get the document's embedded files. | ||||
*/ | */ |
/* ==================================================================== | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
==================================================================== */ | |||||
package org.apache.poi; | |||||
import java.io.IOException; | |||||
import java.util.LinkedList; | |||||
import java.util.List; | |||||
import org.apache.xmlbeans.XmlOptions; | |||||
import org.apache.poi.util.POILogger; | |||||
import org.apache.poi.util.POILogFactory; | |||||
import org.openxml4j.exceptions.OpenXML4JException; | |||||
import org.openxml4j.opc.*; | |||||
/** | |||||
* Represents an entry of a OOXML package. | |||||
* | |||||
* <p> | |||||
* Each POIXMLDocumentPart keeps a reference to the underlying a {@link org.openxml4j.opc.PackagePart}. | |||||
* </p> | |||||
* | |||||
* @author Yegor Kozlov | |||||
*/ | |||||
public class POIXMLDocumentPart { | |||||
private static POILogger logger = POILogFactory.getLogger(POIXMLDocumentPart.class); | |||||
public static XmlOptions DEFAULT_XML_OPTIONS; | |||||
static { | |||||
DEFAULT_XML_OPTIONS = new XmlOptions(); | |||||
DEFAULT_XML_OPTIONS.setSaveOuter(); | |||||
DEFAULT_XML_OPTIONS.setUseDefaultNamespace(); | |||||
} | |||||
protected PackagePart packagePart; | |||||
protected PackageRelationship packageRel; | |||||
protected POIXMLDocumentPart parent; | |||||
protected List<POIXMLDocumentPart> relations; | |||||
public POIXMLDocumentPart(PackagePart part, PackageRelationship rel){ | |||||
relations = new LinkedList<POIXMLDocumentPart>(); | |||||
this.packagePart = part; | |||||
this.packageRel = rel; | |||||
} | |||||
/** | |||||
* Provides access to the underlying PackagePart | |||||
* | |||||
* @return the underlying PackagePart | |||||
*/ | |||||
public PackagePart getPackagePart(){ | |||||
return packagePart; | |||||
} | |||||
/** | |||||
* Provides access to the PackageRelationship that identifies this POIXMLDocumentPart | |||||
* | |||||
* @return the PackageRelationship that identifies this POIXMLDocumentPart | |||||
*/ | |||||
public PackageRelationship getPackageRelationship(){ | |||||
return packageRel; | |||||
} | |||||
/** | |||||
* Returns the list of child relations for this POIXMLDocumentPart | |||||
* | |||||
* @return child relations | |||||
*/ | |||||
public List<POIXMLDocumentPart> getRelations(){ | |||||
return relations; | |||||
} | |||||
/** | |||||
* Add a new child POIXMLDocumentPart | |||||
* | |||||
* @param part the child to add | |||||
*/ | |||||
protected void addRelation(POIXMLDocumentPart part){ | |||||
relations.add(part); | |||||
} | |||||
/** | |||||
* Returns the parent POIXMLDocumentPart. All parts except root have not-null parent. | |||||
* | |||||
* @return the parent POIXMLDocumentPart or <code>null</code> for the root element. | |||||
*/ | |||||
public POIXMLDocumentPart getParent(){ | |||||
return parent; | |||||
} | |||||
@Override | |||||
public String toString(){ | |||||
return packagePart.toString(); | |||||
} | |||||
/** | |||||
* Save the content in the underlying package part. | |||||
* Default implemenation is empty meaning that the package part is left unmodified. | |||||
* | |||||
* Sub-classes should override and add logic to marshal the "model" into Ooxml4J. | |||||
* | |||||
* For example, the code saving a generic XML entry may look as follows: | |||||
* <pre><code> | |||||
* protected void commit() throws IOException { | |||||
* PackagePart part = getPackagePart(); | |||||
* OutputStream out = part.getOutputStream(); | |||||
* XmlObject bean = getXmlBean(); //the "model" which holds changes in memory | |||||
* bean.save(out, DEFAULT_XML_OPTIONS); | |||||
* out.close(); | |||||
* </code></pre> | |||||
* | |||||
*/ | |||||
protected void commit() throws IOException { | |||||
} | |||||
/** | |||||
* Save changes in the underlying OOXML package. | |||||
*/ | |||||
protected void save() throws IOException{ | |||||
commit(); | |||||
for(POIXMLDocumentPart p : relations){ | |||||
p.save(); | |||||
} | |||||
} | |||||
/** | |||||
* Create a new child POIXMLDocumentPart | |||||
* | |||||
* @param descriptor the part descriptor | |||||
* @param cls the Class object identifying the type of instance to create | |||||
* @return the created child POIXMLDocumentPart | |||||
*/ | |||||
protected POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, Class<? extends POIXMLDocumentPart> cls){ | |||||
return createRelationship(descriptor, cls, -1); | |||||
} | |||||
/** | |||||
* Create a new child POIXMLDocumentPart | |||||
* | |||||
* @param descriptor the part descriptor | |||||
* @param cls the Class object identifying the type of instance to create | |||||
* @param idx part number | |||||
* @return the created child POIXMLDocumentPart | |||||
*/ | |||||
protected POIXMLDocumentPart createRelationship(POIXMLRelation descriptor, Class<? extends POIXMLDocumentPart> cls, int idx){ | |||||
try { | |||||
PackagePartName ppName = PackagingURIHelper.createPartName(descriptor.getFileName(idx)); | |||||
PackageRelationship rel = | |||||
packagePart.addRelationship(ppName, TargetMode.INTERNAL, descriptor.getRelation()); | |||||
PackagePart part = packagePart.getPackage().createPart(ppName, descriptor.getContentType()); | |||||
POIXMLDocumentPart doc = cls.newInstance(); | |||||
doc.packageRel = rel; | |||||
doc.packagePart = part; | |||||
addRelation(doc); | |||||
return doc; | |||||
} catch (Exception e){ | |||||
throw new POIXMLException(e); | |||||
} | |||||
} | |||||
/** | |||||
* Iterate through the underlying PackagePart and create child POIXMLFactory instances | |||||
* using the specified factory | |||||
* | |||||
* @param factory the factory object that creates POIXMLFactory instances | |||||
*/ | |||||
protected void read(POIXMLFactory factory) throws OpenXML4JException { | |||||
PackageRelationshipCollection rels = packagePart.getRelationships(); | |||||
for (PackageRelationship rel : rels) { | |||||
if(rel.getTargetMode() == TargetMode.INTERNAL){ | |||||
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); | |||||
PackagePart p = packagePart.getPackage().getPart(relName); | |||||
if(p == null) { | |||||
logger.log(POILogger.ERROR, "Skipped invalid entry " + rel.getTargetURI()); | |||||
continue; | |||||
} | |||||
POIXMLDocumentPart childPart = factory.create(rel, p); | |||||
childPart.parent = this; | |||||
addRelation(childPart); | |||||
if(p.hasRelationships()) childPart.read(factory); | |||||
} | |||||
} | |||||
} | |||||
} |
/* ==================================================================== | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
==================================================================== */ | |||||
package org.apache.poi; | |||||
/** | |||||
* Indicates a generic OOXML error. | |||||
* | |||||
* @author Yegor Kozlov | |||||
*/ | |||||
public class POIXMLException extends RuntimeException{ | |||||
/** | |||||
* Create a new <code>POIXMLException</code> with no | |||||
* detail mesage. | |||||
*/ | |||||
public POIXMLException() { | |||||
super(); | |||||
} | |||||
/** | |||||
* Create a new <code>POIXMLException</code> with | |||||
* the <code>String</code> specified as an error message. | |||||
* | |||||
* @param msg The error message for the exception. | |||||
*/ | |||||
public POIXMLException(String msg) { | |||||
super(msg); | |||||
} | |||||
/** | |||||
* Create a new <code>POIXMLException</code> with | |||||
* the <code>String</code> specified as an error message and the cause. | |||||
* | |||||
* @param msg The error message for the exception. | |||||
* @param cause the cause (which is saved for later retrieval by the | |||||
* {@link #getCause()} method). (A <tt>null</tt> value is | |||||
* permitted, and indicates that the cause is nonexistent or | |||||
* unknown.) | |||||
*/ | |||||
public POIXMLException(String msg, Throwable cause) { | |||||
super(msg, cause); | |||||
} | |||||
/** | |||||
* Create a new <code>POIXMLException</code> with | |||||
* the specified cause. | |||||
* | |||||
* @param cause the cause (which is saved for later retrieval by the | |||||
* {@link #getCause()} method). (A <tt>null</tt> value is | |||||
* permitted, and indicates that the cause is nonexistent or | |||||
* unknown.) | |||||
*/ | |||||
public POIXMLException(Throwable cause) { | |||||
super(cause); | |||||
} | |||||
} |
/* ==================================================================== | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
==================================================================== */ | |||||
package org.apache.poi; | |||||
import org.openxml4j.opc.PackageRelationship; | |||||
import org.openxml4j.opc.PackagePart; | |||||
/** | |||||
* Defines a factory API that enables sub-classes to create instances of <code>POIXMLDocumentPart</code> | |||||
* | |||||
* @author Yegor Kozlov | |||||
*/ | |||||
public class POIXMLFactory { | |||||
/** | |||||
* Creates a new instance of a {@link POIXMLDocumentPart} | |||||
* | |||||
* @param rel the package part relationship | |||||
* @param part the PackagePart representing the created instance | |||||
* @return A new instance of a POIXMLDocumentPart. | |||||
*/ | |||||
public POIXMLDocumentPart create(PackageRelationship rel, PackagePart part){ | |||||
return new POIXMLDocumentPart(part, rel); | |||||
} | |||||
} |
/* ==================================================================== | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
==================================================================== */ | |||||
package org.apache.poi; | |||||
/** | |||||
* Represents a descriptor of a OOXML relation. | |||||
* | |||||
* @author Yegor Kozlov | |||||
*/ | |||||
public class POIXMLRelation { | |||||
protected String _type; | |||||
protected String _relation; | |||||
protected String _defaultName; | |||||
/** | |||||
* Instantiates a POIXMLRelation. | |||||
*/ | |||||
protected POIXMLRelation(String type, String rel, String defaultName) { | |||||
_type = type; | |||||
_relation = rel; | |||||
_defaultName = defaultName; | |||||
} | |||||
public String getContentType() { return _type; } | |||||
public String getRelation() { return _relation; } | |||||
public String getDefaultFileName() { return _defaultName; } | |||||
/** | |||||
* Returns the filename for the nth one of these, | |||||
* eg /xl/comments4.xml | |||||
*/ | |||||
public String getFileName(int index) { | |||||
if(_defaultName.indexOf("#") == -1) { | |||||
// Generic filename in all cases | |||||
return getDefaultFileName(); | |||||
} | |||||
return _defaultName.replace("#", Integer.toString(index)); | |||||
} | |||||
} |
/* ==================================================================== | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
==================================================================== */ | |||||
package org.apache.poi.util; | |||||
import org.openxml4j.opc.*; | |||||
import org.openxml4j.opc.Package; | |||||
import org.openxml4j.opc.internal.PackagePropertiesPart; | |||||
import org.openxml4j.opc.internal.marshallers.PackagePropertiesMarshaller; | |||||
import org.openxml4j.exceptions.OpenXML4JException; | |||||
import org.apache.poi.util.IOUtils; | |||||
import java.io.*; | |||||
import java.util.ArrayList; | |||||
import java.lang.reflect.Method; | |||||
/** | |||||
* Provides handy methods to work with OOXML packages | |||||
* | |||||
* @author Yegor Kozlov | |||||
*/ | |||||
public class PackageHelper { | |||||
/** | |||||
* Clone the specified package. | |||||
* | |||||
* @param pkg the package to clone | |||||
* @return the cloned package | |||||
*/ | |||||
public static Package clone(Package pkg) throws OpenXML4JException, IOException { | |||||
return clone(pkg, createTempFile()); | |||||
} | |||||
/** | |||||
* Clone the specified package. | |||||
* | |||||
* @param pkg the package to clone | |||||
* @param file the destination file | |||||
* @return the cloned package | |||||
*/ | |||||
public static Package clone(Package pkg, File file) throws OpenXML4JException, IOException { | |||||
String path = file.getAbsolutePath(); | |||||
Package dest = Package.create(path); | |||||
PackageRelationshipCollection rels = pkg.getRelationships(); | |||||
for (PackageRelationship rel : rels) { | |||||
PackagePart part = pkg.getPart(rel); | |||||
PackagePart part_tgt; | |||||
if (rel.getRelationshipType().equals(PackageRelationshipTypes.CORE_PROPERTIES)) { | |||||
copyProperties(pkg.getPackageProperties(), dest.getPackageProperties()); | |||||
continue; | |||||
} else { | |||||
dest.addRelationship(part.getPartName(), rel.getTargetMode(), rel.getRelationshipType()); | |||||
part_tgt = dest.createPart(part.getPartName(), part.getContentType()); | |||||
} | |||||
OutputStream out = part_tgt.getOutputStream(); | |||||
IOUtils.copy(part.getInputStream(), out); | |||||
out.close(); | |||||
if(part.hasRelationships()) { | |||||
copy(pkg, part, dest, part_tgt); | |||||
} | |||||
} | |||||
dest.close(); | |||||
//the temp file will be deleted when JVM terminates | |||||
new File(path).deleteOnExit(); | |||||
return Package.open(path); | |||||
} | |||||
/** | |||||
* | |||||
* @return | |||||
* @throws IOException | |||||
*/ | |||||
public static File createTempFile() throws IOException { | |||||
File file = File.createTempFile("poi-ooxml-", ".tmp"); | |||||
//there is no way to pass an existing file to Package.create(file), | |||||
//delete first, the file will be re-created in Packe.create(file) | |||||
file.delete(); | |||||
file.deleteOnExit(); | |||||
return file; | |||||
} | |||||
/** | |||||
* Recursively copy package parts to the destination package | |||||
*/ | |||||
private static void copy(Package pkg, PackagePart part, Package tgt, PackagePart part_tgt) throws OpenXML4JException, IOException { | |||||
PackageRelationshipCollection rels = part.getRelationships(); | |||||
if(rels != null) for (PackageRelationship rel : rels) { | |||||
PackagePart p; | |||||
if(rel.getTargetMode() == TargetMode.EXTERNAL){ | |||||
part_tgt.addExternalRelationship(rel.getTargetURI().toString(), rel.getRelationshipType(), rel.getId()); | |||||
//external relations don't have associated package parts | |||||
continue; | |||||
} else { | |||||
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI()); | |||||
p = pkg.getPart(relName); | |||||
} | |||||
part_tgt.addRelationship(p.getPartName(), rel.getTargetMode(), rel.getRelationshipType(), rel.getId()); | |||||
PackagePart dest; | |||||
if(!tgt.containPart(p.getPartName())){ | |||||
dest = tgt.createPart(p.getPartName(), p.getContentType()); | |||||
OutputStream out = dest.getOutputStream(); | |||||
IOUtils.copy(p.getInputStream(), out); | |||||
out.close(); | |||||
copy(pkg, p, tgt, dest); | |||||
} | |||||
} | |||||
} | |||||
/** | |||||
* Copy core package properties | |||||
* | |||||
* @param src source properties | |||||
* @param tgt target properties | |||||
*/ | |||||
private static void copyProperties(PackageProperties src, PackageProperties tgt){ | |||||
tgt.setCategoryProperty(src.getCategoryProperty().getValue()); | |||||
tgt.setContentStatusProperty(src.getContentStatusProperty().getValue()); | |||||
tgt.setContentTypeProperty(src.getContentTypeProperty().getValue()); | |||||
tgt.setCreatorProperty(src.getCreatorProperty().getValue()); | |||||
tgt.setDescriptionProperty(src.getDescriptionProperty().getValue()); | |||||
tgt.setIdentifierProperty(src.getIdentifierProperty().getValue()); | |||||
tgt.setKeywordsProperty(src.getKeywordsProperty().getValue()); | |||||
tgt.setLanguageProperty(src.getLanguageProperty().getValue()); | |||||
tgt.setRevisionProperty(src.getRevisionProperty().getValue()); | |||||
tgt.setSubjectProperty(src.getSubjectProperty().getValue()); | |||||
tgt.setTitleProperty(src.getTitleProperty().getValue()); | |||||
tgt.setVersionProperty(src.getVersionProperty().getValue()); | |||||
} | |||||
} |
import javax.xml.parsers.DocumentBuilderFactory; | import javax.xml.parsers.DocumentBuilderFactory; | ||||
import javax.xml.parsers.DocumentBuilder; | import javax.xml.parsers.DocumentBuilder; | ||||
import java.io.FileOutputStream; | |||||
import java.io.File; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.io.*; | |||||
import java.util.zip.ZipFile; | import java.util.zip.ZipFile; | ||||
import java.util.zip.ZipEntry; | import java.util.zip.ZipEntry; | ||||
import java.util.Enumeration; | import java.util.Enumeration; | ||||
FileOutputStream out = new FileOutputStream(f); | FileOutputStream out = new FileOutputStream(f); | ||||
if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){ | if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){ | ||||
//pass the xml through the Xerces serializer to produce nicely formatted output | |||||
Document doc = builder.parse(zip.getInputStream(entry)); | |||||
OutputFormat format = new OutputFormat( doc ); | |||||
format.setIndenting(true); | |||||
XMLSerializer serial = new XMLSerializer( out, format ); | |||||
serial.asDOMSerializer(); | |||||
serial.serialize( doc.getDocumentElement() ); | |||||
try { | |||||
//pass the xml through the Xerces serializer to produce nicely formatted output | |||||
Document doc = builder.parse(zip.getInputStream(entry)); | |||||
OutputFormat format = new OutputFormat( doc ); | |||||
format.setIndenting(true); | |||||
XMLSerializer serial = new XMLSerializer( out, format ); | |||||
serial.asDOMSerializer(); | |||||
serial.serialize( doc.getDocumentElement() ); | |||||
} catch (Exception e){ | |||||
System.err.println("Failed to parse " + entry.getName() + ", dumping raw content"); | |||||
dump(zip.getInputStream(entry), out); | |||||
} | |||||
} else { | } else { | ||||
int pos; | |||||
byte[] chunk = new byte[2048]; | |||||
InputStream is = zip.getInputStream(entry); | |||||
while((pos = is.read(chunk)) > 0) out.write(chunk, 0, pos); | |||||
dump(zip.getInputStream(entry), out); | |||||
} | } | ||||
out.close(); | out.close(); | ||||
} | } | ||||
} | } | ||||
protected static void dump(InputStream is, OutputStream out) throws IOException{ | |||||
int pos; | |||||
byte[] chunk = new byte[2048]; | |||||
while((pos = is.read(chunk)) > 0) out.write(chunk, 0, pos); | |||||
} | |||||
} | } |
for (int i = 0; i < args.length; i++) { | for (int i = 0; i < args.length; i++) { | ||||
XSSFWorkbook wb = new XSSFWorkbook(args[i]); | XSSFWorkbook wb = new XSSFWorkbook(args[i]); | ||||
System.out.println("wb.getNumberOfSheets(): " + wb.getNumberOfSheets()); | |||||
int sep = args[i].lastIndexOf('.'); | int sep = args[i].lastIndexOf('.'); | ||||
String outfile = args[i].substring(0, sep) + "-save.xlsx"; | String outfile = args[i].substring(0, sep) + "-save.xlsx"; | ||||
FileOutputStream out = new FileOutputStream(outfile); | FileOutputStream out = new FileOutputStream(outfile); |
import org.apache.poi.ss.usermodel.CommentsSource; | import org.apache.poi.ss.usermodel.CommentsSource; | ||||
import org.apache.poi.ss.util.CellReference; | import org.apache.poi.ss.util.CellReference; | ||||
import org.apache.poi.xssf.usermodel.XSSFComment; | import org.apache.poi.xssf.usermodel.XSSFComment; | ||||
import org.apache.poi.POIXMLDocumentPart; | |||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.apache.xmlbeans.XmlOptions; | import org.apache.xmlbeans.XmlOptions; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument; | ||||
import org.openxml4j.opc.PackagePart; | |||||
import org.openxml4j.opc.PackageRelationship; | |||||
public class CommentsTable implements CommentsSource, XSSFModel { | |||||
private CTComments comments; | |||||
public CommentsTable(InputStream is) throws IOException { | |||||
readFrom(is); | |||||
} | |||||
public CommentsTable() { | |||||
comments = CTComments.Factory.newInstance(); | |||||
} | |||||
/** | |||||
* For unit testing only! | |||||
*/ | |||||
public CommentsTable(CTComments comments) { | |||||
this.comments = comments; | |||||
} | |||||
public void readFrom(InputStream is) throws IOException { | |||||
try { | |||||
CommentsDocument doc = CommentsDocument.Factory.parse(is); | |||||
comments = doc.getComments(); | |||||
public class CommentsTable extends POIXMLDocumentPart implements CommentsSource, XSSFModel { | |||||
private CTComments comments; | |||||
public CommentsTable(InputStream is) throws IOException { | |||||
super(null, null); | |||||
readFrom(is); | |||||
} | |||||
public CommentsTable() { | |||||
super(null, null); | |||||
comments = CTComments.Factory.newInstance(); | |||||
} | |||||
/** | |||||
* For unit testing only! | |||||
*/ | |||||
public CommentsTable(CTComments comments) { | |||||
super(null, null); | |||||
this.comments = comments; | |||||
} | |||||
public CommentsTable(PackagePart part, PackageRelationship rel) throws IOException { | |||||
super(part, rel); | |||||
readFrom(part.getInputStream()); | |||||
} | |||||
public void readFrom(InputStream is) throws IOException { | |||||
try { | |||||
CommentsDocument doc = CommentsDocument.Factory.parse(is); | |||||
comments = doc.getComments(); | |||||
} catch (XmlException e) { | } catch (XmlException e) { | ||||
throw new IOException(e.getLocalizedMessage()); | throw new IOException(e.getLocalizedMessage()); | ||||
} | } | ||||
} | |||||
public void writeTo(OutputStream out) throws IOException { | |||||
} | |||||
public void writeTo(OutputStream out) throws IOException { | |||||
XmlOptions options = new XmlOptions(); | XmlOptions options = new XmlOptions(); | ||||
options.setSaveOuter(); | options.setSaveOuter(); | ||||
options.setUseDefaultNamespace(); | options.setUseDefaultNamespace(); | ||||
// Requests use of whitespace for easier reading | // Requests use of whitespace for easier reading | ||||
//options.setSavePrettyPrint(); | //options.setSavePrettyPrint(); | ||||
CommentsDocument doc = CommentsDocument.Factory.newInstance(options); | CommentsDocument doc = CommentsDocument.Factory.newInstance(options); | ||||
doc.setComments(comments); | doc.setComments(comments); | ||||
doc.save(out, options); | doc.save(out, options); | ||||
} | |||||
public int getNumberOfComments() { | |||||
return comments.getCommentList().sizeOfCommentArray(); | |||||
} | |||||
public int getNumberOfAuthors() { | |||||
return getCommentsAuthors().sizeOfAuthorArray(); | |||||
} | |||||
public String getAuthor(long authorId) { | |||||
return getCommentsAuthors().getAuthorArray((int)authorId); | |||||
} | |||||
public int findAuthor(String author) { | |||||
for (int i = 0 ; i < getCommentsAuthors().sizeOfAuthorArray() ; i++) { | |||||
if (getCommentsAuthors().getAuthorArray(i).equals(author)) { | |||||
return i; | |||||
} | |||||
} | |||||
return addNewAuthor(author); | |||||
} | |||||
public XSSFComment findCellComment(int row, int column) { | |||||
return findCellComment( | |||||
(new CellReference(row, column)).formatAsString() ); | |||||
} | |||||
public XSSFComment findCellComment(String cellRef) { | |||||
for (CTComment comment : getCommentsList().getCommentArray()) { | |||||
if (cellRef.equals(comment.getRef())) { | |||||
return new XSSFComment(this, comment); | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Generates a new XSSFComment, associated with the | |||||
* current comments list. | |||||
*/ | |||||
public XSSFComment addComment() { | |||||
return new XSSFComment(this, getCommentsList().addNewComment()); | |||||
} | |||||
private CTCommentList getCommentsList() { | |||||
if (comments.getCommentList() == null) { | |||||
comments.addNewCommentList(); | |||||
} | |||||
return comments.getCommentList(); | |||||
} | |||||
private CTAuthors getCommentsAuthors() { | |||||
if (comments.getAuthors() == null) { | |||||
comments.addNewAuthors(); | |||||
} | |||||
return comments.getAuthors(); | |||||
} | |||||
private int addNewAuthor(String author) { | |||||
int index = getCommentsAuthors().sizeOfAuthorArray(); | |||||
getCommentsAuthors().insertAuthor(index, author); | |||||
return index; | |||||
} | |||||
} | |||||
@Override | |||||
protected void commit() throws IOException { | |||||
PackagePart part = getPackagePart(); | |||||
OutputStream out = part.getOutputStream(); | |||||
writeTo(out); | |||||
out.close(); | |||||
} | |||||
public int getNumberOfComments() { | |||||
return comments.getCommentList().sizeOfCommentArray(); | |||||
} | |||||
public int getNumberOfAuthors() { | |||||
return getCommentsAuthors().sizeOfAuthorArray(); | |||||
} | |||||
public String getAuthor(long authorId) { | |||||
return getCommentsAuthors().getAuthorArray((int)authorId); | |||||
} | |||||
public int findAuthor(String author) { | |||||
for (int i = 0 ; i < getCommentsAuthors().sizeOfAuthorArray() ; i++) { | |||||
if (getCommentsAuthors().getAuthorArray(i).equals(author)) { | |||||
return i; | |||||
} | |||||
} | |||||
return addNewAuthor(author); | |||||
} | |||||
public XSSFComment findCellComment(int row, int column) { | |||||
return findCellComment( | |||||
(new CellReference(row, column)).formatAsString() ); | |||||
} | |||||
public XSSFComment findCellComment(String cellRef) { | |||||
for (CTComment comment : getCommentsList().getCommentArray()) { | |||||
if (cellRef.equals(comment.getRef())) { | |||||
return new XSSFComment(this, comment); | |||||
} | |||||
} | |||||
return null; | |||||
} | |||||
/** | |||||
* Generates a new XSSFComment, associated with the | |||||
* current comments list. | |||||
*/ | |||||
public XSSFComment addComment() { | |||||
return new XSSFComment(this, getCommentsList().addNewComment()); | |||||
} | |||||
private CTCommentList getCommentsList() { | |||||
if (comments.getCommentList() == null) { | |||||
comments.addNewCommentList(); | |||||
} | |||||
return comments.getCommentList(); | |||||
} | |||||
private CTAuthors getCommentsAuthors() { | |||||
if (comments.getAuthors() == null) { | |||||
comments.addNewAuthors(); | |||||
} | |||||
return comments.getAuthors(); | |||||
} | |||||
private int addNewAuthor(String author) { | |||||
int index = getCommentsAuthors().sizeOfAuthorArray(); | |||||
getCommentsAuthors().insertAuthor(index, author); | |||||
return index; | |||||
} | |||||
} | } |
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.apache.xmlbeans.XmlOptions; | import org.apache.xmlbeans.XmlOptions; | ||||
import org.apache.poi.POIXMLDocumentPart; | |||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; | |||||
import org.openxml4j.opc.PackagePart; | |||||
import org.openxml4j.opc.PackageRelationship; | |||||
/** | /** | ||||
* @author Nick Birch | * @author Nick Birch | ||||
* @author Yegor Kozlov | * @author Yegor Kozlov | ||||
*/ | */ | ||||
public class SharedStringsTable implements SharedStringSource, XSSFModel { | |||||
public class SharedStringsTable extends POIXMLDocumentPart implements XSSFModel, SharedStringSource { | |||||
/** | /** | ||||
* Array of individual string items in the Shared String table. | * Array of individual string items in the Shared String table. | ||||
* @throws IOException if an error occurs while reading. | * @throws IOException if an error occurs while reading. | ||||
*/ | */ | ||||
public SharedStringsTable(InputStream is) throws IOException { | public SharedStringsTable(InputStream is) throws IOException { | ||||
super(null, null); | |||||
readFrom(is); | readFrom(is); | ||||
} | } | ||||
/** | |||||
* Create a new, empty SharedStringsTable | |||||
*/ | |||||
public SharedStringsTable() { | public SharedStringsTable() { | ||||
count = uniqueCount = 0; | |||||
super(null, null); | |||||
} | |||||
public SharedStringsTable(PackagePart part, PackageRelationship rel) throws IOException { | |||||
super(part, rel); | |||||
readFrom(part.getInputStream()); | |||||
} | } | ||||
/** | /** | ||||
sst.setSiArray(ctr); | sst.setSiArray(ctr); | ||||
doc.save(out, options); | doc.save(out, options); | ||||
} | } | ||||
@Override | |||||
protected void commit() throws IOException { | |||||
PackagePart part = getPackagePart(); | |||||
OutputStream out = part.getOutputStream(); | |||||
writeTo(out); | |||||
out.close(); | |||||
} | |||||
} | } |
import org.apache.poi.xssf.usermodel.XSSFFont; | import org.apache.poi.xssf.usermodel.XSSFFont; | ||||
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder; | import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder; | ||||
import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill; | import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill; | ||||
import org.apache.poi.POIXMLDocumentPart; | |||||
import org.apache.xmlbeans.XmlException; | import org.apache.xmlbeans.XmlException; | ||||
import org.apache.xmlbeans.XmlOptions; | import org.apache.xmlbeans.XmlOptions; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument; | ||||
import org.openxml4j.opc.PackagePart; | |||||
import org.openxml4j.opc.PackageRelationship; | |||||
/** | /** | ||||
* Table of styles shared across all sheets in a workbook. | * Table of styles shared across all sheets in a workbook. | ||||
* | * | ||||
* @author ugo | * @author ugo | ||||
*/ | */ | ||||
public class StylesTable implements StylesSource, XSSFModel { | |||||
public class StylesTable extends POIXMLDocumentPart implements StylesSource, XSSFModel { | |||||
private final Hashtable<Long,String> numberFormats = new Hashtable<Long,String>(); | private final Hashtable<Long,String> numberFormats = new Hashtable<Long,String>(); | ||||
private final List<CTFont> fonts = new ArrayList<CTFont>(); | private final List<CTFont> fonts = new ArrayList<CTFont>(); | ||||
private final List<CTFill> fills = new LinkedList<CTFill>(); | private final List<CTFill> fills = new LinkedList<CTFill>(); | ||||
* @throws IOException if an error occurs while reading. | * @throws IOException if an error occurs while reading. | ||||
*/ | */ | ||||
public StylesTable(InputStream is) throws IOException { | public StylesTable(InputStream is) throws IOException { | ||||
super(null, null); | |||||
readFrom(is); | readFrom(is); | ||||
} | } | ||||
/** | /** | ||||
* Create a new, empty StylesTable | * Create a new, empty StylesTable | ||||
*/ | */ | ||||
public StylesTable() { | public StylesTable() { | ||||
super(null, null); | |||||
doc = StyleSheetDocument.Factory.newInstance(); | doc = StyleSheetDocument.Factory.newInstance(); | ||||
doc.addNewStyleSheet(); | doc.addNewStyleSheet(); | ||||
// Initialization required in order to make the document readable by MSExcel | // Initialization required in order to make the document readable by MSExcel | ||||
initialize(); | initialize(); | ||||
} | } | ||||
public StylesTable(PackagePart part, PackageRelationship rel) throws IOException { | |||||
super(part, rel); | |||||
readFrom(part.getInputStream()); | |||||
} | |||||
/** | /** | ||||
* Read this shared styles table from an XML file. | * Read this shared styles table from an XML file. | ||||
* | * | ||||
doc.save(out, options); | doc.save(out, options); | ||||
} | } | ||||
@Override | |||||
protected void commit() throws IOException { | |||||
PackagePart part = getPackagePart(); | |||||
OutputStream out = part.getOutputStream(); | |||||
writeTo(out); | |||||
out.close(); | |||||
} | |||||
private long putBorder(XSSFCellBorder border, List<CTBorder> borders) { | private long putBorder(XSSFCellBorder border, List<CTBorder> borders) { | ||||
return border.putBorder((LinkedList<CTBorder>) borders); // TODO - use List instead of LinkedList | return border.putBorder((LinkedList<CTBorder>) borders); // TODO - use List instead of LinkedList | ||||
} | } |
public class XSSFCreationHelper implements CreationHelper { | public class XSSFCreationHelper implements CreationHelper { | ||||
private XSSFWorkbook workbook; | private XSSFWorkbook workbook; | ||||
private XSSFDataFormat dataFormat; | |||||
XSSFCreationHelper(XSSFWorkbook wb) { | XSSFCreationHelper(XSSFWorkbook wb) { | ||||
workbook = wb; | workbook = wb; | ||||
// Create the things we only ever need one of | |||||
dataFormat = new XSSFDataFormat(workbook.getStylesSource()); | |||||
} | } | ||||
/** | /** | ||||
* Creates a new XSSFRichTextString for you. | * Creates a new XSSFRichTextString for you. | ||||
*/ | */ | ||||
public RichTextString createRichTextString(String text) { | |||||
public XSSFRichTextString createRichTextString(String text) { | |||||
return new XSSFRichTextString(text); | return new XSSFRichTextString(text); | ||||
} | } | ||||
public DataFormat createDataFormat() { | |||||
return dataFormat; | |||||
public XSSFDataFormat createDataFormat() { | |||||
return workbook.createDataFormat(); | |||||
} | } | ||||
public Hyperlink createHyperlink(int type) { | |||||
public XSSFHyperlink createHyperlink(int type) { | |||||
return new XSSFHyperlink(type); | return new XSSFHyperlink(type); | ||||
} | } | ||||
} | } |
/* ==================================================================== | |||||
Licensed to the Apache Software Foundation (ASF) under one or more | |||||
contributor license agreements. See the NOTICE file distributed with | |||||
this work for additional information regarding copyright ownership. | |||||
The ASF licenses this file to You under the Apache License, Version 2.0 | |||||
(the "License"); you may not use this file except in compliance with | |||||
the License. You may obtain a copy of the License at | |||||
http://www.apache.org/licenses/LICENSE-2.0 | |||||
Unless required by applicable law or agreed to in writing, software | |||||
distributed under the License is distributed on an "AS IS" BASIS, | |||||
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |||||
See the License for the specific language governing permissions and | |||||
limitations under the License. | |||||
==================================================================== */ | |||||
package org.apache.poi.xssf.usermodel; | |||||
import org.apache.poi.POIXMLDocumentPart; | |||||
import org.apache.poi.POIXMLFactory; | |||||
import org.apache.poi.POIXMLException; | |||||
import org.apache.poi.xssf.model.SharedStringsTable; | |||||
import org.apache.poi.xssf.model.StylesTable; | |||||
import org.apache.poi.xssf.model.CommentsTable; | |||||
import org.openxml4j.opc.PackageRelationship; | |||||
import org.openxml4j.opc.PackagePart; | |||||
import java.util.Map; | |||||
import java.util.HashMap; | |||||
import java.lang.reflect.Constructor; | |||||
/** | |||||
* Instantiates sub-classes of POIXMLDocumentPart depending on their relationship type | |||||
* | |||||
* @author Yegor Kozlov | |||||
*/ | |||||
public class XSSFFactory extends POIXMLFactory { | |||||
protected static Map<String, Class> parts = new HashMap<String, Class>(); | |||||
static { | |||||
parts.put(XSSFRelation.WORKSHEET.getRelation(), XSSFSheet.class); | |||||
parts.put(XSSFRelation.SHARED_STRINGS.getRelation(), SharedStringsTable.class); | |||||
parts.put(XSSFRelation.STYLES.getRelation(), StylesTable.class); | |||||
parts.put(XSSFRelation.SHEET_COMMENTS.getRelation(), CommentsTable.class); | |||||
} | |||||
public POIXMLDocumentPart create(PackageRelationship rel, PackagePart p){ | |||||
Class cls = parts.get(rel.getRelationshipType()); | |||||
if(cls == null) return super.create(rel, p); | |||||
try { | |||||
Constructor<? extends POIXMLDocumentPart> constructor = cls.getConstructor(PackagePart.class, PackageRelationship.class); | |||||
return constructor.newInstance(p, rel); | |||||
} catch (Exception e){ | |||||
throw new POIXMLException(e); | |||||
} | |||||
} | |||||
} |
import java.util.List; | import java.util.List; | ||||
import org.apache.poi.POIXMLDocument; | import org.apache.poi.POIXMLDocument; | ||||
import org.apache.poi.POIXMLRelation; | |||||
import org.apache.poi.util.POILogFactory; | import org.apache.poi.util.POILogFactory; | ||||
import org.apache.poi.util.POILogger; | import org.apache.poi.util.POILogger; | ||||
import org.apache.poi.xssf.model.BinaryPart; | import org.apache.poi.xssf.model.BinaryPart; | ||||
/** | /** | ||||
* | * | ||||
*/ | */ | ||||
public final class XSSFRelation<W extends XSSFModel> { | |||||
public final class XSSFRelation<W extends XSSFModel> extends POIXMLRelation { | |||||
public static final XSSFRelation WORKBOOK = new XSSFRelation( | public static final XSSFRelation WORKBOOK = new XSSFRelation( | ||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", | "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml", | ||||
return new XSSFRelation<R>(type, rel, defaultName, cls); | return new XSSFRelation<R>(type, rel, defaultName, cls); | ||||
} | } | ||||
private String _type; | |||||
private String _relation; | |||||
private String _defaultName; | |||||
private Constructor<W> _constructor; | private Constructor<W> _constructor; | ||||
private final boolean _constructorTakesTwoArgs; | private final boolean _constructorTakesTwoArgs; | ||||
private XSSFRelation(String type, String rel, String defaultName, Class<W> cls) { | private XSSFRelation(String type, String rel, String defaultName, Class<W> cls) { | ||||
_type = type; | |||||
_relation = rel; | |||||
_defaultName = defaultName; | |||||
super(type, rel, defaultName); | |||||
if (cls == null) { | if (cls == null) { | ||||
_constructor = null; | _constructor = null; | ||||
_constructorTakesTwoArgs = false; | _constructorTakesTwoArgs = false; | ||||
_constructorTakesTwoArgs = twoArg; | _constructorTakesTwoArgs = twoArg; | ||||
} | } | ||||
} | } | ||||
public String getContentType() { return _type; } | |||||
public String getRelation() { return _relation; } | |||||
public String getDefaultFileName() { return _defaultName; } | |||||
/** | /** | ||||
* Does one of these exist for the given core | * Does one of these exist for the given core | ||||
* package part? | * package part? |
private CTBorderPr getBorder(BorderSide side) { | private CTBorderPr getBorder(BorderSide side) { | ||||
switch (side) { | switch (side) { | ||||
case TOP: return border.getTop(); | |||||
case RIGHT: return border.getRight(); | |||||
case BOTTOM: return border.getBottom(); | |||||
case LEFT: return border.getLeft(); | |||||
case TOP: { | |||||
CTBorderPr borderPr = border.isSetTop() ? border.getTop() : border.addNewTop(); | |||||
return borderPr; | |||||
} | |||||
case RIGHT: { | |||||
CTBorderPr borderPr = border.isSetRight() ? border.getRight() : border.addNewRight(); | |||||
return borderPr; | |||||
} | |||||
case BOTTOM:{ | |||||
CTBorderPr borderPr = border.isSetBottom() ? border.getBottom() : border.addNewBottom(); | |||||
return borderPr; | |||||
} | |||||
case LEFT:{ | |||||
CTBorderPr borderPr = border.isSetLeft() ? border.getLeft() : border.addNewLeft(); | |||||
return borderPr; | |||||
} | |||||
default: throw new IllegalArgumentException("No suitable side specified for the border"); | default: throw new IllegalArgumentException("No suitable side specified for the border"); | ||||
} | } | ||||
} | } |
package org.apache.poi.xssf; | package org.apache.poi.xssf; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.IOException; | |||||
import java.io.InputStream; | |||||
import java.io.*; | |||||
import org.apache.poi.hssf.HSSFTestDataSamples; | import org.apache.poi.hssf.HSSFTestDataSamples; | ||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | import org.apache.poi.hssf.usermodel.HSSFWorkbook; | ||||
} | } | ||||
} | } | ||||
public static <R extends Workbook> R writeOutAndReadBack(R wb) { | public static <R extends Workbook> R writeOutAndReadBack(R wb) { | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); | |||||
Workbook result; | Workbook result; | ||||
try { | try { | ||||
wb.write(baos); | |||||
InputStream is = new ByteArrayInputStream(baos.toByteArray()); | |||||
if (wb instanceof HSSFWorkbook) { | if (wb instanceof HSSFWorkbook) { | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192); | |||||
wb.write(baos); | |||||
InputStream is = new ByteArrayInputStream(baos.toByteArray()); | |||||
result = new HSSFWorkbook(is); | result = new HSSFWorkbook(is); | ||||
} else if (wb instanceof XSSFWorkbook) { | } else if (wb instanceof XSSFWorkbook) { | ||||
Package pkg = Package.open(is); | |||||
File tmp = File.createTempFile("poi-ooxml-", ".xlsx"); | |||||
tmp.deleteOnExit(); | |||||
FileOutputStream out = new FileOutputStream(tmp); | |||||
wb.write(out); | |||||
out.close(); | |||||
Package pkg = Package.open(tmp.getAbsolutePath()); | |||||
result = new XSSFWorkbook(pkg); | result = new XSSFWorkbook(pkg); | ||||
} else { | } else { | ||||
throw new RuntimeException("Unexpected workbook type (" | throw new RuntimeException("Unexpected workbook type (" |
import org.apache.poi.xssf.usermodel.XSSFRichTextString; | import org.apache.poi.xssf.usermodel.XSSFRichTextString; | ||||
import org.apache.poi.xssf.usermodel.XSSFSheet; | import org.apache.poi.xssf.usermodel.XSSFSheet; | ||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook; | import org.apache.poi.xssf.usermodel.XSSFWorkbook; | ||||
import org.apache.poi.xssf.XSSFTestDataSamples; | |||||
import org.openxml4j.opc.Package; | import org.openxml4j.opc.Package; | ||||
import org.openxml4j.opc.PackagePart; | import org.openxml4j.opc.PackagePart; | ||||
import org.openxml4j.opc.PackagingURIHelper; | import org.openxml4j.opc.PackagingURIHelper; | ||||
// Save, and re-load the file | // Save, and re-load the file | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
workbook.write(baos); | |||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
workbook = new XSSFWorkbook(Package.open(bais)); | |||||
workbook = XSSFTestDataSamples.writeOutAndReadBack(workbook); | |||||
// Check we still have comments where we should do | // Check we still have comments where we should do | ||||
sheet1 = workbook.getSheetAt(0); | sheet1 = workbook.getSheetAt(0); | ||||
sheet2 = (XSSFSheet)workbook.getSheetAt(1); | sheet2 = (XSSFSheet)workbook.getSheetAt(1); | ||||
sheet1.getRow(12).getCell(2).getCellComment().getAuthor()); | sheet1.getRow(12).getCell(2).getCellComment().getAuthor()); | ||||
// Save, and re-load the file | // Save, and re-load the file | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
workbook.write(baos); | |||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
workbook = new XSSFWorkbook(Package.open(bais)); | |||||
workbook = XSSFTestDataSamples.writeOutAndReadBack(workbook); | |||||
// Check we still have comments where we should do | // Check we still have comments where we should do | ||||
sheet1 = workbook.getSheetAt(0); | sheet1 = workbook.getSheetAt(0); | ||||
assertNotNull(sheet1.getRow(4).getCell(2).getCellComment()); | assertNotNull(sheet1.getRow(4).getCell(2).getCellComment()); |
package org.apache.poi.xssf.usermodel; | package org.apache.poi.xssf.usermodel; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.File; | import java.io.File; | ||||
import java.io.FileOutputStream; | |||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.openxml4j.opc.Package; | import org.openxml4j.opc.Package; | ||||
import org.openxml4j.opc.PackagePart; | import org.openxml4j.opc.PackagePart; | ||||
import org.openxml4j.opc.PackagingURIHelper; | import org.openxml4j.opc.PackagingURIHelper; | ||||
import org.apache.poi.xssf.XSSFTestDataSamples; | |||||
public class TestXSSFBugs extends TestCase { | public class TestXSSFBugs extends TestCase { | ||||
private String getFilePath(String file) { | |||||
File xml = new File( | |||||
System.getProperty("HSSF.testdata.path") + | |||||
File.separator + file | |||||
); | |||||
assertTrue(xml.exists()); | |||||
return xml.toString(); | |||||
} | |||||
private Package saveAndOpen(XSSFWorkbook wb) throws Exception { | |||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
wb.write(baos); | |||||
ByteArrayInputStream inp = new ByteArrayInputStream( | |||||
baos.toByteArray() | |||||
); | |||||
Package pkg = Package.open(inp); | |||||
return pkg; | |||||
} | |||||
/** | |||||
* Named ranges had the right reference, but | |||||
* the wrong sheet name | |||||
*/ | |||||
public void test45430() throws Exception { | |||||
XSSFWorkbook wb = new XSSFWorkbook(getFilePath("45430.xlsx")); | |||||
assertFalse(wb.isMacroEnabled()); | |||||
assertEquals(3, wb.getNumberOfNames()); | |||||
assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId()); | |||||
assertFalse(wb.getNameAt(0).getCTName().isSetLocalSheetId()); | |||||
assertEquals("SheetA!$A$1", wb.getNameAt(0).getReference()); | |||||
assertEquals("SheetA", wb.getNameAt(0).getSheetName()); | |||||
assertEquals(0, wb.getNameAt(1).getCTName().getLocalSheetId()); | |||||
assertFalse(wb.getNameAt(1).getCTName().isSetLocalSheetId()); | |||||
assertEquals("SheetB!$A$1", wb.getNameAt(1).getReference()); | |||||
assertEquals("SheetB", wb.getNameAt(1).getSheetName()); | |||||
assertEquals(0, wb.getNameAt(2).getCTName().getLocalSheetId()); | |||||
assertFalse(wb.getNameAt(2).getCTName().isSetLocalSheetId()); | |||||
assertEquals("SheetC!$A$1", wb.getNameAt(2).getReference()); | |||||
assertEquals("SheetC", wb.getNameAt(2).getSheetName()); | |||||
// Save and re-load, still there | |||||
Package nPkg = saveAndOpen(wb); | |||||
XSSFWorkbook nwb = new XSSFWorkbook(nPkg); | |||||
assertEquals(3, nwb.getNumberOfNames()); | |||||
assertEquals("SheetA!$A$1", nwb.getNameAt(0).getReference()); | |||||
} | |||||
/** | |||||
* We should carry vba macros over after save | |||||
*/ | |||||
public void test45431() throws Exception { | |||||
Package pkg = Package.open(getFilePath("45431.xlsm")); | |||||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||||
assertTrue(wb.isMacroEnabled()); | |||||
// Check the various macro related bits can be found | |||||
PackagePart vba = pkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin") | |||||
); | |||||
assertNotNull(vba); | |||||
// And the drawing bit | |||||
PackagePart drw = pkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") | |||||
); | |||||
assertNotNull(drw); | |||||
// Save and re-open, both still there | |||||
Package nPkg = saveAndOpen(wb); | |||||
XSSFWorkbook nwb = new XSSFWorkbook(nPkg); | |||||
assertTrue(nwb.isMacroEnabled()); | |||||
vba = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin") | |||||
); | |||||
assertNotNull(vba); | |||||
drw = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") | |||||
); | |||||
assertNotNull(drw); | |||||
// And again, just to be sure | |||||
nPkg = saveAndOpen(nwb); | |||||
nwb = new XSSFWorkbook(nPkg); | |||||
assertTrue(nwb.isMacroEnabled()); | |||||
vba = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin") | |||||
); | |||||
assertNotNull(vba); | |||||
drw = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") | |||||
); | |||||
assertNotNull(drw); | |||||
// For testing with excel | |||||
private String getFilePath(String file) { | |||||
File xml = new File( | |||||
System.getProperty("HSSF.testdata.path") + | |||||
File.separator + file | |||||
); | |||||
assertTrue(xml.exists()); | |||||
return xml.toString(); | |||||
} | |||||
/** | |||||
* Named ranges had the right reference, but | |||||
* the wrong sheet name | |||||
*/ | |||||
public void test45430() throws Exception { | |||||
XSSFWorkbook wb = new XSSFWorkbook(getFilePath("45430.xlsx")); | |||||
assertFalse(wb.isMacroEnabled()); | |||||
assertEquals(3, wb.getNumberOfNames()); | |||||
assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId()); | |||||
assertFalse(wb.getNameAt(0).getCTName().isSetLocalSheetId()); | |||||
assertEquals("SheetA!$A$1", wb.getNameAt(0).getReference()); | |||||
assertEquals("SheetA", wb.getNameAt(0).getSheetName()); | |||||
assertEquals(0, wb.getNameAt(1).getCTName().getLocalSheetId()); | |||||
assertFalse(wb.getNameAt(1).getCTName().isSetLocalSheetId()); | |||||
assertEquals("SheetB!$A$1", wb.getNameAt(1).getReference()); | |||||
assertEquals("SheetB", wb.getNameAt(1).getSheetName()); | |||||
assertEquals(0, wb.getNameAt(2).getCTName().getLocalSheetId()); | |||||
assertFalse(wb.getNameAt(2).getCTName().isSetLocalSheetId()); | |||||
assertEquals("SheetC!$A$1", wb.getNameAt(2).getReference()); | |||||
assertEquals("SheetC", wb.getNameAt(2).getSheetName()); | |||||
// Save and re-load, still there | |||||
XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb); | |||||
assertEquals(3, nwb.getNumberOfNames()); | |||||
assertEquals("SheetA!$A$1", nwb.getNameAt(0).getReference()); | |||||
} | |||||
/** | |||||
* We should carry vba macros over after save | |||||
*/ | |||||
public void test45431() throws Exception { | |||||
Package pkg = Package.open(getFilePath("45431.xlsm")); | |||||
XSSFWorkbook wb = new XSSFWorkbook(pkg); | |||||
assertTrue(wb.isMacroEnabled()); | |||||
// Check the various macro related bits can be found | |||||
PackagePart vba = pkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin") | |||||
); | |||||
assertNotNull(vba); | |||||
// And the drawing bit | |||||
PackagePart drw = pkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") | |||||
); | |||||
assertNotNull(drw); | |||||
// Save and re-open, both still there | |||||
XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb); | |||||
Package nPkg = nwb.getPackage(); | |||||
assertTrue(nwb.isMacroEnabled()); | |||||
vba = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin") | |||||
); | |||||
assertNotNull(vba); | |||||
drw = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") | |||||
); | |||||
assertNotNull(drw); | |||||
// And again, just to be sure | |||||
nwb = XSSFTestDataSamples.writeOutAndReadBack(nwb); | |||||
nPkg = nwb.getPackage(); | |||||
assertTrue(nwb.isMacroEnabled()); | |||||
vba = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin") | |||||
); | |||||
assertNotNull(vba); | |||||
drw = nPkg.getPart( | |||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") | |||||
); | |||||
assertNotNull(drw); | |||||
// For testing with excel | |||||
// FileOutputStream fout = new FileOutputStream("/tmp/foo.xlsm"); | // FileOutputStream fout = new FileOutputStream("/tmp/foo.xlsm"); | ||||
// nwb.write(fout); | // nwb.write(fout); | ||||
// fout.close(); | // fout.close(); | ||||
} | |||||
} | |||||
} | } |
package org.apache.poi.xssf.usermodel; | package org.apache.poi.xssf.usermodel; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString; | import org.apache.poi.hssf.usermodel.HSSFRichTextString; | ||||
import org.apache.poi.ss.usermodel.Cell; | import org.apache.poi.ss.usermodel.Cell; | ||||
import org.apache.poi.ss.usermodel.Comment; | import org.apache.poi.ss.usermodel.Comment; | ||||
import org.apache.poi.ss.usermodel.Row; | import org.apache.poi.ss.usermodel.Row; | ||||
import org.apache.poi.ss.util.CellReference; | import org.apache.poi.ss.util.CellReference; | ||||
import org.apache.poi.xssf.model.CommentsTable; | import org.apache.poi.xssf.model.CommentsTable; | ||||
import org.apache.poi.xssf.XSSFTestDataSamples; | |||||
import org.openxml4j.opc.Package; | import org.openxml4j.opc.Package; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; | ||||
*/ | */ | ||||
public void testCreateSave() throws Exception { | public void testCreateSave() throws Exception { | ||||
XSSFWorkbook wb = new XSSFWorkbook(); | XSSFWorkbook wb = new XSSFWorkbook(); | ||||
XSSFSheet s1 = (XSSFSheet)wb.createSheet(); | |||||
XSSFSheet s1 = wb.createSheet(); | |||||
Row r1 = s1.createRow(0); | Row r1 = s1.createRow(0); | ||||
Cell r1c1 = r1.createCell(0); | Cell r1c1 = r1.createCell(0); | ||||
r1c1.setCellValue(2.2); | r1c1.setCellValue(2.2); | ||||
assertEquals(1, s1.getNumberOfComments()); | assertEquals(1, s1.getNumberOfComments()); | ||||
// Save and re-load | // Save and re-load | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
wb.write(baos); | |||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
wb = new XSSFWorkbook(Package.open(bais)); | |||||
s1 = (XSSFSheet)wb.getSheetAt(0); | |||||
wb = XSSFTestDataSamples.writeOutAndReadBack(wb); | |||||
s1 = wb.getSheetAt(0); | |||||
assertEquals(1, s1.getNumberOfComments()); | assertEquals(1, s1.getNumberOfComments()); | ||||
assertNotNull(s1.getRow(0).getCell(0).getCellComment()); | assertNotNull(s1.getRow(0).getCell(0).getCellComment()); | ||||
assertEquals(2, s1.getNumberOfComments()); | assertEquals(2, s1.getNumberOfComments()); | ||||
// Save and re-load | // Save and re-load | ||||
baos = new ByteArrayOutputStream(); | |||||
wb.write(baos); | |||||
bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
wb = new XSSFWorkbook(Package.open(bais)); | |||||
s1 = (XSSFSheet)wb.getSheetAt(0); | |||||
wb = XSSFTestDataSamples.writeOutAndReadBack(wb); | |||||
s1 = wb.getSheetAt(0); | |||||
assertEquals(2, s1.getNumberOfComments()); | assertEquals(2, s1.getNumberOfComments()); | ||||
assertNotNull(s1.getCellComment(0, 0)); | assertNotNull(s1.getCellComment(0, 0)); |
package org.apache.poi.xssf.usermodel; | package org.apache.poi.xssf.usermodel; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.File; | import java.io.File; | ||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.poi.ss.usermodel.CreationHelper; | import org.apache.poi.ss.usermodel.CreationHelper; | ||||
import org.apache.poi.ss.usermodel.Hyperlink; | import org.apache.poi.ss.usermodel.Hyperlink; | ||||
import org.apache.poi.ss.usermodel.Row; | import org.apache.poi.ss.usermodel.Row; | ||||
import org.apache.poi.xssf.XSSFTestDataSamples; | |||||
import org.openxml4j.opc.Package; | import org.openxml4j.opc.Package; | ||||
public class TestXSSFHyperlink extends TestCase { | public class TestXSSFHyperlink extends TestCase { | ||||
// Write out, and check | // Write out, and check | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
workbook.write(baos); | |||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
// Load up again, check all links still there | // Load up again, check all links still there | ||||
XSSFWorkbook wb2 = new XSSFWorkbook(Package.open(bais)); | |||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(workbook); | |||||
assertEquals(3, wb2.getNumberOfSheets()); | assertEquals(3, wb2.getNumberOfSheets()); | ||||
assertNotNull(wb2.getSheetAt(0)); | assertNotNull(wb2.getSheetAt(0)); | ||||
assertNotNull(wb2.getSheetAt(1)); | assertNotNull(wb2.getSheetAt(1)); | ||||
// Save and re-load once more | // Save and re-load once more | ||||
baos = new ByteArrayOutputStream(); | |||||
wb2.write(baos); | |||||
bais = new ByteArrayInputStream(baos.toByteArray()); | |||||
XSSFWorkbook wb3 = new XSSFWorkbook(Package.open(bais)); | |||||
XSSFWorkbook wb3 = XSSFTestDataSamples.writeOutAndReadBack(wb2); | |||||
assertEquals(3, wb3.getNumberOfSheets()); | assertEquals(3, wb3.getNumberOfSheets()); | ||||
assertNotNull(wb3.getSheetAt(0)); | assertNotNull(wb3.getSheetAt(0)); | ||||
assertNotNull(wb3.getSheetAt(1)); | assertNotNull(wb3.getSheetAt(1)); | ||||
assertNotNull(wb3.getSheetAt(2)); | assertNotNull(wb3.getSheetAt(2)); | ||||
sheet = (XSSFSheet)wb3.getSheetAt(0); | |||||
sheet = wb3.getSheetAt(0); | |||||
assertEquals(5, sheet.getNumHyperlinks()); | assertEquals(5, sheet.getNumHyperlinks()); | ||||
doTestHyperlinkContents(sheet); | doTestHyperlinkContents(sheet); |
package org.apache.poi.xssf.usermodel; | package org.apache.poi.xssf.usermodel; | ||||
import java.io.ByteArrayInputStream; | |||||
import java.io.ByteArrayOutputStream; | |||||
import java.io.File; | import java.io.File; | ||||
import java.util.Iterator; | import java.util.Iterator; | ||||
import junit.framework.TestCase; | import junit.framework.TestCase; | ||||
import org.apache.poi.xssf.model.CommentsTable; | import org.apache.poi.xssf.model.CommentsTable; | ||||
import org.apache.poi.xssf.model.StylesTable; | import org.apache.poi.xssf.model.StylesTable; | ||||
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; | import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; | ||||
import org.apache.poi.hssf.usermodel.HSSFSheet; | |||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook; | |||||
import org.apache.poi.hssf.usermodel.HSSFRow; | |||||
import org.apache.poi.hssf.usermodel.HSSFCell; | |||||
import org.openxml4j.opc.Package; | |||||
import org.apache.poi.xssf.XSSFTestDataSamples; | |||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols; | ||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; | import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment; | ||||
// Save and reload | // Save and reload | ||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(); | |||||
workbook.write(baos); | |||||
XSSFWorkbook wb = new XSSFWorkbook(Package.open( | |||||
new ByteArrayInputStream(baos.toByteArray()) | |||||
)); | |||||
XSSFWorkbook wb = XSSFTestDataSamples.writeOutAndReadBack(workbook); | |||||
hdr = (XSSFOddHeader)wb.getSheetAt(0).getHeader(); | hdr = (XSSFOddHeader)wb.getSheetAt(0).getHeader(); | ||||
ftr = (XSSFOddFooter)wb.getSheetAt(0).getFooter(); | ftr = (XSSFOddFooter)wb.getSheetAt(0).getFooter(); |
// Now, an existing file with named ranges | // Now, an existing file with named ranges | ||||
workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx"); | workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx"); | ||||
assertEquals(2, workbook.getNumberOfNames()); | assertEquals(2, workbook.getNumberOfNames()); | ||||
assertEquals("Sheet1!$A$2:$A$7", workbook.getNameAt(0).getReference()); | assertEquals("Sheet1!$A$2:$A$7", workbook.getNameAt(0).getReference()); | ||||
assertEquals("AllANumbers", workbook.getNameAt(0).getNameName()); | assertEquals("AllANumbers", workbook.getNameAt(0).getNameName()); |