From 7081acbc742cb155dd851336248adf4ce8cdd2a4 Mon Sep 17 00:00:00 2001 From: Glen Stampoultzis Date: Sun, 18 Apr 2004 13:02:48 +0000 Subject: [PATCH] Some fixes to the branch. Lots left to do. Boolean records aren't supported at all. Empty spreadsheets have issues but this is a start on getting things healthy again. git-svn-id: https://svn.apache.org/repos/asf/jakarta/poi/trunk@353549 13f79535-47bb-0310-9956-ffa450edef68 --- .cvsignore | 1 + build.xml | 4 + src/java/org/apache/poi/hssf/model/Sheet.java | 2 +- .../aggregates/ValueRecordsAggregate.java | 346 +++++++++++------- .../apache/poi/hssf/usermodel/HSSFCell.java | 14 +- .../org/apache/poi/util/DoubleList2d.java | 58 +++ src/java/org/apache/poi/util/IntList2d.java | 72 ++++ src/java/org/apache/poi/util/List2d.java | 58 +++ .../aggregates/TestValueRecordsAggregate.java | 27 +- .../poi/hssf/usermodel/TestHSSFSheet.java | 1 + .../org/apache/poi/util/TestDoubleList2d.java | 34 ++ .../org/apache/poi/util/TestIntList2d.java | 38 ++ .../org/apache/poi/util/TestList2d.java | 37 ++ 13 files changed, 530 insertions(+), 162 deletions(-) create mode 100644 src/java/org/apache/poi/util/DoubleList2d.java create mode 100644 src/java/org/apache/poi/util/IntList2d.java create mode 100644 src/java/org/apache/poi/util/List2d.java create mode 100644 src/testcases/org/apache/poi/util/TestDoubleList2d.java create mode 100644 src/testcases/org/apache/poi/util/TestIntList2d.java create mode 100644 src/testcases/org/apache/poi/util/TestList2d.java diff --git a/.cvsignore b/.cvsignore index 9a736c2485..ed472945e6 100644 --- a/.cvsignore +++ b/.cvsignore @@ -10,3 +10,4 @@ log*.* build .classpath .project +workbook.xls diff --git a/build.xml b/build.xml index 400e6f799b..8469460180 100644 --- a/build.xml +++ b/build.xml @@ -91,6 +91,7 @@ + @@ -216,6 +217,9 @@ Main targets: + + + diff --git a/src/java/org/apache/poi/hssf/model/Sheet.java b/src/java/org/apache/poi/hssf/model/Sheet.java index 535c542b04..7d2e95468d 100644 --- a/src/java/org/apache/poi/hssf/model/Sheet.java +++ b/src/java/org/apache/poi/hssf/model/Sheet.java @@ -398,8 +398,8 @@ public class Sheet implements Model (DefaultColWidthRecord) retval.createDefaultColWidth(); records.add( retval.defaultcolwidth); retval.dims = ( DimensionsRecord ) retval.createDimensions(); - retval.dimsloc = records.size()-1; records.add(retval.dims); + retval.dimsloc = records.size()-1; records.add(retval.windowTwo = retval.createWindowTwo()); retval.setLoc(records.size() - 1); retval.selection = 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 a11884edb6..8893f96dc0 100644 --- a/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java +++ b/src/java/org/apache/poi/hssf/record/aggregates/ValueRecordsAggregate.java @@ -18,16 +18,16 @@ 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.hssf.usermodel.HSSFCell; +import org.apache.poi.util.DoubleList2d; import org.apache.poi.util.IntList; +import org.apache.poi.util.IntList2d; +import org.apache.poi.util.List2d; import java.util.Iterator; import java.util.List; -import java.util.ArrayList; /** * @@ -42,29 +42,23 @@ public class ValueRecordsAggregate extends Record { public final static short sid = -1000; - int firstcell = -1; - int lastcell = -1; - //TreeMap records = null; private final static int DEFAULT_ROWS=10000; private final static int DEFAULT_COLS=256; - List celltype = null; //array of HSSFCEll.CELL_TYPE_XXX tells us which arrays to use - List xfs = null; // array of style types. Index of XF record - List numericcells = null; // numeric and Shared string indicies. - List formulaptgs = null; // array of arrays of PTGS - List stringvals = null; // array of actual string/formula string vals - IntList populatedRows = null; //indicies of populated rows - int physCells; //physical number of cells + IntList2d celltype = null; + IntList2d xfs = null; // array of style types. Index of XF record + DoubleList2d numericcells = null; // numeric and Shared string indicies. + List2d formulaptgs = null; // array of arrays of FormulaRecordAggregate + List2d stringvals = null; // array of actual string/formula string vals + IntList populatedRows = null; //indicies of populated rows + int physCells; //physical number of cells public CellValueRecordInterface getCell(int row, short col) { return constructRecord(row, col); - } public int getRecordSize() { - //throw new RuntimeException("Not Implemented getRecordSize"); - int size = 0; Iterator irecs = getIterator(); @@ -73,7 +67,6 @@ public class ValueRecordsAggregate } return size; -// return size; } public int serialize(int offset, byte [] data) @@ -82,13 +75,13 @@ public class ValueRecordsAggregate } 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; + celltype = new IntList2d(); + xfs = new IntList2d(); + numericcells = new DoubleList2d(); + formulaptgs = new List2d(); + stringvals = new List2d(); + populatedRows = new IntList(); + physCells = 0; } public Iterator getIterator() { @@ -119,11 +112,19 @@ public class ValueRecordsAggregate } /** Returns true if the row has cells attached to it */ - public boolean rowHasCells(int row) { - if (row >= celltype.size()) + public boolean rowHasCells(int row) + { + if (row == -1) + return false; + + int col = 0; + while (celltype.isAllocated( col, row)) + { + if (celltype.get( col, row ) != 0) + return true; + col++; + } return false; - IntList ctRow = (IntList) celltype.get(row); - return ((ctRow != null) && (ctRow.size() > 0)); } /** Serializes the cells that are allocated to a certain row range*/ @@ -144,7 +145,7 @@ public class ValueRecordsAggregate public int construct(int offset, List records) { - int k = 0; + int k; FormulaRecordAggregate lastFormulaAggregate = null; @@ -183,7 +184,6 @@ public class ValueRecordsAggregate public int getPhysicalNumberOfCellsInRow(int row) { int count = -1; int col = -1; - boolean firsttime = true; while (col > 0 || count == -1) { col = findNextPopulatedCell(row,col); @@ -193,11 +193,11 @@ public class ValueRecordsAggregate } public void setValue(int row, short cell, double val) { - ((DoubleList)numericcells.get(row)).set(cell, val); + numericcells.set(cell, row, val); } public void setStyle(int row, short cell, short xf) { - ((IntList)xfs.get(row)).set(cell, xf); + xfs.set(cell, row, xf); } @@ -214,101 +214,100 @@ public class ValueRecordsAggregate } public void removeCell(CellValueRecordInterface cell) { + if (cell == null) + return; + 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); - } + if (celltype.get( colnum, rownum ) != 0) + { + celltype.set( colnum, rownum, 0 ); + if (rowHasCells( rownum )) + populatedRows.removeValue( populatedRows.indexOf( rownum ) ); physCells--; - } else { - //this cell doesn't exist... - throw new RuntimeException("Tried to remove a cell that does not exist r,c="+rownum+","+colnum); + } + else + { + //this cell doesn't exist... the old code falls through so lets make this fall through too. } } - public void insertCell(CellValueRecordInterface cell) { + 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) { + if (!populatedRows.contains( rownum )) + { populatedRows.add(rownum); //this means we must never have had this row inserted } - ensureRows(rownum); +// ensureRows(rownum); - IntList ctRow = (IntList)celltype.get(rownum); - IntList xfRow = (IntList)xfs.get(rownum); +// IntList ctRow = (IntList)celltype.get(rownum); +// IntList xfRow = (IntList)xfs.get(rownum); +// adjustIntList(ctRow, colnum+1); +// adjustIntList(xfRow, colnum+1); - adjustIntList(ctRow, colnum+1); - adjustIntList(xfRow, colnum+1); - - ctRow.set(colnum, type); - xfRow.set(colnum, xf); + celltype.set(colnum, rownum, type); + xfs.set( colnum, rownum, 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); + if (celltype.get( col, row) == 0) + throw new ArrayIndexOutOfBoundsException("No cell at position col" + col + ", row " + row + "."); +// 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; + int type = celltype.get( col, row ); 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)); + nrecord.setValue( numericcells.get( col, row)); + nrecord.setXFIndex((short)xfs.get( col, row )); +// 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)); + srecord.setSSTIndex((int) numericcells.get( col, row)); + srecord.setXFIndex((short)xfs.get( col, row )); 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)); + brecord.setXFIndex((short)xfs.get( col, row )); 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)); + fr.setXFIndex((short)xfs.get( col, row )); StringRecord st = null; - String strval = (String)((List)stringvals.get(row)).get(col); - List expressionlist = (List)((List)formulaptgs.get(row)).get(col); + String strval = (String)stringvals.get( col, row ); + List expressionlist = (List) formulaptgs.get( col, row); fr.setParsedExpression(expressionlist); fr.setExpressionLength(calculatePtgSize(expressionlist)); if (strval != null) { @@ -319,7 +318,9 @@ public class ValueRecordsAggregate retval= frarecord; break; - + */ + retval = (CellValueRecordInterface) formulaptgs.get( col, row ); + break; default: throw new RuntimeException("UnImplemented Celltype "+type); } @@ -327,7 +328,8 @@ public class ValueRecordsAggregate return retval; } - private short calculatePtgSize(List expressionlist) { + private short calculatePtgSize(List expressionlist) + { short retval = 0; Iterator iter = expressionlist.iterator(); while (iter.hasNext()) { @@ -336,42 +338,49 @@ public class ValueRecordsAggregate return retval; } - private void insertCell(CellValueRecordInterface cell, int type) { + private void insertCell(CellValueRecordInterface cell, int type) + { int rownum = cell.getRow(); int colnum = cell.getColumn(); - DoubleList nmRow = (DoubleList)numericcells.get(rownum); +// 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()); +// adjustDoubleList(nmRow, colnum+1); + numericcells.set(colnum, rownum, nrecord.getValue()); physCells++; break; case HSSFCell.CELL_TYPE_STRING: LabelSSTRecord srecord = (LabelSSTRecord)cell; - adjustDoubleList(nmRow, colnum+1); - nmRow.set(colnum,srecord.getSSTIndex()); +// adjustDoubleList(nmRow, colnum+1); + numericcells.set(colnum, rownum, srecord.getSSTIndex()); +// 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); - } + formulaptgs.set( colnum, rownum, frarecord); physCells++; break; + /* +// 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); + numericcells.set(colnum, rownum, frarecord.getFormulaRecord().getValue()); + formulaptgs.set( colnum, rownum, frarecord.getFormulaRecord().getParsedExpression() ); + StringRecord str = frarecord.getStringRecord(); + if ( str != null ) + stringvals.set( colnum, rownum, str.getString() ); + else + stringvals.set( colnum, rownum, null ); + physCells++; + break; + */ case HSSFCell.CELL_TYPE_BLANK: //BlankRecord brecord = (BlankRecord)cell; physCells++; @@ -418,52 +427,67 @@ public class ValueRecordsAggregate return retval; } - 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); +// 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); - } +// } - 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"); - } - } - } +// 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"); +// } +// } +// } - private void adjustIntList(IntList list, int size) { - while (list.size() < size) { - list.add(-1); - } - } - - 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()); - } - } +// private void adjustIntList(IntList list, int size) { +// while (list.size() < size) { +// list.add(-1); +// } +// } +// +// 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()); +// } +// } + /** + * Find the next populated cell in the row starting from but not + * including the current column + * + * @return the next valid column number + */ protected int findNextPopulatedCell(int row, int col) { + int currentCol = col + 1; + while (celltype.isAllocated( currentCol, row )) + { + if (celltype.get( currentCol, row) > 0) + return currentCol; + currentCol++; + } + return -1; + + /* IntList ctRow = (IntList) celltype.get(row); int retval = -1; if (ctRow.size() > col+1) { @@ -483,6 +507,7 @@ public class ValueRecordsAggregate } //end if (ctRow.size()... return retval; + */ } @@ -509,7 +534,6 @@ class VRAIterator implements Iterator { private int popindex; private int row; private int rowlimit; - private int col; CellValueRecordInterface current = null; CellValueRecordInterface next = null; @@ -527,7 +551,32 @@ class VRAIterator implements Iterator { this.rowlimit = endRow; this.popindex = vra.populatedRows.indexOf(row); if (this.popindex == -1) { - hasNext = false; + if (vra.populatedRows.size() == 0) + hasNext = false; + else + { + int lastRow = vra.populatedRows.get(vra.populatedRows.size()-1); + if (lastRow == -1) + { + hasNext = false; + } + else + { + for (int i = row; i <= lastRow; i++) + { + this.popindex = vra.populatedRows.indexOf(i); + if (popindex != -1) + break; + } + } + if (popindex == -1) + hasNext = false; + else + { + next = findNextCell(null); + hasNext = (next != null); + } + } } else if (vra.getPhysicalNumberOfCells() > 0) { next = findNextCell(null); hasNext = (next != null); @@ -553,7 +602,7 @@ class VRAIterator implements Iterator { } private CellValueRecordInterface findNextCell(CellValueRecordInterface current) { - IntList ctRow = null; +// IntList ctRow = null; int rowNum = -1; int colNum = -1; int newCol = -1; @@ -563,11 +612,24 @@ class VRAIterator implements Iterator { wasntFirst = true; rowNum = current.getRow(); colNum = current.getColumn(); - ctRow = ((IntList)vra.celltype.get(rowNum)); +// 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) { + while (!vra.rowHasCells( rowNum ) && vra.populatedRows.size() > popindex) { + if (wasntFirst == true) { + throw new RuntimeException("CANT HAPPEN WASNTFIRST BUT WE'RE FASTFORWARDING!"); + } + rowNum = vra.populatedRows.get(popindex); + if (!vra.rowHasCells( rowNum )) { + if ((rowlimit == -1)||(rowNum<=rowlimit)) { + popindex++; + } else { + this.hasNext = false; + } + } + } + /*while ((ctRow == null || ctRow.size() == 0) && vra.populatedRows.size() > popindex) { if (wasntFirst == true) { throw new RuntimeException("CANT HAPPEN WASNTFIRST BUT WE'RE FASTFORWARDING!"); } @@ -580,7 +642,7 @@ class VRAIterator implements Iterator { this.hasNext = false; } } - } + } */ if (rowNum == -1) { return null; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java index 9d1d6b83cc..f4969763dc 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFCell.java @@ -71,7 +71,7 @@ public class HSSFCell * @see #getCellType() */ - public final static int CELL_TYPE_NUMERIC = 0; + public final static int CELL_TYPE_NUMERIC = 1; /** * String Cell type (1) @@ -79,7 +79,7 @@ public class HSSFCell * @see #getCellType() */ - public final static int CELL_TYPE_STRING = 1; + public final static int CELL_TYPE_STRING = 2; /** * Formula Cell type (2) @@ -87,7 +87,7 @@ public class HSSFCell * @see #getCellType() */ - public final static int CELL_TYPE_FORMULA = 2; + public final static int CELL_TYPE_FORMULA = 3; /** * Blank Cell type (3) @@ -95,7 +95,7 @@ public class HSSFCell * @see #getCellType() */ - public final static int CELL_TYPE_BLANK = 3; + public final static int CELL_TYPE_BLANK = 4; /** * Boolean Cell type (4) @@ -103,7 +103,7 @@ public class HSSFCell * @see #getCellType() */ - public final static int CELL_TYPE_BOOLEAN = 4; + public final static int CELL_TYPE_BOOLEAN = 5; /** * Error Cell type (5) @@ -111,9 +111,11 @@ public class HSSFCell * @see #getCellType() */ - public final static int CELL_TYPE_ERROR = 5; + public final static int CELL_TYPE_ERROR = 6; + public final static short ENCODING_COMPRESSED_UNICODE = 0; public final static short ENCODING_UTF_16 = 1; + private short cellNum; private int cellType; private HSSFCellStyle cellStyle; diff --git a/src/java/org/apache/poi/util/DoubleList2d.java b/src/java/org/apache/poi/util/DoubleList2d.java new file mode 100644 index 0000000000..3b17fe5322 --- /dev/null +++ b/src/java/org/apache/poi/util/DoubleList2d.java @@ -0,0 +1,58 @@ +package org.apache.poi.util; + +import java.util.List; +import java.util.ArrayList; + +/** + * Provides an interface for interacting with 2d arrays of doubles. This + * implementation will return 0 for items not yet allocated and automatically + * increase the array size for set operations. You never get an index out of + * bounds. + * + * @author Glen Stampoultzis (glens at apache.org) + * @version $Id$ + */ +public class DoubleList2d +{ + // Implemented using a List of DoubleList's. + List rows = new ArrayList(); + + public double get(int col, int row) + { + if (row >= rows.size()) + { + return 0; + } + else + { + DoubleList cols = (DoubleList) rows.get(row); + if (col >= cols.size()) + return 0; + else + return cols.get( col ); + } + } + + public void set(int col, int row, double value) + { + resizeRows(row); + resizeCols(row,col); + DoubleList cols = (DoubleList) rows.get( row ); + cols.set( col, value ); + } + + private void resizeRows( int row ) + { + while (rows.size() <= row) + rows.add( new DoubleList() ); + } + + private void resizeCols( int row, int col ) + { + DoubleList cols = (DoubleList) rows.get( row ); + while (cols.size() <= col) + cols.add(0); + } + + +} diff --git a/src/java/org/apache/poi/util/IntList2d.java b/src/java/org/apache/poi/util/IntList2d.java new file mode 100644 index 0000000000..fb2b03cebb --- /dev/null +++ b/src/java/org/apache/poi/util/IntList2d.java @@ -0,0 +1,72 @@ +package org.apache.poi.util; + +import java.util.List; +import java.util.ArrayList; + +/** + * Provides an interface for interacting with 2d arrays of integers. This + * implementation will return 0 for items not yet allocated and automatically + * increase the array size for set operations. You never get an index out of + * bounds. + * + * @author Glen Stampoultzis (glens at apache.org) + * @version $Id$ + */ +public class IntList2d +{ + // Implemented using a List of IntList's. + List rows = new ArrayList(); + + public int get(int col, int row) + { + if (row >= rows.size()) + { + return 0; + } + else + { + IntList cols = (IntList) rows.get(row); + if (col >= cols.size()) + return 0; + else + return cols.get( col ); + } + } + + public void set(int col, int row, int value) + { + resizeRows(row); + resizeCols(row,col); + IntList cols = (IntList) rows.get( row ); + cols.set( col, value ); + } + + private void resizeRows( int row ) + { + while (rows.size() <= row) + rows.add( new IntList() ); + } + + private void resizeCols( int row, int col ) + { + IntList cols = (IntList) rows.get( row ); + while (cols.size() <= col) + cols.add(0); + } + + public boolean isAllocated( int col, int row ) + { + if (row < rows.size()) + { + IntList cols = (IntList) rows.get( row ); + return ( col < cols.size() ); + } + else + { + return false; + } + } + + + +} diff --git a/src/java/org/apache/poi/util/List2d.java b/src/java/org/apache/poi/util/List2d.java new file mode 100644 index 0000000000..dd9059a623 --- /dev/null +++ b/src/java/org/apache/poi/util/List2d.java @@ -0,0 +1,58 @@ +package org.apache.poi.util; + +import java.util.List; +import java.util.ArrayList; + +/** + * Provides an interface for interacting with 2d arrays of objects. This + * implementation will return null for items not yet allocated and automatically + * increase the array size for set operations. You never get an index out of + * bounds. + * + * @author Glen Stampoultzis (glens at apache.org) + * @version $Id$ + */ +public class List2d +{ + // Implemented using a List of List's. + List rows = new ArrayList(); + + public Object get(int col, int row) + { + if (row >= rows.size()) + { + return null; + } + else + { + List cols = (List) rows.get(row); + if (col >= cols.size()) + return null; + else + return cols.get( col ); + } + } + + public void set(int col, int row, Object value) + { + resizeRows(row); + resizeCols(row,col); + List cols = (List) rows.get( row ); + cols.set( col, value ); + } + + private void resizeRows( int row ) + { + while (rows.size() <= row) + rows.add( new ArrayList() ); + } + + private void resizeCols( int row, int col ) + { + List cols = (List) rows.get( row ); + while (cols.size() <= col) + cols.add(null); + } + + +} diff --git a/src/testcases/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java b/src/testcases/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java index db52f114cd..ece8d5dc84 100755 --- a/src/testcases/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java +++ b/src/testcases/org/apache/poi/hssf/record/aggregates/TestValueRecordsAggregate.java @@ -144,27 +144,28 @@ public class TestValueRecordsAggregate extends TestCase // // } - public void testSerialize() throws Exception + public void testSerializeCellRow() throws Exception { byte[] actualArray = new byte[36]; byte[] expectedArray = new byte[] { - (byte)0x06, (byte)0x00, (byte)0x16, (byte)0x00, - (byte)0x01, (byte)0x00, (byte)0x01, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x00, (byte)0x00, - (byte)0x00, (byte)0x00, (byte)0x01, (byte)0x02, - (byte)0x06, (byte)0x00, (byte)0x02, (byte)0x00, - (byte)0x02, (byte)0x00, (byte)0x00, (byte)0x00, + (byte)0x06,(byte)0x00,(byte)0x16,(byte)0x00, + (byte)0x01,(byte)0x00,(byte)0x01,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + (byte)0x00,(byte)0x00,(byte)0x00,(byte)0x00, + }; List records = testData(); valueRecord.construct( 0, records ); - int bytesWritten = valueRecord.serialize( 0, actualArray ); - assertEquals( 36, bytesWritten ); + int bytesWritten = valueRecord.serializeCellRow( 1, 0, actualArray ); + assertEquals( 26, bytesWritten ); for (int i = 0; i < 36; i++) - assertEquals( expectedArray[i], actualArray[i] ); + assertEquals( "wrong value at offset " + i, expectedArray[i], actualArray[i] ); } public static void main( String[] args ) diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java index 6044ae577f..572c16aa3d 100644 --- a/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java +++ b/src/testcases/org/apache/poi/hssf/usermodel/TestHSSFSheet.java @@ -169,6 +169,7 @@ public class TestHSSFSheet FileOutputStream stream = new FileOutputStream(tempFile); workbook.write(stream); stream.close(); + System.out.println( "tempFile.getCanonicalPath() = " + tempFile.getCanonicalPath() ); FileInputStream readStream = new FileInputStream(tempFile); workbook = new HSSFWorkbook(readStream); diff --git a/src/testcases/org/apache/poi/util/TestDoubleList2d.java b/src/testcases/org/apache/poi/util/TestDoubleList2d.java new file mode 100644 index 0000000000..5b0dcaa1cc --- /dev/null +++ b/src/testcases/org/apache/poi/util/TestDoubleList2d.java @@ -0,0 +1,34 @@ +package org.apache.poi.util; + +import junit.framework.TestCase; + +/** + * @version $Id$ + */ +public class TestDoubleList2d + extends TestCase +{ + public void testAccess() + throws Exception + { + DoubleList2d array = new DoubleList2d(); + assertEquals( 0, array.get( 0, 0 ), 0.00001 ); + assertEquals( 0, array.get( 1, 1 ), 0.00001 ); + assertEquals( 0, array.get( 100, 100 ), 0.00001 ); + array.set( 100, 100, 999 ); + assertEquals( 999, array.get( 100, 100 ), 0.00001 ); + assertEquals( 0, array.get( 0, 0 ), 0.00001 ); + array.set( 0, 0, 999 ); + assertEquals( 999, array.get( 0, 0 ), 0.00001 ); + + try + { + array.get( -1, -1 ); + fail(); + } + catch ( ArrayIndexOutOfBoundsException e ) + { + // pass + } + } +} diff --git a/src/testcases/org/apache/poi/util/TestIntList2d.java b/src/testcases/org/apache/poi/util/TestIntList2d.java new file mode 100644 index 0000000000..7c1bc65ad0 --- /dev/null +++ b/src/testcases/org/apache/poi/util/TestIntList2d.java @@ -0,0 +1,38 @@ +package org.apache.poi.util; + +import junit.framework.TestCase; + +/** + * @version $Id$ + */ +public class TestIntList2d + extends TestCase +{ + public void testAccess() + throws Exception + { + IntList2d array = new IntList2d(); + assertEquals( 0, array.get( 0, 0 ) ); + assertEquals( 0, array.get( 1, 1 ) ); + assertEquals( 0, array.get( 100, 100 ) ); + array.set( 100, 100, 999 ); + assertEquals( 999, array.get( 100, 100 ) ); + assertEquals( 0, array.get( 0, 0 ) ); + array.set( 0, 0, 999 ); + assertEquals( 999, array.get( 0, 0 ) ); + + assertTrue(array.isAllocated( 0, 0 ) ); + assertTrue(array.isAllocated( 100, 100 ) ); + assertFalse(array.isAllocated( 200, 200 ) ); + + try + { + assertEquals( 0, array.get( -1, -1 ) ); + fail(); + } + catch ( ArrayIndexOutOfBoundsException e ) + { + // pass + } + } +} diff --git a/src/testcases/org/apache/poi/util/TestList2d.java b/src/testcases/org/apache/poi/util/TestList2d.java new file mode 100644 index 0000000000..0aaf39c13b --- /dev/null +++ b/src/testcases/org/apache/poi/util/TestList2d.java @@ -0,0 +1,37 @@ +package org.apache.poi.util; + +import junit.framework.TestCase; + +/** + * @version $Id$ + */ +public class TestList2d + extends TestCase +{ + public void testAccess() + throws Exception + { + Object objectA = new Object(); + Object objectB = new Object(); + + List2d array = new List2d(); + assertNull( array.get( 0, 0 ) ); + assertNull( array.get( 1, 1 ) ); + assertNull( array.get( 100, 100 ) ); + array.set( 100, 100, objectA ); + assertSame( objectA, array.get( 100, 100 ) ); + assertNull( array.get( 0, 0 ) ); + array.set( 0, 0, objectB ); + assertSame( objectB, array.get( 0, 0 ) ); + + try + { + array.get( -1, -1 ); + fail(); + } + catch ( ArrayIndexOutOfBoundsException e ) + { + // pass + } + } +}