Help for bug #44840 - Improved handling of HSSFObjectData, especially for entries with data held not in POIFS

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@659575 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-05-23 15:55:08 +00:00
parent 6eb311672a
commit bdf210f9ee
5 changed files with 102 additions and 22 deletions

View 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>

View 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>

View 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();
}

View 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
{
Iterator subRecordIter = record.getSubRecords().iterator();
while (subRecordIter.hasNext())
{
Object subRecord = subRecordIter.next();
if (subRecord instanceof EmbeddedObjectRefSubRecord)
{
int streamId = ((EmbeddedObjectRefSubRecord) subRecord).getStreamId();
String streamName = "MBD" + HexDump.toHex(streamId);
public DirectoryEntry getDirectory() throws IOException {
EmbeddedObjectRefSubRecord subRecord = findObjectRecord();
Entry entry = poifs.getRoot().getEntry(streamName);
if (entry instanceof DirectoryEntry)
{
return (DirectoryEntry) entry;
}
else
{
throw new IOException("Stream " + streamName + " was not an OLE2 directory");
}
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()) {
Object subRecord = subRecordIter.next();
if (subRecord instanceof EmbeddedObjectRefSubRecord) {
return (EmbeddedObjectRefSubRecord)subRecord;
}
}
throw new IllegalStateException("Object data does not contain a reference to an embedded object OLE2 directory");
}
}

View File

@ -18,14 +18,17 @@
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) {}
}
}