Patch largely from Josh from bug #44539 - Support for area references in formulas of rows >= 32768

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@634630 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-03-07 12:06:18 +00:00
parent 96198ae3d1
commit ff78b7ac71
27 changed files with 443 additions and 376 deletions

View File

@ -36,6 +36,7 @@
<!-- Don't forget to update status.xml too! -->
<release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">44539 - Support for area references in formulas of rows >= 32768</action>
<action dev="POI-DEVELOPERS" type="add">44536 - Improved support for detecting read-only recommended files</action>
<action dev="POI-DEVELOPERS" type="fix">43901 - Correctly update the internal last cell number when adding and removing cells (previously sometimes off-by-one)</action>
<action dev="POI-DEVELOPERS" type="fix">28231 - For apparently truncated files, which are somehow still valid, now issue a truncation warning but carry on, rather than giving an exception as before</action>

View File

@ -33,6 +33,7 @@
<!-- Don't forget to update changes.xml too! -->
<changes>
<release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="add">44539 - Support for area references in formulas of rows >= 32768</action>
<action dev="POI-DEVELOPERS" type="add">44536 - Improved support for detecting read-only recommended files</action>
<action dev="POI-DEVELOPERS" type="fix">43901 - Correctly update the internal last cell number when adding and removing cells (previously sometimes off-by-one)</action>
<action dev="POI-DEVELOPERS" type="fix">44504 - Added initial support for recognising external functions like YEARFRAC and ISEVEN (using NameXPtg), via LinkTable support</action>

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -15,8 +14,7 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.record;
import java.util.Stack;
@ -34,10 +32,7 @@ import org.apache.poi.hssf.record.formula.*;
* record types.
* @author Danny Mui at apache dot org
*/
public class SharedFormulaRecord
extends Record
{
public final class SharedFormulaRecord extends Record {
public final static short sid = 0x4BC;
private int field_1_first_row;
@ -58,15 +53,15 @@ public class SharedFormulaRecord
public SharedFormulaRecord(RecordInputStream in)
{
super(in);
super(in);
}
protected void validateSid(short id)
{
if (id != this.sid)
{
throw new RecordFormatException("Not a valid SharedFormula");
}
if (id != this.sid)
{
throw new RecordFormatException("Not a valid SharedFormula");
}
}
public int getFirstRow() {
@ -96,14 +91,14 @@ public class SharedFormulaRecord
public int serialize(int offset, byte [] data)
{
//Because this record is converted to individual Formula records, this method is not required.
throw new UnsupportedOperationException("Cannot serialize a SharedFormulaRecord");
//Because this record is converted to individual Formula records, this method is not required.
throw new UnsupportedOperationException("Cannot serialize a SharedFormulaRecord");
}
public int getRecordSize()
{
//Because this record is converted to individual Formula records, this method is not required.
throw new UnsupportedOperationException("Cannot get the size for a SharedFormulaRecord");
//Because this record is converted to individual Formula records, this method is not required.
throw new UnsupportedOperationException("Cannot get the size for a SharedFormulaRecord");
}
@ -257,39 +252,40 @@ public class SharedFormulaRecord
}
}
private short fixupRelativeColumn(int currentcolumn, short column, boolean relative) {
if(relative) {
if((column&128)!=0) column=(short)(column-256);
column+=currentcolumn;
}
return column;
}
private int fixupRelativeColumn(int currentcolumn, int column, boolean relative) {
if(relative) {
// mask out upper bits to produce 'wrapping' at column 256 ("IV")
return (column + currentcolumn) & 0x00FF;
}
return column;
}
private short fixupRelativeRow(int currentrow, short row, boolean relative) {
if(relative) {
row+=currentrow;
}
return row;
}
private int fixupRelativeRow(int currentrow, int row, boolean relative) {
if(relative) {
// mask out upper bits to produce 'wrapping' at row 65536
return (row+currentrow) & 0x00FFFF;
}
return row;
}
/**
* Mirroring formula records so it is registered in the ValueRecordsAggregate
*/
public boolean isInValueSection()
{
return true;
}
/**
* Mirroring formula records so it is registered in the ValueRecordsAggregate
*/
public boolean isInValueSection()
{
return true;
}
/**
* Register it in the ValueRecordsAggregate so it can go into the FormulaRecordAggregate
*/
public boolean isValue() {
return true;
}
/**
* Register it in the ValueRecordsAggregate so it can go into the FormulaRecordAggregate
*/
public boolean isValue() {
return true;
}
public Object clone() {
//Because this record is converted to individual Formula records, this method is not required.
throw new UnsupportedOperationException("Cannot clone a SharedFormulaRecord");
//Because this record is converted to individual Formula records, this method is not required.
throw new UnsupportedOperationException("Cannot clone a SharedFormulaRecord");
}
}

View File

@ -41,10 +41,10 @@ public class Area3DPtg extends Ptg implements AreaI
public final static byte sid = 0x3b;
private final static int SIZE = 11; // 10 + 1 for Ptg
private short field_1_index_extern_sheet;
private short field_2_first_row;
private short field_3_last_row;
private short field_4_first_column;
private short field_5_last_column;
private int field_2_first_row;
private int field_3_last_row;
private int field_4_first_column;
private int field_5_last_column;
private BitField rowRelative = BitFieldFactory.getInstance( 0x8000 );
private BitField colRelative = BitFieldFactory.getInstance( 0x4000 );
@ -64,27 +64,27 @@ public class Area3DPtg extends Ptg implements AreaI
public Area3DPtg(RecordInputStream in)
{
field_1_index_extern_sheet = in.readShort();
field_2_first_row = in.readShort();
field_3_last_row = in.readShort();
field_4_first_column = in.readShort();
field_5_last_column = in.readShort();
field_2_first_row = in.readUShort();
field_3_last_row = in.readUShort();
field_4_first_column = in.readUShort();
field_5_last_column = in.readUShort();
}
public Area3DPtg(short firstRow, short lastRow, short firstColumn, short lastColumn,
boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative,
short externalSheetIndex) {
setFirstRow(firstRow);
setLastRow(lastRow);
setFirstColumn(firstColumn);
setLastColumn(lastColumn);
setFirstRowRelative(firstRowRelative);
setLastRowRelative(lastRowRelative);
setFirstColRelative(firstColRelative);
setLastColRelative(lastColRelative);
setExternSheetIndex(externalSheetIndex);
}
boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative,
short externalSheetIndex) {
setFirstRow(firstRow);
setLastRow(lastRow);
setFirstColumn(firstColumn);
setLastColumn(lastColumn);
setFirstRowRelative(firstRowRelative);
setLastRowRelative(lastRowRelative);
setFirstColRelative(firstColRelative);
setLastColRelative(lastColRelative);
setExternSheetIndex(externalSheetIndex);
}
public String toString()
public String toString()
{
StringBuffer buffer = new StringBuffer();
@ -99,7 +99,7 @@ public class Area3DPtg extends Ptg implements AreaI
buffer.append( "lastColRowRel = "
+ isLastRowRelative() ).append( "\n" );
buffer.append( "firstColRel = " + isFirstColRelative() ).append( "\n" );
buffer.append( "lastColRel = " + isLastColRelative() ).append( "\n" );
buffer.append( "lastColRel = " + isLastColRelative() ).append( "\n" );
return buffer.toString();
}
@ -107,10 +107,10 @@ public class Area3DPtg extends Ptg implements AreaI
{
array[0 + offset] = (byte) ( sid + ptgClass );
LittleEndian.putShort( array, 1 + offset, getExternSheetIndex() );
LittleEndian.putShort( array, 3 + offset, getFirstRow() );
LittleEndian.putShort( array, 5 + offset, getLastRow() );
LittleEndian.putShort( array, 7 + offset, getFirstColumnRaw() );
LittleEndian.putShort( array, 9 + offset, getLastColumnRaw() );
LittleEndian.putShort( array, 3 + offset, (short)getFirstRow() );
LittleEndian.putShort( array, 5 + offset, (short)getLastRow() );
LittleEndian.putShort( array, 7 + offset, (short)getFirstColumnRaw() );
LittleEndian.putShort( array, 9 + offset, (short)getLastColumnRaw() );
}
public int getSize()
@ -128,32 +128,32 @@ public class Area3DPtg extends Ptg implements AreaI
field_1_index_extern_sheet = index;
}
public short getFirstRow()
public int getFirstRow()
{
return field_2_first_row;
}
public void setFirstRow( short row )
public void setFirstRow( int row )
{
field_2_first_row = row;
}
public short getLastRow()
public int getLastRow()
{
return field_3_last_row;
}
public void setLastRow( short row )
public void setLastRow( int row )
{
field_3_last_row = row;
}
public short getFirstColumn()
public int getFirstColumn()
{
return (short) ( field_4_first_column & 0xFF );
return field_4_first_column & 0xFF;
}
public short getFirstColumnRaw()
public int getFirstColumnRaw()
{
return field_4_first_column;
}
@ -179,12 +179,12 @@ public class Area3DPtg extends Ptg implements AreaI
field_4_first_column = column;
}
public short getLastColumn()
public int getLastColumn()
{
return (short) ( field_5_last_column & 0xFF );
return field_5_last_column & 0xFF;
}
public short getLastColumnRaw()
public int getLastColumnRaw()
{
return field_5_last_column;
}
@ -216,7 +216,7 @@ public class Area3DPtg extends Ptg implements AreaI
*/
public void setFirstRowRelative( boolean rel )
{
field_4_first_column = rowRelative.setShortBoolean( field_4_first_column, rel );
field_4_first_column = rowRelative.setBoolean( field_4_first_column, rel );
}
/**
@ -224,7 +224,7 @@ public class Area3DPtg extends Ptg implements AreaI
*/
public void setFirstColRelative( boolean rel )
{
field_4_first_column = colRelative.setShortBoolean( field_4_first_column, rel );
field_4_first_column = colRelative.setBoolean( field_4_first_column, rel );
}
/**
@ -233,7 +233,7 @@ public class Area3DPtg extends Ptg implements AreaI
*/
public void setLastRowRelative( boolean rel )
{
field_5_last_column = rowRelative.setShortBoolean( field_5_last_column, rel );
field_5_last_column = rowRelative.setBoolean( field_5_last_column, rel );
}
/**
@ -241,7 +241,7 @@ public class Area3DPtg extends Ptg implements AreaI
*/
public void setLastColRelative( boolean rel )
{
field_5_last_column = colRelative.setShortBoolean( field_5_last_column, rel );
field_5_last_column = colRelative.setBoolean( field_5_last_column, rel );
}
@ -259,20 +259,20 @@ public class Area3DPtg extends Ptg implements AreaI
CellReference frstCell = ar.getFirstCell();
CellReference lastCell = ar.getLastCell();
setFirstRow( (short) frstCell.getRow() );
setFirstColumn( frstCell.getCol() );
setLastRow( (short) lastCell.getRow() );
setLastColumn( lastCell.getCol() );
setFirstRow( (short) frstCell.getRow() );
setFirstColumn( frstCell.getCol() );
setLastRow( (short) lastCell.getRow() );
setLastColumn( lastCell.getCol() );
setFirstColRelative( !frstCell.isColAbsolute() );
setLastColRelative( !lastCell.isColAbsolute() );
setFirstRowRelative( !frstCell.isRowAbsolute() );
setLastRowRelative( !lastCell.isRowAbsolute() );
}
/**
* @return text representation of this area reference that can be used in text
* formulas. The sheet name will get properly delimited if required.
*/
/**
* @return text representation of this area reference that can be used in text
* formulas. The sheet name will get properly delimited if required.
*/
public String toFormulaString(Workbook book)
{
// First do the sheet name
@ -303,7 +303,7 @@ public class Area3DPtg extends Ptg implements AreaI
ptg.field_3_last_row = field_3_last_row;
ptg.field_4_first_column = field_4_first_column;
ptg.field_5_last_column = field_5_last_column;
ptg.setClass(ptgClass);
ptg.setClass(ptgClass);
return ptg;
}

View File

@ -36,16 +36,14 @@ import org.apache.poi.hssf.model.Workbook;
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class AreaAPtg
extends AreaPtg
{
public final class AreaAPtg extends AreaPtg {
public final static short sid = 0x65;
protected AreaAPtg() {
//Required for clone methods
}
public AreaAPtg(short firstRow, short lastRow, short firstColumn, short lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
public AreaAPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
}

View File

@ -24,22 +24,22 @@ public interface AreaI {
/**
* @return the first row in the area
*/
public short getFirstRow();
public int getFirstRow();
/**
* @return last row in the range (x2 in x1,y1-x2,y2)
*/
public short getLastRow();
public int getLastRow();
/**
* @return the first column number in the area.
*/
public short getFirstColumn();
public int getFirstColumn();
/**
* @return lastcolumn in the area
*/
public short getLastColumn();
public int getLastColumn();
/**
* @return isrelative first column to relative or not

View File

@ -38,10 +38,14 @@ public class AreaPtg
{
public final static short sid = 0x25;
private final static int SIZE = 9;
private short field_1_first_row;
private short field_2_last_row;
private short field_3_first_column;
private short field_4_last_column;
/** zero based, unsigned 16 bit */
private int field_1_first_row;
/** zero based, unsigned 16 bit */
private int field_2_last_row;
/** zero based, unsigned 8 bit */
private int field_3_first_column;
/** zero based, unsigned 8 bit */
private int field_4_last_column;
private final static BitField rowRelative = BitFieldFactory.getInstance(0x8000);
private final static BitField colRelative = BitFieldFactory.getInstance(0x4000);
@ -55,9 +59,9 @@ public class AreaPtg
AreaReference ar = new AreaReference(arearef);
CellReference firstCell = ar.getFirstCell();
CellReference lastCell = ar.getLastCell();
setFirstRow((short)firstCell.getRow());
setFirstRow(firstCell.getRow());
setFirstColumn(firstCell.getCol());
setLastRow((short)lastCell.getRow());
setLastRow(lastCell.getRow());
setLastColumn(lastCell.getCol());
setFirstColRelative(!firstCell.isColAbsolute());
setLastColRelative(!lastCell.isColAbsolute());
@ -65,7 +69,13 @@ public class AreaPtg
setLastRowRelative(!lastCell.isRowAbsolute());
}
public AreaPtg(short firstRow, short lastRow, short firstColumn, short lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
public AreaPtg(int firstRow, int lastRow, int firstColumn, int lastColumn,
boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
checkColumnBounds(firstColumn);
checkColumnBounds(lastColumn);
checkRowBounds(firstRow);
checkRowBounds(lastRow);
setFirstRow(firstRow);
setLastRow(lastRow);
setFirstColumn(firstColumn);
@ -76,12 +86,23 @@ public class AreaPtg
setLastColRelative(lastColRelative);
}
private static void checkColumnBounds(int colIx) {
if((colIx & 0x0FF) != colIx) {
throw new IllegalArgumentException("colIx (" + colIx + ") is out of range");
}
}
private static void checkRowBounds(int rowIx) {
if((rowIx & 0x0FFFF) != rowIx) {
throw new IllegalArgumentException("rowIx (" + rowIx + ") is out of range");
}
}
public AreaPtg(RecordInputStream in)
{
field_1_first_row = in.readShort();
field_2_last_row = in.readShort();
field_3_first_column = in.readShort();
field_4_last_column = in.readShort();
field_1_first_row = in.readUShort();
field_2_last_row = in.readUShort();
field_3_first_column = in.readUShort();
field_4_last_column = in.readUShort();
//System.out.println(toString());
}
@ -110,10 +131,10 @@ public class AreaPtg
public void writeBytes(byte [] array, int offset) {
array[offset] = (byte) (sid + ptgClass);
LittleEndian.putShort(array,offset+1,field_1_first_row);
LittleEndian.putShort(array,offset+3,field_2_last_row);
LittleEndian.putShort(array,offset+5,field_3_first_column);
LittleEndian.putShort(array,offset+7,field_4_last_column);
LittleEndian.putShort(array,offset+1,(short)field_1_first_row);
LittleEndian.putShort(array,offset+3,(short)field_2_last_row);
LittleEndian.putShort(array,offset+5,(short)field_3_first_column);
LittleEndian.putShort(array,offset+7,(short)field_4_last_column);
}
public int getSize()
@ -124,42 +145,42 @@ public class AreaPtg
/**
* @return the first row in the area
*/
public short getFirstRow()
public int getFirstRow()
{
return field_1_first_row;
}
/**
* sets the first row
* @param row number (0-based)
* @param rowIx number (0-based)
*/
public void setFirstRow(short row)
{
field_1_first_row = row;
public void setFirstRow(int rowIx) {
checkRowBounds(rowIx);
field_1_first_row = rowIx;
}
/**
* @return last row in the range (x2 in x1,y1-x2,y2)
*/
public short getLastRow()
public int getLastRow()
{
return field_2_last_row;
}
/**
* @param row last row number in the area
* @param rowIx last row number in the area
*/
public void setLastRow(short row)
{
field_2_last_row = row;
public void setLastRow(int rowIx) {
checkRowBounds(rowIx);
field_2_last_row = rowIx;
}
/**
* @return the first column number in the area.
*/
public short getFirstColumn()
public int getFirstColumn()
{
return columnMask.getShortValue(field_3_first_column);
return columnMask.getValue(field_3_first_column);
}
/**
@ -167,7 +188,7 @@ public class AreaPtg
*/
public short getFirstColumnRaw()
{
return field_3_first_column;
return (short) field_3_first_column; // TODO
}
/**
@ -183,7 +204,7 @@ public class AreaPtg
* @param rel is relative or not.
*/
public void setFirstRowRelative(boolean rel) {
field_3_first_column=rowRelative.setShortBoolean(field_3_first_column,rel);
field_3_first_column=rowRelative.setBoolean(field_3_first_column,rel);
}
/**
@ -198,21 +219,21 @@ public class AreaPtg
* set whether the first column is relative
*/
public void setFirstColRelative(boolean rel) {
field_3_first_column=colRelative.setShortBoolean(field_3_first_column,rel);
field_3_first_column=colRelative.setBoolean(field_3_first_column,rel);
}
/**
* set the first column in the area
*/
public void setFirstColumn(short column)
{
field_3_first_column=columnMask.setShortValue(field_3_first_column, column);
public void setFirstColumn(int colIx) {
checkColumnBounds(colIx);
field_3_first_column=columnMask.setValue(field_3_first_column, colIx);
}
/**
* set the first column irespective of the bitmasks
*/
public void setFirstColumnRaw(short column)
public void setFirstColumnRaw(int column)
{
field_3_first_column = column;
}
@ -220,9 +241,9 @@ public class AreaPtg
/**
* @return lastcolumn in the area
*/
public short getLastColumn()
public int getLastColumn()
{
return columnMask.getShortValue(field_4_last_column);
return columnMask.getValue(field_4_last_column);
}
/**
@ -230,7 +251,7 @@ public class AreaPtg
*/
public short getLastColumnRaw()
{
return field_4_last_column;
return (short) field_4_last_column;
}
/**
@ -247,7 +268,7 @@ public class AreaPtg
* <code>false</code>
*/
public void setLastRowRelative(boolean rel) {
field_4_last_column=rowRelative.setShortBoolean(field_4_last_column,rel);
field_4_last_column=rowRelative.setBoolean(field_4_last_column,rel);
}
/**
@ -262,16 +283,16 @@ public class AreaPtg
* set whether the last column should be relative or not
*/
public void setLastColRelative(boolean rel) {
field_4_last_column=colRelative.setShortBoolean(field_4_last_column,rel);
field_4_last_column=colRelative.setBoolean(field_4_last_column,rel);
}
/**
* set the last column in the area
*/
public void setLastColumn(short column)
{
field_4_last_column=columnMask.setShortValue(field_4_last_column, column);
public void setLastColumn(int colIx) {
checkColumnBounds(colIx);
field_4_last_column=columnMask.setValue(field_4_last_column, colIx);
}
/**

View File

@ -36,7 +36,7 @@ import org.apache.poi.hssf.model.Workbook;
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class AreaVPtg
public final class AreaVPtg
extends AreaPtg
{
public final static short sid = 0x45;
@ -45,7 +45,7 @@ public class AreaVPtg
//Required for clone methods
}
public AreaVPtg(short firstRow, short lastRow, short firstColumn, short lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
public AreaVPtg(int firstRow, int lastRow, int firstColumn, int lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
super(firstRow, lastRow, firstColumn, lastColumn, firstRowRelative, lastRowRelative, firstColRelative, lastColRelative);
}

View File

@ -18,16 +18,14 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.hssf.util.RangeAddress;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.util.SheetReferences;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.hssf.model.Workbook;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.util.RangeAddress;
import org.apache.poi.hssf.util.SheetReferences;
import org.apache.poi.util.BitField;
import org.apache.poi.util.BitFieldFactory;
import org.apache.poi.util.LittleEndian;
/**
* Title: Reference 3D Ptg <P>
@ -42,8 +40,14 @@ public class Ref3DPtg extends Ptg {
public final static byte sid = 0x3a;
private final static int SIZE = 7; // 6 + 1 for Ptg
private short field_1_index_extern_sheet;
private short field_2_row;
private short field_3_column;
/** The row index - zero based unsigned 16 bit value */
private int field_2_row;
/** Field 2
* - lower 8 bits is the zero based unsigned byte column index
* - bit 16 - isRowRelative
* - bit 15 - isColumnRelative
*/
private int field_3_column;
private BitField rowRelative = BitFieldFactory.getInstance(0x8000);
private BitField colRelative = BitFieldFactory.getInstance(0x4000);
@ -58,8 +62,8 @@ public class Ref3DPtg extends Ptg {
public Ref3DPtg(String cellref, short externIdx ) {
CellReference c= new CellReference(cellref);
setRow((short) c.getRow());
setColumn((short) c.getCol());
setRow(c.getRow());
setColumn(c.getCol());
setColRelative(!c.isColAbsolute());
setRowRelative(!c.isRowAbsolute());
setExternSheetIndex(externIdx);
@ -81,8 +85,8 @@ public class Ref3DPtg extends Ptg {
public void writeBytes(byte [] array, int offset) {
array[ 0 + offset ] = (byte) (sid + ptgClass);
LittleEndian.putShort(array, 1 + offset , getExternSheetIndex());
LittleEndian.putShort(array, 3 + offset , getRow());
LittleEndian.putShort(array, 5 + offset , getColumnRaw());
LittleEndian.putShort(array, 3 + offset , (short)getRow());
LittleEndian.putShort(array, 5 + offset , (short)getColumnRaw());
}
public int getSize() {
@ -97,19 +101,19 @@ public class Ref3DPtg extends Ptg {
field_1_index_extern_sheet = index;
}
public short getRow() {
public int getRow() {
return field_2_row;
}
public void setRow(short row) {
public void setRow(int row) {
field_2_row = row;
}
public short getColumn() {
return ( short ) (field_3_column & 0xFF);
public int getColumn() {
return field_3_column & 0xFF;
}
public short getColumnRaw() {
public int getColumnRaw() {
return field_3_column;
}
@ -119,7 +123,7 @@ public class Ref3DPtg extends Ptg {
}
public void setRowRelative(boolean rel) {
field_3_column=rowRelative.setShortBoolean(field_3_column,rel);
field_3_column=rowRelative.setBoolean(field_3_column,rel);
}
public boolean isColRelative()
@ -128,7 +132,7 @@ public class Ref3DPtg extends Ptg {
}
public void setColRelative(boolean rel) {
field_3_column=colRelative.setShortBoolean(field_3_column,rel);
field_3_column=colRelative.setBoolean(field_3_column,rel);
}
public void setColumn(short column) {
field_3_column &= 0xFF00;
@ -197,5 +201,4 @@ public class Ref3DPtg extends Ptg {
ptg.setClass(ptgClass);
return ptg;
}
}

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -16,34 +15,23 @@
limitations under the License.
==================================================================== */
/*
* ValueReferencePtg.java
*
* Created on November 21, 2001, 5:27 PM
*/
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.BitField;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.model.Workbook;
/**
* RefNAPtg
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class RefAPtg extends ReferencePtg
{
public final class RefAPtg extends ReferencePtg {
public final static byte sid = 0x64;
protected RefAPtg() {
super();
}
public RefAPtg(short row, short column, boolean isRowRelative, boolean isColumnRelative) {
public RefAPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
super(row, column, isRowRelative, isColumnRelative);
}

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -18,27 +17,20 @@
package org.apache.poi.hssf.record.formula;
import org.apache.poi.util.LittleEndian;
import org.apache.poi.util.BitField;
import org.apache.poi.hssf.record.RecordInputStream;
import org.apache.poi.hssf.util.CellReference;
import org.apache.poi.hssf.model.Workbook;
/**
* RefVPtg
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class RefVPtg extends ReferencePtg
{
public final class RefVPtg extends ReferencePtg {
public final static byte sid = 0x44;
protected RefVPtg() {
super();
}
public RefVPtg(short row, short column, boolean isRowRelative, boolean isColumnRelative) {
public RefVPtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
super(row, column, isRowRelative, isColumnRelative);
}

View File

@ -31,26 +31,22 @@ import org.apache.poi.hssf.record.RecordInputStream;
* @author Jason Height (jheight at chariot dot net dot au)
*/
public class ReferencePtg extends Ptg
{
public class ReferencePtg extends Ptg {
private final static int SIZE = 5;
public final static byte sid = 0x24;
private final static int MAX_ROW_NUMBER = 65536;
//public final static byte sid = 0x44;
/**
* The row number, between 0 and 65535, but stored as a signed
* short between -32767 and 32768.
* Take care about which version you fetch back!
/** The row index - zero based unsigned 16 bit value */
private int field_1_row;
/** Field 2
* - lower 8 bits is the zero based unsigned byte column index
* - bit 16 - isRowRelative
* - bit 15 - isColumnRelative
*/
private short field_1_row;
/**
* The column number, between 0 and ??
*/
private short field_2_col;
private BitField rowRelative = BitFieldFactory.getInstance(0x8000);
private BitField colRelative = BitFieldFactory.getInstance(0x4000);
private BitField column = BitFieldFactory.getInstance(0x3FFF);
private int field_2_col;
private static final BitField rowRelative = BitFieldFactory.getInstance(0x8000);
private static final BitField colRelative = BitFieldFactory.getInstance(0x4000);
private static final BitField column = BitFieldFactory.getInstance(0x00FF);
protected ReferencePtg() {
//Required for clone methods
@ -62,13 +58,13 @@ public class ReferencePtg extends Ptg
*/
public ReferencePtg(String cellref) {
CellReference c= new CellReference(cellref);
setRow((short) c.getRow());
setColumn((short) c.getCol());
setRow(c.getRow());
setColumn(c.getCol());
setColRelative(!c.isColAbsolute());
setRowRelative(!c.isRowAbsolute());
}
public ReferencePtg(short row, short column, boolean isRowRelative, boolean isColumnRelative) {
public ReferencePtg(int row, int column, boolean isRowRelative, boolean isColumnRelative) {
setRow(row);
setColumn(column);
setRowRelative(isRowRelative);
@ -79,8 +75,8 @@ public class ReferencePtg extends Ptg
public ReferencePtg(RecordInputStream in)
{
field_1_row = in.readShort();
field_2_col = in.readShort();
field_1_row = in.readUShort();
field_2_col = in.readUShort();
}
public String getRefPtgName() {
@ -104,33 +100,23 @@ public class ReferencePtg extends Ptg
{
array[offset] = (byte) (sid + ptgClass);
LittleEndian.putShort(array,offset+1,field_1_row);
LittleEndian.putShort(array,offset+3,field_2_col);
LittleEndian.putShort(array, offset+1, (short)field_1_row);
LittleEndian.putShort(array, offset+3, (short)field_2_col);
}
public void setRow(short row)
{
field_1_row = row;
}
public void setRow(int row)
{
if(row < 0 || row >= MAX_ROW_NUMBER) {
throw new IllegalArgumentException("The row number, when specified as an integer, must be between 0 and " + MAX_ROW_NUMBER);
}
// Save, wrapping as needed
if(row > Short.MAX_VALUE) {
field_1_row = (short)(row - MAX_ROW_NUMBER);
} else {
field_1_row = (short)row;
}
field_1_row = row;
}
/**
* Returns the row number as a short, which will be
* wrapped (negative) for values between 32769 and 65535
*/
public short getRow()
public int getRow()
{
return field_1_row;
}
@ -151,7 +137,7 @@ public class ReferencePtg extends Ptg
}
public void setRowRelative(boolean rel) {
field_2_col=rowRelative.setShortBoolean(field_2_col,rel);
field_2_col=rowRelative.setBoolean(field_2_col,rel);
}
public boolean isColRelative()
@ -160,27 +146,29 @@ public class ReferencePtg extends Ptg
}
public void setColRelative(boolean rel) {
field_2_col=colRelative.setShortBoolean(field_2_col,rel);
field_2_col=colRelative.setBoolean(field_2_col,rel);
}
public void setColumnRaw(short col)
public void setColumnRaw(int col)
{
field_2_col = col;
}
public short getColumnRaw()
public int getColumnRaw()
{
return field_2_col;
}
public void setColumn(short col)
public void setColumn(int col)
{
field_2_col = column.setShortValue(field_2_col, col);
if(col < 0 || col > 0x100) {
throw new IllegalArgumentException("Specified colIx (" + col + ") is out of range");
}
field_2_col = column.setValue(field_2_col, col);
}
public short getColumn()
{
return column.getShortValue(field_2_col);
public int getColumn() {
return column.getValue(field_2_col);
}
public int getSize()

View File

@ -287,17 +287,30 @@ public final class HSSFRow implements Comparable {
}
/**
* get the hssfcell representing a given column (logical cell) 0-based. If you
* ask for a cell that is not defined....you get a null.
* Get the hssfcell representing a given column (logical cell)
* 0-based. If you ask for a cell that is not defined....
* you get a null.
* Short method signature provided to retain binary
* compatibility.
*
* @param cellnum 0 based column number
* @return HSSFCell representing that column or null if undefined.
*/
public HSSFCell getCell(short cellnum)
{
if(cellnum<0||cellnum>=cells.length) return null;
return cells[cellnum];
return getCell((int)cellnum);
}
/**
* Get the hssfcell representing a given column (logical cell)
* 0-based. If you ask for a cell that is not defined....
* you get a null.
*
* @param cellnum 0 based column number
* @return HSSFCell representing that column or null if undefined.
*/
public HSSFCell getCell(int cellnum) {
if(cellnum<0||cellnum>=cells.length) return null;
return cells[cellnum];
}
/**

View File

@ -53,9 +53,10 @@ public final class AreaReference {
parts[1].length() == 1 &&
parts[0].charAt(0) >= 'A' && parts[0].charAt(0) <= 'Z' &&
parts[1].charAt(0) >= 'A' && parts[1].charAt(0) <= 'Z') {
// Represented internally as x$1 to x$0
// Represented internally as x$1 to x$65536
// which is the maximum range of rows
parts[0] = parts[0] + "$1";
parts[1] = parts[1] + "$0";
parts[1] = parts[1] + "$65536";
}
_firstCell = new CellReference(parts[0]);
@ -98,10 +99,10 @@ public final class AreaReference {
*/
public static boolean isWholeColumnReference(CellReference topLeft, CellReference botRight) {
// These are represented as something like
// C$1:C$0 or D$1:F$0
// C$1:C$65535 or D$1:F$0
// i.e. absolute from 1st row to 0th one
if(topLeft.getRow() == 0 && topLeft.isRowAbsolute() &&
botRight.getRow() == -1 && botRight.isRowAbsolute()) {
botRight.getRow() == 65535 && botRight.isRowAbsolute()) {
return true;
}
return false;

View File

@ -71,6 +71,14 @@ public final class CellReference {
this(null, pRow, pCol, pAbsRow, pAbsCol);
}
public CellReference(String pSheetName, int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
// TODO - "-1" is a special value being temporarily used for whole row and whole column area references.
// so these checks are currently N.Q.R.
if(pRow < -1) {
throw new IllegalArgumentException("row index may not be negative");
}
if(pCol < -1) {
throw new IllegalArgumentException("column index may not be negative");
}
_sheetName = pSheetName;
_rowIndex=pRow;
_colIndex=pCol;

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.AreaPtg;
@ -27,48 +24,60 @@ import org.apache.poi.hssf.record.formula.Ptg;
* @author Amol S. Deshmukh &lt; amolweb at ya hoo dot com &gt;
*
*/
public class Area2DEval implements AreaEval {
public final class Area2DEval implements AreaEval {
// TODO -refactor with Area3DEval
private final AreaPtg _delegate;
private AreaPtg delegate;
private ValueEval[] values;
private final ValueEval[] _values;
public Area2DEval(Ptg ptg, ValueEval[] values) {
this.delegate = (AreaPtg) ptg;
this.values = values;
if(ptg == null) {
throw new IllegalArgumentException("ptg must not be null");
}
if(values == null) {
throw new IllegalArgumentException("values must not be null");
}
for(int i=values.length-1; i>=0; i--) {
if(values[i] == null) {
throw new IllegalArgumentException("value array elements must not be null");
}
}
// TODO - check size of array vs size of AreaPtg
_delegate = (AreaPtg) ptg;
_values = values;
}
public short getFirstColumn() {
return delegate.getFirstColumn();
public int getFirstColumn() {
return _delegate.getFirstColumn();
}
public int getFirstRow() {
return delegate.getFirstRow();
return _delegate.getFirstRow();
}
public short getLastColumn() {
return delegate.getLastColumn();
public int getLastColumn() {
return _delegate.getLastColumn();
}
public int getLastRow() {
return delegate.getLastRow();
return _delegate.getLastRow();
}
public ValueEval[] getValues() {
return values;
return _values;
}
public ValueEval getValueAt(int row, short col) {
public ValueEval getValueAt(int row, int col) {
ValueEval retval;
int index = ((row-getFirstRow())*(getLastColumn()-getFirstColumn()+1))+(col-getFirstColumn());
if (index <0 || index >= values.length)
if (index <0 || index >= _values.length)
retval = ErrorEval.VALUE_INVALID;
else
retval = values[index];
retval = _values[index];
return retval;
}
public boolean contains(int row, short col) {
public boolean contains(int row, int col) {
return (getFirstRow() <= row) && (getLastRow() >= row)
&& (getFirstColumn() <= col) && (getLastColumn() >= col);
}
@ -82,10 +91,10 @@ public class Area2DEval implements AreaEval {
}
public boolean isColumn() {
return delegate.getFirstColumn() == delegate.getLastColumn();
return _delegate.getFirstColumn() == _delegate.getLastColumn();
}
public boolean isRow() {
return delegate.getFirstRow() == delegate.getLastRow();
return _delegate.getFirstRow() == _delegate.getLastRow();
}
}

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 8, 2005
*
*/
package org.apache.poi.hssf.record.formula.eval;
import org.apache.poi.hssf.record.formula.Area3DPtg;
@ -28,47 +25,59 @@ import org.apache.poi.hssf.record.formula.Ptg;
*
*/
public final class Area3DEval implements AreaEval {
// TODO -refactor with Area3DEval
private final Area3DPtg _delegate;
private Area3DPtg delegate;
private ValueEval[] values;
private final ValueEval[] _values;
public Area3DEval(Ptg ptg, ValueEval[] values) {
this.values = values;
this.delegate = (Area3DPtg) ptg;
if(ptg == null) {
throw new IllegalArgumentException("ptg must not be null");
}
if(values == null) {
throw new IllegalArgumentException("values must not be null");
}
for(int i=values.length-1; i>=0; i--) {
if(values[i] == null) {
throw new IllegalArgumentException("value array elements must not be null");
}
}
// TODO - check size of array vs size of AreaPtg
_values = values;
_delegate = (Area3DPtg) ptg;
}
public short getFirstColumn() {
return delegate.getFirstColumn();
public int getFirstColumn() {
return _delegate.getFirstColumn();
}
public int getFirstRow() {
return delegate.getFirstRow();
return _delegate.getFirstRow();
}
public short getLastColumn() {
return delegate.getLastColumn();
public int getLastColumn() {
return (short) _delegate.getLastColumn();
}
public int getLastRow() {
return delegate.getLastRow();
return _delegate.getLastRow();
}
public ValueEval[] getValues() {
return values;
return _values;
}
public ValueEval getValueAt(int row, short col) {
public ValueEval getValueAt(int row, int col) {
ValueEval retval;
int index = (row-getFirstRow())*(col-getFirstColumn());
if (index <0 || index >= values.length)
if (index <0 || index >= _values.length)
retval = ErrorEval.VALUE_INVALID;
else
retval = values[index];
retval = _values[index];
return retval;
}
public boolean contains(int row, short col) {
public boolean contains(int row, int col) {
return (getFirstRow() <= row) && (getLastRow() >= row)
&& (getFirstColumn() <= col) && (getLastColumn() >= col);
}
@ -83,15 +92,14 @@ public final class Area3DEval implements AreaEval {
public boolean isColumn() {
return delegate.getFirstColumn() == delegate.getLastColumn();
return _delegate.getFirstColumn() == _delegate.getLastColumn();
}
public boolean isRow() {
return delegate.getFirstRow() == delegate.getLastRow();
return _delegate.getFirstRow() == _delegate.getLastRow();
}
public int getExternSheetIndex() {
return delegate.getExternSheetIndex();
return _delegate.getExternSheetIndex();
}
}

View File

@ -42,13 +42,13 @@ public interface AreaEval extends ValueEval {
* returns the 0-based index of the first col in
* this area.
*/
public short getFirstColumn();
public int getFirstColumn();
/**
* returns the 0-based index of the last col in
* this area.
*/
public short getLastColumn();
public int getLastColumn();
/**
* returns true if the Area's start and end row indexes
@ -80,7 +80,7 @@ public interface AreaEval extends ValueEval {
* @param row
* @param col
*/
public ValueEval getValueAt(int row, short col);
public ValueEval getValueAt(int row, int col);
/**
* returns true if the cell at row and col specified
@ -89,7 +89,7 @@ public interface AreaEval extends ValueEval {
* @param row
* @param col
*/
public boolean contains(int row, short col);
public boolean contains(int row, int col);
/**
* returns true if the specified col is in range

View File

@ -29,16 +29,22 @@ public final class Ref2DEval implements RefEval {
private final ReferencePtg delegate;
public Ref2DEval(ReferencePtg ptg, ValueEval ve) {
if(ve == null) {
throw new IllegalArgumentException("ve must not be null");
}
if(false && ptg == null) { // TODO - fix dodgy code in MultiOperandNumericFunction
throw new IllegalArgumentException("ptg must not be null");
}
value = ve;
delegate = ptg;
}
public ValueEval getInnerValueEval() {
return value;
}
public short getRow() {
public int getRow() {
return delegate.getRow();
}
public short getColumn() {
public int getColumn() {
return delegate.getColumn();
}
}

View File

@ -29,16 +29,22 @@ public final class Ref3DEval implements RefEval {
private final Ref3DPtg delegate;
public Ref3DEval(Ref3DPtg ptg, ValueEval ve) {
if(ve == null) {
throw new IllegalArgumentException("ve must not be null");
}
if(ptg == null) {
throw new IllegalArgumentException("ptg must not be null");
}
value = ve;
delegate = ptg;
}
public ValueEval getInnerValueEval() {
return value;
}
public short getRow() {
public int getRow() {
return delegate.getRow();
}
public short getColumn() {
public int getColumn() {
return delegate.getColumn();
}
public int getExternSheetIndex() {

View File

@ -40,12 +40,12 @@ public interface RefEval extends ValueEval {
public ValueEval getInnerValueEval();
/**
* returns the column index.
* returns the zero based column index.
*/
public short getColumn();
public int getColumn();
/**
* returns the row index.
* returns the zero based row index.
*/
public short getRow();
public int getRow();
}

View File

@ -287,8 +287,8 @@ final class LookupUtils {
// It doesn't matter if eval is a 2D or 3D ref, because that detail is never asked of AreaEval.
// This code only requires the value array item.
// anything would be ok for rowIx and colIx, but may as well get it right.
short rowIx = refEval.getRow();
short colIx = refEval.getColumn();
int rowIx = refEval.getRow();
int colIx = refEval.getColumn();
AreaPtg ap = new AreaPtg(rowIx, rowIx, colIx, colIx, false, false, false, false);
ValueEval value = refEval.getInnerValueEval();
return new Area2DEval(ap, new ValueEval[] { value, });

View File

@ -14,10 +14,7 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* Created on May 5, 2005
*
*/
package org.apache.poi.hssf.usermodel;
import java.lang.reflect.Constructor;
@ -420,20 +417,20 @@ public class HSSFFormulaEvaluator {
}
else if (ptg instanceof ReferencePtg) {
ReferencePtg refPtg = (ReferencePtg) ptg;
short colnum = refPtg.getColumn();
short rownum = refPtg.getRow();
HSSFRow row = sheet.getRow(rownum);
HSSFCell cell = (row != null) ? row.getCell(colnum) : null;
int colIx = refPtg.getColumn();
int rowIx = refPtg.getRow();
HSSFRow row = sheet.getRow(rowIx);
HSSFCell cell = (row != null) ? row.getCell(colIx) : null;
stack.push(createRef2DEval(refPtg, cell, row, sheet, workbook));
}
else if (ptg instanceof Ref3DPtg) {
Ref3DPtg refPtg = (Ref3DPtg) ptg;
short colnum = refPtg.getColumn();
short rownum = refPtg.getRow();
int colIx = refPtg.getColumn();
int rowIx = refPtg.getRow();
Workbook wb = workbook.getWorkbook();
HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(refPtg.getExternSheetIndex()));
HSSFRow row = xsheet.getRow(rownum);
HSSFCell cell = (row != null) ? row.getCell(colnum) : null;
HSSFRow row = xsheet.getRow(rowIx);
HSSFCell cell = (row != null) ? row.getCell(colIx) : null;
stack.push(createRef3DEval(refPtg, cell, row, xsheet, workbook));
}
else if (ptg instanceof AreaPtg) {
@ -506,10 +503,10 @@ public class HSSFFormulaEvaluator {
}
public static AreaEval evaluateAreaPtg(HSSFSheet sheet, HSSFWorkbook workbook, AreaPtg ap) {
short row0 = ap.getFirstRow();
short col0 = ap.getFirstColumn();
short row1 = ap.getLastRow();
short col1 = ap.getLastColumn();
int row0 = ap.getFirstRow();
int col0 = ap.getFirstColumn();
int row1 = ap.getLastRow();
int col1 = ap.getLastColumn();
// If the last row is -1, then the
// reference is for the rest of the column
@ -518,24 +515,15 @@ public class HSSFFormulaEvaluator {
if(row1 == -1 && row0 >= 0) {
row1 = (short)sheet.getLastRowNum();
}
ValueEval[] values = new ValueEval[(row1 - row0 + 1) * (col1 - col0 + 1)];
for (short x = row0; sheet != null && x < row1 + 1; x++) {
HSSFRow row = sheet.getRow(x);
for (short y = col0; row != null && y < col1 + 1; y++) {
values[(x - row0) * (col1 - col0 + 1) + (y - col0)] =
getEvalForCell(row.getCell(y), row, sheet, workbook);
}
}
AreaEval ae = new Area2DEval(ap, values);
return ae;
ValueEval[] values = evalArea(workbook, sheet, row0, col0, row1, col1);
return new Area2DEval(ap, values);
}
public static AreaEval evaluateArea3dPtg(HSSFWorkbook workbook, Area3DPtg a3dp) {
short row0 = a3dp.getFirstRow();
short col0 = a3dp.getFirstColumn();
short row1 = a3dp.getLastRow();
short col1 = a3dp.getLastColumn();
int row0 = a3dp.getFirstRow();
int col0 = a3dp.getFirstColumn();
int row1 = a3dp.getLastRow();
int col1 = a3dp.getLastColumn();
Workbook wb = workbook.getWorkbook();
HSSFSheet xsheet = workbook.getSheetAt(wb.getSheetIndexFromExternSheetIndex(a3dp.getExternSheetIndex()));
@ -547,19 +535,28 @@ public class HSSFFormulaEvaluator {
row1 = (short)xsheet.getLastRowNum();
}
ValueEval[] values = evalArea(workbook, xsheet, row0, col0, row1, col1);
return new Area3DEval(a3dp, values);
}
private static ValueEval[] evalArea(HSSFWorkbook workbook, HSSFSheet sheet,
int row0, int col0, int row1, int col1) {
ValueEval[] values = new ValueEval[(row1 - row0 + 1) * (col1 - col0 + 1)];
for (short x = row0; xsheet != null && x < row1 + 1; x++) {
HSSFRow row = xsheet.getRow(x);
for (short y = col0; row != null && y < col1 + 1; y++) {
values[(x - row0) * (col1 - col0 + 1) + (y - col0)] =
getEvalForCell(row.getCell(y), row, xsheet, workbook);
for (int x = row0; sheet != null && x < row1 + 1; x++) {
HSSFRow row = sheet.getRow(x);
for (int y = col0; y < col1 + 1; y++) {
ValueEval cellEval;
if(row == null) {
cellEval = BlankEval.INSTANCE;
} else {
cellEval = getEvalForCell(row.getCell(y), row, sheet, workbook);
}
values[(x - row0) * (col1 - col0 + 1) + (y - col0)] = cellEval;
}
}
AreaEval ae = new Area3DEval(a3dp, values);
return ae;
return values;
}
/**
* returns the OperationEval concrete impl instance corresponding
* to the suplied operationPtg

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -15,30 +14,30 @@
See the License for the specific language governing permissions and
limitations under the License.
==================================================================== */
package org.apache.poi.hssf.model;
import junit.framework.TestCase;
import org.apache.poi.hssf.model.FormulaParser.FormulaParseException;
import org.apache.poi.hssf.record.formula.FuncVarPtg;
import org.apache.poi.hssf.record.formula.NamePtg;
import org.apache.poi.hssf.record.formula.Ptg;
import org.apache.poi.hssf.usermodel.HSSFCell;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator;
import org.apache.poi.hssf.usermodel.HSSFName;
import org.apache.poi.hssf.usermodel.HSSFRow;
import org.apache.poi.hssf.usermodel.HSSFSheet;
import org.apache.poi.hssf.usermodel.HSSFWorkbook;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
/**
* Test the low level formula parser functionality,
* but using parts which need to use the
* HSSFFormulaEvaluator, which is in scratchpad
*/
public class TestFormulaParserSP extends TestCase {
public final class TestFormulaParserSP extends TestCase {
public TestFormulaParserSP(String name) {
super(name);
}
public void testWithNamedRange() throws Exception {
HSSFWorkbook workbook = new HSSFWorkbook();
FormulaParser fp;
@ -80,4 +79,32 @@ public class TestFormulaParserSP extends TestCase {
assertEquals(FuncVarPtg.class, ptgs[1].getClass());
}
public void testEvaluateFormulaWithRowBeyond32768_Bug44539() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0, "Sheet1");
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short)0);
cell.setCellFormula("SUM(A32769:A32770)");
// put some values in the cells to make the evaluation more interesting
sheet.createRow(32768).createCell((short)0).setCellValue(31);
sheet.createRow(32769).createCell((short)0).setCellValue(11);
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(sheet, wb);
fe.setCurrentRow(row);
CellValue result;
try {
result = fe.evaluate(cell);
} catch (FormulaParseException e) {
if(e.getMessage().equals("Found reference to named range \"A\", but that named range wasn't defined!")) {
fail("Identifed bug 44539");
}
throw new RuntimeException(e);
}
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, result.getCellType());
assertEquals(42.0, result.getNumberValue(), 0.0);
}
}

View File

@ -63,12 +63,13 @@ public class TestBug44410 extends TestCase {
assertEquals(AreaPtg.class, ops.get(0).getClass());
assertEquals(FuncVarPtg.class, ops.get(1).getClass());
// Actually stored as C1 to C0 (last row is -1)
// Actually stored as C1 to C65536
// (last row is -1 === 65535)
AreaPtg ptg = (AreaPtg)ops.get(0);
assertEquals(2, ptg.getFirstColumn());
assertEquals(2, ptg.getLastColumn());
assertEquals(0, ptg.getFirstRow());
assertEquals(-1, ptg.getLastRow());
assertEquals(65535, ptg.getLastRow());
assertEquals("C:C", ptg.toFormulaString(wb.getWorkbook()));
// Will show as C:C, but won't know how many

View File

@ -1,4 +1,3 @@
/* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with
@ -21,6 +20,7 @@ package org.apache.poi.hssf.model;
import junit.framework.AssertionFailedError;
import junit.framework.TestCase;
import org.apache.poi.hssf.model.FormulaParser.FormulaParseException;
import org.apache.poi.hssf.record.formula.AbstractFunctionPtg;
import org.apache.poi.hssf.record.formula.AddPtg;
import org.apache.poi.hssf.record.formula.AreaPtg;
@ -59,18 +59,8 @@ import org.apache.poi.hssf.usermodel.HSSFWorkbook;
* Some tests are also done in scratchpad, if they need
* HSSFFormulaEvaluator, which is there
*/
public class TestFormulaParser extends TestCase {
public final class TestFormulaParser extends TestCase {
public TestFormulaParser(String name) {
super(name);
}
public void setUp(){
}
public void tearDown() {
}
/**
* @return parsed token array already confirmed not <code>null</code>
*/
@ -831,10 +821,27 @@ public class TestFormulaParser extends TestCase {
try {
parseFormula(formula);
throw new AssertionFailedError("expected parse exception");
} catch (RuntimeException e) {
// TODO - catch more specific exception
} catch (FormulaParseException e) {
// expected during successful test
return;
assertNotNull(e.getMessage());
} catch (RuntimeException e) {
e.printStackTrace();
fail("Wrong exception:" + e.getMessage());
}
}
public void testSetFormulaWithRowBeyond32768_Bug44539() {
HSSFWorkbook wb = new HSSFWorkbook();
HSSFSheet sheet = wb.createSheet();
wb.setSheetName(0, "Sheet1");
HSSFRow row = sheet.createRow(0);
HSSFCell cell = row.createCell((short)0);
cell.setCellFormula("SUM(A32769:A32770)");
if("SUM(A-32767:A-32766)".equals(cell.getCellFormula())) {
fail("Identified bug 44539");
}
assertEquals("SUM(A32769:A32770)", cell.getCellFormula());
}
}

View File

@ -27,15 +27,12 @@ import org.apache.poi.hssf.model.FormulaParser;
*
* @author Dmitriy Kumshayev
*/
public class TestAreaPtg extends TestCase
{
public final class TestAreaPtg extends TestCase {
AreaPtg relative;
AreaPtg absolute;
protected void setUp() throws Exception
{
super.setUp();
protected void setUp() {
short firstRow=5;
short lastRow=13;
short firstCol=7;
@ -64,10 +61,9 @@ public class TestAreaPtg extends TestCase
}
public void resetColumns(AreaPtg aptg)
{
short fc = aptg.getFirstColumn();
short lc = aptg.getLastColumn();
private static void resetColumns(AreaPtg aptg) {
int fc = aptg.getFirstColumn();
int lc = aptg.getLastColumn();
aptg.setFirstColumn(fc);
aptg.setLastColumn(lc);
assertEquals(fc , aptg.getFirstColumn() );