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();
|
CreationHelper createHelper = wb.getCreationHelper();
|
||||||
|
|
||||||
XSSFSheet s1 = wb.createSheet("Sheet One");
|
XSSFSheet s1 = wb.createSheet("Sheet One");
|
||||||
XSSFSheet s2 = wb.createSheet("Sheet One");
|
XSSFSheet s2 = wb.createSheet("Sheet Two");
|
||||||
|
|
||||||
// Create a few cells
|
// Create a few cells
|
||||||
s1.createRow(0);
|
s1.createRow(0);
|
||||||
|
@ -376,9 +376,6 @@ public interface Workbook {
|
|||||||
|
|
||||||
Palette getCustomPalette();
|
Palette getCustomPalette();
|
||||||
|
|
||||||
/** Test only. Do not use */
|
|
||||||
void insertChartRecord();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Adds a picture to the workbook.
|
* Adds a picture to the workbook.
|
||||||
*
|
*
|
||||||
@ -392,7 +389,7 @@ public interface Workbook {
|
|||||||
/**
|
/**
|
||||||
* Gets all pictures from the Workbook.
|
* Gets all pictures from the Workbook.
|
||||||
*
|
*
|
||||||
* @return the list of pictures (a list of {@link HSSFPictureData} objects.)
|
* @return the list of pictures (a list of {@link PictureData} objects.)
|
||||||
*/
|
*/
|
||||||
List getAllPictures();
|
List getAllPictures();
|
||||||
|
|
||||||
|
@ -16,78 +16,61 @@
|
|||||||
==================================================================== */
|
==================================================================== */
|
||||||
package org.apache.poi;
|
package org.apache.poi;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.*;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.io.PushbackInputStream;
|
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.poifs.common.POIFSConstants;
|
import org.apache.poi.poifs.common.POIFSConstants;
|
||||||
import org.apache.poi.util.IOUtils;
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.apache.poi.util.PackageHelper;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.openxml4j.exceptions.InvalidFormatException;
|
import org.openxml4j.exceptions.InvalidFormatException;
|
||||||
import org.openxml4j.exceptions.OpenXML4JException;
|
import org.openxml4j.exceptions.OpenXML4JException;
|
||||||
|
import org.openxml4j.opc.*;
|
||||||
import org.openxml4j.opc.Package;
|
import org.openxml4j.opc.Package;
|
||||||
import org.openxml4j.opc.PackagePart;
|
|
||||||
import org.openxml4j.opc.PackagePartName;
|
|
||||||
import org.openxml4j.opc.PackageRelationship;
|
|
||||||
import org.openxml4j.opc.PackageRelationshipCollection;
|
|
||||||
import org.openxml4j.opc.PackageRelationshipTypes;
|
|
||||||
import org.openxml4j.opc.PackagingURIHelper;
|
|
||||||
|
|
||||||
public abstract class POIXMLDocument {
|
public class POIXMLDocument extends POIXMLDocumentPart{
|
||||||
|
|
||||||
public static final String CORE_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
public static final String CORE_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/package/2006/relationships/metadata/core-properties";
|
||||||
public static final String EXTENDED_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
|
public static final String EXTENDED_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/extended-properties";
|
||||||
public static final String CUSTOM_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties";
|
public static final String CUSTOM_PROPERTIES_REL_TYPE = "http://schemas.openxmlformats.org/officeDocument/2006/relationships/custom-properties";
|
||||||
|
|
||||||
// OLE embeddings relation name
|
// OLE embeddings relation name
|
||||||
public static final String OLE_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
|
public static final String OLE_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/oleObject";
|
||||||
|
|
||||||
// Embedded OPC documents relation name
|
// Embedded OPC documents relation name
|
||||||
public static final String PACK_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
|
public static final String PACK_OBJECT_REL_TYPE="http://schemas.openxmlformats.org/officeDocument/2006/relationships/package";
|
||||||
|
|
||||||
/** The OPC Package */
|
/** The OPC Package */
|
||||||
private Package pkg;
|
private Package pkg;
|
||||||
|
|
||||||
/** The OPC core Package Part */
|
/** The OPC core Package Part */
|
||||||
private PackagePart corePart;
|
private PackagePart corePart;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* The properties of the OPC package, opened as needed
|
* The properties of the OPC package, opened as needed
|
||||||
*/
|
*/
|
||||||
private POIXMLProperties properties;
|
private POIXMLProperties properties;
|
||||||
|
|
||||||
/**
|
|
||||||
* The embedded OLE2 files in the OPC package
|
|
||||||
*/
|
|
||||||
protected List<PackagePart> embedds = new LinkedList<PackagePart>();
|
|
||||||
|
|
||||||
protected POIXMLDocument() {}
|
|
||||||
|
|
||||||
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) {
|
* The embedded OLE2 files in the OPC package
|
||||||
throw new IllegalArgumentException("No core part found for this document! Nothing with " + coreDocRelationship.getRelationshipType() + " present as a relation.");
|
*/
|
||||||
}
|
protected List<PackagePart> embedds;
|
||||||
} catch (OpenXML4JException e) {
|
|
||||||
throw new IOException(e.toString());
|
protected POIXMLDocument() {
|
||||||
}
|
super(null, null);
|
||||||
|
embedds = new LinkedList<PackagePart>();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected POIXMLDocument(Package pkg) throws IOException {
|
||||||
|
this();
|
||||||
|
initialize(pkg);
|
||||||
|
}
|
||||||
|
|
||||||
protected POIXMLDocument(String path) throws IOException {
|
protected POIXMLDocument(String path) throws IOException {
|
||||||
this(openPackage(path));
|
this(openPackage(path));
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Wrapper to open a package, returning an IOException
|
* Wrapper to open a package, returning an IOException
|
||||||
* in the event of a problem.
|
* in the event of a problem.
|
||||||
@ -100,25 +83,37 @@ public abstract class POIXMLDocument {
|
|||||||
throw new IOException(e.toString());
|
throw new IOException(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static Package openPackage(InputStream is) throws IOException {
|
|
||||||
|
protected void initialize(Package pkg) throws IOException {
|
||||||
try {
|
try {
|
||||||
return Package.open(is);
|
this.pkg = pkg;
|
||||||
} catch (InvalidFormatException e) {
|
|
||||||
|
PackageRelationship coreDocRelationship = this.pkg.getRelationshipsByType(
|
||||||
|
PackageRelationshipTypes.CORE_DOCUMENT).getRelationship(0);
|
||||||
|
|
||||||
|
// Get core part
|
||||||
|
this.corePart = super.packagePart = this.pkg.getPart(coreDocRelationship);
|
||||||
|
|
||||||
|
// Verify it's there
|
||||||
|
if(corePart == null) {
|
||||||
|
throw new IllegalArgumentException("No core part found for this document! Nothing with " + coreDocRelationship.getRelationshipType() + " present as a relation.");
|
||||||
|
}
|
||||||
|
} catch (OpenXML4JException e) {
|
||||||
throw new IOException(e.toString());
|
throw new IOException(e.toString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected Package getPackage() {
|
public Package getPackage() {
|
||||||
return this.pkg;
|
return this.pkg;
|
||||||
}
|
}
|
||||||
|
|
||||||
protected PackagePart getCorePart() {
|
protected PackagePart getCorePart() {
|
||||||
return this.corePart;
|
return this.corePart;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the PackagePart that is the target of a relationship.
|
* Get the PackagePart that is the target of a relationship.
|
||||||
*
|
*
|
||||||
* @param rel The relationship
|
* @param rel The relationship
|
||||||
* @return The target part
|
* @return The target part
|
||||||
* @throws InvalidFormatException
|
* @throws InvalidFormatException
|
||||||
@ -128,7 +123,7 @@ public abstract class POIXMLDocument {
|
|||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Get the PackagePart that is the target of a relationship.
|
* Get the PackagePart that is the target of a relationship.
|
||||||
*
|
*
|
||||||
* @param rel The relationship
|
* @param rel The relationship
|
||||||
* @param pkg The package to fetch from
|
* @param pkg The package to fetch from
|
||||||
* @return The target part
|
* @return The target part
|
||||||
@ -143,90 +138,90 @@ public abstract class POIXMLDocument {
|
|||||||
return part;
|
return part;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Fetches the (single) PackagePart which is defined as
|
* Fetches the (single) PackagePart which is defined as
|
||||||
* the supplied relation content type of the base
|
* the supplied relation content type of the base
|
||||||
* package/container, or null if none found.
|
* package/container, or null if none found.
|
||||||
* @param relationType The relation content type to search for
|
* @param relationType The relation content type to search for
|
||||||
* @throws IllegalArgumentException If we find more than one part of that type
|
* @throws IllegalArgumentException If we find more than one part of that type
|
||||||
*/
|
*/
|
||||||
protected PackagePart getSinglePartByRelationType(String relationType) throws IllegalArgumentException, OpenXML4JException {
|
protected PackagePart getSinglePartByRelationType(String relationType) throws IllegalArgumentException, OpenXML4JException {
|
||||||
PackageRelationshipCollection rels =
|
PackageRelationshipCollection rels =
|
||||||
pkg.getRelationshipsByType(relationType);
|
pkg.getRelationshipsByType(relationType);
|
||||||
if(rels.size() == 0) {
|
if(rels.size() == 0) {
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
if(rels.size() > 1) {
|
if(rels.size() > 1) {
|
||||||
throw new IllegalArgumentException("Found " + rels.size() + " relations for the type " + relationType + ", should only ever be one!");
|
throw new IllegalArgumentException("Found " + rels.size() + " relations for the type " + relationType + ", should only ever be one!");
|
||||||
}
|
}
|
||||||
PackageRelationship rel = rels.getRelationship(0);
|
PackageRelationship rel = rels.getRelationship(0);
|
||||||
return getTargetPart(rel);
|
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
|
* Checks that the supplied InputStream (which MUST
|
||||||
* support mark and reset, or be a PushbackInputStream)
|
* support mark and reset, or be a PushbackInputStream)
|
||||||
* has a OOXML (zip) header at the start of it.
|
* has a OOXML (zip) header at the start of it.
|
||||||
* If your InputStream does not support mark / reset,
|
* If your InputStream does not support mark / reset,
|
||||||
* then wrap it in a PushBackInputStream, then be
|
* then wrap it in a PushBackInputStream, then be
|
||||||
* sure to always use that, and not the original!
|
* sure to always use that, and not the original!
|
||||||
* @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream
|
* @param inp An InputStream which supports either mark/reset, or is a PushbackInputStream
|
||||||
*/
|
*/
|
||||||
public static boolean hasOOXMLHeader(InputStream inp) throws IOException {
|
public static boolean hasOOXMLHeader(InputStream inp) throws IOException {
|
||||||
// We want to peek at the first 4 bytes
|
// We want to peek at the first 4 bytes
|
||||||
inp.mark(4);
|
inp.mark(4);
|
||||||
|
|
||||||
byte[] header = new byte[4];
|
byte[] header = new byte[4];
|
||||||
IOUtils.readFully(inp, header);
|
IOUtils.readFully(inp, header);
|
||||||
|
|
||||||
// Wind back those 4 bytes
|
// Wind back those 4 bytes
|
||||||
if(inp instanceof PushbackInputStream) {
|
if(inp instanceof PushbackInputStream) {
|
||||||
PushbackInputStream pin = (PushbackInputStream)inp;
|
PushbackInputStream pin = (PushbackInputStream)inp;
|
||||||
pin.unread(header);
|
pin.unread(header);
|
||||||
} else {
|
} else {
|
||||||
inp.reset();
|
inp.reset();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Did it match the ooxml zip signature?
|
// Did it match the ooxml zip signature?
|
||||||
return (
|
return (
|
||||||
header[0] == POIFSConstants.OOXML_FILE_HEADER[0] &&
|
header[0] == POIFSConstants.OOXML_FILE_HEADER[0] &&
|
||||||
header[1] == POIFSConstants.OOXML_FILE_HEADER[1] &&
|
header[1] == POIFSConstants.OOXML_FILE_HEADER[1] &&
|
||||||
header[2] == POIFSConstants.OOXML_FILE_HEADER[2] &&
|
header[2] == POIFSConstants.OOXML_FILE_HEADER[2] &&
|
||||||
header[3] == POIFSConstants.OOXML_FILE_HEADER[3]
|
header[3] == POIFSConstants.OOXML_FILE_HEADER[3]
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the document properties. This gives you access to the
|
||||||
|
* core ooxml properties, and the extended ooxml properties.
|
||||||
|
*/
|
||||||
|
public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException {
|
||||||
|
if(properties == null) {
|
||||||
|
properties = new POIXMLProperties(pkg);
|
||||||
|
}
|
||||||
|
return properties;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
|
||||||
* Get the document properties. This gives you access to the
|
|
||||||
* core ooxml properties, and the extended ooxml properties.
|
|
||||||
*/
|
|
||||||
public POIXMLProperties getProperties() throws OpenXML4JException, IOException, XmlException {
|
|
||||||
if(properties == null) {
|
|
||||||
properties = new POIXMLProperties(pkg);
|
|
||||||
}
|
|
||||||
return properties;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Get the document's embedded files.
|
* Get the document's embedded files.
|
||||||
*/
|
*/
|
||||||
|
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.DocumentBuilderFactory;
|
||||||
import javax.xml.parsers.DocumentBuilder;
|
import javax.xml.parsers.DocumentBuilder;
|
||||||
import java.io.FileOutputStream;
|
import java.io.*;
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
import java.util.zip.ZipFile;
|
import java.util.zip.ZipFile;
|
||||||
import java.util.zip.ZipEntry;
|
import java.util.zip.ZipEntry;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
@ -70,24 +67,32 @@ public class XSSFDump {
|
|||||||
FileOutputStream out = new FileOutputStream(f);
|
FileOutputStream out = new FileOutputStream(f);
|
||||||
|
|
||||||
if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){
|
if(entry.getName().endsWith(".xml") || entry.getName().endsWith(".vml") || entry.getName().endsWith(".rels")){
|
||||||
//pass the xml through the Xerces serializer to produce nicely formatted output
|
try {
|
||||||
Document doc = builder.parse(zip.getInputStream(entry));
|
//pass the xml through the Xerces serializer to produce nicely formatted output
|
||||||
|
Document doc = builder.parse(zip.getInputStream(entry));
|
||||||
|
|
||||||
OutputFormat format = new OutputFormat( doc );
|
OutputFormat format = new OutputFormat( doc );
|
||||||
format.setIndenting(true);
|
format.setIndenting(true);
|
||||||
|
|
||||||
XMLSerializer serial = new XMLSerializer( out, format );
|
|
||||||
serial.asDOMSerializer();
|
|
||||||
serial.serialize( doc.getDocumentElement() );
|
|
||||||
|
|
||||||
|
XMLSerializer serial = new XMLSerializer( out, format );
|
||||||
|
serial.asDOMSerializer();
|
||||||
|
serial.serialize( doc.getDocumentElement() );
|
||||||
|
} catch (Exception e){
|
||||||
|
System.err.println("Failed to parse " + entry.getName() + ", dumping raw content");
|
||||||
|
dump(zip.getInputStream(entry), out);
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
int pos;
|
dump(zip.getInputStream(entry), out);
|
||||||
byte[] chunk = new byte[2048];
|
|
||||||
InputStream is = zip.getInputStream(entry);
|
|
||||||
while((pos = is.read(chunk)) > 0) out.write(chunk, 0, pos);
|
|
||||||
}
|
}
|
||||||
out.close();
|
out.close();
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
protected static void dump(InputStream is, OutputStream out) throws IOException{
|
||||||
|
int pos;
|
||||||
|
byte[] chunk = new byte[2048];
|
||||||
|
while((pos = is.read(chunk)) > 0) out.write(chunk, 0, pos);
|
||||||
|
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -31,6 +31,7 @@ public class XSSFSave {
|
|||||||
for (int i = 0; i < args.length; i++) {
|
for (int i = 0; i < args.length; i++) {
|
||||||
XSSFWorkbook wb = new XSSFWorkbook(args[i]);
|
XSSFWorkbook wb = new XSSFWorkbook(args[i]);
|
||||||
|
|
||||||
|
System.out.println("wb.getNumberOfSheets(): " + wb.getNumberOfSheets());
|
||||||
int sep = args[i].lastIndexOf('.');
|
int sep = args[i].lastIndexOf('.');
|
||||||
String outfile = args[i].substring(0, sep) + "-save.xlsx";
|
String outfile = args[i].substring(0, sep) + "-save.xlsx";
|
||||||
FileOutputStream out = new FileOutputStream(outfile);
|
FileOutputStream out = new FileOutputStream(outfile);
|
||||||
|
@ -23,6 +23,7 @@ import java.io.OutputStream;
|
|||||||
import org.apache.poi.ss.usermodel.CommentsSource;
|
import org.apache.poi.ss.usermodel.CommentsSource;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFComment;
|
import org.apache.poi.xssf.usermodel.XSSFComment;
|
||||||
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
||||||
@ -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.CTCommentList;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComments;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CommentsDocument;
|
||||||
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
import org.openxml4j.opc.PackageRelationship;
|
||||||
|
|
||||||
public class CommentsTable implements CommentsSource, XSSFModel {
|
public class CommentsTable extends POIXMLDocumentPart implements CommentsSource, XSSFModel {
|
||||||
private CTComments comments;
|
private CTComments comments;
|
||||||
|
|
||||||
public CommentsTable(InputStream is) throws IOException {
|
public CommentsTable(InputStream is) throws IOException {
|
||||||
readFrom(is);
|
super(null, null);
|
||||||
}
|
readFrom(is);
|
||||||
public CommentsTable() {
|
}
|
||||||
comments = CTComments.Factory.newInstance();
|
public CommentsTable() {
|
||||||
}
|
super(null, null);
|
||||||
/**
|
comments = CTComments.Factory.newInstance();
|
||||||
* For unit testing only!
|
}
|
||||||
*/
|
/**
|
||||||
public CommentsTable(CTComments comments) {
|
* For unit testing only!
|
||||||
this.comments = comments;
|
*/
|
||||||
}
|
public CommentsTable(CTComments comments) {
|
||||||
|
super(null, null);
|
||||||
public void readFrom(InputStream is) throws IOException {
|
this.comments = comments;
|
||||||
try {
|
}
|
||||||
CommentsDocument doc = CommentsDocument.Factory.parse(is);
|
|
||||||
comments = doc.getComments();
|
public CommentsTable(PackagePart part, PackageRelationship rel) throws IOException {
|
||||||
|
super(part, rel);
|
||||||
|
readFrom(part.getInputStream());
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readFrom(InputStream is) throws IOException {
|
||||||
|
try {
|
||||||
|
CommentsDocument doc = CommentsDocument.Factory.parse(is);
|
||||||
|
comments = doc.getComments();
|
||||||
} catch (XmlException e) {
|
} catch (XmlException e) {
|
||||||
throw new IOException(e.getLocalizedMessage());
|
throw new IOException(e.getLocalizedMessage());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public void writeTo(OutputStream out) throws IOException {
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
XmlOptions options = new XmlOptions();
|
XmlOptions options = new XmlOptions();
|
||||||
options.setSaveOuter();
|
options.setSaveOuter();
|
||||||
options.setUseDefaultNamespace();
|
options.setUseDefaultNamespace();
|
||||||
|
|
||||||
// Requests use of whitespace for easier reading
|
// Requests use of whitespace for easier reading
|
||||||
//options.setSavePrettyPrint();
|
//options.setSavePrettyPrint();
|
||||||
|
|
||||||
CommentsDocument doc = CommentsDocument.Factory.newInstance(options);
|
CommentsDocument doc = CommentsDocument.Factory.newInstance(options);
|
||||||
doc.setComments(comments);
|
doc.setComments(comments);
|
||||||
doc.save(out, options);
|
doc.save(out, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
public int getNumberOfComments() {
|
|
||||||
return comments.getCommentList().sizeOfCommentArray();
|
|
||||||
}
|
|
||||||
public int getNumberOfAuthors() {
|
|
||||||
return getCommentsAuthors().sizeOfAuthorArray();
|
|
||||||
}
|
|
||||||
|
|
||||||
public String getAuthor(long authorId) {
|
|
||||||
return getCommentsAuthors().getAuthorArray((int)authorId);
|
|
||||||
}
|
|
||||||
|
|
||||||
public int findAuthor(String author) {
|
|
||||||
for (int i = 0 ; i < getCommentsAuthors().sizeOfAuthorArray() ; i++) {
|
|
||||||
if (getCommentsAuthors().getAuthorArray(i).equals(author)) {
|
|
||||||
return i;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return addNewAuthor(author);
|
|
||||||
}
|
|
||||||
|
|
||||||
public XSSFComment findCellComment(int row, int column) {
|
|
||||||
return findCellComment(
|
|
||||||
(new CellReference(row, column)).formatAsString() );
|
|
||||||
}
|
|
||||||
|
|
||||||
public XSSFComment findCellComment(String cellRef) {
|
|
||||||
for (CTComment comment : getCommentsList().getCommentArray()) {
|
|
||||||
if (cellRef.equals(comment.getRef())) {
|
|
||||||
return new XSSFComment(this, comment);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
/**
|
@Override
|
||||||
* Generates a new XSSFComment, associated with the
|
protected void commit() throws IOException {
|
||||||
* current comments list.
|
PackagePart part = getPackagePart();
|
||||||
*/
|
OutputStream out = part.getOutputStream();
|
||||||
public XSSFComment addComment() {
|
writeTo(out);
|
||||||
return new XSSFComment(this, getCommentsList().addNewComment());
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
private CTCommentList getCommentsList() {
|
public int getNumberOfComments() {
|
||||||
if (comments.getCommentList() == null) {
|
return comments.getCommentList().sizeOfCommentArray();
|
||||||
comments.addNewCommentList();
|
}
|
||||||
}
|
public int getNumberOfAuthors() {
|
||||||
return comments.getCommentList();
|
return getCommentsAuthors().sizeOfAuthorArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
private CTAuthors getCommentsAuthors() {
|
public String getAuthor(long authorId) {
|
||||||
if (comments.getAuthors() == null) {
|
return getCommentsAuthors().getAuthorArray((int)authorId);
|
||||||
comments.addNewAuthors();
|
}
|
||||||
}
|
|
||||||
return comments.getAuthors();
|
public int findAuthor(String author) {
|
||||||
}
|
for (int i = 0 ; i < getCommentsAuthors().sizeOfAuthorArray() ; i++) {
|
||||||
|
if (getCommentsAuthors().getAuthorArray(i).equals(author)) {
|
||||||
private int addNewAuthor(String author) {
|
return i;
|
||||||
int index = getCommentsAuthors().sizeOfAuthorArray();
|
}
|
||||||
getCommentsAuthors().insertAuthor(index, author);
|
}
|
||||||
return index;
|
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.XmlException;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRst;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTSst;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet;
|
||||||
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
import org.openxml4j.opc.PackageRelationship;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -56,7 +60,7 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.SstDocument;
|
|||||||
* @author Nick Birch
|
* @author Nick Birch
|
||||||
* @author Yegor Kozlov
|
* @author Yegor Kozlov
|
||||||
*/
|
*/
|
||||||
public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
public class SharedStringsTable extends POIXMLDocumentPart implements XSSFModel, SharedStringSource {
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Array of individual string items in the Shared String table.
|
* Array of individual string items in the Shared String table.
|
||||||
@ -89,13 +93,17 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
|||||||
* @throws IOException if an error occurs while reading.
|
* @throws IOException if an error occurs while reading.
|
||||||
*/
|
*/
|
||||||
public SharedStringsTable(InputStream is) throws IOException {
|
public SharedStringsTable(InputStream is) throws IOException {
|
||||||
|
super(null, null);
|
||||||
readFrom(is);
|
readFrom(is);
|
||||||
}
|
}
|
||||||
/**
|
|
||||||
* Create a new, empty SharedStringsTable
|
|
||||||
*/
|
|
||||||
public SharedStringsTable() {
|
public SharedStringsTable() {
|
||||||
count = uniqueCount = 0;
|
super(null, null);
|
||||||
|
}
|
||||||
|
|
||||||
|
public SharedStringsTable(PackagePart part, PackageRelationship rel) throws IOException {
|
||||||
|
super(part, rel);
|
||||||
|
readFrom(part.getInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -204,4 +212,12 @@ public class SharedStringsTable implements SharedStringSource, XSSFModel {
|
|||||||
sst.setSiArray(ctr);
|
sst.setSiArray(ctr);
|
||||||
doc.save(out, options);
|
doc.save(out, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void commit() throws IOException {
|
||||||
|
PackagePart part = getPackagePart();
|
||||||
|
OutputStream out = part.getOutputStream();
|
||||||
|
writeTo(out);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -36,6 +36,7 @@ import org.apache.poi.xssf.usermodel.XSSFCellStyle;
|
|||||||
import org.apache.poi.xssf.usermodel.XSSFFont;
|
import org.apache.poi.xssf.usermodel.XSSFFont;
|
||||||
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder;
|
import org.apache.poi.xssf.usermodel.extensions.XSSFCellBorder;
|
||||||
import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill;
|
import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill;
|
||||||
|
import org.apache.poi.POIXMLDocumentPart;
|
||||||
import org.apache.xmlbeans.XmlException;
|
import org.apache.xmlbeans.XmlException;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTBorder;
|
||||||
@ -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.CTXf;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.STPatternType;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.StyleSheetDocument;
|
||||||
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
import org.openxml4j.opc.PackageRelationship;
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Table of styles shared across all sheets in a workbook.
|
* Table of styles shared across all sheets in a workbook.
|
||||||
*
|
*
|
||||||
* @author ugo
|
* @author ugo
|
||||||
*/
|
*/
|
||||||
public class StylesTable implements StylesSource, XSSFModel {
|
public class StylesTable extends POIXMLDocumentPart implements StylesSource, XSSFModel {
|
||||||
private final Hashtable<Long,String> numberFormats = new Hashtable<Long,String>();
|
private final Hashtable<Long,String> numberFormats = new Hashtable<Long,String>();
|
||||||
private final List<CTFont> fonts = new ArrayList<CTFont>();
|
private final List<CTFont> fonts = new ArrayList<CTFont>();
|
||||||
private final List<CTFill> fills = new LinkedList<CTFill>();
|
private final List<CTFill> fills = new LinkedList<CTFill>();
|
||||||
@ -85,18 +89,25 @@ public class StylesTable implements StylesSource, XSSFModel {
|
|||||||
* @throws IOException if an error occurs while reading.
|
* @throws IOException if an error occurs while reading.
|
||||||
*/
|
*/
|
||||||
public StylesTable(InputStream is) throws IOException {
|
public StylesTable(InputStream is) throws IOException {
|
||||||
|
super(null, null);
|
||||||
readFrom(is);
|
readFrom(is);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* Create a new, empty StylesTable
|
* Create a new, empty StylesTable
|
||||||
*/
|
*/
|
||||||
public StylesTable() {
|
public StylesTable() {
|
||||||
|
super(null, null);
|
||||||
doc = StyleSheetDocument.Factory.newInstance();
|
doc = StyleSheetDocument.Factory.newInstance();
|
||||||
doc.addNewStyleSheet();
|
doc.addNewStyleSheet();
|
||||||
// Initialization required in order to make the document readable by MSExcel
|
// Initialization required in order to make the document readable by MSExcel
|
||||||
initialize();
|
initialize();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public StylesTable(PackagePart part, PackageRelationship rel) throws IOException {
|
||||||
|
super(part, rel);
|
||||||
|
readFrom(part.getInputStream());
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Read this shared styles table from an XML file.
|
* Read this shared styles table from an XML file.
|
||||||
*
|
*
|
||||||
@ -365,6 +376,14 @@ public class StylesTable implements StylesSource, XSSFModel {
|
|||||||
doc.save(out, options);
|
doc.save(out, options);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
protected void commit() throws IOException {
|
||||||
|
PackagePart part = getPackagePart();
|
||||||
|
OutputStream out = part.getOutputStream();
|
||||||
|
writeTo(out);
|
||||||
|
out.close();
|
||||||
|
}
|
||||||
|
|
||||||
private long putBorder(XSSFCellBorder border, List<CTBorder> borders) {
|
private long putBorder(XSSFCellBorder border, List<CTBorder> borders) {
|
||||||
return border.putBorder((LinkedList<CTBorder>) borders); // TODO - use List instead of LinkedList
|
return border.putBorder((LinkedList<CTBorder>) borders); // TODO - use List instead of LinkedList
|
||||||
}
|
}
|
||||||
|
@ -23,26 +23,22 @@ import org.apache.poi.ss.usermodel.RichTextString;
|
|||||||
|
|
||||||
public class XSSFCreationHelper implements CreationHelper {
|
public class XSSFCreationHelper implements CreationHelper {
|
||||||
private XSSFWorkbook workbook;
|
private XSSFWorkbook workbook;
|
||||||
private XSSFDataFormat dataFormat;
|
|
||||||
XSSFCreationHelper(XSSFWorkbook wb) {
|
XSSFCreationHelper(XSSFWorkbook wb) {
|
||||||
workbook = wb;
|
workbook = wb;
|
||||||
|
|
||||||
// Create the things we only ever need one of
|
|
||||||
dataFormat = new XSSFDataFormat(workbook.getStylesSource());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates a new XSSFRichTextString for you.
|
* Creates a new XSSFRichTextString for you.
|
||||||
*/
|
*/
|
||||||
public RichTextString createRichTextString(String text) {
|
public XSSFRichTextString createRichTextString(String text) {
|
||||||
return new XSSFRichTextString(text);
|
return new XSSFRichTextString(text);
|
||||||
}
|
}
|
||||||
|
|
||||||
public DataFormat createDataFormat() {
|
public XSSFDataFormat createDataFormat() {
|
||||||
return dataFormat;
|
return workbook.createDataFormat();
|
||||||
}
|
}
|
||||||
|
|
||||||
public Hyperlink createHyperlink(int type) {
|
public XSSFHyperlink createHyperlink(int type) {
|
||||||
return new XSSFHyperlink(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 java.util.List;
|
||||||
|
|
||||||
import org.apache.poi.POIXMLDocument;
|
import org.apache.poi.POIXMLDocument;
|
||||||
|
import org.apache.poi.POIXMLRelation;
|
||||||
import org.apache.poi.util.POILogFactory;
|
import org.apache.poi.util.POILogFactory;
|
||||||
import org.apache.poi.util.POILogger;
|
import org.apache.poi.util.POILogger;
|
||||||
import org.apache.poi.xssf.model.BinaryPart;
|
import org.apache.poi.xssf.model.BinaryPart;
|
||||||
@ -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(
|
public static final XSSFRelation WORKBOOK = new XSSFRelation(
|
||||||
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.main+xml",
|
"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);
|
return new XSSFRelation<R>(type, rel, defaultName, cls);
|
||||||
}
|
}
|
||||||
|
|
||||||
private String _type;
|
|
||||||
private String _relation;
|
|
||||||
private String _defaultName;
|
|
||||||
private Constructor<W> _constructor;
|
private Constructor<W> _constructor;
|
||||||
private final boolean _constructorTakesTwoArgs;
|
private final boolean _constructorTakesTwoArgs;
|
||||||
|
|
||||||
private XSSFRelation(String type, String rel, String defaultName, Class<W> cls) {
|
private XSSFRelation(String type, String rel, String defaultName, Class<W> cls) {
|
||||||
_type = type;
|
super(type, rel, defaultName);
|
||||||
_relation = rel;
|
|
||||||
_defaultName = defaultName;
|
|
||||||
if (cls == null) {
|
if (cls == null) {
|
||||||
_constructor = null;
|
_constructor = null;
|
||||||
_constructorTakesTwoArgs = false;
|
_constructorTakesTwoArgs = false;
|
||||||
@ -189,10 +186,7 @@ public final class XSSFRelation<W extends XSSFModel> {
|
|||||||
_constructorTakesTwoArgs = twoArg;
|
_constructorTakesTwoArgs = twoArg;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
public String getContentType() { return _type; }
|
|
||||||
public String getRelation() { return _relation; }
|
|
||||||
public String getDefaultFileName() { return _defaultName; }
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Does one of these exist for the given core
|
* Does one of these exist for the given core
|
||||||
* package part?
|
* package part?
|
||||||
|
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) {
|
private CTBorderPr getBorder(BorderSide side) {
|
||||||
switch (side) {
|
switch (side) {
|
||||||
case TOP: return border.getTop();
|
case TOP: {
|
||||||
case RIGHT: return border.getRight();
|
CTBorderPr borderPr = border.isSetTop() ? border.getTop() : border.addNewTop();
|
||||||
case BOTTOM: return border.getBottom();
|
return borderPr;
|
||||||
case LEFT: return border.getLeft();
|
}
|
||||||
|
case RIGHT: {
|
||||||
|
CTBorderPr borderPr = border.isSetRight() ? border.getRight() : border.addNewRight();
|
||||||
|
return borderPr;
|
||||||
|
}
|
||||||
|
case BOTTOM:{
|
||||||
|
CTBorderPr borderPr = border.isSetBottom() ? border.getBottom() : border.addNewBottom();
|
||||||
|
return borderPr;
|
||||||
|
}
|
||||||
|
case LEFT:{
|
||||||
|
CTBorderPr borderPr = border.isSetLeft() ? border.getLeft() : border.addNewLeft();
|
||||||
|
return borderPr;
|
||||||
|
}
|
||||||
default: throw new IllegalArgumentException("No suitable side specified for the border");
|
default: throw new IllegalArgumentException("No suitable side specified for the border");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,10 +17,7 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf;
|
package org.apache.poi.xssf;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
import java.io.*;
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.io.InputStream;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.HSSFTestDataSamples;
|
import org.apache.poi.hssf.HSSFTestDataSamples;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||||
@ -47,15 +44,20 @@ public class XSSFTestDataSamples {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
public static <R extends Workbook> R writeOutAndReadBack(R wb) {
|
public static <R extends Workbook> R writeOutAndReadBack(R wb) {
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
|
|
||||||
Workbook result;
|
Workbook result;
|
||||||
try {
|
try {
|
||||||
wb.write(baos);
|
|
||||||
InputStream is = new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
if (wb instanceof HSSFWorkbook) {
|
if (wb instanceof HSSFWorkbook) {
|
||||||
|
ByteArrayOutputStream baos = new ByteArrayOutputStream(8192);
|
||||||
|
wb.write(baos);
|
||||||
|
InputStream is = new ByteArrayInputStream(baos.toByteArray());
|
||||||
result = new HSSFWorkbook(is);
|
result = new HSSFWorkbook(is);
|
||||||
} else if (wb instanceof XSSFWorkbook) {
|
} else if (wb instanceof XSSFWorkbook) {
|
||||||
Package pkg = Package.open(is);
|
File tmp = File.createTempFile("poi-ooxml-", ".xlsx");
|
||||||
|
tmp.deleteOnExit();
|
||||||
|
FileOutputStream out = new FileOutputStream(tmp);
|
||||||
|
wb.write(out);
|
||||||
|
out.close();
|
||||||
|
Package pkg = Package.open(tmp.getAbsolutePath());
|
||||||
result = new XSSFWorkbook(pkg);
|
result = new XSSFWorkbook(pkg);
|
||||||
} else {
|
} else {
|
||||||
throw new RuntimeException("Unexpected workbook type ("
|
throw new RuntimeException("Unexpected workbook type ("
|
||||||
|
@ -30,6 +30,7 @@ import org.apache.poi.xssf.usermodel.XSSFComment;
|
|||||||
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
import org.apache.poi.xssf.usermodel.XSSFRichTextString;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
import org.apache.poi.xssf.usermodel.XSSFSheet;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.openxml4j.opc.Package;
|
import org.openxml4j.opc.Package;
|
||||||
import org.openxml4j.opc.PackagePart;
|
import org.openxml4j.opc.PackagePart;
|
||||||
import org.openxml4j.opc.PackagingURIHelper;
|
import org.openxml4j.opc.PackagingURIHelper;
|
||||||
@ -212,12 +213,8 @@ public class TestCommentsTable extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
// Save, and re-load the file
|
// Save, and re-load the file
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
workbook = XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||||
workbook.write(baos);
|
|
||||||
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
workbook = new XSSFWorkbook(Package.open(bais));
|
|
||||||
|
|
||||||
// Check we still have comments where we should do
|
// Check we still have comments where we should do
|
||||||
sheet1 = workbook.getSheetAt(0);
|
sheet1 = workbook.getSheetAt(0);
|
||||||
sheet2 = (XSSFSheet)workbook.getSheetAt(1);
|
sheet2 = (XSSFSheet)workbook.getSheetAt(1);
|
||||||
@ -259,12 +256,8 @@ public class TestCommentsTable extends TestCase {
|
|||||||
sheet1.getRow(12).getCell(2).getCellComment().getAuthor());
|
sheet1.getRow(12).getCell(2).getCellComment().getAuthor());
|
||||||
|
|
||||||
// Save, and re-load the file
|
// Save, and re-load the file
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
workbook = XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||||
workbook.write(baos);
|
|
||||||
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
workbook = new XSSFWorkbook(Package.open(bais));
|
|
||||||
|
|
||||||
// Check we still have comments where we should do
|
// Check we still have comments where we should do
|
||||||
sheet1 = workbook.getSheetAt(0);
|
sheet1 = workbook.getSheetAt(0);
|
||||||
assertNotNull(sheet1.getRow(4).getCell(2).getCellComment());
|
assertNotNull(sheet1.getRow(4).getCell(2).getCellComment());
|
||||||
|
@ -17,120 +17,107 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf.usermodel;
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.io.FileOutputStream;
|
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
import org.openxml4j.opc.Package;
|
import org.openxml4j.opc.Package;
|
||||||
import org.openxml4j.opc.PackagePart;
|
import org.openxml4j.opc.PackagePart;
|
||||||
import org.openxml4j.opc.PackagingURIHelper;
|
import org.openxml4j.opc.PackagingURIHelper;
|
||||||
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
|
|
||||||
public class TestXSSFBugs extends TestCase {
|
public class TestXSSFBugs extends TestCase {
|
||||||
private String getFilePath(String file) {
|
private String getFilePath(String file) {
|
||||||
File xml = new File(
|
File xml = new File(
|
||||||
System.getProperty("HSSF.testdata.path") +
|
System.getProperty("HSSF.testdata.path") +
|
||||||
File.separator + file
|
File.separator + file
|
||||||
);
|
);
|
||||||
assertTrue(xml.exists());
|
assertTrue(xml.exists());
|
||||||
|
|
||||||
return xml.toString();
|
return xml.toString();
|
||||||
}
|
}
|
||||||
|
|
||||||
private Package saveAndOpen(XSSFWorkbook wb) throws Exception {
|
/**
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
* Named ranges had the right reference, but
|
||||||
wb.write(baos);
|
* the wrong sheet name
|
||||||
ByteArrayInputStream inp = new ByteArrayInputStream(
|
*/
|
||||||
baos.toByteArray()
|
public void test45430() throws Exception {
|
||||||
);
|
XSSFWorkbook wb = new XSSFWorkbook(getFilePath("45430.xlsx"));
|
||||||
Package pkg = Package.open(inp);
|
assertFalse(wb.isMacroEnabled());
|
||||||
return pkg;
|
assertEquals(3, wb.getNumberOfNames());
|
||||||
}
|
|
||||||
|
assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId());
|
||||||
/**
|
assertFalse(wb.getNameAt(0).getCTName().isSetLocalSheetId());
|
||||||
* Named ranges had the right reference, but
|
assertEquals("SheetA!$A$1", wb.getNameAt(0).getReference());
|
||||||
* the wrong sheet name
|
assertEquals("SheetA", wb.getNameAt(0).getSheetName());
|
||||||
*/
|
|
||||||
public void test45430() throws Exception {
|
assertEquals(0, wb.getNameAt(1).getCTName().getLocalSheetId());
|
||||||
XSSFWorkbook wb = new XSSFWorkbook(getFilePath("45430.xlsx"));
|
assertFalse(wb.getNameAt(1).getCTName().isSetLocalSheetId());
|
||||||
assertFalse(wb.isMacroEnabled());
|
assertEquals("SheetB!$A$1", wb.getNameAt(1).getReference());
|
||||||
assertEquals(3, wb.getNumberOfNames());
|
assertEquals("SheetB", wb.getNameAt(1).getSheetName());
|
||||||
|
|
||||||
assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId());
|
assertEquals(0, wb.getNameAt(2).getCTName().getLocalSheetId());
|
||||||
assertFalse(wb.getNameAt(0).getCTName().isSetLocalSheetId());
|
assertFalse(wb.getNameAt(2).getCTName().isSetLocalSheetId());
|
||||||
assertEquals("SheetA!$A$1", wb.getNameAt(0).getReference());
|
assertEquals("SheetC!$A$1", wb.getNameAt(2).getReference());
|
||||||
assertEquals("SheetA", wb.getNameAt(0).getSheetName());
|
assertEquals("SheetC", wb.getNameAt(2).getSheetName());
|
||||||
|
|
||||||
assertEquals(0, wb.getNameAt(1).getCTName().getLocalSheetId());
|
// Save and re-load, still there
|
||||||
assertFalse(wb.getNameAt(1).getCTName().isSetLocalSheetId());
|
XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
assertEquals("SheetB!$A$1", wb.getNameAt(1).getReference());
|
assertEquals(3, nwb.getNumberOfNames());
|
||||||
assertEquals("SheetB", wb.getNameAt(1).getSheetName());
|
assertEquals("SheetA!$A$1", nwb.getNameAt(0).getReference());
|
||||||
|
}
|
||||||
assertEquals(0, wb.getNameAt(2).getCTName().getLocalSheetId());
|
|
||||||
assertFalse(wb.getNameAt(2).getCTName().isSetLocalSheetId());
|
/**
|
||||||
assertEquals("SheetC!$A$1", wb.getNameAt(2).getReference());
|
* We should carry vba macros over after save
|
||||||
assertEquals("SheetC", wb.getNameAt(2).getSheetName());
|
*/
|
||||||
|
public void test45431() throws Exception {
|
||||||
// Save and re-load, still there
|
Package pkg = Package.open(getFilePath("45431.xlsm"));
|
||||||
Package nPkg = saveAndOpen(wb);
|
XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
||||||
XSSFWorkbook nwb = new XSSFWorkbook(nPkg);
|
assertTrue(wb.isMacroEnabled());
|
||||||
assertEquals(3, nwb.getNumberOfNames());
|
|
||||||
assertEquals("SheetA!$A$1", nwb.getNameAt(0).getReference());
|
// Check the various macro related bits can be found
|
||||||
}
|
PackagePart vba = pkg.getPart(
|
||||||
|
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
||||||
/**
|
);
|
||||||
* We should carry vba macros over after save
|
assertNotNull(vba);
|
||||||
*/
|
// And the drawing bit
|
||||||
public void test45431() throws Exception {
|
PackagePart drw = pkg.getPart(
|
||||||
Package pkg = Package.open(getFilePath("45431.xlsm"));
|
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
|
||||||
XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
);
|
||||||
assertTrue(wb.isMacroEnabled());
|
assertNotNull(drw);
|
||||||
|
|
||||||
// Check the various macro related bits can be found
|
|
||||||
PackagePart vba = pkg.getPart(
|
// Save and re-open, both still there
|
||||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
);
|
Package nPkg = nwb.getPackage();
|
||||||
assertNotNull(vba);
|
assertTrue(nwb.isMacroEnabled());
|
||||||
// And the drawing bit
|
|
||||||
PackagePart drw = pkg.getPart(
|
vba = nPkg.getPart(
|
||||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
|
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
||||||
);
|
);
|
||||||
assertNotNull(drw);
|
assertNotNull(vba);
|
||||||
|
drw = nPkg.getPart(
|
||||||
|
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
|
||||||
// Save and re-open, both still there
|
);
|
||||||
Package nPkg = saveAndOpen(wb);
|
assertNotNull(drw);
|
||||||
XSSFWorkbook nwb = new XSSFWorkbook(nPkg);
|
|
||||||
assertTrue(nwb.isMacroEnabled());
|
// And again, just to be sure
|
||||||
|
nwb = XSSFTestDataSamples.writeOutAndReadBack(nwb);
|
||||||
vba = nPkg.getPart(
|
nPkg = nwb.getPackage();
|
||||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
assertTrue(nwb.isMacroEnabled());
|
||||||
);
|
|
||||||
assertNotNull(vba);
|
vba = nPkg.getPart(
|
||||||
drw = nPkg.getPart(
|
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
||||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
|
);
|
||||||
);
|
assertNotNull(vba);
|
||||||
assertNotNull(drw);
|
drw = nPkg.getPart(
|
||||||
|
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
|
||||||
// And again, just to be sure
|
);
|
||||||
nPkg = saveAndOpen(nwb);
|
assertNotNull(drw);
|
||||||
nwb = new XSSFWorkbook(nPkg);
|
|
||||||
assertTrue(nwb.isMacroEnabled());
|
// For testing with excel
|
||||||
|
|
||||||
vba = nPkg.getPart(
|
|
||||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
|
||||||
);
|
|
||||||
assertNotNull(vba);
|
|
||||||
drw = nPkg.getPart(
|
|
||||||
PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml")
|
|
||||||
);
|
|
||||||
assertNotNull(drw);
|
|
||||||
|
|
||||||
// For testing with excel
|
|
||||||
// FileOutputStream fout = new FileOutputStream("/tmp/foo.xlsm");
|
// FileOutputStream fout = new FileOutputStream("/tmp/foo.xlsm");
|
||||||
// nwb.write(fout);
|
// nwb.write(fout);
|
||||||
// fout.close();
|
// fout.close();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,9 +17,6 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf.usermodel;
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
|
|
||||||
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
import org.apache.poi.hssf.usermodel.HSSFRichTextString;
|
||||||
import org.apache.poi.ss.usermodel.Cell;
|
import org.apache.poi.ss.usermodel.Cell;
|
||||||
import org.apache.poi.ss.usermodel.Comment;
|
import org.apache.poi.ss.usermodel.Comment;
|
||||||
@ -27,6 +24,7 @@ import org.apache.poi.ss.usermodel.RichTextString;
|
|||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.xssf.model.CommentsTable;
|
import org.apache.poi.xssf.model.CommentsTable;
|
||||||
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.openxml4j.opc.Package;
|
import org.openxml4j.opc.Package;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTAuthors;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
||||||
@ -135,7 +133,7 @@ public class TestXSSFComment extends TestCase {
|
|||||||
*/
|
*/
|
||||||
public void testCreateSave() throws Exception {
|
public void testCreateSave() throws Exception {
|
||||||
XSSFWorkbook wb = new XSSFWorkbook();
|
XSSFWorkbook wb = new XSSFWorkbook();
|
||||||
XSSFSheet s1 = (XSSFSheet)wb.createSheet();
|
XSSFSheet s1 = wb.createSheet();
|
||||||
Row r1 = s1.createRow(0);
|
Row r1 = s1.createRow(0);
|
||||||
Cell r1c1 = r1.createCell(0);
|
Cell r1c1 = r1.createCell(0);
|
||||||
r1c1.setCellValue(2.2);
|
r1c1.setCellValue(2.2);
|
||||||
@ -150,12 +148,8 @@ public class TestXSSFComment extends TestCase {
|
|||||||
assertEquals(1, s1.getNumberOfComments());
|
assertEquals(1, s1.getNumberOfComments());
|
||||||
|
|
||||||
// Save and re-load
|
// Save and re-load
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
wb.write(baos);
|
s1 = wb.getSheetAt(0);
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
|
|
||||||
wb = new XSSFWorkbook(Package.open(bais));
|
|
||||||
s1 = (XSSFSheet)wb.getSheetAt(0);
|
|
||||||
|
|
||||||
assertEquals(1, s1.getNumberOfComments());
|
assertEquals(1, s1.getNumberOfComments());
|
||||||
assertNotNull(s1.getRow(0).getCell(0).getCellComment());
|
assertNotNull(s1.getRow(0).getCell(0).getCellComment());
|
||||||
@ -171,12 +165,9 @@ public class TestXSSFComment extends TestCase {
|
|||||||
assertEquals(2, s1.getNumberOfComments());
|
assertEquals(2, s1.getNumberOfComments());
|
||||||
|
|
||||||
// Save and re-load
|
// Save and re-load
|
||||||
baos = new ByteArrayOutputStream();
|
|
||||||
wb.write(baos);
|
wb = XSSFTestDataSamples.writeOutAndReadBack(wb);
|
||||||
bais = new ByteArrayInputStream(baos.toByteArray());
|
s1 = wb.getSheetAt(0);
|
||||||
|
|
||||||
wb = new XSSFWorkbook(Package.open(bais));
|
|
||||||
s1 = (XSSFSheet)wb.getSheetAt(0);
|
|
||||||
|
|
||||||
assertEquals(2, s1.getNumberOfComments());
|
assertEquals(2, s1.getNumberOfComments());
|
||||||
assertNotNull(s1.getCellComment(0, 0));
|
assertNotNull(s1.getCellComment(0, 0));
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf.usermodel;
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
|
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
@ -27,6 +25,7 @@ import org.apache.poi.ss.usermodel.Cell;
|
|||||||
import org.apache.poi.ss.usermodel.CreationHelper;
|
import org.apache.poi.ss.usermodel.CreationHelper;
|
||||||
import org.apache.poi.ss.usermodel.Hyperlink;
|
import org.apache.poi.ss.usermodel.Hyperlink;
|
||||||
import org.apache.poi.ss.usermodel.Row;
|
import org.apache.poi.ss.usermodel.Row;
|
||||||
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.openxml4j.opc.Package;
|
import org.openxml4j.opc.Package;
|
||||||
|
|
||||||
public class TestXSSFHyperlink extends TestCase {
|
public class TestXSSFHyperlink extends TestCase {
|
||||||
@ -79,12 +78,9 @@ public class TestXSSFHyperlink extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
// Write out, and check
|
// Write out, and check
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
|
||||||
workbook.write(baos);
|
|
||||||
ByteArrayInputStream bais = new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
|
|
||||||
// Load up again, check all links still there
|
// Load up again, check all links still there
|
||||||
XSSFWorkbook wb2 = new XSSFWorkbook(Package.open(bais));
|
XSSFWorkbook wb2 = XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||||
assertEquals(3, wb2.getNumberOfSheets());
|
assertEquals(3, wb2.getNumberOfSheets());
|
||||||
assertNotNull(wb2.getSheetAt(0));
|
assertNotNull(wb2.getSheetAt(0));
|
||||||
assertNotNull(wb2.getSheetAt(1));
|
assertNotNull(wb2.getSheetAt(1));
|
||||||
@ -119,18 +115,14 @@ public class TestXSSFHyperlink extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
// Save and re-load once more
|
// Save and re-load once more
|
||||||
baos = new ByteArrayOutputStream();
|
|
||||||
wb2.write(baos);
|
XSSFWorkbook wb3 = XSSFTestDataSamples.writeOutAndReadBack(wb2);
|
||||||
bais = new ByteArrayInputStream(baos.toByteArray());
|
|
||||||
|
|
||||||
|
|
||||||
XSSFWorkbook wb3 = new XSSFWorkbook(Package.open(bais));
|
|
||||||
assertEquals(3, wb3.getNumberOfSheets());
|
assertEquals(3, wb3.getNumberOfSheets());
|
||||||
assertNotNull(wb3.getSheetAt(0));
|
assertNotNull(wb3.getSheetAt(0));
|
||||||
assertNotNull(wb3.getSheetAt(1));
|
assertNotNull(wb3.getSheetAt(1));
|
||||||
assertNotNull(wb3.getSheetAt(2));
|
assertNotNull(wb3.getSheetAt(2));
|
||||||
|
|
||||||
sheet = (XSSFSheet)wb3.getSheetAt(0);
|
sheet = wb3.getSheetAt(0);
|
||||||
|
|
||||||
assertEquals(5, sheet.getNumHyperlinks());
|
assertEquals(5, sheet.getNumHyperlinks());
|
||||||
doTestHyperlinkContents(sheet);
|
doTestHyperlinkContents(sheet);
|
||||||
|
@ -17,8 +17,6 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf.usermodel;
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
import java.io.ByteArrayInputStream;
|
|
||||||
import java.io.ByteArrayOutputStream;
|
|
||||||
import java.io.File;
|
import java.io.File;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import junit.framework.TestCase;
|
import junit.framework.TestCase;
|
||||||
@ -30,11 +28,7 @@ import org.apache.poi.ss.util.Region;
|
|||||||
import org.apache.poi.xssf.model.CommentsTable;
|
import org.apache.poi.xssf.model.CommentsTable;
|
||||||
import org.apache.poi.xssf.model.StylesTable;
|
import org.apache.poi.xssf.model.StylesTable;
|
||||||
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
|
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
|
||||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
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.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCol;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols;
|
||||||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTComment;
|
||||||
@ -349,11 +343,7 @@ public class TestXSSFSheet extends TestCase {
|
|||||||
|
|
||||||
|
|
||||||
// Save and reload
|
// Save and reload
|
||||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
XSSFWorkbook wb = XSSFTestDataSamples.writeOutAndReadBack(workbook);
|
||||||
workbook.write(baos);
|
|
||||||
XSSFWorkbook wb = new XSSFWorkbook(Package.open(
|
|
||||||
new ByteArrayInputStream(baos.toByteArray())
|
|
||||||
));
|
|
||||||
|
|
||||||
hdr = (XSSFOddHeader)wb.getSheetAt(0).getHeader();
|
hdr = (XSSFOddHeader)wb.getSheetAt(0).getHeader();
|
||||||
ftr = (XSSFOddFooter)wb.getSheetAt(0).getFooter();
|
ftr = (XSSFOddFooter)wb.getSheetAt(0).getFooter();
|
||||||
|
@ -441,7 +441,7 @@ public final class TestXSSFWorkbook extends TestCase {
|
|||||||
|
|
||||||
// Now, an existing file with named ranges
|
// Now, an existing file with named ranges
|
||||||
workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx");
|
workbook = XSSFTestDataSamples.openSampleWorkbook("WithVariousData.xlsx");
|
||||||
|
|
||||||
assertEquals(2, workbook.getNumberOfNames());
|
assertEquals(2, workbook.getNumberOfNames());
|
||||||
assertEquals("Sheet1!$A$2:$A$7", workbook.getNameAt(0).getReference());
|
assertEquals("Sheet1!$A$2:$A$7", workbook.getNameAt(0).getReference());
|
||||||
assertEquals("AllANumbers", workbook.getNameAt(0).getNameName());
|
assertEquals("AllANumbers", workbook.getNameAt(0).getNameName());
|
||||||
|
Loading…
Reference in New Issue
Block a user