Merged revisions 614878-614909 via svnmerge from
https://svn.apache.org/repos/asf/poi/trunk ........ r614878 | nick | 2008-01-24 15:13:05 +0100 (Thu, 24 Jan 2008) | 1 line Add another formula evaluation method, evaluateFormulaCell(cell), which will re-calculate the value for a formula, without affecting the formula itself. Add tests too, and update the documentation ........ r614909 | nick | 2008-01-24 17:05:27 +0100 (Thu, 24 Jan 2008) | 1 line From bug #44254 - avoid some unread bytes warnings, and process the contents of DVALRecord ........ git-svn-id: https://svn.apache.org/repos/asf/poi/branches/ooxml@615185 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
66c126f70c
commit
86a0e470b9
@ -36,6 +36,8 @@
|
|||||||
|
|
||||||
<!-- Don't forget to update status.xml too! -->
|
<!-- Don't forget to update status.xml too! -->
|
||||||
<release version="3.0.2-FINAL" date="2008-??-??">
|
<release version="3.0.2-FINAL" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">44254 - Avoid some unread byte warnings, and properly understand DVALRecord</action>
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">Add another formula evaluation method, evaluateFormulaCell(cell), which will re-calculate the value for a formula, without affecting the formula itself.</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">41726 - Fix how we handle signed cell offsets in relative areas and references</action>
|
<action dev="POI-DEVELOPERS" type="fix">41726 - Fix how we handle signed cell offsets in relative areas and references</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">44233 - Support for getting and setting a flag on the sheet, which tells excel to re-calculate all formulas on it at next reload</action>
|
<action dev="POI-DEVELOPERS" type="add">44233 - Support for getting and setting a flag on the sheet, which tells excel to re-calculate all formulas on it at next reload</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44201 - Enable cloning of sheets with data validation rules</action>
|
<action dev="POI-DEVELOPERS" type="fix">44201 - Enable cloning of sheets with data validation rules</action>
|
||||||
|
@ -55,10 +55,12 @@
|
|||||||
<p>The following code demonstrates how to use the HSSFFormulaEvaluator
|
<p>The following code demonstrates how to use the HSSFFormulaEvaluator
|
||||||
in the context of other POI excel reading code.
|
in the context of other POI excel reading code.
|
||||||
</p>
|
</p>
|
||||||
<p>There are two ways in which you can use the HSSFFormulaEvalutator API.</p>
|
<p>There are several ways in which you can use the HSSFFormulaEvalutator API.</p>
|
||||||
|
|
||||||
<anchor id="Evaluate"/>
|
<anchor id="Evaluate"/>
|
||||||
<section><title>Using HSSFFormulaEvaluator.<strong>evaluate</strong>(HSSFCell cell)</title>
|
<section><title>Using HSSFFormulaEvaluator.<strong>evaluate</strong>(HSSFCell cell)</title>
|
||||||
|
<p>This evaluates a given cell, and returns the new value,
|
||||||
|
without affecting the cell</p>
|
||||||
<source>
|
<source>
|
||||||
FileInputStream fis = new FileInputStream("c:/temp/test.xls");
|
FileInputStream fis = new FileInputStream("c:/temp/test.xls");
|
||||||
HSSFWorkbook wb = new HSSFWorkbook(fis);
|
HSSFWorkbook wb = new HSSFWorkbook(fis);
|
||||||
@ -102,12 +104,60 @@ switch (cellValue.getCellType()) {
|
|||||||
</p>
|
</p>
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
<anchor id="EvaluateFormulaCell"/>
|
||||||
|
<section><title>Using HSSFFormulaEvaluator.<strong>evaluateFormulaCell</strong>(HSSFCell cell)</title>
|
||||||
|
<p><strong>evaluateFormulaCell</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. The value for the formula
|
||||||
|
is saved alongside it, to be displayed in excel. The
|
||||||
|
formula remains in the cell, just with a new value</p>
|
||||||
|
<p>The return of the function is the type of the
|
||||||
|
formula result, such as HSSFCell.CELL_TYPE_BOOLEAN</p>
|
||||||
|
<source>
|
||||||
|
FileInputStream fis = new FileInputStream("/somepath/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());
|
||||||
|
evaluator.setCurrentRow(row);
|
||||||
|
|
||||||
|
if (cell!=null) {
|
||||||
|
switch (<strong>evaluator.evaluateFormulaCell</strong>(cell)) {
|
||||||
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</source>
|
||||||
|
</section>
|
||||||
|
|
||||||
<anchor id="EvaluateInCell"/>
|
<anchor id="EvaluateInCell"/>
|
||||||
<section><title>Using HSSFFormulaEvaluator.<strong>evaluateInCell</strong>(HSSFCell cell)</title>
|
<section><title>Using HSSFFormulaEvaluator.<strong>evaluateInCell</strong>(HSSFCell cell)</title>
|
||||||
<p><strong>evaluateInCell</strong>(HSSFCell cell) will check to
|
<p><strong>evaluateInCell</strong>(HSSFCell cell) will check to
|
||||||
see if the supplied cell is a formula cell. If it isn't,
|
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
|
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>
|
formula is evaluated, and the new value saved into the cell,
|
||||||
|
in place of the old formula.</p>
|
||||||
<source>
|
<source>
|
||||||
FileInputStream fis = new FileInputStream("/somepath/test.xls");
|
FileInputStream fis = new FileInputStream("/somepath/test.xls");
|
||||||
HSSFWorkbook wb = new HSSFWorkbook(fis);
|
HSSFWorkbook wb = new HSSFWorkbook(fis);
|
||||||
@ -154,14 +204,14 @@ for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {
|
|||||||
HSSFSheet sheet = wb.getSheetAt(sheetNum);
|
HSSFSheet sheet = wb.getSheetAt(sheetNum);
|
||||||
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||||
|
|
||||||
for(Iterator rit = s.rowIterator(); rit.hasNext();) {
|
for(Iterator rit = sheet.rowIterator(); rit.hasNext();) {
|
||||||
HSSFRow r = (HSSFRow)rit.next();
|
HSSFRow r = (HSSFRow)rit.next();
|
||||||
evaluator.setCurrentRow(r);
|
evaluator.setCurrentRow(r);
|
||||||
|
|
||||||
for(Iterator cit = r.cellIterator(); cit.hasNext();) {
|
for(Iterator cit = r.cellIterator(); cit.hasNext();) {
|
||||||
HSSFCell c = (HSSFCell)cit.next();
|
HSSFCell c = (HSSFCell)cit.next();
|
||||||
if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
if(c.getCellType() == HSSFCell.CELL_TYPE_FORMULA) {
|
||||||
evaluator.evaluateInCell(c);
|
evaluator.evaluateFormulaCell(c);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -33,6 +33,8 @@
|
|||||||
<!-- Don't forget to update changes.xml too! -->
|
<!-- Don't forget to update changes.xml too! -->
|
||||||
<changes>
|
<changes>
|
||||||
<release version="3.0.2-FINAL" date="2008-??-??">
|
<release version="3.0.2-FINAL" date="2008-??-??">
|
||||||
|
<action dev="POI-DEVELOPERS" type="fix">44254 - Avoid some unread byte warnings, and properly understand DVALRecord</action>
|
||||||
|
<action dev="POI-DEVELOPERS" type="add">Add another formula evaluation method, evaluateFormulaCell(cell), which will re-calculate the value for a formula, without affecting the formula itself.</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">41726 - Fix how we handle signed cell offsets in relative areas and references</action>
|
<action dev="POI-DEVELOPERS" type="fix">41726 - Fix how we handle signed cell offsets in relative areas and references</action>
|
||||||
<action dev="POI-DEVELOPERS" type="add">44233 - Support for getting and setting a flag on the sheet, which tells excel to re-calculate all formulas on it at next reload</action>
|
<action dev="POI-DEVELOPERS" type="add">44233 - Support for getting and setting a flag on the sheet, which tells excel to re-calculate all formulas on it at next reload</action>
|
||||||
<action dev="POI-DEVELOPERS" type="fix">44201 - Enable cloning of sheets with data validation rules</action>
|
<action dev="POI-DEVELOPERS" type="fix">44201 - Enable cloning of sheets with data validation rules</action>
|
||||||
|
@ -29,19 +29,22 @@ import org.apache.poi.util.LittleEndian;
|
|||||||
|
|
||||||
public class DVALRecord extends Record
|
public class DVALRecord extends Record
|
||||||
{
|
{
|
||||||
public final static short sid = 0x01B2;
|
public final static short sid = 0x01B2;
|
||||||
|
|
||||||
//unknown field ; it's size should be 10
|
/** Options of the DVAL */
|
||||||
private short field_unknown = 0x0000;
|
private short field_1_options;
|
||||||
|
/** Horizontal position of the dialog */
|
||||||
|
private int field_2_horiz_pos;
|
||||||
|
/** Vertical position of the dialog */
|
||||||
|
private int field_3_vert_pos;
|
||||||
|
|
||||||
//Object ID of the drop down arrow object for list boxes ;
|
/** Object ID of the drop down arrow object for list boxes ;
|
||||||
//in our case this will be always FFFF , until
|
* in our case this will be always FFFF , until
|
||||||
//MSODrawingGroup and MSODrawing records are implemented
|
* MSODrawingGroup and MSODrawing records are implemented */
|
||||||
private int field_cbo_id = 0xFFFFFFFF;
|
private int field_cbo_id = 0xFFFFFFFF;
|
||||||
|
|
||||||
//Number of following DV records
|
/** Number of following DV Records */
|
||||||
//Default value is 1
|
private int field_5_dv_no = 0x00000000;
|
||||||
private int field_3_dv_no = 0x00000000;
|
|
||||||
|
|
||||||
public DVALRecord()
|
public DVALRecord()
|
||||||
{
|
{
|
||||||
@ -66,17 +69,38 @@ public class DVALRecord extends Record
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void fillFields(RecordInputStream in)
|
protected void fillFields(RecordInputStream in)
|
||||||
{
|
{
|
||||||
for ( int i=0; i<5; i++)
|
this.field_1_options = in.readShort();
|
||||||
{
|
this.field_2_horiz_pos = in.readInt();
|
||||||
this.field_unknown = in.readShort();
|
this.field_3_vert_pos = in.readInt();
|
||||||
}
|
|
||||||
this.field_cbo_id = in.readInt();
|
this.field_cbo_id = in.readInt();
|
||||||
this.field_3_dv_no = in.readInt();
|
this.field_5_dv_no = in.readInt();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @param field_1_options the options of the dialog
|
||||||
|
*/
|
||||||
|
public void setOptions(short field_1_options) {
|
||||||
|
this.field_1_options = field_1_options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param field_2_horiz_pos the Horizontal position of the dialog
|
||||||
|
*/
|
||||||
|
public void setHorizontalPos(int field_2_horiz_pos) {
|
||||||
|
this.field_2_horiz_pos = field_2_horiz_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param field_3_vert_pos the Vertical position of the dialog
|
||||||
|
*/
|
||||||
|
public void setVerticalPos(int field_3_vert_pos) {
|
||||||
|
this.field_3_vert_pos = field_3_vert_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* set the object ID of the drop down arrow object for list boxes
|
* set the object ID of the drop down arrow object for list boxes
|
||||||
* @param cboID - Object ID
|
* @param cboID - Object ID
|
||||||
*/
|
*/
|
||||||
@ -91,10 +115,33 @@ public class DVALRecord extends Record
|
|||||||
*/
|
*/
|
||||||
public void setDVRecNo(int dvNo)
|
public void setDVRecNo(int dvNo)
|
||||||
{
|
{
|
||||||
this.field_3_dv_no = dvNo;
|
this.field_5_dv_no = dvNo;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
* @return the field_1_options
|
||||||
|
*/
|
||||||
|
public short getOptions() {
|
||||||
|
return field_1_options;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the Horizontal position of the dialog
|
||||||
|
*/
|
||||||
|
public int getHorizontalPos() {
|
||||||
|
return field_2_horiz_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @return the the Vertical position of the dialog
|
||||||
|
*/
|
||||||
|
public int getVerticalPos() {
|
||||||
|
return field_3_vert_pos;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
* get Object ID of the drop down arrow object for list boxes
|
* get Object ID of the drop down arrow object for list boxes
|
||||||
*/
|
*/
|
||||||
public int getObjectID( )
|
public int getObjectID( )
|
||||||
@ -107,29 +154,32 @@ public class DVALRecord extends Record
|
|||||||
*/
|
*/
|
||||||
public int getDVRecNo( )
|
public int getDVRecNo( )
|
||||||
{
|
{
|
||||||
return this.field_3_dv_no;
|
return this.field_5_dv_no;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
public String toString()
|
public String toString()
|
||||||
{
|
{
|
||||||
StringBuffer buffer = new StringBuffer();
|
StringBuffer buffer = new StringBuffer();
|
||||||
|
|
||||||
buffer.append("[DVAL]\n");
|
buffer.append("[DVAL]\n");
|
||||||
buffer.append(" .comboObjectID = ").append(Integer.toHexString(this.getObjectID())).append("\n");
|
buffer.append(" .options = ").append(this.getOptions()).append('\n');
|
||||||
buffer.append(" .DVRecordsNumber = ").append(Integer.toHexString(this.getDVRecNo())).append("\n");
|
buffer.append(" .horizPos = ").append(this.getHorizontalPos()).append('\n');
|
||||||
buffer.append("[/DVAL]\n");
|
buffer.append(" .vertPos = ").append(this.getVerticalPos()).append('\n');
|
||||||
return buffer.toString();
|
buffer.append(" .comboObjectID = ").append(Integer.toHexString(this.getObjectID())).append("\n");
|
||||||
}
|
buffer.append(" .DVRecordsNumber = ").append(Integer.toHexString(this.getDVRecNo())).append("\n");
|
||||||
|
buffer.append("[/DVAL]\n");
|
||||||
|
return buffer.toString();
|
||||||
|
}
|
||||||
|
|
||||||
public int serialize(int offset, byte [] data)
|
public int serialize(int offset, byte [] data)
|
||||||
{
|
{
|
||||||
LittleEndian.putShort(data, 0 + offset, this.sid);
|
LittleEndian.putShort(data, 0 + offset, this.sid);
|
||||||
LittleEndian.putShort(data, 2 + offset, ( short)(this.getRecordSize()-4));
|
LittleEndian.putShort(data, 2 + offset, ( short)(this.getRecordSize()-4));
|
||||||
for ( int i=0; i<5; i++)
|
|
||||||
{
|
LittleEndian.putShort(data, 4 + offset, this.getOptions());
|
||||||
LittleEndian.putShort(data, 4 + i*2 + offset, (short)this.field_unknown);
|
LittleEndian.putInt(data, 6 + offset, this.getHorizontalPos());
|
||||||
}
|
LittleEndian.putInt(data, 10 + offset, this.getVerticalPos());
|
||||||
LittleEndian.putInt(data, 14 + offset, this.getObjectID());
|
LittleEndian.putInt(data, 14 + offset, this.getObjectID());
|
||||||
LittleEndian.putInt(data, 18 + offset, this.getDVRecNo());
|
LittleEndian.putInt(data, 18 + offset, this.getDVRecNo());
|
||||||
return getRecordSize();
|
return getRecordSize();
|
||||||
@ -149,9 +199,11 @@ public class DVALRecord extends Record
|
|||||||
public Object clone()
|
public Object clone()
|
||||||
{
|
{
|
||||||
DVALRecord rec = new DVALRecord();
|
DVALRecord rec = new DVALRecord();
|
||||||
rec.field_unknown = this.field_unknown;
|
rec.field_1_options = field_1_options;
|
||||||
|
rec.field_2_horiz_pos = field_2_horiz_pos;
|
||||||
|
rec.field_3_vert_pos = field_3_vert_pos;
|
||||||
rec.field_cbo_id = this.field_cbo_id;
|
rec.field_cbo_id = this.field_cbo_id;
|
||||||
rec.field_3_dv_no = this.field_3_dv_no;
|
rec.field_5_dv_no = this.field_5_dv_no;
|
||||||
return rec;
|
return rec;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,6 +55,7 @@ public class UncalcedRecord extends Record
|
|||||||
}
|
}
|
||||||
|
|
||||||
protected void fillFields(RecordInputStream in) {
|
protected void fillFields(RecordInputStream in) {
|
||||||
|
short unused = in.readShort();
|
||||||
}
|
}
|
||||||
|
|
||||||
public String toString() {
|
public String toString() {
|
||||||
|
@ -29,7 +29,7 @@ import org.apache.poi.hssf.usermodel.HSSFErrorConstants;
|
|||||||
public class ErrPtg extends Ptg
|
public class ErrPtg extends Ptg
|
||||||
{
|
{
|
||||||
public static final short sid = 0x1c;
|
public static final short sid = 0x1c;
|
||||||
private static final int SIZE = 7;
|
private static final int SIZE = 2;
|
||||||
private byte field_1_error_code;
|
private byte field_1_error_code;
|
||||||
|
|
||||||
/** Creates new ErrPtg */
|
/** Creates new ErrPtg */
|
||||||
|
@ -538,7 +538,13 @@ public class HSSFCell implements Cell
|
|||||||
{
|
{
|
||||||
setCellType(CELL_TYPE_NUMERIC, false, row, col, styleIndex);
|
setCellType(CELL_TYPE_NUMERIC, false, row, col, styleIndex);
|
||||||
}
|
}
|
||||||
(( NumberRecord ) record).setValue(value);
|
|
||||||
|
// Save into the apropriate record
|
||||||
|
if(record instanceof FormulaRecordAggregate) {
|
||||||
|
(( FormulaRecordAggregate ) record).getFormulaRecord().setValue(value);
|
||||||
|
} else {
|
||||||
|
(( NumberRecord ) record).setValue(value);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -217,14 +217,66 @@ public class HSSFFormulaEvaluator {
|
|||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* If cell contains formula, it evaluates the formula, and puts the
|
* If cell contains formula, it evaluates the formula,
|
||||||
* formula result back into the cell.
|
* and saves the result of the formula. The cell
|
||||||
* Else if cell does not contain formula, this method leaves the cell
|
* remains as a formula cell.
|
||||||
* unchanged. Note that the same instance of HSSFCell is returned to
|
* Else if cell does not contain formula, this method leaves
|
||||||
|
* the cell unchanged.
|
||||||
|
* Note that the type of the formula result is returned,
|
||||||
|
* so you know what kind of value is also stored with
|
||||||
|
* the formula.
|
||||||
|
* <pre>
|
||||||
|
* int evaluatedCellType = evaluator.evaluateFormulaCell(cell);
|
||||||
|
* </pre>
|
||||||
|
* Be aware that your cell will hold both the formula,
|
||||||
|
* and the result. If you want the cell replaced with
|
||||||
|
* the result of the formula, use {@link #evaluateInCell(HSSFCell)}
|
||||||
|
* @param cell The cell to evaluate
|
||||||
|
* @return The type of the formula result (the cell's type remains as HSSFCell.CELL_TYPE_FORMULA however)
|
||||||
|
*/
|
||||||
|
public int evaluateFormulaCell(HSSFCell cell) {
|
||||||
|
if (cell != null) {
|
||||||
|
switch (cell.getCellType()) {
|
||||||
|
case HSSFCell.CELL_TYPE_FORMULA:
|
||||||
|
CellValue cv = getCellValueForEval(internalEvaluate(cell, row, sheet, workbook));
|
||||||
|
switch (cv.getCellType()) {
|
||||||
|
case HSSFCell.CELL_TYPE_BOOLEAN:
|
||||||
|
cell.setCellValue(cv.getBooleanValue());
|
||||||
|
break;
|
||||||
|
case HSSFCell.CELL_TYPE_ERROR:
|
||||||
|
cell.setCellValue(cv.getErrorValue());
|
||||||
|
break;
|
||||||
|
case HSSFCell.CELL_TYPE_NUMERIC:
|
||||||
|
cell.setCellValue(cv.getNumberValue());
|
||||||
|
break;
|
||||||
|
case HSSFCell.CELL_TYPE_STRING:
|
||||||
|
cell.setCellValue(cv.getRichTextStringValue());
|
||||||
|
break;
|
||||||
|
case HSSFCell.CELL_TYPE_BLANK:
|
||||||
|
break;
|
||||||
|
case HSSFCell.CELL_TYPE_FORMULA: // this will never happen, we have already evaluated the formula
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
return cv.getCellType();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If cell contains formula, it evaluates the formula, and
|
||||||
|
* puts the formula result back into the cell, in place
|
||||||
|
* of the old formula.
|
||||||
|
* Else if cell does not contain formula, this method leaves
|
||||||
|
* the cell unchanged.
|
||||||
|
* Note that the same instance of HSSFCell is returned to
|
||||||
* allow chained calls like:
|
* allow chained calls like:
|
||||||
* <pre>
|
* <pre>
|
||||||
* int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
|
* int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
|
||||||
* </pre>
|
* </pre>
|
||||||
|
* Be aware that your cell value will be changed to hold the
|
||||||
|
* result of the formula. If you simply want the formula
|
||||||
|
* value computed for you, use {@link #evaluateFormulaCell(HSSFCell)}
|
||||||
* @param cell
|
* @param cell
|
||||||
*/
|
*/
|
||||||
public HSSFCell evaluateInCell(HSSFCell cell) {
|
public HSSFCell evaluateInCell(HSSFCell cell) {
|
||||||
|
@ -0,0 +1,117 @@
|
|||||||
|
package org.apache.poi.hssf.usermodel;
|
||||||
|
|
||||||
|
import java.util.Iterator;
|
||||||
|
|
||||||
|
import junit.framework.TestCase;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Tests to show that our documentation at
|
||||||
|
* http://poi.apache.org/hssf/eval.html
|
||||||
|
* all actually works as we'd expect them to
|
||||||
|
*/
|
||||||
|
public class TestFormulaEvaluatorDocs extends TestCase {
|
||||||
|
protected void setUp() throws Exception {
|
||||||
|
super.setUp();
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* http://poi.apache.org/hssf/eval.html#EvaluateAll
|
||||||
|
*/
|
||||||
|
public void testEvaluateAll() throws Exception {
|
||||||
|
HSSFWorkbook wb = new HSSFWorkbook();
|
||||||
|
HSSFSheet s1 = wb.createSheet();
|
||||||
|
HSSFSheet s2 = wb.createSheet();
|
||||||
|
wb.setSheetName(0, "S1");
|
||||||
|
wb.setSheetName(1, "S2");
|
||||||
|
|
||||||
|
HSSFRow s1r1 = s1.createRow(0);
|
||||||
|
HSSFRow s1r2 = s1.createRow(1);
|
||||||
|
HSSFRow s2r1 = s2.createRow(0);
|
||||||
|
|
||||||
|
HSSFCell s1r1c1 = s1r1.createCell((short)0);
|
||||||
|
HSSFCell s1r1c2 = s1r1.createCell((short)1);
|
||||||
|
HSSFCell s1r1c3 = s1r1.createCell((short)2);
|
||||||
|
s1r1c1.setCellValue(22.3);
|
||||||
|
s1r1c2.setCellValue(33.4);
|
||||||
|
s1r1c3.setCellFormula("SUM(A1:B1)");
|
||||||
|
|
||||||
|
HSSFCell s1r2c1 = s1r2.createCell((short)0);
|
||||||
|
HSSFCell s1r2c2 = s1r2.createCell((short)1);
|
||||||
|
HSSFCell s1r2c3 = s1r2.createCell((short)2);
|
||||||
|
s1r2c1.setCellValue(-1.2);
|
||||||
|
s1r2c2.setCellValue(-3.4);
|
||||||
|
s1r2c3.setCellFormula("SUM(A2:B2)");
|
||||||
|
|
||||||
|
HSSFCell s2r1c1 = s2r1.createCell((short)0);
|
||||||
|
s2r1c1.setCellFormula("S1!A1");
|
||||||
|
|
||||||
|
// Not evaluated yet
|
||||||
|
assertEquals(0.0, s1r1c3.getNumericCellValue(), 0);
|
||||||
|
assertEquals(0.0, s1r2c3.getNumericCellValue(), 0);
|
||||||
|
assertEquals(0.0, s2r1c1.getNumericCellValue(), 0);
|
||||||
|
|
||||||
|
// Do a full evaluate, as per our docs
|
||||||
|
// uses evaluateFormulaCell()
|
||||||
|
for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {
|
||||||
|
HSSFSheet sheet = wb.getSheetAt(sheetNum);
|
||||||
|
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||||
|
|
||||||
|
for(Iterator rit = sheet.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.evaluateFormulaCell(c);
|
||||||
|
|
||||||
|
// For testing - all should be numeric
|
||||||
|
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, evaluator.evaluateFormulaCell(c));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check now as expected
|
||||||
|
assertEquals(55.7, wb.getSheetAt(0).getRow(0).getCell((short)2).getNumericCellValue(), 0);
|
||||||
|
assertEquals("SUM(A1:B1)", wb.getSheetAt(0).getRow(0).getCell((short)2).getCellFormula());
|
||||||
|
assertEquals(HSSFCell.CELL_TYPE_FORMULA, wb.getSheetAt(0).getRow(0).getCell((short)2).getCellType());
|
||||||
|
|
||||||
|
assertEquals(-4.6, wb.getSheetAt(0).getRow(1).getCell((short)2).getNumericCellValue(), 0);
|
||||||
|
assertEquals("SUM(A2:B2)", wb.getSheetAt(0).getRow(1).getCell((short)2).getCellFormula());
|
||||||
|
assertEquals(HSSFCell.CELL_TYPE_FORMULA, wb.getSheetAt(0).getRow(1).getCell((short)2).getCellType());
|
||||||
|
|
||||||
|
assertEquals(22.3, wb.getSheetAt(1).getRow(0).getCell((short)0).getNumericCellValue(), 0);
|
||||||
|
assertEquals("S1!A1", wb.getSheetAt(1).getRow(0).getCell((short)0).getCellFormula());
|
||||||
|
assertEquals(HSSFCell.CELL_TYPE_FORMULA, wb.getSheetAt(1).getRow(0).getCell((short)0).getCellType());
|
||||||
|
|
||||||
|
|
||||||
|
// Now do the alternate call, which zaps the formulas
|
||||||
|
// uses evaluateInCell()
|
||||||
|
for(int sheetNum = 0; sheetNum < wb.getNumberOfSheets(); sheetNum++) {
|
||||||
|
HSSFSheet sheet = wb.getSheetAt(sheetNum);
|
||||||
|
HSSFFormulaEvaluator evaluator = new HSSFFormulaEvaluator(sheet, wb);
|
||||||
|
|
||||||
|
for(Iterator rit = sheet.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);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
assertEquals(55.7, wb.getSheetAt(0).getRow(0).getCell((short)2).getNumericCellValue(), 0);
|
||||||
|
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, wb.getSheetAt(0).getRow(0).getCell((short)2).getCellType());
|
||||||
|
|
||||||
|
assertEquals(-4.6, wb.getSheetAt(0).getRow(1).getCell((short)2).getNumericCellValue(), 0);
|
||||||
|
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, wb.getSheetAt(0).getRow(1).getCell((short)2).getCellType());
|
||||||
|
|
||||||
|
assertEquals(22.3, wb.getSheetAt(1).getRow(0).getCell((short)0).getNumericCellValue(), 0);
|
||||||
|
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, wb.getSheetAt(1).getRow(0).getCell((short)0).getCellType());
|
||||||
|
}
|
||||||
|
}
|
Loading…
Reference in New Issue
Block a user