]> source.dussan.org Git - poi.git/commitdiff
Help for bug #44840 - Improved handling of HSSFObjectData, especially for entries...
authorNick Burch <nick@apache.org>
Fri, 23 May 2008 15:55:08 +0000 (15:55 +0000)
committerNick Burch <nick@apache.org>
Fri, 23 May 2008 15:55:08 +0000 (15:55 +0000)
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@659575 13f79535-47bb-0310-9956-ffa450edef68

src/documentation/content/xdocs/changes.xml
src/documentation/content/xdocs/status.xml
src/java/org/apache/poi/hssf/record/EmbeddedObjectRefSubRecord.java
src/java/org/apache/poi/hssf/usermodel/HSSFObjectData.java
src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java

index 21a6f6702c599c5a47cc29a4f1a730bd1847c172..688410c8936f5f4557cfda9b385f37ff306bd7ed 100644 (file)
@@ -37,6 +37,7 @@
 
                <!-- Don't forget to update status.xml too! -->
         <release version="3.1-final" date="2008-06-??">
+           <action dev="POI-DEVELOPERS" type="add">44840 - Improved handling of HSSFObjectData, especially for entries with data held not in POIFS</action>
            <action dev="POI-DEVELOPERS" type="add">45043 - Support for getting excel cell comments when extracting text</action>
            <action dev="POI-DEVELOPERS" type="add">Extend the support for specifying a policy to HSSF on missing / blank cells when fetching, to be able to specify the policy at the HSSFWorkbook level</action>
            <action dev="POI-DEVELOPERS" type="fix">45025 - improved FormulaParser parse error messages</action>
index 456ee3ebcae73f5468b871f82751be6f92dfbfe3..9b81f2a01e96b757e3eec1f3044738f1ab133068 100644 (file)
@@ -34,6 +34,7 @@
        <!-- Don't forget to update changes.xml too! -->
     <changes>
         <release version="3.1-final" date="2008-06-??">
+           <action dev="POI-DEVELOPERS" type="add">44840 - Improved handling of HSSFObjectData, especially for entries with data held not in POIFS</action>
            <action dev="POI-DEVELOPERS" type="add">45043 - Support for getting excel cell comments when extracting text</action>
            <action dev="POI-DEVELOPERS" type="add">Extend the support for specifying a policy to HSSF on missing / blank cells when fetching, to be able to specify the policy at the HSSFWorkbook level</action>
            <action dev="POI-DEVELOPERS" type="fix">45025 - improved FormulaParser parse error messages</action>
index 24cf2fae12a6255c1039d42c9b1ccb1243f89a33..0e59282f5e22789ee809382c36aaedd081aa15ef 100644 (file)
@@ -108,7 +108,10 @@ public class EmbeddedObjectRefSubRecord
             in.readByte(); // discard
         }
 
-        field_6_stream_id              = in.readInt();
+        // Fetch the stream ID
+        field_6_stream_id = in.readInt();
+        
+        // Store what's left
         remainingBytes = in.readRemainder();
     }
 
index b1c5c66e08b03c1064006dac82221cf523ff56c4..697c33b9e2b9d5731bcff562b6123992f49b36de 100644 (file)
@@ -55,36 +55,72 @@ public class HSSFObjectData
         this.record = record;
         this.poifs = poifs;
     }
+    
+    /**
+     * Returns the OLE2 Class Name of the object
+     */
+    public String getOLE2ClassName() {
+       EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+       return subRecord.field_5_ole_classname;
+    }
 
     /**
-     * Gets the object data.
+     * Gets the object data. Only call for ones that have
+     *  data though. See {@link #hasDirectoryEntry()}
      *
      * @return the object data as an OLE2 directory.
      * @throws IOException if there was an error reading the data.
      */
-    public DirectoryEntry getDirectory() throws IOException
-    {
+    public DirectoryEntry getDirectory() throws IOException {
+       EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+
+       int streamId = ((EmbeddedObjectRefSubRecord) subRecord).getStreamId();
+        String streamName = "MBD" + HexDump.toHex(streamId);
+
+        Entry entry = poifs.getRoot().getEntry(streamName);
+        if (entry instanceof DirectoryEntry) {
+            return (DirectoryEntry) entry;
+        } else {
+            throw new IOException("Stream " + streamName + " was not an OLE2 directory");
+        }
+    }
+    
+    /**
+     * Returns the data portion, for an ObjectData
+     *  that doesn't have an associated POIFS Directory
+     *  Entry
+     */
+    public byte[] getObjectData() {
+       EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+       return subRecord.remainingBytes;
+    }
+    
+    /**
+     * Does this ObjectData have an associated POIFS 
+     *  Directory Entry?
+     * (Not all do, those that don't have a data portion)
+     */
+    public boolean hasDirectoryEntry() {
+       EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
+       
+       // Field 6 tells you
+       return (subRecord.field_6_stream_id != 0);
+    }
+    
+    /**
+     * Finds the EmbeddedObjectRefSubRecord, or throws an 
+     *  Exception if there wasn't one
+     */
+    protected EmbeddedObjectRefSubRecord findObjectRecord() {
         Iterator subRecordIter = record.getSubRecords().iterator();
-        while (subRecordIter.hasNext())
-        {
+        
+        while (subRecordIter.hasNext()) {
             Object subRecord = subRecordIter.next();
-            if (subRecord instanceof EmbeddedObjectRefSubRecord)
-            {
-                int streamId = ((EmbeddedObjectRefSubRecord) subRecord).getStreamId();
-                String streamName = "MBD" + HexDump.toHex(streamId);
-
-                Entry entry = poifs.getRoot().getEntry(streamName);
-                if (entry instanceof DirectoryEntry)
-                {
-                    return (DirectoryEntry) entry;
-                }
-                else
-                {
-                    throw new IOException("Stream " + streamName + " was not an OLE2 directory");
-                }
+            if (subRecord instanceof EmbeddedObjectRefSubRecord) {
+               return (EmbeddedObjectRefSubRecord)subRecord;
             }
         }
-
+        
         throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
     }
 }
index 53e06ab292128d11c162dff5cd9d744d10aec397..cbe175a0e3bba0446be779c87b3a72eb5b67892d 100644 (file)
 package org.apache.poi.hssf.usermodel;
 
 import java.io.File;
+import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.util.Iterator;
+import java.util.List;
 
 import junit.framework.AssertionFailedError;
 import junit.framework.TestCase;
 
 import org.apache.poi.hssf.HSSFTestDataSamples;
+import org.apache.poi.hssf.record.EmbeddedObjectRefSubRecord;
 import org.apache.poi.hssf.util.Region;
 import org.apache.poi.util.TempFile;
 
@@ -950,4 +953,40 @@ public final class TestBugs extends TestCase {
         writeOutAndReadBack(wb);
         assertTrue("no errors writing sample xls", true);
     }
+    
+    /**
+     * Problems with extracting check boxes from
+     *  HSSFObjectData
+     * @throws Exception
+     */
+    public void test44840() throws Exception {
+        HSSFWorkbook wb = openSample("WithCheckBoxes.xls");
+
+        // Take a look at the embeded objects
+        List objects = wb.getAllEmbeddedObjects();
+        assertEquals(1, objects.size());
+        
+        HSSFObjectData obj = (HSSFObjectData)objects.get(0);
+        assertNotNull(obj);
+        
+        // Peek inside the underlying record
+        EmbeddedObjectRefSubRecord rec = obj.findObjectRecord();
+        assertNotNull(rec);
+        
+        assertEquals(32, rec.field_1_stream_id_offset);
+        assertEquals(0, rec.field_6_stream_id); // WRONG!
+        assertEquals("Forms.CheckBox.1", rec.field_5_ole_classname);
+        assertEquals(12, rec.remainingBytes.length);
+        
+        // Doesn't have a directory
+        assertFalse(obj.hasDirectoryEntry());
+        assertNotNull(obj.getObjectData());
+        assertEquals(12, obj.getObjectData().length);
+        assertEquals("Forms.CheckBox.1", obj.getOLE2ClassName());
+        
+        try {
+               obj.getDirectory();
+               fail();
+        } catch(FileNotFoundException e) {}
+    }
 }