Bug 28203 - [PATCH] Unable to open read-write excel file including forms
[PATCH] Unable to open read-write excel file including forms
Product: POI
Classification: Unclassified
Component: HSSF
PC All
: P3 normal with 4 votes (vote)
: ---
Assigned To: POI Developers List
Depends on: 27497
Blocks: 29802
  Show dependency tree
Reported: 2004-04-05 11:57 UTC by Antoine Mottier
Modified: 2012-05-28 07:15 UTC (History)
1 user (show)

Excel basic file with a textbox (14.00 KB, application/vnd.ms-ex)
2004-04-05 12:02 UTC, Antoine Mottier
CVS diff -u against HEAD (4.74 KB, patch)
2004-06-26 02:33 UTC, Michael Zalewski
Details | Diff

Note You need to log in before you can comment on or make changes to this bug.
Description Antoine Mottier 2004-04-05 11:57:33 UTC
After I execute the following code on the attached Excel file, openning the 
excel file is impossible : Excel 97 display an error message "unable to read 
file". Excel file is just a new document including a forms component such as a 

POIFSFileSystem fs = new POIFSFileSystem(new FileInputStream("workbook.xls"));	
HSSFWorkbook wb = new HSSFWorkbook(fs, true);
HSSFSheet sheet = wb.getSheetAt(0);
HSSFRow row = sheet.getRow(1);
if (row == null)
	row = sheet.createRow(1);
HSSFCell cell = row.getCell((short)1);
if (cell == null)
	cell = row.createCell((short)1);
cell.setCellValue("a test");			

FileOutputStream fileOut = new FileOutputStream("workbook.xls");

(I'm using POI 2.5 FINAL)
Comment 1 Antoine Mottier 2004-04-05 12:02:00 UTC
Created attachment 11133 [details]
Excel basic file with a textbox
Comment 2 Antoine Mottier 2004-04-13 12:12:04 UTC
Use of 2.0-final version (see bug #27497) solve the problem
Comment 3 Michael Zalewski 2004-06-17 12:49:09 UTC
I got this to work by making the following corrections to 
AbstractEscherHolderRecord.java (in package org.apache.poi.hssf.records). 
Replace the serialize() and getRecordSize() methods with the code below

public int serialize(int offset, byte[] data)
  LittleEndian.putShort(data, 0 + offset, getSid());
  LittleEndian.putShort(data, 2 + offset, (short)(getRecordSize() - 4));
  if (escherRecords.size() == 0 && rawData != null)
    System.arraycopy( rawData, 0, data, offset + 4, rawData.length);
    int pos = offset + 4;
    for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
      EscherRecord r = (EscherRecord) iterator.next();
      pos += r.serialize(pos, data, new NullEscherSerializationListener() );
  return getRecordSize();

 * Size of record (including 4 byte header)
public int getRecordSize()
  if (escherRecords.size() == 0 && rawData != null)
    return rawData.length + 4;
    int size = 4;
    for ( Iterator iterator = escherRecords.iterator(); iterator.hasNext(); )
      EscherRecord r = (EscherRecord) iterator.next();
      size += r.getRecordSize();
    return size;

The problem is in serialization of the Escher records (MSODRAWING, 
MSODRAWINGGROUP, and MSODRAWINGSELECTION). Even though your spreadsheet 
contains no images, forms controls are positioned on the page using the Escher 
layer, so the new Escher code is involved.

The new Escher code will not parse an the Escher records until you actually 
make a drawing. Until you use the ddf package, it just holds the data of each 
Escher record as raw bytes. But if you attempt to write these raw bytes back, 
there is a logic problem where the MSODRAWINGGROUP (and other) record is not 
reconstructed correctly -- namely, the required four byte BIFF record header is 
Comment 4 Michael Zalewski 2004-06-26 02:33:32 UTC
Created attachment 11955 [details]
CVS diff -u against HEAD
Comment 5 Glen Stampoultzis 2004-06-27 11:22:34 UTC
Resolved with many thanks to Michael.