【问题标题】:How to set blank cell as 0 during formula evaluation in Apache poi java如何在Apache poi java中的公式评估期间将空白单元格设置为0
【发布时间】: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,...)-公式,即使B1C1 为空白,也会计算apache poi 5.0.0。所以无法重现。对于CustomFunction,我们至少需要定义。
  • 嘿 Axel,我不认为我有最新版本的 Apache poi,让我用最新版本尝试一次。非常感谢您的评论,我将使用自定义函数定义更新问题。
  • 请同时显示准确的EvaluationException (stacktrace)。
  • CustomFunction.java 代码行 22 是什么代码行?堆栈跟踪来自...} catch (EvaluationException e) { e.printStackTrace() ;...,它显示OperandResolver 失败。所以args[0]args[1] 都指向错误值本身。所以A1B1 都包含错误值。只需不要e.printStackTrace() 并且评估器将返回该错误值作为结果。当A1B1 包含错误值时,它还应该返回什么?
  • 如果公式是=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


【解决方案1】:

我会这样做:

=if(and(A1>0,B1>0,C1>0), do something,not something)

AND() 确保所有 3 个单元格都大于 o,Excel 将空白视为 0,但如果单元格有空格等,您可能需要进行错误检查。

【讨论】:

  • 我知道 excel 将空白视为 0,但如何让 Apache poi 将空白视为 0
  • 你标记了 Excel,所以我给你一些 Excel 的东西......
  • 嗯,它是使用 java Apache poi 的 excel,问题本身包含该
  • @Doofenshmirtz 所以使用逻辑并将其应用到你想要的地方。
  • 我无法更改excel文件中的公式,我只能控制java代码,所以就像你说的添加“和”,我不能这样做
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多