Browse Source

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
remotes/performance-branch@550310
Andrew C. Oliver 21 years ago
parent
commit
c5943b54ff

+ 2
- 2
src/contrib/src/org/apache/poi/hssf/usermodel/HSSFChart.java View File

@@ -139,8 +139,8 @@ public class HSSFChart



sheet.insertChartRecords( records );
workbook.insertChartRecord();
//sheet.insertChartRecords( records );
//workbook.insertChartRecord();
}

private EOFRecord createEOFRecord()

+ 134
- 172
src/java/org/apache/poi/hssf/model/Sheet.java View File

@@ -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
* <P>
* @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()

+ 117
- 212
src/java/org/apache/poi/hssf/model/Workbook.java View File

@@ -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.
* <P>
@@ -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

private static POILogger log = POILogFactory.getLogger(Workbook.class);
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);

/**
* 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;
}
}

+ 22
- 17
src/java/org/apache/poi/hssf/record/FormulaRecord.java View File

@@ -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");
}

+ 52
- 2
src/java/org/apache/poi/hssf/record/aggregates/RowRecordsAggregate.java View File

@@ -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();

+ 478
- 154
src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java View File

@@ -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,64 +82,73 @@ 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();
}
else
{
size += (( Record ) cell).getRecordSize()
- (( Record ) records.get(cell)).getRecordSize();
}*/
public int getRecordSize() {
//throw new RuntimeException("Not Implemented getRecordSize");

// XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn());
Object o = records.put(cell, cell);
int size = 0;
Iterator irecs = getIterator();

if ((cell.getColumn() < firstcell) || (firstcell == -1))
{
firstcell = cell.getColumn();
}
if ((cell.getColumn() > lastcell) || (lastcell == -1))
{
lastcell = cell.getColumn();
while (irecs.hasNext()) {
size += (( Record ) irecs.next()).getRecordSize();
}

return size;
// return size;
}

public void removeCell(CellValueRecordInterface cell)
public int serialize(int offset, byte [] data)
{
// size -= (( Record ) cell).getRecordSize();
//throw new RuntimeException("Not Implemented serialize");
int pos = offset;
Iterator irecs = getIterator();

// XYLocator xy = new XYLocator(cell.getRow(), cell.getColumn());
records.remove(cell);
}
while (irecs.hasNext()) {
pos += (( Record ) irecs.next()).serialize(pos,data);
}

public int getPhysicalNumberOfCells()
{
return records.size();
/* Iterator itr = records.values().iterator();
int pos = offset;

while (itr.hasNext())
{
pos += (( Record ) itr.next()).serialize(pos, data);
}*/
return pos - offset;
}

public int getFirstCellNum()
{
return firstcell;
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 getLastCellNum()
{
return lastcell;
public Iterator getIterator() {
return new VRAIterator(this);
}


public int construct(int offset, List records)
{
int k = 0;
@@ -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 getPhysicalNumberOfCellsInRow(int row) {
int count = -1;
int col = -1;
boolean firsttime = true;

public int serialize(int offset, byte [] data)
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;
return retval;
}
/**
* 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)
{
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);

}

/**
* 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 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");
}
}
}

protected void validateSid(short id)
{
private void adjustIntList(IntList list, int size) {
while (list.size() < size) {
list.add(-1);
}
}

/**
* return the non static version of the id for this record.
*/
private void adjustDoubleList(DoubleList list, int size) {
while (list.size() < size) {
list.add(-1);
}
}

public short getSid()
{
return sid;
private void adjustObjectList(List list, int size) {
while (list.size() < size) {
list.add(new ArrayList());
}
}

public int getRecordSize() {
int size = 0;
Iterator irecs = records.values().iterator();
while (irecs.hasNext()) {
size += (( Record ) irecs.next()).getRecordSize();
private void adjustStringList(List list, int size) {
while (list.size() < size) {
list.add(new String());
}
}

return size;
// return size;

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 Iterator getIterator()
{
return records.values().iterator();


public short getSid() {
return sid;
}

/** 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;

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);
}

}

+ 71
- 60
src/java/org/apache/poi/hssf/usermodel/HSSFCell.java View File

@@ -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);
}
}

+ 117
- 166
src/java/org/apache/poi/hssf/usermodel/HSSFSheet.java View File

@@ -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();
while (iter.hasNext())
// 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())
{
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);
}

/**
* 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);
}
}

/**
* Sets whether sheet is selected.
* @param sel Whether to select the sheet or deselect the sheet.
*/
public void setSelected( boolean sel )
{
getSheet().setSelected( sel );
}
class SheetRowIterator implements Iterator {
Iterator rows;
Workbook book;
Sheet sheet;

/**
* 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 );
public SheetRowIterator(HSSFSheet sheet, Workbook book) {
this.sheet = sheet.getSheet();
this.book = book;
rows = this.sheet.rowRecordIterator();
}

/**
* 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 );
public boolean hasNext() {
return rows.hasNext();
}

/**
* 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 );
}
}
public Object next() {
HSSFRow retval = null;
if (rows.hasNext()) {
retval = new HSSFRow(book, sheet, (RowRecord)rows.next());
}
if ( endRow == lastrow || endRow + n > lastrow ) lastrow = Math.min( endRow + n, 65535 );
if ( startRow == firstrow || startRow + n < firstrow ) firstrow = Math.max( startRow + n, 0 );
return retval;
}

protected void insertChartRecords( List records )
{
int window2Loc = sheet.findFirstRecordLocBySid( WindowTwoRecord.sid );
sheet.getRecords().addAll( window2Loc, records );
public void remove() {
rows.remove();
}


}




+ 16
- 150
src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java View File

@@ -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);
}

}

+ 27
- 4
src/java/org/apache/poi/util/IntList.java View File

@@ -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;
}

+ 0
- 103
src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java View File

@@ -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 );
}
}

Loading…
Cancel
Save