So I'm having some issues getting Apache POI to evaluate formulas.
Here's the code I call to evaluate formulas before writing:
complete.getCreationHelper().createFormulaEvaluator().evaluateAll();
complete.write(fileOut);
Here's the code I call to write to the cells being used (proving they're numbers):
try{
cell.setCellValue((Double)grid[i][j]);
}
catch(Exception e){
cell.setCellValue((String)grid[i][j]);
}
FYI: grid is a 2D Object array containing only entries of the type double and String.
Here's the formulas I'm trying to evaluate:
"=G13 - H13"
"=STDEV.P(C1:L1)"
"=I13/G13"
Any ideas why when I open up my final workbook in Excel the formulas arn't evaluated? Also, when I click on an unevaluated field and hit enter Excel will recognize the formula and evaluate it. In bulk this isn't practical, but I believe it demonstrates that the cells being used are the correct type. Could this be related to the formulas being of the String type?
EDIT:
OK, so looks like you're supposed to explicitly tell it you have a formula cell. Here's my modified code to do that:
try{
cell.setCellValue((Double)grid[i][j]);
}
catch(Exception e){
String val = (String) grid[i][j];
if (val != null && val.startsWith("=")){
val = val.replaceAll("=", "");
cell.setCellType(XSSFCell.CELL_TYPE_FORMULA);
cell.setCellFormula(val);
}
else{
cell.setCellValue(val);
}
}
Unfortunately you need to remove the equals sign (which is dumb) to pass formulas and then force it to reevaluate before saving (which is dumb). After trying to get it to reevaluate formulas it complained, however, saying:
Caused by:
org.apache.poi.ss.formula.eval.NotImplementedFunctionException:
STDEV.P
I'm imagining that this means Excel has implemented standard deviation calculations but POI hasn't caught up yet?
Try this:
XSSFFormulaEvaluator.evaluateAllFormulaCells(workbook);
or, if you are using xls
HSSFFormulaEvaluator.evaluateAllFormulaCells(hssfWorkbook)
You probably want to call this just before saving.
Related
I'm trying to import an Excel file (using easyxls) which contains cells with formulas like '=3*5',
now I would like to get 15 as the value of the cell during the import.
Does anyone know how to get the formula result and not the formula itself from the excel cells?
What I tried so far
cell.getValue().. returns the formula for the formula cells, not the result
cell.getFormulaResultValue() ... this is what I thought should work, but it always returns '#N/A'
cell.getFormulaResultValue() is the method that you need to use, but you need to calculate the sheet first with worksheet.easy_computeFormulas() method.
table.easy_getCell("A1").setValue("=3*5");
worksheet.easy_computeFormulas(workbook, true);
table.easy_getCell("A1").getFormulaResultValue();
Check also this code sample about get formula result in Excel cell with EasyXLS.
I have a excel file with a cell that generates the number 3.69 (based on calculations from proceeding numbers)
However when pulling that number in java using
if (brightCell.getNumericCellValue()) > 0 )
{
double brightness = brightCell.getNumericCellValue();
return brightness;
}
I've also tried:
if (Double.parseDouble(brightCell.getStringCellValue()) > 0 )
{
double brightness = Double.parseDouble(brightCell.getStringCellValue());
return brightness;
}
brightCell is instantiated with :
brightCell = spreadsheet.getRow(new CellReference(brightString).getRow()).getCell(new CellReference(brightString).getCol());
brightString is String brightString = "BV29"
But with both solutions, brightness receives the value, 3.2133....
So thanks to #Igor I managed to figure it out but it led to more issues.
So the solution was creating an evaluator
FormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator();
evaluator.setIgnoreMissingWorkbooks(true); //if you need it
when you finish setting the required cells and want to evaluate.
evaluator.EvaluateAll();
The problem for me is I'm doing this multiple times and my 1st resut is correct but upon the second iteration it becomes skewed, and more skewed.
What I'm doing is setting various cells (via java) then before I retrieve the value for a cell (that contains a formula) I run EvaluateAll. Now, I'm not sure if I should be evaluating after EVERY change or after I make all my changes to the excel sheet (via java).
I can't evaluate a specific cell at a time because there's over 38 sheets with multitudes of formulas. So EvaluateAll is the best option for me
EDIT 26/10/2018*
So the issue was not clearing the cache after making inputs. The solution was after each input as specified in the javaDoc that:
Should be called whenever there are changes to input cells in the evaluated workbook.
Failure to call this method after changing cell values will cause incorrect behaviour
of the evaluate~ methods of this class
therefore after making an input on a cell you should call evaluator.clearAllCachedResultValues();
I've been searching around a lot for this but couldn't find a solution. Hope someone can help me here.
I am using Apache POI to create a simple tool. Formulas will be inputted by user, and the result will be written on file. Im stuck at extending/filling the formula.
Suppose you have a simple excel formula:
IF(A2=B2,True,False)
A drag downwards on excel would result in:
IF(A2=B2,True,False)
IF(A3=B3,True,False)
IF(A4=B4,True,False)
IF(A5=B5,True,False)
. .
.
Now I want to do the same in my program. I will know which row to end. i just can't get the row index to increment. I have already done it manually (writing formula in program), but now I need to use this when formula is passed by user.
I have something like this for the manual part:
for (int ind = 2; ind < rownumb ; ind++)
{
sheet.getRow(i).createCell(12).setCellFormula("IF(K" + ind + "=L" + ind + ",FALSE,TRUE)");
}
Now the user will input:
=IF(K=L, False, True) OR =IF(K0=L0, False, True)
I want to add this formula auto-filling (incrementing) all the way till rownumb. How can I do this?
If there is no direct way, can someone suggest some other approach, however the requirement is that the formula will be passed by user.
Thanks.
Excel does not store it's function "in a sheet's cell" but as a VBA function. In order to be able to properly utilize excel function yourself you will need to emulate that. Check this article about user defined functions, this might get you going.
I need some help on setting the cell style base on the cell value.
The code used to populate cell.
String totalvariationweightv1 = "J" + (x+1);
String totalvariationweightv2 = "L" + (x+1);
cell85014.setCellType(Cell.CELL_TYPE_FORMULA);
cell85014.setCellFormula("SUM(((" + totalvariationweightv2 + "-" + totalvariationweightv1 + ")/" + totalvariationweightv1 + ")*100)");
Then I need to color the field if it exceeds a certain value. Right now I just have alternating colors:
cell85014.setCellStyle((x%2)==0?stylefloatGray:stylefloat);
I cannot figure out how to get the cell value. Using getNumericValue returns 0.
Apache POI stores the formula, but it doesn't evaluate it automatically.
The Excel file format (both .xls and .xlsx) stores a "cached" result for every formula along with the formula itself. This means that when the file is opened, it can be quickly displayed, without needing to spend a long time calculating all of the formula results. It also means that when reading a file through Apache POI, the result is quickly available to you too!
After making changes with Apache POI to either Formula Cells themselves, or those that they depend on, you should normally perform a Formula Evaluation to have these "cached" results updated. This is normally done after all changes have been performed, but before you write the file out.
You must tell Apache POI to evaluate the formula separately.
FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator();
// Set your cell formula here
switch (evaluator.evaluateFormulaCell(cell85014)) {
case Cell.CELL_TYPE_NUMERIC:
double x = cell85014.getNumericCellValue();
// Set cell style here, based on numeric value,
// as you already are doing in your code.
// Watch out for floating point inaccuracies!
break;
default:
System.err.println("Unexpected result type!");
break;
}
I'm parsing a CSV using Processing's Table interface, but some rows are missing some data. I want to pull all the data available into my table, but I'm not sure how to handle the missing data--I keep getting NullPointerException when I loop over the table with dataTable.getInt on the missing values.
I don't have a background in statically typed languages, so I've no idea how to conditionally assign this data short of putting a separate try/catch around each assignment. Surely there's a better way?
Before calling dataTable.getInt method check if dataTable is not null like
if(dataTable != null) {
int my_nt = dataTable.getInt
}
//else skip since it is empty
Since your're using getInt--you should perform a regex search/replace ,<not numeric>, with ,<some int>,. In your case it may be as simple as replacing ,, with ,0,
Also, as Hassan suggests, double check that dataTable is not null.
Ok, so I figured out a way to do this:
First, call dataTable.makeNullEmpty(), which turns all the null values into empty strings.
Then, you can use a pattern like this:
String total_value = dataTable.getString(i, 4);
if(total_value.length() > 0) s.total_value = parseInt(total_value);
and you get assignment only if an int is there to be parsed.