More work on bug #45431 - Support for .xlsm files, sufficient for simple files to be loaded by excel without warning
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@680871 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
c090d99907
commit
233d99fc4d
@ -37,6 +37,7 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.5.1-beta2" date="2008-??-??">
|
<release version="3.5.1-beta2" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">45431 - Support for .xlsm files, sufficient for simple files to be loaded by excel without warning</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">New class org.apache.poi.hssf.record.RecordFormatException, which DDF uses instead of the HSSF version, and the HSSF version inherits from</action>
|
<action dev="POI-DEVELOPERS" type="add">New class org.apache.poi.hssf.record.RecordFormatException, which DDF uses instead of the HSSF version, and the HSSF version inherits from</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45431 - Partial support for .xlm files. Not quite enough for excel to load them though</action>
|
<action dev="POI-DEVELOPERS" type="add">45431 - Partial support for .xlm files. Not quite enough for excel to load them though</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45430 - Correct named range sheet reporting when no local sheet id is given in the xml</action>
|
<action dev="POI-DEVELOPERS" type="fix">45430 - Correct named range sheet reporting when no local sheet id is given in the xml</action>
|
||||||
|
@ -34,6 +34,7 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.5.1-beta2" date="2008-??-??">
|
<release version="3.5.1-beta2" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">45431 - Support for .xlsm files, sufficient for simple files to be loaded by excel without warning</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">New class org.apache.poi.hssf.record.RecordFormatException, which DDF uses instead of the HSSF version, and the HSSF version inherits from</action>
|
<action dev="POI-DEVELOPERS" type="add">New class org.apache.poi.hssf.record.RecordFormatException, which DDF uses instead of the HSSF version, and the HSSF version inherits from</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">45431 - Partial support for .xlm files. Not quite enough for excel to load them though</action>
|
<action dev="POI-DEVELOPERS" type="add">45431 - Partial support for .xlm files. Not quite enough for excel to load them though</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">45430 - Correct named range sheet reporting when no local sheet id is given in the xml</action>
|
<action dev="POI-DEVELOPERS" type="fix">45430 - Correct named range sheet reporting when no local sheet id is given in the xml</action>
|
||||||
|
@ -22,6 +22,7 @@ package org.apache.poi.util;
|
|||||||
import java.io.ByteArrayOutputStream;
|
import java.io.ByteArrayOutputStream;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
public class IOUtils
|
public class IOUtils
|
||||||
{
|
{
|
||||||
@ -84,4 +85,19 @@ public class IOUtils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies all the data from the given InputStream to the
|
||||||
|
* OutputStream. It leaves both streams open, so you
|
||||||
|
* will still need to close them once done.
|
||||||
|
*/
|
||||||
|
public static void copy(InputStream inp, OutputStream out) throws IOException {
|
||||||
|
byte[] buff = new byte[4096];
|
||||||
|
int count;
|
||||||
|
while( (count = inp.read(buff)) != -1 ) {
|
||||||
|
if(count > 0) {
|
||||||
|
out.write(buff, 0, count);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
@ -117,8 +117,19 @@ public abstract class POIXMLDocument {
|
|||||||
* @throws InvalidFormatException
|
* @throws InvalidFormatException
|
||||||
*/
|
*/
|
||||||
protected PackagePart getTargetPart(PackageRelationship rel) throws InvalidFormatException {
|
protected PackagePart getTargetPart(PackageRelationship rel) throws InvalidFormatException {
|
||||||
|
return getTargetPart(getPackage(), rel);
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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
|
||||||
|
* @throws InvalidFormatException
|
||||||
|
*/
|
||||||
|
public static PackagePart getTargetPart(Package pkg, PackageRelationship rel) throws InvalidFormatException {
|
||||||
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
|
PackagePartName relName = PackagingURIHelper.createPartName(rel.getTargetURI());
|
||||||
PackagePart part = getPackage().getPart(relName);
|
PackagePart part = pkg.getPart(relName);
|
||||||
if (part == null) {
|
if (part == null) {
|
||||||
throw new IllegalArgumentException("No part found for relationship " + rel);
|
throw new IllegalArgumentException("No part found for relationship " + rel);
|
||||||
}
|
}
|
||||||
|
101
src/ooxml/java/org/apache/poi/xssf/model/Control.java
Normal file
101
src/ooxml/java/org/apache/poi/xssf/model/Control.java
Normal file
@ -0,0 +1,101 @@
|
|||||||
|
package org.apache.poi.xssf.model;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFActiveXData;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
|
import org.openxml4j.exceptions.InvalidFormatException;
|
||||||
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
import org.openxml4j.opc.PackagePartName;
|
||||||
|
import org.openxml4j.opc.PackageRelationship;
|
||||||
|
import org.openxml4j.opc.PackagingURIHelper;
|
||||||
|
import org.openxml4j.opc.TargetMode;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTControl;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A control object in XSSF, which will typically
|
||||||
|
* have active x data associated with it.
|
||||||
|
*/
|
||||||
|
public class Control implements XSSFChildContainingModel {
|
||||||
|
private CTControl control;
|
||||||
|
private String originalId;
|
||||||
|
private ArrayList<XSSFActiveXData> activexBins;
|
||||||
|
|
||||||
|
public Control(InputStream is, String originalId) throws IOException {
|
||||||
|
readFrom(is);
|
||||||
|
this.originalId = originalId;
|
||||||
|
this.activexBins = new ArrayList<XSSFActiveXData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOriginalId() {
|
||||||
|
return this.originalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Control() {
|
||||||
|
this.control = CTControl.Factory.newInstance();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* For unit testing only!
|
||||||
|
*/
|
||||||
|
protected Control(CTControl control) {
|
||||||
|
this.control = control;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readFrom(InputStream is) throws IOException {
|
||||||
|
try {
|
||||||
|
CTControl doc = CTControl.Factory.parse(is);
|
||||||
|
control = doc;
|
||||||
|
} catch (XmlException e) {
|
||||||
|
throw new IOException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
XmlOptions options = new XmlOptions();
|
||||||
|
options.setSaveOuter();
|
||||||
|
options.setUseDefaultNamespace();
|
||||||
|
// Requests use of whitespace for easier reading
|
||||||
|
options.setSavePrettyPrint();
|
||||||
|
control.save(out, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds our XSSFActiveXData children
|
||||||
|
*/
|
||||||
|
public void findChildren(PackagePart modelPart) throws IOException, InvalidFormatException {
|
||||||
|
for(PackageRelationship rel : modelPart.getRelationshipsByType(XSSFWorkbook.ACTIVEX_BINS.getRelation())) {
|
||||||
|
PackagePart binPart = XSSFWorkbook.getTargetPart(modelPart.getPackage(), rel);
|
||||||
|
XSSFActiveXData actX = new XSSFActiveXData(binPart, rel.getId());
|
||||||
|
activexBins.add(actX);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes back out our XSSFPictureData children
|
||||||
|
*/
|
||||||
|
public void writeChildren(PackagePart modelPart) throws IOException, InvalidFormatException {
|
||||||
|
int binIndex = 1;
|
||||||
|
OutputStream out;
|
||||||
|
|
||||||
|
for(XSSFActiveXData actX : activexBins) {
|
||||||
|
PackagePartName binPartName = PackagingURIHelper.createPartName(XSSFWorkbook.ACTIVEX_BINS.getFileName(binIndex));
|
||||||
|
modelPart.addRelationship(binPartName, TargetMode.INTERNAL, XSSFWorkbook.ACTIVEX_BINS.getRelation(), getOriginalId());
|
||||||
|
PackagePart imagePart = modelPart.getPackage().createPart(binPartName, XSSFWorkbook.ACTIVEX_BINS.getContentType());
|
||||||
|
out = imagePart.getOutputStream();
|
||||||
|
actX.writeTo(out);
|
||||||
|
out.close();
|
||||||
|
binIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<XSSFActiveXData> getData() {
|
||||||
|
return this.activexBins;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addData(XSSFActiveXData activeX) {
|
||||||
|
this.activexBins.add(activeX);
|
||||||
|
}
|
||||||
|
}
|
105
src/ooxml/java/org/apache/poi/xssf/model/Drawing.java
Normal file
105
src/ooxml/java/org/apache/poi/xssf/model/Drawing.java
Normal file
@ -0,0 +1,105 @@
|
|||||||
|
package org.apache.poi.xssf.model;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
import java.util.ArrayList;
|
||||||
|
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFPictureData;
|
||||||
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
|
import org.apache.xmlbeans.XmlException;
|
||||||
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
|
import org.openxml4j.exceptions.InvalidFormatException;
|
||||||
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
import org.openxml4j.opc.PackagePartName;
|
||||||
|
import org.openxml4j.opc.PackageRelationship;
|
||||||
|
import org.openxml4j.opc.PackagingURIHelper;
|
||||||
|
import org.openxml4j.opc.TargetMode;
|
||||||
|
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTDrawing;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A drawing object in XSSF. May well have raw pictures
|
||||||
|
* attached to it as children.
|
||||||
|
*/
|
||||||
|
public class Drawing implements XSSFChildContainingModel {
|
||||||
|
private CTDrawing drawing;
|
||||||
|
private String originalId;
|
||||||
|
|
||||||
|
/** Raw pictures attached to the drawing */
|
||||||
|
private ArrayList<XSSFPictureData> pictures;
|
||||||
|
|
||||||
|
public Drawing(InputStream is, String originalId) throws IOException {
|
||||||
|
readFrom(is);
|
||||||
|
this.originalId = originalId;
|
||||||
|
this.pictures = new ArrayList<XSSFPictureData>();
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOriginalId() {
|
||||||
|
return this.originalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Drawing() {
|
||||||
|
this.drawing = CTDrawing.Factory.newInstance();
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* For unit testing only!
|
||||||
|
*/
|
||||||
|
protected Drawing(CTDrawing drawing) {
|
||||||
|
this.drawing = drawing;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void readFrom(InputStream is) throws IOException {
|
||||||
|
try {
|
||||||
|
CTDrawing doc = CTDrawing.Factory.parse(is);
|
||||||
|
drawing = doc;
|
||||||
|
} catch (XmlException e) {
|
||||||
|
throw new IOException(e.getLocalizedMessage());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
XmlOptions options = new XmlOptions();
|
||||||
|
options.setSaveOuter();
|
||||||
|
options.setUseDefaultNamespace();
|
||||||
|
// Requests use of whitespace for easier reading
|
||||||
|
options.setSavePrettyPrint();
|
||||||
|
drawing.save(out, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds our XSSFPictureData children
|
||||||
|
*/
|
||||||
|
public void findChildren(PackagePart modelPart) throws IOException, InvalidFormatException {
|
||||||
|
for(PackageRelationship rel : modelPart.getRelationshipsByType(XSSFWorkbook.IMAGES.getRelation())) {
|
||||||
|
PackagePart imagePart = XSSFWorkbook.getTargetPart(modelPart.getPackage(), rel);
|
||||||
|
XSSFPictureData pd = new XSSFPictureData(imagePart, rel.getId());
|
||||||
|
pictures.add(pd);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Writes back out our XSSFPictureData children
|
||||||
|
*/
|
||||||
|
public void writeChildren(PackagePart modelPart) throws IOException, InvalidFormatException {
|
||||||
|
int pictureIndex = 1;
|
||||||
|
OutputStream out;
|
||||||
|
|
||||||
|
for(XSSFPictureData picture : pictures) {
|
||||||
|
PackagePartName imagePartName = PackagingURIHelper.createPartName(XSSFWorkbook.IMAGES.getFileName(pictureIndex));
|
||||||
|
modelPart.addRelationship(imagePartName, TargetMode.INTERNAL, XSSFWorkbook.IMAGES.getRelation(), getOriginalId());
|
||||||
|
PackagePart imagePart = modelPart.getPackage().createPart(imagePartName, XSSFWorkbook.IMAGES.getContentType());
|
||||||
|
out = imagePart.getOutputStream();
|
||||||
|
picture.writeTo(out);
|
||||||
|
out.close();
|
||||||
|
pictureIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<XSSFPictureData> getPictures()
|
||||||
|
{
|
||||||
|
return this.pictures;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void addPictures(XSSFPictureData picture)
|
||||||
|
{
|
||||||
|
this.pictures.add(picture);
|
||||||
|
}
|
||||||
|
}
|
@ -0,0 +1,42 @@
|
|||||||
|
/* ====================================================================
|
||||||
|
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.model;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
|
||||||
|
import org.openxml4j.exceptions.InvalidFormatException;
|
||||||
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Common interface for XSSF models, which have (typically
|
||||||
|
* binary) children to them.
|
||||||
|
* One example is a VmlDrawing (Drawing), which can have
|
||||||
|
* raw images associated with it.
|
||||||
|
*/
|
||||||
|
public interface XSSFChildContainingModel extends XSSFModel {
|
||||||
|
/**
|
||||||
|
* Find any children associated with the {@link XSSFModel}.
|
||||||
|
* @param modelPart The PackagePart of this model
|
||||||
|
*/
|
||||||
|
public void findChildren(PackagePart modelPart) throws IOException, InvalidFormatException;
|
||||||
|
/**
|
||||||
|
* Writes out any children associated with the {@link XSSFModel},
|
||||||
|
* along with the required relationship stuff.
|
||||||
|
* @param modelPart The new PackagePart of this model
|
||||||
|
*/
|
||||||
|
public void writeChildren(PackagePart modelPart) throws IOException, InvalidFormatException;
|
||||||
|
}
|
@ -0,0 +1,49 @@
|
|||||||
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
|
import org.apache.poi.ss.usermodel.PictureData;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
|
||||||
|
public class XSSFActiveXData implements PictureData {
|
||||||
|
|
||||||
|
private PackagePart packagePart;
|
||||||
|
private String originalId;
|
||||||
|
|
||||||
|
public XSSFActiveXData(PackagePart packagePart, String originalId) {
|
||||||
|
this(packagePart);
|
||||||
|
this.originalId = originalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public XSSFActiveXData(PackagePart packagePart) {
|
||||||
|
this.packagePart = packagePart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getOriginalId() {
|
||||||
|
return originalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
public PackagePart getPart() {
|
||||||
|
return packagePart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
IOUtils.copy(packagePart.getInputStream(), out);
|
||||||
|
}
|
||||||
|
|
||||||
|
public byte[] getData() {
|
||||||
|
// TODO - is this right?
|
||||||
|
// Are there headers etc?
|
||||||
|
try {
|
||||||
|
return IOUtils.toByteArray(packagePart.getInputStream());
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
public String suggestFileExtension() {
|
||||||
|
return packagePart.getPartName().getExtension();
|
||||||
|
}
|
||||||
|
}
|
@ -17,26 +17,51 @@
|
|||||||
|
|
||||||
package org.apache.poi.xssf.usermodel;
|
package org.apache.poi.xssf.usermodel;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.OutputStream;
|
||||||
|
|
||||||
import org.apache.poi.ss.usermodel.PictureData;
|
import org.apache.poi.ss.usermodel.PictureData;
|
||||||
|
import org.apache.poi.util.IOUtils;
|
||||||
import org.openxml4j.opc.PackagePart;
|
import org.openxml4j.opc.PackagePart;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Raw picture data, normally attached to a
|
||||||
|
* vmlDrawing
|
||||||
|
*/
|
||||||
public class XSSFPictureData implements PictureData {
|
public class XSSFPictureData implements PictureData {
|
||||||
|
|
||||||
private PackagePart packagePart;
|
private PackagePart packagePart;
|
||||||
|
private String originalId;
|
||||||
|
|
||||||
|
public XSSFPictureData(PackagePart packagePart, String originalId) {
|
||||||
|
this(packagePart);
|
||||||
|
this.originalId = originalId;
|
||||||
|
}
|
||||||
|
|
||||||
public XSSFPictureData(PackagePart packagePart) {
|
public XSSFPictureData(PackagePart packagePart) {
|
||||||
this.packagePart = packagePart;
|
this.packagePart = packagePart;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public String getOriginalId() {
|
||||||
|
return originalId;
|
||||||
|
}
|
||||||
|
|
||||||
|
protected PackagePart getPart() {
|
||||||
|
return packagePart;
|
||||||
|
}
|
||||||
|
|
||||||
|
public void writeTo(OutputStream out) throws IOException {
|
||||||
|
IOUtils.copy(packagePart.getInputStream(), out);
|
||||||
|
}
|
||||||
|
|
||||||
public byte[] getData() {
|
public byte[] getData() {
|
||||||
// TODO Auto-generated method stub
|
try {
|
||||||
return null;
|
return IOUtils.toByteArray(packagePart.getInputStream());
|
||||||
|
} catch(IOException e) {
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public String suggestFileExtension() {
|
public String suggestFileExtension() {
|
||||||
// TODO Auto-generated method stub
|
return packagePart.getPartName().getExtension();
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -38,6 +38,8 @@ import org.apache.poi.ss.usermodel.Sheet;
|
|||||||
import org.apache.poi.ss.util.CellReference;
|
import org.apache.poi.ss.util.CellReference;
|
||||||
import org.apache.poi.ss.util.Region;
|
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.Control;
|
||||||
|
import org.apache.poi.xssf.model.Drawing;
|
||||||
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
|
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
|
||||||
import org.apache.xmlbeans.XmlOptions;
|
import org.apache.xmlbeans.XmlOptions;
|
||||||
import org.openxml4j.opc.PackagePart;
|
import org.openxml4j.opc.PackagePart;
|
||||||
@ -77,6 +79,8 @@ public class XSSFSheet implements Sheet {
|
|||||||
protected XSSFWorkbook workbook;
|
protected XSSFWorkbook workbook;
|
||||||
protected CommentsSource sheetComments;
|
protected CommentsSource sheetComments;
|
||||||
protected CTMergeCells ctMergeCells;
|
protected CTMergeCells ctMergeCells;
|
||||||
|
protected ArrayList<Drawing> drawings;
|
||||||
|
protected ArrayList<Control> controls;
|
||||||
|
|
||||||
public static final short LeftMargin = 0;
|
public static final short LeftMargin = 0;
|
||||||
public static final short RightMargin = 1;
|
public static final short RightMargin = 1;
|
||||||
@ -85,6 +89,22 @@ public class XSSFSheet implements Sheet {
|
|||||||
public static final short HeaderMargin = 4;
|
public static final short HeaderMargin = 4;
|
||||||
public static final short FooterMargin = 5;
|
public static final short FooterMargin = 5;
|
||||||
|
|
||||||
|
public XSSFSheet(CTSheet sheet, CTWorksheet worksheet, XSSFWorkbook workbook, CommentsSource sheetComments, ArrayList<Drawing> drawings, ArrayList<Control> controls) {
|
||||||
|
this(sheet, worksheet, workbook, sheetComments);
|
||||||
|
this.drawings = drawings;
|
||||||
|
this.controls = controls;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Drawing> getDrawings()
|
||||||
|
{
|
||||||
|
return drawings;
|
||||||
|
}
|
||||||
|
|
||||||
|
public ArrayList<Control> getControls()
|
||||||
|
{
|
||||||
|
return controls;
|
||||||
|
}
|
||||||
|
|
||||||
public XSSFSheet(CTSheet sheet, CTWorksheet worksheet, XSSFWorkbook workbook, CommentsSource sheetComments) {
|
public XSSFSheet(CTSheet sheet, CTWorksheet worksheet, XSSFWorkbook workbook, CommentsSource sheetComments) {
|
||||||
this(sheet, worksheet, workbook);
|
this(sheet, worksheet, workbook);
|
||||||
this.sheetComments = sheetComments;
|
this.sheetComments = sheetComments;
|
||||||
|
@ -21,6 +21,7 @@ import java.io.IOException;
|
|||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
import java.lang.reflect.Constructor;
|
import java.lang.reflect.Constructor;
|
||||||
|
import java.util.ArrayList;
|
||||||
import java.util.Iterator;
|
import java.util.Iterator;
|
||||||
import java.util.LinkedList;
|
import java.util.LinkedList;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
@ -46,6 +47,8 @@ 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;
|
||||||
import org.apache.poi.xssf.model.CommentsTable;
|
import org.apache.poi.xssf.model.CommentsTable;
|
||||||
|
import org.apache.poi.xssf.model.Control;
|
||||||
|
import org.apache.poi.xssf.model.Drawing;
|
||||||
import org.apache.poi.xssf.model.SharedStringsTable;
|
import org.apache.poi.xssf.model.SharedStringsTable;
|
||||||
import org.apache.poi.xssf.model.StylesTable;
|
import org.apache.poi.xssf.model.StylesTable;
|
||||||
import org.apache.poi.xssf.model.XSSFModel;
|
import org.apache.poi.xssf.model.XSSFModel;
|
||||||
@ -110,10 +113,16 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
|||||||
"/xl/drawings/drawing#.xml",
|
"/xl/drawings/drawing#.xml",
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
|
public static final XSSFRelation VML_DRAWINGS = new XSSFRelation(
|
||||||
|
"application/vnd.openxmlformats-officedocument.vmlDrawing",
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/vmlDrawing",
|
||||||
|
"/xl/drawings/vmlDrawing#.vml",
|
||||||
|
null
|
||||||
|
);
|
||||||
public static final XSSFRelation IMAGES = new XSSFRelation(
|
public static final XSSFRelation IMAGES = new XSSFRelation(
|
||||||
null, // TODO
|
"image/x-emf", // TODO
|
||||||
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
|
||||||
"/xl/image#.xml",
|
"/xl/media/image#.emf",
|
||||||
null
|
null
|
||||||
);
|
);
|
||||||
public static final XSSFRelation SHEET_COMMENTS = new XSSFRelation(
|
public static final XSSFRelation SHEET_COMMENTS = new XSSFRelation(
|
||||||
@ -140,12 +149,25 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
|||||||
null,
|
null,
|
||||||
BinaryPart.class
|
BinaryPart.class
|
||||||
);
|
);
|
||||||
|
|
||||||
public static final XSSFRelation VBA_MACROS = new XSSFRelation(
|
public static final XSSFRelation VBA_MACROS = new XSSFRelation(
|
||||||
"application/vnd.ms-office.vbaProject",
|
"application/vnd.ms-office.vbaProject",
|
||||||
"http://schemas.microsoft.com/office/2006/relationships/vbaProject",
|
"http://schemas.microsoft.com/office/2006/relationships/vbaProject",
|
||||||
"/xl/vbaProject.bin",
|
"/xl/vbaProject.bin",
|
||||||
BinaryPart.class
|
BinaryPart.class
|
||||||
);
|
);
|
||||||
|
public static final XSSFRelation ACTIVEX_CONTROLS = new XSSFRelation(
|
||||||
|
"application/vnd.ms-office.activeX+xml",
|
||||||
|
"http://schemas.openxmlformats.org/officeDocument/2006/relationships/control",
|
||||||
|
"/xl/activeX/activeX#.xml",
|
||||||
|
null
|
||||||
|
);
|
||||||
|
public static final XSSFRelation ACTIVEX_BINS = new XSSFRelation(
|
||||||
|
"application/vnd.ms-office.activeX",
|
||||||
|
"http://schemas.microsoft.com/office/2006/relationships/activeXControlBinary",
|
||||||
|
"/xl/activeX/activeX#.bin",
|
||||||
|
BinaryPart.class
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
public static class XSSFRelation {
|
public static class XSSFRelation {
|
||||||
@ -335,9 +357,27 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
|||||||
comments = new CommentsTable(commentsPart.getInputStream());
|
comments = new CommentsTable(commentsPart.getInputStream());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the drawings for the sheet, if there are any
|
||||||
|
ArrayList<Drawing> drawings = new ArrayList<Drawing>();
|
||||||
|
for(PackageRelationship rel : part.getRelationshipsByType(VML_DRAWINGS.REL)) {
|
||||||
|
PackagePart drawingPart = getTargetPart(rel);
|
||||||
|
Drawing drawing = new Drawing(drawingPart.getInputStream(), rel.getId());
|
||||||
|
drawing.findChildren(drawingPart);
|
||||||
|
drawings.add(drawing);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Get the activeX controls for the sheet, if there are any
|
||||||
|
ArrayList<Control> controls = new ArrayList<Control>();
|
||||||
|
for(PackageRelationship rel : part.getRelationshipsByType(ACTIVEX_CONTROLS.REL)) {
|
||||||
|
PackagePart controlPart = getTargetPart(rel);
|
||||||
|
Control control = new Control(controlPart.getInputStream(), rel.getId());
|
||||||
|
control.findChildren(controlPart);
|
||||||
|
controls.add(control);
|
||||||
|
}
|
||||||
|
|
||||||
// Now create the sheet
|
// Now create the sheet
|
||||||
WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream());
|
WorksheetDocument worksheetDoc = WorksheetDocument.Factory.parse(part.getInputStream());
|
||||||
XSSFSheet sheet = new XSSFSheet(ctSheet, worksheetDoc.getWorksheet(), this, comments);
|
XSSFSheet sheet = new XSSFSheet(ctSheet, worksheetDoc.getWorksheet(), this, comments, drawings, controls);
|
||||||
this.sheets.add(sheet);
|
this.sheets.add(sheet);
|
||||||
|
|
||||||
// Process external hyperlinks for the sheet,
|
// Process external hyperlinks for the sheet,
|
||||||
@ -839,6 +879,40 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
|||||||
ct.writeTo(out);
|
ct.writeTo(out);
|
||||||
out.close();
|
out.close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// If our sheet has drawings, then write out those
|
||||||
|
if(sheet.getDrawings() != null) {
|
||||||
|
int drawingIndex = 1;
|
||||||
|
for(Drawing drawing : sheet.getDrawings()) {
|
||||||
|
PackagePartName drName = PackagingURIHelper.createPartName(
|
||||||
|
VML_DRAWINGS.getFileName(drawingIndex));
|
||||||
|
part.addRelationship(drName, TargetMode.INTERNAL, VML_DRAWINGS.getRelation(), drawing.getOriginalId());
|
||||||
|
PackagePart drPart = pkg.createPart(drName, VML_DRAWINGS.getContentType());
|
||||||
|
|
||||||
|
drawing.writeChildren(drPart);
|
||||||
|
out = drPart.getOutputStream();
|
||||||
|
drawing.writeTo(out);
|
||||||
|
out.close();
|
||||||
|
drawingIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// If our sheet has controls, then write out those
|
||||||
|
if(sheet.getControls() != null) {
|
||||||
|
int controlIndex = 1;
|
||||||
|
for(Control control : sheet.getControls()) {
|
||||||
|
PackagePartName crName = PackagingURIHelper.createPartName(
|
||||||
|
ACTIVEX_CONTROLS.getFileName(controlIndex));
|
||||||
|
part.addRelationship(crName, TargetMode.INTERNAL, ACTIVEX_CONTROLS.getRelation(), control.getOriginalId());
|
||||||
|
PackagePart crPart = pkg.createPart(crName, ACTIVEX_CONTROLS.getContentType());
|
||||||
|
|
||||||
|
control.writeChildren(crPart);
|
||||||
|
out = crPart.getOutputStream();
|
||||||
|
control.writeTo(out);
|
||||||
|
out.close();
|
||||||
|
controlIndex++;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Write shared strings and styles
|
// Write shared strings and styles
|
||||||
|
@ -55,6 +55,7 @@ public class TestXSSFBugs extends TestCase {
|
|||||||
*/
|
*/
|
||||||
public void test45430() throws Exception {
|
public void test45430() throws Exception {
|
||||||
XSSFWorkbook wb = new XSSFWorkbook(getFilePath("45430.xlsx"));
|
XSSFWorkbook wb = new XSSFWorkbook(getFilePath("45430.xlsx"));
|
||||||
|
assertFalse(wb.isMacroEnabled());
|
||||||
assertEquals(3, wb.getNumberOfNames());
|
assertEquals(3, wb.getNumberOfNames());
|
||||||
|
|
||||||
assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId());
|
assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId());
|
||||||
@ -85,6 +86,7 @@ public class TestXSSFBugs extends TestCase {
|
|||||||
public void test45431() throws Exception {
|
public void test45431() throws Exception {
|
||||||
Package pkg = Package.open(getFilePath("45431.xlsm"));
|
Package pkg = Package.open(getFilePath("45431.xlsm"));
|
||||||
XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
||||||
|
assertTrue(wb.isMacroEnabled());
|
||||||
|
|
||||||
// Check the various macro related bits can be found
|
// Check the various macro related bits can be found
|
||||||
PackagePart vba = pkg.getPart(
|
PackagePart vba = pkg.getPart(
|
||||||
@ -95,6 +97,7 @@ public class TestXSSFBugs extends TestCase {
|
|||||||
// Save and re-open, is still there
|
// Save and re-open, is still there
|
||||||
Package nPkg = saveAndOpen(wb);
|
Package nPkg = saveAndOpen(wb);
|
||||||
XSSFWorkbook nwb = new XSSFWorkbook(nPkg);
|
XSSFWorkbook nwb = new XSSFWorkbook(nPkg);
|
||||||
|
assertTrue(nwb.isMacroEnabled());
|
||||||
vba = nPkg.getPart(
|
vba = nPkg.getPart(
|
||||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
||||||
);
|
);
|
||||||
|
Loading…
Reference in New Issue
Block a user