System.setProperty("poi.deserialize.escher", "true");
} else if ("--rawhex".equals(arg)) {
rawhex = true;
- } else if ("--noheader".equals(arg)) {
- noheader = true;
+ } else if ("--noheader".equals(arg)) {
+ noheader = true;
} else {
throw new CommandParseException("Unexpected option '" + arg + "'");
}
package org.apache.poi.hssf.record;
-import org.apache.poi.hssf.record.formula.AreaPtgBase;
import org.apache.poi.hssf.record.formula.Ptg;
-import org.apache.poi.hssf.record.formula.RefPtgBase;
import org.apache.poi.hssf.util.CellRangeAddress8Bit;
import org.apache.poi.ss.formula.Formula;
import org.apache.poi.util.HexDump;
* Treated in a similar way to SharedFormulaRecord
*
* @author Josh Micich
- * @author Vladimirs Abramovs(Vladimirs.Abramovs at exigenservices.com) - Array Formula support
*/
public final class ArrayRecord extends SharedValueRecordBase {
_formula = Formula.read(formulaTokenLen, in, totalFormulaLen);
}
- public ArrayRecord(Formula formula, CellRangeAddress8Bit range ) {
+ public ArrayRecord(Formula formula, CellRangeAddress8Bit range) {
super(range);
_options = 0; //YK: Excel 2007 leaves this field unset
_field3notUsed = 0;
return (_options & OPT_CALCULATE_ON_OPEN) != 0;
}
- public void setOptions(int val){
- _options = val;
- }
+ public Ptg[] getFormulaTokens() {
+ return _formula.getTokens();
+ }
- protected int getExtraDataSize() {
- return 2 + 4
- + _formula.getEncodedSize();
+ protected int getExtraDataSize() {
+ return 2 + 4 + _formula.getEncodedSize();
}
protected void serializeExtraData(LittleEndianOutput out) {
out.writeShort(_options);
sb.append("]");
return sb.toString();
}
-
- /**
- * @return the equivalent {@link Ptg} array that the formula would have,
- * were it not shared.
- */
- public Ptg[] getFormulaTokens() {
- return _formula.getTokens();
- /*
- YK: I don't understand all t
-
- int formulaRow = this.getFirstRow();
- int formulaColumn = this.getLastColumn();
-
- // Use SharedFormulaRecord static method to convert formula
-
- Ptg[] ptgs = _formula.getTokens();
-
- // Convert from relative addressing to absolute
- // because all formulas in array need to be referenced to the same
- // ref/range
- for (int i = 0; i < ptgs.length; i++) {
- Ptg ptg = ptgs[i];
- if (ptg instanceof AreaPtgBase) {
- AreaPtgBase aptg = (AreaPtgBase) ptg;
- aptg.setFirstRowRelative(false);
- aptg.setLastRowRelative(false);
- aptg.setFirstColRelative(false);
- aptg.setLastColRelative(false);
-
- } else if (ptg instanceof RefPtgBase) {
- RefPtgBase rptg = (RefPtgBase) ptg;
- rptg.setRowRelative(false);
- rptg.setColRelative(false);
- }
- }
- return SharedFormulaRecord.convertSharedFormulas(ptgs, formulaRow, formulaColumn);
- */
- }
}
}
public Ptg[] getFormulaTokens() {
- if (_sharedFormulaRecord != null) {
- return _sharedFormulaRecord.getFormulaTokens(_formulaRecord);
- }
+ if (_sharedFormulaRecord != null) {
+ return _sharedFormulaRecord.getFormulaTokens(_formulaRecord);
+ }
CellReference expRef = _formulaRecord.getFormula().getExpReference();
if (expRef != null) {
ArrayRecord arec = _sharedValueManager.getArrayRecord(expRef.getRow(), expRef.getCol());
_sharedValueManager.unlink(_sharedFormulaRecord);
}
}
+ public boolean isPartOfArrayFormula() {
+ if (_sharedFormulaRecord != null) {
+ return false;
+ }
+ return _formulaRecord.getFormula().getExpReference() != null;
+ }
- public boolean isPartOfArrayFormula() {
- if (_sharedFormulaRecord != null) {
- return false;
- }
- return _formulaRecord.getFormula().getExpReference() != null;
- }
-
- public CellRangeAddress getArrayFormulaRange() {
+ public CellRangeAddress getArrayFormulaRange() {
if (_sharedFormulaRecord != null) {
throw new IllegalStateException("not an array formula cell.");
}
throw new IllegalStateException("not an array formula cell.");
}
ArrayRecord arec = _sharedValueManager.getArrayRecord(expRef.getRow(), expRef.getCol());
- if (arec == null) {
- throw new IllegalStateException("ArrayRecord was not found for the locator " + expRef.formatAsString());
- }
+ if (arec == null) {
+ throw new IllegalStateException("ArrayRecord was not found for the locator " + expRef.formatAsString());
+ }
CellRangeAddress8Bit a = arec.getRange();
return new CellRangeAddress(a.getFirstRow(), a.getLastRow(), a.getFirstColumn(),a.getLastColumn());
}
-
- public void setArrayFormula(CellRangeAddress r, Ptg[] ptgs) {
+
+ public void setArrayFormula(CellRangeAddress r, Ptg[] ptgs) {
ArrayRecord arr = new ArrayRecord(Formula.create(ptgs), new CellRangeAddress8Bit(r.getFirstRow(), r.getLastRow(), r.getFirstColumn(), r.getLastColumn()));
_sharedValueManager.addArrayRecord(arr);
return new SharedValueManager(
new SharedFormulaRecord[0], new CellReference[0], new ArrayRecord[0], new TableRecord[0]);
}
- private final List<ArrayRecord> _arrayRecords;
+ private final List<ArrayRecord> _arrayRecords;
private final TableRecord[] _tableRecords;
private final Map<SharedFormulaRecord, SharedFormulaGroup> _groupsBySharedFormulaRecord;
/** cached for optimization purposes */
if (nShF != firstCells.length) {
throw new IllegalArgumentException("array sizes don't match: " + nShF + "!=" + firstCells.length + ".");
}
- _arrayRecords = new ArrayList<ArrayRecord>();
- _arrayRecords.addAll(Arrays.asList(arrayRecords));
+ _arrayRecords = toList(arrayRecords);
_tableRecords = tableRecords;
Map<SharedFormulaRecord, SharedFormulaGroup> m = new HashMap<SharedFormulaRecord, SharedFormulaGroup>(nShF * 3 / 2);
for (int i = 0; i < nShF; i++) {
_groupsBySharedFormulaRecord = m;
}
+ /**
+ * @return a modifiable list, independent of the supplied array
+ */
+ private static <Z> List<Z> toList(Z[] zz) {
+ List<Z> result = new ArrayList<Z>(zz.length);
+ for (int i = 0; i < zz.length; i++) {
+ result.add(zz[i]);
+ }
+ return result;
+ }
+
+ /**
+ * @param firstCells
+ * @param recs list of sheet records (possibly contains records for other parts of the Excel file)
+ * @param startIx index of first row/cell record for current sheet
+ * @param endIx one past index of last row/cell record for current sheet. It is important
+ * that this code does not inadvertently collect <tt>SharedFormulaRecord</tt>s from any other
+ * sheet (which could happen if endIx is chosen poorly). (see bug 44449)
+ */
public static SharedValueManager create(SharedFormulaRecord[] sharedFormulaRecords,
CellReference[] firstCells, ArrayRecord[] arrayRecords, TableRecord[] tableRecords) {
if (sharedFormulaRecords.length + firstCells.length + arrayRecords.length + tableRecords.length < 1) {
// The first cell will be the top left in the range. So we can match the
// ARRAY/TABLE record directly.
- for (int i = 0; i < _tableRecords.length; i++) {
- TableRecord tr = _tableRecords[i];
+ for (TableRecord tr : _tableRecords) {
if (tr.isFirstCell(row, column)) {
return tr;
}
*/
public void unlink(SharedFormulaRecord sharedFormulaRecord) {
SharedFormulaGroup svg = _groupsBySharedFormulaRecord.remove(sharedFormulaRecord);
- _groups = null; // be sure to reset cached value
if (svg == null) {
throw new IllegalStateException("Failed to find formulas for shared formula");
}
+ _groups = null; // be sure to reset cached value
svg.unlinkSharedFormulas();
}
- /**
- * Add specified Array Record.
- */
- public void addArrayRecord(ArrayRecord ar) {
- // could do a check here to make sure none of the ranges overlap
- _arrayRecords.add(ar);
- }
-
- /**
- * Removes the {@link ArrayRecord} for the cell group containing the specified cell.
- * The caller should clear (set blank) all cells in the returned range.
- * @return the range of the array formula which was just removed. Never <code>null</code>.
- */
- public CellRangeAddress8Bit removeArrayFormula(int rowIndex, int columnIndex) {
- for (ArrayRecord ar : _arrayRecords) {
- if (ar.isInRange(rowIndex, columnIndex)) {
- _arrayRecords.remove(ar);
- return ar.getRange();
- }
- }
- throw new IllegalArgumentException("Specified cell is not part of an array formula.");
- }
-
- /**
- * @return the shared ArrayRecord identified by (firstRow, firstColumn). never <code>null</code>.
- */
- public ArrayRecord getArrayRecord(int firstRow, int firstColumn) {
- for(ArrayRecord ar : _arrayRecords) {
- if(ar.isFirstCell(firstRow, firstColumn)) {
- return ar;
- }
- }
- return null;
- }
-
+ /**
+ * Add specified Array Record.
+ */
+ public void addArrayRecord(ArrayRecord ar) {
+ // could do a check here to make sure none of the ranges overlap
+ _arrayRecords.add(ar);
+ }
+
+ /**
+ * Removes the {@link ArrayRecord} for the cell group containing the specified cell.
+ * The caller should clear (set blank) all cells in the returned range.
+ * @return the range of the array formula which was just removed. Never <code>null</code>.
+ */
+ public CellRangeAddress8Bit removeArrayFormula(int rowIndex, int columnIndex) {
+ for (ArrayRecord ar : _arrayRecords) {
+ if (ar.isInRange(rowIndex, columnIndex)) {
+ _arrayRecords.remove(ar);
+ return ar.getRange();
+ }
+ }
+ String ref = new CellReference(rowIndex, columnIndex, false, false).formatAsString();
+ throw new IllegalArgumentException("Specified cell " + ref
+ + " is not part of an array formula.");
+ }
+
+ /**
+ * @return the shared ArrayRecord identified by (firstRow, firstColumn). never <code>null</code>.
+ */
+ public ArrayRecord getArrayRecord(int firstRow, int firstColumn) {
+ for(ArrayRecord ar : _arrayRecords) {
+ if(ar.isFirstCell(firstRow, firstColumn)) {
+ return ar;
+ }
+ }
+ return null;
+ }
}
import org.apache.poi.ss.usermodel.Hyperlink;
import org.apache.poi.ss.usermodel.RichTextString;
import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.util.NumberToTextConverter;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.util.POILogger;
public CellRangeAddress getArrayFormulaRange() {
if (_cellType != CELL_TYPE_FORMULA) {
String ref = new CellReference(this).formatAsString();
- throw new IllegalStateException("Cell "+ref+" is not part of an array formula");
+ throw new IllegalStateException("Cell " + ref
+ + " is not part of an array formula.");
}
return ((FormulaRecordAggregate)_record).getArrayFormulaRange();
}
import org.apache.poi.hssf.util.Region;
import org.apache.poi.ss.formula.FormulaType;
import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellRange;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Row;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.util.SSCellRange;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
* @author Shawn Laubach (slaubach at apache dot org) (Just a little)
* @author Jean-Pierre Paris (jean-pierre.paris at m4x dot org) (Just a little, too)
* @author Yegor Kozlov (yegor at apache.org) (Autosizing columns)
+ * @author Josh Micich
+ * @author Petr Udalau(Petr.Udalau at exigenservices.com) - set/remove array formulas
*/
public final class HSSFSheet implements org.apache.poi.ss.usermodel.Sheet {
private static final POILogger log = POILogFactory.getLogger(HSSFSheet.class);
*/
public void setRightToLeft(boolean value)
{
- _sheet.getWindowTwo().setArabic(value);
+ _sheet.getWindowTwo().setArabic(value);
}
/**
*/
public boolean isRightToLeft()
{
- return _sheet.getWindowTwo().getArabic();
+ return _sheet.getWindowTwo().getArabic();
}
/**
return wb.getSheetName(idx);
}
- public HSSFCell[] setArrayFormula(String formula, CellRangeAddress range) {
- HSSFCell[] cells = new HSSFCell[range.getNumberOfCells()];
- int k = 0;
-
- // make sure the formula parses OK first
- int sheetIndex = _workbook.getSheetIndex(this);
- Ptg[] ptgs = HSSFFormulaParser.parse(formula, _workbook, FormulaType.ARRAY, sheetIndex);
+ /**
+ * Also creates cells if they don't exist
+ */
+ private CellRange<HSSFCell> getCellRange(CellRangeAddress range) {
int firstRow = range.getFirstRow();
int firstColumn = range.getFirstColumn();
- for (int rowIn = firstRow; rowIn <= range.getLastRow(); rowIn++) {
- for (int colIn = firstColumn; colIn <= range.getLastColumn(); colIn++) {
+ int lastRow = range.getLastRow();
+ int lastColumn = range.getLastColumn();
+ int height = lastRow - firstRow + 1;
+ int width = lastColumn - firstColumn + 1;
+ List<HSSFCell> temp = new ArrayList<HSSFCell>(height*width);
+ for (int rowIn = firstRow; rowIn <= lastRow; rowIn++) {
+ for (int colIn = firstColumn; colIn <= lastColumn; colIn++) {
HSSFRow row = getRow(rowIn);
if (row == null) {
row = createRow(rowIn);
if (cell == null) {
cell = row.createCell(colIn);
}
- cell.setCellArrayFormula(range);
- cells[k++] = cell;
+ temp.add(cell);
}
}
- HSSFCell mainArrayFormulaCell = getRow(firstRow).getCell(firstColumn);
+ return SSCellRange.create(firstRow, firstColumn, height, width, temp, HSSFCell.class);
+ }
+
+ public CellRange<HSSFCell> setArrayFormula(String formula, CellRangeAddress range) {
+ // make sure the formula parses OK first
+ int sheetIndex = _workbook.getSheetIndex(this);
+ Ptg[] ptgs = HSSFFormulaParser.parse(formula, _workbook, FormulaType.ARRAY, sheetIndex);
+ CellRange<HSSFCell> cells = getCellRange(range);
+
+ for (HSSFCell c : cells) {
+ c.setCellArrayFormula(range);
+ }
+ HSSFCell mainArrayFormulaCell = cells.getTopLeftCell();
FormulaRecordAggregate agg = (FormulaRecordAggregate)mainArrayFormulaCell.getCellValueRecord();
agg.setArrayFormula(range, ptgs);
return cells;
}
- public HSSFCell[] removeArrayFormula(Cell cell) {
- ArrayList<HSSFCell> lst = new ArrayList<HSSFCell>();
+ public CellRange<HSSFCell> removeArrayFormula(Cell cell) {
+ if (cell.getSheet() != this) {
+ throw new IllegalArgumentException("Specified cell does not belong to this sheet.");
+ }
CellValueRecordInterface rec = ((HSSFCell) cell).getCellValueRecord();
if (!(rec instanceof FormulaRecordAggregate)) {
String ref = new CellReference(cell).formatAsString();
- throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula");
+ throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula.");
}
FormulaRecordAggregate fra = (FormulaRecordAggregate) rec;
CellRangeAddress range = fra.removeArrayFormula(cell.getRowIndex(), cell.getColumnIndex());
- if (range == null) {
- String ref = new CellReference(cell).formatAsString();
- throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula");
- }
+
+ CellRange<HSSFCell> result = getCellRange(range);
// clear all cells in the range
- for (int rowIn = range.getFirstRow(); rowIn <= range.getLastRow(); rowIn++) {
- for (int colIn = range.getFirstColumn(); colIn <= range.getLastColumn(); colIn++) {
- HSSFCell rCell = getRow(rowIn).getCell(colIn);
- rCell.setCellType(Cell.CELL_TYPE_BLANK);
- lst.add(rCell);
- }
+ for (Cell c : result) {
+ c.setCellType(Cell.CELL_TYPE_BLANK);
}
- return lst.toArray(new HSSFCell[lst.size()]);
+ return result;
}
}
case FormulaType.CELL:
rootNodeOperandClass = Ptg.CLASS_VALUE;
break;
- case FormulaType.ARRAY:
- rootNodeOperandClass = Ptg.CLASS_ARRAY;
- break;
- case FormulaType.NAMEDRANGE:
+ case FormulaType.ARRAY:
+ rootNodeOperandClass = Ptg.CLASS_ARRAY;
+ break;
+ case FormulaType.NAMEDRANGE:
case FormulaType.DATAVALIDATION_LIST:
rootNodeOperandClass = Ptg.CLASS_REF;
break;
void removeCellComment();
/**
- * Returns hyperlink associated with this cell
- *
* @return hyperlink associated with this cell or <code>null</code> if not found
*/
Hyperlink getHyperlink();
/**
- * Assign a hypelrink to this cell
+ * Assign a hyperlink to this cell
*
- * @param link hypelrink associated with this cell
+ * @param link hyperlink associated with this cell
*/
void setHyperlink(Hyperlink link);
-
/**
* Only valid for array formula cells
*
* @return <code>true</code> if this cell is part of group of cells having a common array formula.
*/
boolean isPartOfArrayFormulaGroup();
-
}
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.usermodel;
+
+import java.util.Iterator;
+
+
+/**
+ * Represents a rectangular region of a {@link Sheet}
+ *
+ * @author Josh Micich
+ */
+public interface CellRange<C extends Cell> extends Iterable<C> {
+
+ int getWidth();
+ int getHeight();
+ /**
+ * Gets the number of cells in this range.
+ * @return <tt>height * width </tt>
+ */
+ int size();
+ String getReferenceText();
+
+ /**
+ * @return the cell at relative coordinates (0,0). Never <code>null</code>.
+ */
+ C getTopLeftCell();
+
+ /**
+ * @param relativeRowIndex must be between <tt>0</tt> and <tt>height-1</tt>
+ * @param relativeColumnIndex must be between <tt>0</tt> and <tt>width-1</tt>
+ * @return the cell at the specified coordinates. Never <code>null</code>.
+ */
+ C getCell(int relativeRowIndex, int relativeColumnIndex);
+ /**
+ * @return a flattened array of all the cells in this {@link CellRange}
+ */
+ C[] getFlattenedCells();
+ /**
+ * @return a 2-D array of all the cells in this {@link CellRange}. The first
+ * array dimension is the row index (values <tt>0...height-1</tt>)
+ * and the second dimension is the column index (values <tt>0...width-1</tt>)
+ */
+ C[][] getCells();
+
+ /**
+ * @return an {@link Iterator} over all cells in this range. Iteration starts
+ * with all cells in the first row followed by all cells in the next row, etc.
+ */
+ Iterator<C> iterator();
+}
/**
* Sets array formula to specified region for result.
*
- * @param formula Formula
- * @param range Region of array formula for result.
+ * @param formula text representation of the formula
+ * @param range Region of array formula for result.
+ * @return the {@link CellRange} of cells affected by this change
*/
- Cell[] setArrayFormula(String formula, CellRangeAddress range);
+ CellRange<? extends Cell> setArrayFormula(String formula, CellRangeAddress range);
/**
* Remove a Array Formula from this sheet. All cells contained in the Array Formula range are removed as well
*
- * @param cell any cell within Array Formula range
+ * @param cell any cell within Array Formula range
+ * @return the {@link CellRange} of cells affected by this change
*/
- Cell[] removeArrayFormula(Cell cell);
-
+ CellRange<? extends Cell> removeArrayFormula(Cell cell);
}
/**
* See OOO documentation: excelfileformat.pdf sec 2.5.14 - 'Cell Range Address'<p/>
- *
+ *
* Note - {@link SelectionRecord} uses the BIFF5 version of this structure
* @author Dragos Buleandra (dragos.buleandra@trade2b.ro)
*/
out.writeShort(getFirstColumn());
out.writeShort(getLastColumn());
}
-
+
public CellRangeAddress(RecordInputStream in) {
super(readUShortAndCheck(in), in.readUShort(), in.readUShort(), in.readUShort());
}
return numberOfItems * ENCODED_SIZE;
}
+ /**
+ * @return the text format of this range. Single cell ranges are formatted
+ * like single cell references (e.g. 'A1' instead of 'A1:A1').
+ */
public String formatAsString() {
StringBuffer sb = new StringBuffer();
CellReference cellRefFrom = new CellReference(getFirstRow(), getFirstColumn());
public CellReference(int pRow, short pCol) {
this(pRow, pCol & 0xFFFF, false, false);
}
-
- public CellReference(Cell cell) {
- this(cell.getRowIndex(), cell.getColumnIndex(), false, false);
- }
+
+ public CellReference(Cell cell) {
+ this(cell.getRowIndex(), cell.getColumnIndex(), false, false);
+ }
public CellReference(int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
this(null, pRow, pCol, pAbsRow, pAbsCol);
sb.append(_rowIndex+1);
}
- /**
- * Checks whether this cell reference is equal to another object.
- * <p>
- * Two cells references are assumed to be equal if their string representations
- * ({@link #formatAsString()} are equal.
- * </p>
- */
- @Override
- public boolean equals(Object o){
- if(o == null || !(o instanceof CellReference)) {
- return false;
- }
-
- String me = formatAsString();
- String anotherRef = ((CellReference)o).formatAsString();
- return me.equals(anotherRef);
- }
+ /**
+ * Checks whether this cell reference is equal to another object.
+ * <p>
+ * Two cells references are assumed to be equal if their string representations
+ * ({@link #formatAsString()} are equal.
+ * </p>
+ */
+ @Override
+ public boolean equals(Object o){
+ if(!(o instanceof CellReference)) {
+ return false;
+ }
+ CellReference cr = (CellReference) o;
+ return _rowIndex == cr._rowIndex
+ && _colIndex == cr._colIndex
+ && _isRowAbs == cr._isColAbs
+ && _isColAbs == cr._isColAbs;
+ }
}
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.util;
+
+import java.lang.reflect.Array;
+import java.util.Iterator;
+import java.util.List;
+import java.util.NoSuchElementException;
+
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellRange;
+import org.apache.poi.util.Internal;
+
+/**
+ * For POI internal use only
+ *
+ * @author Josh Micich
+ */
+@Internal
+public final class SSCellRange<K extends Cell> implements CellRange<K> {
+
+ private final int _height;
+ private final int _width;
+ private final K[] _flattenedArray;
+ private final int _firstRow;
+ private final int _firstColumn;
+
+ private SSCellRange(int firstRow, int firstColumn, int height, int width, K[] flattenedArray) {
+ _firstRow = firstRow;
+ _firstColumn = firstColumn;
+ _height = height;
+ _width = width;
+ _flattenedArray = flattenedArray;
+ }
+
+ public static <B extends Cell> SSCellRange<B> create(int firstRow, int firstColumn, int height, int width, List<B> flattenedList, Class<B> cellClass) {
+ int nItems = flattenedList.size();
+ if (height * width != nItems) {
+ throw new IllegalArgumentException("Array size mismatch.");
+ }
+
+ @SuppressWarnings("unchecked")
+ B[] flattenedArray = (B[]) Array.newInstance(cellClass, nItems);
+ flattenedList.toArray(flattenedArray);
+ return new SSCellRange<B>(firstRow, firstColumn, height, width, flattenedArray);
+ }
+
+ public int getHeight() {
+ return _height;
+ }
+ public int getWidth() {
+ return _width;
+ }
+ public int size() {
+ return _height*_width;
+ }
+
+ public String getReferenceText() {
+ CellRangeAddress cra = new CellRangeAddress(_firstRow, _firstRow+_height-1, _firstColumn, _firstColumn+_width-1);
+ return cra.formatAsString();
+ }
+
+ public K getTopLeftCell() {
+ return _flattenedArray[0];
+ }
+
+ public K getCell(int relativeRowIndex, int relativeColumnIndex) {
+ if (relativeRowIndex < 0 || relativeRowIndex >= _height) {
+ throw new ArrayIndexOutOfBoundsException("Specified row " + relativeRowIndex
+ + " is outside the allowable range (0.." + (_height-1) + ").");
+ }
+ if (relativeColumnIndex < 0 || relativeColumnIndex >= _width) {
+ throw new ArrayIndexOutOfBoundsException("Specified colummn " + relativeColumnIndex
+ + " is outside the allowable range (0.." + (_width-1) + ").");
+ }
+ int flatIndex = _width * relativeRowIndex + relativeColumnIndex;
+ return _flattenedArray[flatIndex];
+ }
+ public K[] getFlattenedCells() {
+ return _flattenedArray.clone();
+ }
+
+ public K[][] getCells() {
+ Class<?> itemCls = _flattenedArray.getClass();
+ @SuppressWarnings("unchecked")
+ K[][] result = (K[][]) Array.newInstance(itemCls, _height);
+ itemCls = itemCls.getComponentType();
+ for (int r=_height-1; r>=0; r--) {
+ @SuppressWarnings("unchecked")
+ K[] row = (K[]) Array.newInstance(itemCls, _width);
+ int flatIndex = _width * r;
+ System.arraycopy(_flattenedArray, flatIndex, row, 0, _width);
+ }
+ return result;
+ }
+ public Iterator<K> iterator() {
+ return new ArrayIterator<K>(_flattenedArray);
+ }
+ private static final class ArrayIterator<D> implements Iterator<D> {
+
+ private final D[] _array;
+ private int _index;
+
+ public ArrayIterator(D[] array) {
+ _array = array;
+ _index = 0;
+ }
+ public boolean hasNext() {
+ return _index < _array.length;
+ }
+ public D next() {
+ if (_index >= _array.length) {
+ throw new NoSuchElementException(String.valueOf(_index));
+ }
+ return _array[_index++];
+ }
+
+ public void remove() {
+ throw new UnsupportedOperationException("Cannot remove cells from this CellRange.");
+ }
+ }
+}
throw new IllegalStateException("Unexpected formula result type (" + cellType + ")");
}
- /**
- * If this cell is part of an array formula, returns a CellRangeAddress object
- * that represents the entire array.
- *
- * @return the range of the array formula group that this cell belongs to.
- * @throws IllegalStateException if this cell is not part of an array formula
- * @see #isPartOfArrayFormulaGroup()
- */
public CellRangeAddress getArrayFormulaRange() {
XSSFCell cell = getSheet().getFirstCellInArrayFormula(this);
if (cell == null) {
- throw new IllegalStateException("Cell " + _cell.getR() + " is not part of an array formula");
+ throw new IllegalStateException("Cell " + _cell.getR()
+ + " is not part of an array formula.");
}
String formulaRef = cell._cell.getF().getRef();
return CellRangeAddress.valueOf(formulaRef);
}
- /**
- * Test if this cell is included in an array formula
- *
- * @return true if this cell is part of an array formula
- * @see #getArrayFormulaRange()
- */
public boolean isPartOfArrayFormulaGroup() {
return getSheet().isCellInArrayFormulaContext(this);
}
import org.apache.poi.openxml4j.opc.PackageRelationshipCollection;
import org.apache.poi.ss.SpreadsheetVersion;
import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.CellRange;
import org.apache.poi.ss.usermodel.CellStyle;
import org.apache.poi.ss.usermodel.Footer;
import org.apache.poi.ss.usermodel.Header;
import org.apache.poi.ss.usermodel.Sheet;
import org.apache.poi.ss.util.CellRangeAddress;
import org.apache.poi.ss.util.CellReference;
+import org.apache.poi.ss.util.SSCellRange;
+import org.apache.poi.util.Internal;
import org.apache.poi.util.POILogFactory;
import org.apache.poi.util.POILogger;
-import org.apache.poi.util.Internal;
import org.apache.poi.xssf.model.CommentsTable;
import org.apache.poi.xssf.usermodel.helpers.ColumnHelper;
import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter;
}
if (f != null && f.getT() == STCellFormulaType.ARRAY && f.getRef() != null) {
arrayFormulas.add(CellRangeAddress.valueOf(f.getRef()));
- }
+ }
}
@Override
}
/**
- * Sets array formula to the specified range of cells.
- * <p>
- * Note, that this method silently creates cells in the
- * specified range if they don't exist.
- * </p>
- * Example:
- * <blockquote><pre>
- * Workbook workbook = new XSSFWorkbook();
- * Sheet sheet = workbook.createSheet();
- * CellRangeAddress range = CellRangeAddress.valueOf("C1:C3");
- * Cell[] cells = sheet.setArrayFormula("A1:A3*B1:B3", range);
- * </pre></blockquote>
- * Three cells in the C1:C3 range are created and returned.
- *
- * @param formula the formula to set
- * @param range Region of array formula for result.
- * @return the array of cells that represent the entire formula array
- * @throws org.apache.poi.ss.formula.FormulaParseException if
- * the formula has incorrect syntax or is otherwise invalid
- */
- public XSSFCell[] setArrayFormula(String formula, CellRangeAddress range) {
- XSSFRow row = getRow(range.getFirstRow());
- if (row == null) {
- row = createRow(range.getFirstRow());
- }
- XSSFCell mainArrayFormulaCell = row.getCell(range.getFirstColumn());
- if (mainArrayFormulaCell == null) {
- mainArrayFormulaCell = row.createCell(range.getFirstColumn());
- }
- mainArrayFormulaCell.setCellArrayFormula(formula, range);
- arrayFormulas.add(range);
-
- XSSFCell[] cells = new XSSFCell[range.getNumberOfCells()];
- int k = 0;
- for (int rowIndex = range.getFirstRow(); rowIndex <= range.getLastRow(); rowIndex++) {
- row = getRow(rowIndex);
- if (row == null) {
- row = createRow(rowIndex);
- }
- for (int columnIndex = range.getFirstColumn(); columnIndex <= range.getLastColumn(); columnIndex++) {
- XSSFCell arrayFormulaCell = row.getCell(columnIndex);
- if (arrayFormulaCell == null) {
- arrayFormulaCell = row.createCell(columnIndex);
+ * Also creates cells if they don't exist
+ */
+ private CellRange<XSSFCell> getCellRange(CellRangeAddress range) {
+ int firstRow = range.getFirstRow();
+ int firstColumn = range.getFirstColumn();
+ int lastRow = range.getLastRow();
+ int lastColumn = range.getLastColumn();
+ int height = lastRow - firstRow + 1;
+ int width = lastColumn - firstColumn + 1;
+ List<XSSFCell> temp = new ArrayList<XSSFCell>(height*width);
+ for (int rowIn = firstRow; rowIn <= lastRow; rowIn++) {
+ for (int colIn = firstColumn; colIn <= lastColumn; colIn++) {
+ XSSFRow row = getRow(rowIn);
+ if (row == null) {
+ row = createRow(rowIn);
+ }
+ XSSFCell cell = row.getCell(colIn);
+ if (cell == null) {
+ cell = row.createCell(colIn);
}
- cells[k++] = arrayFormulaCell;
+ temp.add(cell);
}
}
- return cells;
+ return SSCellRange.create(firstRow, firstColumn, height, width, temp, XSSFCell.class);
}
- /**
- * Remove an Array Formula from this sheet.
- * <p>
- * All cells contained in the Array Formula range are removed as well
- * </p>
- *
- * @param cell any cell within Array Formula range
- * @return the array of affected cells.
- * @throws IllegalArgumentException if the specified cell is not part of an array formula
- */
- public XSSFCell[] removeArrayFormula(Cell cell) {
- ArrayList<XSSFCell> lst = new ArrayList<XSSFCell>();
+ public CellRange<XSSFCell> setArrayFormula(String formula, CellRangeAddress range) {
+
+ CellRange<XSSFCell> cr = getCellRange(range);
+
+ XSSFCell mainArrayFormulaCell = cr.getTopLeftCell();
+ mainArrayFormulaCell.setCellArrayFormula(formula, range);
+ arrayFormulas.add(range);
+ return cr;
+ }
+
+ public CellRange<XSSFCell> removeArrayFormula(Cell cell) {
+ if (cell.getSheet() != this) {
+ throw new IllegalArgumentException("Specified cell does not belong to this sheet.");
+ }
for (CellRangeAddress range : arrayFormulas) {
if (range.isInRange(cell.getRowIndex(), cell.getColumnIndex())) {
arrayFormulas.remove(range);
- for (int rowIndex = range.getFirstRow(); rowIndex <= range.getLastRow(); rowIndex++) {
- XSSFRow row = getRow(rowIndex);
- for (int columnIndex = range.getFirstColumn(); columnIndex <= range.getLastColumn(); columnIndex++) {
- XSSFCell arrayFormulaCell = row.getCell(columnIndex);
- if (arrayFormulaCell != null) {
- arrayFormulaCell.setCellType(Cell.CELL_TYPE_BLANK);
- lst.add(arrayFormulaCell);
- }
- }
+ CellRange<XSSFCell> cr = getCellRange(range);
+ for (XSSFCell c : cr) {
+ c.setCellType(Cell.CELL_TYPE_BLANK);
}
- return lst.toArray(new XSSFCell[lst.size()]);
+ return cr;
}
}
String ref = ((XSSFCell)cell).getCTCell().getR();
- throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula");
+ throw new IllegalArgumentException("Cell " + ref + " is not part of an array formula.");
}
}
/**
* Collects all tests for <tt>org.apache.poi.xssf.usermodel</tt> and sub-packages.
- *
+ *
* @author Josh Micich
*/
public final class AllXSSFUsermodelTests {
result.addTestSuite(TestXSSFRichTextString.class);
result.addTestSuite(TestXSSFRow.class);
result.addTestSuite(TestXSSFSheet.class);
+ result.addTestSuite(TestXSSFSheetUpdateArrayFormulas.class);
result.addTestSuite(TestXSSFWorkbook.class);
result.addTestSuite(TestXSSFBorder.class);
result.addTestSuite(TestXSSFCellFill.class);
result.addTestSuite(TestXSSFSheetComments.class);
-
+
result.addTestSuite(TestColumnHelper.class);
result.addTestSuite(TestHeaderFooterHelper.class);
+++ /dev/null
-/* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================== */
-
-package org.apache.poi.xssf.usermodel;
-
-import org.apache.poi.ss.usermodel.BaseTestArrayFormulas;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.xssf.XSSFITestDataProvider;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
-import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
-
-/**
- * Test array formulas in XSSF
- *
- * @author Yegor Kozlov
- */
-public final class TestXSSFArrayFormulas extends BaseTestArrayFormulas {
-
- @Override
- protected XSSFITestDataProvider getTestDataProvider(){
- return XSSFITestDataProvider.getInstance();
- }
-
- public void testXSSFSetArrayFormula_singleCell() {
- XSSFWorkbook workbook = getTestDataProvider().createWorkbook();
- XSSFSheet sheet = workbook.createSheet();
-
- // row 3 does not yet exist
- assertNull(sheet.getRow(2));
- CellRangeAddress range = new CellRangeAddress(2, 2, 2, 2);
- XSSFCell[] cells = sheet.setArrayFormula("SUM(C11:C12*D11:D12)", range);
- assertEquals(1, cells.length);
-
- // sheet.setArrayFormula creates rows and cells for the designated range
- assertNotNull(sheet.getRow(2));
- XSSFCell cell = sheet.getRow(2).getCell(2);
- assertNotNull(cell);
-
- assertTrue(cell.isPartOfArrayFormulaGroup());
- assertSame(cells[0], sheet.getFirstCellInArrayFormula(cells[0]));
- //retrieve the range and check it is the same
- assertEquals(range.formatAsString(), cell.getArrayFormulaRange().formatAsString());
-
- //check the CTCellFormula bean
- CTCellFormula f = cell.getCTCell().getF();
- assertEquals("SUM(C11:C12*D11:D12)", f.getStringValue());
- assertEquals("C3", f.getRef());
- assertEquals(STCellFormulaType.ARRAY, f.getT());
-
- }
-
- public void testXSSFSetArrayFormula_multiCell() {
- XSSFCell[] cells;
-
- XSSFWorkbook workbook = getTestDataProvider().createWorkbook();
- XSSFSheet sheet = workbook.createSheet();
-
- CellRangeAddress range = new CellRangeAddress(3, 5, 2, 2);
- assertEquals("C4:C6", range.formatAsString());
- cells = sheet.setArrayFormula("SUM(A1:A3*B1:B3)", range);
- assertEquals(3, cells.length);
-
- // sheet.setArrayFormula creates rows and cells for the designated range
- assertEquals("C4", cells[0].getCTCell().getR());
- assertEquals("C5", cells[1].getCTCell().getR());
- assertEquals("C6", cells[2].getCTCell().getR());
- assertSame(cells[0], sheet.getFirstCellInArrayFormula(cells[0]));
-
- /*
- * From the spec:
- * For a multi-cell formula, the c elements for all cells except the top-left
- * cell in that range shall not have an f element;
- */
-
- //the first cell has an f element
- CTCellFormula f = cells[0].getCTCell().getF();
- assertEquals("SUM(A1:A3*B1:B3)", f.getStringValue());
- assertEquals("C4:C6", f.getRef());
- assertEquals(STCellFormulaType.ARRAY, f.getT());
- //the other two cells don't have an f element
- assertNull(cells[1].getCTCell().getF());
- assertNull(cells[2].getCTCell().getF());
- }
-}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.xssf.usermodel;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.poi.ss.usermodel.BaseTestSheetUpdateArrayFormulas;
+import org.apache.poi.ss.usermodel.CellRange;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.xssf.XSSFITestDataProvider;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCell;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCellFormula;
+import org.openxmlformats.schemas.spreadsheetml.x2006.main.STCellFormulaType;
+/**
+ * Test array formulas in XSSF
+ *
+ * @author Yegor Kozlov
+ * @author Josh Micich
+ */
+public final class TestXSSFSheetUpdateArrayFormulas extends BaseTestSheetUpdateArrayFormulas {
+
+ public TestXSSFSheetUpdateArrayFormulas() {
+ super(XSSFITestDataProvider.getInstance());
+ }
+
+ // Test methods common with HSSF are in superclass
+ // Local methods here test XSSF-specific details of updating array formulas
+
+ public void testXSSFSetArrayFormula_singleCell() {
+ CellRange<XSSFCell> cells;
+
+ XSSFWorkbook workbook = new XSSFWorkbook();
+ XSSFSheet sheet = workbook.createSheet();
+
+ // 1. single-cell array formula
+ String formula1 = "123";
+ CellRangeAddress range = CellRangeAddress.valueOf("C3:C3");
+ cells = sheet.setArrayFormula(formula1, range);
+ assertEquals(1, cells.size());
+
+ // check getFirstCell...
+ XSSFCell firstCell = cells.getTopLeftCell();
+ assertSame(firstCell, sheet.getFirstCellInArrayFormula(firstCell));
+ //retrieve the range and check it is the same
+ assertEquals(range.formatAsString(), firstCell.getArrayFormulaRange().formatAsString());
+ confirmArrayFormulaCell(firstCell, "C3", formula1, "C3");
+ }
+
+ public void testXSSFSetArrayFormula_multiCell() {
+ CellRange<XSSFCell> cells;
+
+ String formula2 = "456";
+ XSSFWorkbook workbook = new XSSFWorkbook();
+ XSSFSheet sheet = workbook.createSheet();
+
+ CellRangeAddress range = CellRangeAddress.valueOf("C4:C6");
+ cells = sheet.setArrayFormula(formula2, range);
+ assertEquals(3, cells.size());
+
+ // sheet.setArrayFormula creates rows and cells for the designated range
+ /*
+ * From the spec:
+ * For a multi-cell formula, the c elements for all cells except the top-left
+ * cell in that range shall not have an f element;
+ */
+ // Check that each cell exists and that the formula text is set correctly on the first cell
+ XSSFCell firstCell = cells.getTopLeftCell();
+ confirmArrayFormulaCell(firstCell, "C4", formula2, "C4:C6");
+ confirmArrayFormulaCell(cells.getCell(1, 0), "C5");
+ confirmArrayFormulaCell(cells.getCell(2, 0), "C6");
+
+ assertSame(firstCell, sheet.getFirstCellInArrayFormula(firstCell));
+ }
+
+ private static void confirmArrayFormulaCell(XSSFCell c, String cellRef) {
+ confirmArrayFormulaCell(c, cellRef, null, null);
+ }
+ private static void confirmArrayFormulaCell(XSSFCell c, String cellRef, String formulaText, String arrayRangeRef) {
+ if (c == null) {
+ throw new AssertionFailedError("Cell should not be null.");
+ }
+ CTCell ctCell = c.getCTCell();
+ assertEquals(cellRef, ctCell.getR());
+ if (formulaText == null) {
+ assertFalse(ctCell.isSetF());
+ assertNull(ctCell.getF());
+ } else {
+ CTCellFormula f = ctCell.getF();
+ assertEquals(arrayRangeRef, f.getRef());
+ assertEquals(formulaText, f.getStringValue());
+ assertEquals(STCellFormulaType.ARRAY, f.getT());
+ }
+ }
+}
s.setString("abc");
FormulaRecordAggregate fagg = new FormulaRecordAggregate(f, s, SharedValueManager.createEmpty());
assertEquals("abc", fagg.getStringValue());
- assertFalse(fagg.isPartOfArrayFormula());
- }
+ assertFalse(fagg.isPartOfArrayFormula());
+ }
/**
* Sometimes a {@link StringRecord} appears after a {@link FormulaRecord} even though the
assertEquals(fr, vraRecs[0]);
}
- public void testArrayFormulas() {
- int rownum = 4;
- int colnum = 4;
+ public void testArrayFormulas() {
+ int rownum = 4;
+ int colnum = 4;
- FormulaRecord fr = new FormulaRecord();
- fr.setRow(rownum);
- fr.setColumn((short)colnum);
+ FormulaRecord fr = new FormulaRecord();
+ fr.setRow(rownum);
+ fr.setColumn((short)colnum);
- FormulaRecordAggregate agg = new FormulaRecordAggregate(fr, null, SharedValueManager.createEmpty());
- Ptg[] ptgsForCell = {new ExpPtg(rownum, colnum)};
- agg.setParsedExpression(ptgsForCell);
+ FormulaRecordAggregate agg = new FormulaRecordAggregate(fr, null, SharedValueManager.createEmpty());
+ Ptg[] ptgsForCell = {new ExpPtg(rownum, colnum)};
+ agg.setParsedExpression(ptgsForCell);
- String formula = "SUM(A1:A3*B1:B3)";
- Ptg[] ptgs = HSSFFormulaParser.parse(formula, null, FormulaType.ARRAY, 0);
- agg.setArrayFormula(new CellRangeAddress(rownum, rownum, colnum, colnum), ptgs);
+ String formula = "SUM(A1:A3*B1:B3)";
+ Ptg[] ptgs = HSSFFormulaParser.parse(formula, null, FormulaType.ARRAY, 0);
+ agg.setArrayFormula(new CellRangeAddress(rownum, rownum, colnum, colnum), ptgs);
- assertTrue(agg.isPartOfArrayFormula());
- assertEquals("E5", agg.getArrayFormulaRange().formatAsString());
- Ptg[] ptg = agg.getFormulaTokens();
- String fmlaSer = FormulaRenderer.toFormulaString(null, ptg);
- assertEquals(formula, fmlaSer);
- }
+ assertTrue(agg.isPartOfArrayFormula());
+ assertEquals("E5", agg.getArrayFormulaRange().formatAsString());
+ Ptg[] ptg = agg.getFormulaTokens();
+ String fmlaSer = FormulaRenderer.toFormulaString(null, ptg);
+ assertEquals(formula, fmlaSer);
+ }
}
package org.apache.poi.hssf.record.aggregates;
+import java.lang.reflect.Field;
import java.util.Collection;
import java.util.HashMap;
}
assertEquals("$AF24*A$7", formulaText);
}
+
+ /**
+ * Convenience test method for digging the {@link SharedValueManager} out of a
+ * {@link RowRecordsAggregate}.
+ */
+ public static SharedValueManager extractFromRRA(RowRecordsAggregate rra) {
+ Field f;
+ try {
+ f = RowRecordsAggregate.class.getDeclaredField("_sharedValueManager");
+ } catch (NoSuchFieldException e) {
+ throw new RuntimeException(e);
+ }
+
+ f.setAccessible(true);
+ try {
+ return (SharedValueManager) f.get(rra);
+ } catch (IllegalArgumentException e) {
+ throw new RuntimeException(e);
+ } catch (IllegalAccessException e) {
+ throw new RuntimeException(e);
+ }
+ }
}
/**
* Collects all tests for the <tt>org.apache.poi.hssf.usermodel</tt> package.
- *
+ *
* @author Josh Micich
*/
public class AllUserModelTests {
-
+
public static Test suite() {
TestSuite result = new TestSuite(AllUserModelTests.class.getName());
-
+
result.addTestSuite(TestBugs.class);
result.addTestSuite(TestCellStyle.class);
result.addTestSuite(TestCloneSheet.class);
result.addTestSuite(TestHSSFRichTextString.class);
result.addTestSuite(TestHSSFRow.class);
result.addTestSuite(TestHSSFSheet.class);
+ result.addTestSuite(TestHSSFSheetUpdateArrayFormulas.class);
result.addTestSuite(TestHSSFTextbox.class);
result.addTestSuite(TestHSSFWorkbook.class);
result.addTestSuite(TestHSSFName.class);
}
result.addTestSuite(TestUnicodeWorkbook.class);
result.addTestSuite(TestUppercaseWorkbook.class);
- result.addTestSuite(TestWorkbook.class);
-
+ result.addTestSuite(TestWorkbook.class);
+
return result;
}
}
+++ /dev/null
-/* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================== */
-
-package org.apache.poi.hssf.usermodel;
-
-import org.apache.poi.ss.usermodel.BaseTestArrayFormulas;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.hssf.HSSFITestDataProvider;
-import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
-
-/**
- * Test array formulas in HSSF
- *
- * @author Yegor Kozlov
- */
-public final class TestHSSFArrayFormulas extends BaseTestArrayFormulas {
-
- @Override
- protected HSSFITestDataProvider getTestDataProvider(){
- return HSSFITestDataProvider.getInstance();
- }
-
- public void testHSSFSetArrayFormula_singleCell() {
- HSSFWorkbook workbook = getTestDataProvider().createWorkbook();
- HSSFSheet sheet = workbook.createSheet();
-
- CellRangeAddress range = new CellRangeAddress(2, 2, 2, 2);
- HSSFCell[] cells = sheet.setArrayFormula("SUM(C11:C12*D11:D12)", range);
- assertEquals(1, cells.length);
-
- // sheet.setArrayFormula creates rows and cells for the designated range
- assertNotNull(sheet.getRow(2));
- HSSFCell cell = sheet.getRow(2).getCell(2);
- assertNotNull(cell);
-
- assertTrue(cell.isPartOfArrayFormulaGroup());
- //retrieve the range and check it is the same
- assertEquals(range.formatAsString(), cell.getArrayFormulaRange().formatAsString());
-
- FormulaRecordAggregate agg = (FormulaRecordAggregate)cell.getCellValueRecord();
- assertEquals(range.formatAsString(), agg.getArrayFormulaRange().formatAsString());
- assertTrue(agg.isPartOfArrayFormula());
-
- }
-
-}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.hssf.usermodel;
+
+import junit.framework.AssertionFailedError;
+
+import org.apache.poi.hssf.HSSFITestDataProvider;
+import org.apache.poi.hssf.record.ArrayRecord;
+import org.apache.poi.hssf.record.FormulaRecord;
+import org.apache.poi.hssf.record.Record;
+import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
+import org.apache.poi.hssf.record.aggregates.RowRecordsAggregate;
+import org.apache.poi.hssf.record.aggregates.SharedValueManager;
+import org.apache.poi.hssf.record.aggregates.TestSharedValueManager;
+import org.apache.poi.ss.usermodel.BaseTestSheetUpdateArrayFormulas;
+import org.apache.poi.ss.usermodel.CellRange;
+import org.apache.poi.ss.util.CellRangeAddress;
+
+/**
+ * Test array formulas in HSSF
+ *
+ * @author Yegor Kozlov
+ * @author Josh Micich
+ */
+public final class TestHSSFSheetUpdateArrayFormulas extends BaseTestSheetUpdateArrayFormulas {
+
+ public TestHSSFSheetUpdateArrayFormulas() {
+ super(HSSFITestDataProvider.getInstance());
+ }
+
+ // Test methods common with XSSF are in superclass
+ // Local methods here test HSSF-specific details of updating array formulas
+
+ public void testHSSFSetArrayFormula_singleCell() {
+ HSSFWorkbook workbook = new HSSFWorkbook();
+ HSSFSheet sheet = workbook.createSheet("Sheet1");
+
+ CellRangeAddress range = new CellRangeAddress(2, 2, 2, 2);
+ HSSFCell[] cells = sheet.setArrayFormula("SUM(C11:C12*D11:D12)", range).getFlattenedCells();
+ assertEquals(1, cells.length);
+
+ // sheet.setArrayFormula creates rows and cells for the designated range
+ assertNotNull(sheet.getRow(2));
+ HSSFCell cell = sheet.getRow(2).getCell(2);
+ assertNotNull(cell);
+
+ assertTrue(cell.isPartOfArrayFormulaGroup());
+ //retrieve the range and check it is the same
+ assertEquals(range.formatAsString(), cell.getArrayFormulaRange().formatAsString());
+
+ FormulaRecordAggregate agg = (FormulaRecordAggregate)cell.getCellValueRecord();
+ assertEquals(range.formatAsString(), agg.getArrayFormulaRange().formatAsString());
+ assertTrue(agg.isPartOfArrayFormula());
+ }
+
+ /**
+ * Makes sure the internal state of HSSFSheet is consistent after removing array formulas
+ */
+ public void testAddRemoveArrayFormulas_recordUpdates() {
+ HSSFWorkbook wb = new HSSFWorkbook();
+ HSSFSheet s = wb.createSheet("Sheet1");
+
+ CellRange<HSSFCell> cr = s.setArrayFormula("123", CellRangeAddress.valueOf("B5:C6"));
+ Record[] recs;
+ int ix;
+ recs = RecordInspector.getRecords(s, 0);
+ ix = findRecordOfType(recs, ArrayRecord.class, 0);
+ confirmRecordClass(recs, ix-1, FormulaRecord.class);
+ confirmRecordClass(recs, ix+1, FormulaRecord.class);
+ confirmRecordClass(recs, ix+2, FormulaRecord.class);
+ confirmRecordClass(recs, ix+3, FormulaRecord.class);
+ // just one array record
+ assertTrue(findRecordOfType(recs, ArrayRecord.class, ix+1) < 0);
+
+ s.removeArrayFormula(cr.getTopLeftCell());
+
+ // Make sure the array formula has been removed properly
+
+ recs = RecordInspector.getRecords(s, 0);
+ assertTrue(findRecordOfType(recs, ArrayRecord.class, 0) < 0);
+ assertTrue(findRecordOfType(recs, FormulaRecord.class, 0) < 0);
+ RowRecordsAggregate rra = s.getSheet().getRowsAggregate();
+ SharedValueManager svm = TestSharedValueManager.extractFromRRA(rra);
+ if (svm.getArrayRecord(4, 1) != null) {
+ throw new AssertionFailedError("Array record was not cleaned up properly.");
+ }
+ }
+
+ private static void confirmRecordClass(Record[] recs, int index, Class<? extends Record> cls) {
+ if (recs.length <= index) {
+ throw new AssertionFailedError("Expected (" + cls.getName() + ") at index "
+ + index + " but array length is " + recs.length + ".");
+ }
+ assertEquals(cls, recs[index].getClass());
+ }
+ /**
+ * @return <tt>-1<tt> if not found
+ */
+ private static int findRecordOfType(Record[] recs, Class<?> type, int fromIndex) {
+ for (int i=fromIndex; i<recs.length; i++) {
+ if (type.isInstance(recs[i])) {
+ return i;
+ }
+ }
+ return -1;
+ }
+}
+++ /dev/null
-/* ====================================================================
- Licensed to the Apache Software Foundation (ASF) under one or more
- contributor license agreements. See the NOTICE file distributed with
- this work for additional information regarding copyright ownership.
- The ASF licenses this file to You under the Apache License, Version 2.0
- (the "License"); you may not use this file except in compliance with
- the License. You may obtain a copy of the License at
-
- http://www.apache.org/licenses/LICENSE-2.0
-
- Unless required by applicable law or agreed to in writing, software
- distributed under the License is distributed on an "AS IS" BASIS,
- WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- See the License for the specific language governing permissions and
- limitations under the License.
-==================================================================== */
-
-package org.apache.poi.ss.usermodel;
-
-import junit.framework.TestCase;
-import org.apache.poi.ss.ITestDataProvider;
-import org.apache.poi.ss.SpreadsheetVersion;
-import org.apache.poi.ss.formula.FormulaParseException;
-import org.apache.poi.ss.util.CellRangeAddress;
-import org.apache.poi.ss.util.CellReference;
-
-import java.util.Iterator;
-import java.util.Arrays;
-
-/**
- * Common superclass for testing usermodel API for array formulas
- *
- * @author Yegor Kozlov
- */
-public abstract class BaseTestArrayFormulas extends TestCase {
-
- /**
- * @return an object that provides test data in HSSF / XSSF specific way
- */
- protected abstract ITestDataProvider getTestDataProvider();
-
-
- /**
- * Set single-cell array formula
- */
- public void testSetArrayFormula_singleCell() {
- Workbook workbook = getTestDataProvider().createWorkbook();
- Sheet sheet = workbook.createSheet();
-
- // row 3 does not yet exist
- assertNull(sheet.getRow(2));
- CellRangeAddress range = new CellRangeAddress(2, 2, 2, 2);
- Cell[] cells = sheet.setArrayFormula("SUM(C11:C12*D11:D12)", range);
- assertEquals(1, cells.length);
- // sheet.setArrayFormula creates rows and cells for the designated range
- assertNotNull(sheet.getRow(2));
- Cell cell = sheet.getRow(2).getCell(2);
- assertNotNull(cell);
-
- assertTrue(cell.isPartOfArrayFormulaGroup());
- //retrieve the range and check it is the same
- assertEquals(range.formatAsString(), cell.getArrayFormulaRange().formatAsString());
- //check the formula
- assertEquals("SUM(C11:C12*D11:D12)", cell.getCellFormula());
- }
-
- /**
- * Set multi-cell array formula
- */
- public void testSetArrayFormula_multiCell() {
- Workbook workbook = getTestDataProvider().createWorkbook();
- Sheet sheet = workbook.createSheet();
-
- // multi-cell formula
- // rows 3-5 don't exist yet
- assertNull(sheet.getRow(3));
- assertNull(sheet.getRow(4));
- assertNull(sheet.getRow(5));
-
- CellRangeAddress range = new CellRangeAddress(3, 5, 2, 2);
- assertEquals("C4:C6", range.formatAsString());
- Cell[] cells = sheet.setArrayFormula("SUM(A1:A3*B1:B3)", range);
- assertEquals(3, cells.length);
-
- // sheet.setArrayFormula creates rows and cells for the designated range
- assertSame(cells[0], sheet.getRow(3).getCell(2));
- assertSame(cells[1], sheet.getRow(4).getCell(2));
- assertSame(cells[2], sheet.getRow(5).getCell(2));
-
- for(Cell acell : cells){
- assertTrue(acell.isPartOfArrayFormulaGroup());
- assertEquals(Cell.CELL_TYPE_FORMULA, acell.getCellType());
- assertEquals("SUM(A1:A3*B1:B3)", acell.getCellFormula());
- //retrieve the range and check it is the same
- assertEquals(range.formatAsString(), acell.getArrayFormulaRange().formatAsString());
- }
- }
-
- /**
- * Passing an incorrect formula to sheet.setArrayFormula
- * should throw FormulaParseException
- */
- public void testSetArrayFormula_incorrectFormula() {
- Workbook workbook = getTestDataProvider().createWorkbook();
- Sheet sheet = workbook.createSheet();
-
- try {
- sheet.setArrayFormula("incorrect-formula(C11_C12*D11_D12)",
- new CellRangeAddress(10, 10, 10, 10));
- fail("expected exception");
- } catch (FormulaParseException e){
- //expected exception
- }
- }
-
- /**
- * Calls of cell.getArrayFormulaRange and sheet.removeArrayFormula
- * on a not-array-formula cell throw IllegalStateException
- */
- public void testArrayFormulas_illegalCalls() {
- Workbook workbook = getTestDataProvider().createWorkbook();
- Sheet sheet = workbook.createSheet();
-
- Cell cell = sheet.createRow(0).createCell(0);
- assertFalse(cell.isPartOfArrayFormulaGroup());
- try {
- CellRangeAddress range = cell.getArrayFormulaRange();
- fail("expected exception");
- } catch (IllegalStateException e){
- assertEquals("Cell A1 is not part of an array formula", e.getMessage());
- }
-
- try {
- sheet.removeArrayFormula(cell);
- fail("expected exception");
- } catch (IllegalArgumentException e){
- assertEquals("Cell A1 is not part of an array formula", e.getMessage());
- }
- }
-
- /**
- * create and remove array formulas
- */
- public void testRemoveArrayFormula() {
- Workbook workbook = getTestDataProvider().createWorkbook();
- Sheet sheet = workbook.createSheet();
-
- CellRangeAddress range = new CellRangeAddress(3, 5, 2, 2);
- assertEquals("C4:C6", range.formatAsString());
- Cell[] cells = sheet.setArrayFormula("SUM(A1:A3*B1:B3)", range);
- assertEquals(3, cells.length);
-
- // remove the formula cells in C4:C6
- Cell[] dcells = sheet.removeArrayFormula(cells[0]);
- // removeArrayFormula should return the same cells as setArrayFormula
- assertTrue(Arrays.equals(cells, dcells));
-
- for(Cell acell : cells){
- assertFalse(acell.isPartOfArrayFormulaGroup());
- assertEquals(Cell.CELL_TYPE_BLANK, acell.getCellType());
- }
-
- // cells C4:C6 are not included in array formula,
- // invocation of sheet.removeArrayFormula on any of them throws IllegalArgumentException
- for(Cell acell : cells){
- try {
- sheet.removeArrayFormula(acell);
- fail("expected exception");
- } catch (IllegalArgumentException e){
- String ref = new CellReference(acell).formatAsString();
- assertEquals("Cell "+ref+" is not part of an array formula", e.getMessage());
- }
- }
- }
-
- /**
- * Test that when reading a workbook from input stream, array formulas are recognized
- */
- public void testReadArrayFormula() {
- Cell[] cells;
-
- Workbook workbook = getTestDataProvider().createWorkbook();
- Sheet sheet1 = workbook.createSheet();
- cells = sheet1.setArrayFormula("SUM(A1:A3*B1:B3)", CellRangeAddress.valueOf("C4:C6"));
- assertEquals(3, cells.length);
-
- cells = sheet1.setArrayFormula("MAX(A1:A3*B1:B3)", CellRangeAddress.valueOf("A4:A6"));
- assertEquals(3, cells.length);
-
- Sheet sheet2 = workbook.createSheet();
- cells = sheet2.setArrayFormula("MIN(A1:A3*B1:B3)", CellRangeAddress.valueOf("D2:D4"));
- assertEquals(3, cells.length);
-
- workbook = getTestDataProvider().writeOutAndReadBack(workbook);
- sheet1 = workbook.getSheetAt(0);
- for(int rownum=3; rownum <= 5; rownum++) {
- Cell cell1 = sheet1.getRow(rownum).getCell(2);
- assertTrue( cell1.isPartOfArrayFormulaGroup());
-
- Cell cell2 = sheet1.getRow(rownum).getCell(0);
- assertTrue( cell2.isPartOfArrayFormulaGroup());
- }
-
- sheet2 = workbook.getSheetAt(1);
- for(int rownum=1; rownum <= 3; rownum++) {
- Cell cell1 = sheet2.getRow(rownum).getCell(3);
- assertTrue( cell1.isPartOfArrayFormulaGroup());
- }
- }
-}
\ No newline at end of file
--- /dev/null
+/* ====================================================================
+ Licensed to the Apache Software Foundation (ASF) under one or more
+ contributor license agreements. See the NOTICE file distributed with
+ this work for additional information regarding copyright ownership.
+ The ASF licenses this file to You under the Apache License, Version 2.0
+ (the "License"); you may not use this file except in compliance with
+ the License. You may obtain a copy of the License at
+
+ http://www.apache.org/licenses/LICENSE-2.0
+
+ Unless required by applicable law or agreed to in writing, software
+ distributed under the License is distributed on an "AS IS" BASIS,
+ WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ See the License for the specific language governing permissions and
+ limitations under the License.
+==================================================================== */
+
+package org.apache.poi.ss.usermodel;
+
+import java.util.Arrays;
+
+import junit.framework.TestCase;
+
+import org.apache.poi.ss.ITestDataProvider;
+import org.apache.poi.ss.formula.FormulaParseException;
+import org.apache.poi.ss.util.CellRangeAddress;
+import org.apache.poi.ss.util.CellReference;
+
+/**
+ * Common superclass for testing usermodel API for array formulas.<br/>
+ * Formula evaluation is not tested here.
+ *
+ * @author Yegor Kozlov
+ * @author Josh Micich
+ */
+public abstract class BaseTestSheetUpdateArrayFormulas extends TestCase {
+ protected final ITestDataProvider _testDataProvider;
+
+ protected BaseTestSheetUpdateArrayFormulas(ITestDataProvider testDataProvider) {
+ _testDataProvider = testDataProvider;
+ }
+
+ public final void testAutoCreateOtherCells() {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet("Sheet1");
+
+ Row row1 = sheet.createRow(0);
+ Cell cellA1 = row1.createCell(0);
+ Cell cellB1 = row1.createCell(1);
+ String formula = "42";
+ sheet.setArrayFormula(formula, CellRangeAddress.valueOf("A1:B2"));
+
+ assertEquals(formula, cellA1.getCellFormula());
+ assertEquals(formula, cellB1.getCellFormula());
+ Row row2 = sheet.getRow(1);
+ assertNotNull(row2);
+ assertEquals(formula, row2.getCell(0).getCellFormula());
+ assertEquals(formula, row2.getCell(1).getCellFormula());
+ }
+ /**
+ * Set single-cell array formula
+ */
+ public final void testSetArrayFormula_singleCell() {
+ Cell[] cells;
+
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet();
+ Cell cell = sheet.createRow(0).createCell(0);
+ assertFalse(cell.isPartOfArrayFormulaGroup());
+ try {
+ cell.getArrayFormulaRange();
+ fail("expected exception");
+ } catch (IllegalStateException e){
+ assertEquals("Cell A1 is not part of an array formula.", e.getMessage());
+ }
+
+ // row 3 does not yet exist
+ assertNull(sheet.getRow(2));
+ CellRangeAddress range = new CellRangeAddress(2, 2, 2, 2);
+ cells = sheet.setArrayFormula("SUM(C11:C12*D11:D12)", range).getFlattenedCells();
+ assertEquals(1, cells.length);
+ // sheet.setArrayFormula creates rows and cells for the designated range
+ assertNotNull(sheet.getRow(2));
+ cell = sheet.getRow(2).getCell(2);
+ assertNotNull(cell);
+
+ assertTrue(cell.isPartOfArrayFormulaGroup());
+ //retrieve the range and check it is the same
+ assertEquals(range.formatAsString(), cell.getArrayFormulaRange().formatAsString());
+ //check the formula
+ assertEquals("SUM(C11:C12*D11:D12)", cell.getCellFormula());
+ }
+
+ /**
+ * Set multi-cell array formula
+ */
+ public final void testSetArrayFormula_multiCell() {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet();
+
+ // multi-cell formula
+ // rows 3-5 don't exist yet
+ assertNull(sheet.getRow(3));
+ assertNull(sheet.getRow(4));
+ assertNull(sheet.getRow(5));
+
+ CellRangeAddress range = CellRangeAddress.valueOf("C4:C6");
+ Cell[] cells = sheet.setArrayFormula("SUM(A1:A3*B1:B3)", range).getFlattenedCells();
+ assertEquals(3, cells.length);
+
+ // sheet.setArrayFormula creates rows and cells for the designated range
+ assertSame(cells[0], sheet.getRow(3).getCell(2));
+ assertSame(cells[1], sheet.getRow(4).getCell(2));
+ assertSame(cells[2], sheet.getRow(5).getCell(2));
+
+ for(Cell acell : cells){
+ assertTrue(acell.isPartOfArrayFormulaGroup());
+ assertEquals(Cell.CELL_TYPE_FORMULA, acell.getCellType());
+ assertEquals("SUM(A1:A3*B1:B3)", acell.getCellFormula());
+ //retrieve the range and check it is the same
+ assertEquals(range.formatAsString(), acell.getArrayFormulaRange().formatAsString());
+ }
+ }
+
+ /**
+ * Passing an incorrect formula to sheet.setArrayFormula
+ * should throw FormulaParseException
+ */
+ public final void testSetArrayFormula_incorrectFormula() {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet();
+
+ try {
+ sheet.setArrayFormula("incorrect-formula(C11_C12*D11_D12)",
+ new CellRangeAddress(10, 10, 10, 10));
+ fail("expected exception");
+ } catch (FormulaParseException e){
+ //expected exception
+ }
+ }
+
+ /**
+ * Calls of cell.getArrayFormulaRange and sheet.removeArrayFormula
+ * on a not-array-formula cell throw IllegalStateException
+ */
+ public final void testArrayFormulas_illegalCalls() {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet();
+
+ Cell cell = sheet.createRow(0).createCell(0);
+ assertFalse(cell.isPartOfArrayFormulaGroup());
+ try {
+ cell.getArrayFormulaRange();
+ fail("expected exception");
+ } catch (IllegalStateException e){
+ assertEquals("Cell A1 is not part of an array formula.", e.getMessage());
+ }
+
+ try {
+ sheet.removeArrayFormula(cell);
+ fail("expected exception");
+ } catch (IllegalArgumentException e){
+ assertEquals("Cell A1 is not part of an array formula.", e.getMessage());
+ }
+ }
+
+ /**
+ * create and remove array formulas
+ */
+ public final void testRemoveArrayFormula() {
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet = workbook.createSheet();
+
+ CellRangeAddress range = new CellRangeAddress(3, 5, 2, 2);
+ assertEquals("C4:C6", range.formatAsString());
+ CellRange<?> cr = sheet.setArrayFormula("SUM(A1:A3*B1:B3)", range);
+ assertEquals(3, cr.size());
+
+ // remove the formula cells in C4:C6
+ CellRange<?> dcells = sheet.removeArrayFormula(cr.getTopLeftCell());
+ // removeArrayFormula should return the same cells as setArrayFormula
+ assertTrue(Arrays.equals(cr.getFlattenedCells(), dcells.getFlattenedCells()));
+
+ for(Cell acell : cr){
+ assertFalse(acell.isPartOfArrayFormulaGroup());
+ assertEquals(Cell.CELL_TYPE_BLANK, acell.getCellType());
+ }
+
+ // cells C4:C6 are not included in array formula,
+ // invocation of sheet.removeArrayFormula on any of them throws IllegalArgumentException
+ for(Cell acell : cr){
+ try {
+ sheet.removeArrayFormula(acell);
+ fail("expected exception");
+ } catch (IllegalArgumentException e){
+ String ref = new CellReference(acell).formatAsString();
+ assertEquals("Cell "+ref+" is not part of an array formula.", e.getMessage());
+ }
+ }
+ }
+
+ /**
+ * Test that when reading a workbook from input stream, array formulas are recognized
+ */
+ public final void testReadArrayFormula() {
+ Cell[] cells;
+
+ Workbook workbook = _testDataProvider.createWorkbook();
+ Sheet sheet1 = workbook.createSheet();
+ cells = sheet1.setArrayFormula("SUM(A1:A3*B1:B3)", CellRangeAddress.valueOf("C4:C6")).getFlattenedCells();
+ assertEquals(3, cells.length);
+
+ cells = sheet1.setArrayFormula("MAX(A1:A3*B1:B3)", CellRangeAddress.valueOf("A4:A6")).getFlattenedCells();
+ assertEquals(3, cells.length);
+
+ Sheet sheet2 = workbook.createSheet();
+ cells = sheet2.setArrayFormula("MIN(A1:A3*B1:B3)", CellRangeAddress.valueOf("D2:D4")).getFlattenedCells();
+ assertEquals(3, cells.length);
+
+ workbook = _testDataProvider.writeOutAndReadBack(workbook);
+ sheet1 = workbook.getSheetAt(0);
+ for(int rownum=3; rownum <= 5; rownum++) {
+ Cell cell1 = sheet1.getRow(rownum).getCell(2);
+ assertTrue( cell1.isPartOfArrayFormulaGroup());
+
+ Cell cell2 = sheet1.getRow(rownum).getCell(0);
+ assertTrue( cell2.isPartOfArrayFormulaGroup());
+ }
+
+ sheet2 = workbook.getSheetAt(1);
+ for(int rownum=1; rownum <= 3; rownum++) {
+ Cell cell1 = sheet2.getRow(rownum).getCell(3);
+ assertTrue( cell1.isPartOfArrayFormulaGroup());
+ }
+ }
+}