diff options
Diffstat (limited to 'src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java')
-rw-r--r-- | src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java | 349 |
1 files changed, 174 insertions, 175 deletions
diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java index d797a7dfe5..610c1f3c6d 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFRow.java @@ -17,11 +17,8 @@ package org.apache.poi.xssf.usermodel; -import java.util.Iterator; -import java.util.LinkedList; -import java.util.List; +import java.util.*; -import org.apache.poi.hssf.usermodel.HSSFCell; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell; @@ -30,28 +27,38 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTRow; /** * High level representation of a row of a spreadsheet. */ -public class XSSFRow implements Row, Comparable { +public class XSSFRow implements Row, Comparable<XSSFRow> { - private CTRow row; - - private List<Cell> cells; - - private XSSFSheet sheet; + /** + * the xml bean containing all cell definitions for this row + */ + private final CTRow row; + + /** + * Cells of this row keyed by their column indexes. + * The TreeMap ensures that the cells are ordered by columnIndex in the ascending order. + */ + private final TreeMap<Integer, Cell> cells; /** - * Create a new XSSFRow. - * - * @param row The underlying XMLBeans row. - * @param sheet The parent sheet. + * the parent sheet */ - public XSSFRow(CTRow row, XSSFSheet sheet) { + private final XSSFSheet sheet; + + /** + * Construct a XSSFRow. + * + * @param row the xml bean containing all cell definitions for this row. + * @param sheet the parent sheet. + */ + protected XSSFRow(CTRow row, XSSFSheet sheet) { this.row = row; this.sheet = sheet; - this.cells = new LinkedList<Cell>(); + this.cells = new TreeMap<Integer, Cell>(); for (CTCell c : row.getCArray()) { - this.cells.add(new XSSFCell(this, c)); + XSSFCell cell = new XSSFCell(this, c); + this.cells.put(cell.getColumnIndex(), cell); } - } /** @@ -62,25 +69,39 @@ public class XSSFRow implements Row, Comparable { public XSSFSheet getSheet() { return this.sheet; } - + /** - * @return Cell iterator of the physically defined cells. Note element 4 may - * actually be row cell depending on how many are defined! + * Cell iterator over the physically defined cells: + * <blockquote><pre> + * for (Iterator<Cell> it = row.cellIterator(); it.hasNext(); ) { + * Cell cell = it.next(); + * ... + * } + * </pre></blockquote> + * + * @return an iterator over cells in this row. */ public Iterator<Cell> cellIterator() { - return cells.iterator(); + return cells.values().iterator(); } /** - * Alias for {@link #cellIterator()} to allow - * foreach loops + * Alias for {@link #cellIterator()} to allow foreach loops: + * <blockquote><pre> + * for(Cell cell : row){ + * ... + * } + * </pre></blockquote> + * + * @return an iterator over cells in this row. */ public Iterator<Cell> iterator() { return cellIterator(); } /** - * Compares two <code>XSSFRow</code> objects. + * Compares two <code>XSSFRow</code> objects. Two rows are equal if they belong to the same worksheet and + * their row indexes are equal. * * @param row the <code>XSSFRow</code> to be compared. * @return the value <code>0</code> if the row number of this <code>XSSFRow</code> is @@ -89,84 +110,57 @@ public class XSSFRow implements Row, Comparable { * than the row number of the argument <code>XSSFRow</code>; and a value greater * than <code>0</code> if the row number of this this <code>XSSFRow</code> is numerically * greater than the row number of the argument <code>XSSFRow</code>. + * @throws IllegalArgumentException if the argument row belongs to a different worksheet */ - public int compareTo(Object row) { + public int compareTo(XSSFRow row) { int thisVal = this.getRowNum(); - int anotherVal = ((XSSFRow)row).getRowNum(); + if(row.getSheet() != getSheet()) throw new IllegalArgumentException("The compared rows must belong to the same XSSFSheet"); + + int anotherVal = row.getRowNum(); return (thisVal < anotherVal ? -1 : (thisVal == anotherVal ? 0 : 1)); } /** * Use this to create new cells within the row and return it. * <p> - * The cell that is returned is a CELL_TYPE_BLANK. The type can be changed + * The cell that is returned is a {@link Cell#CELL_TYPE_BLANK}. The type can be changed * either through calling <code>setCellValue</code> or <code>setCellType</code>. - * - * @param column - the column number this cell represents + * </p> + * @param columnIndex - the column number this cell represents * @return Cell a high level representation of the created cell. + * @throws IllegalArgumentException if columnIndex < 0 */ - public XSSFCell createCell(int column) { - return createCell(column, Cell.CELL_TYPE_BLANK); - } - - /** - * Add a new empty cell to this row. - * - * @param column Cell column number. - * @param index Position where to insert cell. - * @param type cell type, one of Cell.CELL_TYPE_* - * @return The new cell. - */ - protected XSSFCell addCell(int column, int index, int type) { - CTCell ctcell = row.insertNewC(index); - XSSFCell xcell = new XSSFCell(this, ctcell); - xcell.setCellNum(column); - if (type != Cell.CELL_TYPE_BLANK) { - xcell.setCellType(type); - } - return xcell; + public XSSFCell createCell(int columnIndex) { + return createCell(columnIndex, Cell.CELL_TYPE_BLANK); } /** * Use this to create new cells within the row and return it. * - * @param column - the column number this cell represents + * @param columnIndex - the column number this cell represents * @param type - the cell's data type - * * @return XSSFCell a high level representation of the created cell. + * @throws IllegalArgumentException if columnIndex < 0 or if the specified cell type is invalid + * @see Cell#CELL_TYPE_BLANK + * @see Cell#CELL_TYPE_BOOLEAN + * @see Cell#CELL_TYPE_ERROR + * @see Cell#CELL_TYPE_FORMULA + * @see Cell#CELL_TYPE_NUMERIC + * @see Cell#CELL_TYPE_STRING */ - public XSSFCell createCell(int column, int type) { - int index = 0; - for (Cell c : this.cells) { - if (c.getColumnIndex() == column) { - // Replace c with new Cell - XSSFCell xcell = addCell(column, index, type); - cells.set(index, xcell); - return xcell; - } - if (c.getColumnIndex() > column) { - XSSFCell xcell = addCell(column, index, type); - cells.add(index, xcell); - return xcell; - } - ++index; + public XSSFCell createCell(int columnIndex, int type) { + if(columnIndex < 0) throw new IllegalArgumentException("columnIndex must be >= 0, was " + columnIndex); + + CTCell ctcell = CTCell.Factory.newInstance(); + XSSFCell xcell = new XSSFCell(this, ctcell); + xcell.setCellNum(columnIndex); + if (type != Cell.CELL_TYPE_BLANK) { + xcell.setCellType(type); } - XSSFCell xcell = addCell(column, index, type); - cells.add(xcell); + cells.put(columnIndex, xcell); return xcell; } - private XSSFCell retrieveCell(int cellnum) { - Iterator<Cell> it = cellIterator(); - for ( ; it.hasNext() ; ) { - Cell cell = it.next(); - if (cell.getColumnIndex() == cellnum) { - return (XSSFCell)cell; - } - } - return null; - } - /** * Returns the cell at the given (0 based) index, * with the {@link MissingCellPolicy} from the parent Workbook. @@ -176,28 +170,33 @@ public class XSSFRow implements Row, Comparable { public XSSFCell getCell(int cellnum) { return getCell(cellnum, sheet.getWorkbook().getMissingCellPolicy()); } - + /** - * Returns the cell at the given (0 based) index, - * with the specified {@link MissingCellPolicy} + * Returns the cell at the given (0 based) index, with the specified {@link MissingCellPolicy} * * @return the cell at the given (0 based) index + * @throws IllegalArgumentException if cellnum < 0 or the specified MissingCellPolicy is invalid + * @see Row#RETURN_NULL_AND_BLANK + * @see Row#RETURN_BLANK_AS_NULL + * @see Row#CREATE_NULL_AS_BLANK */ public XSSFCell getCell(int cellnum, MissingCellPolicy policy) { - XSSFCell cell = retrieveCell(cellnum); + if(cellnum < 0) throw new IllegalArgumentException("Cell index must be >= 0"); + + XSSFCell cell = (XSSFCell)cells.get(cellnum); if(policy == RETURN_NULL_AND_BLANK) { return cell; } if(policy == RETURN_BLANK_AS_NULL) { if(cell == null) return cell; - if(cell.getCellType() == HSSFCell.CELL_TYPE_BLANK) { + if(cell.getCellType() == Cell.CELL_TYPE_BLANK) { return null; } return cell; } if(policy == CREATE_NULL_AS_BLANK) { if(cell == null) { - return createCell((short)cellnum, HSSFCell.CELL_TYPE_BLANK); + return createCell((short)cellnum, Cell.CELL_TYPE_BLANK); } return cell; } @@ -207,41 +206,11 @@ public class XSSFRow implements Row, Comparable { /** * Get the number of the first cell contained in this row. * - * @return short representing the first logical cell in the row, or -1 if the row does not contain any cells. + * @return short representing the first logical cell in the row, + * or -1 if the row does not contain any cells. */ public short getFirstCellNum() { - for (Iterator<Cell> it = cellIterator() ; it.hasNext() ; ) { - Cell cell = it.next(); - if (cell != null) { - return (short)cell.getColumnIndex(); - } - } - return -1; - } - - /** - * Get the row's height measured in twips (1/20th of a point). If the height is not set, the default worksheet value is returned, - * See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()} - * - * @return row height measured in twips (1/20th of a point) - */ - public short getHeight() { - return (short)(getHeightInPoints()*20); - } - - /** - * Returns row height measured in point size. If the height is not set, the default worksheet value is returned, - * See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()} - * - * @return row height measured in point size - * @see org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints() - */ - public float getHeightInPoints() { - if (this.row.isSetHt()) { - return (float) this.row.getHt(); - } else { - return sheet.getDefaultRowHeightInPoints(); - } + return (short)(cells.size() == 0 ? -1 : cells.firstKey()); } /** @@ -260,70 +229,36 @@ public class XSSFRow implements Row, Comparable { * } * </pre> * - * @return short representing the last logical cell in the row <b>PLUS ONE</b>, or -1 if the - * row does not contain any cells. + * @return short representing the last logical cell in the row <b>PLUS ONE</b>, + * or -1 if the row does not contain any cells. */ public short getLastCellNum() { - short lastCellNum = -1; - for (Iterator<Cell> it = cellIterator() ; it.hasNext() ; ) { - Cell cell = it.next(); - if (cell != null) { - lastCellNum = (short)(cell.getColumnIndex() + 1); - } - } - return lastCellNum; + return (short)(cells.size() == 0 ? -1 : (cells.lastKey() + 1)); } /** - * Gets the number of defined cells (NOT number of cells in the actual row!). - * That is to say if only columns 0,4,5 have values then there would be 3. - * - * @return int representing the number of defined cells in the row. - */ - public int getPhysicalNumberOfCells() { - int count = 0; - for (Iterator<Cell> it = cellIterator() ; it.hasNext() ; ) { - if (it.next() != null) { - count++; - } - } - return count; - } - - /** - * Get row number this row represents - * - * @return the row number (0 based) - */ - public int getRowNum() { - return (int) (row.getR() - 1); - } - - /** - * Get whether or not to display this row with 0 height + * Get the row's height measured in twips (1/20th of a point). If the height is not set, the default worksheet value is returned, + * See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()} * - * @return - height is zero or not. + * @return row height measured in twips (1/20th of a point) */ - public boolean getZeroHeight() { - return this.row.getHidden(); + public short getHeight() { + return (short)(getHeightInPoints()*20); } /** - * Remove the Cell from this row. + * Returns row height measured in point size. If the height is not set, the default worksheet value is returned, + * See {@link org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints()} * - * @param cell to remove + * @return row height measured in point size + * @see org.apache.poi.xssf.usermodel.XSSFSheet#getDefaultRowHeightInPoints() */ - public void removeCell(Cell cell) { - int counter = 0; - for (Iterator<Cell> it = cellIterator(); it.hasNext(); ) { - Cell c = it.next(); - if (c.getColumnIndex() == cell.getColumnIndex()) { - it.remove(); - row.removeC(counter); - continue; - } - counter++; - } + public float getHeightInPoints() { + if (this.row.isSetHt()) { + return (float) this.row.getHt(); + } else { + return sheet.getDefaultRowHeightInPoints(); + } } /** @@ -351,13 +286,43 @@ public class XSSFRow implements Row, Comparable { } /** + * Gets the number of defined cells (NOT number of cells in the actual row!). + * That is to say if only columns 0,4,5 have values then there would be 3. + * + * @return int representing the number of defined cells in the row. + */ + public int getPhysicalNumberOfCells() { + return cells.size(); + } + + /** + * Get row number this row represents + * + * @return the row number (0 based) + */ + public int getRowNum() { + return (int) (row.getR() - 1); + } + + /** * Set the row number of this row. * * @param rowNum the row number (0-based) + * @throws IllegalArgumentException if rowNum < 0 */ public void setRowNum(int rowNum) { + if(rowNum < 0) throw new IllegalArgumentException("Row number must be >= 0"); + this.row.setR(rowNum + 1); + } + /** + * Get whether or not to display this row with 0 height + * + * @return - height is zero or not. + */ + public boolean getZeroHeight() { + return this.row.getHidden(); } /** @@ -369,14 +334,48 @@ public class XSSFRow implements Row, Comparable { this.row.setHidden(height); } - + + /** + * Remove the Cell from this row. + * + * @param cell the cell to remove + */ + public void removeCell(Cell cell) { + cells.remove(cell.getColumnIndex()); + } + /** - * Returns the underlying CTRow xml bean representing this row + * Returns the underlying CTRow xml bean containing all cell definitions in this row * - * @return the underlying CTRow bean + * @return the underlying CTRow xml bean */ public CTRow getCTRow(){ - return this.row; + return row; } + /** + * Fired when the document is written to an output stream. + * <p> + * Attaches CTCell beans to the underlying CTRow bean + * </p> + * @see org.apache.poi.xssf.usermodel.XSSFSheet#commit() + */ + protected void onDocumentWrite(){ + ArrayList<CTCell> cArray = new ArrayList<CTCell>(cells.size()); + //create array of CTCell objects. + //TreeMap's value iterator ensures that the cells are ordered by columnIndex in the ascending order + for (Cell cell : cells.values()) { + XSSFCell c = (XSSFCell)cell; + cArray.add(c.getCTCell()); + } + row.setCArray(cArray.toArray(new CTCell[cArray.size()])); + } + + /** + * @return formatted xml representation of this row + */ + @Override + public String toString(){ + return row.toString(); + } } |