Made HSSFFormulaEvaluator no longer require initialisation with sheet or row.
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@694643 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
0799612198
commit
324d79a0ba
@ -37,6 +37,7 @@
|
||||
|
||||
<!-- Don't forget to update status.xml too! -->
|
||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">Made HSSFFormulaEvaluator no longer require initialisation with sheet or row</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Extended support for cached results of formula cells</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45639 - Fixed AIOOBE due to bad index logic in ColumnInfoRecordsAggregate</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Fixed special cases of INDEX function (single column/single row, errors)</action>
|
||||
|
@ -34,6 +34,7 @@
|
||||
<!-- Don't forget to update changes.xml too! -->
|
||||
<changes>
|
||||
<release version="3.1.1-alpha1" date="2008-??-??">
|
||||
<action dev="POI-DEVELOPERS" type="add">Made HSSFFormulaEvaluator no longer require initialisation with sheet or row</action>
|
||||
<action dev="POI-DEVELOPERS" type="add">Extended support for cached results of formula cells</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">45639 - Fixed AIOOBE due to bad index logic in ColumnInfoRecordsAggregate</action>
|
||||
<action dev="POI-DEVELOPERS" type="fix">Fixed special cases of INDEX function (single column/single row, errors)</action>
|
||||
|
@ -24,15 +24,14 @@ import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
|
||||
public final class AnalysisToolPak {
|
||||
|
||||
private static final FreeRefFunction NotImplemented = new FreeRefFunction() {
|
||||
|
||||
public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol,
|
||||
HSSFWorkbook workbook, HSSFSheet sheet) {
|
||||
public ValueEval evaluate(Eval[] args, HSSFWorkbook workbook, int srcCellSheet,
|
||||
int srcCellRow, int srcCellCol) {
|
||||
return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
|
||||
}
|
||||
};
|
||||
|
@ -42,8 +42,8 @@ final class ParityFunction implements FreeRefFunction {
|
||||
_desiredParity = desiredParity;
|
||||
}
|
||||
|
||||
public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook,
|
||||
HSSFSheet sheet) {
|
||||
public ValueEval evaluate(Eval[] args, HSSFWorkbook workbook, int srcCellSheet, int srcCellRow,
|
||||
int srcCellCol) {
|
||||
if (args.length != 1) {
|
||||
return ErrorEval.VALUE_INVALID;
|
||||
}
|
||||
@ -58,8 +58,8 @@ final class ParityFunction implements FreeRefFunction {
|
||||
return BoolEval.valueOf(val == _desiredParity);
|
||||
}
|
||||
|
||||
private static int evaluateArgParity(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||
private static int evaluateArgParity(Eval arg, int srcCellRow, int srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, (short)srcCellCol);
|
||||
|
||||
double d = OperandResolver.coerceValueToDouble(ve);
|
||||
if (d < 0) {
|
||||
|
@ -61,8 +61,8 @@ final class YearFrac implements FreeRefFunction {
|
||||
// enforce singleton
|
||||
}
|
||||
|
||||
public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook,
|
||||
HSSFSheet sheet) {
|
||||
public ValueEval evaluate(Eval[] args, HSSFWorkbook workbook, int srcCellSheet, int srcCellRow,
|
||||
int srcCellCol) {
|
||||
|
||||
double result;
|
||||
try {
|
||||
@ -85,8 +85,8 @@ final class YearFrac implements FreeRefFunction {
|
||||
return new NumberEval(result);
|
||||
}
|
||||
|
||||
private static double evaluateDateArg(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||
private static double evaluateDateArg(Eval arg, int srcCellRow, int srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, (short) srcCellCol);
|
||||
|
||||
if (ve instanceof StringEval) {
|
||||
String strVal = ((StringEval) ve).getStringValue();
|
||||
@ -155,8 +155,8 @@ final class YearFrac implements FreeRefFunction {
|
||||
return cal;
|
||||
}
|
||||
|
||||
private static int evaluateIntArg(Eval arg, int srcCellRow, short srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, srcCellCol);
|
||||
private static int evaluateIntArg(Eval arg, int srcCellRow, int srcCellCol) throws EvaluationException {
|
||||
ValueEval ve = OperandResolver.getSingleValue(arg, srcCellRow, (short) srcCellCol);
|
||||
return OperandResolver.coerceValueToInt(ve);
|
||||
}
|
||||
}
|
||||
|
@ -19,7 +19,6 @@ package org.apache.poi.hssf.record.formula.eval;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.atp.AnalysisToolPak;
|
||||
import org.apache.poi.hssf.record.formula.functions.FreeRefFunction;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
/**
|
||||
*
|
||||
@ -31,7 +30,8 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
*/
|
||||
final class ExternalFunction implements FreeRefFunction {
|
||||
|
||||
public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook, HSSFSheet sheet) {
|
||||
public ValueEval evaluate(Eval[] args, HSSFWorkbook workbook,
|
||||
int srcCellSheet, int srcCellRow,int srcCellCol) {
|
||||
|
||||
int nIncomingArgs = args.length;
|
||||
if(nIncomingArgs < 1) {
|
||||
@ -55,7 +55,7 @@ final class ExternalFunction implements FreeRefFunction {
|
||||
int nOutGoingArgs = nIncomingArgs -1;
|
||||
Eval[] outGoingArgs = new Eval[nOutGoingArgs];
|
||||
System.arraycopy(args, 1, outGoingArgs, 0, nOutGoingArgs);
|
||||
return targetFunc.evaluate(outGoingArgs, srcCellRow, srcCellCol, workbook, sheet);
|
||||
return targetFunc.evaluate(outGoingArgs, workbook, srcCellSheet, srcCellRow, srcCellCol);
|
||||
}
|
||||
|
||||
private FreeRefFunction findExternalUserDefinedFunction(HSSFWorkbook workbook,
|
||||
|
@ -45,13 +45,13 @@ public interface FreeRefFunction {
|
||||
*
|
||||
* @param args the pre-evaluated arguments for this function. args is never <code>null</code>,
|
||||
* nor are any of its elements.
|
||||
* @param srcCellSheet zero based sheet index of the cell containing the currently evaluating formula
|
||||
* @param srcCellRow zero based row index of the cell containing the currently evaluating formula
|
||||
* @param srcCellCol zero based column index of the cell containing the currently evaluating formula
|
||||
* @param workbook is the workbook containing the formula/cell being evaluated
|
||||
* @param sheet is the sheet containing the formula/cell being evaluated
|
||||
* @return never <code>null</code>. Possibly an instance of <tt>ErrorEval</tt> in the case of
|
||||
* a specified Excel error (Exceptions are never thrown to represent Excel errors).
|
||||
*
|
||||
*/
|
||||
ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook, HSSFSheet sheet);
|
||||
ValueEval evaluate(Eval[] args, HSSFWorkbook workbook, int srcCellSheet, int srcCellRow, int srcCellCol);
|
||||
}
|
||||
|
@ -41,7 +41,7 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
|
||||
*/
|
||||
public final class Indirect implements FreeRefFunction {
|
||||
|
||||
public ValueEval evaluate(Eval[] args, int srcCellRow, short srcCellCol, HSSFWorkbook workbook, HSSFSheet sheet) {
|
||||
public ValueEval evaluate(Eval[] args, HSSFWorkbook workbook, int srcCellSheet, int srcCellRow, int srcCellCol) {
|
||||
// TODO - implement INDIRECT()
|
||||
return ErrorEval.FUNCTION_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
@ -37,19 +37,19 @@ final class EvaluationCycleDetector {
|
||||
private static final class CellEvaluationFrame {
|
||||
|
||||
private final HSSFWorkbook _workbook;
|
||||
private final HSSFSheet _sheet;
|
||||
private final int _sheetIndex;
|
||||
private final int _srcRowNum;
|
||||
private final int _srcColNum;
|
||||
|
||||
public CellEvaluationFrame(HSSFWorkbook workbook, HSSFSheet sheet, int srcRowNum, int srcColNum) {
|
||||
public CellEvaluationFrame(HSSFWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
|
||||
if (workbook == null) {
|
||||
throw new IllegalArgumentException("workbook must not be null");
|
||||
}
|
||||
if (sheet == null) {
|
||||
throw new IllegalArgumentException("sheet must not be null");
|
||||
if (sheetIndex < 0) {
|
||||
throw new IllegalArgumentException("sheetIndex must not be negative");
|
||||
}
|
||||
_workbook = workbook;
|
||||
_sheet = sheet;
|
||||
_sheetIndex = sheetIndex;
|
||||
_srcRowNum = srcRowNum;
|
||||
_srcColNum = srcColNum;
|
||||
}
|
||||
@ -59,7 +59,7 @@ final class EvaluationCycleDetector {
|
||||
if (_workbook != other._workbook) {
|
||||
return false;
|
||||
}
|
||||
if (_sheet != other._sheet) {
|
||||
if (_sheetIndex != other._sheetIndex) {
|
||||
return false;
|
||||
}
|
||||
if (_srcRowNum != other._srcRowNum) {
|
||||
@ -75,7 +75,7 @@ final class EvaluationCycleDetector {
|
||||
* @return human readable string for debug purposes
|
||||
*/
|
||||
public String formatAsString() {
|
||||
return "R=" + _srcRowNum + " C=" + _srcColNum + " ShIx=" + _workbook.getSheetIndex(_sheet);
|
||||
return "R=" + _srcRowNum + " C=" + _srcColNum + " ShIx=" + _sheetIndex;
|
||||
}
|
||||
|
||||
public String toString() {
|
||||
@ -108,8 +108,8 @@ final class EvaluationCycleDetector {
|
||||
* @return <code>true</code> if the specified cell has not been visited yet in the current
|
||||
* evaluation. <code>false</code> if the specified cell is already being evaluated.
|
||||
*/
|
||||
public boolean startEvaluate(HSSFWorkbook workbook, HSSFSheet sheet, int srcRowNum, int srcColNum) {
|
||||
CellEvaluationFrame cef = new CellEvaluationFrame(workbook, sheet, srcRowNum, srcColNum);
|
||||
public boolean startEvaluate(HSSFWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
|
||||
CellEvaluationFrame cef = new CellEvaluationFrame(workbook, sheetIndex, srcRowNum, srcColNum);
|
||||
if (_evaluationFrames.contains(cef)) {
|
||||
return false;
|
||||
}
|
||||
@ -129,7 +129,7 @@ final class EvaluationCycleDetector {
|
||||
* required. However, they have been included to assert correct behaviour,
|
||||
* and form more meaningful error messages.
|
||||
*/
|
||||
public void endEvaluate(HSSFWorkbook workbook, HSSFSheet sheet, int srcRowNum, int srcColNum) {
|
||||
public void endEvaluate(HSSFWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
|
||||
int nFrames = _evaluationFrames.size();
|
||||
if (nFrames < 1) {
|
||||
throw new IllegalStateException("Call to endEvaluate without matching call to startEvaluate");
|
||||
@ -137,7 +137,7 @@ final class EvaluationCycleDetector {
|
||||
|
||||
nFrames--;
|
||||
CellEvaluationFrame cefExpected = (CellEvaluationFrame) _evaluationFrames.get(nFrames);
|
||||
CellEvaluationFrame cefActual = new CellEvaluationFrame(workbook, sheet, srcRowNum, srcColNum);
|
||||
CellEvaluationFrame cefActual = new CellEvaluationFrame(workbook, sheetIndex, srcRowNum, srcColNum);
|
||||
if (!cefActual.equals(cefExpected)) {
|
||||
throw new RuntimeException("Wrong cell specified. "
|
||||
+ "Corresponding startEvaluate() call was for cell {"
|
||||
|
@ -47,8 +47,6 @@ import org.apache.poi.hssf.record.formula.eval.BoolEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ErrorEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.Eval;
|
||||
import org.apache.poi.hssf.record.formula.eval.FunctionEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.LazyAreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.LazyRefEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NameEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NameXEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.NumberEval;
|
||||
@ -70,28 +68,36 @@ import org.apache.poi.hssf.util.CellReference;
|
||||
*/
|
||||
public class HSSFFormulaEvaluator {
|
||||
|
||||
/**
|
||||
* used to track the number of evaluations
|
||||
*/
|
||||
/**
|
||||
* used to track the number of evaluations
|
||||
*/
|
||||
private static final class Counter {
|
||||
public int value;
|
||||
public int depth;
|
||||
public Counter() {
|
||||
value = 0;
|
||||
}
|
||||
}
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private final HSSFWorkbook _workbook;
|
||||
private final EvaluationCache _cache;
|
||||
|
||||
private Counter _evaluationCounter;
|
||||
|
||||
/**
|
||||
* @deprecated (Sep 2008) HSSFSheet parameter is ignored
|
||||
*/
|
||||
public HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook) {
|
||||
this(sheet, workbook, new EvaluationCache(), new Counter());
|
||||
this(workbook);
|
||||
if (false) {
|
||||
sheet.toString(); // suppress unused parameter compiler warning
|
||||
}
|
||||
}
|
||||
public HSSFFormulaEvaluator(HSSFWorkbook workbook) {
|
||||
this(workbook, new EvaluationCache(), new Counter());
|
||||
}
|
||||
|
||||
private HSSFFormulaEvaluator(HSSFSheet sheet, HSSFWorkbook workbook, EvaluationCache cache, Counter evaluationCounter) {
|
||||
_sheet = sheet;
|
||||
private HSSFFormulaEvaluator(HSSFWorkbook workbook, EvaluationCache cache, Counter evaluationCounter) {
|
||||
_workbook = workbook;
|
||||
_cache = cache;
|
||||
_evaluationCounter = evaluationCounter;
|
||||
@ -100,7 +106,7 @@ public class HSSFFormulaEvaluator {
|
||||
/**
|
||||
* for debug use. Used in toString methods
|
||||
*/
|
||||
public String getSheetName(HSSFSheet sheet) {
|
||||
/* package */ String getSheetName(HSSFSheet sheet) {
|
||||
return _workbook.getSheetName(_workbook.getSheetIndex(sheet));
|
||||
}
|
||||
/**
|
||||
@ -159,34 +165,23 @@ public class HSSFFormulaEvaluator {
|
||||
* @param cell
|
||||
*/
|
||||
public CellValue evaluate(HSSFCell cell) {
|
||||
CellValue retval = null;
|
||||
if (cell != null) {
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_BLANK);
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_BOOLEAN);
|
||||
retval.setBooleanValue(cell.getBooleanCellValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_ERROR);
|
||||
retval.setErrorValue(cell.getErrorCellValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
retval = getCellValueForEval(internalEvaluate(cell, _sheet));
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_NUMERIC);
|
||||
retval.setNumberValue(cell.getNumericCellValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_STRING);
|
||||
retval.setRichTextStringValue(cell.getRichStringCellValue());
|
||||
break;
|
||||
}
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
return retval;
|
||||
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return CellValue.valueOf(cell.getBooleanCellValue());
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
return CellValue.getError(cell.getErrorCellValue());
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return evaluateFormulaCellValue(cell);
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
return new CellValue(cell.getNumericCellValue());
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new CellValue(cell.getRichStringCellValue());
|
||||
}
|
||||
throw new IllegalStateException("Bad cell type (" + cell.getCellType() + ")");
|
||||
}
|
||||
|
||||
|
||||
@ -209,32 +204,13 @@ public class HSSFFormulaEvaluator {
|
||||
* @return The type of the formula result (the cell's type remains as HSSFCell.CELL_TYPE_FORMULA however)
|
||||
*/
|
||||
public int evaluateFormulaCell(HSSFCell cell) {
|
||||
if (cell != null) {
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet));
|
||||
switch (cv.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
cell.setCellValue(cv.getBooleanValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
cell.setCellValue(cv.getErrorValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
cell.setCellValue(cv.getNumberValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellValue(cv.getRichTextStringValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_FORMULA: // this will never happen, we have already evaluated the formula
|
||||
break;
|
||||
}
|
||||
return cv.getCellType();
|
||||
}
|
||||
if (cell == null || cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
|
||||
return -1;
|
||||
}
|
||||
return -1;
|
||||
CellValue cv = evaluateFormulaCellValue(cell);
|
||||
// cell remains a formula cell, but the cached value is changed
|
||||
setCellValue(cell, cv);
|
||||
return cv.getCellType();
|
||||
}
|
||||
|
||||
/**
|
||||
@ -254,35 +230,56 @@ public class HSSFFormulaEvaluator {
|
||||
* @param cell
|
||||
*/
|
||||
public HSSFCell evaluateInCell(HSSFCell cell) {
|
||||
if (cell != null) {
|
||||
switch (cell.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
CellValue cv = getCellValueForEval(internalEvaluate(cell, _sheet));
|
||||
switch (cv.getCellType()) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
cell.setCellType(HSSFCell.CELL_TYPE_BOOLEAN);
|
||||
cell.setCellValue(cv.getBooleanValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
cell.setCellErrorValue(cv.getErrorValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
cell.setCellType(HSSFCell.CELL_TYPE_NUMERIC);
|
||||
cell.setCellValue(cv.getNumberValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellType(HSSFCell.CELL_TYPE_STRING);
|
||||
cell.setCellValue(cv.getRichTextStringValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_FORMULA: // this will never happen, we have already evaluated the formula
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (cell == null) {
|
||||
return null;
|
||||
}
|
||||
if (cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
||||
CellValue cv = evaluateFormulaCellValue(cell);
|
||||
setCellType(cell, cv); // cell will no longer be a formula cell
|
||||
setCellValue(cell, cv);
|
||||
}
|
||||
return cell;
|
||||
}
|
||||
private static void setCellType(HSSFCell cell, CellValue cv) {
|
||||
int cellType = cv.getCellType();
|
||||
switch (cellType) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellType(cellType);
|
||||
return;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
// never happens - blanks eventually get translated to zero
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
// this will never happen, we have already evaluated the formula
|
||||
}
|
||||
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
|
||||
}
|
||||
|
||||
private static void setCellValue(HSSFCell cell, CellValue cv) {
|
||||
int cellType = cv.getCellType();
|
||||
switch (cellType) {
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
cell.setCellValue(cv.getBooleanValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_ERROR:
|
||||
cell.setCellErrorValue(cv.getErrorValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||
cell.setCellValue(cv.getNumberValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
cell.setCellValue(cv.getRichTextStringValue());
|
||||
break;
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
// never happens - blanks eventually get translated to zero
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
// this will never happen, we have already evaluated the formula
|
||||
default:
|
||||
throw new IllegalStateException("Unexpected cell value type (" + cellType + ")");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Loops over all cells in all sheets of the supplied
|
||||
@ -296,9 +293,9 @@ public class HSSFFormulaEvaluator {
|
||||
* cells, and calling evaluateFormulaCell on each one.
|
||||
*/
|
||||
public static void evaluateAllFormulaCells(HSSFWorkbook wb) {
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
for(int i=0; i<wb.getNumberOfSheets(); i++) {
|
||||
HSSFSheet sheet = wb.getSheetAt(i);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||
|
||||
for (Iterator rit = sheet.rowIterator(); rit.hasNext();) {
|
||||
HSSFRow r = (HSSFRow)rit.next();
|
||||
@ -312,72 +309,61 @@ public class HSSFFormulaEvaluator {
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Returns a CellValue wrapper around the supplied ValueEval instance.
|
||||
* @param eval
|
||||
*/
|
||||
private static CellValue getCellValueForEval(ValueEval eval) {
|
||||
CellValue retval = null;
|
||||
if (eval != null) {
|
||||
if (eval instanceof NumberEval) {
|
||||
NumberEval ne = (NumberEval) eval;
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_NUMERIC);
|
||||
retval.setNumberValue(ne.getNumberValue());
|
||||
}
|
||||
else if (eval instanceof BoolEval) {
|
||||
BoolEval be = (BoolEval) eval;
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_BOOLEAN);
|
||||
retval.setBooleanValue(be.getBooleanValue());
|
||||
}
|
||||
else if (eval instanceof StringEval) {
|
||||
StringEval ne = (StringEval) eval;
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_STRING);
|
||||
retval.setStringValue(ne.getStringValue());
|
||||
}
|
||||
else if (eval instanceof BlankEval) {
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_BLANK);
|
||||
}
|
||||
else if (eval instanceof ErrorEval) {
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_ERROR);
|
||||
retval.setErrorValue((byte)((ErrorEval)eval).getErrorCode());
|
||||
// retval.setRichTextStringValue(new HSSFRichTextString("#An error occurred. check cell.getErrorCode()"));
|
||||
}
|
||||
else {
|
||||
retval = new CellValue(HSSFCell.CELL_TYPE_ERROR);
|
||||
}
|
||||
private CellValue evaluateFormulaCellValue(HSSFCell cell) {
|
||||
ValueEval eval = internalEvaluate(cell);
|
||||
if (eval instanceof NumberEval) {
|
||||
NumberEval ne = (NumberEval) eval;
|
||||
return new CellValue(ne.getNumberValue());
|
||||
}
|
||||
return retval;
|
||||
if (eval instanceof BoolEval) {
|
||||
BoolEval be = (BoolEval) eval;
|
||||
return CellValue.valueOf(be.getBooleanValue());
|
||||
}
|
||||
if (eval instanceof StringEval) {
|
||||
StringEval ne = (StringEval) eval;
|
||||
return new CellValue(new HSSFRichTextString(ne.getStringValue()));
|
||||
}
|
||||
if (eval instanceof ErrorEval) {
|
||||
return CellValue.getError(((ErrorEval)eval).getErrorCode());
|
||||
}
|
||||
throw new RuntimeException("Unexpected eval class (" + eval.getClass().getName() + ")");
|
||||
}
|
||||
|
||||
/**
|
||||
* Dev. Note: Internal evaluate must be passed only a formula cell
|
||||
* else a runtime exception will be thrown somewhere inside the method.
|
||||
* (Hence this is a private method.)
|
||||
* @return never <code>null</code>, never {@link BlankEval}
|
||||
*/
|
||||
private ValueEval internalEvaluate(HSSFCell srcCell, HSSFSheet sheet) {
|
||||
private ValueEval internalEvaluate(HSSFCell srcCell) {
|
||||
int srcRowNum = srcCell.getRowIndex();
|
||||
int srcColNum = srcCell.getCellNum();
|
||||
|
||||
ValueEval result;
|
||||
|
||||
int sheetIndex = _workbook.getSheetIndex(sheet);
|
||||
int sheetIndex = _workbook.findSheetIndex(srcCell.getSheet());
|
||||
result = _cache.getValue(sheetIndex, srcRowNum, srcColNum);
|
||||
if (result != null) {
|
||||
return result;
|
||||
}
|
||||
_evaluationCounter.value++;
|
||||
_evaluationCounter.depth++;
|
||||
|
||||
EvaluationCycleDetector tracker = EvaluationCycleDetectorManager.getTracker();
|
||||
|
||||
if(!tracker.startEvaluate(_workbook, sheet, srcRowNum, srcColNum)) {
|
||||
if(!tracker.startEvaluate(_workbook, sheetIndex, srcRowNum, srcColNum)) {
|
||||
return ErrorEval.CIRCULAR_REF_ERROR;
|
||||
}
|
||||
try {
|
||||
result = evaluateCell(srcRowNum, (short)srcColNum, srcCell.getCellFormula());
|
||||
result = evaluateCell(sheetIndex, srcRowNum, (short)srcColNum, srcCell.getCellFormula());
|
||||
} finally {
|
||||
tracker.endEvaluate(_workbook, sheet, srcRowNum, srcColNum);
|
||||
tracker.endEvaluate(_workbook, sheetIndex, srcRowNum, srcColNum);
|
||||
_cache.setValue(sheetIndex, srcRowNum, srcColNum, result);
|
||||
_evaluationCounter.depth--;
|
||||
}
|
||||
if (isDebugLogEnabled()) {
|
||||
String sheetName = _workbook.getSheetName(sheetIndex);
|
||||
@ -386,7 +372,7 @@ public class HSSFFormulaEvaluator {
|
||||
}
|
||||
return result;
|
||||
}
|
||||
private ValueEval evaluateCell(int srcRowNum, short srcColNum, String cellFormulaText) {
|
||||
private ValueEval evaluateCell(int sheetIndex, int srcRowNum, short srcColNum, String cellFormulaText) {
|
||||
|
||||
Ptg[] ptgs = FormulaParser.parse(cellFormulaText, _workbook);
|
||||
|
||||
@ -420,15 +406,15 @@ public class HSSFFormulaEvaluator {
|
||||
Eval p = (Eval) stack.pop();
|
||||
ops[j] = p;
|
||||
}
|
||||
logDebug("invoke " + operation + " (nAgs=" + numops + ")");
|
||||
opResult = invokeOperation(operation, ops, srcRowNum, srcColNum, _workbook, _sheet);
|
||||
// logDebug("invoke " + operation + " (nAgs=" + numops + ")");
|
||||
opResult = invokeOperation(operation, ops, _workbook, sheetIndex, srcRowNum, srcColNum);
|
||||
} else {
|
||||
opResult = getEvalForPtg(ptg, _sheet);
|
||||
opResult = getEvalForPtg(ptg, sheetIndex);
|
||||
}
|
||||
if (opResult == null) {
|
||||
throw new RuntimeException("Evaluation result must not be null");
|
||||
}
|
||||
logDebug("push " + opResult);
|
||||
// logDebug("push " + opResult);
|
||||
stack.push(opResult);
|
||||
}
|
||||
|
||||
@ -473,25 +459,22 @@ public class HSSFFormulaEvaluator {
|
||||
return evaluationResult;
|
||||
}
|
||||
|
||||
private static Eval invokeOperation(OperationEval operation, Eval[] ops, int srcRowNum, short srcColNum,
|
||||
HSSFWorkbook workbook, HSSFSheet sheet) {
|
||||
private static Eval invokeOperation(OperationEval operation, Eval[] ops,
|
||||
HSSFWorkbook workbook, int sheetIndex, int srcRowNum, int srcColNum) {
|
||||
|
||||
if(operation instanceof FunctionEval) {
|
||||
FunctionEval fe = (FunctionEval) operation;
|
||||
if(fe.isFreeRefFunction()) {
|
||||
return fe.getFreeRefFunction().evaluate(ops, srcRowNum, srcColNum, workbook, sheet);
|
||||
return fe.getFreeRefFunction().evaluate(ops, workbook, sheetIndex, srcRowNum, srcColNum);
|
||||
}
|
||||
}
|
||||
return operation.evaluate(ops, srcRowNum, srcColNum);
|
||||
return operation.evaluate(ops, srcRowNum, (short)srcColNum);
|
||||
}
|
||||
|
||||
private HSSFSheet getOtherSheet(int externSheetIndex) {
|
||||
Workbook wb = _workbook.getWorkbook();
|
||||
return _workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(externSheetIndex));
|
||||
}
|
||||
private HSSFFormulaEvaluator createEvaluatorForAnotherSheet(HSSFSheet sheet) {
|
||||
return new HSSFFormulaEvaluator(sheet, _workbook, _cache, _evaluationCounter);
|
||||
}
|
||||
|
||||
/**
|
||||
* returns an appropriate Eval impl instance for the Ptg. The Ptg must be
|
||||
@ -499,7 +482,7 @@ public class HSSFFormulaEvaluator {
|
||||
* StringPtg, BoolPtg <br/>special Note: OperationPtg subtypes cannot be
|
||||
* passed here!
|
||||
*/
|
||||
private Eval getEvalForPtg(Ptg ptg, HSSFSheet sheet) {
|
||||
private Eval getEvalForPtg(Ptg ptg, int sheetIndex) {
|
||||
if (ptg instanceof NamePtg) {
|
||||
// named ranges, macro functions
|
||||
NamePtg namePtg = (NamePtg) ptg;
|
||||
@ -514,7 +497,7 @@ public class HSSFFormulaEvaluator {
|
||||
return new NameEval(nameRecord.getNameText());
|
||||
}
|
||||
if (nameRecord.hasFormula()) {
|
||||
return evaluateNameFormula(nameRecord.getNameDefinition(), sheet);
|
||||
return evaluateNameFormula(nameRecord.getNameDefinition(), sheetIndex);
|
||||
}
|
||||
|
||||
throw new RuntimeException("Don't now how to evalate name '" + nameRecord.getNameText() + "'");
|
||||
@ -523,22 +506,6 @@ public class HSSFFormulaEvaluator {
|
||||
NameXPtg nameXPtg = (NameXPtg) ptg;
|
||||
return new NameXEval(nameXPtg.getSheetRefIndex(), nameXPtg.getNameIndex());
|
||||
}
|
||||
if (ptg instanceof RefPtg) {
|
||||
return new LazyRefEval(((RefPtg) ptg), sheet, this);
|
||||
}
|
||||
if (ptg instanceof Ref3DPtg) {
|
||||
Ref3DPtg refPtg = (Ref3DPtg) ptg;
|
||||
HSSFSheet xsheet = getOtherSheet(refPtg.getExternSheetIndex());
|
||||
return new LazyRefEval(refPtg, xsheet, createEvaluatorForAnotherSheet(xsheet));
|
||||
}
|
||||
if (ptg instanceof AreaPtg) {
|
||||
return new LazyAreaEval(((AreaPtg) ptg), sheet, this);
|
||||
}
|
||||
if (ptg instanceof Area3DPtg) {
|
||||
Area3DPtg a3dp = (Area3DPtg) ptg;
|
||||
HSSFSheet xsheet = getOtherSheet(a3dp.getExternSheetIndex());
|
||||
return new LazyAreaEval(a3dp, xsheet, createEvaluatorForAnotherSheet(xsheet));
|
||||
}
|
||||
|
||||
if (ptg instanceof IntPtg) {
|
||||
return new NumberEval(((IntPtg)ptg).getValue());
|
||||
@ -555,17 +522,38 @@ public class HSSFFormulaEvaluator {
|
||||
if (ptg instanceof ErrPtg) {
|
||||
return ErrorEval.valueOf(((ErrPtg) ptg).getErrorCode());
|
||||
}
|
||||
HSSFSheet sheet = _workbook.getSheetAt(sheetIndex);
|
||||
if (ptg instanceof RefPtg) {
|
||||
return new LazyRefEval(((RefPtg) ptg), sheet, this);
|
||||
}
|
||||
if (ptg instanceof AreaPtg) {
|
||||
return new LazyAreaEval(((AreaPtg) ptg), sheet, this);
|
||||
}
|
||||
if (ptg instanceof Ref3DPtg) {
|
||||
Ref3DPtg refPtg = (Ref3DPtg) ptg;
|
||||
HSSFSheet xsheet = getOtherSheet(refPtg.getExternSheetIndex());
|
||||
return new LazyRefEval(refPtg, xsheet, this);
|
||||
}
|
||||
if (ptg instanceof Area3DPtg) {
|
||||
Area3DPtg a3dp = (Area3DPtg) ptg;
|
||||
HSSFSheet xsheet = getOtherSheet(a3dp.getExternSheetIndex());
|
||||
return new LazyAreaEval(a3dp, xsheet, this);
|
||||
}
|
||||
|
||||
if (ptg instanceof UnknownPtg) {
|
||||
// TODO - remove UnknownPtg
|
||||
// POI uses UnknownPtg when the encoded Ptg array seems to be corrupted.
|
||||
// This seems to occur in very rare cases (e.g. unused name formulas in bug 44774, attachment 21790)
|
||||
// In any case, formulas are re-parsed before execution, so UnknownPtg should not get here
|
||||
throw new RuntimeException("UnknownPtg not allowed");
|
||||
}
|
||||
|
||||
throw new RuntimeException("Unexpected ptg class (" + ptg.getClass().getName() + ")");
|
||||
}
|
||||
private Eval evaluateNameFormula(Ptg[] ptgs, HSSFSheet sheet) {
|
||||
private Eval evaluateNameFormula(Ptg[] ptgs, int sheetIndex) {
|
||||
if (ptgs.length > 1) {
|
||||
throw new RuntimeException("Complex name formulas not supported yet");
|
||||
}
|
||||
return getEvalForPtg(ptgs[0], sheet);
|
||||
return getEvalForPtg(ptgs[0], sheetIndex);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -573,11 +561,8 @@ public class HSSFFormulaEvaluator {
|
||||
* impl instance and return that. Since the cell could be an external
|
||||
* reference, we need the sheet that this belongs to.
|
||||
* Non existent cells are treated as empty.
|
||||
* @param cell
|
||||
* @param sheet
|
||||
* @param workbook
|
||||
*/
|
||||
public ValueEval getEvalForCell(HSSFCell cell, HSSFSheet sheet) {
|
||||
/* package */ ValueEval getEvalForCell(HSSFCell cell) {
|
||||
|
||||
if (cell == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
@ -588,7 +573,7 @@ public class HSSFFormulaEvaluator {
|
||||
case HSSFCell.CELL_TYPE_STRING:
|
||||
return new StringEval(cell.getRichStringCellValue().getString());
|
||||
case HSSFCell.CELL_TYPE_FORMULA:
|
||||
return internalEvaluate(cell, sheet);
|
||||
return internalEvaluate(cell);
|
||||
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||
return BoolEval.valueOf(cell.getBooleanCellValue());
|
||||
case HSSFCell.CELL_TYPE_BLANK:
|
||||
@ -606,43 +591,50 @@ public class HSSFFormulaEvaluator {
|
||||
* @author Amol S. Deshmukh < amolweb at ya hoo dot com >
|
||||
*/
|
||||
public static final class CellValue {
|
||||
private int cellType;
|
||||
private HSSFRichTextString richTextStringValue;
|
||||
private double numberValue;
|
||||
private boolean booleanValue;
|
||||
private byte errorValue;
|
||||
public static final CellValue TRUE = new CellValue(HSSFCell.CELL_TYPE_BOOLEAN, 0.0, true, null, 0);
|
||||
public static final CellValue FALSE= new CellValue(HSSFCell.CELL_TYPE_BOOLEAN, 0.0, false, null, 0);
|
||||
|
||||
private final int _cellType;
|
||||
private final double _numberValue;
|
||||
private final boolean _booleanValue;
|
||||
private final HSSFRichTextString _richTextStringValue;
|
||||
private final int _errorCode;
|
||||
|
||||
/**
|
||||
* CellType should be one of the types defined in HSSFCell
|
||||
* @param cellType
|
||||
*/
|
||||
public CellValue(int cellType) {
|
||||
super();
|
||||
this.cellType = cellType;
|
||||
private CellValue(int cellType, double numberValue, boolean booleanValue,
|
||||
HSSFRichTextString textValue, int errorCode) {
|
||||
_cellType = cellType;
|
||||
_numberValue = numberValue;
|
||||
_booleanValue = booleanValue;
|
||||
_richTextStringValue = textValue;
|
||||
_errorCode = errorCode;
|
||||
}
|
||||
|
||||
|
||||
/* package*/ CellValue(double numberValue) {
|
||||
this(HSSFCell.CELL_TYPE_NUMERIC, numberValue, false, null, 0);
|
||||
}
|
||||
/* package*/ static CellValue valueOf(boolean booleanValue) {
|
||||
return booleanValue ? TRUE : FALSE;
|
||||
}
|
||||
/* package*/ CellValue(HSSFRichTextString stringValue) {
|
||||
this(HSSFCell.CELL_TYPE_STRING, 0.0, false, stringValue, 0);
|
||||
}
|
||||
/* package*/ static CellValue getError(int errorCode) {
|
||||
return new CellValue(HSSFCell.CELL_TYPE_ERROR, 0.0, false, null, errorCode);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* @return Returns the booleanValue.
|
||||
*/
|
||||
public boolean getBooleanValue() {
|
||||
return booleanValue;
|
||||
}
|
||||
/**
|
||||
* @param booleanValue The booleanValue to set.
|
||||
*/
|
||||
public void setBooleanValue(boolean booleanValue) {
|
||||
this.booleanValue = booleanValue;
|
||||
return _booleanValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the numberValue.
|
||||
*/
|
||||
public double getNumberValue() {
|
||||
return numberValue;
|
||||
}
|
||||
/**
|
||||
* @param numberValue The numberValue to set.
|
||||
*/
|
||||
public void setNumberValue(double numberValue) {
|
||||
this.numberValue = numberValue;
|
||||
return _numberValue;
|
||||
}
|
||||
/**
|
||||
* @return Returns the stringValue. This method is deprecated, use
|
||||
@ -650,45 +642,25 @@ public class HSSFFormulaEvaluator {
|
||||
* @deprecated
|
||||
*/
|
||||
public String getStringValue() {
|
||||
return richTextStringValue.getString();
|
||||
}
|
||||
/**
|
||||
* @param stringValue The stringValue to set. This method is deprecated, use
|
||||
* getRichTextStringValue instead.
|
||||
* @deprecated
|
||||
*/
|
||||
public void setStringValue(String stringValue) {
|
||||
this.richTextStringValue = new HSSFRichTextString(stringValue);
|
||||
return _richTextStringValue.getString();
|
||||
}
|
||||
/**
|
||||
* @return Returns the cellType.
|
||||
*/
|
||||
public int getCellType() {
|
||||
return cellType;
|
||||
return _cellType;
|
||||
}
|
||||
/**
|
||||
* @return Returns the errorValue.
|
||||
*/
|
||||
public byte getErrorValue() {
|
||||
return errorValue;
|
||||
}
|
||||
/**
|
||||
* @param errorValue The errorValue to set.
|
||||
*/
|
||||
public void setErrorValue(byte errorValue) {
|
||||
this.errorValue = errorValue;
|
||||
return (byte) _errorCode;
|
||||
}
|
||||
/**
|
||||
* @return Returns the richTextStringValue.
|
||||
*/
|
||||
public HSSFRichTextString getRichTextStringValue() {
|
||||
return richTextStringValue;
|
||||
}
|
||||
/**
|
||||
* @param richTextStringValue The richTextStringValue to set.
|
||||
*/
|
||||
public void setRichTextStringValue(HSSFRichTextString richTextStringValue) {
|
||||
this.richTextStringValue = richTextStringValue;
|
||||
return _richTextStringValue;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -15,21 +15,21 @@
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula.eval;
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaI;
|
||||
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEvalBase;
|
||||
import org.apache.poi.hssf.record.formula.eval.BlankEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class LazyAreaEval extends AreaEvalBase {
|
||||
final class LazyAreaEval extends AreaEvalBase {
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private HSSFFormulaEvaluator _evaluator;
|
||||
@ -53,7 +53,7 @@ public final class LazyAreaEval extends AreaEvalBase {
|
||||
if (cell == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
}
|
||||
return _evaluator.getEvalForCell(cell, _sheet);
|
||||
return _evaluator.getEvalForCell(cell);
|
||||
}
|
||||
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
@ -15,23 +15,23 @@
|
||||
limitations under the License.
|
||||
==================================================================== */
|
||||
|
||||
package org.apache.poi.hssf.record.formula.eval;
|
||||
package org.apache.poi.hssf.usermodel;
|
||||
|
||||
import org.apache.poi.hssf.record.formula.AreaI;
|
||||
import org.apache.poi.hssf.record.formula.Ref3DPtg;
|
||||
import org.apache.poi.hssf.record.formula.RefPtg;
|
||||
import org.apache.poi.hssf.record.formula.AreaI.OffsetArea;
|
||||
import org.apache.poi.hssf.usermodel.HSSFCell;
|
||||
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
|
||||
import org.apache.poi.hssf.usermodel.HSSFRow;
|
||||
import org.apache.poi.hssf.usermodel.HSSFSheet;
|
||||
import org.apache.poi.hssf.record.formula.eval.AreaEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.BlankEval;
|
||||
import org.apache.poi.hssf.record.formula.eval.RefEvalBase;
|
||||
import org.apache.poi.hssf.record.formula.eval.ValueEval;
|
||||
import org.apache.poi.hssf.util.CellReference;
|
||||
|
||||
/**
|
||||
*
|
||||
* @author Josh Micich
|
||||
*/
|
||||
public final class LazyRefEval extends RefEvalBase {
|
||||
final class LazyRefEval extends RefEvalBase {
|
||||
|
||||
private final HSSFSheet _sheet;
|
||||
private final HSSFFormulaEvaluator _evaluator;
|
||||
@ -60,7 +60,7 @@ public final class LazyRefEval extends RefEvalBase {
|
||||
if (cell == null) {
|
||||
return BlankEval.INSTANCE;
|
||||
}
|
||||
return _evaluator.getEvalForCell(cell, _sheet);
|
||||
return _evaluator.getEvalForCell(cell);
|
||||
}
|
||||
|
||||
public AreaEval offset(int relFirstRowIx, int relLastRowIx, int relFirstColIx, int relLastColIx) {
|
@ -85,7 +85,7 @@ public final class TestFormulaParserEval extends TestCase {
|
||||
sheet.createRow(32768).createCell(0).setCellValue(31);
|
||||
sheet.createRow(32769).createCell(0).setCellValue(11);
|
||||
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue result;
|
||||
try {
|
||||
result = fe.evaluate(cell);
|
||||
|
@ -74,7 +74,7 @@ public final class TestExternalFunctionFormulas extends TestCase {
|
||||
public void testEvaluate() {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("externalFunctionExample.xls");
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
confirmCellEval(sheet, 0, 0, fe, "YEARFRAC(B1,C1)", 29.0/90.0);
|
||||
confirmCellEval(sheet, 1, 0, fe, "YEARFRAC(B2,C2)", 0.0);
|
||||
confirmCellEval(sheet, 2, 0, fe, "YEARFRAC(B3,C3,D3)", 0.0);
|
||||
|
@ -56,7 +56,7 @@ public final class TestYearFracCalculatorFromSpreadsheet extends TestCase {
|
||||
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("yearfracExamples.xls");
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator formulaEvaluator = new HSSFFormulaEvaluator(wb);
|
||||
int nSuccess = 0;
|
||||
int nFailures = 0;
|
||||
int nUnexpectedErrors = 0;
|
||||
|
@ -35,9 +35,9 @@ public final class TestCircularReferences extends TestCase {
|
||||
/**
|
||||
* Translates StackOverflowError into AssertionFailedError
|
||||
*/
|
||||
private static CellValue evaluateWithCycles(HSSFWorkbook wb, HSSFSheet sheet, HSSFCell testCell)
|
||||
private static CellValue evaluateWithCycles(HSSFWorkbook wb, HSSFCell testCell)
|
||||
throws AssertionFailedError {
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
try {
|
||||
return evaluator.evaluate(testCell);
|
||||
} catch (StackOverflowError e) {
|
||||
@ -75,7 +75,7 @@ public final class TestCircularReferences extends TestCase {
|
||||
// arguments before invoking operators, POI must handle such potential cycles gracefully.
|
||||
|
||||
|
||||
CellValue cellValue = evaluateWithCycles(wb, sheet, testCell);
|
||||
CellValue cellValue = evaluateWithCycles(wb, testCell);
|
||||
|
||||
assertTrue(cellValue.getCellType() == HSSFCell.CELL_TYPE_NUMERIC);
|
||||
assertEquals(2, cellValue.getNumberValue(), 0);
|
||||
@ -93,7 +93,7 @@ public final class TestCircularReferences extends TestCase {
|
||||
HSSFCell testCell = row.createCell(0);
|
||||
testCell.setCellFormula("A1");
|
||||
|
||||
CellValue cellValue = evaluateWithCycles(wb, sheet, testCell);
|
||||
CellValue cellValue = evaluateWithCycles(wb, testCell);
|
||||
|
||||
confirmCycleErrorCode(cellValue);
|
||||
}
|
||||
@ -113,7 +113,7 @@ public final class TestCircularReferences extends TestCase {
|
||||
HSSFCell testCell = row.createCell(3);
|
||||
testCell.setCellFormula("A1");
|
||||
|
||||
CellValue cellValue = evaluateWithCycles(wb, sheet, testCell);
|
||||
CellValue cellValue = evaluateWithCycles(wb, testCell);
|
||||
|
||||
confirmCycleErrorCode(cellValue);
|
||||
}
|
||||
|
@ -65,7 +65,7 @@ public final class TestExternalFunction extends TestCase {
|
||||
String actualFormula=cell.getCellFormula();
|
||||
assertEquals("myFunc()", actualFormula);
|
||||
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue evalResult = fe.evaluate(cell);
|
||||
|
||||
// Check the return value from ExternalFunction.evaluate()
|
||||
|
@ -66,7 +66,7 @@ public final class TestFormulaBugs extends TestCase {
|
||||
.getCellFormula());
|
||||
|
||||
// We might as well evaluate the formula
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue cv = fe.evaluate(cell);
|
||||
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
|
||||
@ -111,7 +111,7 @@ public final class TestFormulaBugs extends TestCase {
|
||||
}
|
||||
|
||||
// use POI's evaluator as an extra sanity check
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue cv;
|
||||
cv = fe.evaluate(cell);
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
|
||||
@ -162,7 +162,7 @@ public final class TestFormulaBugs extends TestCase {
|
||||
|
||||
double expectedResult = (4.0 * 8.0 + 5.0 * 9.0) / 10.0;
|
||||
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet1, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue cv = fe.evaluate(cell);
|
||||
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
|
||||
|
@ -178,7 +178,7 @@ public final class TestFormulasFromSpreadsheet extends TestCase {
|
||||
*/
|
||||
private void processFunctionGroup(int startRowIndex, String testFocusFunctionName) {
|
||||
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, workbook);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
|
||||
|
||||
int rowIndex = startRowIndex;
|
||||
while (true) {
|
||||
|
@ -67,7 +67,7 @@ public final class TestPercentEval extends TestCase {
|
||||
cell.setCellFormula("B1%");
|
||||
row.createCell(1).setCellValue(50.0);
|
||||
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue cv;
|
||||
try {
|
||||
cv = fe.evaluate(cell);
|
||||
|
@ -268,7 +268,7 @@ public final class TestCountFuncs extends TestCase {
|
||||
int failureCount = 0;
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook(FILE_NAME);
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
int maxRow = sheet.getLastRowNum();
|
||||
for (int rowIx=START_ROW_IX; rowIx<maxRow; rowIx++) {
|
||||
HSSFRow row = sheet.getRow(rowIx);
|
||||
|
@ -37,7 +37,7 @@ public final class TestDate extends TestCase {
|
||||
HSSFSheet sheet = wb.createSheet("new sheet");
|
||||
cell11 = sheet.createRow(0).createCell(0);
|
||||
cell11.setCellType(HSSFCell.CELL_TYPE_FORMULA);
|
||||
evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||
evaluator = new HSSFFormulaEvaluator(wb);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -177,7 +177,7 @@ public final class TestIndexFunctionFromSpreadsheet extends TestCase {
|
||||
|
||||
private void processTestSheet(HSSFWorkbook workbook, String sheetName) {
|
||||
HSSFSheet sheet = workbook.getSheetAt(0);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, workbook);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
|
||||
int maxRows = sheet.getLastRowNum()+1;
|
||||
int result = Result.NO_EVALUATIONS_FOUND; // so far
|
||||
|
||||
|
@ -44,7 +44,7 @@ public final class TestIsBlank extends TestCase {
|
||||
|
||||
cell.setCellFormula("isblank(Sheet2!A1:A1)");
|
||||
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet1, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue result = fe.evaluate(cell);
|
||||
assertEquals(HSSFCell.CELL_TYPE_BOOLEAN, result.getCellType());
|
||||
assertEquals(true, result.getBooleanValue());
|
||||
|
@ -211,7 +211,7 @@ public final class TestLookupFunctionsFromSpreadsheet extends TestCase {
|
||||
|
||||
private int processTestSheet(HSSFWorkbook workbook, int sheetIndex, String sheetName) {
|
||||
HSSFSheet sheet = workbook.getSheetAt(sheetIndex);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, workbook);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(workbook);
|
||||
int maxRows = sheet.getLastRowNum()+1;
|
||||
int result = Result.NO_EVALUATIONS_FOUND; // so far
|
||||
|
||||
|
@ -43,10 +43,9 @@ public final class TestBug42464 extends TestCase {
|
||||
}
|
||||
|
||||
private static void process(HSSFWorkbook wb) {
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(wb);
|
||||
for(int i=0; i<wb.getNumberOfSheets(); i++) {
|
||||
HSSFSheet s = wb.getSheetAt(i);
|
||||
HSSFFormulaEvaluator eval =
|
||||
new HSSFFormulaEvaluator(s, wb);
|
||||
|
||||
Iterator it = s.rowIterator();
|
||||
while(it.hasNext()) {
|
||||
|
@ -39,7 +39,7 @@ public final class TestBug43093 extends TestCase {
|
||||
}
|
||||
|
||||
public void testBug43093() {
|
||||
HSSFWorkbook xlw = new HSSFWorkbook();
|
||||
HSSFWorkbook xlw = new HSSFWorkbook();
|
||||
|
||||
addNewSheetWithCellsA1toD4(xlw, 1);
|
||||
addNewSheetWithCellsA1toD4(xlw, 2);
|
||||
@ -51,7 +51,7 @@ public final class TestBug43093 extends TestCase {
|
||||
HSSFCell s2E4 = s2r3.createCell(4);
|
||||
s2E4.setCellFormula("SUM(s3!B2:C3)");
|
||||
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(s2, xlw);
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(xlw);
|
||||
double d = eva.evaluate(s2E4).getNumberValue();
|
||||
|
||||
// internalEvaluate(...) Area3DEval.: 311+312+321+322 expected
|
||||
|
@ -1183,7 +1183,7 @@ public final class TestBugs extends TestCase {
|
||||
|
||||
|
||||
// Now evaluate, they should all be changed
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(s, wb);
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(wb);
|
||||
eval.evaluateFormulaCell(c1);
|
||||
eval.evaluateFormulaCell(c2);
|
||||
eval.evaluateFormulaCell(c3);
|
||||
|
@ -117,7 +117,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
||||
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
row = sheet.getRow(0);
|
||||
cell = row.getCell(0);
|
||||
@ -177,7 +177,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
||||
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator eva = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
// =index(C:C,2,1) -> 2
|
||||
HSSFRow rowIDX = sheet.getRow(3);
|
||||
@ -238,7 +238,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
||||
|
||||
cell.setCellFormula("1=1");
|
||||
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
try {
|
||||
fe.evaluateInCell(cell);
|
||||
} catch (NumberFormatException e) {
|
||||
@ -257,7 +257,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
||||
int numSheets = wb.getNumberOfSheets();
|
||||
for (int i = 0; i < numSheets; i++) {
|
||||
HSSFSheet s = wb.getSheetAt(i);
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(s, wb);
|
||||
HSSFFormulaEvaluator eval = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
for (Iterator rows = s.rowIterator(); rows.hasNext();) {
|
||||
HSSFRow r = (HSSFRow) rows.next();
|
||||
@ -276,7 +276,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
||||
HSSFRow row = sheet.createRow(1);
|
||||
HSSFCell cell = row.createCell(0);
|
||||
cell.setCellFormula("na()"); // this formula evaluates to an Excel error code '#N/A'
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
try {
|
||||
fe.evaluateInCell(cell);
|
||||
} catch (NumberFormatException e) {
|
||||
@ -312,7 +312,7 @@ public final class TestFormulaEvaluatorBugs extends TestCase {
|
||||
|
||||
// Choose cell A9, so that the failing test case doesn't take too long to execute.
|
||||
HSSFCell cell = row.getCell(8);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
evaluator.evaluate(cell);
|
||||
int evalCount = evaluator.getEvaluationCount();
|
||||
// With caching, the evaluationCount is 8 which is a big improvement
|
||||
|
@ -68,7 +68,7 @@ public final class TestFormulaEvaluatorDocs extends TestCase {
|
||||
// uses evaluateFormulaCell()
|
||||
for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {
|
||||
HSSFSheet sheet = wb.getSheetAt(sheetNum);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
for(Iterator rit = sheet.rowIterator(); rit.hasNext();) {
|
||||
HSSFRow r = (HSSFRow)rit.next();
|
||||
@ -103,7 +103,7 @@ public final class TestFormulaEvaluatorDocs extends TestCase {
|
||||
// uses evaluateInCell()
|
||||
for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {
|
||||
HSSFSheet sheet = wb.getSheetAt(sheetNum);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
|
||||
for(Iterator rit = sheet.rowIterator(); rit.hasNext();) {
|
||||
HSSFRow r = (HSSFRow)rit.next();
|
||||
|
@ -243,7 +243,7 @@ public final class TestHSSFDataFormatter extends TestCase {
|
||||
assertEquals("SUM(12.25,12.25)/100", formatter.formatCellValue(cell));
|
||||
|
||||
// now with a formula evaluator
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb.getSheetAt(0), wb);
|
||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(wb);
|
||||
log(formatter.formatCellValue(cell, evaluator) + "\t\t\t (with evaluator)");
|
||||
assertEquals("24.50%", formatter.formatCellValue(cell,evaluator));
|
||||
}
|
||||
@ -257,7 +257,7 @@ public final class TestHSSFDataFormatter extends TestCase {
|
||||
Iterator it = row.cellIterator();
|
||||
Format defaultFormat = new DecimalFormat("Balance $#,#00.00 USD;Balance -$#,#00.00 USD");
|
||||
formatter.setDefaultNumberFormat(defaultFormat);
|
||||
double value = 10d;
|
||||
|
||||
log("\n==== DEFAULT NUMBER FORMAT ====");
|
||||
while (it.hasNext()) {
|
||||
HSSFCell cell = (HSSFCell) it.next();
|
||||
|
@ -35,7 +35,7 @@ public final class TestHSSFFormulaEvaluator extends TestCase {
|
||||
HSSFWorkbook wb = HSSFTestDataSamples.openSampleWorkbook("testNames.xls");
|
||||
HSSFSheet sheet = wb.getSheetAt(0);
|
||||
HSSFCell cell = sheet.getRow(8).getCell(0);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
CellValue cv = fe.evaluate(cell);
|
||||
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
|
||||
assertEquals(3.72, cv.getNumberValue(), 0.0);
|
||||
@ -67,7 +67,7 @@ public final class TestHSSFFormulaEvaluator extends TestCase {
|
||||
setValue(sheet, 3, 6, 100.0);
|
||||
|
||||
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
|
||||
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
|
||||
assertEquals(26.0, fe.evaluate(cell0).getNumberValue(), 0.0);
|
||||
assertEquals(56.0, fe.evaluate(cell1).getNumberValue(), 0.0);
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user