I read the tutorial on the website of Apache POI on how to register custom functions into a FormulaEvaluator and I wanted to use it to define the function MINVERSE for which POI does not provide support. So, first off I created a class that defines MINVERSE (For testing purposes only, I defined MINVERSE to return always the value 10). So here is 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);
}
}
Afterwards I tried something really simplistic: I created the following excel sheet:

A1 is a given constant and A2 is A2=MINVERSE(A1)
Here is my main class code:
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());
}
}
However, whenever I try to execute it I get the following error:
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
Any suggestions? Thanks a lot in advance!
The Custom Functions tutorial you've been looking at is only for real custom functions. It won't let you override built-in Excel functions that don't have a POI implementation yet
If you look at org/apache/poi/ss/formula/function/functionMetadata.txt you'll see the list of the built-in Excel functions defined in the file format. Anything in that list can't be overriden as a custom function, as they get stored differently in the file format. (Well, certainly for .xls files, .xlsx is a little different). While looking at that file, make a note of the ID of your function.
If your formula function is a built in one, then you should take a look at FunctionEval. You can use getNotSupportedFunctionNames() or just look in the code to see if the function is implemented yet. (The array is indexed by function ID, which you got from functionMetadata.txt)
If your function isn't implemented, you'll need to grab the POI source code, and:
Shortly after your patch is submitted, then POI will include your missing function, and the community will help maintain it so you win going forward :)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With