Partial support for .xlsm files (bug #45431), but still not quite there as they seem to have some hidden reference we don't know about to update
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@677990 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5d5982fb0f
commit
2591008752
67
src/ooxml/java/org/apache/poi/xssf/model/BinaryPart.java
Normal file
67
src/ooxml/java/org/apache/poi/xssf/model/BinaryPart.java
Normal file
@ -0,0 +1,67 @@
|
||||
/* ====================================================================
|
||||
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.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
/**
|
||||
* An implementation of XSSFModel for binary parts of
|
||||
* the file, eg images or vba macros
|
||||
*/
|
||||
public class BinaryPart implements XSSFModel {
|
||||
private byte[] data;
|
||||
|
||||
public BinaryPart(InputStream in) throws IOException {
|
||||
readFrom(in);
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetch the contents of the binary part
|
||||
*/
|
||||
public byte[] getContents() {
|
||||
return data;
|
||||
}
|
||||
/**
|
||||
* Changes the contents of the binary part
|
||||
*/
|
||||
public void setContents(byte[] data) {
|
||||
this.data = data;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reads the contents of the binary part in.
|
||||
*/
|
||||
public void readFrom(InputStream is) throws IOException {
|
||||
int read = 0;
|
||||
byte[] buffer = new byte[4096];
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
|
||||
while( (read = is.read(buffer)) != -1 ) {
|
||||
if(read > 0) {
|
||||
baos.write(buffer, 0, read);
|
||||
}
|
||||
}
|
||||
data = baos.toByteArray();
|
||||
}
|
||||
|
||||
public void writeTo(OutputStream out) throws IOException {
|
||||
out.write(data);
|
||||
}
|
||||
}
|
@ -20,6 +20,15 @@ import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook.XSSFRelation;
|
||||
|
||||
/**
|
||||
* Common interface for XSSF models, which deal with
|
||||
* parts of the xssf file.
|
||||
* These should also implement a constructor of
|
||||
* (InputStream is), so they can be used with
|
||||
* {@link XSSFRelation}
|
||||
*/
|
||||
public interface XSSFModel {
|
||||
/** Read from the given InputStream */
|
||||
public void readFrom(InputStream is) throws IOException;
|
||||
|
@ -44,6 +44,7 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy;
|
||||
import org.apache.poi.ss.util.SheetReferences;
|
||||
import org.apache.poi.util.POILogFactory;
|
||||
import org.apache.poi.util.POILogger;
|
||||
import org.apache.poi.xssf.model.BinaryPart;
|
||||
import org.apache.poi.xssf.model.CommentsTable;
|
||||
import org.apache.poi.xssf.model.SharedStringsTable;
|
||||
import org.apache.poi.xssf.model.StylesTable;
|
||||
@ -125,14 +126,19 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||
null,
|
||||
OLE_OBJECT_REL_TYPE,
|
||||
null,
|
||||
null
|
||||
BinaryPart.class
|
||||
);
|
||||
|
||||
public static final XSSFRelation PACKEMBEDDINGS = new XSSFRelation(
|
||||
null,
|
||||
PACK_OBJECT_REL_TYPE,
|
||||
null,
|
||||
null
|
||||
BinaryPart.class
|
||||
);
|
||||
public static final XSSFRelation VBA_MACROS = new XSSFRelation(
|
||||
"application/vnd.ms-office.vbaProject",
|
||||
"http://schemas.microsoft.com/office/2006/relationships/vbaProject",
|
||||
"/xl/vbaProject.bin",
|
||||
BinaryPart.class
|
||||
);
|
||||
|
||||
|
||||
@ -151,6 +157,26 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||
public String getRelation() { return REL; }
|
||||
public String getDefaultFileName() { return DEFAULT_NAME; }
|
||||
|
||||
/**
|
||||
* Does one of these exist for the given core
|
||||
* package part?
|
||||
*/
|
||||
public boolean exists(PackagePart corePart) throws IOException, InvalidFormatException {
|
||||
if(corePart == null) {
|
||||
// new file, can't exist
|
||||
return false;
|
||||
}
|
||||
|
||||
PackageRelationshipCollection prc =
|
||||
corePart.getRelationshipsByType(REL);
|
||||
Iterator<PackageRelationship> it = prc.iterator();
|
||||
if(it.hasNext()) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the filename for the nth one of these,
|
||||
* eg /xl/comments4.xml
|
||||
@ -814,6 +840,17 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
|
||||
}
|
||||
}
|
||||
|
||||
// VBA Macros
|
||||
if(VBA_MACROS.exists( getCorePart() )) {
|
||||
// Copy over
|
||||
try {
|
||||
XSSFModel vba = VBA_MACROS.load(getCorePart());
|
||||
VBA_MACROS.save(vba, corePart);
|
||||
} catch(Exception e) {
|
||||
throw new RuntimeException("Unable to copy vba macros over", e);
|
||||
}
|
||||
}
|
||||
|
||||
// Now we can write out the main Workbook, with
|
||||
// the correct references to the other parts
|
||||
out = corePart.getOutputStream();
|
||||
|
@ -17,7 +17,14 @@
|
||||
|
||||
package org.apache.poi.xssf.usermodel;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileOutputStream;
|
||||
|
||||
import org.openxml4j.opc.Package;
|
||||
import org.openxml4j.opc.PackagePart;
|
||||
import org.openxml4j.opc.PackagingURIHelper;
|
||||
|
||||
import junit.framework.TestCase;
|
||||
|
||||
@ -32,6 +39,16 @@ public class TestXSSFBugs extends TestCase {
|
||||
return xml.toString();
|
||||
}
|
||||
|
||||
private Package saveAndOpen(XSSFWorkbook wb) throws Exception {
|
||||
ByteArrayOutputStream baos = new ByteArrayOutputStream();
|
||||
wb.write(baos);
|
||||
ByteArrayInputStream inp = new ByteArrayInputStream(
|
||||
baos.toByteArray()
|
||||
);
|
||||
Package pkg = Package.open(inp);
|
||||
return pkg;
|
||||
}
|
||||
|
||||
/**
|
||||
* Named ranges had the right reference, but
|
||||
* the wrong sheet name
|
||||
@ -55,4 +72,38 @@ public class TestXSSFBugs extends TestCase {
|
||||
assertEquals("SheetC!$A$1", wb.getNameAt(2).getReference());
|
||||
assertEquals("SheetC", wb.getNameAt(2).getSheetName());
|
||||
}
|
||||
|
||||
/**
|
||||
* We should carry vba macros over after save
|
||||
*/
|
||||
public void test45431() throws Exception {
|
||||
Package pkg = Package.open(getFilePath("45431.xlsm"));
|
||||
XSSFWorkbook wb = new XSSFWorkbook(pkg);
|
||||
|
||||
PackagePart vba = pkg.getPart(
|
||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
||||
);
|
||||
assertNotNull(vba);
|
||||
|
||||
// Save and re-open, is still there
|
||||
Package nPkg = saveAndOpen(wb);
|
||||
XSSFWorkbook nwb = new XSSFWorkbook(nPkg);
|
||||
vba = nPkg.getPart(
|
||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
||||
);
|
||||
assertNotNull(vba);
|
||||
|
||||
// And again, just to be sure
|
||||
nPkg = saveAndOpen(nwb);
|
||||
nwb = new XSSFWorkbook(nPkg);
|
||||
vba = nPkg.getPart(
|
||||
PackagingURIHelper.createPartName("/xl/vbaProject.bin")
|
||||
);
|
||||
assertNotNull(vba);
|
||||
|
||||
// For testing with excel
|
||||
// FileOutputStream fout = new FileOutputStream("/tmp/foo.xlsm");
|
||||
// nwb.write(fout);
|
||||
// fout.close();
|
||||
}
|
||||
}
|
||||
|
BIN
src/testcases/org/apache/poi/hssf/data/45431.xlsm
Normal file
BIN
src/testcases/org/apache/poi/hssf/data/45431.xlsm
Normal file
Binary file not shown.
Loading…
Reference in New Issue
Block a user