2005-05-13 10:52:42 -04:00
|
|
|
<?xml version="1.0" encoding="UTF-8"?>
|
2007-01-15 18:11:09 -05:00
|
|
|
<!--
|
|
|
|
====================================================================
|
|
|
|
Licensed to the Apache Software Foundation (ASF) under one or more
|
|
|
|
contributor license agreements. See the NOTICE file distributed with
|
|
|
|
this work for additional information regarding copyright ownership.
|
|
|
|
The ASF licenses this file to You under the Apache License, Version 2.0
|
|
|
|
(the "License"); you may not use this file except in compliance with
|
|
|
|
the License. You may obtain a copy of the License at
|
|
|
|
|
|
|
|
http://www.apache.org/licenses/LICENSE-2.0
|
|
|
|
|
|
|
|
Unless required by applicable law or agreed to in writing, software
|
|
|
|
distributed under the License is distributed on an "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
|
|
See the License for the specific language governing permissions and
|
|
|
|
limitations under the License.
|
|
|
|
====================================================================
|
|
|
|
-->
|
2005-05-13 10:52:42 -04:00
|
|
|
<!DOCTYPE document PUBLIC "-//APACHE//DTD Documentation V1.1//EN" "../dtd/document-v11.dtd">
|
|
|
|
|
|
|
|
<document>
|
|
|
|
<header>
|
|
|
|
<title>Formula Evaluation</title>
|
|
|
|
<authors>
|
|
|
|
<person email="amoweb@yahoo.com" name="Amol Deshmukh" id="AD"/>
|
|
|
|
</authors>
|
|
|
|
</header>
|
|
|
|
<body>
|
|
|
|
<section><title>Introduction</title>
|
|
|
|
<p>The POI formula evaluation code enables you to calculate the result of
|
|
|
|
formulas in Excels sheets read-in, or created in POI. This document explains
|
|
|
|
how to use the API to evaluate your formulas.
|
|
|
|
</p>
|
2008-01-09 15:37:06 -05:00
|
|
|
<note> This code currently lives the scratchpad area of the POI SVN repository.
|
2005-05-24 10:23:03 -04:00
|
|
|
Ensure that you have the scratchpad jar or the scratchpad build area in your
|
2008-01-09 15:37:06 -05:00
|
|
|
classpath before experimenting with this code. You are advised
|
|
|
|
to make use of a recent SVN checkout, as new functions are
|
|
|
|
being supported fairly frequently.
|
2005-05-24 10:23:03 -04:00
|
|
|
</note>
|
2005-05-13 10:52:42 -04:00
|
|
|
</section>
|
2008-01-09 15:50:00 -05:00
|
|
|
|
|
|
|
<anchor id="Status"/>
|
2005-05-13 10:52:42 -04:00
|
|
|
<section><title>Status</title>
|
|
|
|
<p> The code currently provides implementations for all the arithmatic operators.
|
2008-01-09 15:37:06 -05:00
|
|
|
It also provides implementations for approx. 100 built in
|
2005-05-13 10:52:42 -04:00
|
|
|
functions in Excel. The framework however makes is easy to add
|
|
|
|
implementation of new functions. See the <link href="eval-devguide.html"> Formula
|
|
|
|
evaluation development guide</link> for details. </p>
|
|
|
|
<p> Note that user-defined functions are not supported, and is not likely to done
|
|
|
|
any time soon... at least, not till there is a VB implementation in Java!
|
|
|
|
</p>
|
|
|
|
</section>
|
|
|
|
<section><title>User API How-TO</title>
|
|
|
|
<p>The following code demonstrates how to use the HSSFFormulaEvaluator
|
|
|
|
in the context of other POI excel reading code.
|
|
|
|
</p>
|
|
|
|
<p>There are two ways in which you can use the HSSFFormulaEvalutator API.</p>
|
2008-01-09 15:50:00 -05:00
|
|
|
|
|
|
|
<anchor id="Evaluate"/>
|
2005-05-13 10:52:42 -04:00
|
|
|
<section><title>Using HSSFFormulaEvaluator.<strong>evaluate</strong>(HSSFCell cell)</title>
|
|
|
|
<source>
|
|
|
|
FileInputStream fis = new FileInputStream("c:/temp/test.xls");
|
|
|
|
HSSFWorkbook wb = new HSSFWorkbook(fis);
|
|
|
|
HSSFSheet sheet = wb.getSheetAt(0);
|
|
|
|
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
|
|
|
|
|
|
|
// suppose your formula is in B3
|
|
|
|
CellReference cellReference = new CellReference("B3");
|
|
|
|
HSSFRow row = sheet.getRow(cellReference.getRow());
|
|
|
|
HSSFCell cell = row.getCell(cellReference.getCol());
|
2007-12-13 08:17:49 -05:00
|
|
|
|
|
|
|
evaluator.setCurrentRow(row);
|
2005-05-19 06:36:06 -04:00
|
|
|
HSSFFormulaEvaluator.CellValue cellValue = evaluator.evaluate(cell);
|
2005-05-13 10:52:42 -04:00
|
|
|
|
|
|
|
switch (cellValue.getCellType()) {
|
|
|
|
case HSSFCell.CELL_TYPE_BOOLEAN:
|
2005-05-19 06:36:06 -04:00
|
|
|
System.out.println(cellValue.getBooleanValue());
|
2005-05-13 10:52:42 -04:00
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_NUMERIC:
|
2005-05-19 06:36:06 -04:00
|
|
|
System.out.println(cellValue.getNumberValue());
|
2005-05-13 10:52:42 -04:00
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_STRING:
|
2005-05-19 06:36:06 -04:00
|
|
|
System.out.println(cellValue.getStringValue());
|
2005-05-13 10:52:42 -04:00
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_BLANK:
|
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_ERROR:
|
|
|
|
break;
|
|
|
|
|
|
|
|
// CELL_TYPE_FORMULA will never happen
|
|
|
|
case HSSFCell.CELL_TYPE_FORMULA:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
</source>
|
|
|
|
<p>Thus using the retrieved value (of type
|
|
|
|
HSSFFormulaEvaluator.CellValue - a nested class) returned
|
|
|
|
by HSSFFormulaEvaluator is similar to using a HSSFCell object
|
|
|
|
containing the value of the formula evaluation. CellValue is
|
|
|
|
a simple value object and does not maintain reference
|
|
|
|
to the original cell.
|
|
|
|
</p>
|
|
|
|
</section>
|
2008-01-09 15:50:00 -05:00
|
|
|
|
|
|
|
<anchor id="EvaluateInCell"/>
|
2008-01-09 15:37:06 -05:00
|
|
|
<section><title>Using HSSFFormulaEvaluator.<strong>evaluateInCell</strong>(HSSFCell cell)</title>
|
|
|
|
<p><strong>evaluateInCell</strong>(HSSFCell cell) will check to
|
|
|
|
see if the supplied cell is a formula cell. If it isn't,
|
|
|
|
then no changes will be made to it. If it is, then the
|
|
|
|
formula is evaluated, and the new value saved into the cell.</p>
|
2005-05-13 10:52:42 -04:00
|
|
|
<source>
|
2005-05-19 06:36:06 -04:00
|
|
|
FileInputStream fis = new FileInputStream("/somepath/test.xls");
|
2005-05-13 10:52:42 -04:00
|
|
|
HSSFWorkbook wb = new HSSFWorkbook(fis);
|
|
|
|
HSSFSheet sheet = wb.getSheetAt(0);
|
|
|
|
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
|
|
|
|
|
|
|
// suppose your formula is in B3
|
|
|
|
CellReference cellReference = new CellReference("B3");
|
|
|
|
HSSFRow row = sheet.getRow(cellReference.getRow());
|
|
|
|
HSSFCell cell = row.getCell(cellReference.getCol());
|
2007-12-13 08:17:49 -05:00
|
|
|
evaluator.setCurrentRow(row);
|
2005-05-13 10:52:42 -04:00
|
|
|
|
|
|
|
if (cell!=null) {
|
|
|
|
switch (<strong>evaluator.evaluateInCell</strong>(cell).getCellType()) {
|
|
|
|
case HSSFCell.CELL_TYPE_BOOLEAN:
|
|
|
|
System.out.println(cell.getBooleanCellValue());
|
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_NUMERIC:
|
|
|
|
System.out.println(cell.getNumberCellValue());
|
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_STRING:
|
|
|
|
System.out.println(cell.getStringCellValue());
|
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_BLANK:
|
|
|
|
break;
|
|
|
|
case HSSFCell.CELL_TYPE_ERROR:
|
|
|
|
System.out.println(cell.getErrorCellValue());
|
|
|
|
break;
|
|
|
|
|
|
|
|
// CELL_TYPE_FORMULA will never occur
|
|
|
|
case HSSFCell.CELL_TYPE_FORMULA:
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
2008-01-09 15:37:06 -05:00
|
|
|
</source>
|
|
|
|
</section>
|
2008-01-09 15:50:00 -05:00
|
|
|
|
|
|
|
<anchor id="EvaluateAll"/>
|
2008-01-09 15:37:06 -05:00
|
|
|
<section><title>Re-calculating all formulas in a Workbook</title>
|
|
|
|
<source>
|
|
|
|
FileInputStream fis = new FileInputStream("/somepath/test.xls");
|
|
|
|
HSSFWorkbook wb = new HSSFWorkbook(fis);
|
|
|
|
for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {
|
|
|
|
HSSFSheet sheet = wb.getSheetAt(sheetNum);
|
|
|
|
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
2005-05-13 10:52:42 -04:00
|
|
|
|
2008-01-09 15:37:06 -05:00
|
|
|
for(Iterator rit = s.rowIterator(); rit.hasNext();) {
|
|
|
|
HSSFRow r = (HSSFRow)rit.next();
|
|
|
|
evaluator.setCurrentRow(r);
|
|
|
|
|
|
|
|
for(Iterator cit = r.cellIterator(); cit.hasNext();) {
|
|
|
|
HSSFCell c = (HSSFCell)cit.next();
|
|
|
|
if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
|
|
|
evaluator.evaluateInCell(c);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
wb.write(new FileOutputStream("/somepath/changed.xls"));
|
|
|
|
</source>
|
|
|
|
</section>
|
2005-05-13 10:52:42 -04:00
|
|
|
</section>
|
|
|
|
|
2008-01-09 15:50:00 -05:00
|
|
|
<anchor id="Performance"/>
|
2005-05-13 10:52:42 -04:00
|
|
|
<section><title>Performance Notes</title>
|
|
|
|
<ul>
|
|
|
|
<li>Generally you should have to create only one HSSFFormulaEvaluator
|
|
|
|
instance per sheet, but there really is no overhead in creating
|
|
|
|
multiple HSSFFormulaEvaluators per sheet other than that of the
|
|
|
|
HSSFFormulaEvaluator object creation.
|
|
|
|
</li>
|
|
|
|
<li>Also note that HSSFFormulaEvaluator maintains a reference to
|
|
|
|
the sheet and workbook, so ensure that the evaluator instance
|
|
|
|
is available for garbage collection when you are done with it
|
|
|
|
(in other words don't maintain long lived reference to
|
|
|
|
HSSFFormulaEvaluator if you don't really need to - unless
|
|
|
|
all references to the sheet and workbook are removed, these
|
|
|
|
don't get garbage collected and continue to occupy potentially
|
|
|
|
large amounts of memory).
|
|
|
|
</li>
|
|
|
|
<li>CellValue instances however do not maintain reference to the
|
|
|
|
HSSFCell or the sheet or workbook, so these can be long-lived
|
|
|
|
objects without any adverse effect on performance.
|
|
|
|
</li>
|
|
|
|
</ul>
|
|
|
|
</section>
|
|
|
|
</body>
|
|
|
|
</document>
|