我在工作表的单元格中有一个公式,如下所示. 这里的特殊之处在于,因为工作表名称是用日语编写的,所以它包含一个特殊字符:"[". 示例:Formula

当使用由ApachePoi提供的"valuateInCell(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 了一些方法,如添加引号、斜杠,但似乎只是将公式转换为字符串. 我该如何处理这种问题呢?

额外:

这里的错误如果没有Have 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单元格中执行公式并获得结果.

推荐答案

这是微软与自己的规则相矛盾的 case 之一.如果我们查看Create or change a cell reference->创建一个对另一个工作表的单元格引用,我们会发现:

注意:如果另一个工作表的名称包含非字母顺序 字符,则必须将名称(或路径)括在单个 引号(‘).

但是,如果工作表名称是【一日】,Excel将用单引号(‘)将名称括起来.为什么不行?显然,[和]都不是字母字符,不是吗?

因此,ApachePOI无法判断这一点,因为它依赖于Microsoft规则.参见FormulaParser.java:// unquoted sheet names must start with underscore or a letter.

您可以使用以下测试进行判断:

...
  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

那么公式求值应该会起作用,因为表名【一日】现在被引用了.

使用当前的ApachePOI版本5.2.3测试了ME.


以上是对问题原因的描述.这不是一个解决方案.这甚至不是一种变通办法.要将未加引号的工作表名称替换为带引号的工作表名称,必须知道所有可能受影响的工作表名称.这不可能.

解决方案是让ApachePOI在FormulaParser.java中更改他们的代码.从private ParseNode parseSimpleFactor()开始,到private ParseNode parseRangeExpression(),再到 private ParseNode parseRangeable().但这需要一个可靠的规则,规定哪些页名可以不加引号,哪些必须加引号.但这条规则似乎并不存在.所以:你没有任何机会,利用它!;-).

Java相关问答推荐

使用json参数通过单击jSP文件中的按钮来运行server时出现问题

Java 8 RDX-如何设置单个选项卡标题文本的 colored颜色

方法没有用正确的值填充数组—而是将数组保留为null,'

RxJava PublishSubject缓冲区元素超时

在Java Stream上调用collect方法出现意外结果

JUnit—如何模拟局部变量对象方法调用

如何配置ActiveMQ Artemis以使用AMQP 1.0和其他协议与Java

R.id.main给我一个红色错误,无法解析MainActivity.java中的符号main

什么是Java原子属性的正确getter和setter

用OSQL创建索引

如何使用路径过渡方法使 node 绕圆旋转?

是否有一个Java Future实现可以在池繁忙时在调用者线程中执行?

Java集合:NPE,即使没有添加空值

在Java中将对象&转换为&q;HashMap(&Q)

Java类型推断:为什么要编译它?

在具有Quarkus Panache的PostgreSQL中将JSON数据存储为JSONB时,会将其存储为转义字符串

Bash数组的单引号元素并使用空格连接

rest api服务 spring 启动中出现IllegalFormatConversionException

java.lang.ClassCastException:com.google.firebase.FirebaseException无法转换为com.google.fire base.auth.FirebaseAuthException

从 Java 17 切换回 Java 8 后出现的问题