在Apache Poi(Java)中从Excel单元格执行公式(包含特殊字符)时出错

lyr7nygr  于 2023-04-04  发布在  Java
关注(0)|答案(1)|浏览(404)

我在一个工作表的单元格中有一个公式,如图所示。这里的特殊之处在于,因为工作表名称是用日语写的,所以它包含一个特殊字符:“["。示例:Formula
当使用Apache Poi提供的“evaluateInCell(cell)”函数时,它似乎无法处理该特殊字符。
参考代码如下。

case FORMULA: {
                String formula = cell.getCellFormula();
                
                try {
                    System.out.println(formula +" excute...");
                    evaluator.evaluateInCell(cell);
                    System.out.println(formula+" excute success...");
                } catch (Exception e) {
                    System.out.println(String.format("Paste the value error in the Cell: %s", cell.getAddress()) + "   :");

                    System.out.println(formula+" failed");
                }
                break;
            }

运行结果示例:Result
我试过一些方法,比如加引号,斜杠,但似乎只是把公式变成了字符串。我该怎么处理这种问题呢?
额外:
如果没有try...catch(或使用e.printStackTrace()),则会出现以下错误:

org.apache.poi.ss.formula.FormulaParseException: Parse error near char 7 '【' in specified formula 'SUM(E4,【一日】!B2)'. Expected cell ref or constant literal

我想以某种方式不影响Excel文件(如手工更改工作表的名称),但仍然可以在Excel单元格中执行公式并获得结果。

vc6uscn9

vc6uscn91#

这是微软与自己的规则相矛盾的情况之一。如果我们查看Create or change a cell reference-〉Create a cell reference to another worksheet,我们会发现:
注:如果其他工作表的名称包含非字母字符,则必须用单引号(')将名称(或路径)括起来。
但是如果工作表名称是【一日】,Excel将 * 不 * 将名称括在单引号(')中。为什么不呢?显然[和]都不是字母字符,对吗?
所以Apache POI无法评估这个,因为它依赖于Microsoft规则FormulaParser.java。
您可以使用以下测试进行检查:

...
  String formula = cell.getCellFormula();
  //formula = formula.replace("【一日】", "'【一日】'"); cell.setCellFormula(formula); //set the sheet name to be a quoted sheet name
  try {
   System.out.println("Evaluate formula " + formula + " ...");
   //evaluator.evaluateInCell(cell);
   CellValue cellValue = evaluator.evaluate(cell);
   System.out.println("Success! Result: "+ cellValue);
  } catch (Exception e) {
   System.out.println(String.format("Error in the cell: %s, reason: %s", cell.getAddress(), e.getMessage()));
  }
...

如果取消注解代码行:

//formula = formula.replace("【一日】", "'【一日】'"); cell.setCellFormula(formula); //set the sheet name to be a quoted sheet name

那么公式评估应该起作用,因为现在引用了工作表名称【一日】
我使用当前的Apache POI版本5.2.3进行了测试。
以上是问题原因的描述。它不是解决方案。它甚至不是一种变通方法。要将未加引号的工作表名称替换为加引号的工作表名称,必须知道所有可能受影响的工作表名称。这是不可能的。
解决方案是Apache POI在FormulaParser.java中更改代码。从私有ParseNode parseSimpleFactor()开始,到私有ParseNode parseRangeExpression(),直到私有ParseNode parseRangeable()。但这需要一个可靠的规则来确定哪些工作表名称可以不加引号,哪些必须加引号。但该规则似乎不存在。所以:你没有任何机会,利用它吧!- ).

相关问题