I am using apache-poi api (v3.9) in my project to process the excel template. I do update the all required cell values in all sheets of my excel document. I am using some complex formulas to calculate the double value for some cell.
I am facing the problem in reading the cell value of a cell having some complex formula. This complex formula works fine in excel sheet but return zero when I read it using poi.
Complex formula which I am using:
"=SUMPRODUCT(--('A-La-Carte'!$L$12:$L$100000=E129)*IF('A-La-Carte'!$K$12:$K$100000<>"-",'A-La-Carte'!$K$12:$K$100000,0)*IF(ISNUMBER(INT(LEFT('A-La-Carte'!$D$12:$D$100000,2))),12/INT(LEFT('A-La-Carte'!$D$12:$D$100000,2)),0))+(NOW()*0)"
If I change the above formula with some simple formula it works fine.
Below is the sample code which I used to read the cell value:
XSSFFormulaEvaluator.evaluateAllFormulaCells(workbook);
private String getCellValue(String cellRef,
XSSFWorkbook workbook,String sheetName) {
XSSFSheet xssfSheet = workbook.getSheet(sheetName);
CellReference cellReference = new CellReference(cellRef);
XSSFRow r = xssfSheet.getRow(cellReference.getRow());
if (r != null) {
XSSFCell c = r.getCell(cellReference.getCol());
if(c.getCellType()==XSSFCell.CELL_TYPE_NUMERIC)
return c.getNumericCellValue()+"";
else if((c.getCellType()==XSSFCell.CELL_TYPE_FORMULA)){
return c. getNumericCellValue()+"";
}
return c.getStringCellValue();
}
return null;
}
Can anybody tell me whats wrong with formula or API?
Related
I have one excel workbook file in which there are 2 sheets. Sheet 1 has two columns which are just like values and criteria's like
and the other sheet has formula defined as =COUNTIF(Sheet1!A2:A13,Sheet1!B2:B4)
so other sheet looks like
Now when I am reading this second sheet, I want to evaluate the formula to extract the correct values from the workbook but it is giving all wrong values.
Code is as follows:
try {
fis = new FileInputStream(fileName);
workbook = new XSSFWorkbook(fis);
} catch (IOException e) {
e.printStackTrace();
}
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
Iterator<Row> rowIterator = workbook.getSheetAt(1).iterator();
while (rowIterator.hasNext()) {
Row row = rowIterator.next();
Iterator<Cell> cellIterator = row.cellIterator();
while (cellIterator.hasNext()) {
Cell cell = cellIterator.next();
if (cell.getCellType() == CellType.FORMULA) {
String cellFormula = cell.getCellFormula();
System.out.println("Cell Formula=" + cellFormula);
CellType cellType = evaluator.evaluateFormulaCell(cell);
if (cellType == CellType.NUMERIC) {
System.out.println(cell.getNumericCellValue());
}
} else if (cell.getCellType() == CellType.NUMERIC)
System.out.println(cell.getNumericCellValue());
}
}
closeFIS();
Could some one please point me what wrong I am doing here...
Used as normal worksheet function, COUNTIF does not use a cell range as second parameter but only one value or one cell reference.
If you have =COUNTIF(Sheet1!A2:A13,Sheet1!B2:B4) as formula in a sheet, then you are using that function as dynamic array formula using spilled array behavior. Current Excel versions provide this. But Apache POI (current versions of January 2023) cannot evaluate such formulas properly.
If you would have normal worksheet functions in your Sheet2, such as:
=COUNTIF(Sheet1!A2:A13,Sheet1!B2) in Sheet2!A1
=COUNTIF(Sheet1!A2:A13,Sheet1!B3) in Sheet2!A2
=COUNTIF(Sheet1!A2:A13,Sheet1!B4) in Sheet2!A3
then formula evaluation should work.
I am using poi version 3.17. In my java code I want to read a cell value which has formula and I am using evaluateInCell function of FormulaEvaluator to resolve the cell value.
I have a template excel in my resource in which cells has formulas, if I create a workbook from this and set some value, and try to read it back, the FormulaEvaluator resolve the cell and put the actual value, by this formula of those cells get replaced and updated with actual value. WHY??
I have seen the implementation of evaluateInCell function which intentionally setting the cell type as setCellType(cell, cv);
public XSSFCell evaluateInCell(Cell cell) {
if (cell == null) {
return null;
} else {
XSSFCell result = (XSSFCell)cell;
if (cell.getCellType() == 2) {
CellValue cv = this.evaluateFormulaCellValue(cell);
setCellType(cell, cv);
setCellValue(cell, cv);
}
return result;
}
}
Why library is doing so, and removing actual formula from the cell.
There are different functions:
CellType evaluateFormulaCell(Cell cell) - your cell will hold both the formula, and the result.
Cell evaluateInCell(Cell cell) - you cell will contain result only, formula is erased.
CellValue evaluate(Cell cell) - the formula is evaluated and returned. No changes in the cell.
void evaluateAll() = mass evaluateFormulaCell for the whole book.
Obviously, you have taken evaluateInCell for evaluateFormulaCell. evaluateInCell is very useful, and not only for counting - Use it for clean erasing of formulae.
Also, don't forget clearAllCachedResultValues() or notifyUpdateCell()/notifySetFormula(). Without those, any evaluation after any changes on the sheet can fail.
I want to get content of a cell in Excel whose value is calculated using a Formula (=D6*0.1236) and i am using HssfWorkbook and using getCell() method to get content. But i am getting D6*0.1236. I want to get the value calculated using this formula and not the formula. Please suggest some solution for this.
Below is the code to get the contents
HSSFSheet sheet = workbook.getSheetAt(1);
Row r = sheet.getRow(13);
//get the cell [a particular cell of the row obtained above]
Cell c = r.getCell(2);
You are not suppose to use getCell() to fetch a value. Try the following ,
Cell c = r.getCell(2);
System.out.println("The Cell value is " + c.getNumericCellValue());
I use poi-ooxml 3.9 to generate invoice report from an excel template I store in db. I have formulas at the end of the sheet that will do sum and other tax calculations.
cell D30 =SUM(D22:D28)
cell D31 =D30*0.12
cell D32 =D31*0.02
cell D33 =D31*0.01
cell D35 =SUM(D30:D33)
Before I write the sheet to a new file I evaluate the formulas, but nothing works. The code below is used to evaluate the formulas. Do I need to evaluate the formulas whenever I write the values into the cells or only at the end of the operation?
String formulaCells[] = { "D30", "D31", "D32", "D33", "D35" };
FormulaEvaluator formulaEvaluator = workBook.getCreationHelper()
.createFormulaEvaluator();
Sheet sheet = workBook.getSheetAt(0);
for (String cellRef : formulaCells) {
CellReference ref = new CellReference(cellRef);
Row actualRow = sheet.getRow(ref.getRow());
Cell cell = actualRow.getCell(ref.getCol());
if (cell != null) {
// here I evaluate the formula
formulaEvaluator.evaluateFormulaCell(cell);
anything I have missed?
Note: Only after I open the generated sheet and press enter in every cells the formulas are evaluated!
Are you sure that your cell are added as number?
if not, try to do something like this:
if(type.equals("String")) {
cell.setCellValue (value.toString());
} else if (type.equals("int")) {
cell.setCellValue(Integer.parseInt(value.toString()));
} else if (type.equals("double")) {
cell.setCellValue(Double.parseDouble(value.toString()));
}
I am using XSSF to access the .xlsx format. Extracting row data and cell data is being done by
Row.getCell(1) // to get the first cell data.
Is there a way to access cells like
Row.getCell(A) or Row.getCell(AC).
This will be very helpfull for me to access columns.
Can any one tell me the way to do this?
I think the main class you're looking for is CellReference - it handles converting between user facing references such as "B2" into file format references like row=1,col=1 . There's a static method on there that handles your exact use case, convertColStringToIndex
For your use case, you'd want code something like
Cell c = row.getCell( CellReference.convertColStringToIndex("G") );
The question is regarding reaching out a cell using its references, if I am not wrong.
Sheet referenceSheet = workbook.getsheet("Sheet name your intrested in");
CellReference ref = new CellReference("C24");
Row row = referenceSheet.getRow(ref.getRow());
// null check for the row
if(row != null)
{
Cell cell = row.getCell(ref.getCol());
}
In this way we can refer a cell using its reference.