diff --git a/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java b/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java index 4935f1ef4..5e07c953f 100644 --- a/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java +++ b/src/java/org/apache/poi/hssf/eventmodel/HSSFEventFactory.java @@ -78,7 +78,7 @@ import org.apache.poi.poifs.filesystem.POIFSFileSystem; * @see org.apache.poi.hssf.dev.EFHSSF * * @author Andrew C. Oliver (acoliver at apache dot org) - * @authro Carey Sublette (careysub@earthling.net) + * @author Carey Sublette (careysub@earthling.net) */ public class HSSFEventFactory @@ -103,7 +103,7 @@ public class HSSFEventFactory processEvents(req, in); } - + /** * Processes a file into essentially record events. * @@ -111,7 +111,7 @@ public class HSSFEventFactory * @param fs a POIFS filesystem containing your workbook * @return numeric user-specified result code. */ - + public short abortableProcessWorkbookEvents(HSSFRequest req, POIFSFileSystem fs) throws IOException, HSSFUserException { @@ -121,9 +121,9 @@ public class HSSFEventFactory /** * Processes a DocumentInputStream into essentially Record events. - * + * * If an AbortableHSSFListener causes a halt to processing during this call - * the method will return just as with abortableProcessEvents, but no + * the method will return just as with abortableProcessEvents, but no * user code or HSSFUserException will be passed back. * * @see org.apache.poi.poifs.filesystem.POIFSFileSystem#createDocumentInputStream(String) @@ -133,15 +133,15 @@ public class HSSFEventFactory public void processEvents(HSSFRequest req, InputStream in) throws IOException - { + { try { genericProcessEvents(req, in); } - catch (HSSFUserException hue) + catch (HSSFUserException hue) {/*If an HSSFUserException user exception is thrown, ignore it.*/ } } - + /** * Processes a DocumentInputStream into essentially Record events. @@ -153,11 +153,11 @@ public class HSSFEventFactory */ public short abortableProcessEvents(HSSFRequest req, InputStream in) - throws IOException, HSSFUserException + throws IOException, HSSFUserException { return genericProcessEvents(req, in); - } - + } + /** * Processes a DocumentInputStream into essentially Record events. * diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java index 9b88a67f9..0fc37939a 100644 --- a/src/java/org/apache/poi/hssf/model/Sheet.java +++ b/src/java/org/apache/poi/hssf/model/Sheet.java @@ -59,12 +59,10 @@ import java.util.List; import java.util.ArrayList; import java.util.Iterator; -import org.apache.poi.util.POILogFactory; import org.apache.poi.hssf .record.*; // normally I don't do this, buy we literally mean ALL import org.apache.poi.hssf.record.formula.Ptg; -import org.apache.poi.util.IntList; -import org.apache.poi.util.POILogger; +import org.apache.poi.util.*; import org.apache.poi.hssf.record .aggregates.*; // normally I don't do this, buy we literally mean ALL @@ -91,35 +89,33 @@ import org.apache.poi.hssf.record public class Sheet extends java.lang.Object { - public static final short LeftMargin = 0; - public static final short RightMargin = 1; - public static final short TopMargin = 2; - public static final short BottomMargin = 3; + public static final short LeftMargin = 0; + public static final short RightMargin = 1; + public static final short TopMargin = 2; + public static final short BottomMargin = 3; - protected ArrayList records = null; - int preoffset = 0; // offset of the sheet in a new file - int loc = 0; - protected boolean containsLabels = false; - ; - protected int dimsloc = 0; - protected DimensionsRecord dims; - protected DefaultColWidthRecord defaultcolwidth = null; - protected DefaultRowHeightRecord defaultrowheight = null; - protected GridsetRecord gridset = null; - protected PrintSetupRecord printSetup = null; - protected HeaderRecord header = null; - protected FooterRecord footer = null; - protected PrintGridlinesRecord printGridlines = null; - protected MergeCellsRecord merged = null; - protected int mergedloc = 0; - private static POILogger log = - POILogFactory.getLogger(Sheet.class); - private ArrayList columnSizes = - null; // holds column info - protected ValueRecordsAggregate cells = null; - protected RowRecordsAggregate rows = null; - private Iterator valueRecIterator = null; - private Iterator rowRecIterator = null; + protected ArrayList records = null; + int preoffset = 0; // offset of the sheet in a new file + int loc = 0; + protected boolean containsLabels = false; + protected int dimsloc = 0; + protected DimensionsRecord dims; + protected DefaultColWidthRecord defaultcolwidth = null; + protected DefaultRowHeightRecord defaultrowheight = null; + protected GridsetRecord gridset = null; + protected PrintSetupRecord printSetup = null; + protected HeaderRecord header = null; + protected FooterRecord footer = null; + protected PrintGridlinesRecord printGridlines = null; + protected MergeCellsRecord merged = null; + protected int mergedloc = 0; + private static POILogger log = POILogFactory.getLogger(Sheet.class); + private ArrayList columnSizes = null; // holds column info + protected ValueRecordsAggregate cells = null; + protected RowRecordsAggregate rows = null; + private Iterator valueRecIterator = null; + private Iterator rowRecIterator = null; + protected int eofLoc = 0; /** * Creates new Sheet with no intialization --useless at this point @@ -164,19 +160,23 @@ public class Sheet if (rec.getSid() == LabelRecord.sid) { - log.log(log.DEBUG, "Hit label record"); + log.log(log.DEBUG, "Hit label record."); retval.containsLabels = true; } else if (rec.getSid() == BOFRecord.sid) { bofEofNestingLevel++; + log.log(log.DEBUG, "Hit BOF record. Nesting increased to " + bofEofNestingLevel); } - else if ((rec.getSid() == EOFRecord.sid) - && (--bofEofNestingLevel == 0)) + else if (rec.getSid() == EOFRecord.sid) { - log.log(log.DEBUG, "Hit EOF record at "); - records.add(rec); - break; + --bofEofNestingLevel; + log.log(log.DEBUG, "Hit EOF record. Nesting decreased to " + bofEofNestingLevel); + if (bofEofNestingLevel == 0) { + records.add(rec); + retval.eofLoc = k; + break; + } } else if (rec.getSid() == DimensionsRecord.sid) { @@ -204,7 +204,7 @@ public class Sheet { retval.defaultrowheight = ( DefaultRowHeightRecord ) rec; } - else if ( rec.isValue() ) + else if ( rec.isValue() && bofEofNestingLevel == 1 ) { if ( isfirstcell ) { @@ -218,6 +218,10 @@ public class Sheet rec = null; } } + else if ( rec.getSid() == StringRecord.sid ) + { + rec = null; + } else if ( rec.getSid() == RowRecord.sid ) { if ( isfirstrow ) @@ -255,6 +259,14 @@ public class Sheet } } retval.records = records; + if (retval.rows == null) + { + retval.rows = new RowRecordsAggregate(); + } + if (retval.cells == null) + { + retval.cells = new ValueRecordsAggregate(); + } log.log(log.DEBUG, "sheet createSheet (existing file) exited"); return retval; } @@ -421,7 +433,7 @@ public class Sheet newrec.setColumn(oldrec.getColumn()); newrec.setXFIndex(oldrec.getXFIndex()); newrec.setSSTIndex(stringid); - records.add(k, newrec); + records.add(k, newrec); } } } @@ -608,11 +620,19 @@ public class Sheet // } for (int k = 0; k < records.size(); k++) { - - // byte[] rec = (( byte [] ) bytes.get(k)); +// byte[] rec = (( byte [] ) bytes.get(k)); // System.arraycopy(rec, 0, data, offset + pos, rec.length); - pos += (( Record ) records.get(k)).serialize(pos + offset, - data); // rec.length; + Record record = (( Record ) records.get(k)); + + //uncomment to test record sizes +// byte[] data2 = new byte[record.getRecordSize()]; +// record.serialize(0, data2 ); // rec.length; +// if (LittleEndian.getUShort(data2, 2) != record.getRecordSize() - 4 +// && record instanceof RowRecordsAggregate == false && record instanceof ValueRecordsAggregate == false) +// throw new RuntimeException("Blah!!!"); + + pos += record.serialize(pos + offset, data ); // rec.length; + } log.log(log.DEBUG, "Sheet.serialize returning "); return pos; @@ -2116,4 +2136,10 @@ public class Sheet } m.setMargin(size); } + + public int getEofLoc() + { + return eofLoc; + } + } diff --git a/src/java/org/apache/poi/hssf/record/DBCellRecord.java b/src/java/org/apache/poi/hssf/record/DBCellRecord.java index 3ccfbe127..24ae29b90 100644 --- a/src/java/org/apache/poi/hssf/record/DBCellRecord.java +++ b/src/java/org/apache/poi/hssf/record/DBCellRecord.java @@ -57,8 +57,6 @@ package org.apache.poi.hssf.record; import org.apache.poi.util.LittleEndian; -import java.util.ArrayList; - /** * Title: DBCell Record (Currently read only. Not required.) * Description: Used to find rows in blocks...TODO

@@ -130,7 +128,7 @@ public class DBCellRecord * sets offset from the start of this DBCellRecord to the start of the first cell in * the next DBCell block. * - * @param rowoffset to the start of the first cell in the next DBCell block + * @param offset offset to the start of the first cell in the next DBCell block */ public void setRowOffset(int offset) diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index b5ee198f1..836bd08d9 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -370,7 +370,7 @@ public class FormulaRecord LittleEndian.putShort(data, 4 + offset, ( short ) getRow()); LittleEndian.putShort(data, 6 + offset, getColumn()); LittleEndian.putShort(data, 8 + offset, getXFIndex()); - LittleEndian.putDouble(data, 10 + offset, getValue()); + LittleEndian.putDouble(data, 10 + offset, field_4_value); LittleEndian.putShort(data, 18 + offset, getOptions()); LittleEndian.putInt(data, 20 + offset, field_6_zero); LittleEndian.putShort(data, 24 + offset, getExpressionLength()); diff --git a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java index c949e6fc5..f30a5afd5 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -55,9 +55,7 @@ package org.apache.poi.hssf.record.aggregates; -import org.apache.poi.hssf.record.CellValueRecordInterface; -import org.apache.poi.hssf.record.Record; -import org.apache.poi.hssf.record.UnknownRecord; +import org.apache.poi.hssf.record.*; import java.util.Iterator; import java.util.List; @@ -100,7 +98,8 @@ public class ValueRecordsAggregate }*/ // XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn()); - records.put(cell, cell); + Object o = records.put(cell, cell); + if ((cell.getColumn() < firstcell) || (firstcell == -1)) { firstcell = cell.getColumn(); @@ -138,15 +137,26 @@ public class ValueRecordsAggregate { int k = 0; + FormulaRecordAggregate lastFormulaAggregate = null; + for (k = offset; k < records.size(); k++) { Record rec = ( Record ) records.get(k); - if (!rec.isInValueSection() && !(rec instanceof UnknownRecord)) + if (rec instanceof StringRecord == false && !rec.isInValueSection() && !(rec instanceof UnknownRecord)) { break; } - if (rec.isValue()) + if (rec instanceof FormulaRecord) + { + lastFormulaAggregate = new FormulaRecordAggregate((FormulaRecord)rec, null); + insertCell( lastFormulaAggregate ); + } + else if (rec instanceof StringRecord) + { + lastFormulaAggregate.setStringRecord((StringRecord)rec); + } + else if (rec.isValue()) { insertCell(( CellValueRecordInterface ) rec); } @@ -175,7 +185,6 @@ public class ValueRecordsAggregate } return pos - offset; } - /** * called by the constructor, should set class level fields. Should throw * runtime exception for bad/icomplete data. diff --git a/src/java/org/apache/poi/hssf/record/formula/Ptg.java b/src/java/org/apache/poi/hssf/record/formula/Ptg.java index 9bebec869..0781c3cac 100644 --- a/src/java/org/apache/poi/hssf/record/formula/Ptg.java +++ b/src/java/org/apache/poi/hssf/record/formula/Ptg.java @@ -299,14 +299,14 @@ public abstract class Ptg */ public abstract String toFormulaString(SheetReferences refs); /** - * dump a debug representation (hexdump) to a strnig + * dump a debug representation (hexdump) to a string */ public String toDebugString() { byte[] ba = new byte[getSize()]; String retval=null; writeBytes(ba,0); try { - retval = org.apache.poi.util.HexDump.dump(ba,0,0); + retval = org.apache.poi.util.HexDump.dump(ba,0,0); } catch (Exception e) { e.printStackTrace(); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 6ba0c63f7..27d9d681e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -71,6 +71,7 @@ import org.apache.poi.hssf.record.NumberRecord; import org.apache.poi.hssf.record.BlankRecord; import org.apache.poi.hssf.record.BoolErrRecord; import org.apache.poi.hssf.record.ExtendedFormatRecord; +import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.hssf.util.SheetReferences; @@ -259,10 +260,11 @@ public class HSSFCell break; case CELL_TYPE_FORMULA : - record = new FormulaRecord(); - (( FormulaRecord ) record).setColumn(col); - (( FormulaRecord ) record).setRow(row); - (( FormulaRecord ) record).setXFIndex(( short ) 0); + FormulaRecord formulaRecord = new FormulaRecord(); + record = new FormulaRecordAggregate(formulaRecord,null); + formulaRecord.setColumn(col); + formulaRecord.setRow(row); + formulaRecord.setXFIndex(( short ) 0); case CELL_TYPE_BOOLEAN : record = new BoolErrRecord(); (( BoolErrRecord ) record).setColumn(col); @@ -314,15 +316,14 @@ public class HSSFCell case CELL_TYPE_STRING : stringValue = - book - .getSSTString((( LabelSSTRecord ) cval).getSSTIndex()); + book.getSSTString( ( (LabelSSTRecord ) cval).getSSTIndex()); break; case CELL_TYPE_BLANK : break; case CELL_TYPE_FORMULA : - cellValue = (( FormulaRecord ) cval).getValue(); + cellValue = (( FormulaRecordAggregate ) cval).getFormulaRecord().getValue(); break; case CELL_TYPE_BOOLEAN : @@ -369,7 +370,7 @@ public class HSSFCell retval = HSSFCell.CELL_TYPE_STRING; break; - case FormulaRecord.sid : + case FormulaRecordAggregate.sid : retval = HSSFCell.CELL_TYPE_FORMULA; break; @@ -446,20 +447,20 @@ public class HSSFCell { case CELL_TYPE_FORMULA : - FormulaRecord frec = null; + FormulaRecordAggregate frec = null; if (cellType != this.cellType) { - frec = new FormulaRecord(); + frec = new FormulaRecordAggregate(new FormulaRecord(),null); } else { - frec = ( FormulaRecord ) record; + frec = ( FormulaRecordAggregate ) record; } frec.setColumn(getCellNum()); if (setValue) { - frec.setValue(getNumericCellValue()); + frec.getFormulaRecord().setValue(getNumericCellValue()); } frec.setXFIndex(( short ) cellStyle.getIndex()); frec.setRow(row); @@ -676,8 +677,7 @@ public class HSSFCell } else { - if ((cellType != CELL_TYPE_STRING) - && (cellType != CELL_TYPE_FORMULA)) + if ((cellType != CELL_TYPE_STRING ) && ( cellType != CELL_TYPE_FORMULA)) { setCellType(CELL_TYPE_STRING, false); } @@ -702,9 +702,9 @@ public class HSSFCell setCellType(CELL_TYPE_BLANK,false); } else { setCellType(CELL_TYPE_FORMULA,false); - FormulaRecord rec = (FormulaRecord) record; - rec.setOptions(( short ) 2); - rec.setValue(0); + FormulaRecordAggregate rec = (FormulaRecordAggregate) record; + rec.getFormulaRecord().setOptions(( short ) 2); + rec.getFormulaRecord().setValue(0); rec.setXFIndex(( short ) 0x0f); FormulaParser fp = new FormulaParser(formula+";",book); fp.parse(); @@ -713,9 +713,9 @@ public class HSSFCell //System.out.println("got Ptgs " + ptg.length); for (int k = 0; k < ptg.length; k++) { size += ptg[ k ].getSize(); - rec.pushExpressionToken(ptg[ k ]); + rec.getFormulaRecord().pushExpressionToken(ptg[ k ]); } - rec.setExpressionLength(( short ) size); + rec.getFormulaRecord().setExpressionLength(( short ) size); //Workbook.currentBook = null; } } @@ -723,7 +723,7 @@ public class HSSFCell public String getCellFormula() { //Workbook.currentBook=book; SheetReferences refs = book.getSheetReferences(); - String retval = FormulaParser.toFormulaString(refs, ((FormulaRecord)record).getParsedExpression()); + String retval = FormulaParser.toFormulaString(refs, ((FormulaRecordAggregate)record).getFormulaRecord().getParsedExpression()); //Workbook.currentBook=null; return retval; } @@ -825,8 +825,7 @@ public class HSSFCell public void setCellValue(boolean value) { - if ((cellType != CELL_TYPE_BOOLEAN) - && (cellType != CELL_TYPE_FORMULA)) + if ((cellType != CELL_TYPE_BOOLEAN ) && ( cellType != CELL_TYPE_FORMULA)) { setCellType(CELL_TYPE_BOOLEAN, false); } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 3c9df3c27..89d4b1b18 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -152,14 +152,14 @@ public class HSSFWorkbook workbook = Workbook.createWorkbook(records); setPropertiesFromWorkbook(workbook); - int numRecords = workbook.getNumRecords(); + int recOffset = workbook.getNumRecords(); int sheetNum = 0; - while (numRecords < records.size()) + while (recOffset < records.size()) { - Sheet sheet = Sheet.createSheet(records, sheetNum++, numRecords); + Sheet sheet = Sheet.createSheet(records, sheetNum++, recOffset ); - numRecords += sheet.getNumRecords(); + recOffset = sheet.getEofLoc()+1; sheet.convertLabelRecords( workbook); // convert all LabelRecord records to LabelSSTRecord HSSFSheet hsheet = new HSSFSheet(workbook, sheet); @@ -511,8 +511,8 @@ public class HSSFWorkbook { totalsize = 4096; } - byte[] retval = new byte[totalsize]; - int pos = workbook.serialize(0, retval); + byte[] data = new byte[totalsize]; + int pos = workbook.serialize(0, data); // System.arraycopy(wb, 0, retval, 0, wb.length); for (int k = 0; k < sheets.size(); k++) @@ -521,13 +521,13 @@ public class HSSFWorkbook // byte[] sb = (byte[])sheetbytes.get(k); // System.arraycopy(sb, 0, retval, pos, sb.length); pos += ((HSSFSheet) sheets.get(k)).getSheet().serialize(pos, - retval); // sb.length; + data); // sb.length; } for (int k = pos; k < totalsize; k++) { - retval[k] = 0; + data[k] = 0; } - return retval; + return data; } public int addSSTString(String string) diff --git a/src/java/org/apache/poi/util/LittleEndian.java b/src/java/org/apache/poi/util/LittleEndian.java index 95752e56a..935fd5a66 100644 --- a/src/java/org/apache/poi/util/LittleEndian.java +++ b/src/java/org/apache/poi/util/LittleEndian.java @@ -386,7 +386,7 @@ public class LittleEndian public static void putDouble(final byte[] data, final int offset, final double value) { - putNumber(data, offset, Double.doubleToLongBits(value), DOUBLE_SIZE); + putNumber(data, offset, Double.doubleToRawLongBits(value), DOUBLE_SIZE); } diff --git a/src/testcases/org/apache/poi/util/TestLittleEndian.java b/src/testcases/org/apache/poi/util/TestLittleEndian.java index a42686cea..56d830cc0 100644 --- a/src/testcases/org/apache/poi/util/TestLittleEndian.java +++ b/src/testcases/org/apache/poi/util/TestLittleEndian.java @@ -147,9 +147,13 @@ public class TestLittleEndian { 56, 50, -113, -4, -63, -64, -13, 63, 76, -32, -42, -35, 60, -43, 3, 64 }; + private static final byte[] _nan_double_array = + { + (byte)0x00, (byte)0x00, (byte)0x3C, (byte)0x00, (byte)0x20, (byte)0x04, (byte)0xFF, (byte)0xFF + }; private static final double[] _doubles = { - 1.23456, 2.47912 + 1.23456, 2.47912, Double.NaN }; /** @@ -158,10 +162,21 @@ public class TestLittleEndian public void testGetDouble() { - assertEquals(_doubles[ 0 ], LittleEndian.getDouble(_double_array), - 0.000001); - assertEquals(_doubles[ 1 ], LittleEndian - .getDouble(_double_array, LittleEndian.DOUBLE_SIZE), 0.000001); + assertEquals(_doubles[ 0 ], LittleEndian.getDouble(_double_array), 0.000001 ); + assertEquals(_doubles[ 1 ], LittleEndian.getDouble( _double_array, LittleEndian.DOUBLE_SIZE), 0.000001); + assertTrue(Double.isNaN(LittleEndian.getDouble(_nan_double_array))); + + // does not work. apparently nan does not always equal nan! + //assertEquals(_doubles[ 2 ], LittleEndian.getDouble(_nan_double_array), 0.000001); + + double nan = LittleEndian.getDouble(_nan_double_array); + byte[] data = new byte[8]; + LittleEndian.putDouble(data, nan); + for ( int i = 0; i < data.length; i++ ) + { + byte b = data[i]; + assertEquals(data[i], _nan_double_array[i]); + } } /**