From fea5acbbe9a45aff67f4e73cdbf488a418ebc9e9 Mon Sep 17 00:00:00 2001 From: "Andrew C. Oliver" Date: Sun, 5 Jan 2003 19:04:40 +0000 Subject: [PATCH] First go at performance refactor. Most unit tests working, some have to be removed to compile (need to get things up to spec as far as new patches) PR: Obtained from: Submitted by: Reviewed by: git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/branches/performance-branch@352982 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/poi/hssf/usermodel/HSSFChart.java | 4 +- src/java/org/apache/poi/hssf/model/Sheet.java | 306 ++++---- .../org/apache/poi/hssf/model/Workbook.java | 325 +++------ .../apache/poi/hssf/record/FormulaRecord.java | 39 +- .../aggregates/RowRecordsAggregate.java | 54 +- .../aggregates/ValueRecordsAggregate.java | 652 +++++++++++++----- .../apache/poi/hssf/usermodel/HSSFCell.java | 131 ++-- .../apache/poi/hssf/usermodel/HSSFSheet.java | 295 ++++---- .../poi/hssf/usermodel/HSSFWorkbook.java | 166 +---- src/java/org/apache/poi/util/IntList.java | 31 +- .../poi/hssf/usermodel/TestHSSFSheet.java | 103 --- 11 files changed, 1050 insertions(+), 1056 deletions(-) diff --git a/src/contrib/src/org/apache/poi/hssf/usermodel/HSSFChart.java b/src/contrib/src/org/apache/poi/hssf/usermodel/HSSFChart.java index b23b1669e..e7fdecd93 100644 --- a/src/contrib/src/org/apache/poi/hssf/usermodel/HSSFChart.java +++ b/src/contrib/src/org/apache/poi/hssf/usermodel/HSSFChart.java @@ -139,8 +139,8 @@ public class HSSFChart - sheet.insertChartRecords( records ); - workbook.insertChartRecord(); + //sheet.insertChartRecords( records ); + //workbook.insertChartRecord(); } private EOFRecord createEOFRecord() diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java index 69d9beecd..4f50be099 100644 --- a/src/java/org/apache/poi/hssf/model/Sheet.java +++ b/src/java/org/apache/poi/hssf/model/Sheet.java @@ -61,6 +61,7 @@ import java.util.Iterator; import org.apache.poi.hssf .record.*; // normally I don't do this, buy we literally mean ALL +import org.apache.poi.hssf.model.Model; import org.apache.poi.hssf.record.formula.Ptg; import org.apache.poi.util.*; import org.apache.poi.hssf.record @@ -79,16 +80,17 @@ import org.apache.poi.hssf.record *

* @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) - * @author Shawn Laubach (slaubach at apache dot org) Gridlines, Headers, Footers, and PrintSetup + * @author Shawn Laubach (laubach at acm.org) Just Gridlines, Headers, Footers, and PrintSetup * @author Jason Height (jheight at chariot dot net dot au) Clone support - * @author Brian Sanders (kestrel at burdell dot org) Active Cell support * * @see org.apache.poi.hssf.model.Workbook * @see org.apache.poi.hssf.usermodel.HSSFSheet * @version 1.0-pre */ -public class Sheet implements Model +public class Sheet + extends java.lang.Object + implements Model { public static final short LeftMargin = 0; public static final short RightMargin = 1; @@ -109,7 +111,6 @@ public class Sheet implements Model protected FooterRecord footer = null; protected PrintGridlinesRecord printGridlines = null; protected MergeCellsRecord merged = null; - protected SelectionRecord selection = null; protected int mergedloc = 0; private static POILogger log = POILogFactory.getLogger(Sheet.class); private ArrayList columnSizes = null; // holds column info @@ -196,7 +197,7 @@ public class Sheet implements Model { retval.columnSizes = new ArrayList(); } - retval.columnSizes.add(rec); + retval.columnSizes.add(( ColumnInfoRecord ) rec); } else if (rec.getSid() == DefaultColWidthRecord.sid) { @@ -254,10 +255,6 @@ public class Sheet implements Model { retval.printSetup = (PrintSetupRecord) rec; } - else if ( rec.getSid() == SelectionRecord.sid ) - { - retval.selection = (SelectionRecord) rec; - } if (rec != null) { @@ -382,9 +379,7 @@ public class Sheet implements Model records.add(retval.dims); records.add(retval.createWindowTwo()); retval.setLoc(records.size() - 1); - retval.selection = - (SelectionRecord) retval.createSelection(); - records.add(retval.selection); + records.add(retval.createSelection()); records.add(retval.createEOF()); retval.records = records; log.log(log.DEBUG, "Sheet createsheet from scratch exit"); @@ -439,10 +434,9 @@ public class Sheet implements Model } public int getNumMergedRegions() - { - return merged!=null ? merged.getNumAreas() : 0; - } - + { + return merged.getNumAreas(); + } /** * This is basically a kludge to deal with the now obsolete Label records. If @@ -1047,6 +1041,7 @@ public class Sheet implements Model setLoc(getDimsLoc()); rows.removeRow(row); + cells.removeRow(row.getRowNumber()); /* * for (int k = loc; k < records.size(); k++) @@ -1118,6 +1113,10 @@ public class Sheet implements Model */ } + public CellValueRecordInterface getValueRecord(int row, short col) { + return cells.getCell(row, col); + } + /** * get the NEXT RowRecord or CellValueRecord(from LOC). The first record that * is a Row record or CellValueRecord(starting at LOC) will be returned. @@ -1223,6 +1222,9 @@ public class Sheet implements Model public RowRecord getRow(int rownum) { log.log(log.DEBUG, "getNextRow loc= " + loc); + if (rows == null) { + return null; + } return rows.getRow(rownum); /* @@ -1247,6 +1249,15 @@ public class Sheet implements Model // return null; } + + public Iterator rowRecordIterator() { + return rows.getIterator(); + } + + public Iterator rowCellIterator(int row) { + return this.cells.getRowCellIterator(row); + } + /** * Not currently used method to calculate and add dbcell records * @@ -1325,6 +1336,15 @@ public class Sheet implements Model } } + public int getFirstRow() { + return rows.getFirstRowNum(); + } + + public int getLastRow() { + return rows.getLastRowNum(); + } + + /** not currently used */ private DBCellRecord createDBCell(int offset, IntList rowoffsets, @@ -1943,66 +1963,6 @@ public class Sheet implements Model retval.setNumRefs(( short ) 0x0); return retval; } - - /** - * Returns the active row - * - * @see org.apache.poi.hssf.record.SelectionRecord - * @return row the active row index - */ - public int getActiveCellRow() - { - if (selection == null) - { - return 0; - } - return selection.getActiveCellRow(); - } - - /** - * Sets the active row - * - * @param row the row index - * @see org.apache.poi.hssf.record.SelectionRecord - */ - public void setActiveCellRow(int row) - { - //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway - if (selection != null) - { - selection.setActiveCellRow(row); - } - } - - /** - * Returns the active column - * - * @see org.apache.poi.hssf.record.SelectionRecord - * @return row the active column index - */ - public short getActiveCellCol() - { - if (selection == null) - { - return (short) 0; - } - return selection.getActiveCellCol(); - } - - /** - * Sets the active column - * - * @param col the column index - * @see org.apache.poi.hssf.record.SelectionRecord - */ - public void setActiveCellCol(short col) - { - //shouldn't have a sheet w/o a SelectionRecord, but best to guard anyway - if (selection != null) - { - selection.setActiveCellCol(col); - } - } protected Record createMergedCells() { @@ -2024,6 +1984,32 @@ public class Sheet implements Model return new EOFRecord(); } + public void setLastColForRow(int row, short col) { + this.getRow(row).setLastCol(col); + } + + public void setFirstColForRow(int row, short col) { + this.getRow(row).setFirstCol(col); + } + + public short getLastColForRow(int row) { + return this.getRow(row).getLastCol(); + } + + + public short getFirstColForRow(int row) { + return this.getRow(row).getFirstCol(); + } + + public void setCellValue(int row, short col, double val) { + this.cells.setValue(row, col, val); + } + + public void setCellStyle(int row, short col, short xf) { + this.cells.setStyle(row, col, xf); + } + + /** * get the location of the DimensionsRecord (which is the last record before the value section) * @return location in the array of records of the DimensionsRecord @@ -2056,6 +2042,7 @@ public class Sheet implements Model { retval += (( Record ) records.get(k)).getRecordSize(); } + return retval; } @@ -2091,27 +2078,8 @@ public class Sheet implements Model return null; } - /** - * Finds the first occurance of a record matching a particular sid and - * returns it's position. - * @param sid the sid to search for - * @return the record position of the matching record or -1 if no match - * is made. - */ - public int findFirstRecordLocBySid( short sid ) - { - int index = 0; - for (Iterator iterator = records.iterator(); iterator.hasNext(); ) - { - Record record = ( Record ) iterator.next(); - - if (record.getSid() == sid) - { - return index; - } - index++; - } - return -1; + public int getPhysicalNumberOfRows() { + return rows.getPhysicalNumberOfRows(); } /** @@ -2129,7 +2097,7 @@ public class Sheet implements Model */ public void setHeader (HeaderRecord newHeader) { - header = newHeader; + header = newHeader; } /** @@ -2138,7 +2106,7 @@ public class Sheet implements Model */ public FooterRecord getFooter () { - return footer; + return footer; } /** @@ -2147,7 +2115,7 @@ public class Sheet implements Model */ public void setFooter (FooterRecord newFooter) { - footer = newFooter; + footer = newFooter; } /** @@ -2156,7 +2124,7 @@ public class Sheet implements Model */ public PrintSetupRecord getPrintSetup () { - return printSetup; + return printSetup; } /** @@ -2165,7 +2133,7 @@ public class Sheet implements Model */ public void setPrintSetup (PrintSetupRecord newPrintSetup) { - printSetup = newPrintSetup; + printSetup = newPrintSetup; } /** @@ -2174,7 +2142,7 @@ public class Sheet implements Model */ public PrintGridlinesRecord getPrintGridlines () { - return printGridlines; + return printGridlines; } /** @@ -2183,7 +2151,7 @@ public class Sheet implements Model */ public void setPrintGridlines (PrintGridlinesRecord newPrintGridlines) { - printGridlines = newPrintGridlines; + printGridlines = newPrintGridlines; } /** @@ -2191,43 +2159,43 @@ public class Sheet implements Model * @param sel True to select the sheet, false otherwise. */ public void setSelected(boolean sel) { - WindowTwoRecord windowTwo = (WindowTwoRecord) findFirstRecordBySid(WindowTwoRecord.sid); - windowTwo.setSelected(sel); + WindowTwoRecord windowTwo = (WindowTwoRecord) findFirstRecordBySid(WindowTwoRecord.sid); + windowTwo.setSelected(sel); } + + /** * Gets the size of the margin in inches. * @param margin which margin to get * @return the size of the margin */ public double getMargin(short margin) { - Margin m; - switch ( margin ) - { - case LeftMargin: - m = (Margin) findFirstRecordBySid( LeftMarginRecord.sid ); - if ( m == null ) - return .75; - break; - case RightMargin: - m = (Margin) findFirstRecordBySid( RightMarginRecord.sid ); - if ( m == null ) - return .75; - break; - case TopMargin: - m = (Margin) findFirstRecordBySid( TopMarginRecord.sid ); - if ( m == null ) - return 1.0; - break; - case BottomMargin: - m = (Margin) findFirstRecordBySid( BottomMarginRecord.sid ); - if ( m == null ) - return 1.0; - break; - default : - throw new RuntimeException( "Unknown margin constant: " + margin ); - } - return m.getMargin(); + Margin m; + switch (margin) { + case LeftMargin : + m = (Margin)findFirstRecordBySid(LeftMarginRecord.sid); + if (m == null) + return .75; + break; + case RightMargin : + m = (Margin)findFirstRecordBySid(RightMarginRecord.sid); + if (m == null) + return .75; + break; + case TopMargin : + m = (Margin)findFirstRecordBySid(TopMarginRecord.sid); + if (m == null) + return 1.0; + break; + case BottomMargin : + m = (Margin)findFirstRecordBySid(BottomMarginRecord.sid); + if (m == null) + return 1.0; + break; + default : throw new RuntimeException("Unknown margin constant: " + margin); + } + return m.getMargin(); } /** @@ -2236,45 +2204,39 @@ public class Sheet implements Model * @param size the size of the margin */ public void setMargin(short margin, double size) { - Margin m; - switch ( margin ) - { - case LeftMargin: - m = (Margin) findFirstRecordBySid( LeftMarginRecord.sid ); - if ( m == null ) - { - m = new LeftMarginRecord(); - records.add( getDimsLoc() + 1, m ); - } - break; - case RightMargin: - m = (Margin) findFirstRecordBySid( RightMarginRecord.sid ); - if ( m == null ) - { - m = new RightMarginRecord(); - records.add( getDimsLoc() + 1, m ); - } - break; - case TopMargin: - m = (Margin) findFirstRecordBySid( TopMarginRecord.sid ); - if ( m == null ) - { - m = new TopMarginRecord(); - records.add( getDimsLoc() + 1, m ); - } - break; - case BottomMargin: - m = (Margin) findFirstRecordBySid( BottomMarginRecord.sid ); - if ( m == null ) - { - m = new BottomMarginRecord(); - records.add( getDimsLoc() + 1, m ); - } - break; - default : - throw new RuntimeException( "Unknown margin constant: " + margin ); - } - m.setMargin( size ); + Margin m; + switch (margin) { + case LeftMargin : + m = (Margin)findFirstRecordBySid(LeftMarginRecord.sid); + if (m == null) { + m = new LeftMarginRecord(); + records.add(getDimsLoc() + 1, (Record)m); + } + break; + case RightMargin : + m = (Margin)findFirstRecordBySid(RightMarginRecord.sid); + if (m == null) { + m = new RightMarginRecord(); + records.add(getDimsLoc() + 1, (Record)m); + } + break; + case TopMargin : + m = (Margin)findFirstRecordBySid(TopMarginRecord.sid); + if (m == null) { + m = new TopMarginRecord(); + records.add(getDimsLoc() + 1, (Record)m); + } + break; + case BottomMargin : + m = (Margin)findFirstRecordBySid(BottomMarginRecord.sid); + if (m == null) { + m = new BottomMarginRecord(); + records.add(getDimsLoc() + 1, (Record)m); + } + break; + default : throw new RuntimeException("Unknown margin constant: " + margin); + } + m.setMargin(size); } public int getEofLoc() diff --git a/src/java/org/apache/poi/hssf/model/Workbook.java b/src/java/org/apache/poi/hssf/model/Workbook.java index a1a4f4e41..52413e515 100644 --- a/src/java/org/apache/poi/hssf/model/Workbook.java +++ b/src/java/org/apache/poi/hssf/model/Workbook.java @@ -55,18 +55,24 @@ package org.apache.poi.hssf.model; -import org.apache.poi.hssf.record.*; -import org.apache.poi.hssf.util.HSSFColor; -import org.apache.poi.hssf.util.SheetReferences; -import org.apache.poi.util.POILogFactory; -import org.apache.poi.util.POILogger; +import java.io.*; import java.util.ArrayList; -import java.util.Iterator; import java.util.List; +import java.util.Iterator; import java.util.Locale; + +import org.apache.poi.util.POILogger; +import org.apache.poi.util.POILogFactory; + +import org.apache.poi.hssf.model.Model; +import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.util.SheetReferences; +import org.apache.poi.hssf.util.HSSFColor; + /** + * Workbook * Low level model implementation of a Workbook. Provides creational methods * for settings and objects contained in the workbook object. *

@@ -79,17 +85,10 @@ import java.util.Locale; * Kit (Microsoft Press) and the documentation at http://sc.openoffice.org/excelfileformat.pdf * before even attempting to use this. * - * @todo Need a good way of keeping track of bookmarks in a list. Currently - * we are manually incrementing multiple indexes whenever new records - * are added. This mechanism makes it very easy to introduce bugs. - * - * @author Shawn Laubach (slaubach at apache dot org) (Data Formats) + * @author Shawn Laubach (shawnlaubach at cox.net) (Data Formats) * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) * @author Sergei Kozello (sergeikozello at mail.ru) - * @author Luc Girardin (luc dot girardin at macrofocus dot com) - * @author Dan Sherman (dsherman at isisph.com) - * @author Brian Sanders (bsanders at risklabs dot com) - custom palette * @see org.apache.poi.hssf.usermodel.HSSFWorkbook * @version 1.0-pre */ @@ -137,21 +136,29 @@ public class Workbook implements Model { protected ArrayList names = new ArrayList(); - protected int protpos = 0; // holds the position of the protect record. - protected int bspos = 0; // holds the position of the last bound sheet. - protected int tabpos = 0; // holds the position of the tabid record - protected int fontpos = 0; // hold the position of the last font record - protected int numfonts = 0; // hold the number of font records - protected int xfpos = 0; // hold the position of the last extended font record - protected int numxfs = 0; // hold the number of extended format records - private int backuppos = 0; // holds the position of the backup record. - private int namepos = 0; // holds the position of last name record - private int supbookpos = 0; // holds the position of sup book - private int palettepos = 0; // hold the position of the palette, if applicable - private short maxformatid = -1; // holds the max format id - private boolean uses1904datewindowing = false; // whether 1904 date windowing is being used + protected int bspos = + 0; // holds the position of the last bound sheet. + protected int tabpos = + 0; // holds the position of the tabid record + protected int fontpos = + 0; // hold the position of the last font record + protected int numfonts = + 0; // hold the number of font records + protected int xfpos = + 0; // hold the position of the last extended font record + protected int numxfs = + 0; // hold the number of extended format records + private int backuppos = + 0; // holds the position of the backup record. + private int namepos = + 0; // holds the position of last name record + private int supbookpos = + 0; // holds the position of sup book + private short maxformatid = + -1; // holds the max format id - private static POILogger log = POILogFactory.getLogger(Workbook.class); + private static POILogger log = + POILogFactory.getLogger(Workbook.class); /** * Creates new Workbook with no intitialization --useless right now @@ -218,11 +225,6 @@ public class Workbook implements Model { retval.tabpos = k; break; - case ProtectRecord.sid : - log.log(DEBUG, "found protect record at " + k); - retval.protpos = k; - break; - case BackupRecord.sid : log.log(DEBUG, "found backup record at " + k); retval.backuppos = k; @@ -247,13 +249,7 @@ public class Workbook implements Model { retval.formats.add(rec); retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode(); break; - case DateWindow1904Record.sid : - log.log(DEBUG, "found datewindow1904 record at " + k); - retval.uses1904datewindowing = ((DateWindow1904Record)rec).getWindowing() == 1; - break; - case PaletteRecord.sid: - log.log(DEBUG, "found palette record at " + k); - retval.palettepos = k; + default : } records.add(rec); @@ -273,84 +269,79 @@ public class Workbook implements Model { * Creates an empty workbook object with three blank sheets and all the empty * fields. Use this to create a workbook from scratch. */ - public static Workbook createWorkbook() - { - log.log( DEBUG, "creating new workbook from scratch" ); - Workbook retval = new Workbook(); - ArrayList records = new ArrayList( 30 ); - ArrayList formats = new ArrayList( 8 ); - records.add( retval.createBOF() ); - records.add( retval.createInterfaceHdr() ); - records.add( retval.createMMS() ); - records.add( retval.createInterfaceEnd() ); - records.add( retval.createWriteAccess() ); - records.add( retval.createCodepage() ); - records.add( retval.createDSF() ); - records.add( retval.createTabId() ); + public static Workbook createWorkbook() { + log.log(DEBUG, "creating new workbook from scratch"); + Workbook retval = new Workbook(); + ArrayList records = new ArrayList(30); + ArrayList formats = new ArrayList(8); + + records.add(retval.createBOF()); + records.add(retval.createInterfaceHdr()); + records.add(retval.createMMS()); + records.add(retval.createInterfaceEnd()); + records.add(retval.createWriteAccess()); + records.add(retval.createCodepage()); + records.add(retval.createDSF()); + records.add(retval.createTabId()); retval.tabpos = records.size() - 1; - records.add( retval.createFnGroupCount() ); - records.add( retval.createWindowProtect() ); - records.add( retval.createProtect() ); - retval.protpos = records.size() - 1; - records.add( retval.createPassword() ); - records.add( retval.createProtectionRev4() ); - records.add( retval.createPasswordRev4() ); - records.add( retval.createWindowOne() ); - records.add( retval.createBackup() ); + records.add(retval.createFnGroupCount()); + records.add(retval.createWindowProtect()); + records.add(retval.createProtect()); + records.add(retval.createPassword()); + records.add(retval.createProtectionRev4()); + records.add(retval.createPasswordRev4()); + records.add(retval.createWindowOne()); + records.add(retval.createBackup()); retval.backuppos = records.size() - 1; - records.add( retval.createHideObj() ); - records.add( retval.createDateWindow1904() ); - records.add( retval.createPrecision() ); - records.add( retval.createRefreshAll() ); - records.add( retval.createBookBool() ); - records.add( retval.createFont() ); - records.add( retval.createFont() ); - records.add( retval.createFont() ); - records.add( retval.createFont() ); - retval.fontpos = records.size() - 1; // last font record postion + records.add(retval.createHideObj()); + records.add(retval.createDateWindow1904()); + records.add(retval.createPrecision()); + records.add(retval.createRefreshAll()); + records.add(retval.createBookBool()); + records.add(retval.createFont()); + records.add(retval.createFont()); + records.add(retval.createFont()); + records.add(retval.createFont()); + retval.fontpos = records.size() - 1; // last font record postion retval.numfonts = 4; // set up format records - for ( int i = 0; i <= 7; i++ ) - { - Record rec; - rec = retval.createFormat( i ); - retval.maxformatid = retval.maxformatid >= ( (FormatRecord) rec ).getIndexCode() ? retval.maxformatid : ( (FormatRecord) rec ).getIndexCode(); - formats.add( rec ); - records.add( rec ); - } - retval.formats = formats; + for (int i = 0; i <= 7; i++) { + Record rec; + rec = retval.createFormat(i); + retval.maxformatid = retval.maxformatid >= ((FormatRecord)rec).getIndexCode() ? retval.maxformatid : ((FormatRecord)rec).getIndexCode(); + formats.add(rec); + records.add(rec); + } + retval.formats = formats; - for ( int k = 0; k < 21; k++ ) - { - records.add( retval.createExtendedFormat( k ) ); + for (int k = 0; k < 21; k++) { + records.add(retval.createExtendedFormat(k)); retval.numxfs++; } retval.xfpos = records.size() - 1; - for ( int k = 0; k < 6; k++ ) - { - records.add( retval.createStyle( k ) ); + for (int k = 0; k < 6; k++) { + records.add(retval.createStyle(k)); } - retval.palettepos = records.size(); - records.add( retval.createUseSelFS() ); - for ( int k = 0; k < 1; k++ ) - { // now just do 1 + records.add(retval.createUseSelFS()); + for (int k = 0; k < 1; k++) { // now just do 1 BoundSheetRecord bsr = - (BoundSheetRecord) retval.createBoundSheet( k ); + ( BoundSheetRecord ) retval.createBoundSheet(k); - records.add( bsr ); - retval.boundsheets.add( bsr ); + records.add(bsr); + retval.boundsheets.add(bsr); retval.bspos = records.size() - 1; } - records.add( retval.createCountry() ); - retval.sst = (SSTRecord) retval.createSST(); - records.add( retval.sst ); - records.add( retval.createExtendedSST() ); + records.add(retval.createCountry()); + retval.sst = ( SSTRecord ) retval.createSST(); + records.add(retval.sst); + records.add(retval.createExtendedSST()); - records.add( retval.createEOF() ); + // TODO + records.add(retval.createEOF()); retval.records = records; - log.log( DEBUG, "exit create new workbook from scratch" ); + log.log(DEBUG, "exit create new workbook from scratch"); return retval; } @@ -523,6 +514,7 @@ public class Workbook implements Model { * make the tabid record look like the current situation. * */ + private void fixTabIdRecord() { TabIdRecord tir = ( TabIdRecord ) records.get(tabpos); short[] tia = new short[ boundsheets.size() ]; @@ -583,7 +575,6 @@ public class Workbook implements Model { ExtendedFormatRecord xf = createExtendedFormat(); ++xfpos; - ++palettepos; ++bspos; records.add(xfpos, xf); numxfs++; @@ -680,11 +671,8 @@ public class Workbook implements Model { // byte[] rec = (( byte [] ) bytes.get(k)); // System.arraycopy(rec, 0, retval, pos, rec.length); - Record record = (( Record ) records.get(k)); - // Let's skip RECALCID records, as they are only use for optimization - if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { - pos += record.serialize(pos, retval); // rec.length; - } + pos += (( Record ) records.get(k)).serialize(pos, + retval); // rec.length; } log.log(DEBUG, "Exiting serialize workbook"); return retval; @@ -717,11 +705,8 @@ public class Workbook implements Model { // byte[] rec = (( byte [] ) bytes.get(k)); // System.arraycopy(rec, 0, data, offset + pos, rec.length); - Record record = (( Record ) records.get(k)); - // Let's skip RECALCID records, as they are only use for optimization - if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { - pos += record.serialize(pos + offset, data); // rec.length; - } + pos += (( Record ) records.get(k)).serialize(pos + offset, + data); // rec.length; } log.log(DEBUG, "Exiting serialize workbook"); return pos; @@ -731,11 +716,7 @@ public class Workbook implements Model { int retval = 0; for (int k = 0; k < records.size(); k++) { - Record record = (( Record ) records.get(k)); - // Let's skip RECALCID records, as they are only use for optimization - if(record.getSid() != RecalcIdRecord.sid || ((RecalcIdRecord)record).isNeeded()) { - retval += record.getRecordSize(); - } + retval += (( Record ) records.get(k)).getRecordSize(); } return retval; } @@ -1572,16 +1553,6 @@ public class Workbook implements Model { return retval; } - /** - * Creates a palette record initialized to the default palette - * @return a PaletteRecord instance populated with the default colors - * @see org.apache.poi.hssf.record.PaletteRecord - */ - protected PaletteRecord createPalette() - { - return new PaletteRecord(PaletteRecord.sid); - } - /** * Creates the UseSelFS object with the use natural language flag set to 0 (false) * @return record containing a UseSelFSRecord @@ -1877,30 +1848,27 @@ public class Workbook implements Model { * @see org.apache.poi.hssf.record.FormatRecord * @see org.apache.poi.hssf.record.Record */ - public short createFormat( String format ) - { - ++xfpos; //These are to ensure that positions are updated properly - ++palettepos; - ++bspos; - FormatRecord rec = new FormatRecord(); - maxformatid = maxformatid >= (short) 0xa4 ? (short) ( maxformatid + 1 ) : (short) 0xa4; //Starting value from M$ empiracle study. - rec.setIndexCode( maxformatid ); - rec.setFormatStringLength( (byte) format.length() ); - rec.setFormatString( format ); + public short createFormat(String format) { + FormatRecord rec = new FormatRecord(); + maxformatid = maxformatid >= (short)0xa4 ? (short)(maxformatid + 1) : (short)0xa4; //Starting value from M$ empiracle study. + rec.setIndexCode(maxformatid); + rec.setFormatStringLength((byte)format.length()); + rec.setFormatString(format); - int pos = 0; - while ( pos < records.size() && ( (Record) records.get( pos ) ).getSid() != FormatRecord.sid ) - pos++; - pos += formats.size(); - formats.add( rec ); - records.add( pos, rec ); - return maxformatid; - } + int pos = 0; + while (pos < records.size() && ((Record)records.get(pos)).getSid() != FormatRecord.sid) + pos++; + pos += formats.size(); + formats.add(rec); + records.add(pos, rec); + return maxformatid; + } /** * Returns the first occurance of a record matching a particular sid. */ + public Record findFirstRecordBySid(short sid) { for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { Record record = ( Record ) iterator.next(); @@ -1912,34 +1880,13 @@ public class Workbook implements Model { return null; } - /** - * Returns the index of a record matching a particular sid. - * @param sid The sid of the record to match - * @return The index of -1 if no match made. - */ - public int findFirstRecordLocBySid(short sid) { - int index = 0; - for (Iterator iterator = records.iterator(); iterator.hasNext(); ) { - Record record = ( Record ) iterator.next(); - - if (record.getSid() == sid) { - return index; - } - index ++; - } - return -1; - } - /** * Returns the next occurance of a record matching a particular sid. */ public Record findNextRecordBySid(short sid, int pos) { Iterator iterator = records.iterator(); - for (;pos > 0 && iterator.hasNext(); iterator.next(),pos--) - { - // intentionally empty - } - while (iterator.hasNext()) { + for (;pos > 0 && iterator.hasNext(); iterator.next(),pos--); + while (iterator.hasNext()) { Record record = ( Record ) iterator.next(); if (record.getSid() == sid) { @@ -1953,46 +1900,4 @@ public class Workbook implements Model { { return records; } - -// public void insertChartRecords( List chartRecords ) -// { -// backuppos += chartRecords.size(); -// fontpos += chartRecords.size(); -// palettepos += chartRecords.size(); -// bspos += chartRecords.size(); -// xfpos += chartRecords.size(); -// -// records.addAll(protpos, chartRecords); -// } - - /** - * Whether date windowing is based on 1/2/1904 or 1/1/1900. - * Some versions of Excel (Mac) can save workbooks using 1904 date windowing. - * - * @return true if using 1904 date windowing - */ - public boolean isUsing1904DateWindowing() { - return uses1904datewindowing; - } - - /** - * Returns the custom palette in use for this workbook; if a custom palette record - * does not exist, then it is created. - */ - public PaletteRecord getCustomPalette() - { - PaletteRecord palette; - Record rec = (Record) records.get(palettepos); - if (rec instanceof PaletteRecord) - { - palette = (PaletteRecord) rec; - } - else - { - palette = createPalette(); - records.add(palettepos, palette); - ++bspos; - } - return palette; - } } diff --git a/src/java/org/apache/poi/hssf/record/FormulaRecord.java b/src/java/org/apache/poi/hssf/record/FormulaRecord.java index ea8c9183d..7af09a21b 100644 --- a/src/java/org/apache/poi/hssf/record/FormulaRecord.java +++ b/src/java/org/apache/poi/hssf/record/FormulaRecord.java @@ -145,7 +145,7 @@ public class FormulaRecord field_6_zero = LittleEndian.getInt(data, 16 + offset); field_7_expression_len = LittleEndian.getShort(data, 20 + offset); field_8_parsed_expr = getParsedExpressionTokens(data, size, - 22 + offset); + offset); } catch (java.lang.UnsupportedOperationException uoe) { field_8_parsed_expr = null; @@ -164,7 +164,7 @@ public class FormulaRecord int offset) { Stack stack = new Stack(); - int pos = offset; + int pos = 22 + offset; while (pos < size) { @@ -329,7 +329,15 @@ public class FormulaRecord public List getParsedExpression() { - return field_8_parsed_expr; + return ( List ) field_8_parsed_expr; + } + + /** + * sets the stack with a list + */ + public void setParsedExpression(List ptgs) { + field_8_parsed_expr = new Stack(); + field_8_parsed_expr.addAll(ptgs); } /** @@ -545,23 +553,20 @@ public class FormulaRecord .append("\n"); buffer.append(" .expressionlength= ").append(getExpressionLength()) .append("\n"); - - if (field_8_parsed_expr != null) { - buffer.append(" .numptgsinarray = ").append(field_8_parsed_expr.size()) - .append("\n"); + buffer.append(" .numptgsinarray = ").append(field_8_parsed_expr.size()) + .append("\n"); - for (int k = 0; k < field_8_parsed_expr.size(); k++ ) { + for (int k = 0; k < field_8_parsed_expr.size(); k++ ) { /* buffer.append("formula ").append(k).append(" ") - .append(((Ptg)field_8_parsed_expr.get(k)).toFormulaString());*/ - buffer.append("Formula ") - .append(k) - .append("=") - .append(field_8_parsed_expr.get(k).toString()) - .append("\n") - .append(((Ptg)field_8_parsed_expr.get(k)).toDebugString()) - .append("\n"); - } + .append(((Ptg)field_8_parsed_expr.get(k)).toFormulaString());*/ + buffer.append("Formula ") + .append(k) + .append("=") + .append(((Ptg)field_8_parsed_expr.get(k)).toString()) + .append("\n") + .append(((Ptg)field_8_parsed_expr.get(k)).toDebugString()) + .append("\n"); } diff --git a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java index ed3edfba2..09587af81 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java @@ -75,10 +75,12 @@ public class RowRecordsAggregate { int firstrow = -1; int lastrow = -1; + boolean firstdirty = false; + boolean lastdirty = false; Map records = null; int size = 0; - /** Creates a new instance of ValueRecordsAggregate */ + /** Creates a new instance of RowRecordsAggregate */ public RowRecordsAggregate() { @@ -107,6 +109,12 @@ public class RowRecordsAggregate size -= row.getRecordSize(); // Integer integer = new Integer(row.getRowNumber()); + if (lastrow == row.getRowNumber()) { + lastdirty = true; + } + if (firstrow == row.getRowNumber()) { + firstdirty = true; + } records.remove(row); } @@ -127,11 +135,17 @@ public class RowRecordsAggregate public int getFirstRowNum() { + if (firstdirty) { + firstrow = findFirstRow(); + } return firstrow; } public int getLastRowNum() { + if (lastdirty) { + lastrow = findLastRow(); + } return lastrow; } @@ -219,7 +233,43 @@ public class RowRecordsAggregate { return records.values().iterator(); } - + + /** + * used internally to refresh the "last row" when the last row is removed. + */ + private int findLastRow() + { + int rownum = lastrow-1; + RowRecord r = getRow(rownum); + + while (r == null && rownum >= 0) + { + r = this.getRow(--rownum); + } + return rownum; + } + + /** + * used internally to refresh the "first row" when the first row is removed. + */ + + private int findFirstRow() + { + int rownum = firstrow+1; + RowRecord r = getRow(rownum); + + while (r == null && rownum <= getLastRowNum()) + { + r = getRow(++rownum); + } + + if (rownum > getLastRowNum()) + return -1; + + return rownum; + } + + /** Performs a deep clone of the record*/ public Object clone() { RowRecordsAggregate rec = new RowRecordsAggregate(); 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 db9ab481c..42ab4a742 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -55,17 +55,23 @@ package org.apache.poi.hssf.record.aggregates; +import org.apache.poi.hssf.usermodel.HSSFCell; //kludge shouldn't refer to this + import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.record.formula.Ptg; +import org.apache.poi.util.DoubleList; +import org.apache.poi.util.IntList; import java.util.Iterator; import java.util.List; +import java.util.ArrayList; import java.util.TreeMap; /** * * Aggregate value records together. Things are easier to handle that way. * - * @author andy + * @author Andrew C. Oliver * @author Glen Stampoultzis (glens at apache.org) * @author Jason Height (jheight at chariot dot net dot au) */ @@ -76,63 +82,72 @@ public class ValueRecordsAggregate public final static short sid = -1000; int firstcell = -1; int lastcell = -1; - TreeMap records = null; -// int size = 0; + //TreeMap records = null; - /** Creates a new instance of ValueRecordsAggregate */ + private final static int DEFAULT_ROWS=10000; + private final static int DEFAULT_COLS=256; + + List celltype = null; + List xfs = null; + List numericcells = null; + List formulaptgs = null; + List stringvals = null; + IntList populatedRows = null; + int physCells; //physical number of cells + + public CellValueRecordInterface getCell(int row, short col) { + return constructRecord(row, col); - public ValueRecordsAggregate() - { - records = new TreeMap(); } - public void insertCell(CellValueRecordInterface cell) - { -/* if (records.get(cell) == null) - { - size += (( Record ) cell).getRecordSize(); + public int getRecordSize() { + //throw new RuntimeException("Not Implemented getRecordSize"); + + int size = 0; + Iterator irecs = getIterator(); + + while (irecs.hasNext()) { + size += (( Record ) irecs.next()).getRecordSize(); } - else + + return size; +// return size; + } + + public int serialize(int offset, byte [] data) + { + //throw new RuntimeException("Not Implemented serialize"); + int pos = offset; + Iterator irecs = getIterator(); + + while (irecs.hasNext()) { + pos += (( Record ) irecs.next()).serialize(pos,data); + } + +/* Iterator itr = records.values().iterator(); + int pos = offset; + + while (itr.hasNext()) { - size += (( Record ) cell).getRecordSize() - - (( Record ) records.get(cell)).getRecordSize(); + pos += (( Record ) itr.next()).serialize(pos, data); }*/ - - // XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn()); - Object o = records.put(cell, cell); - - if ((cell.getColumn() < firstcell) || (firstcell == -1)) - { - firstcell = cell.getColumn(); - } - if ((cell.getColumn() > lastcell) || (lastcell == -1)) - { - lastcell = cell.getColumn(); - } + return pos - offset; } - public void removeCell(CellValueRecordInterface cell) - { - // size -= (( Record ) cell).getRecordSize(); - - // XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn()); - records.remove(cell); + public ValueRecordsAggregate() { + celltype = new ArrayList(DEFAULT_ROWS); + xfs = new ArrayList(DEFAULT_ROWS); + numericcells = new ArrayList(DEFAULT_ROWS); + formulaptgs = new ArrayList(DEFAULT_ROWS); + stringvals = new ArrayList(DEFAULT_ROWS); + populatedRows = new IntList(DEFAULT_ROWS); + physCells = 0; } - public int getPhysicalNumberOfCells() - { - return records.size(); + public Iterator getIterator() { + return new VRAIterator(this); } - public int getFirstCellNum() - { - return firstcell; - } - - public int getLastCellNum() - { - return lastcell; - } public int construct(int offset, List records) { @@ -165,140 +180,449 @@ public class ValueRecordsAggregate return k; } - /** - * called by the class that is responsible for writing this sucker. - * Subclasses should implement this so that their data is passed back in a - * byte array. - * - * @param offset to begin writing at - * @param data byte array containing instance data - * @return number of bytes written - */ + public int getPhysicalNumberOfCells() { + return physCells; + } - public int serialize(int offset, byte [] data) + public int getPhysicalNumberOfCellsInRow(int row) { + int count = -1; + int col = -1; + boolean firsttime = true; + + while (col > 0 || count == -1) { + col = findNextPopulatedCell(row,col); + count++; + } + return count; + } + + public void setValue(int row, short cell, double val) { + ((DoubleList)numericcells.get(row)).set(cell, val); + } + + public void setStyle(int row, short cell, short xf) { + ((IntList)xfs.get(row)).set(cell, xf); + } + + + public Iterator getRowCellIterator(int row) { + return new VRAIterator(this, row); + } + + public void removeRow(int row) { + Iterator iterator = this.getRowCellIterator(row); + while(iterator.hasNext()) { + iterator.next(); + iterator.remove(); + } + } + + public void removeCell(CellValueRecordInterface cell) { + int rownum = cell.getRow(); + int colnum = cell.getColumn(); + int xf = cell.getXFIndex(); + int type = determineType(cell); + + if (rownum < celltype.size() && colnum < ((IntList)celltype.get(rownum)).size()) { + IntList ctRow = (IntList)celltype.get(rownum); + if (ctRow.size()-1 == colnum) { + ctRow.remove(colnum); + if (ctRow.size() == 0 && celltype.size()-1 == rownum) { + celltype.remove(rownum); + int remp = populatedRows.indexOf(rownum); + System.err.println("remp == "+remp); + populatedRows.removeValue(rownum); + } + } else { + ctRow.set(colnum,-1); + } + physCells--; + } else { + //this cell doesn't exist... + throw new RuntimeException("Tried to remove a cell that does not exist r,c="+rownum+","+colnum); + } + } + + public void insertCell(CellValueRecordInterface cell) { + int rownum = cell.getRow(); + int colnum = cell.getColumn(); + int xf = cell.getXFIndex(); + int type = determineType(cell); + + if (celltype.size() < rownum+1) { + populatedRows.add(rownum); //this means we must never have had this row inserted + } + + ensureRows(rownum); + + IntList ctRow = (IntList)celltype.get(rownum); + IntList xfRow = (IntList)xfs.get(rownum); + + + adjustIntList(ctRow, colnum+1); + adjustIntList(xfRow, colnum+1); + + ctRow.set(colnum, type); + xfRow.set(colnum, xf); + + insertCell(cell, type); + } + + CellValueRecordInterface constructRecord(int row, int col) { + if (celltype.size() < row || ((IntList)celltype.get(row)).size() < col) { + throw new ArrayIndexOutOfBoundsException("constructRecord called with row = "+row+ + "and col ="+col+" but there are only "+celltype.size()+" rows and "+ + ((IntList)celltype.get(row)).size()+" cols!!"); + } + + CellValueRecordInterface retval = null; + int type = ((IntList)celltype.get(row)).get(col); + + + switch (type) { + case HSSFCell.CELL_TYPE_NUMERIC: + NumberRecord nrecord = new NumberRecord(); + nrecord.setColumn((short)col); + nrecord.setRow(row); + nrecord.setValue(((DoubleList)numericcells.get(row)).get(col)); + nrecord.setXFIndex((short)((IntList)xfs.get(row)).get(col)); + retval = nrecord; + break; + case HSSFCell.CELL_TYPE_STRING: + LabelSSTRecord srecord = new LabelSSTRecord(); + srecord.setColumn((short)col); + srecord.setRow(row); + srecord.setSSTIndex((int)((DoubleList)numericcells.get(row)).get(col)); + srecord.setXFIndex((short)((IntList)xfs.get(row)).get(col)); + retval=srecord; + break; + case HSSFCell.CELL_TYPE_BLANK: + BlankRecord brecord = new BlankRecord(); + brecord.setColumn((short)col); + brecord.setRow(row); + brecord.setXFIndex((short)((IntList)xfs.get(row)).get(col)); + retval=brecord; + break; + case HSSFCell.CELL_TYPE_FORMULA: + FormulaRecord fr = new FormulaRecord(); + fr.setColumn((short)col); + fr.setOptions((short)2); + + fr.setRow(row); + fr.setXFIndex((short)((IntList)xfs.get(row)).get(col)); + StringRecord st = null; + String strval = (String)((List)stringvals.get(row)).get(col); + List expressionlist = (List)((List)formulaptgs.get(row)).get(col); + fr.setParsedExpression(expressionlist); + fr.setExpressionLength(calculatePtgSize(expressionlist)); + if (strval != null) { + st = new StringRecord(); + st.setString(strval); + } + FormulaRecordAggregate frarecord = new FormulaRecordAggregate(fr,st); + + retval= frarecord; + break; + + default: + throw new RuntimeException("UnImplemented Celltype "+type); + } + + return retval; + } + + private short calculatePtgSize(List expressionlist) { + short retval = 0; + Iterator iter = expressionlist.iterator(); + while (iter.hasNext()) { + retval += (short)((Ptg)iter.next()).getSize(); + } + return retval; + } + + private void insertCell(CellValueRecordInterface cell, int type) { + int rownum = cell.getRow(); + int colnum = cell.getColumn(); + + DoubleList nmRow = (DoubleList)numericcells.get(rownum); + + switch (type) { + case HSSFCell.CELL_TYPE_NUMERIC: + NumberRecord nrecord = (NumberRecord)cell; + adjustDoubleList(nmRow, colnum+1); + nmRow.set(colnum,nrecord.getValue()); + physCells++; + break; + case HSSFCell.CELL_TYPE_STRING: + LabelSSTRecord srecord = (LabelSSTRecord)cell; + adjustDoubleList(nmRow, colnum+1); + nmRow.set(colnum,srecord.getSSTIndex()); + physCells++; + break; + case HSSFCell.CELL_TYPE_FORMULA: + List ptRow = (List)formulaptgs.get(rownum); + List stRow = (List)stringvals.get(rownum); + FormulaRecordAggregate frarecord = (FormulaRecordAggregate)cell; + adjustDoubleList(nmRow, colnum+1); + adjustObjectList(ptRow, colnum+1); + adjustStringList(stRow, colnum+1); + nmRow.set(colnum,frarecord.getFormulaRecord().getValue()); + ptRow.set(colnum,frarecord.getFormulaRecord().getParsedExpression()); + StringRecord str = frarecord.getStringRecord(); + if (str != null) { + stRow.set(colnum,str.getString()); + } else { + stRow.set(colnum,null); + } + physCells++; + break; + case HSSFCell.CELL_TYPE_BLANK: + //BlankRecord brecord = (BlankRecord)cell; + physCells++; + break; + + default: + throw new RuntimeException("UnImplemented Celltype "+cell.toString()); + } + } + + private int determineType(CellValueRecordInterface cval) { - Iterator itr = records.values().iterator(); - int pos = offset; + Record record = ( Record ) cval; + int sid = record.getSid(); + int retval = 0; - while (itr.hasNext()) + switch (sid) { - pos += (( Record ) itr.next()).serialize(pos, data); + + case NumberRecord.sid : + retval = HSSFCell.CELL_TYPE_NUMERIC; + break; + + case BlankRecord.sid : + retval = HSSFCell.CELL_TYPE_BLANK; + break; + + case LabelSSTRecord.sid : + retval = HSSFCell.CELL_TYPE_STRING; + break; + + case FormulaRecordAggregate.sid : + retval = HSSFCell.CELL_TYPE_FORMULA; + break; + + case BoolErrRecord.sid : + BoolErrRecord boolErrRecord = ( BoolErrRecord ) record; + + retval = (boolErrRecord.isBoolean()) + ? HSSFCell.CELL_TYPE_BOOLEAN + : HSSFCell.CELL_TYPE_ERROR; + break; } - return pos - offset; - } - /** - * called by the constructor, should set class level fields. Should throw - * runtime exception for bad/icomplete data. - * - * @param data raw data - * @param size size of data - * @param offset of the record's data (provided a big array of the file) - */ - - protected void fillFields(byte [] data, short size, int offset) - { + return retval; } - /** - * called by constructor, should throw runtime exception in the event of a - * record passed with a differing ID. - * - * @param id alleged id for this record - */ + private void ensureRows(int rownum) { + adjustRows(celltype, rownum+1, IntList.class); + adjustRows(xfs, rownum+1, IntList.class); + adjustRows(numericcells, rownum+1, DoubleList.class); + adjustRows(formulaptgs, rownum+1, ArrayList.class); + adjustRows(stringvals, rownum+1, ArrayList.class); - protected void validateSid(short id) - { } - /** - * return the non static version of the id for this record. - */ - - public short getSid() - { - return sid; - } - - public int getRecordSize() { - - int size = 0; - Iterator irecs = records.values().iterator(); - - while (irecs.hasNext()) { - size += (( Record ) irecs.next()).getRecordSize(); + private void adjustRows(List list, int size, Class theclass) { + while (list.size() < size) { + try { + list.add(theclass.newInstance()); + } catch (Exception e) { + throw new RuntimeException("Could Not Instantiate Row in adjustRows"); + } } - - return size; -// return size; } - public Iterator getIterator() - { - return records.values().iterator(); + private void adjustIntList(IntList list, int size) { + while (list.size() < size) { + list.add(-1); + } } - /** Performs a deep clone of the record*/ - public Object clone() { - ValueRecordsAggregate rec = new ValueRecordsAggregate(); - for (Iterator valIter = getIterator(); valIter.hasNext();) { - CellValueRecordInterface val = (CellValueRecordInterface)((CellValueRecordInterface)valIter.next()).clone(); - rec.insertCell(val); - } - return rec; + private void adjustDoubleList(DoubleList list, int size) { + while (list.size() < size) { + list.add(-1); + } } + + private void adjustObjectList(List list, int size) { + while (list.size() < size) { + list.add(new ArrayList()); + } + } + + private void adjustStringList(List list, int size) { + while (list.size() < size) { + list.add(new String()); + } + } + + + protected int findNextPopulatedCell(int row, int col) { + + IntList ctRow = (IntList) celltype.get(row); + int retval = -1; + if (ctRow.size() > col+1) { + for (int k = col+1; k < ctRow.size() +1; k++) { + + if (k != ctRow.size()) { + int val = ctRow.get(k); + + if (val != -1) { + retval = k; + break; + } // end if (val !=... + + } //end if (k !=.. + + } //end for + + } //end if (ctRow.size()... + return retval; + } + + + + public short getSid() { + return sid; + } + + + public void fillFields(byte[] data, short size, int offset) { + + } + + protected void validateSid(short sid) { + + } + + } -/* - * class XYLocator implements Comparable { - * private int row = 0; - * private int col = 0; - * public XYLocator(int row, int col) { - * this.row = row; - * this.col = col; - * } - * - * public int getRow() { - * return row; - * } - * - * public int getCol() { - * return col; - * } - * - * public int compareTo(Object obj) { - * XYLocator loc = (XYLocator)obj; - * - * if (this.getRow() == loc.getRow() && - * this.getCol() == loc.getCol() ) - * return 0; - * - * if (this.getRow() < loc.getRow()) - * return -1; - * - * if (this.getRow() > loc.getRow()) - * return 1; - * - * if (this.getCol() < loc.getCol()) - * return -1; - * - * if (this.getCol() > loc.getCol()) - * return 1; - * - * return -1; - * - * } - * - * public boolean equals(Object obj) { - * if (!(obj instanceof XYLocator)) return false; - * - * XYLocator loc = (XYLocator)obj; - * if (this.getRow() == loc.getRow() - * && - * this.getCol() == loc.getCol() - * ) return true; - * return false; - * } - * - * - * } - */ +class VRAIterator implements Iterator { + private boolean hasNext; + private ValueRecordsAggregate vra; + int popindex; + int row; + int rowlimit; + int col; + CellValueRecordInterface current = null; + CellValueRecordInterface next = null; + + public VRAIterator(ValueRecordsAggregate vra) { + this.vra = vra; + this.rowlimit = -1; + popindex = 0; + if (vra.getPhysicalNumberOfCells() > 0) { + hasNext = true; + next = findNextCell(null); + } + } + + public VRAIterator(ValueRecordsAggregate vra, int row) { + this(vra); + rowlimit = row; + this.row = row; + this.popindex = vra.populatedRows.indexOf(row); + } + + public boolean hasNext() { + return hasNext; + } + + public Object next() { + current = next; + next = findNextCell(current); + if (next == null) { + hasNext = false; + } + return current; + } + + public void remove() { + vra.removeCell(current); + } + + private CellValueRecordInterface findNextCell(CellValueRecordInterface current) { + IntList ctRow = null; + int rowNum = -1; + int colNum = -1; + int newCol = -1; + boolean wasntFirst = false; + + if (current != null) { + wasntFirst = true; + rowNum = current.getRow(); + colNum = current.getColumn(); + ctRow = ((IntList)vra.celltype.get(rowNum)); + } + + //if popindex = row iwth no cells, fast forward till we get to one with size > 0 + while ((ctRow == null || ctRow.size() == 0) && vra.populatedRows.size() > popindex) { + if (wasntFirst == true) { + throw new RuntimeException("CANT HAPPEN WASNTFIRST BUT WE'RE FASTFORWARDING!"); + } + rowNum = vra.populatedRows.get(popindex); + ctRow = (IntList)vra.celltype.get(rowNum); + if (ctRow.size() == 0) { + if (rowlimit == -1) { + popindex++; + } else { + this.hasNext = false; + } + } + } + + if (rowNum == -1) { + return null; + } + + while (newCol == -1) { + newCol = findNextPopulatedCell(rowNum,colNum); + colNum = newCol; + if (colNum == -1) { //end of row, forward one row + popindex++; + if (popindex < vra.populatedRows.size() && rowlimit == -1) { + rowNum = vra.populatedRows.get(popindex); + } else { + return null; + } + } + } + + return vra.constructRecord(rowNum,colNum); + } + + private int findNextPopulatedCell(int row, int col) { + + /*IntList ctRow = (IntList) vra.celltype.get(row); + int retval = -1; + if (ctRow.size() > col+1) { + for (int k = col+1; k < ctRow.size() +1; k++) { + + if (k != ctRow.size()) { + int val = ctRow.get(k); + + if (val != -1) { + retval = k; + break; + } // end if (val !=... + + } //end if (k !=.. + + } //end for + + } //end if (ctRow.size()... + return retval;*/ + return vra.findNextPopulatedCell(row, col); + } + +} \ No newline at end of file diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 46aeb29c2..a24cd1e4a 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -94,8 +94,6 @@ import java.util.Calendar; * NOTE: the alpha won't be implementing formulas * * @author Andrew C. Oliver (acoliver at apache dot org) - * @author Dan Sherman (dsherman at isisph.com) - * @author Brian Sanders (kestrel at burdell dot org) Active Cell support * @version 1.0-pre */ @@ -163,7 +161,7 @@ public class HSSFCell private Sheet sheet; //private short row; private int row; - private CellValueRecordInterface record; +// private CellValueRecordInterface record; /** * Creates new Cell - Should only be called by HSSFRow. This creates a cell @@ -196,13 +194,25 @@ public class HSSFCell this.book = book; this.sheet = sheet; + BlankRecord rec = new BlankRecord(); + rec.setRow(row); + rec.setColumn(cellNum); + + rec.setXFIndex((short)0xf); + + cellType = HSSFCell.CELL_TYPE_BLANK; + sheet.addValueRecord(row,(CellValueRecordInterface)rec); + + + // Relying on the fact that by default the cellType is set to 0 which // is different to CELL_TYPE_BLANK hence the following method call correctly // creates a new blank cell. - setCellType(CELL_TYPE_BLANK, false); - ExtendedFormatRecord xf = book.getExFormatAt(0xf); + //setCellType(CELL_TYPE_BLANK, false); + + //ExtendedFormatRecord xf = book.getExFormatAt(0xf); + //setCellStyle(new HSSFCellStyle(( short ) 0xf, xf)); - setCellStyle(new HSSFCellStyle(( short ) 0xf, xf)); } /** @@ -236,15 +246,16 @@ public class HSSFCell errorValue = ( byte ) 0; this.book = book; this.sheet = sheet; - switch (type) +/* switch (type) { case CELL_TYPE_NUMERIC : - record = new NumberRecord(); - (( NumberRecord ) record).setColumn(col); - (( NumberRecord ) record).setRow(row); - (( NumberRecord ) record).setValue(( short ) 0); - (( NumberRecord ) record).setXFIndex(( short ) 0); + + //record = new NumberRecord(); + //(( NumberRecord ) record).setColumn(col); + //(( NumberRecord ) record).setRow(row); + //(( NumberRecord ) record).setValue(( short ) 0); + //(( NumberRecord ) record).setXFIndex(( short ) 0); break; case CELL_TYPE_STRING : @@ -285,7 +296,7 @@ public class HSSFCell } ExtendedFormatRecord xf = book.getExFormatAt(0xf); - setCellStyle(new HSSFCellStyle(( short ) 0xf, xf)); + setCellStyle(new HSSFCellStyle(( short ) 0xf, xf)); */ } /** @@ -302,7 +313,7 @@ public class HSSFCell CellValueRecordInterface cval) { cellNum = cval.getColumn(); - record = cval; + //record = cval; this.row = row; cellType = determineType(cval); cellStyle = null; @@ -394,8 +405,14 @@ public class HSSFCell public void setCellNum(short num) { + CellValueRecordInterface cval = sheet.getValueRecord(row, cellNum); + if (cval != null) { + sheet.removeValueRecord(this.row, cval); + } cellNum = num; - record.setColumn(num); + sheet.addValueRecord(row, cval); + //record.setColumn(num); + } /** @@ -457,16 +474,17 @@ public class HSSFCell } else { - frec = ( FormulaRecordAggregate ) record; + frec = (FormulaRecordAggregate)sheet.getValueRecord(row, cellNum); } frec.setColumn(getCellNum()); if (setValue) { frec.getFormulaRecord().setValue(getNumericCellValue()); + //frec.getFormulaRecord().setParsedExpression(); } - frec.setXFIndex(( short ) cellStyle.getIndex()); +// frec.setXFIndex(( short ) cellStyle.getIndex()); frec.setRow(row); - record = frec; + sheet.replaceValueRecord(frec); break; case CELL_TYPE_NUMERIC : @@ -478,16 +496,16 @@ public class HSSFCell } else { - nrec = ( NumberRecord ) record; + nrec = ( NumberRecord ) sheet.getValueRecord(row, cellNum); } nrec.setColumn(getCellNum()); if (setValue) { nrec.setValue(getNumericCellValue()); } - nrec.setXFIndex(( short ) cellStyle.getIndex()); + nrec.setXFIndex(sheet.getValueRecord(row,cellNum).getXFIndex()); nrec.setRow(row); - record = nrec; + sheet.replaceValueRecord(nrec); break; case CELL_TYPE_STRING : @@ -499,11 +517,11 @@ public class HSSFCell } else { - lrec = ( LabelSSTRecord ) record; + lrec = ( LabelSSTRecord ) sheet.getValueRecord(row, cellNum); } lrec.setColumn(getCellNum()); lrec.setRow(row); - lrec.setXFIndex(( short ) cellStyle.getIndex()); + lrec.setXFIndex(sheet.getValueRecord(row,cellNum).getXFIndex()); if (setValue) { if ((getStringCellValue() != null) @@ -523,7 +541,7 @@ public class HSSFCell lrec.setSSTIndex(sst); } } - record = lrec; + sheet.replaceValueRecord(lrec); break; case CELL_TYPE_BLANK : @@ -535,21 +553,21 @@ public class HSSFCell } else { - brec = ( BlankRecord ) record; + brec = ( BlankRecord ) sheet.getValueRecord(row, cellNum); } brec.setColumn(getCellNum()); // During construction the cellStyle may be null for a Blank cell. if (cellStyle != null) { - brec.setXFIndex(( short ) cellStyle.getIndex()); + brec.setXFIndex(sheet.getValueRecord(row,cellNum).getXFIndex()); } else { brec.setXFIndex(( short ) 0); } brec.setRow(row); - record = brec; + sheet.replaceValueRecord(brec); break; case CELL_TYPE_BOOLEAN : @@ -561,7 +579,7 @@ public class HSSFCell } else { - boolRec = ( BoolErrRecord ) record; + boolRec = ( BoolErrRecord ) sheet.getValueRecord(row, cellNum); } boolRec.setColumn(getCellNum()); if (setValue) @@ -570,7 +588,7 @@ public class HSSFCell } boolRec.setXFIndex(( short ) cellStyle.getIndex()); boolRec.setRow(row); - record = boolRec; + sheet.replaceValueRecord(boolRec); break; case CELL_TYPE_ERROR : @@ -582,7 +600,7 @@ public class HSSFCell } else { - errRec = ( BoolErrRecord ) record; + errRec = ( BoolErrRecord ) sheet.getValueRecord(row, cellNum); } errRec.setColumn(getCellNum()); if (setValue) @@ -591,16 +609,17 @@ public class HSSFCell } errRec.setXFIndex(( short ) cellStyle.getIndex()); errRec.setRow(row); - record = errRec; + sheet.replaceValueRecord(errRec); break; } if (cellType != this.cellType) { int loc = sheet.getLoc(); - sheet.replaceValueRecord(record); + //sheet.replaceValueRecord(record); sheet.setLoc(loc); } + //sheet.setCellType(this.row, this.cellNum); this.cellType = cellType; } @@ -631,7 +650,7 @@ public class HSSFCell { setCellType(CELL_TYPE_NUMERIC, false); } - (( NumberRecord ) record).setValue(value); + sheet.setCellValue(row, cellNum, value); cellValue = value; } @@ -693,7 +712,7 @@ public class HSSFCell { index = book.addSSTString(value, true); } - (( LabelSSTRecord ) record).setSSTIndex(index); + sheet.setCellValue(row, cellNum, index); stringValue = value; } } @@ -704,12 +723,12 @@ public class HSSFCell setCellType(CELL_TYPE_BLANK,false); } else { setCellType(CELL_TYPE_FORMULA,false); - FormulaRecordAggregate rec = (FormulaRecordAggregate) record; + FormulaRecordAggregate rec = new FormulaRecordAggregate(new FormulaRecord(), null); rec.getFormulaRecord().setOptions(( short ) 2); rec.getFormulaRecord().setValue(0); - - //only set to default if there is no extended format index already set - if (rec.getXFIndex() == (short)0) rec.setXFIndex(( short ) 0x0f); + rec.setRow(row); + rec.setColumn(cellNum); + rec.setXFIndex(( short ) 0x0f); FormulaParser fp = new FormulaParser(formula+";",book); fp.parse(); Ptg[] ptg = fp.getRPNPtg(); @@ -720,6 +739,9 @@ public class HSSFCell rec.getFormulaRecord().pushExpressionToken(ptg[ k ]); } rec.getFormulaRecord().setExpressionLength(( short ) size); + + sheet.replaceValueRecord(rec); + //sheet.setCellFormula(row, cellNum, options, value //Workbook.currentBook = null; } } @@ -727,9 +749,11 @@ public class HSSFCell public String getCellFormula() { //Workbook.currentBook=book; SheetReferences refs = book.getSheetReferences(); - String retval = FormulaParser.toFormulaString(refs, ((FormulaRecordAggregate)record).getFormulaRecord().getParsedExpression()); + String retval = FormulaParser.toFormulaString(refs, + ((FormulaRecordAggregate)sheet.getValueRecord(row,cellNum)).getFormulaRecord().getParsedExpression()); //Workbook.currentBook=null; return retval; + //return null; } @@ -787,12 +811,7 @@ public class HSSFCell throw new NumberFormatException( "You cannot get a date value from an error cell"); } - if (book.isUsing1904DateWindowing()) { - return HSSFDateUtil.getJavaDate(cellValue,true); - } - else { - return HSSFDateUtil.getJavaDate(cellValue,false); - } + return HSSFDateUtil.getJavaDate(cellValue); } /** @@ -834,12 +853,12 @@ 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); } (( BoolErrRecord ) record).setValue(value); - booleanValue = value; + booleanValue = value; */ } /** @@ -853,11 +872,11 @@ public class HSSFCell public void setCellErrorValue(byte value) { - if ((cellType != CELL_TYPE_ERROR) && (cellType != CELL_TYPE_FORMULA)) + /*if ((cellType != CELL_TYPE_ERROR) && (cellType != CELL_TYPE_FORMULA)) { setCellType(CELL_TYPE_ERROR, false); } - (( BoolErrRecord ) record).setValue(value); + (( BoolErrRecord ) record).setValue(value);*/ errorValue = value; } @@ -911,7 +930,8 @@ public class HSSFCell public void setCellStyle(HSSFCellStyle style) { cellStyle = style; - record.setXFIndex(style.getIndex()); + + sheet.setCellStyle(row, cellNum, style.getIndex()); } /** @@ -961,7 +981,7 @@ public class HSSFCell protected CellValueRecordInterface getCellValueRecord() { - return record; + return sheet.getValueRecord(row, cellNum); } /** @@ -976,13 +996,4 @@ public class HSSFCell throw new RuntimeException("You cannot reference columns with an index of less then 0."); } } - - /** - * Sets this cell as the active cell for the worksheet - */ - public void setAsActiveCell() - { - this.sheet.setActiveCellRow(this.row); - this.sheet.setActiveCellCol(this.cellNum); - } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java index 17b24aadb..683ae616b 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java @@ -61,21 +61,28 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Workbook; -import org.apache.poi.hssf.record.*; +import org.apache.poi.hssf.record.CellValueRecordInterface; +import org.apache.poi.hssf.record.Record; +import org.apache.poi.hssf.record.RowRecord; +import org.apache.poi.hssf.record.VCenterRecord; +import org.apache.poi.hssf.record.WindowTwoRecord; +import org.apache.poi.hssf.record.WSBoolRecord; +import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate; +import org.apache.poi.hssf.record.aggregates.ValueRecordsAggregate; import org.apache.poi.hssf.util.Region; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; +import org.apache.poi.util.IntList; import java.util.Iterator; import java.util.TreeMap; -import java.util.List; /** * High level representation of a worksheet. * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) * @author Libin Roman (romal at vistaportal.com) - * @author Shawn Laubach (slaubach at apache dot org) (Just a little) + * @author Shawn Laubach (laubach at acm.org) (Just a little) */ public class HSSFSheet @@ -101,7 +108,9 @@ public class HSSFSheet */ private Sheet sheet; - private TreeMap rows; + // private TreeMap rows; +// private RowRecordsAggregate rows; +// private ValueRecordsAggregate vra; private Workbook book; private int firstrow; private int lastrow; @@ -118,7 +127,7 @@ public class HSSFSheet protected HSSFSheet(Workbook book) { sheet = Sheet.createSheet(); - rows = new TreeMap(); // new ArrayList(INITIAL_CAPACITY); + //rows = new TreeMap(); // new ArrayList(INITIAL_CAPACITY); this.book = book; } @@ -134,7 +143,7 @@ public class HSSFSheet protected HSSFSheet(Workbook book, Sheet sheet) { this.sheet = sheet; - rows = new TreeMap(); + //rows = new TreeMap(); this.book = book; setPropertiesFromSheet(sheet); } @@ -150,7 +159,7 @@ public class HSSFSheet private void setPropertiesFromSheet(Sheet sheet) { - int sloc = sheet.getLoc(); +/* int sloc = sheet.getLoc(); RowRecord row = sheet.getNextRow(); while (row != null) @@ -159,7 +168,9 @@ public class HSSFSheet row = sheet.getNextRow(); } - sheet.setLoc(sloc); + sheet.setLoc(sloc);*/ + + /* CellValueRecordInterface cval = sheet.getNextValueRecord(); long timestart = System.currentTimeMillis(); @@ -190,8 +201,9 @@ public class HSSFSheet cval = null; } } - log.log(DEBUG, "total sheet cell creation took ", - new Long(System.currentTimeMillis() - timestart)); + */ +// log.log(DEBUG, "total sheet cell creation took ", +// new Long(System.currentTimeMillis() - timestart)); } /** @@ -219,13 +231,13 @@ public class HSSFSheet * @return HSSFRow high level representation */ - private HSSFRow createRowFromRecord(RowRecord row) +/* private HSSFRow createRowFromRecord(RowRecord row) { HSSFRow hrow = new HSSFRow(book, sheet, row); addRow(hrow, false); return hrow; - } + }*/ /** * Remove a row from this sheet. All cells contained in the row are removed as well @@ -236,35 +248,35 @@ public class HSSFSheet public void removeRow(HSSFRow row) { sheet.setLoc(sheet.getDimsLoc()); - if (rows.size() > 0) - { - rows.remove(row); - if (row.getRowNum() == getLastRowNum()) - { - lastrow = findLastRow(lastrow); - } - if (row.getRowNum() == getFirstRowNum()) - { - firstrow = findFirstRow(firstrow); - } - Iterator iter = row.cellIterator(); +// if (rows.size() > 0) +// { +// rows.remove(row); + // if (row.getRowNum() == getLastRowNum()) + // { + // lastrow = findLastRow(lastrow); + // } + // if (row.getRowNum() == getFirstRowNum()) + // { + // firstrow = findFirstRow(firstrow); + // } + //Iterator iter = row.cellIterator(); - while (iter.hasNext()) +/* while (iter.hasNext()) { HSSFCell cell = (HSSFCell) iter.next(); sheet.removeValueRecord(row.getRowNum(), cell.getCellValueRecord()); - } + }*/ sheet.removeRow(row.getRowRecord()); - } + //} } /** * used internally to refresh the "last row" when the last row is removed. */ - private int findLastRow(int lastrow) +/* private int findLastRow(int lastrow) { int rownum = lastrow - 1; HSSFRow r = getRow(rownum); @@ -274,13 +286,13 @@ public class HSSFSheet r = getRow(--rownum); } return rownum; - } + }*/ /** * used internally to refresh the "first row" when the first row is removed. */ - private int findFirstRow(int firstrow) + /*private int findFirstRow(int firstrow) { int rownum = firstrow + 1; HSSFRow r = getRow(rownum); @@ -294,7 +306,7 @@ public class HSSFSheet return -1; return rownum; - } + } */ /** * add a row to the sheet @@ -304,19 +316,22 @@ public class HSSFSheet private void addRow(HSSFRow row, boolean addLow) { - rows.put(row, row); - if (addLow) - { - sheet.addRow(row.getRowRecord()); + //rows.put(row, row); + if (addLow) { + RowRecord rec = sheet.getRow(row.getRowNum()); + if (rec == null) { + rec = new RowRecord(); + sheet.addRow(sheet.createRow(row.getRowNum())); + } } - if (row.getRowNum() > getLastRowNum()) +/* if (row.getRowNum() > getLastRowNum()) { lastrow = row.getRowNum(); } if (row.getRowNum() < getFirstRowNum()) { firstrow = row.getRowNum(); - } + }*/ } /** @@ -328,11 +343,9 @@ public class HSSFSheet public HSSFRow getRow(int rownum) { - HSSFRow row = new HSSFRow(); + HSSFRow retval = new HSSFRow(book, sheet, this.sheet.getRow(rownum)); - //row.setRowNum((short) rownum); - row.setRowNum( rownum); - return (HSSFRow) rows.get(row); + return retval; } /** @@ -341,7 +354,7 @@ public class HSSFSheet public int getPhysicalNumberOfRows() { - return rows.size(); + return sheet.getPhysicalNumberOfRows(); } /** @@ -351,7 +364,7 @@ public class HSSFSheet public int getFirstRowNum() { - return firstrow; + return sheet.getFirstRow(); } /** @@ -361,7 +374,7 @@ public class HSSFSheet public int getLastRowNum() { - return lastrow; + return sheet.getLastRow(); } /** @@ -513,33 +526,6 @@ public class HSSFSheet return record.getVCenter(); } - /** - * determines whether the output is horizontally centered on the page. - * @param value true to horizontally center, false otherwise. - */ - - public void setHorizontallyCenter(boolean value) - { - HCenterRecord record = - (HCenterRecord) sheet.findFirstRecordBySid(HCenterRecord.sid); - - record.setHCenter(value); - } - - /** - * Determine whether printed output for this sheet will be horizontally centered. - */ - - public boolean getHorizontallyCenter() - { - HCenterRecord record = - (HCenterRecord) sheet.findFirstRecordBySid(HCenterRecord.sid); - - return record.getHCenter(); - } - - - /** * removes a merged region of cells (hence letting them free) * @param index of the region to unmerge @@ -578,7 +564,7 @@ public class HSSFSheet public Iterator rowIterator() { - return rows.values().iterator(); + return new SheetRowIterator(this, this.book); } /** @@ -799,125 +785,90 @@ public class HSSFSheet * @param newPrintGridlines boolean to turn on or off the printing of * gridlines */ - public void setPrintGridlines( boolean newPrintGridlines ) - { - getSheet().getPrintGridlines().setPrintGridlines( newPrintGridlines ); + public void setPrintGridlines(boolean newPrintGridlines) { + getSheet().getPrintGridlines().setPrintGridlines(newPrintGridlines); } /** * Gets the print setup object. * @return The user model for the print setup object. */ - public HSSFPrintSetup getPrintSetup() - { - return new HSSFPrintSetup( getSheet().getPrintSetup() ); + public HSSFPrintSetup getPrintSetup() { + return new HSSFPrintSetup(getSheet().getPrintSetup()); } /** * Gets the user model for the document header. * @return The Document header. */ - public HSSFHeader getHeader() - { - return new HSSFHeader( getSheet().getHeader() ); + public HSSFHeader getHeader() { + return new HSSFHeader(getSheet().getHeader()); } /** * Gets the user model for the document footer. * @return The Document footer. */ - public HSSFFooter getFooter() - { - return new HSSFFooter( getSheet().getFooter() ); - } + public HSSFFooter getFooter() { + return new HSSFFooter(getSheet().getFooter()); + } - /** - * Sets whether sheet is selected. - * @param sel Whether to select the sheet or deselect the sheet. - */ - public void setSelected( boolean sel ) - { - getSheet().setSelected( sel ); - } + /** + * Sets whether sheet is selected. + * @param sel Whether to select the sheet or deselect the sheet. + */ + public void setSelected(boolean sel) { + getSheet().setSelected(sel); + } - /** - * Gets the size of the margin in inches. - * @param margin which margin to get - * @return the size of the margin - */ - public double getMargin( short margin ) - { - return getSheet().getMargin( margin ); - } + /** + * Gets the size of the margin in inches. + * @param margin which margin to get + * @return the size of the margin + */ + public double getMargin(short margin) { + return getSheet().getMargin(margin); + } - /** - * Sets the size of the margin in inches. - * @param margin which margin to get - * @param size the size of the margin - */ - public void setMargin( short margin, double size ) - { - getSheet().setMargin( margin, size ); - } - - /** - * Shifts rows between startRow and endRow n number of rows. - * If you use a negative number, it will shift rows up. - * Code ensures that rows don't wrap around - * - * @param startRow the row to start shifting - * @param endRow the row to end shifting - * @param n the number of rows to shift - */ - public void shiftRows( int startRow, int endRow, int n ) - { - int s, e, inc; - if ( n < 0 ) - { - s = startRow; - e = endRow; - inc = 1; - } - else - { - s = endRow; - e = startRow; - inc = -1; - } - for ( int rowNum = s; rowNum >= startRow && rowNum <= endRow && rowNum >= 0 && rowNum < 65536; rowNum += inc ) - { - HSSFRow row = getRow( rowNum ); - HSSFRow row2Replace = getRow( rowNum + n ); - if ( row2Replace == null ) - row2Replace = createRow( rowNum + n ); - - HSSFCell cell; - for ( short col = row2Replace.getFirstCellNum(); col <= row2Replace.getLastCellNum(); col++ ) - { - cell = row2Replace.getCell( col ); - if ( cell != null ) - row2Replace.removeCell( cell ); - } - for ( short col = row.getFirstCellNum(); col <= row.getLastCellNum(); col++ ) - { - cell = row.getCell( col ); - if ( cell != null ) - { - row.removeCell( cell ); - CellValueRecordInterface cellRecord = cell.getCellValueRecord(); - cellRecord.setRow( rowNum + n ); - row2Replace.createCellFromRecord( cellRecord ); - sheet.addValueRecord( rowNum + n, cellRecord ); - } - } - } - if ( endRow == lastrow || endRow + n > lastrow ) lastrow = Math.min( endRow + n, 65535 ); - if ( startRow == firstrow || startRow + n < firstrow ) firstrow = Math.max( startRow + n, 0 ); - } - - protected void insertChartRecords( List records ) - { - int window2Loc = sheet.findFirstRecordLocBySid( WindowTwoRecord.sid ); - sheet.getRecords().addAll( window2Loc, records ); - } + /** + * Sets the size of the margin in inches. + * @param margin which margin to get + * @param size the size of the margin + */ + public void setMargin(short margin, double size) { + getSheet().setMargin(margin, size); + } } + +class SheetRowIterator implements Iterator { + Iterator rows; + Workbook book; + Sheet sheet; + + public SheetRowIterator(HSSFSheet sheet, Workbook book) { + this.sheet = sheet.getSheet(); + this.book = book; + rows = this.sheet.rowRecordIterator(); + } + + public boolean hasNext() { + return rows.hasNext(); + } + + public Object next() { + HSSFRow retval = null; + if (rows.hasNext()) { + retval = new HSSFRow(book, sheet, (RowRecord)rows.next()); + } + return retval; + } + + public void remove() { + rows.remove(); + } + + +} + + + diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 777b53f31..a345c4433 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -60,15 +60,10 @@ package org.apache.poi.hssf.usermodel; import org.apache.poi.util.POILogFactory; -import org.apache.poi.hssf.eventmodel.EventRecordFactory; import org.apache.poi.hssf.model.Sheet; import org.apache.poi.hssf.model.Workbook; import org.apache.poi.hssf.record.*; import org.apache.poi.poifs.filesystem.POIFSFileSystem; -import org.apache.poi.poifs.filesystem.Entry; -import org.apache.poi.poifs.filesystem.DirectoryEntry; -import org.apache.poi.poifs.filesystem.DocumentEntry; -import org.apache.poi.poifs.filesystem.DocumentInputStream; import org.apache.poi.util.POILogger; import java.io.ByteArrayInputStream; @@ -77,7 +72,6 @@ import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; -import java.util.Iterator; /** * High level representation of a workbook. This is the first object most users @@ -88,7 +82,7 @@ import java.util.Iterator; * @see org.apache.poi.hssf.usermodel.HSSFSheet * @author Andrew C. Oliver (acoliver at apache dot org) * @author Glen Stampoultzis (glens at apache.org) - * @author Shawn Laubach (slaubach at apache dot org) + * @author Shawn Laubach (shawnlaubach at cox.net) * @version 2.0-pre */ @@ -123,18 +117,6 @@ public class HSSFWorkbook */ private ArrayList names; - - /** - * holds whether or not to preserve other nodes in the POIFS. Used - * for macros and embedded objects. - */ - private boolean preserveNodes; - - /** - * if you do preserve the nodes, you'll need to hold the whole POIFS in - * memory. - */ - private POIFSFileSystem poifs; private static POILogger log = POILogFactory.getLogger(HSSFWorkbook.class); @@ -150,40 +132,22 @@ public class HSSFWorkbook names = new ArrayList(INITIAL_CAPACITY); } - public HSSFWorkbook(POIFSFileSystem fs) throws IOException { - this(fs,true); - } - /** * given a POI POIFSFileSystem object, read in its Workbook and populate the high and * low level models. If you're reading in a workbook...start here. * * @param fs the POI filesystem that contains the Workbook stream. - * @param preserveNodes whether to preseve other nodes, such as - * macros. This takes more memory, so only say yes if you - * need to. * @see org.apache.poi.poifs.filesystem.POIFSFileSystem * @exception IOException if the stream cannot be read */ - public HSSFWorkbook(POIFSFileSystem fs, boolean preserveNodes) + public HSSFWorkbook(POIFSFileSystem fs) throws IOException { - this.preserveNodes = preserveNodes; - - if (preserveNodes) { - this.poifs = fs; - } - sheets = new ArrayList(INITIAL_CAPACITY); names = new ArrayList(INITIAL_CAPACITY); InputStream stream = fs.createDocumentInputStream("Workbook"); - - EventRecordFactory factory = new EventRecordFactory(); - - - List records = RecordFactory.createRecords(stream); workbook = Workbook.createWorkbook(records); @@ -211,27 +175,20 @@ public class HSSFWorkbook } } - public HSSFWorkbook(InputStream s) throws IOException { - this(s,true); - } - /** * Companion to HSSFWorkbook(POIFSFileSystem), this constructs the POI filesystem around your * inputstream. * * @param s the POI filesystem that contains the Workbook stream. - * @param preserveNodes whether to preseve other nodes, such as - * macros. This takes more memory, so only say yes if you - * need to. * @see org.apache.poi.poifs.filesystem.POIFSFileSystem * @see #HSSFWorkbook(POIFSFileSystem) * @exception IOException if the stream cannot be read */ - public HSSFWorkbook(InputStream s, boolean preserveNodes) + public HSSFWorkbook(InputStream s) throws IOException { - this(new POIFSFileSystem(s), preserveNodes); + this((new POIFSFileSystem(s))); } /** @@ -558,16 +515,9 @@ public class HSSFWorkbook { byte[] bytes = getBytes(); POIFSFileSystem fs = new POIFSFileSystem(); - - fs.createDocument(new ByteArrayInputStream(bytes), "Workbook"); - if (preserveNodes) { - List excepts = new ArrayList(1); - excepts.add("Workbook"); - copyNodes(this.poifs,fs,excepts); - } + fs.createDocument(new ByteArrayInputStream(bytes), "Workbook"); fs.writeFilesystem(stream); - //poifs.writeFilesystem(stream); } /** @@ -598,12 +548,12 @@ public class HSSFWorkbook // sheetbytes.add((( HSSFSheet ) sheets.get(k)).getSheet().getSize()); totalsize += ((HSSFSheet) sheets.get(k)).getSheet().getSize(); } -/* if (totalsize < 4096) + if (totalsize < 4096) { 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++) @@ -612,13 +562,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++) + for (int k = pos; k < totalsize; k++) { - retval[k] = 0; - }*/ - return retval; + data[k] = 0; + } + return data; } public int addSSTString(String string) @@ -708,14 +658,14 @@ public class HSSFWorkbook workbook.removeName(index); } - /** + /** * Creates an instance of HSSFDataFormat. * @return the HSSFDataFormat object * @see org.apache.poi.hssf.record.FormatRecord * @see org.apache.poi.hssf.record.Record */ public HSSFDataFormat createDataFormat() { - return new HSSFDataFormat(workbook); + return new HSSFDataFormat(workbook); } /** remove the named range by his name @@ -727,89 +677,5 @@ public class HSSFWorkbook removeName(index); } - - public HSSFPalette getCustomPalette() - { - return new HSSFPalette(workbook.getCustomPalette()); - } - /** - * Copies nodes from one POIFS to the other minus the excepts - * @param source is the source POIFS to copy from - * @param target is the target POIFS to copy to - * @param excepts is a list of Strings specifying what nodes NOT to copy - */ - private void copyNodes(POIFSFileSystem source, POIFSFileSystem target, - List excepts) throws IOException { - //System.err.println("CopyNodes called"); - - DirectoryEntry root = source.getRoot(); - DirectoryEntry newRoot = target.getRoot(); - - Iterator entries = root.getEntries(); - - while (entries.hasNext()) { - Entry entry = (Entry)entries.next(); - if (!isInList(entry.getName(), excepts)) { - copyNodeRecursively(entry,newRoot); - } - } - } - - private boolean isInList(String entry, List list) { - for (int k = 0; k < list.size(); k++) { - if (list.get(k).equals(entry)) { - return true; - } - } - return false; - } - - private void copyNodeRecursively(Entry entry, DirectoryEntry target) - throws IOException { - //System.err.println("copyNodeRecursively called with "+entry.getName()+ - // ","+target.getName()); - DirectoryEntry newTarget = null; - if (entry.isDirectoryEntry()) { - newTarget = target.createDirectory(entry.getName()); - Iterator entries = ((DirectoryEntry)entry).getEntries(); - - while (entries.hasNext()) { - copyNodeRecursively((Entry)entries.next(),newTarget); - } - } else { - DocumentEntry dentry = (DocumentEntry)entry; - DocumentInputStream dstream = new DocumentInputStream(dentry); - target.createDocument(dentry.getName(),dstream); - dstream.close(); - } - } - - public void insertChartRecord() - { - int loc = workbook.findFirstRecordLocBySid(SSTRecord.sid); - byte[] data = { - (byte)0x0F, (byte)0x00, (byte)0x00, (byte)0xF0, (byte)0x52, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x06, (byte)0xF0, (byte)0x18, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x01, (byte)0x08, (byte)0x00, (byte)0x00, - (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x02, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x03, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x33, (byte)0x00, (byte)0x0B, (byte)0xF0, (byte)0x12, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0xBF, (byte)0x00, - (byte)0x08, (byte)0x00, (byte)0x08, (byte)0x00, (byte)0x81, - (byte)0x01, (byte)0x09, (byte)0x00, (byte)0x00, (byte)0x08, - (byte)0xC0, (byte)0x01, (byte)0x40, (byte)0x00, (byte)0x00, - (byte)0x08, (byte)0x40, (byte)0x00, (byte)0x1E, (byte)0xF1, - (byte)0x10, (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x0D, - (byte)0x00, (byte)0x00, (byte)0x08, (byte)0x0C, (byte)0x00, - (byte)0x00, (byte)0x08, (byte)0x17, (byte)0x00, (byte)0x00, - (byte)0x08, (byte)0xF7, (byte)0x00, (byte)0x00, (byte)0x10, - }; - UnknownRecord r = new UnknownRecord((short)0x00EB,(short)0x005a, data); - workbook.getRecords().add(loc, r); - } - } diff --git a/src/java/org/apache/poi/util/IntList.java b/src/java/org/apache/poi/util/IntList.java index 79e7a6bbb..814df512d 100644 --- a/src/java/org/apache/poi/util/IntList.java +++ b/src/java/org/apache/poi/util/IntList.java @@ -88,6 +88,7 @@ public class IntList { private int[] _array; private int _limit; + private int fillval = 0; private static final int _default_size = 128; /** @@ -97,8 +98,14 @@ public class IntList public IntList() { this(_default_size); - } + } + public IntList(final int initialCapacity) + { + this(initialCapacity,0); + } + + /** * create a copy of an existing IntList * @@ -118,12 +125,22 @@ public class IntList * @param initialCapacity the size for the internal array */ - public IntList(final int initialCapacity) + public IntList(final int initialCapacity, int fillvalue) { _array = new int[ initialCapacity ]; + if (fillval != 0) { + fillval = fillvalue; + fillArray(fillval, _array, 0); + } _limit = 0; } + private void fillArray(int val, int[] array, int index) { + for (int k = index; k < array.length; k++) { + array[k] = val; + } + } + /** * add the specfied value at the specified index * @@ -519,7 +536,9 @@ public class IntList { if (o == _array[ j ]) { - System.arraycopy(_array, j + 1, _array, j, _limit - j); + if (j+1 < _limit) { + System.arraycopy(_array, j + 1, _array, j, _limit - j); + } _limit--; rval = true; } @@ -670,7 +689,11 @@ public class IntList int size = (new_size == _array.length) ? new_size + 1 : new_size; int[] new_array = new int[ size ]; - + + if (fillval != 0) { + fillArray(fillval, new_array, _array.length); + } + System.arraycopy(_array, 0, new_array, 0, _limit); _array = new_array; } diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java index 27aa0e24f..5ce12b461 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java @@ -56,7 +56,6 @@ package org.apache.poi.hssf.usermodel; import junit.framework.TestCase; import org.apache.poi.hssf.model.Sheet; -import org.apache.poi.hssf.record.HCenterRecord; import org.apache.poi.hssf.record.VCenterRecord; import org.apache.poi.hssf.record.WSBoolRecord; @@ -116,26 +115,6 @@ public class TestHSSFSheet // wb.write(new FileOutputStream("c:\\test.xls")); } - /** - * Test horizontally centered output. - */ - - public void testHorizontallyCenter() - throws Exception - { - HSSFWorkbook wb = new HSSFWorkbook(); - HSSFSheet s = wb.createSheet(); - Sheet sheet = s.getSheet(); - HCenterRecord record = - (HCenterRecord) sheet.findFirstRecordBySid(HCenterRecord.sid); - - assertEquals(false, record.getHCenter()); - s.setHorizontallyCenter(true); - assertEquals(true, record.getHCenter()); - - } - - /** * Test WSBboolRecord fields get set in the user model. */ @@ -236,86 +215,4 @@ public class TestHSSFSheet assertEquals(cloned.getRow((short)0).getCell((short)0).getStringCellValue(), "clone_test"); } - /** - * Tests the shiftRows function. Does three different shifts. - * After each shift, writes the workbook to file and reads back to - * check. This ensures that if some changes code that breaks - * writing or what not, they realize it. - * - * Shawn Laubach (slaubach at apache dot org) - */ - public void testShiftRows() throws Exception - { - // Read initial file in - String filename = System.getProperty( "HSSF.testdata.path" ); - filename = filename + "/SimpleMultiCell.xls"; - FileInputStream fin = new FileInputStream( filename ); - HSSFWorkbook wb = new HSSFWorkbook( fin ); - fin.close(); - HSSFSheet s = wb.getSheetAt( 0 ); - - // Shift the second row down 1 and write to temp file - s.shiftRows( 1, 1, 1 ); - File tempFile = File.createTempFile( "shift", "test.xls" ); - FileOutputStream fout = new FileOutputStream( tempFile ); - wb.write( fout ); - fout.close(); - - // Read from temp file and check the number of cells in each - // row (in original file each row was unique) - fin = new FileInputStream( tempFile ); - wb = new HSSFWorkbook( fin ); - fin.close(); - s = wb.getSheetAt( 0 ); - - assertEquals( s.getRow( 0 ).getPhysicalNumberOfCells(), 1 ); - assertTrue( s.getRow( 1 ) == null || s.getRow( 1 ).getPhysicalNumberOfCells() == 0 ); - assertEquals( s.getRow( 2 ).getPhysicalNumberOfCells(), 2 ); - assertEquals( s.getRow( 3 ).getPhysicalNumberOfCells(), 4 ); - assertEquals( s.getRow( 4 ).getPhysicalNumberOfCells(), 5 ); - - // Shift rows 1-3 down 3 in the current one. This tests when - // 1 row is blank. Write to a another temp file - s.shiftRows( 0, 2, 3 ); - tempFile = File.createTempFile( "shift", "test.xls" ); - fout = new FileOutputStream( tempFile ); - wb.write( fout ); - fout.close(); - - // Read and ensure things are where they should be - fin = new FileInputStream( tempFile ); - wb = new HSSFWorkbook( fin ); - fin.close(); - s = wb.getSheetAt( 0 ); - assertTrue( s.getRow( 0 ) == null || s.getRow( 0 ).getPhysicalNumberOfCells() == 0 ); - assertTrue( s.getRow( 1 ) == null || s.getRow( 1 ).getPhysicalNumberOfCells() == 0 ); - assertTrue( s.getRow( 2 ) == null || s.getRow( 2 ).getPhysicalNumberOfCells() == 0 ); - assertEquals( s.getRow( 3 ).getPhysicalNumberOfCells(), 1 ); - assertTrue( s.getRow( 4 ) == null || s.getRow( 4 ).getPhysicalNumberOfCells() == 0 ); - assertEquals( s.getRow( 5 ).getPhysicalNumberOfCells(), 2 ); - - // Read the first file again - fin = new FileInputStream( filename ); - wb = new HSSFWorkbook( fin ); - fin.close(); - s = wb.getSheetAt( 0 ); - - // Shift rows 3 and 4 up and write to temp file - s.shiftRows( 2, 3, -2 ); - tempFile = File.createTempFile( "shift", "test.xls" ); - fout = new FileOutputStream( tempFile ); - wb.write( fout ); - fout.close(); - - // Read file and test - fin = new FileInputStream( tempFile ); - wb = new HSSFWorkbook( fin ); - fin.close(); - s = wb.getSheetAt( 0 ); - assertEquals( s.getRow( 0 ).getPhysicalNumberOfCells(), 3 ); - assertEquals( s.getRow( 1 ).getPhysicalNumberOfCells(), 4 ); - assertTrue( s.getRow( 2 ) == null || s.getRow( 2 ).getPhysicalNumberOfCells() == 0 ); - assertTrue( s.getRow( 3 ) == null || s.getRow( 3 ).getPhysicalNumberOfCells() == 0 ); - assertEquals( s.getRow( 4 ).getPhysicalNumberOfCells(), 5 ); - } }