refactored POIXMLDocument to be a composite of POIXMLDocumentPart, this way XSSFWorkbook is a root of a tree: XSSFSheets are children, XSSFDrawings are children of worksheets, etc,
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-ffa450edef68
This commit is contained in:
parent
57e7f5f10f
commit
baa56c4fc8
@ -29,7 +29,7 @@ public class CreateNewSpreadsheet {
|
||||
CreationHelper createHelper = wb.getCreationHelper();
|
||||
|
||||
XSSFSheet s1 = wb.createSheet("Sheet One");
|
||||
XSSFSheet s2 = wb.createSheet("Sheet One");
|
||||
XSSFSheet s2 = wb.createSheet("Sheet Two");
|
||||
|
||||
// Create a few cells
|
||||
s1.createRow(0);
|
||||
|
@ -376,9 +376,6 @@ public interface Workbook {
|
||||
|
||||
Palette getCustomPalette();
|
||||
|
||||
/** Test only. Do not use */
|
||||
void insertChartRecord();
|
||||
|
||||
/**
|
||||
* Adds a picture to the workbook.
|
||||
*
|
||||
@ -392,7 +389,7 @@ public interface 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();
|
||||
|
||||
|
@ -16,78 +16,61 @@
|
||||
==================================================================== */
|
||||
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.List;
|
||||
|
||||
import org.apache.poi.poifs.common.POIFSConstants;
|
||||
import org.apache.poi.util.IOUtils;
|
||||
import org.apache.poi.util.PackageHelper;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.openxml4j.exceptions.InvalidFormatException;
|
||||
import org.openxml4j.exceptions.OpenXML4JException;
|
||||
import org.openxml4j.opc.*;
|
||||
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 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";
|
||||
|
||||
|
||||
// OLE embeddings relation name
|
||||
public static final String OLE_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
|
||||
|
||||
|
||||
// Embedded OPC documents relation name
|
||||
public static final String PACK_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
|
||||
|
||||
|
||||
/** The OPC Package */
|
||||
private Package pkg;
|
||||
|
||||
/** The OPC core Package Part */
|
||||
private PackagePart corePart;
|
||||
|
||||
|
||||
/**
|
||||
* The properties of the OPC package, opened as needed
|
||||
*/
|
||||
private POIXMLProperties properties;
|
||||
|
||||
/**
|
||||
* The embedded OLE2 files in the OPC package
|
||||
*/
|
||||
protected List<PackagePart> embedds = new LinkedList<PackagePart>();
|
||||
|
||||
protected POIXMLDocument() {}
|
||||
|
||||
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());
|
||||
}
|
||||
/**
|
||||
* 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 {
|
||||
this();
|
||||
initialize(pkg);
|
||||
}
|
||||
|
||||
protected POIXMLDocument(String path) throws IOException {
|
||||
this(openPackage(path));
|
||||
this(openPackage(path));
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Wrapper to open a package, returning an IOException
|
||||
* in the event of a problem.
|
||||
@ -100,25 +83,37 @@ public abstract class POIXMLDocument {
|
||||
throw new IOException(e.toString());
|
||||
}
|
||||
}
|
||||
public static Package openPackage(InputStream is) throws IOException {
|
||||
|
||||
protected void initialize(Package pkg) throws IOException {
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
protected Package getPackage() {
|
||||
public Package getPackage() {
|
||||
return this.pkg;
|
||||
}
|
||||
|
||||
|
||||
protected PackagePart getCorePart() {
|
||||
return this.corePart;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the PackagePart that is the target of a relationship.
|
||||
*
|
||||
*
|
||||
* @param rel The relationship
|
||||
* @return The target part
|
||||
* @throws InvalidFormatException
|
||||
@ -128,7 +123,7 @@ public abstract class POIXMLDocument {
|
||||
}
|
||||
/**
|
||||
* Get the PackagePart that is the target of a relationship.
|
||||
*
|
||||
*
|
||||
* @param rel The relationship
|
||||
* @param pkg The package to fetch from
|
||||
* @return The target part
|
||||
@ -143,90 +138,90 @@ public abstract class POIXMLDocument {
|
||||
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);
|
||||
}
|
||||
/**
|
||||
* 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;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
* 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.
|
||||
* If your InputStream does not support mark / reset,
|
||||
* then wrap it in a PushBackInputStream, then be
|
||||
* 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 {
|
||||
// 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
|
||||
if(inp instanceof PushbackInputStream) {
|
||||
PushbackInputStream pin = (PushbackInputStream)inp;
|
||||
pin.unread(header);
|
||||
PushbackInputStream pin = (PushbackInputStream)inp;
|
||||
pin.unread(header);
|
||||
} else {
|
||||
inp.reset();
|
||||
inp.reset();
|
||||
}
|
||||
|
||||
// Did it match the ooxml zip signature?
|
||||
|
||||
// Did it match the ooxml zip signature?
|
||||
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.
|
||||
*/
|
||||
|
203
src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java
Executable file
203
src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java
Executable file
@ -0,0 +1,203 @@
|
||||
/* ====================================================================
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
69
src/ooxml/java/org/apache/poi/POIXMLException.java
Executable file
69
src/ooxml/java/org/apache/poi/POIXMLException.java
Executable file
@ -0,0 +1,69 @@
|
||||
/* ====================================================================
|
||||
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);
|
||||
}
|
||||
}
|
40
src/ooxml/java/org/apache/poi/POIXMLFactory.java
Executable file
40
src/ooxml/java/org/apache/poi/POIXMLFactory.java
Executable file
@ -0,0 +1,40 @@
|
||||
/* ====================================================================
|
||||
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);
|
||||
}
|
||||
}
|
54
src/ooxml/java/org/apache/poi/POIXMLRelation.java
Executable file
54
src/ooxml/java/org/apache/poi/POIXMLRelation.java
Executable file
@ -0,0 +1,54 @@
|
||||
/* ====================================================================
|
||||
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));
|
||||
}
|
||||
}
|
150
src/ooxml/java/org/apache/poi/util/PackageHelper.java
Executable file
150
src/ooxml/java/org/apache/poi/util/PackageHelper.java
Executable file
@ -0,0 +1,150 @@
|
||||
/* ====================================================================
|
||||
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());
|
||||
}
|
||||
}
|
@ -21,10 +21,7 @@ import org.w3c.dom.Document;
|
||||
|
||||
import javax.xml.parsers.DocumentBuilderFactory;
|
||||
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.ZipEntry;
|
||||
import java.util.Enumeration;
|
||||
@ -70,24 +67,32 @@ public class XSSFDump {
|
||||
FileOutputStream out = new FileOutputStream(f);
|
||||
|
||||
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));
|
||||
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() );
|
||||
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 {
|
||||
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();
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
|
||||
}
|
||||
}
|
||||
|
@ -31,6 +31,7 @@ public class XSSFSave {
|
||||
for (int i = 0; i < args.length; i++) {
|
||||
XSSFWorkbook wb = new XSSFWorkbook(args[i]);
|
||||
|
||||
System.out.println("wb.getNumberOfSheets(): " + wb.getNumberOfSheets());
|
||||
int sep = args[i].lastIndexOf('.');
|
||||
String outfile = args[i].substring(0, sep) + "-save.xlsx";
|
||||
FileOutputStream out = new FileOutputStream(outfile);
|
||||
|
@ -23,6 +23,7 @@ import java.io.OutputStream;
|
||||
import org.apache.poi.ss.usermodel.CommentsSource;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.usermodel.XSSFComment;
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
||||
@ -30,103 +31,121 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCommentList;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
|
||||
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 class CommentsTable extends POIXMLDocumentPart 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 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) {
|
||||
throw new IOException(e.getLocalizedMessage());
|
||||
}
|
||||
}
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
}
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
XmlOptions options = new XmlOptions();
|
||||
options.setSaveOuter();
|
||||
options.setUseDefaultNamespace();
|
||||
|
||||
|
||||
// Requests use of whitespace for easier reading
|
||||
//options.setSavePrettyPrint();
|
||||
|
||||
|
||||
CommentsDocument doc = CommentsDocument.Factory.newInstance(options);
|
||||
doc.setComments(comments);
|
||||
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());
|
||||
}
|
||||
@Override
|
||||
protected void commit() throws IOException {
|
||||
PackagePart part = getPackagePart();
|
||||
OutputStream out = part.getOutputStream();
|
||||
writeTo(out);
|
||||
out.close();
|
||||
}
|
||||
|
||||
private CTCommentList getCommentsList() {
|
||||
if (comments.getCommentList() == null) {
|
||||
comments.addNewCommentList();
|
||||
}
|
||||
return comments.getCommentList();
|
||||
}
|
||||
public int getNumberOfComments() {
|
||||
return comments.getCommentList().sizeOfCommentArray();
|
||||
}
|
||||
public int getNumberOfAuthors() {
|
||||
return getCommentsAuthors().sizeOfAuthorArray();
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
}
|
@ -27,9 +27,13 @@ import java.util.Map;
|
||||
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
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.CTSst;
|
||||
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;
|
||||
|
||||
|
||||
/**
|
||||
@ -56,7 +60,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
|
||||
* @author Nick Birch
|
||||
* @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.
|
||||
@ -89,13 +93,17 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
||||
* @throws IOException if an error occurs while reading.
|
||||
*/
|
||||
public SharedStringsTable(InputStream is) throws IOException {
|
||||
super(null, null);
|
||||
readFrom(is);
|
||||
}
|
||||
/**
|
||||
* Create a new, empty SharedStringsTable
|
||||
*/
|
||||
|
||||
public SharedStringsTable() {
|
||||
count = uniqueCount = 0;
|
||||
super(null, null);
|
||||
}
|
||||
|
||||
public SharedStringsTable(PackagePart part, PackageRelationship rel) throws IOException {
|
||||
super(part, rel);
|
||||
readFrom(part.getInputStream());
|
||||
}
|
||||
|
||||
/**
|
||||
@ -204,4 +212,12 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
||||
sst.setSiArray(ctr);
|
||||
doc.save(out, options);
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void commit() throws IOException {
|
||||
PackagePart part = getPackagePart();
|
||||
OutputStream out = part.getOutputStream();
|
||||
writeTo(out);
|
||||
out.close();
|
||||
}
|
||||
}
|
||||
|
@ -36,6 +36,7 @@ import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
||||
import org.apache.poi.xssf.usermodel.XSSFFont;
|
||||
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder;
|
||||
import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill;
|
||||
import org.apache.poi.POIXMLDocumentPart;
|
||||
import org.apache.xmlbeans.XmlException;
|
||||
import org.apache.xmlbeans.XmlOptions;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
|
||||
@ -54,13 +55,16 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTStylesheet;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTXf;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
|
||||
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.
|
||||
*
|
||||
* @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 List<CTFont> fonts = new ArrayList<CTFont>();
|
||||
private final List<CTFill> fills = new LinkedList<CTFill>();
|
||||
@ -85,18 +89,25 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
* @throws IOException if an error occurs while reading.
|
||||
*/
|
||||
public StylesTable(InputStream is) throws IOException {
|
||||
super(null, null);
|
||||
readFrom(is);
|
||||
}
|
||||
/**
|
||||
* Create a new, empty StylesTable
|
||||
*/
|
||||
public StylesTable() {
|
||||
super(null, null);
|
||||
doc = StyleSheetDocument.Factory.newInstance();
|
||||
doc.addNewStyleSheet();
|
||||
// Initialization required in order to make the document readable by MSExcel
|
||||
initialize();
|
||||
}
|
||||
|
||||
public StylesTable(PackagePart part, PackageRelationship rel) throws IOException {
|
||||
super(part, rel);
|
||||
readFrom(part.getInputStream());
|
||||
}
|
||||
|
||||
/**
|
||||
* Read this shared styles table from an XML file.
|
||||
*
|
||||
@ -365,6 +376,14 @@ public class StylesTable implements StylesSource, XSSFModel {
|
||||
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) {
|
||||
return border.putBorder((LinkedList<CTBorder>) borders); // TODO - use List instead of LinkedList
|
||||
}
|
||||
|
@ -23,26 +23,22 @@ import org.apache.poi.ss.usermodel.RichTextString;
|
||||
|
||||
public class XSSFCreationHelper implements CreationHelper {
|
||||
private XSSFWorkbook workbook;
|
||||
private XSSFDataFormat dataFormat;
|
||||
XSSFCreationHelper(XSSFWorkbook wb) {
|
||||
workbook = wb;
|
||||
|
||||
// Create the things we only ever need one of
|
||||
dataFormat = new XSSFDataFormat(workbook.getStylesSource());
|
||||
}
|
||||
|
||||
/**
|
||||
* Creates a new XSSFRichTextString for you.
|
||||
*/
|
||||
public RichTextString createRichTextString(String text) {
|
||||
public XSSFRichTextString createRichTextString(String 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);
|
||||
}
|
||||
}
|
||||
|
57
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java
Executable file
57
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java
Executable file
@ -0,0 +1,57 @@
|
||||
/* ====================================================================
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
@ -26,6 +26,7 @@ import java.util.Iterator;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.poi.POIXMLDocument;
|
||||
import org.apache.poi.POIXMLRelation;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.xssf.model.BinaryPart;
|
||||
@ -49,7 +50,7 @@ import org.openxml4j.opc.TargetMode;
|
||||
/**
|
||||
*
|
||||
*/
|
||||
public final class XSSFRelation<W extends XSSFModel> {
|
||||
public final class XSSFRelation<W extends XSSFModel> extends POIXMLRelation {
|
||||
|
||||
public static final XSSFRelation WORKBOOK = new XSSFRelation(
|
||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
|
||||
@ -156,16 +157,12 @@ public final class XSSFRelation<W extends XSSFModel> {
|
||||
return new XSSFRelation<R>(type, rel, defaultName, cls);
|
||||
}
|
||||
|
||||
private String _type;
|
||||
private String _relation;
|
||||
private String _defaultName;
|
||||
private Constructor<W> _constructor;
|
||||
private final boolean _constructorTakesTwoArgs;
|
||||
|
||||
private XSSFRelation(String type, String rel, String defaultName, Class<W> cls) {
|
||||
_type = type;
|
||||
_relation = rel;
|
||||
_defaultName = defaultName;
|
||||
super(type, rel, defaultName);
|
||||
|
||||
if (cls == null) {
|
||||
_constructor = null;
|
||||
_constructorTakesTwoArgs = false;
|
||||
@ -189,10 +186,7 @@ public final class XSSFRelation<W extends XSSFModel> {
|
||||
_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
|
||||
* package part?
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
@ -75,10 +75,22 @@ public class XSSFCellBorder {
|
||||
|
||||
private CTBorderPr getBorder(BorderSide 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");
|
||||
}
|
||||
}
|
||||
|
@ -17,10 +17,7 @@
|
||||
|
||||
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.usermodel.HSSFWorkbook;
|
||||
@ -47,15 +44,20 @@ public class XSSFTestDataSamples {
|
||||
}
|
||||
}
|
||||
public static <R extends Workbook> R writeOutAndReadBack(R wb) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
|
||||
Workbook result;
|
||||
try {
|
||||
wb.write(baos);
|
||||
InputStream is = new ByteArrayInputStream(baos.toByteArray());
|
||||
if (wb instanceof HSSFWorkbook) {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
|
||||
wb.write(baos);
|
||||
InputStream is = new ByteArrayInputStream(baos.toByteArray());
|
||||
result = new HSSFWorkbook(is);
|
||||
} 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);
|
||||
} else {
|
||||
throw new RuntimeException("Unexpected workbook type ("
|
||||
|
@ -30,6 +30,7 @@ import org.apache.poi.xssf.usermodel.XSSFComment;
|
||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
import org.openxml4j.opc.Package;
|
||||
import org.openxml4j.opc.PackagePart;
|
||||
import org.openxml4j.opc.PackagingURIHelper;
|
||||
@ -212,12 +213,8 @@ public class TestCommentsTable extends TestCase {
|
||||
|
||||
|
||||
// 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
|
||||
sheet1 = workbook.getSheetAt(0);
|
||||
sheet2 = (XSSFSheet)workbook.getSheetAt(1);
|
||||
@ -259,12 +256,8 @@ public class TestCommentsTable extends TestCase {
|
||||
sheet1.getRow(12).getCell(2).getCellComment().getAuthor());
|
||||
|
||||
// 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
|
||||
sheet1 = workbook.getSheetAt(0);
|
||||
assertNotNull(sheet1.getRow(4).getCell(2).getCellComment());
|
||||
|
@ -17,120 +17,107 @@
|
||||
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
import org.openxml4j.opc.Package;
|
||||
import org.openxml4j.opc.PackagePart;
|
||||
import org.openxml4j.opc.PackagingURIHelper;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
|
||||
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");
|
||||
// nwb.write(fout);
|
||||
// fout.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -17,9 +17,6 @@
|
||||
|
||||
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.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.Comment;
|
||||
@ -27,6 +24,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.ss.util.CellReference;
|
||||
import org.apache.poi.xssf.model.CommentsTable;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
import org.openxml4j.opc.Package;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
||||
@ -135,7 +133,7 @@ public class TestXSSFComment extends TestCase {
|
||||
*/
|
||||
public void testCreateSave() throws Exception {
|
||||
XSSFWorkbook wb = new XSSFWorkbook();
|
||||
XSSFSheet s1 = (XSSFSheet)wb.createSheet();
|
||||
XSSFSheet s1 = wb.createSheet();
|
||||
Row r1 = s1.createRow(0);
|
||||
Cell r1c1 = r1.createCell(0);
|
||||
r1c1.setCellValue(2.2);
|
||||
@ -150,12 +148,8 @@ public class TestXSSFComment extends TestCase {
|
||||
assertEquals(1, s1.getNumberOfComments());
|
||||
|
||||
// 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());
|
||||
assertNotNull(s1.getRow(0).getCell(0).getCellComment());
|
||||
@ -171,12 +165,9 @@ public class TestXSSFComment extends TestCase {
|
||||
assertEquals(2, s1.getNumberOfComments());
|
||||
|
||||
// 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());
|
||||
assertNotNull(s1.getCellComment(0, 0));
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
@ -27,6 +25,7 @@ import org.apache.poi.ss.usermodel.Cell;
|
||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||
import org.apache.poi.ss.usermodel.Row;
|
||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||
import org.openxml4j.opc.Package;
|
||||
|
||||
public class TestXSSFHyperlink extends TestCase {
|
||||
@ -79,12 +78,9 @@ public class TestXSSFHyperlink extends TestCase {
|
||||
|
||||
|
||||
// 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
|
||||
XSSFWorkbook wb2 = new XSSFWorkbook(Package.open(bais));
|
||||
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||
assertEquals(3, wb2.getNumberOfSheets());
|
||||
assertNotNull(wb2.getSheetAt(0));
|
||||
assertNotNull(wb2.getSheetAt(1));
|
||||
@ -119,18 +115,14 @@ public class TestXSSFHyperlink extends TestCase {
|
||||
|
||||
|
||||
// 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());
|
||||
assertNotNull(wb3.getSheetAt(0));
|
||||
assertNotNull(wb3.getSheetAt(1));
|
||||
assertNotNull(wb3.getSheetAt(2));
|
||||
|
||||
sheet = (XSSFSheet)wb3.getSheetAt(0);
|
||||
sheet = wb3.getSheetAt(0);
|
||||
|
||||
assertEquals(5, sheet.getNumHyperlinks());
|
||||
doTestHyperlinkContents(sheet);
|
||||
|
@ -17,8 +17,6 @@
|
||||
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.util.Iterator;
|
||||
import junit.framework.TestCase;
|
||||
@ -30,11 +28,7 @@ import org.apache.poi.ss.util.Region;
|
||||
import org.apache.poi.xssf.model.CommentsTable;
|
||||
import org.apache.poi.xssf.model.StylesTable;
|
||||
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.CTCols;
|
||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
||||
@ -349,11 +343,7 @@ public class TestXSSFSheet extends TestCase {
|
||||
|
||||
|
||||
// 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();
|
||||
ftr = (XSSFOddFooter)wb.getSheetAt(0).getFooter();
|
||||
|
@ -441,7 +441,7 @@ public final class TestXSSFWorkbook extends TestCase {
|
||||
|
||||
// Now, an existing file with named ranges
|
||||
workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx");
|
||||
|
||||
|
||||
assertEquals(2, workbook.getNumberOfNames());
|
||||
assertEquals("Sheet1!$A$2:$A$7", workbook.getNameAt(0).getReference());
|
||||
assertEquals("AllANumbers", workbook.getNameAt(0).getNameName());
|
||||
|
Loading…
Reference in New Issue
Block a user