package org.apache.poi.xssf.usermodel;
+import java.util.HashMap;
+import java.util.Map;
+
import org.apache.poi.ss.formula.EvaluationCell;
import org.apache.poi.ss.formula.EvaluationSheet;
+import org.apache.poi.ss.usermodel.Cell;
+import org.apache.poi.ss.usermodel.Row;
/**
* XSSF wrapper for a sheet under evaluation
final class XSSFEvaluationSheet implements EvaluationSheet {
private final XSSFSheet _xs;
+ private Map<CellKey, EvaluationCell> _cellCache;
public XSSFEvaluationSheet(XSSFSheet sheet) {
_xs = sheet;
return _xs;
}
public EvaluationCell getCell(int rowIndex, int columnIndex) {
- XSSFRow row = _xs.getRow(rowIndex);
- if (row == null) {
- return null;
- }
- XSSFCell cell = row.getCell(columnIndex);
- if (cell == null) {
- return null;
- }
- return new XSSFEvaluationCell(cell, this);
+ // cache for performance: ~30% speedup due to caching
+ if (_cellCache == null) {
+ _cellCache = new HashMap<CellKey, EvaluationCell>(_xs.getLastRowNum()*3);
+ for (final Row row : _xs) {
+ final int rowNum = row.getRowNum();
+ for (final Cell cell : row) {
+ // cast is safe, the iterator is just defined using the interface
+ final CellKey key = new CellKey(rowNum, cell.getColumnIndex());
+ final EvaluationCell evalcell = new XSSFEvaluationCell((XSSFCell) cell, this);
+ _cellCache.put(key, evalcell);
+ }
+ }
+ }
+
+ return _cellCache.get(new CellKey(rowIndex, columnIndex));
+
+ }
+
+ private static class CellKey {
+ private final int _row;
+ private final int _col;
+ private final int _hash;
+
+ protected CellKey(int row, int col) {
+ _row = row;
+ _col = col;
+ _hash = (17 * 37 + row) * 37 + col;
+ }
+
+ @Override
+ public int hashCode() {
+ return _hash;
+ }
+
+ @Override
+ public boolean equals(Object obj) {
+ if (obj == null) return false;
+ // assumes other object is one of us, otherwise ClassCastException is thrown
+ final CellKey oKey = (CellKey) obj;
+ return _row == oKey._row && _col == oKey._col;
+ }
}
}
* Internal POI use only
*/
public final class XSSFEvaluationWorkbook extends BaseXSSFEvaluationWorkbook {
+ private XSSFEvaluationSheet[] _sheetCache;
+
public static XSSFEvaluationWorkbook create(XSSFWorkbook book) {
if (book == null) {
return null;
@Override
public EvaluationSheet getSheet(int sheetIndex) {
- return new XSSFEvaluationSheet(_uBook.getSheetAt(sheetIndex));
+ // Performance optimization: build sheet cache the first time this is called
+ // to avoid re-creating the XSSFEvaluationSheet each time a new cell is evaluated
+ // EvaluationWorkbooks make not guarentee to syncronize changes made to
+ // the underlying workbook after the EvaluationWorkbook is created.
+ if (_sheetCache == null) {
+ _sheetCache = new XSSFEvaluationSheet[_uBook.getNumberOfSheets()];
+ for (int i=0; i < _uBook.getNumberOfSheets(); i++) {
+ _sheetCache[i] = new XSSFEvaluationSheet(_uBook.getSheetAt(i));
+ }
+ }
+ if (sheetIndex < 0 || sheetIndex >= _sheetCache.length) {
+ // do this to reuse the out-of-bounds logic and message from XSSFWorkbook
+ _uBook.getSheetAt(sheetIndex);
+ }
+ return _sheetCache[sheetIndex];
}
@Override