Browse Source

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
tags/ooxml_20081107
Yegor Kozlov 15 years ago
parent
commit
0c4ee58c9f
26 changed files with 3022 additions and 2256 deletions
  1. 1
    1
      src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateNewSpreadsheet.java
  2. 1
    4
      src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Workbook.java
  3. 110
    115
      src/ooxml/java/org/apache/poi/POIXMLDocument.java
  4. 203
    0
      src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java
  5. 69
    0
      src/ooxml/java/org/apache/poi/POIXMLException.java
  6. 40
    0
      src/ooxml/java/org/apache/poi/POIXMLFactory.java
  7. 54
    0
      src/ooxml/java/org/apache/poi/POIXMLRelation.java
  8. 150
    0
      src/ooxml/java/org/apache/poi/util/PackageHelper.java
  9. 23
    18
      src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java
  10. 1
    0
      src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java
  11. 106
    87
      src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java
  12. 21
    5
      src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java
  13. 20
    1
      src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java
  14. 4
    8
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java
  15. 57
    0
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java
  16. 5
    11
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java
  17. 1508
    1510
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
  18. 511
    325
      src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
  19. 16
    4
      src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellBorder.java
  20. 10
    8
      src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java
  21. 5
    12
      src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java
  22. 91
    104
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
  23. 7
    16
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFComment.java
  24. 6
    14
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java
  25. 2
    12
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java
  26. 1
    1
      src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java

+ 1
- 1
src/examples/src/org/apache/poi/xssf/usermodel/examples/CreateNewSpreadsheet.java View File

@@ -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);

+ 1
- 4
src/ooxml/interfaces-jdk15/org/apache/poi/ss/usermodel/Workbook.java View File

@@ -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();


+ 110
- 115
src/ooxml/java/org/apache/poi/POIXMLDocument.java View File

@@ -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() {}

/**
* 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 {
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 {
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);
}
/**
* 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
* 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
- 0
src/ooxml/java/org/apache/poi/POIXMLDocumentPart.java View 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
- 0
src/ooxml/java/org/apache/poi/POIXMLException.java View 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
- 0
src/ooxml/java/org/apache/poi/POIXMLFactory.java View 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
- 0
src/ooxml/java/org/apache/poi/POIXMLRelation.java View 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
- 0
src/ooxml/java/org/apache/poi/util/PackageHelper.java View 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());
}
}

+ 23
- 18
src/ooxml/java/org/apache/poi/xssf/dev/XSSFDump.java View File

@@ -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));
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 {
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);
}
}

+ 1
- 0
src/ooxml/java/org/apache/poi/xssf/dev/XSSFSave.java View File

@@ -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);

+ 106
- 87
src/ooxml/java/org/apache/poi/xssf/model/CommentsTable.java View File

@@ -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 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) {
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());
}

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;
}
}

+ 21
- 5
src/ooxml/java/org/apache/poi/xssf/model/SharedStringsTable.java View File

@@ -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();
}
}

+ 20
- 1
src/ooxml/java/org/apache/poi/xssf/model/StylesTable.java View File

@@ -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
}

+ 4
- 8
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCreationHelper.java View File

@@ -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
- 0
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFFactory.java View 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);
}
}
}

+ 5
- 11
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java View File

@@ -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?

+ 1508
- 1510
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
File diff suppressed because it is too large
View File


+ 511
- 325
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
File diff suppressed because it is too large
View File


+ 16
- 4
src/ooxml/java/org/apache/poi/xssf/usermodel/extensions/XSSFCellBorder.java View File

@@ -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");
}
}

+ 10
- 8
src/ooxml/testcases/org/apache/poi/xssf/XSSFTestDataSamples.java View File

@@ -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 ("

+ 5
- 12
src/ooxml/testcases/org/apache/poi/xssf/model/TestCommentsTable.java View File

@@ -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());

+ 91
- 104
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java View File

@@ -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();
}
}
}

+ 7
- 16
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFComment.java View File

@@ -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));

+ 6
- 14
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFHyperlink.java View File

@@ -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);

+ 2
- 12
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java View File

@@ -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();

+ 1
- 1
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java View File

@@ -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…
Cancel
Save