This is one of the cases where Microsoft
does not follow their own rules. IRR function tells:
Microsoft Excel uses an iterative technique for calculating IRR.
Starting with guess, IRR cycles through the calculation until the
result is accurate within 0.00001 percent. If IRR can't find a result
that works after 20 tries, the #NUM! error value is returned.
In most cases you do not need to provide guess for the IRR
calculation. If guess is omitted, it is assumed to be 0.1 (10
percent).
This is exactly what apache poi
has implemented for IRR
function. And that's why it gets the #NUM!
error for your data sample. But Microsoft
seems to do something different.
Using the formula IRR(A2:C2,-0.7)
, which has a given guess of -0.7
, also apache poi
is able to evaluate that IRR
formula.
To get around this, one could do what IRR
function description also tells:
If IRR gives the #NUM! error value, or if the result is not close to
what you expected, try again with a different value for guess.
So try a guess
from -1.0 to 1.0 in steps of 0.1 until you get a value instead of the `#NUM!' error.
Example:
import java.io.FileInputStream;
import java.io.FileOutputStream;
import org.apache.poi.ss.usermodel.*;
class ExcelEvaluateIRRFunction {
public static void main(String[] args) throws Exception {
Workbook workbook = WorkbookFactory.create(new FileInputStream("./Excel.xlsx")); String filePath = "./ExcelNew.xlsx";
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
Sheet sheet = workbook.getSheetAt(0);
Row row = sheet.getRow(1); if (row == null) row = sheet.createRow(1);
row.createCell(0).setCellValue(-20000000d);
row.createCell(1).setCellValue(-1000d);
row.createCell(2).setCellValue(2399000d);
row = sheet.getRow(0); if (row == null) row = sheet.createRow(0);
Cell cell = row.createCell(0);
CellValue evaluatedValue = null;
for (int i = -10; i < 10; i++) {
double guess = i/10d;
System.out.println(guess);
cell.setCellFormula("IRR(A2:C2," + guess + ")");
evaluator.clearAllCachedResultValues();
evaluatedValue = evaluator.evaluate(cell);
System.out.println(evaluatedValue);
if (evaluatedValue.getCellType() != CellType.ERROR) break;
}
evaluator.evaluateFormulaCell(cell);
System.out.println(cell.getNumericCellValue());
FileOutputStream out = new FileOutputStream(filePath);
workbook.write(out);
out.close() ;
workbook.close();
}
}
See also IRR in poi return NaN but correct value in excel for another example of the same problem.