【发布时间】:2021-07-13 08:40:36
【问题描述】:
我有一个 xlsm 文件,其中很少有单元格给出 3 个表格的累积结果。
但是,有时只有 1 个表有值,其余 2 个是空白的。
因此,当我在 Apache poi 中对累积结果表运行公式评估时,我得到了评估异常,因为剩余 2 个表中的值是空白的。
例子
Cumulative cells D1, E1
D1 = CustomFunction(A1,B1)
E1 = IF(A1+B1+C1=0, do something)
/*
CustomFunction definition is added in a class which implements FreeRefFunction and added to workbook using workbook.addToolPack(udfToolPack).
https://poi.apache.org/components/spreadsheet/user-defined-functions.html
*/
A1= 5
B1 = blank
C1 = blank
如果我这样做了
evaluator.evaluateFormulaCell(cellD1);
evaluator.evaluateFormulaCell(cellE1);
我得到了评估异常
org.apache.poi.ss.formula.eval.EvaluationException
at org.apache.poi.ss.formula.eval.OperandResolver.getSingleValue(OperandResolver.java:69)
at CustomFunction.evaluate(CustomFunction.java:22)
at org.apache.poi.ss.formula.UserDefinedFunction.evaluate(UserDefinedFunction.java:64)
at org.apache.poi.ss.formula.OperationEvaluatorFactory.evaluate(OperationEvaluatorFactory.java:129)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:525)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:288)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateReference(WorkbookEvaluator.java:702)
at org.apache.poi.ss.formula.SheetRefEvaluator.getEvalForCell(SheetRefEvaluator.java:51)
at org.apache.poi.ss.formula.LazyRefEval.getInnerValueEval(LazyRefEval.java:44)
at org.apache.poi.ss.formula.eval.OperandResolver.getSingleValue(OperandResolver.java:62)
at org.apache.poi.ss.formula.eval.TwoOperandNumericOperation.singleOperandEvaluate(TwoOperandNumericOperation.java:29)
at org.apache.poi.ss.formula.eval.TwoOperandNumericOperation.evaluate(TwoOperandNumericOperation.java:35)
at org.apache.poi.ss.formula.functions.Fixed2ArgFunction.evaluate(Fixed2ArgFunction.java:33)
at org.apache.poi.ss.formula.OperationEvaluatorFactory.evaluate(OperationEvaluatorFactory.java:119)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:525)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:288)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateReference(WorkbookEvaluator.java:702)
at org.apache.poi.ss.formula.SheetRefEvaluator.getEvalForCell(SheetRefEvaluator.java:51)
at org.apache.poi.ss.formula.LazyRefEval.getInnerValueEval(LazyRefEval.java:44)
at org.apache.poi.ss.formula.eval.OperandResolver.getSingleValue(OperandResolver.java:62)
at org.apache.poi.ss.formula.eval.TwoOperandNumericOperation.singleOperandEvaluate(TwoOperandNumericOperation.java:29)
at org.apache.poi.ss.formula.eval.TwoOperandNumericOperation.evaluate(TwoOperandNumericOperation.java:36)
at org.apache.poi.ss.formula.functions.Fixed2ArgFunction.evaluate(Fixed2ArgFunction.java:33)
at org.apache.poi.ss.formula.OperationEvaluatorFactory.evaluate(OperationEvaluatorFactory.java:119)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:525)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:288)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateReference(WorkbookEvaluator.java:702)
at org.apache.poi.ss.formula.SheetRefEvaluator.getEvalForCell(SheetRefEvaluator.java:51)
at org.apache.poi.ss.formula.LazyRefEval.getInnerValueEval(LazyRefEval.java:44)
at org.apache.poi.ss.formula.eval.OperandResolver.getSingleValue(OperandResolver.java:62)
at org.apache.poi.ss.formula.eval.TwoOperandNumericOperation.singleOperandEvaluate(TwoOperandNumericOperation.java:29)
at org.apache.poi.ss.formula.eval.TwoOperandNumericOperation.evaluate(TwoOperandNumericOperation.java:36)
at org.apache.poi.ss.formula.functions.Fixed2ArgFunction.evaluate(Fixed2ArgFunction.java:33)
at org.apache.poi.ss.formula.OperationEvaluatorFactory.evaluate(OperationEvaluatorFactory.java:119)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:525)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:288)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateReference(WorkbookEvaluator.java:702)
at org.apache.poi.ss.formula.SheetRefEvaluator.getEvalForCell(SheetRefEvaluator.java:51)
at org.apache.poi.ss.formula.LazyRefEval.getInnerValueEval(LazyRefEval.java:44)
at org.apache.poi.ss.formula.eval.OperandResolver.getSingleValue(OperandResolver.java:62)
at org.apache.poi.ss.formula.eval.RelationalOperationEval.evaluate(RelationalOperationEval.java:64)
at org.apache.poi.ss.formula.functions.Fixed2ArgFunction.evaluate(Fixed2ArgFunction.java:33)
at org.apache.poi.ss.formula.OperationEvaluatorFactory.evaluate(OperationEvaluatorFactory.java:119)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:525)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:288)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluate(WorkbookEvaluator.java:230)
at org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator.evaluateFormulaCellValue(XSSFFormulaEvaluator.java:264)
at org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator.evaluateFormulaCell(XSSFFormulaEvaluator.java:151)
at ExcelProcessor.main(ExcelProcessor.java:314)
CustomFunction.java
public class CustomFunction implements FreeRefFunction {
public ValueEval evaluate( ValueEval[] args, OperationEvaluationContext ec ) {
if (args.length != 2) {
return ErrorEval.VALUE_INVALID;
}
double val;
double result;
int length;
try {
ValueEval v1 = OperandResolver.getSingleValue( args[0],
ec.getRowIndex(),
ec.getColumnIndex() ) ;
ValueEval v2 = OperandResolver.getSingleValue( args[1],
ec.getRowIndex(),
ec.getColumnIndex() ) ;
val = OperandResolver.coerceValueToDouble(v1) ;
length = OperandResolver.coerceValueToInt(v2);
result = calculate( val, length) ;
checkValue(result);
} catch (EvaluationException e) {
e.printStackTrace() ;
return e.getErrorEval();
}
return new NumberEval( result ) ;
}
public double calculate( double val, int length) {
double retVal = 0.0; //some complex calculation
return retVal;
}
static final void checkValue(double result) throws EvaluationException {
if (Double.isNaN(result) || Double.isInfinite(result)) {
throw new EvaluationException(ErrorEval.NUM_ERROR);
}
}
}
那么,在公式评估中,我如何将空白值视为 0?
【问题讨论】:
-
请显示准确的
EvaluationException(堆栈跟踪)。对于=IF(A1+B1+C1=0,...)-公式,即使B1和C1为空白,也会计算apache poi 5.0.0。所以无法重现。对于CustomFunction,我们至少需要定义。 -
嘿 Axel,我不认为我有最新版本的 Apache poi,让我用最新版本尝试一次。非常感谢您的评论,我将使用自定义函数定义更新问题。
-
请同时显示准确的
EvaluationException(stacktrace)。 -
CustomFunction.java代码行 22 是什么代码行?堆栈跟踪来自...} catch (EvaluationException e) { e.printStackTrace() ;...,它显示OperandResolver失败。所以args[0]或args[1]都指向错误值本身。所以A1或B1都包含错误值。只需不要e.printStackTrace()并且评估器将返回该错误值作为结果。当A1或B1包含错误值时,它还应该返回什么? -
如果公式是
=CustomFunction(A1,B1),如您所说,ValueEval[] args包含org.apache.poi.ss.formula.LazyRefEval[SheetName!A1]和org.apache.poi.ss.formula.LazyRefEval[SheetName!B1]。如果A1包含 5 并且B1为空,如您所说,那么ValueEval v1将是org.apache.poi.ss.formula.eval.NumberEval [5]和ValueEval v2将是org.apache.poi.ss.formula.eval.BlankEval。并且不会抛出EvaluationException。
标签: java excel excel-formula apache-poi evaluate