View | Details | Raw Unified | Return to bug 58036
Collapse All | Expand All

(-)a/src/ooxml/java/org/apache/poi/openxml4j/opc/OPCPackage.java (+27 lines)
Lines 1551-1554 public abstract class OPCPackage implements RelationshipSource, Closeable { Link Here
1551
        }
1551
        }
1552
        return success;
1552
        return success;
1553
    }
1553
    }
1554
1555
    /**
1556
    * Add the specified part, and register its content type with the content
1557
    * type manager.
1558
    *
1559
    * @param part
1560
    *            The part to add.
1561
    */
1562
    public void registerPartAndContentType(PackagePart part) {
1563
        addPackagePart(part);
1564
        this.contentTypeManager.addContentType(part.getPartName(), part.getContentType());
1565
        this.isDirty = true;
1566
    }
1567
1568
    /**
1569
     * Remove the specified part, and clear its content type from the content
1570
     * type manager.
1571
     *
1572
     * @param partName
1573
     *            The part name of the part to remove.
1574
     */
1575
    public void unregisterPartAndContentType(PackagePartName partName) {
1576
        removePart(partName);
1577
        this.contentTypeManager.removeContentType(partName);
1578
        this.isDirty = true;
1579
    }
1580
1554
}
1581
}
(-)a/src/ooxml/java/org/apache/poi/openxml4j/opc/PackagePart.java (-5 / +8 lines)
Lines 601-611 public abstract class PackagePart implements RelationshipSource, Comparable<Pack Link Here
601
	 */
601
	 */
602
	public void setContentType(String contentType)
602
	public void setContentType(String contentType)
603
			throws InvalidFormatException {
603
			throws InvalidFormatException {
604
		if (_container == null)
604
		if (_container == null) {
605
			this._contentType = new ContentType(contentType);
605
			_contentType = new ContentType(contentType);
606
		else
606
		}
607
			throw new InvalidOperationException(
607
		else {
608
					"You can't change the content type of a part.");
608
		    _container.unregisterPartAndContentType(_partName);
609
		    _contentType = new ContentType(contentType);
610
		    _container.registerPartAndContentType(this);
611
		}
609
	}
612
	}
610
613
611
	public OPCPackage getPackage() {
614
	public OPCPackage getPackage() {
(-)a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRelation.java (-1 / +1 lines)
Lines 281-287 public final class XSSFRelation extends POIXMLRelation { Link Here
281
        "application/vnd.ms-office.vbaProject",
281
        "application/vnd.ms-office.vbaProject",
282
        "http://schemas.microsoft.com/office/2006/relationships/vbaProject",
282
        "http://schemas.microsoft.com/office/2006/relationships/vbaProject",
283
        "/xl/vbaProject.bin",
283
        "/xl/vbaProject.bin",
284
        null
284
        XSSFVBAPart.class
285
    );
285
    );
286
286
287
    public static final XSSFRelation ACTIVEX_CONTROLS = new XSSFRelation(
287
    public static final XSSFRelation ACTIVEX_CONTROLS = new XSSFRelation(
(-)a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFVBAPart.java (+52 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.xssf.usermodel;
19
20
import org.apache.poi.POIXMLDocumentPart;
21
import org.apache.poi.openxml4j.opc.PackagePart;
22
import org.apache.poi.openxml4j.opc.PackageRelationship;
23
24
public class XSSFVBAPart extends POIXMLDocumentPart {
25
26
    /**
27
     * Create a new XSSFVBAPart node
28
     */
29
    protected XSSFVBAPart() {
30
        super();
31
    }
32
33
    /**
34
     * Construct XSSFVBAPart from a package part
35
     *
36
     * @param part the package part holding the VBA data,
37
     * @param rel  the package relationship holding this part
38
     */
39
    protected XSSFVBAPart(PackagePart part, PackageRelationship rel) {
40
        super(part, rel);
41
    }
42
43
    /**
44
     * Like *PictureData, VBA objects store the actual content in the part
45
     * directly without keeping a copy like all others therefore we need to
46
     * handle them differently.
47
     */
48
    protected void prepareForCommit() {
49
        // do not clear the part here
50
    }
51
52
}
(-)a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java (-3 / +74 lines)
Lines 215-221 public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X Link Here
215
     * Create a new SpreadsheetML workbook.
215
     * Create a new SpreadsheetML workbook.
216
     */
216
     */
217
    public XSSFWorkbook() {
217
    public XSSFWorkbook() {
218
        super(newPackage());
218
        this(XSSFWorkbookType.XLSX);
219
    }
220
221
    /**
222
     * Create a new SpreadsheetML workbook.
223
     * @param workbookType The type of workbook to make (.xlsx or .xlsm).
224
     */
225
    public XSSFWorkbook(XSSFWorkbookType workbookType) {
226
        super(newPackage(workbookType));
219
        onWorkbookCreate();
227
        onWorkbookCreate();
220
    }
228
    }
221
229
Lines 429-435 public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X Link Here
429
    /**
437
    /**
430
     * Create a new SpreadsheetML package and setup the default minimal content
438
     * Create a new SpreadsheetML package and setup the default minimal content
431
     */
439
     */
432
    protected static OPCPackage newPackage() {
440
    protected static OPCPackage newPackage(XSSFWorkbookType workbookType) {
433
        try {
441
        try {
434
            OPCPackage pkg = OPCPackage.create(new ByteArrayOutputStream());
442
            OPCPackage pkg = OPCPackage.create(new ByteArrayOutputStream());
435
            // Main part
443
            // Main part
Lines 437-443 public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X Link Here
437
            // Create main part relationship
445
            // Create main part relationship
438
            pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT);
446
            pkg.addRelationship(corePartName, TargetMode.INTERNAL, PackageRelationshipTypes.CORE_DOCUMENT);
439
            // Create main document part
447
            // Create main document part
440
            pkg.createPart(corePartName, XSSFRelation.WORKBOOK.getContentType());
448
            pkg.createPart(corePartName, workbookType.getContentType());
441
449
442
            pkg.getPackageProperties().setCreatorProperty(DOCUMENT_CREATOR);
450
            pkg.getPackageProperties().setCreatorProperty(DOCUMENT_CREATOR);
443
451
Lines 2044-2047 public class XSSFWorkbook extends POIXMLDocument implements Workbook, Iterable<X Link Here
2044
    protected void setPivotTables(List<XSSFPivotTable> pivotTables) {
2052
    protected void setPivotTables(List<XSSFPivotTable> pivotTables) {
2045
        this.pivotTables = pivotTables;
2053
        this.pivotTables = pivotTables;
2046
    }
2054
    }
2055
2056
    public XSSFWorkbookType getWorkbookType() {
2057
        return isMacroEnabled() ? XSSFWorkbookType.XLSM : XSSFWorkbookType.XLSX;
2058
    }
2059
2060
    /**
2061
     * Sets whether the workbook will be an .xlsx or .xlsm (macro-enabled) file.
2062
     */
2063
    public void setWorkbookType(XSSFWorkbookType type) {
2064
        try {
2065
            getPackagePart().setContentType(type.getContentType());
2066
        } catch (InvalidFormatException e) {
2067
            throw new POIXMLException(e);
2068
        }
2069
    }
2070
2071
    /**
2072
     * Adds a vbaProject.bin file to the workbook.  This will change the workbook
2073
     * type if necessary.
2074
     *
2075
     * @throws IOException
2076
     */
2077
    public void setVBAProject(InputStream vbaProjectStream) throws IOException {
2078
        if (!isMacroEnabled()) {
2079
            setWorkbookType(XSSFWorkbookType.XLSM);
2080
        }
2081
2082
        PackagePartName ppName;
2083
        try {
2084
            ppName = PackagingURIHelper.createPartName(XSSFRelation.VBA_MACROS.getDefaultFileName());
2085
        } catch (InvalidFormatException e) {
2086
            throw new POIXMLException(e);
2087
        }
2088
        OPCPackage opc = getPackage();
2089
        OutputStream outputStream;
2090
        if (!opc.containPart(ppName)) {
2091
            POIXMLDocumentPart relationship = createRelationship(XSSFRelation.VBA_MACROS, XSSFFactory.getInstance());
2092
            outputStream = relationship.getPackagePart().getOutputStream();
2093
        } else {
2094
            PackagePart part = opc.getPart(ppName);
2095
            outputStream = part.getOutputStream();
2096
        }
2097
        try {
2098
            IOUtils.copy(vbaProjectStream, outputStream);
2099
        } finally {
2100
            IOUtils.closeQuietly(outputStream);
2101
        }
2102
    }
2103
2104
    /**
2105
     * Adds a vbaProject.bin file taken from another, given workbook to this one.
2106
     * @throws IOException
2107
     * @throws InvalidFormatException
2108
     */
2109
    public void setVBAProject(XSSFWorkbook macroWorkbook) throws IOException, InvalidFormatException {
2110
        if (!macroWorkbook.isMacroEnabled()) {
2111
            return;
2112
        }
2113
        InputStream vbaProjectStream = XSSFRelation.VBA_MACROS.getContents(macroWorkbook.getCorePart());
2114
        if (vbaProjectStream != null) {
2115
            setVBAProject(vbaProjectStream);
2116
        }
2117
    }
2047
}
2118
}
(-)a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbookType.java (+45 lines)
Line 0 Link Here
1
/* ====================================================================
2
   Licensed to the Apache Software Foundation (ASF) under one or more
3
   contributor license agreements.  See the NOTICE file distributed with
4
   this work for additional information regarding copyright ownership.
5
   The ASF licenses this file to You under the Apache License, Version 2.0
6
   (the "License"); you may not use this file except in compliance with
7
   the License.  You may obtain a copy of the License at
8
9
       http://www.apache.org/licenses/LICENSE-2.0
10
11
   Unless required by applicable law or agreed to in writing, software
12
   distributed under the License is distributed on an "AS IS" BASIS,
13
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
   See the License for the specific language governing permissions and
15
   limitations under the License.
16
==================================================================== */
17
18
package org.apache.poi.xssf.usermodel;
19
20
21
/**
22
 * Represents the two different kinds of XML-based OOXML document.
23
 */
24
public enum XSSFWorkbookType {
25
26
    XLSX(XSSFRelation.WORKBOOK.getContentType(), "xlsx"),
27
    XLSM(XSSFRelation.MACROS_WORKBOOK.getContentType(), "xlsm");
28
29
    private final String _contentType;
30
    private final String _extension;
31
32
    private XSSFWorkbookType(String contentType, String extension) {
33
        _contentType = contentType;
34
        _extension = extension;
35
    }
36
37
    public String getContentType() {
38
        return _contentType;
39
    }
40
41
    public String getExtension() {
42
        return _extension;
43
    }
44
45
}
(-)a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFWorkbook.java (-2 / +54 lines)
Lines 17-22 Link Here
17
17
18
package org.apache.poi.xssf.usermodel;
18
package org.apache.poi.xssf.usermodel;
19
19
20
import static org.junit.Assert.assertArrayEquals;
20
import static org.junit.Assert.assertEquals;
21
import static org.junit.Assert.assertEquals;
21
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertFalse;
22
import static org.junit.Assert.assertNotNull;
23
import static org.junit.Assert.assertNotNull;
Lines 25-30 import static org.junit.Assert.assertSame; Link Here
25
import static org.junit.Assert.assertTrue;
26
import static org.junit.Assert.assertTrue;
26
import static org.junit.Assert.fail;
27
import static org.junit.Assert.fail;
27
28
29
import java.io.ByteArrayInputStream;
28
import java.io.ByteArrayOutputStream;
30
import java.io.ByteArrayOutputStream;
29
import java.io.File;
31
import java.io.File;
30
import java.io.FileOutputStream;
32
import java.io.FileOutputStream;
Lines 39-48 import org.apache.poi.openxml4j.opc.ContentTypes; Link Here
39
import org.apache.poi.openxml4j.opc.OPCPackage;
41
import org.apache.poi.openxml4j.opc.OPCPackage;
40
import org.apache.poi.openxml4j.opc.PackagePart;
42
import org.apache.poi.openxml4j.opc.PackagePart;
41
import org.apache.poi.openxml4j.opc.PackagePartName;
43
import org.apache.poi.openxml4j.opc.PackagePartName;
44
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
42
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
45
import org.apache.poi.openxml4j.opc.PackagingURIHelper;
43
import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart;
46
import org.apache.poi.openxml4j.opc.internal.MemoryPackagePart;
44
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
47
import org.apache.poi.openxml4j.opc.internal.PackagePropertiesPart;
45
46
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
48
import org.apache.poi.ss.usermodel.BaseTestWorkbook;
47
import org.apache.poi.ss.usermodel.Cell;
49
import org.apache.poi.ss.usermodel.Cell;
48
import org.apache.poi.ss.usermodel.CellStyle;
50
import org.apache.poi.ss.usermodel.CellStyle;
Lines 60-65 import org.apache.poi.util.TempFile; Link Here
60
import org.apache.poi.xssf.XSSFITestDataProvider;
62
import org.apache.poi.xssf.XSSFITestDataProvider;
61
import org.apache.poi.xssf.XSSFTestDataSamples;
63
import org.apache.poi.xssf.XSSFTestDataSamples;
62
import org.apache.poi.xssf.model.StylesTable;
64
import org.apache.poi.xssf.model.StylesTable;
65
import org.bouncycastle.util.Arrays;
63
import org.junit.Test;
66
import org.junit.Test;
64
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCalcPr;
67
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCalcPr;
65
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCache;
68
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCache;
Lines 869-872 public final class TestXSSFWorkbook extends BaseTestWorkbook { Link Here
869
            wb.close();
872
            wb.close();
870
        }
873
        }
871
    }
874
    }
875
876
    /**
877
     * Tests that we can save a workbook with macros and reload it.
878
     */
879
    @Test
880
    public void testSetVBAProject() throws Exception {
881
        XSSFWorkbook workbook = null;
882
        OutputStream out = null;
883
        File file;
884
        final byte[] allBytes = new byte[256];
885
        for (int i = 0; i < 256; i++) {
886
            allBytes[i] = (byte) (i - 128);
887
        }
888
        try {
889
            workbook = new XSSFWorkbook();
890
            workbook.createSheet();
891
            workbook.setVBAProject(new ByteArrayInputStream(allBytes));
892
            file = TempFile.createTempFile("poi-", ".xlsm");
893
            out = new FileOutputStream(file);
894
            workbook.write(out);
895
        }
896
        finally {
897
            IOUtils.closeQuietly(out);
898
            IOUtils.closeQuietly(workbook);
899
        }
900
901
        try {
902
            // Check the package contains what we'd expect it to
903
            OPCPackage pkg = OPCPackage.open(file.toString());
904
            PackagePart wbPart = pkg.getPart(PackagingURIHelper.createPartName("/xl/workbook.xml"));
905
            assertTrue(wbPart.hasRelationships());
906
            final PackageRelationshipCollection relationships = wbPart.getRelationships().getRelationships(XSSFRelation.VBA_MACROS.getRelation());
907
            assertEquals(1, relationships.size());
908
            assertEquals(XSSFRelation.VBA_MACROS.getDefaultFileName(), relationships.getRelationship(0).getTargetURI().toString());
909
            PackagePart vbaPart = pkg.getPart(PackagingURIHelper.createPartName(XSSFRelation.VBA_MACROS.getDefaultFileName()));
910
            assertNotNull(vbaPart);
911
            assertFalse(vbaPart.isRelationshipPart());
912
            assertEquals(XSSFRelation.VBA_MACROS.getContentType(), vbaPart.getContentType());
913
            final byte[] fromFile = IOUtils.toByteArray(vbaPart.getInputStream());
914
            assertArrayEquals(allBytes, fromFile);
915
916
            // Load back the XSSFWorkbook just to check nothing explodes
917
            workbook = new XSSFWorkbook(pkg);
918
            assertEquals(1, workbook.getNumberOfSheets());
919
            assertEquals(XSSFWorkbookType.XLSM, workbook.getWorkbookType());
920
        }
921
        finally {
922
            IOUtils.closeQuietly(workbook);
923
        }
924
    }
872
}
925
}
873
- 

Return to bug 58036