--- src/java/org/apache/poi/ddf/EscherSplitMenuColorsRecord.java (revision 1311869) +++ src/java/org/apache/poi/ddf/EscherSplitMenuColorsRecord.java (revision ) @@ -99,6 +99,21 @@ ""; } + @Override + public String toXml(String tab) { + StringBuilder builder = new StringBuilder(); + builder.append(tab).append("<").append(getClass().getSimpleName()).append(">\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(RECORD_ID)).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getVersion())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getInstance())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(field_1_color1)).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(field_2_color2)).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(field_3_color3)).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(field_4_color4)).append("\n"); + builder.append(tab).append("\n"); + return builder.toString(); + } + public int getColor1() { return field_1_color1; --- src/java/org/apache/poi/hssf/record/EscherAggregate.java (revision 1311869) +++ src/java/org/apache/poi/hssf/record/EscherAggregate.java (revision ) @@ -329,7 +329,19 @@ return result.toString(); } - + + public String toXml(String tab){ + StringBuilder builder = new StringBuilder(); + builder.append(tab).append("<").append(getRecordName()).append(">\n"); + for ( Iterator iterator = getEscherRecords().iterator(); iterator.hasNext(); ) + { + EscherRecord escherRecord = (EscherRecord) iterator.next(); + builder.append( escherRecord.toXml(tab+"\t") ); + } + builder.append(tab).append("\n"); + return builder.toString(); + } + /** * Collapses the drawing records into an aggregate. */ --- src/java/org/apache/poi/ddf/EscherBSERecord.java (revision 1311869) +++ src/java/org/apache/poi/ddf/EscherBSERecord.java (revision ) @@ -330,6 +330,28 @@ " Extra Data:" + '\n' + extraData; } + @Override + public String toXml(String tab) { + StringBuilder builder = new StringBuilder(); + builder.append(tab).append("<").append(getClass().getSimpleName()).append(">\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(RECORD_ID)).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getVersion())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getInstance())).append("\n") + .append(tab).append("\t").append("").append(field_1_blipTypeWin32).append("\n") + .append(tab).append("\t").append("").append(field_2_blipTypeMacOS).append("\n") + .append(tab).append("\t").append("").append(field_3_uid == null ? "" : HexDump.toHex(field_3_uid)).append("\n") + .append(tab).append("\t").append("").append(field_4_tag).append("\n") + .append(tab).append("\t").append("").append(field_5_size).append("\n") + .append(tab).append("\t").append("").append(field_6_ref).append("\n") + .append(tab).append("\t").append("").append(field_7_offset).append("\n") + .append(tab).append("\t").append("").append(field_8_usage).append("\n") + .append(tab).append("\t").append("").append(field_9_name).append("\n") + .append(tab).append("\t").append("").append(field_10_unused2).append("\n") + .append(tab).append("\t").append("").append(field_11_unused3).append("\n"); + builder.append(tab).append("\n"); + return builder.toString(); + } + /** * Retrieve the string representation given a blip id. */ --- src/java/org/apache/poi/ddf/EscherDggRecord.java (revision 1311869) +++ src/java/org/apache/poi/ddf/EscherDggRecord.java (revision ) @@ -142,6 +142,21 @@ } + @Override + public String toXml(String tab) { + StringBuilder builder = new StringBuilder(); + builder.append(tab).append("<").append(getClass().getSimpleName()).append(">\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(RECORD_ID)).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getVersion())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getInstance())).append("\n") + .append(tab).append("\t").append("").append(field_1_shapeIdMax).append("\n") + .append(tab).append("\t").append("").append(getNumIdClusters()).append("\n") + .append(tab).append("\t").append("").append(field_3_numShapesSaved).append("\n") + .append(tab).append("\t").append("").append(field_4_drawingsSaved).append("\n"); + builder.append(tab).append("\n"); + return builder.toString(); + } + public int getShapeIdMax() { return field_1_shapeIdMax; } --- src/java/org/apache/poi/ddf/EscherContainerRecord.java (revision 1311869) +++ src/java/org/apache/poi/ddf/EscherContainerRecord.java (revision ) @@ -255,6 +255,26 @@ + children.toString(); } + @Override + public String toXml(String tab) { + StringBuilder builder = new StringBuilder(); + builder.append(tab).append("<").append(getClass().getSimpleName()).append(">\n") + .append(tab).append("\t").append("").append(getRecordName()).append("\n") + .append(tab).append("\t").append("").append(isContainerRecord()).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getVersion())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getInstance())).append("\n") + .append(tab).append("\t").append("0x").append(HexDump.toHex(getRecordId())).append("\n") + .append(tab).append("\t").append("").append(HexDump.toHex(_childRecords.size())).append("\n"); + for ( Iterator iterator = _childRecords.iterator(); iterator + .hasNext(); ) + { + EscherRecord record = iterator.next(); + builder.append(record.toXml(tab+"\t")); + } + builder.append(tab).append("\n"); + return builder.toString(); + } + public T getChildById( short recordId ) { for ( EscherRecord childRecord : _childRecords ) --- src/java/org/apache/poi/ddf/EscherRecord.java (revision 1311869) +++ src/java/org/apache/poi/ddf/EscherRecord.java (revision ) @@ -297,4 +297,21 @@ { _options = fVersion.setShortValue( _options, value ); } + + /** + * @param tab - each children must be a right of his parent + * @return + */ + public String toXml(String tab){ + StringBuilder builder = new StringBuilder(); + builder.append(tab).append("<").append(getClass().getSimpleName()).append(">\n") + .append(tab).append("\t").append("").append(_options).append("\n") + .append(tab).append("\t").append("").append(_recordId).append("\n") + .append(tab).append("\n"); + return builder.toString(); + } + + public String toXml(){ + return toXml(""); + } } --- src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java (revision ) +++ src/java/org/apache/poi/hssf/dev/BiffDrawingToXml.java (revision ) @@ -0,0 +1,79 @@ +package org.apache.poi.hssf.dev; + +import org.apache.poi.ddf.EscherRecord; +import org.apache.poi.hssf.model.InternalWorkbook; +import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.usermodel.HSSFPatriarch; +import org.apache.poi.hssf.usermodel.HSSFWorkbook; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; + +import java.io.*; +import java.lang.reflect.Field; +import java.util.List; + +/** + * Utility for representing drawings contained in a binary Excel file as a XML tree + * @author Evgeniy Berlog + * date: 10.04.12 + */ +public class BiffDrawingToXml { + + public static void main(String[] params) throws IOException { + FileOutputStream test = new FileOutputStream("D:\\temp\\test.xml"); + FileInputStream inp = new FileInputStream("D:\\temp\\workbook.xls"); + writeToFile(test, inp); + } + + public static void writeToFile(FileOutputStream fos, InputStream xlsWorkbook) throws IOException { + POIFSFileSystem fs = new POIFSFileSystem(xlsWorkbook); + HSSFWorkbook workbook = new HSSFWorkbook(fs); + InternalWorkbook internalWorkbook = getInternalWorkbook(workbook); + DrawingGroupRecord r = (DrawingGroupRecord) internalWorkbook.findFirstRecordBySid( DrawingGroupRecord.sid ); + r.decode(); + + StringBuilder builder = new StringBuilder(); + builder.append("\n"); + String tab = "\t"; + List escherRecords = r.getEscherRecords(); + for (EscherRecord record : escherRecords){ + builder.append(record.toXml(tab)); + } + int sheetCount = workbook.getNumberOfSheets(); + for(int i=0; i < sheetCount; i++) { + builder.append(tab).append("\n"); + builder.append(getHSSFPatriarchBoundAggregate(workbook.getSheetAt(i).getDrawingPatriarch()).toXml(tab + "\t")); + builder.append(tab).append("\n"); + } + builder.append("\n"); + fos.write(builder.toString().getBytes()); + fos.close(); + } + + private static EscherAggregate getHSSFPatriarchBoundAggregate(HSSFPatriarch patriarch) { + Field boundAggregateField = null; + try { + boundAggregateField = patriarch.getClass().getDeclaredField("_boundAggregate"); + boundAggregateField.setAccessible(true); + return (EscherAggregate) boundAggregateField.get(patriarch); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } + + private static InternalWorkbook getInternalWorkbook(HSSFWorkbook workbook) { + Field internalSheetField = null; + try { + internalSheetField = workbook.getClass().getDeclaredField("workbook"); + internalSheetField.setAccessible(true); + return (InternalWorkbook) internalSheetField.get(workbook); + } catch (NoSuchFieldException e) { + e.printStackTrace(); + } catch (IllegalAccessException e) { + e.printStackTrace(); + } + return null; + } +}