我遇到了一个问题,我使用的公式非常具体。通过编程输入公式时,我得到了意想不到的结果。例如
MF = "IF(INDEX(CELL(\"width\",INDIRECT(ADDRESS(ROW(),COLUMN()))),1)<6,\"\",AGGREGATE(4,5,INDIRECT(ADDRESS(ROW()-"+readingsPerThirty+",COLUMN())):INDIRECT(ADDRESS(ROW()-1,COLUMN()))))";
Run Code Online (Sandbox Code Playgroud)
我将该 Excel 函数存储为字符串,稍后将被调用:
data.getRow(r+1).getCell(c,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).setCellFormula(readings.get(r).getC(c));
Run Code Online (Sandbox Code Playgroud)
其中数据是 XSSFSheet
当程序运行时,实际输入单元格的公式是:
=@IF(@INDEX(CELL("width",INDIRECT(ADDRESS(ROW(),COLUMN()))),1)<6,"",AGGREGATE(4,5,INDIRECT(ADDRESS(ROW()-1,COLUMN())):INDIRECT(ADDRESS(ROW()-1,COLUMN()))))
Run Code Online (Sandbox Code Playgroud)
我找不到任何关于@ 符号来自何处或导致它们的原因的文档或报告。我的问题是它们为什么会出现,我可以做些什么来防止它出现。@ 导致 Excel 出现错误,公式在没有它们的情况下也能正常工作。
谢谢
问题在于Excel 365通常以_xlfnin为前缀的新函数Excel的文件系统存储。
让我们有一个完整的例子来重现这个问题:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
class ExcelSetCellFormula {
static final String WRONG = "IF(INDEX(CELL(\"width\",INDIRECT(ADDRESS(ROW(),COLUMN()))),1)<6,\"\",AGGREGATE(4,5,INDIRECT(ADDRESS(ROW()-1,COLUMN())):INDIRECT(ADDRESS(ROW()-1,COLUMN()))))";
static final String CORRECT = "IF(INDEX(CELL(\"width\",INDIRECT(ADDRESS(ROW(),COLUMN()))),1)<6,\"\",_xlfn.AGGREGATE(4,5,INDIRECT(ADDRESS(ROW()-1,COLUMN())):INDIRECT(ADDRESS(ROW()-1,COLUMN()))))";
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new FileInputStream("./Excel.xlsx")); String filePath = "./ExcelNew.xlsx";
Sheet data = workbook.getSheetAt(0);
int r = 0;
int c = 4;
data.getRow(r+1).getCell(c,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).setCellFormula(WRONG);
//data.getRow(r+1).getCell(c,Row.MissingCellPolicy.CREATE_NULL_AS_BLANK).setCellFormula(CORRECT);
System.out.println(data.getRow(r+1).getCell(c));
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close() ;
workbook.close();
}
}
Run Code Online (Sandbox Code Playgroud)
在Excel.xlsx需要具有具有的行的至少一个工作表1〜2已经。代码在单元格中设置公式E2。
如果
static final String WRONG = "IF(INDEX(CELL(\"width\",INDIRECT(ADDRESS(ROW(),COLUMN()))),1)<6,\"\",AGGREGATE(4,5,INDIRECT(ADDRESS(ROW()-1,COLUMN())):INDIRECT(ADDRESS(ROW()-1,COLUMN()))))";
Run Code Online (Sandbox Code Playgroud)
被设置为公式,您正在打开结果ExcelNew.xlsxusingExcel 365并且您正在尝试更改 中的公式E2,然后您会看到弹出窗口:
为什么 @ 操作符在这里?
我们升级了 Excel 的公式语言,因此您可能会注意到某些公式中的 @ 运算符。您的公式的行为方式与以往相同。
这是指隐式交集运算符:@。
但是如果我们仔细观察,之前在该公式中甚至没有理由使用该隐式交集运算符 IF。那么为什么要使用它呢?
原因是新AGGREGATE函数通常以_xlfn.in Excels 文件系统存储为前缀。但Apache POI不是这样做的。因此Excel 365,在渲染时将该函数解释为用户定义的函数,并为其添加前缀_xludf.. 这就是#NAME?错误的原因。这就是使用隐式交集运算符的原因@。
因此,如果
static final String CORRECT = "IF(INDEX(CELL(\"width\",INDIRECT(ADDRESS(ROW(),COLUMN()))),1)<6,\"\",_xlfn.AGGREGATE(4,5,INDIRECT(ADDRESS(ROW()-1,COLUMN())):INDIRECT(ADDRESS(ROW()-1,COLUMN()))))";
Run Code Online (Sandbox Code Playgroud)
设置为公式,其中以AGGREGATE为前缀_xlfn.,#NAME?错误消失。并且@不使用隐式交集运算符Excel 365。
| 归档时间: |
|
| 查看次数: |
394 次 |
| 最近记录: |