It is correct that apache poi
's WorkbookEvaluator
needs a workbook. And since you are talking about evaluating "excel formula-like expressions", this is necessary because all variables in such formulas must either be cell references or names in that workbook. Your given example CONCATENATE(a,b,c)
can only work as an Excel
formula when a
, b
, and c
are Excel
names . Else it would lead to #Name?
error in Excel
. And btw.: The Excel
function is CONCATENATE
and not CONCAT
.
But this workbook must not necessarily stored somewhere. It can be only in random access memory too.
And the formulas itself need not to be in the sheet somewhere. The formula can also be given as a string since there is WorkbookEvaluator.evaluate(java.lang.String formula, CellReference ref).
Example:
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.ss.usermodel.Workbook;
import org.apache.poi.ss.usermodel.CreationHelper;
import org.apache.poi.ss.usermodel.FormulaEvaluator;
import org.apache.poi.ss.usermodel.Name;
import org.apache.poi.ss.formula.BaseFormulaEvaluator;
import org.apache.poi.ss.formula.WorkbookEvaluator;
import org.apache.poi.ss.formula.eval.*;
import org.apache.poi.ss.util.CellReference;
public class EvaluateExcelFunctions {
static Object evaluateExcelFormula(String formula, Workbook workbookWithVariables) {
if (workbookWithVariables.getNumberOfSheets() < 1) workbookWithVariables.createSheet();
CellReference reference = new CellReference(workbookWithVariables.getSheetName(0), 0 , 0, false, false);
CreationHelper helper = workbookWithVariables.getCreationHelper();
FormulaEvaluator formulaevaluator = helper.createFormulaEvaluator();
WorkbookEvaluator workbookevaluator = ((BaseFormulaEvaluator)formulaevaluator)._getWorkbookEvaluator();
ValueEval valueeval = null;
try {
valueeval = workbookevaluator.evaluate(formula, reference);
} catch (Exception ex) {
return ex.toString();
}
if (valueeval instanceof StringValueEval) {
String result = ((StringValueEval)valueeval).getStringValue();
return result;
} else if (valueeval instanceof NumericValueEval) {
double result = ((NumericValueEval)valueeval).getNumberValue();
return result;
} else if (valueeval instanceof ErrorEval) {
String result = ((ErrorEval)valueeval).getErrorString();
return result;
}
return null;
}
public static void main(String[] args) throws Exception {
Workbook workbook =
//new XSSFWorkbook();
new HSSFWorkbook();
Name name;
String formula;
Object result;
// example 1 concatenating strings - your example
name = workbook.createName();
name.setNameName("_a");
name.setRefersToFormula("\"Text A \"");
name = workbook.createName();
name.setNameName("_b");
name.setRefersToFormula("\"Text B \"");
name = workbook.createName();
name.setNameName("_c");
name.setRefersToFormula("\"Text C \"");
formula = "CONCATENATE(_a, _b, _c)";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
// example 2 Pythagorean theorem
name = workbook.getName("_a");
name.setRefersToFormula("12.34");
name = workbook.getName("_b");
name.setRefersToFormula("56.78");
formula = "SQRT(_a^2 + _b^2)";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
// example 3 complex math formula
name = workbook.getName("_a");
name.setRefersToFormula("12.34");
name = workbook.getName("_b");
name.setRefersToFormula("56.78");
name = workbook.getName("_c");
name.setRefersToFormula("90.12");
formula = "((_a+_b+_c)*_c/_b-_a)/2";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
// example 4 faulty formulas
name = workbook.getName("_a");
name.setRefersToFormula("56.78");
name = workbook.getName("_b");
name.setRefersToFormula("190.12");
name = workbook.getName("_c");
name.setRefersToFormula("\"text\"");
formula = "_a + _c";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
formula = "((_a + _b";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
formula = "_a \\ 2";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
formula = "_a^_b";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
formula = "_a/(_b-_b)";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
formula = "CONCAT(_a, _b)";
result = evaluateExcelFormula(formula, workbook);
System.out.println(result);
workbook.close();
}
}
This code is tested using apache poi 4.1.0
.
Note, Excel
names cannot be all possible variable names. For example a Excel
name cannot be c
or C
because this would be in conflict with possible R1C1
cell references. That's why I have named my names _a
, _b
and _c
.