]> source.dussan.org Git - poi.git/commitdiff
Partial support for .xlsm files (bug #45431), but still not quite there as they seem...
authorNick Burch <nick@apache.org>
Fri, 18 Jul 2008 18:22:25 +0000 (18:22 +0000)
committerNick Burch <nick@apache.org>
Fri, 18 Jul 2008 18:22:25 +0000 (18:22 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@677990 13f79535-47bb-0310-9956-ffa450edef68

src/ooxml/java/org/apache/poi/xssf/model/BinaryPart.java [new file with mode: 0644]
src/ooxml/java/org/apache/poi/xssf/model/XSSFModel.java
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java
src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java
src/testcases/org/apache/poi/hssf/data/45431.xlsm [new file with mode: 0644]

diff --git a/src/ooxml/java/org/apache/poi/xssf/model/BinaryPart.java b/src/ooxml/java/org/apache/poi/xssf/model/BinaryPart.java
new file mode 100644 (file)
index 0000000..9582b8a
--- /dev/null
@@ -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);
+       }
+}
index eedf39117929285d448b266798c06111c4ffc7e6..03d08c030f00179ca0da093398c40944c6057881 100644 (file)
@@ -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;
index 719fc63a1d6e5d0f3f4b43149c1efec611985798..c98135d585013194566502e5e71f38ea89cc7ca3 100644 (file)
@@ -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
@@ -813,6 +839,17 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
                        workbook.setDefinedNames(null);
                }
             }
+            
+            // 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
index e3d67457342b32fc257e238970e6b2516d744306..642b723a5a15e1b8363315943fac5e7081bb0033 100644 (file)
 
 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();
+       }
 }
diff --git a/src/testcases/org/apache/poi/hssf/data/45431.xlsm b/src/testcases/org/apache/poi/hssf/data/45431.xlsm
new file mode 100644 (file)
index 0000000..fabbd0d
Binary files /dev/null and b/src/testcases/org/apache/poi/hssf/data/45431.xlsm differ