]> source.dussan.org Git - poi.git/commitdiff
More work on bug #45431 - Support for .xlsm files, sufficient for simple files to...
authorNick Burch <nick@apache.org>
Tue, 29 Jul 2008 23:03:25 +0000 (23:03 +0000)
committerNick Burch <nick@apache.org>
Tue, 29 Jul 2008 23:03:25 +0000 (23:03 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@680871 13f79535-47bb-0310-9956-ffa450edef68

12 files changed:
src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/util/IOUtils.java
src/ooxml/java/org/apache/poi/POIXMLDocument.java
src/ooxml/java/org/apache/poi/xssf/model/Control.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/model/Drawing.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/model/XSSFChildContainingModel.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFActiveXData.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPictureData.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java

index 12bce0ccf5321546e48399c3ad134df5676ee1ae..d7f6d17324b256735d9f651eda1c57d66f1a8d36 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <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">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>
index 3b6644db96572c851a66cf2d003d68cc22a1d8f7..208799a0048ed360ed809defc9f541dccc14e3e6 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <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">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>
index c3aa8695e25c45f3f2a83e9da6a34f7740a2cd1c..2e60e9bdbee436eea0d0640cb49c6ea03d1434c5 100644 (file)
@@ -22,6 +22,7 @@ package org.apache.poi.util;
 import java.io.ByteArrayOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
+import java.io.OutputStream;
 
 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);
+                       }
+               }
+       }
 }
\ No newline at end of file
index 3fb718f6ce97216b455cdae29646bfe67ea2cada..1f61a5cdcf86c1516e4cac101dfa85da03991fd8 100644 (file)
@@ -117,8 +117,19 @@ public abstract class POIXMLDocument {
      * @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());
-        PackagePart part = getPackage().getPart(relName);
+        PackagePart part = pkg.getPart(relName);
         if (part == null) {
             throw new IllegalArgumentException("No part found for relationship " + rel);
         }
diff --git a/src/ooxml/java/org/apache/poi/xssf/model/Control.java b/src/ooxml/java/org/apache/poi/xssf/model/Control.java
new file mode 100644 (file)
index 0000000..55f4872
--- /dev/null
@@ -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);
+       }       
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xssf/model/Drawing.java b/src/ooxml/java/org/apache/poi/xssf/model/Drawing.java
new file mode 100644 (file)
index 0000000..41123e0
--- /dev/null
@@ -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);
+       }       
+}
\ No newline at end of file
diff --git a/src/ooxml/java/org/apache/poi/xssf/model/XSSFChildContainingModel.java b/src/ooxml/java/org/apache/poi/xssf/model/XSSFChildContainingModel.java
new file mode 100644 (file)
index 0000000..eedfcc0
--- /dev/null
@@ -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;
+}
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFActiveXData.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFActiveXData.java
new file mode 100644 (file)
index 0000000..84ef049
--- /dev/null
@@ -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();
+    }
+}
index 91ed5f8658c2b54f9b253c6264e87720f45615f5..eb153ce09dbeb23b73a5f35c13f3356ecfd2f1a2 100644 (file)
 
 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;
 
-
+/**
+ * Raw picture data, normally attached to a 
+ *  vmlDrawing
+ */
 public class XSSFPictureData implements PictureData {
-
     private PackagePart packagePart;
+    private String originalId;
+
+    public XSSFPictureData(PackagePart packagePart, String originalId) {
+        this(packagePart);
+        this.originalId = originalId;
+    }
     
     public XSSFPictureData(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() {
-        // TODO Auto-generated method stub
-        return null;
+       try {
+               return IOUtils.toByteArray(packagePart.getInputStream());
+       } catch(IOException e) {
+               throw new RuntimeException(e);
+       }
     }
 
     public String suggestFileExtension() {
-        // TODO Auto-generated method stub
-        return null;
+       return packagePart.getPartName().getExtension();
     }
-
 }
index b4378cdd4242c09495eb429a48121dda4c6dada9..18c0e8f16129bd72b5541937539dab21a87e67bb 100644 (file)
@@ -38,6 +38,8 @@ import org.apache.poi.ss.usermodel.Sheet;
 import org.apache.poi.ss.util.CellReference;
 import org.apache.poi.ss.util.Region;
 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.xmlbeans.XmlOptions;
 import org.openxml4j.opc.PackagePart;
@@ -77,6 +79,8 @@ public class XSSFSheet implements Sheet {
     protected XSSFWorkbook workbook;
     protected CommentsSource sheetComments;
     protected CTMergeCells ctMergeCells;
+    protected ArrayList<Drawing> drawings;
+    protected ArrayList<Control> controls;
 
     public static final short LeftMargin = 0;
     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 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) {
                this(sheet, worksheet, workbook);
                this.sheetComments = sheetComments;
index 3c395264ec85da6a1e1b600593540f096186dda3..9aea48a0f3d181550d9e028fbdec14b31ee660d3 100644 (file)
@@ -21,6 +21,7 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.OutputStream;
 import java.lang.reflect.Constructor;
+import java.util.ArrayList;
 import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.List;
@@ -46,6 +47,8 @@ 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.Control;
+import org.apache.poi.xssf.model.Drawing;
 import org.apache.poi.xssf.model.SharedStringsTable;
 import org.apache.poi.xssf.model.StylesTable;
 import org.apache.poi.xssf.model.XSSFModel;
@@ -110,10 +113,16 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
                        "/xl/drawings/drawing#.xml",
                        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(
-               null, // TODO
-               "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
-               "/xl/image#.xml",
+               "image/x-emf", // TODO
+               "http://schemas.openxmlformats.org/officeDocument/2006/relationships/image",
+               "/xl/media/image#.emf",
                null
     );
        public static final XSSFRelation SHEET_COMMENTS = new XSSFRelation(
@@ -140,12 +149,25 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
             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
     );
+       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 {
@@ -335,9 +357,27 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
                        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
                 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);
                 
                 // Process external hyperlinks for the sheet,
@@ -839,6 +879,40 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
                     ct.writeTo(out);
                     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
index 518a15f56a08b73c24ad231db8aef3701bc1ea6f..703133f425e0d40c1c7d8a0e841a99b7751bec3f 100644 (file)
@@ -55,6 +55,7 @@ public class TestXSSFBugs extends TestCase {
         */
        public void test45430() throws Exception {
                XSSFWorkbook wb = new XSSFWorkbook(getFilePath("45430.xlsx"));
+               assertFalse(wb.isMacroEnabled());
                assertEquals(3, wb.getNumberOfNames());
                
                assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId());
@@ -85,6 +86,7 @@ public class TestXSSFBugs extends TestCase {
        public void test45431() throws Exception {
                Package pkg = Package.open(getFilePath("45431.xlsm"));
                XSSFWorkbook wb = new XSSFWorkbook(pkg);
+               assertTrue(wb.isMacroEnabled());
                
                // Check the various macro related bits can be found
                PackagePart vba = pkg.getPart(
@@ -95,6 +97,7 @@ public class TestXSSFBugs extends TestCase {
                // Save and re-open, is still there
                Package nPkg = saveAndOpen(wb);
                XSSFWorkbook nwb = new XSSFWorkbook(nPkg);
+               assertTrue(nwb.isMacroEnabled());
                vba = nPkg.getPart(
                                PackagingURIHelper.createPartName("/xl/vbaProject.bin")
                );