我在how to register custom functions上阅读了Apache POI网站上的教程。到 FormulaEvaluator 中,我想用它来定义 POI 不提供支持的函数 MINVERSE。因此,首先我创建了一个定义 MINVERSE 的类(仅出于测试目的,我将 MINVERSE 定义为始终返回值 10)。所以这是 MINVERSE.java:
package simpleboxapi;
import org.apache.poi.ss.formula.OperationEvaluationContext;
import org.apache.poi.ss.formula.eval.NumberEval;
import org.apache.poi.ss.formula.eval.ValueEval;
import org.apache.poi.ss.formula.functions.FreeRefFunction;
public class MINVERSE implements FreeRefFunction{
@Override
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
return new NumberEval(10);
}
}
之后我尝试了一些非常简单的方法:我创建了以下 excel 表:
A1 是一个给定的常量,A2 是 A2=MINVERSE(A1)
这是我的主类代码:
package simpleboxapi;
import java.io.*;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.ss.formula.functions.FreeRefFunction;
import org.apache.poi.ss.formula.udf.AggregatingUDFFinder;
import org.apache.poi.ss.formula.udf.DefaultUDFFinder;
import org.apache.poi.ss.formula.udf.UDFFinder;
import org.apache.poi.ss.usermodel.*;
public class SimpleBoxAPI {
static String fileName = "workbook.xls";
static Workbook wb;
private static double updateInputVal(String cell, double val) throws IOException, InvalidFormatException{
InputStream inp = new FileInputStream(fileName);
wb = WorkbookFactory.create(inp);
CellReference crInput = new CellReference(cell);
Sheet sheet = wb.getSheetAt(0);
Row rowInput = sheet.getRow(crInput.getRow());
Cell cellInput = rowInput.getCell(crInput.getCol());
cellInput.setCellValue(val);
FileOutputStream fileOut = new FileOutputStream(fileName);
wb.write(fileOut);
fileOut.close();
double cellContents = cellInput.getNumericCellValue();
inp.close();
return cellContents;
}
private static void registerMINVERSE(){
String[] functionNames = {"MINVERSE"};
FreeRefFunction[] functionImpls = {new MINVERSE()};
UDFFinder udfs = new DefaultUDFFinder(functionNames, functionImpls);
UDFFinder udfToolpack = new AggregatingUDFFinder(udfs);
wb.addToolPack(udfToolpack);
}
public static void main(String[] args) throws Exception {
double updatedValue = updateInputVal("A1",55);
System.out.println(updatedValue);
registerMINVERSE();
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
CellReference cr = new CellReference("A2");
Sheet sheet = wb.getSheetAt(0);
Row row = sheet.getRow(cr.getRow());
Cell cell = row.getCell(cr.getCol());
System.out.println(evaluator.evaluate(cell).getNumberValue());
}
}
但是,每当我尝试执行它时,我都会收到以下错误:
org.apache.poi.ss.formula.eval.NotImplementedException: Error evaluating cell 'new sheet'!A2
at org.apache.poi.ss.formula.WorkbookEvaluator.addExceptionInfo(WorkbookEvaluator.java:356)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:297)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluate(WorkbookEvaluator.java:229)
at org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.evaluateFormulaCellValue(HSSFFormulaEvaluator.java:354)
at org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.evaluate(HSSFFormulaEvaluator.java:185)
at simpleboxapi.SimpleBoxAPI.main(SimpleBoxAPI.java:56)
Caused by: org.apache.poi.ss.formula.eval.NotImplementedException: MINVERSE
at org.apache.poi.ss.formula.functions.NotImplementedFunction.evaluate(NotImplementedFunction.java:42)
at org.apache.poi.ss.formula.OperationEvaluatorFactory.evaluate(OperationEvaluatorFactory.java:132)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateFormula(WorkbookEvaluator.java:491)
at org.apache.poi.ss.formula.WorkbookEvaluator.evaluateAny(WorkbookEvaluator.java:287)
... 4 more
有什么建议吗?非常感谢!
最佳答案
您一直在查看的自定义函数教程仅适用于真正的自定义函数。它不会让您覆盖尚未实现 POI 的内置 Excel 函数
如果你看org/apache/poi/ss/formula/function/functionMetadata.txt您将看到以文件格式定义的内置 Excel 函数列表。该列表中的任何内容都不能作为自定义函数被覆盖,因为它们以不同的文件格式存储。 (当然,对于 .xls 文件,.xlsx 有点不同)。在查看该文件时,记下您的函数的 ID。
如果您的公式函数是内置的,那么您应该看看 FunctionEval .您可以使用 getNotSupportedFunctionNames()或者只是查看代码以查看该功能是否已实现。 (该数组由您从 functionMetadata.txt 中获得的函数 ID 索引)
如果您的功能未实现,您需要获取 POI 源代码,并且:
- 在某处添加您的函数实现
- 用正确的 ID 列出 FunctionEval 中的函数
- 测试(您可以使用 POI 公式测试来帮助)
- 将其作为补丁提交!查看POI contribution guidelines详情
提交补丁后不久,POI 将包含您缺少的功能,社区将帮助维护它,以便您继续前进:)
关于java - Apache POI - 如何注册一个函数,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/10298512/