You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@poi.apache.org by ni...@apache.org on 2008/01/10 00:21:45 UTC

svn commit: r610608 - in /poi/trunk/src: java/org/apache/poi/ddf/ java/org/apache/poi/hssf/model/ java/org/apache/poi/hssf/record/ java/org/apache/poi/hssf/usermodel/ testcases/org/apache/poi/hssf/usermodel/

Author: nick
Date: Wed Jan  9 15:21:35 2008
New Revision: 610608

URL: http://svn.apache.org/viewvc?rev=610608&view=rev
Log:
Make a start on processing shapes on a sheet out of a record. For now, doesn't actually manage to do this, but has much of the infrastructure that'll be needed. Includes ability to get an existing HSSFPatriarch for a sheet, if there are the required records, and for the HSSFPatriarch to be in a position to be given the shapes that make it up (but this isn't done yet)

Modified:
    poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java
    poi/trunk/src/java/org/apache/poi/hssf/model/Workbook.java
    poi/trunk/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java
    poi/trunk/src/java/org/apache/poi/hssf/record/EscherAggregate.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java
    poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java
    poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java

Modified: poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/ddf/EscherOptRecord.java Wed Jan  9 15:21:35 2008
@@ -18,11 +18,14 @@
         
 package org.apache.poi.ddf;
 
-import org.apache.poi.util.LittleEndian;
-import org.apache.poi.util.HexDump;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.Comparator;
+import java.util.Iterator;
+import java.util.List;
 
-import java.util.*;
-import java.io.IOException;
+import org.apache.poi.util.HexDump;
+import org.apache.poi.util.LittleEndian;
 
 /**
  * The opt record is used to store property values for a shape.  It is the key to determining

Modified: poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/model/Sheet.java Wed Jan  9 15:21:35 2008
@@ -2663,12 +2663,26 @@
     	return margins;
     }
 
-    public int aggregateDrawingRecords(DrawingManager2 drawingManager)
+    /**
+     * Finds the DrawingRecord for our sheet, and
+     *  attaches it to the DrawingManager (which knows about
+     *  the overall DrawingGroup for our workbook).
+     * If requested, will create a new DrawRecord
+     *  if none currently exist
+     * @param drawingManager The DrawingManager2 for our workbook
+     * @param createIfMissing Should one be created if missing?
+     */
+    public int aggregateDrawingRecords(DrawingManager2 drawingManager, boolean createIfMissing)
     {
         int loc = findFirstRecordLocBySid(DrawingRecord.sid);
-        boolean noDrawingRecordsFound = loc == -1;
+        boolean noDrawingRecordsFound = (loc == -1);
         if (noDrawingRecordsFound)
         {
+        	if(!createIfMissing) {
+        		// None found, and not allowed to add in
+        		return -1;
+        	}
+        	
             EscherAggregate aggregate = new EscherAggregate( drawingManager );
             loc = findFirstRecordLocBySid(EscherAggregate.sid);
             if (loc == -1)

Modified: poi/trunk/src/java/org/apache/poi/hssf/model/Workbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/model/Workbook.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/model/Workbook.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/model/Workbook.java Wed Jan  9 15:21:35 2008
@@ -2165,13 +2165,68 @@
       }
       return palette;
     }
+    
+    /**
+     * Finds the primary drawing group, if one already exists
+     */
+    public void findDrawingGroup() {
+    	// Need to find a DrawingGroupRecord that
+    	//  contains a EscherDggRecord
+    	for(Iterator rit = records.iterator(); rit.hasNext();) {
+    		Record r = (Record)rit.next();
+    		
+    		if(r instanceof DrawingGroupRecord) {
+            	DrawingGroupRecord dg =	(DrawingGroupRecord)r;
+            	dg.processChildRecords();
+            	
+            	EscherContainerRecord cr =
+            		dg.getEscherContainer();
+            	if(cr == null) {
+            		continue;
+            	}
+            	
+            	EscherDggRecord dgg = null;
+            	for(Iterator it = cr.getChildRecords().iterator(); it.hasNext();) {
+            		Object er = it.next();
+            		if(er instanceof EscherDggRecord) {
+            			dgg = (EscherDggRecord)er;
+            		}
+            	}
+            	
+            	if(dgg != null) {
+            		drawingManager = new DrawingManager2(dgg);
+            		return;
+            	}
+    		}
+    	}
+
+    	// Look for the DrawingGroup record
+        int dgLoc = findFirstRecordLocBySid(DrawingGroupRecord.sid);
+        
+    	// If there is one, does it have a EscherDggRecord?
+        if(dgLoc != -1) {
+        	DrawingGroupRecord dg =
+        		(DrawingGroupRecord)records.get(dgLoc);
+        	EscherDggRecord dgg = null;
+        	for(Iterator it = dg.getEscherRecords().iterator(); it.hasNext();) {
+        		Object er = it.next();
+        		if(er instanceof EscherDggRecord) {
+        			dgg = (EscherDggRecord)er;
+        		}
+        	}
+        	
+        	if(dgg != null) {
+        		drawingManager = new DrawingManager2(dgg);
+        	}
+        }
+    }
 
     /**
-     * Creates a drawing group record.  If it already exists then it's modified.
+     * Creates a primary drawing group record.  If it already 
+     *  exists then it's modified.
      */
     public void createDrawingGroup()
     {
-
         if (drawingManager == null)
         {
             EscherContainerRecord dggContainer = new EscherContainerRecord();
@@ -2235,7 +2290,6 @@
             }
 
         }
-
     }
     
     public WindowOneRecord getWindowOne() {

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/AbstractEscherHolderRecord.java Wed Jan  9 15:21:35 2008
@@ -18,19 +18,18 @@
 
 package org.apache.poi.hssf.record;
 
+import java.io.ByteArrayInputStream;
+import java.util.ArrayList;
+import java.util.Iterator;
+import java.util.List;
+
 import org.apache.poi.ddf.DefaultEscherRecordFactory;
+import org.apache.poi.ddf.EscherContainerRecord;
 import org.apache.poi.ddf.EscherRecord;
 import org.apache.poi.ddf.EscherRecordFactory;
 import org.apache.poi.ddf.NullEscherSerializationListener;
 import org.apache.poi.util.LittleEndian;
 
-import java.io.ByteArrayInputStream;
-import java.lang.reflect.Constructor;
-import java.lang.reflect.InvocationTargetException;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-
 /**
  * The escher container record is used to hold escher records.  It is abstract and
  * must be subclassed for maximum benefit.
@@ -97,6 +96,9 @@
         }
     }
 
+    protected void convertRawBytesToEscherRecords() {
+    	convertToEscherRecords(0, rawData.length, rawData);
+    }
     private void convertToEscherRecords( int offset, int size, byte[] data )
     {
         EscherRecordFactory recordFactory = new DefaultEscherRecordFactory();
@@ -263,6 +265,54 @@
     public void clearEscherRecords()
     {
         escherRecords.clear();
+    }
+    
+    /**
+     * If we have a EscherContainerRecord as one of our
+     *  children (and most top level escher holders do),
+     *  then return that.
+     */
+    public EscherContainerRecord getEscherContainer() {
+    	for(Iterator it = escherRecords.iterator(); it.hasNext();) {
+    		Object er = it.next();
+    		if(er instanceof EscherContainerRecord) {
+    			return (EscherContainerRecord)er;
+    		}
+    	}
+    	return null;
+    }
+
+    /**
+     * Descends into all our children, returning the
+     *  first EscherRecord with the given id, or null
+     *  if none found
+     */
+    public EscherRecord findFirstWithId(short id) {
+    	return findFirstWithId(id, getEscherRecords());
+    }
+    private EscherRecord findFirstWithId(short id, List records) {
+    	// Check at our level
+    	for(Iterator it = records.iterator(); it.hasNext();) {
+    		EscherRecord r = (EscherRecord)it.next();
+    		if(r.getRecordId() == id) {
+    			return r;
+    		}
+    	}
+    	
+    	// Then check our children in turn
+    	for(Iterator it = records.iterator(); it.hasNext();) {
+    		EscherRecord r = (EscherRecord)it.next();
+    		if(r.isContainerRecord()) {
+    			EscherRecord found =
+    				findFirstWithId(id, r.getChildRecords());
+    			if(found != null) {
+    				return found;
+    			}
+    		}
+    	}
+    	
+    	// Not found in this lot
+    	return null;
     }
 
 

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/DrawingGroupRecord.java Wed Jan  9 15:21:35 2008
@@ -72,6 +72,16 @@
             return writeData( offset, data, buffer );
         }
     }
+    
+    /**
+     * Process the bytes into escher records.
+     * (Not done by default in case we break things,
+     *  unless you set the "poi.deserialize.escher" 
+     *  system property)
+     */
+    public void processChildRecords() {
+    	convertRawBytesToEscherRecords();
+    }
 
     /**
      * Size of record (including 4 byte headers for all sections)

Modified: poi/trunk/src/java/org/apache/poi/hssf/record/EscherAggregate.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/record/EscherAggregate.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/record/EscherAggregate.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/record/EscherAggregate.java Wed Jan  9 15:21:35 2008
@@ -523,7 +523,20 @@
     {
         this.patriarch = patriarch;
     }
-
+    
+    /**
+     * Converts the Records into UserModel
+     *  objects on the bound HSSFPatriarch
+     */
+    public void convertRecordsToUserModel() {
+    	if(patriarch == null) {
+    		throw new IllegalStateException("Must call setPatriarch() first");
+    	}
+    	
+    	// TODO: Support converting our records
+    	//  back into shapes
+    }
+    
     public void clear()
     {
         clearEscherRecords();

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFPatriarch.java Wed Jan  9 15:21:35 2008
@@ -21,6 +21,13 @@
 import java.util.Iterator;
 import java.util.List;
 
+import org.apache.poi.ddf.EscherComplexProperty;
+import org.apache.poi.ddf.EscherOptRecord;
+import org.apache.poi.ddf.EscherProperty;
+import org.apache.poi.hssf.record.EscherAggregate;
+import org.apache.poi.util.LittleEndian;
+import org.apache.poi.util.StringUtil;
+
 /**
  * The patriarch is the toplevel container for shapes in a sheet.  It does
  * little other than act as a container for other shapes and groups.
@@ -38,12 +45,20 @@
     int y2 = 255;
 
     /**
+     * The EscherAggregate we have been bound to.
+     * (This will handle writing us out into records,
+     *  and building up our shapes from the records)
+     */
+    private EscherAggregate boundAggregate;
+
+    /**
      * Creates the patriarch.
      *
-     * @param sheet     the sheet this patriarch is stored in.
+     * @param sheet the sheet this patriarch is stored in.
      */
-    HSSFPatriarch(HSSFSheet sheet)
+    HSSFPatriarch(HSSFSheet sheet, EscherAggregate boundAggregate)
     {
+    	this.boundAggregate = boundAggregate;
         this.sheet = sheet;
     }
 
@@ -172,6 +187,39 @@
         this.y1 = y1;
         this.x2 = x2;
         this.y2 = y2;
+    }
+    
+    /**
+     * Does this HSSFPatriarch contain a chart?
+     * (Technically a reference to a chart, since they
+     *  get stored in a different block of records)
+     * FIXME - detect chart in all cases (only seems
+     *  to work on some charts so far)
+     */
+    public boolean containsChart() {
+    	// TODO - support charts properly in usermodel
+    	
+    	// We're looking for a EscherOptRecord
+    	EscherOptRecord optRecord = (EscherOptRecord)
+    		boundAggregate.findFirstWithId(EscherOptRecord.RECORD_ID);
+    	if(optRecord == null) {
+    		// No opt record, can't have chart
+    		return false;
+    	}
+    	
+    	for(Iterator it = optRecord.getEscherProperties().iterator(); it.hasNext();) {
+    		EscherProperty prop = (EscherProperty)it.next();
+    		if(prop.getPropertyNumber() == 896 && prop.isComplex()) {
+    			EscherComplexProperty cp = (EscherComplexProperty)prop;
+    			String str = StringUtil.getFromUnicodeLE(cp.getComplexData());
+    			System.err.println(str);
+    			if(str.equals("Chart 1\0")) {
+    				return true;
+    			}
+    		}
+    	}
+
+    	return false;
     }
 
     /**

Modified: poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java (original)
+++ poi/trunk/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java Wed Jan  9 15:21:35 2008
@@ -1488,7 +1488,7 @@
      */
     public void dumpDrawingRecords(boolean fat)
     {
-        sheet.aggregateDrawingRecords(book.getDrawingManager());
+        sheet.aggregateDrawingRecords(book.getDrawingManager(), false);
 
         EscherAggregate r = (EscherAggregate) getSheet().findFirstRecordBySid(EscherAggregate.sid);
         List escherRecords = r.getEscherRecords();
@@ -1505,9 +1505,10 @@
     }
 
     /**
-     * Creates the toplevel drawing patriarch.  This will have the effect of
-     * removing any existing drawings on this sheet.
-     *
+     * Creates the top-level drawing patriarch.  This will have
+     *  the effect of removing any existing drawings on this
+     *  sheet.
+     * This may then be used to add graphics or charts
      * @return  The new patriarch.
      */
     public HSSFPatriarch createDrawingPatriarch()
@@ -1515,12 +1516,41 @@
         // Create the drawing group if it doesn't already exist.
         book.createDrawingGroup();
 
-        sheet.aggregateDrawingRecords(book.getDrawingManager());
+        sheet.aggregateDrawingRecords(book.getDrawingManager(), true);
         EscherAggregate agg = (EscherAggregate) sheet.findFirstRecordBySid(EscherAggregate.sid);
-        HSSFPatriarch patriarch = new HSSFPatriarch(this);
+        HSSFPatriarch patriarch = new HSSFPatriarch(this, agg);
         agg.clear();     // Initially the behaviour will be to clear out any existing shapes in the sheet when
                          // creating a new patriarch.
         agg.setPatriarch(patriarch);
+        return patriarch;
+    }
+    
+    /**
+     * Returns the top-level drawing patriach, if there is
+     *  one.
+     * This will hold any graphics or charts for the sheet
+     */
+    public HSSFPatriarch getDrawingPatriarch() {
+    	book.findDrawingGroup();
+    	
+    	// If there's now no drawing manager, then there's
+    	//  no drawing escher records on the workbook
+    	if(book.getDrawingManager() == null) {
+    		return null;
+    	}
+    	
+    	int found = sheet.aggregateDrawingRecords(
+    			book.getDrawingManager(), false
+    	);
+    	if(found == -1) {
+    		// Workbook has drawing stuff, but this sheet doesn't
+    		return null;
+    	}
+    	
+        EscherAggregate agg = (EscherAggregate) sheet.findFirstRecordBySid(EscherAggregate.sid);
+        HSSFPatriarch patriarch = new HSSFPatriarch(this, agg);
+        agg.setPatriarch(patriarch);
+        agg.convertRecordsToUserModel();
         return patriarch;
     }
 

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java Wed Jan  9 15:21:35 2008
@@ -407,6 +407,30 @@
         assertEquals(0, r6.getOutlineLevel());
     }
     
+    public void testGetDrawings() throws Exception {
+        String filename = System.getProperty("HSSF.testdata.path");
+    	HSSFWorkbook wb1c = new HSSFWorkbook(
+    			new FileInputStream(new File(filename,"WithChart.xls"))
+    	);
+    	HSSFWorkbook wb2c = new HSSFWorkbook(
+    			new FileInputStream(new File(filename,"WithTwoCharts.xls"))
+    	);
+    	
+    	// 1 chart sheet -> data on 1st, chart on 2nd
+    	assertNotNull(wb1c.getSheetAt(0).getDrawingPatriarch());
+    	assertNotNull(wb1c.getSheetAt(1).getDrawingPatriarch());
+    	assertFalse(wb1c.getSheetAt(0).getDrawingPatriarch().containsChart());
+    	assertTrue(wb1c.getSheetAt(1).getDrawingPatriarch().containsChart());
+    	
+    	// 2 chart sheet -> data on 1st, chart on 2nd+3rd
+    	assertNotNull(wb2c.getSheetAt(0).getDrawingPatriarch());
+    	assertNotNull(wb2c.getSheetAt(1).getDrawingPatriarch());
+    	assertNotNull(wb2c.getSheetAt(2).getDrawingPatriarch());
+    	assertFalse(wb2c.getSheetAt(0).getDrawingPatriarch().containsChart());
+    	assertTrue(wb2c.getSheetAt(1).getDrawingPatriarch().containsChart());
+    	assertTrue(wb2c.getSheetAt(2).getDrawingPatriarch().containsChart());
+    }
+    
 	/**
 	 * Test that the ProtectRecord is included when creating or cloning a sheet
 	 */

Modified: poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java
URL: http://svn.apache.org/viewvc/poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java?rev=610608&r1=610607&r2=610608&view=diff
==============================================================================
--- poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java (original)
+++ poi/trunk/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFWorkbook.java Wed Jan  9 15:21:35 2008
@@ -16,6 +16,8 @@
 */
 package org.apache.poi.hssf.usermodel;
 
+import java.io.ByteArrayInputStream;
+import java.io.ByteArrayOutputStream;
 import java.io.File;
 import java.io.FileInputStream;
 
@@ -128,5 +130,70 @@
         assertEquals(1, b.getNumberOfSheets());
         b.cloneSheet(0);
         assertEquals(2, b.getNumberOfSheets());
+    }
+    
+    public void testReadWriteWithCharts() throws Exception {
+        HSSFWorkbook b;
+        HSSFSheet s;
+        
+        // Single chart, two sheets
+        b = new HSSFWorkbook(
+        		new FileInputStream(new File(filename,"44010-SingleChart.xls"))
+        );
+        assertEquals(2, b.getNumberOfSheets());
+        s = b.getSheetAt(1);
+        assertEquals(0, s.getFirstRowNum());
+        assertEquals(0, s.getLastRowNum());
+        
+        // Has chart on 1st sheet??
+        // FIXME
+        assertNotNull(b.getSheetAt(0).getDrawingPatriarch());
+        assertNull(b.getSheetAt(1).getDrawingPatriarch());
+        assertFalse(b.getSheetAt(0).getDrawingPatriarch().containsChart());
+        
+        b = writeRead(b);
+        assertEquals(2, b.getNumberOfSheets());
+        s = b.getSheetAt(1);
+        assertEquals(0, s.getFirstRowNum());
+        assertEquals(0, s.getLastRowNum());
+
+        
+        // Two charts, three sheets
+        b = new HSSFWorkbook(
+        		new FileInputStream(new File(filename,"44010-TwoCharts.xls"))
+        );
+        assertEquals(3, b.getNumberOfSheets());
+        
+        s = b.getSheetAt(1);
+        assertEquals(0, s.getFirstRowNum());
+        assertEquals(0, s.getLastRowNum());
+        s = b.getSheetAt(2);
+        assertEquals(0, s.getFirstRowNum());
+        assertEquals(0, s.getLastRowNum());
+        
+        // Has chart on 1st sheet??
+        // FIXME
+        assertNotNull(b.getSheetAt(0).getDrawingPatriarch());
+        assertNull(b.getSheetAt(1).getDrawingPatriarch());
+        assertNull(b.getSheetAt(2).getDrawingPatriarch());
+        assertFalse(b.getSheetAt(0).getDrawingPatriarch().containsChart());
+        
+        b = writeRead(b);
+        assertEquals(3, b.getNumberOfSheets());
+        
+        s = b.getSheetAt(1);
+        assertEquals(0, s.getFirstRowNum());
+        assertEquals(0, s.getLastRowNum());
+        s = b.getSheetAt(2);
+        assertEquals(0, s.getFirstRowNum());
+        assertEquals(0, s.getLastRowNum());
+    }
+    
+    private HSSFWorkbook writeRead(HSSFWorkbook b) throws Exception {
+    	ByteArrayOutputStream baos = new ByteArrayOutputStream();
+    	b.write(baos);
+    	return new HSSFWorkbook(
+    			new ByteArrayInputStream(baos.toByteArray())
+    	);
     }
 }



---------------------------------------------------------------------
To unsubscribe, e-mail: commits-unsubscribe@poi.apache.org
For additional commands, e-mail: commits-help@poi.apache.org