}
return success;
}
+
+ /**
+ * Add the specified part, and register its content type with the content
+ * type manager.
+ *
+ * @param part
+ * The part to add.
+ */
+ public void registerPartAndContentType(PackagePart part) {
+ addPackagePart(part);
+ this.contentTypeManager.addContentType(part.getPartName(), part.getContentType());
+ this.isDirty = true;
+ }
+
+ /**
+ * Remove the specified part, and clear its content type from the content
+ * type manager.
+ *
+ * @param partName
+ * The part name of the part to remove.
+ */
+ public void unregisterPartAndContentType(PackagePartName partName) {
+ removePart(partName);
+ this.contentTypeManager.removeContentType(partName);
+ this.isDirty = true;
+ }
+
}
*/
public void setContentType(String contentType)
throws InvalidFormatException {
- if (_container == null)
- this._contentType = new ContentType(contentType);
- else
- throw new InvalidOperationException(
- "You can't change the content type of a part.");
+ if (_container == null) {
+ _contentType = new ContentType(contentType);
+ }
+ else {
+ _container.unregisterPartAndContentType(_partName);
+ _contentType = new ContentType(contentType);
+ _container.registerPartAndContentType(this);
+ }
}
public OPCPackage getPackage() {
"application/vnd.ms-office.vbaProject",
"http://schemas.microsoft.com/office/2006/relationships/vbaProject",
"/xl/vbaProject.bin",
- null
+ XSSFVBAPart.class
);
public static final XSSFRelation ACTIVEX_CONTROLS = new XSSFRelation(
--- /dev/null
+/* ====================================================================
+ 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.openxml4j.opc.PackagePart;
+import org.apache.poi.openxml4j.opc.PackageRelationship;
+
+public class XSSFVBAPart extends POIXMLDocumentPart {
+
+ /**
+ * Create a new XSSFVBAPart node
+ */
+ protected XSSFVBAPart() {
+ super();
+ }
+
+ /**
+ * Construct XSSFVBAPart from a package part
+ *
+ * @param part the package part holding the VBA data,
+ * @param rel the package relationship holding this part
+ */
+ protected XSSFVBAPart(PackagePart part, PackageRelationship rel) {
+ super(part, rel);
+ }
+
+ /**
+ * Like *PictureData, VBA objects store the actual content in the part
+ * directly without keeping a copy like all others therefore we need to
+ * handle them differently.
+ */
+ protected void prepareForCommit() {
+ // do not clear the part here
+ }
+
+}
* Create a new SpreadsheetML workbook.
*/
public XSSFWorkbook() {
- super(newPackage());
+ this(XSSFWorkbookType.XLSX);
+ }
+
+ /**
+ * Create a new SpreadsheetML workbook.
+ * @param workbookType The type of workbook to make (.xlsx or .xlsm).
+ */
+ public XSSFWorkbook(XSSFWorkbookType workbookType) {
+ super(newPackage(workbookType));
onWorkbookCreate();
}
/**
* Create a new SpreadsheetML package and setup the default minimal content
*/
- protected static OPCPackage newPackage() {
+ protected static OPCPackage newPackage(XSSFWorkbookType workbookType) {
try {
OPCPackage pkg = OPCPackage.create(new ByteArrayOutputStream());
// Main part
// Create main part relationship
pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT);
// Create main document part
- pkg.createPart(corePartName, XSSFRelation.WORKBOOK.getContentType());
+ pkg.createPart(corePartName, workbookType.getContentType());
pkg.getPackageProperties().setCreatorProperty(DOCUMENT_CREATOR);
protected void setPivotTables(List<XSSFPivotTable> pivotTables) {
this.pivotTables = pivotTables;
}
+
+ public XSSFWorkbookType getWorkbookType() {
+ return isMacroEnabled() ? XSSFWorkbookType.XLSM : XSSFWorkbookType.XLSX;
+ }
+
+ /**
+ * Sets whether the workbook will be an .xlsx or .xlsm (macro-enabled) file.
+ */
+ public void setWorkbookType(XSSFWorkbookType type) {
+ try {
+ getPackagePart().setContentType(type.getContentType());
+ } catch (InvalidFormatException e) {
+ throw new POIXMLException(e);
+ }
+ }
+
+ /**
+ * Adds a vbaProject.bin file to the workbook. This will change the workbook
+ * type if necessary.
+ *
+ * @throws IOException
+ */
+ public void setVBAProject(InputStream vbaProjectStream) throws IOException {
+ if (!isMacroEnabled()) {
+ setWorkbookType(XSSFWorkbookType.XLSM);
+ }
+
+ PackagePartName ppName;
+ try {
+ ppName = PackagingURIHelper.createPartName(XSSFRelation.VBA_MACROS.getDefaultFileName());
+ } catch (InvalidFormatException e) {
+ throw new POIXMLException(e);
+ }
+ OPCPackage opc = getPackage();
+ OutputStream outputStream;
+ if (!opc.containPart(ppName)) {
+ POIXMLDocumentPart relationship = createRelationship(XSSFRelation.VBA_MACROS, XSSFFactory.getInstance());
+ outputStream = relationship.getPackagePart().getOutputStream();
+ } else {
+ PackagePart part = opc.getPart(ppName);
+ outputStream = part.getOutputStream();
+ }
+ try {
+ IOUtils.copy(vbaProjectStream, outputStream);
+ } finally {
+ IOUtils.closeQuietly(outputStream);
+ }
+ }
+
+ /**
+ * Adds a vbaProject.bin file taken from another, given workbook to this one.
+ * @throws IOException
+ * @throws InvalidFormatException
+ */
+ public void setVBAProject(XSSFWorkbook macroWorkbook) throws IOException, InvalidFormatException {
+ if (!macroWorkbook.isMacroEnabled()) {
+ return;
+ }
+ InputStream vbaProjectStream = XSSFRelation.VBA_MACROS.getContents(macroWorkbook.getCorePart());
+ if (vbaProjectStream != null) {
+ setVBAProject(vbaProjectStream);
+ }
+ }
}
--- /dev/null
+/* ====================================================================
+ 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;
+
+
+/**
+ * Represents the two different kinds of XML-based OOXML document.
+ */
+public enum XSSFWorkbookType {
+
+ XLSX(XSSFRelation.WORKBOOK.getContentType(), "xlsx"),
+ XLSM(XSSFRelation.MACROS_WORKBOOK.getContentType(), "xlsm");
+
+ private final String _contentType;
+ private final String _extension;
+
+ private XSSFWorkbookType(String contentType, String extension) {
+ _contentType = contentType;
+ _extension = extension;
+ }
+
+ public String getContentType() {
+ return _contentType;
+ }
+
+ public String getExtension() {
+ return _extension;
+ }
+
+}
package org.apache.poi.xssf.usermodel;
+import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertFalse;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
+import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileOutputStream;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.openxml4j.opc.PackagePart;
import org.apache.poi.openxml4j.opc.PackagePartName;
+import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart;
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
-
+import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
import org.apache.poi.ss.usermodel.Cell;
import org.apache.poi.ss.usermodel.CellStyle;
*/
@Test
public void saveLoadNew() throws Exception {
- XSSFWorkbook workbook = new XSSFWorkbook();
+ @SuppressWarnings("resource")
+ XSSFWorkbook workbook = new XSSFWorkbook();
//check that the default date system is set to 1900
CTWorkbookPr pr = workbook.getCTWorkbook().getWorkbookPr();
// Links to the three sheets, shared strings and styles
assertTrue(wbPart.hasRelationships());
assertEquals(5, wbPart.getRelationships().size());
-
+ workbook.close();
+
// Load back the XSSFWorkbook
workbook = new XSSFWorkbook(pkg);
assertEquals(3, workbook.getNumberOfSheets());
Cell cell9 = row3.createCell(2);
cell9.setCellValue("Bepa");
- AreaReference source = new AreaReference("A1:B2");
+ AreaReference source = new AreaReference("A1:B2", SpreadsheetVersion.EXCEL2007);
sheet.createPivotTable(source, new CellReference("H5"));
}
wb.close();
}
}
+
+ /**
+ * Tests that we can save a workbook with macros and reload it.
+ */
+ @Test
+ public void testSetVBAProject() throws Exception {
+ XSSFWorkbook workbook = null;
+ OutputStream out = null;
+ File file;
+ final byte[] allBytes = new byte[256];
+ for (int i = 0; i < 256; i++) {
+ allBytes[i] = (byte) (i - 128);
+ }
+ try {
+ workbook = new XSSFWorkbook();
+ workbook.createSheet();
+ workbook.setVBAProject(new ByteArrayInputStream(allBytes));
+ file = TempFile.createTempFile("poi-", ".xlsm");
+ out = new FileOutputStream(file);
+ workbook.write(out);
+ }
+ finally {
+ IOUtils.closeQuietly(out);
+ IOUtils.closeQuietly(workbook);
+ }
+
+ try {
+ // Check the package contains what we'd expect it to
+ OPCPackage pkg = OPCPackage.open(file.toString());
+ PackagePart wbPart = pkg.getPart(PackagingURIHelper.createPartName("/xl/workbook.xml"));
+ assertTrue(wbPart.hasRelationships());
+ final PackageRelationshipCollection relationships = wbPart.getRelationships().getRelationships(XSSFRelation.VBA_MACROS.getRelation());
+ assertEquals(1, relationships.size());
+ assertEquals(XSSFRelation.VBA_MACROS.getDefaultFileName(), relationships.getRelationship(0).getTargetURI().toString());
+ PackagePart vbaPart = pkg.getPart(PackagingURIHelper.createPartName(XSSFRelation.VBA_MACROS.getDefaultFileName()));
+ assertNotNull(vbaPart);
+ assertFalse(vbaPart.isRelationshipPart());
+ assertEquals(XSSFRelation.VBA_MACROS.getContentType(), vbaPart.getContentType());
+ final byte[] fromFile = IOUtils.toByteArray(vbaPart.getInputStream());
+ assertArrayEquals(allBytes, fromFile);
+
+ // Load back the XSSFWorkbook just to check nothing explodes
+ workbook = new XSSFWorkbook(pkg);
+ assertEquals(1, workbook.getNumberOfSheets());
+ assertEquals(XSSFWorkbookType.XLSM, workbook.getWorkbookType());
+ }
+ finally {
+ IOUtils.closeQuietly(workbook);
+ }
+ }
}