Fix from Josh from bug #44417 - Improved handling of references for the need to quote the sheet name for some formulas, but not when fetching a sheet by name

git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@628033 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Nick Burch 2008-02-15 12:04:42 +00:00
parent 8827c07cdb
commit e113d12d34
18 changed files with 554 additions and 355 deletions

View File

@ -36,6 +36,7 @@
<!-- Don't forget to update status.xml too! --> <!-- Don't forget to update status.xml too! -->
<release version="3.1-beta1" date="2008-??-??"> <release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">44417 - Improved handling of references for the need to quote the sheet name for some formulas, but not when fetching a sheet by name</action>
<action dev="POI-DEVELOPERS" type="fix">44413 - Fix for circular references in INDEX, OFFSET, VLOOKUP formulas, where a cell is actually allowed to reference itself</action> <action dev="POI-DEVELOPERS" type="fix">44413 - Fix for circular references in INDEX, OFFSET, VLOOKUP formulas, where a cell is actually allowed to reference itself</action>
<action dev="POI-DEVELOPERS" type="fix">44403 - Fix for Mid function handling its arguments wrong</action> <action dev="POI-DEVELOPERS" type="fix">44403 - Fix for Mid function handling its arguments wrong</action>
<action dev="POI-DEVELOPERS" type="add">44364 - Support for Match, NA and SumProduct functions, as well as initial function error support</action> <action dev="POI-DEVELOPERS" type="add">44364 - Support for Match, NA and SumProduct functions, as well as initial function error support</action>

View File

@ -33,6 +33,7 @@
<!-- Don't forget to update changes.xml too! --> <!-- Don't forget to update changes.xml too! -->
<changes> <changes>
<release version="3.1-beta1" date="2008-??-??"> <release version="3.1-beta1" date="2008-??-??">
<action dev="POI-DEVELOPERS" type="fix">44417 - Improved handling of references for the need to quote the sheet name for some formulas, but not when fetching a sheet by name</action>
<action dev="POI-DEVELOPERS" type="fix">44413 - Fix for circular references in INDEX, OFFSET, VLOOKUP formulas, where a cell is actually allowed to reference itself</action> <action dev="POI-DEVELOPERS" type="fix">44413 - Fix for circular references in INDEX, OFFSET, VLOOKUP formulas, where a cell is actually allowed to reference itself</action>
<action dev="POI-DEVELOPERS" type="fix">44403 - Fix for Mid function handling its arguments wrong</action> <action dev="POI-DEVELOPERS" type="fix">44403 - Fix for Mid function handling its arguments wrong</action>
<action dev="POI-DEVELOPERS" type="add">44364 - Support for Match, NA and SumProduct functions, as well as initial function error support</action> <action dev="POI-DEVELOPERS" type="add">44364 - Support for Match, NA and SumProduct functions, as well as initial function error support</action>

View File

@ -726,7 +726,7 @@ public class NameRecord extends Record {
for(int i=0; i<refs.length; i++) { for(int i=0; i<refs.length; i++) {
ptg = new Area3DPtg(); ptg = new Area3DPtg();
((Area3DPtg) ptg).setExternSheetIndex(externSheetIndex); ((Area3DPtg) ptg).setExternSheetIndex(externSheetIndex);
((Area3DPtg) ptg).setArea(refs[i].toString()); ((Area3DPtg) ptg).setArea(refs[i].formatAsString());
field_13_name_definition.push(ptg); field_13_name_definition.push(ptg);
this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) ); this.setDefinitionTextLength( (short)(getDefinitionLength() + ptg.getSize()) );
} }

View File

@ -243,21 +243,17 @@ public class Area3DPtg extends Ptg
public void setArea( String ref ) public void setArea( String ref )
{ {
AreaReference ar = new AreaReference( ref ); AreaReference ar = new AreaReference( ref );
CellReference[] crs = ar.getCells();
CellReference firstCell = crs[0]; CellReference frstCell = ar.getFirstCell();
CellReference lastCell = firstCell; CellReference lastCell = ar.getLastCell();
if(crs.length > 1) {
lastCell = crs[1];
}
setFirstRow( (short) firstCell.getRow() ); setFirstRow( (short) frstCell.getRow() );
setFirstColumn( (short) firstCell.getCol() ); setFirstColumn( frstCell.getCol() );
setLastRow( (short) lastCell.getRow() ); setLastRow( (short) lastCell.getRow() );
setLastColumn( (short) lastCell.getCol() ); setLastColumn( lastCell.getCol() );
setFirstColRelative( !firstCell.isColAbsolute() ); setFirstColRelative( !frstCell.isColAbsolute() );
setLastColRelative( !lastCell.isColAbsolute() ); setLastColRelative( !lastCell.isColAbsolute() );
setFirstRowRelative( !firstCell.isRowAbsolute() ); setFirstRowRelative( !frstCell.isRowAbsolute() );
setLastRowRelative( !lastCell.isRowAbsolute() ); setLastRowRelative( !lastCell.isRowAbsolute() );
} }
@ -273,9 +269,9 @@ public class Area3DPtg extends Ptg
SheetNameFormatter.appendFormat(retval, sheetName); SheetNameFormatter.appendFormat(retval, sheetName);
retval.append( '!' ); retval.append( '!' );
} }
retval.append( ( new CellReference( getFirstRow(), getFirstColumn(), !isFirstRowRelative(), !isFirstColRelative() ) ).toString() ); retval.append( ( new CellReference( getFirstRow(), getFirstColumn(), !isFirstRowRelative(), !isFirstColRelative() ) ).formatAsString() );
retval.append( ':' ); retval.append( ':' );
retval.append( ( new CellReference( getLastRow(), getLastColumn(), !isLastRowRelative(), !isLastColRelative() ) ).toString() ); retval.append( ( new CellReference( getLastRow(), getLastColumn(), !isLastRowRelative(), !isLastColRelative() ) ).formatAsString() );
return retval.toString(); return retval.toString();
} }

View File

@ -53,14 +53,16 @@ public class AreaPtg
public AreaPtg(String arearef) { public AreaPtg(String arearef) {
AreaReference ar = new AreaReference(arearef); AreaReference ar = new AreaReference(arearef);
setFirstRow((short)ar.getCells()[0].getRow()); CellReference firstCell = ar.getFirstCell();
setFirstColumn((short)ar.getCells()[0].getCol()); CellReference lastCell = ar.getLastCell();
setLastRow((short)ar.getCells()[1].getRow()); setFirstRow((short)firstCell.getRow());
setLastColumn((short)ar.getCells()[1].getCol()); setFirstColumn(firstCell.getCol());
setFirstColRelative(!ar.getCells()[0].isColAbsolute()); setLastRow((short)lastCell.getRow());
setLastColRelative(!ar.getCells()[1].isColAbsolute()); setLastColumn(lastCell.getCol());
setFirstRowRelative(!ar.getCells()[0].isRowAbsolute()); setFirstColRelative(!firstCell.isColAbsolute());
setLastRowRelative(!ar.getCells()[1].isRowAbsolute()); setLastColRelative(!lastCell.isColAbsolute());
setFirstRowRelative(!firstCell.isRowAbsolute());
setLastRowRelative(!lastCell.isRowAbsolute());
} }
public AreaPtg(short firstRow, short lastRow, short firstColumn, short lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) { public AreaPtg(short firstRow, short lastRow, short firstColumn, short lastColumn, boolean firstRowRelative, boolean lastRowRelative, boolean firstColRelative, boolean lastColRelative) {
@ -282,8 +284,8 @@ public class AreaPtg
public String toFormulaString(Workbook book) public String toFormulaString(Workbook book)
{ {
return (new CellReference(getFirstRow(),getFirstColumn(),!isFirstRowRelative(),!isFirstColRelative())).toString() + ":" + return (new CellReference(getFirstRow(),getFirstColumn(),!isFirstRowRelative(),!isFirstColRelative())).formatAsString() + ":" +
(new CellReference(getLastRow(),getLastColumn(),!isLastRowRelative(),!isLastColRelative())).toString(); (new CellReference(getLastRow(),getLastColumn(),!isLastRowRelative(),!isLastColRelative())).formatAsString();
} }
public byte getDefaultOperandClass() { public byte getDefaultOperandClass() {

View File

@ -183,7 +183,7 @@ public class Ref3DPtg extends Ptg {
SheetNameFormatter.appendFormat(retval, sheetName); SheetNameFormatter.appendFormat(retval, sheetName);
retval.append( '!' ); retval.append( '!' );
} }
retval.append((new CellReference(getRow(),getColumn(),!isRowRelative(),!isColRelative())).toString()); retval.append((new CellReference(getRow(),getColumn(),!isRowRelative(),!isColRelative())).formatAsString());
return retval.toString(); return retval.toString();
} }

View File

@ -191,7 +191,7 @@ public class ReferencePtg extends Ptg
public String toFormulaString(Workbook book) public String toFormulaString(Workbook book)
{ {
//TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe! //TODO -- should we store a cellreference instance in this ptg?? but .. memory is an issue, i believe!
return (new CellReference(getRowAsInt(),getColumn(),!isRowRelative(),!isColRelative())).toString(); return (new CellReference(getRowAsInt(),getColumn(),!isRowRelative(),!isColRelative())).formatAsString();
} }
public byte getDefaultOperandClass() { public byte getDefaultOperandClass() {

View File

@ -26,7 +26,7 @@ import java.util.regex.Pattern;
* *
* @author Josh Micich * @author Josh Micich
*/ */
final class SheetNameFormatter { public final class SheetNameFormatter {
private static final String BIFF8_LAST_COLUMN = "IV"; private static final String BIFF8_LAST_COLUMN = "IV";
private static final int BIFF8_LAST_COLUMN_TEXT_LEN = BIFF8_LAST_COLUMN.length(); private static final int BIFF8_LAST_COLUMN_TEXT_LEN = BIFF8_LAST_COLUMN.length();

View File

@ -1119,12 +1119,12 @@ public class HSSFWorkbook extends POIDocument
public void setPrintArea(int sheetIndex, int startColumn, int endColumn, public void setPrintArea(int sheetIndex, int startColumn, int endColumn,
int startRow, int endRow) { int startRow, int endRow) {
//using absolute references because they dont get copied and pasted anyway //using absolute references because they don't get copied and pasted anyway
CellReference cell = new CellReference(startRow, startColumn, true, true); CellReference cell = new CellReference(startRow, startColumn, true, true);
String reference = cell.toString(); String reference = cell.formatAsString();
cell = new CellReference(endRow, endColumn, true, true); cell = new CellReference(endRow, endColumn, true, true);
reference = reference+":"+cell.toString(); reference = reference+":"+cell.formatAsString();
setPrintArea(sheetIndex, reference); setPrintArea(sheetIndex, reference);
} }

View File

@ -21,26 +21,40 @@ package org.apache.poi.hssf.util;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.StringTokenizer; import java.util.StringTokenizer;
public class AreaReference { public final class AreaReference {
/** The character (!) that separates sheet names from cell references */
private CellReference [] cells; private static final char SHEET_NAME_DELIMITER = '!';
private int dim; /** The character (:) that separates the two cell references in a multi-cell area reference */
private static final char CELL_DELIMITER = ':';
/** The character (') used to quote sheet names when they contain special characters */
private static final char SPECIAL_NAME_DELIMITER = '\'';
private final CellReference _firstCell;
private final CellReference _lastCell;
private final boolean _isSingleCell;
/** /**
* Create an area ref from a string representation. * Create an area ref from a string representation. Sheet names containing special characters should be
* The area reference must be contiguous * delimited and escaped as per normal syntax rules for formulas.<br/>
* The area reference must be contiguous (i.e. represent a single rectangle, not a union of rectangles)
*/ */
public AreaReference(String reference) { public AreaReference(String reference) {
if(! isContiguous(reference)) { if(! isContiguous(reference)) {
throw new IllegalArgumentException("References passed to the AreaReference must be contiguous, use generateContiguous(ref) if you have non-contiguous references"); throw new IllegalArgumentException(
"References passed to the AreaReference must be contiguous, " +
"use generateContiguous(ref) if you have non-contiguous references");
} }
String[] refs = seperateAreaRefs(reference); String[] parts = separateAreaRefs(reference);
dim = refs.length; _firstCell = new CellReference(parts[0]);
cells = new CellReference[dim];
for (int i=0;i<dim;i++) { if(parts.length == 2) {
cells[i]=new CellReference(refs[i]); _lastCell = new CellReference(parts[1]);
_isSingleCell = false;
} else {
_lastCell = _firstCell;
_isSingleCell = true;
} }
} }
@ -73,75 +87,163 @@ private int dim;
return (AreaReference[])refs.toArray(new AreaReference[refs.size()]); return (AreaReference[])refs.toArray(new AreaReference[refs.size()]);
} }
//not sure if we need to be flexible here! /**
/** return the dimensions of this area * @return <code>false</code> if this area reference involves more than one cell
**/
public int getDim() {
return dim;
}
/**
* Return the cell references that define this area
* (i.e. the two corners)
*/ */
public CellReference[] getCells() { public boolean isSingleCell() {
return cells; return _isSingleCell;
}
/**
* @return the first cell reference which defines this area. Usually this cell is in the upper
* left corner of the area (but this is not a requirement).
*/
public CellReference getFirstCell() {
return _firstCell;
}
/**
* Note - if this area reference refers to a single cell, the return value of this method will
* be identical to that of <tt>getFirstCell()</tt>
* @return the second cell reference which defines this area. For multi-cell areas, this is
* cell diagonally opposite the 'first cell'. Usually this cell is in the lower right corner
* of the area (but this is not a requirement).
*/
public CellReference getLastCell() {
return _lastCell;
} }
/** /**
* Returns a reference to every cell covered by this area * Returns a reference to every cell covered by this area
*/ */
public CellReference[] getAllReferencedCells() { public CellReference[] getAllReferencedCells() {
// Special case for single cell reference // Special case for single cell reference
if(cells.length == 1) { if(_isSingleCell) {
return cells; return new CellReference[] { _firstCell, };
} }
// Interpolate between the two // Interpolate between the two
int minRow = Math.min(cells[0].getRow(), cells[1].getRow()); int minRow = Math.min(_firstCell.getRow(), _lastCell.getRow());
int maxRow = Math.max(cells[0].getRow(), cells[1].getRow()); int maxRow = Math.max(_firstCell.getRow(), _lastCell.getRow());
int minCol = Math.min(cells[0].getCol(), cells[1].getCol()); int minCol = Math.min(_firstCell.getCol(), _lastCell.getCol());
int maxCol = Math.max(cells[0].getCol(), cells[1].getCol()); int maxCol = Math.max(_firstCell.getCol(), _lastCell.getCol());
String sheetName = _firstCell.getSheetName();
ArrayList refs = new ArrayList(); ArrayList refs = new ArrayList();
for(int row=minRow; row<=maxRow; row++) { for(int row=minRow; row<=maxRow; row++) {
for(int col=minCol; col<=maxCol; col++) { for(int col=minCol; col<=maxCol; col++) {
CellReference ref = new CellReference(row, col, cells[0].isRowAbsolute(), cells[0].isColAbsolute()); CellReference ref = new CellReference(sheetName, row, col, _firstCell.isRowAbsolute(), _firstCell.isColAbsolute());
ref.setSheetName(cells[0].getSheetName());
refs.add(ref); refs.add(ref);
} }
} }
return (CellReference[])refs.toArray(new CellReference[refs.size()]); return (CellReference[])refs.toArray(new CellReference[refs.size()]);
} }
public String toString() { /**
StringBuffer retval = new StringBuffer(); * Example return values:
for (int i=0;i<dim;i++){ * <table border="0" cellpadding="1" cellspacing="0" summary="Example return values">
retval.append(':'); * <tr><th align='left'>Result</th><th align='left'>Comment</th></tr>
retval.append(cells[i].toString()); * <tr><td>A1:A1</td><td>Single cell area reference without sheet</td></tr>
* <tr><td>A1:$C$1</td><td>Multi-cell area reference without sheet</td></tr>
* <tr><td>Sheet1!A$1:B4</td><td>Standard sheet name</td></tr>
* <tr><td>'O''Brien''s Sales'!B5:C6'&nbsp;</td><td>Sheet name with special characters</td></tr>
* </table>
* @return the text representation of this area reference as it would appear in a formula.
*/
public String formatAsString() {
StringBuffer sb = new StringBuffer(32);
sb.append(_firstCell.formatAsString());
if(!_isSingleCell) {
sb.append(CELL_DELIMITER);
if(_lastCell.getSheetName() == null) {
sb.append(_lastCell.formatAsString());
} else {
// don't want to include the sheet name twice
_lastCell.appendCellReference(sb);
}
} }
retval.deleteCharAt(0); return sb.toString();
return retval.toString(); }
public String toString() {
StringBuffer sb = new StringBuffer(64);
sb.append(getClass().getName()).append(" [");
sb.append(formatAsString());
sb.append("]");
return sb.toString();
} }
/** /**
* seperates Area refs in two parts and returns them as seperate elements in a * Separates Area refs in two parts and returns them as separate elements in a String array,
* String array * each qualified with the sheet name (if present)
*
* @return array with one or two elements. never <code>null</code>
*/ */
private String[] seperateAreaRefs(String reference) { private static String[] separateAreaRefs(String reference) {
String[] retval = null; // TODO - refactor cell reference parsing logic to one place.
// Current known incarnations:
int length = reference.length(); // FormulaParser.GetName()
// CellReference.separateRefParts()
int loc = reference.indexOf(':',0); // AreaReference.separateAreaRefs() (here)
if(loc == -1){ // SheetNameFormatter.format() (inverse)
retval = new String[1];
retval[0] = reference;
int len = reference.length();
int delimiterPos = -1;
boolean insideDelimitedName = false;
for(int i=0; i<len; i++) {
switch(reference.charAt(i)) {
case CELL_DELIMITER:
if(!insideDelimitedName) {
if(delimiterPos >=0) {
throw new IllegalArgumentException("More than one cell delimiter '"
+ CELL_DELIMITER + "' appears in area reference '" + reference + "'");
}
delimiterPos = i;
}
default:
continue;
case SPECIAL_NAME_DELIMITER:
// fall through
}
if(!insideDelimitedName) {
insideDelimitedName = true;
continue;
}
if(i >= len-1) {
// reference ends with the delimited name.
// Assume names like: "Sheet1!'A1'" are never legal.
throw new IllegalArgumentException("Area reference '" + reference
+ "' ends with special name delimiter '" + SPECIAL_NAME_DELIMITER + "'");
}
if(reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
// two consecutive quotes is the escape sequence for a single one
i++; // skip this and keep parsing the special name
} else {
// this is the end of the delimited name
insideDelimitedName = false;
}
} }
else{ if(delimiterPos < 0) {
retval = new String[2]; return new String[] { reference, };
int sheetStart = reference.indexOf("!");
retval[0] = reference.substring(0, sheetStart+1) + reference.substring(sheetStart + 1,loc);
retval[1] = reference.substring(0, sheetStart+1) + reference.substring(loc+1);
} }
return retval;
String partA = reference.substring(0, delimiterPos);
String partB = reference.substring(delimiterPos+1);
if(partB.indexOf(SHEET_NAME_DELIMITER) >=0) {
// TODO - are references like "Sheet1!A1:Sheet1:B2" ever valid?
// FormulaParser has code to handle that.
throw new RuntimeException("Unexpected " + SHEET_NAME_DELIMITER
+ " in second cell reference of '" + reference + "'");
}
int plingPos = partA.lastIndexOf(SHEET_NAME_DELIMITER);
if(plingPos < 0) {
return new String [] { partA, partB, };
}
String sheetName = partA.substring(0, plingPos + 1); // +1 to include delimiter
return new String [] { partA, sheetName + partB, };
} }
} }

View File

@ -15,75 +15,91 @@
limitations under the License. limitations under the License.
==================================================================== */ ==================================================================== */
package org.apache.poi.hssf.util; package org.apache.poi.hssf.util;
import org.apache.poi.hssf.record.formula.SheetNameFormatter;
/** /**
* *
* @author Avik Sengupta * @author Avik Sengupta
* @author Dennis Doubleday (patch to seperateRowColumns()) * @author Dennis Doubleday (patch to seperateRowColumns())
*/ */
public class CellReference { public final class CellReference {
/** The character ($) that signifies a row or column value is absolute instead of relative */
private static final char ABSOLUTE_REFERENCE_MARKER = '$';
/** The character (!) that separates sheet names from cell references */
private static final char SHEET_NAME_DELIMITER = '!';
/** The character (') used to quote sheet names when they contain special characters */
private static final char SPECIAL_NAME_DELIMITER = '\'';
/** Creates new CellReference */ private final int _rowIndex;
private int row; private final int _colIndex;
private int col; private final String _sheetName;
private String sheetName; private final boolean _isRowAbs;
private boolean rowAbs; private final boolean _isColAbs;
private boolean colAbs;
/**
* Create an cell ref from a string representation. Sheet names containing special characters should be
* delimited and escaped as per normal syntax rules for formulas.
*/
public CellReference(String cellRef) { public CellReference(String cellRef) {
String[] parts = separateRefParts(cellRef); String[] parts = separateRefParts(cellRef);
sheetName = parts[0]; _sheetName = parts[0];
String ref = parts[1]; String colRef = parts[1];
if ((ref == null)||("".equals(ref))) if (colRef.length() < 1) {
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'"); throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
if (ref.charAt(0) == '$') {
colAbs=true;
ref=ref.substring(1);
} }
col = convertColStringToNum(ref); _isColAbs = colRef.charAt(0) == '$';
ref=parts[2]; if (_isColAbs) {
if ((ref == null)||("".equals(ref))) colRef=colRef.substring(1);
throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
if (ref.charAt(0) == '$') {
rowAbs=true;
ref=ref.substring(1);
} }
row = Integer.parseInt(ref)-1; _colIndex = convertColStringToNum(colRef);
}
String rowRef=parts[2];
public CellReference(int pRow, int pCol) { if (rowRef.length() < 1) {
this(pRow,pCol,false,false); throw new IllegalArgumentException("Invalid Formula cell reference: '"+cellRef+"'");
}
_isRowAbs = rowRef.charAt(0) == '$';
if (_isRowAbs) {
rowRef=rowRef.substring(1);
}
_rowIndex = Integer.parseInt(rowRef)-1; // -1 to convert 1-based to zero-based
} }
public CellReference(int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) { public CellReference(int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
row=pRow;col=pCol; this(null, pRow, pCol, pAbsRow, pAbsCol);
rowAbs = pAbsRow; }
colAbs=pAbsCol; public CellReference(String pSheetName, int pRow, int pCol, boolean pAbsRow, boolean pAbsCol) {
_sheetName = pSheetName;
_rowIndex=pRow;
_colIndex=pCol;
_isRowAbs = pAbsRow;
_isColAbs=pAbsCol;
} }
public int getRow(){return row;} public int getRow(){return _rowIndex;}
public short getCol(){return (short) col;} public short getCol(){return (short) _colIndex;}
public boolean isRowAbsolute(){return rowAbs;} public boolean isRowAbsolute(){return _isRowAbs;}
public boolean isColAbsolute(){return colAbs;} public boolean isColAbsolute(){return _isColAbs;}
public String getSheetName(){return sheetName;} /**
* @return possibly <code>null</code> if this is a 2D reference. Special characters are not
* escaped or delimited
*/
public String getSheetName(){
return _sheetName;
}
protected void setSheetName(String sheetName) {
this.sheetName = sheetName;
}
/** /**
* takes in a column reference portion of a CellRef and converts it from * takes in a column reference portion of a CellRef and converts it from
* ALPHA-26 number format to 0-based base 10. * ALPHA-26 number format to 0-based base 10.
*/ */
private int convertColStringToNum(String ref) { private int convertColStringToNum(String ref) {
int len = ref.length(); int lastIx = ref.length()-1;
int retval=0; int retval=0;
int pos = 0; int pos = 0;
for (int k = ref.length()-1; k > -1; k--) { for (int k = lastIx; k > -1; k--) {
char thechar = ref.charAt(k); char thechar = ref.charAt(k);
if ( pos == 0) { if ( pos == 0) {
retval += (Character.getNumericValue(thechar)-9); retval += (Character.getNumericValue(thechar)-9);
@ -97,36 +113,78 @@ public class CellReference {
/** /**
* Seperates the row from the columns and returns an array. Element in * Separates the row from the columns and returns an array of three Strings. The first element
* position one is the substring containing the columns still in ALPHA-26 * is the sheet name. Only the first element may be null. The second element in is the column
* number format. * name still in ALPHA-26 number format. The third element is the row.
*/ */
private String[] separateRefParts(String reference) { private static String[] separateRefParts(String reference) {
// Look for end of sheet name. This will either set int plingPos = reference.lastIndexOf(SHEET_NAME_DELIMITER);
// start to 0 (if no sheet name present) or the String sheetName = parseSheetName(reference, plingPos);
// index after the sheet reference ends. int start = plingPos+1;
String retval[] = new String[3];
int start = reference.indexOf("!");
if (start != -1) retval[0] = reference.substring(0, start);
start += 1;
int length = reference.length(); int length = reference.length();
char[] chars = reference.toCharArray();
int loc = start; int loc = start;
if (chars[loc]=='$') loc++; // skip initial dollars
for (; loc < chars.length; loc++) { if (reference.charAt(loc)==ABSOLUTE_REFERENCE_MARKER) {
if (Character.isDigit(chars[loc]) || chars[loc] == '$') { loc++;
}
// step over column name chars until first digit (or dollars) for row number.
for (; loc < length; loc++) {
char ch = reference.charAt(loc);
if (Character.isDigit(ch) || ch == ABSOLUTE_REFERENCE_MARKER) {
break; break;
} }
} }
return new String[] {
sheetName,
reference.substring(start,loc),
reference.substring(loc),
};
}
retval[1] = reference.substring(start,loc); private static String parseSheetName(String reference, int indexOfSheetNameDelimiter) {
retval[2] = reference.substring(loc); if(indexOfSheetNameDelimiter < 0) {
return retval; return null;
}
boolean isQuoted = reference.charAt(0) == SPECIAL_NAME_DELIMITER;
if(!isQuoted) {
return reference.substring(0, indexOfSheetNameDelimiter);
}
int lastQuotePos = indexOfSheetNameDelimiter-1;
if(reference.charAt(lastQuotePos) != SPECIAL_NAME_DELIMITER) {
throw new RuntimeException("Mismatched quotes: (" + reference + ")");
}
// TODO - refactor cell reference parsing logic to one place.
// Current known incarnations:
// FormulaParser.GetName()
// CellReference.parseSheetName() (here)
// AreaReference.separateAreaRefs()
// SheetNameFormatter.format() (inverse)
StringBuffer sb = new StringBuffer(indexOfSheetNameDelimiter);
for(int i=1; i<lastQuotePos; i++) { // Note boundaries - skip outer quotes
char ch = reference.charAt(i);
if(ch != SPECIAL_NAME_DELIMITER) {
sb.append(ch);
continue;
}
if(i < lastQuotePos) {
if(reference.charAt(i+1) == SPECIAL_NAME_DELIMITER) {
// two consecutive quotes is the escape sequence for a single one
i++; // skip this and keep parsing the special name
sb.append(ch);
continue;
}
}
throw new RuntimeException("Bad sheet name quote escaping: (" + reference + ")");
}
return sb.toString();
} }
/** /**
@ -148,14 +206,46 @@ public class CellReference {
return retval; return retval;
} }
/**
* Example return values:
* <table border="0" cellpadding="1" cellspacing="0" summary="Example return values">
* <tr><th align='left'>Result</th><th align='left'>Comment</th></tr>
* <tr><td>A1</td><td>Cell reference without sheet</td></tr>
* <tr><td>Sheet1!A1</td><td>Standard sheet name</td></tr>
* <tr><td>'O''Brien''s Sales'!A1'&nbsp;</td><td>Sheet name with special characters</td></tr>
* </table>
* @return the text representation of this cell reference as it would appear in a formula.
*/
public String formatAsString() {
StringBuffer sb = new StringBuffer(32);
if(_sheetName != null) {
SheetNameFormatter.appendFormat(sb, _sheetName);
sb.append(SHEET_NAME_DELIMITER);
}
appendCellReference(sb);
return sb.toString();
}
public String toString() { public String toString() {
StringBuffer retval = new StringBuffer(); StringBuffer sb = new StringBuffer(64);
retval.append( (colAbs)?"$":""); sb.append(getClass().getName()).append(" [");
retval.append( convertNumToColString(col)); sb.append(formatAsString());
retval.append((rowAbs)?"$":""); sb.append("]");
retval.append(row+1); return sb.toString();
}
return retval.toString(); /**
* Appends cell reference with '$' markers for absolute values as required.
* Sheet name is not included.
*/
/* package */ void appendCellReference(StringBuffer sb) {
if(_isColAbs) {
sb.append(ABSOLUTE_REFERENCE_MARKER);
}
sb.append( convertNumToColString(_colIndex));
if(_isRowAbs) {
sb.append(ABSOLUTE_REFERENCE_MARKER);
}
sb.append(_rowIndex+1);
} }
} }

View File

@ -21,14 +21,14 @@ import java.io.FileInputStream;
import java.util.Iterator; import java.util.Iterator;
import java.util.List; import java.util.List;
import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.record.formula.ExpPtg;
import org.apache.poi.hssf.util.CellReference;
import junit.framework.TestCase; import junit.framework.TestCase;
public class TestBug42464 extends TestCase { import org.apache.poi.hssf.record.FormulaRecord;
import org.apache.poi.hssf.record.aggregates.FormulaRecordAggregate;
import org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator.CellValue;
import org.apache.poi.hssf.util.CellReference;
public final class TestBug42464 extends TestCase {
String dirname; String dirname;
protected void setUp() throws Exception { protected void setUp() throws Exception {
@ -68,26 +68,27 @@ public class TestBug42464 extends TestCase {
Iterator it = row.cellIterator(); Iterator it = row.cellIterator();
while(it.hasNext()) { while(it.hasNext()) {
HSSFCell cell = (HSSFCell)it.next(); HSSFCell cell = (HSSFCell)it.next();
if(cell.getCellType() == HSSFCell.CELL_TYPE_FORMULA) { if(cell.getCellType() != HSSFCell.CELL_TYPE_FORMULA) {
FormulaRecordAggregate record = (FormulaRecordAggregate) continue;
cell.getCellValueRecord();
FormulaRecord r = record.getFormulaRecord();
List ptgs = r.getParsedExpression();
String cellRef = (new CellReference(row.getRowNum(), cell.getCellNum())).toString();
if(cellRef.equals("BP24")) {
System.out.print(cellRef);
System.out.println(" - has " + r.getNumberOfExpressionTokens() + " ptgs over " + r.getExpressionLength() + " tokens:");
for(int i=0; i<ptgs.size(); i++) {
String c = ptgs.get(i).getClass().toString();
System.out.println("\t" + c.substring(c.lastIndexOf('.')+1) );
}
System.out.println("-> " + cell.getCellFormula());
}
eval.evaluate(cell);
} }
FormulaRecordAggregate record = (FormulaRecordAggregate) cell.getCellValueRecord();
FormulaRecord r = record.getFormulaRecord();
List ptgs = r.getParsedExpression();
String cellRef = new CellReference(row.getRowNum(), cell.getCellNum(), false, false).formatAsString();
if(false && cellRef.equals("BP24")) { // TODO - replace System.out.println()s with asserts
System.out.print(cellRef);
System.out.println(" - has " + r.getNumberOfExpressionTokens()
+ " ptgs over " + r.getExpressionLength() + " tokens:");
for(int i=0; i<ptgs.size(); i++) {
String c = ptgs.get(i).getClass().toString();
System.out.println("\t" + c.substring(c.lastIndexOf('.')+1) );
}
System.out.println("-> " + cell.getCellFormula());
}
CellValue evalResult = eval.evaluate(cell);
assertNotNull(evalResult);
} }
} }
} }

View File

@ -100,11 +100,7 @@ import org.apache.poi.hssf.usermodel.TestReadWriteChart;
import org.apache.poi.hssf.usermodel.TestSanityChecker; import org.apache.poi.hssf.usermodel.TestSanityChecker;
import org.apache.poi.hssf.usermodel.TestSheetShiftRows; import org.apache.poi.hssf.usermodel.TestSheetShiftRows;
import org.apache.poi.hssf.usermodel.TestWorkbook; import org.apache.poi.hssf.usermodel.TestWorkbook;
import org.apache.poi.hssf.util.TestAreaReference; import org.apache.poi.hssf.util.AllHSSFUtilTests;
import org.apache.poi.hssf.util.TestCellReference;
import org.apache.poi.hssf.util.TestRKUtil;
import org.apache.poi.hssf.util.TestRangeAddress;
import org.apache.poi.hssf.util.TestSheetReferences;
/** /**
* Test Suite for running just HSSF tests. Mostly * Test Suite for running just HSSF tests. Mostly
@ -202,11 +198,7 @@ public class HSSFTests
suite.addTest(new TestSuite(TestUnitsRecord.class)); suite.addTest(new TestSuite(TestUnitsRecord.class));
suite.addTest(new TestSuite(TestValueRangeRecord.class)); suite.addTest(new TestSuite(TestValueRangeRecord.class));
suite.addTest(new TestSuite(TestRowRecordsAggregate.class)); suite.addTest(new TestSuite(TestRowRecordsAggregate.class));
suite.addTest(new TestSuite(TestAreaReference.class)); suite.addTest(AllHSSFUtilTests.suite());
suite.addTest(new TestSuite(TestCellReference.class));
suite.addTest(new TestSuite(TestRangeAddress.class));
suite.addTest(new TestSuite(TestRKUtil.class));
suite.addTest(new TestSuite(TestSheetReferences.class));
suite.addTest(AllFormulaTests.suite()); suite.addTest(AllFormulaTests.suite());

View File

@ -302,10 +302,10 @@ extends TestCase {
} }
c = r.getCell((short) y); c = r.getCell((short) y);
CellReference cr= new CellReference(refx1,refy1); CellReference cr= new CellReference(refx1,refy1, false, false);
ref=cr.toString(); ref=cr.formatAsString();
cr=new CellReference(refx2,refy2); cr=new CellReference(refx2,refy2, false, false);
ref2=cr.toString(); ref2=cr.formatAsString();
c = r.createCell((short) y); c = r.createCell((short) y);
c.setCellFormula("" + ref + operator + ref2); c.setCellFormula("" + ref + operator + ref2);
@ -379,10 +379,10 @@ extends TestCase {
} }
c = r.getCell((short) y); c = r.getCell((short) y);
CellReference cr= new CellReference(refx1,refy1); CellReference cr= new CellReference(refx1, refy1, false, false);
ref=cr.toString(); ref=cr.formatAsString();
cr=new CellReference(refx2,refy2); cr=new CellReference(refx2,refy2, false, false);
ref2=cr.toString(); ref2=cr.formatAsString();
assertTrue("loop Formula is as expected "+ref+operator+ref2+"!="+c.getCellFormula(),( assertTrue("loop Formula is as expected "+ref+operator+ref2+"!="+c.getCellFormula(),(

View File

@ -578,18 +578,16 @@ public class TestNamedRange
// retrieve the cell at the named range and test its contents // retrieve the cell at the named range and test its contents
AreaReference aref = new AreaReference(aNamedCell.getReference()); AreaReference aref = new AreaReference(aNamedCell.getReference());
CellReference[] crefs = aref.getCells(); assertTrue("Should be exactly 1 cell in the named cell :'" +cellName+"'", aref.isSingleCell());
assertNotNull(crefs);
assertEquals("Should be exactly 1 cell in the named cell :'" +cellName+"'", 1, crefs.length); CellReference cref = aref.getFirstCell();
for (int i=0, iSize=crefs.length; i<iSize; i++) { assertNotNull(cref);
CellReference cref = crefs[i]; HSSFSheet s = wb.getSheet(cref.getSheetName());
assertNotNull(cref); assertNotNull(s);
HSSFSheet s = wb.getSheet(cref.getSheetName()); HSSFRow r = sheet.getRow(cref.getRow());
HSSFRow r = sheet.getRow(cref.getRow()); HSSFCell c = r.getCell(cref.getCol());
HSSFCell c = r.getCell(cref.getCol()); String contents = c.getRichStringCellValue().getString();
String contents = c.getStringCellValue(); assertEquals("Contents of cell retrieved by its named reference", contents, cellValue);
assertEquals("Contents of cell retrieved by its named reference", contents, cellValue);
}
} }
/** /**

View File

@ -0,0 +1,39 @@
/* ====================================================================
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.
==================================================================== */
package org.apache.poi.hssf.util;
import junit.framework.Test;
import junit.framework.TestSuite;
/**
* Collects all tests for org.apache.poi.hssf.util.
*
* @author Josh Micich
*/
public class AllHSSFUtilTests {
public static Test suite() {
TestSuite result = new TestSuite("Tests for org.apache.poi.hssf.util");
result.addTestSuite(TestAreaReference.class);
result.addTestSuite(TestCellReference.class);
result.addTestSuite(TestRangeAddress.class);
result.addTestSuite(TestRKUtil.class);
result.addTestSuite(TestSheetReferences.class);
return result;
}
}

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -29,29 +28,28 @@ import org.apache.poi.hssf.record.formula.Area3DPtg;
import org.apache.poi.hssf.record.formula.UnionPtg; import org.apache.poi.hssf.record.formula.UnionPtg;
import java.io.FileInputStream; import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.util.List; import java.util.List;
public class TestAreaReference extends TestCase { public final class TestAreaReference extends TestCase {
public TestAreaReference(String s) {
super(s);
}
public void testAreaRef1() { public void testAreaRef1() {
AreaReference ar = new AreaReference("$A$1:$B$2"); AreaReference ar = new AreaReference("$A$1:$B$2");
assertTrue("Two cells expected",ar.getCells().length == 2); assertFalse("Two cells expected", ar.isSingleCell());
CellReference cf = ar.getCells()[0]; CellReference cf = ar.getFirstCell();
assertTrue("row is 4",cf.getRow()==0); assertTrue("row is 4",cf.getRow()==0);
assertTrue("col is 1",cf.getCol()==0); assertTrue("col is 1",cf.getCol()==0);
assertTrue("row is abs",cf.isRowAbsolute()); assertTrue("row is abs",cf.isRowAbsolute());
assertTrue("col is abs",cf.isColAbsolute()); assertTrue("col is abs",cf.isColAbsolute());
assertTrue("string is $A$1",cf.toString().equals("$A$1")); assertTrue("string is $A$1",cf.formatAsString().equals("$A$1"));
cf = ar.getCells()[1]; cf = ar.getLastCell();
assertTrue("row is 4",cf.getRow()==1); assertTrue("row is 4",cf.getRow()==1);
assertTrue("col is 1",cf.getCol()==1); assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",cf.isRowAbsolute()); assertTrue("row is abs",cf.isRowAbsolute());
assertTrue("col is abs",cf.isColAbsolute()); assertTrue("col is abs",cf.isColAbsolute());
assertTrue("string is $B$2",cf.toString().equals("$B$2")); assertTrue("string is $B$2",cf.formatAsString().equals("$B$2"));
CellReference[] refs = ar.getAllReferencedCells(); CellReference[] refs = ar.getAllReferencedCells();
assertEquals(4, refs.length); assertEquals(4, refs.length);
@ -78,62 +76,31 @@ public class TestAreaReference extends TestCase {
* Reported by Arne.Clauss@gedas.de * Reported by Arne.Clauss@gedas.de
*/ */
public void testReferenceWithSheet() { public void testReferenceWithSheet() {
String ref = "Tabelle1!B5"; AreaReference ar;
AreaReference myAreaReference = new AreaReference(ref);
CellReference[] myCellReference = myAreaReference.getCells(); ar = new AreaReference("Tabelle1!B5");
assertTrue(ar.isSingleCell());
assertEquals(1, myCellReference.length); TestCellReference.confirmCell(ar.getFirstCell(), "Tabelle1", 4, 1, false, false, "Tabelle1!B5");
assertNotNull("cell reference not null : "+myCellReference[0]);
assertEquals("Not Column B", (short)1,myCellReference[0].getCol()); assertEquals(1, ar.getAllReferencedCells().length);
assertEquals("Not Row 5", 4,myCellReference[0].getRow());
assertEquals("Shouldn't be absolute", false, myCellReference[0].isRowAbsolute());
assertEquals("Shouldn't be absolute", false, myCellReference[0].isColAbsolute()); ar = new AreaReference("Tabelle1!$B$5:$B$7");
assertFalse(ar.isSingleCell());
assertEquals(1, myAreaReference.getAllReferencedCells().length);
TestCellReference.confirmCell(ar.getFirstCell(), "Tabelle1", 4, 1, true, true, "Tabelle1!$B$5");
TestCellReference.confirmCell(ar.getLastCell(), "Tabelle1", 6, 1, true, true, "Tabelle1!$B$7");
ref = "Tabelle1!$B$5:$B$7";
myAreaReference = new AreaReference(ref); // And all that make it up
myCellReference = myAreaReference.getCells(); CellReference[] allCells = ar.getAllReferencedCells();
assertEquals(2, myCellReference.length); assertEquals(3, allCells.length);
TestCellReference.confirmCell(allCells[0], "Tabelle1", 4, 1, true, true, "Tabelle1!$B$5");
assertEquals("Tabelle1", myCellReference[0].getSheetName()); TestCellReference.confirmCell(allCells[1], "Tabelle1", 5, 1, true, true, "Tabelle1!$B$6");
assertEquals(4, myCellReference[0].getRow()); TestCellReference.confirmCell(allCells[2], "Tabelle1", 6, 1, true, true, "Tabelle1!$B$7");
assertEquals(1, myCellReference[0].getCol());
assertTrue(myCellReference[0].isRowAbsolute());
assertTrue(myCellReference[0].isColAbsolute());
assertEquals("Tabelle1", myCellReference[1].getSheetName());
assertEquals(6, myCellReference[1].getRow());
assertEquals(1, myCellReference[1].getCol());
assertTrue(myCellReference[1].isRowAbsolute());
assertTrue(myCellReference[1].isColAbsolute());
// And all that make it up
myCellReference = myAreaReference.getAllReferencedCells();
assertEquals(3, myCellReference.length);
assertEquals("Tabelle1", myCellReference[0].getSheetName());
assertEquals(4, myCellReference[0].getRow());
assertEquals(1, myCellReference[0].getCol());
assertTrue(myCellReference[0].isRowAbsolute());
assertTrue(myCellReference[0].isColAbsolute());
assertEquals("Tabelle1", myCellReference[1].getSheetName());
assertEquals(5, myCellReference[1].getRow());
assertEquals(1, myCellReference[1].getCol());
assertTrue(myCellReference[1].isRowAbsolute());
assertTrue(myCellReference[1].isColAbsolute());
assertEquals("Tabelle1", myCellReference[2].getSheetName());
assertEquals(6, myCellReference[2].getRow());
assertEquals(1, myCellReference[2].getCol());
assertTrue(myCellReference[2].isRowAbsolute());
assertTrue(myCellReference[2].isColAbsolute());
} }
private static class HSSFWB extends HSSFWorkbook { private static class HSSFWB extends HSSFWorkbook {
private HSSFWB(InputStream in) throws Exception { public HSSFWB(InputStream in) throws IOException {
super(in); super(in);
} }
public Workbook getWorkbook() { public Workbook getWorkbook() {
@ -176,42 +143,42 @@ public class TestAreaReference extends TestCase {
refs = AreaReference.generateContiguous(refSimple); refs = AreaReference.generateContiguous(refSimple);
assertEquals(1, refs.length); assertEquals(1, refs.length);
assertEquals(1, refs[0].getDim()); assertTrue(refs[0].isSingleCell());
assertEquals("$C$10", refs[0].toString()); assertEquals("$C$10", refs[0].formatAsString());
refs = AreaReference.generateContiguous(ref2D); refs = AreaReference.generateContiguous(ref2D);
assertEquals(1, refs.length); assertEquals(1, refs.length);
assertEquals(2, refs[0].getDim()); assertFalse(refs[0].isSingleCell());
assertEquals("$C$10:$D$11", refs[0].toString()); assertEquals("$C$10:$D$11", refs[0].formatAsString());
refs = AreaReference.generateContiguous(refDCSimple); refs = AreaReference.generateContiguous(refDCSimple);
assertEquals(3, refs.length); assertEquals(3, refs.length);
assertEquals(1, refs[0].getDim()); assertTrue(refs[0].isSingleCell());
assertEquals(1, refs[1].getDim()); assertTrue(refs[1].isSingleCell());
assertEquals(1, refs[2].getDim()); assertTrue(refs[2].isSingleCell());
assertEquals("$C$10", refs[0].toString()); assertEquals("$C$10", refs[0].formatAsString());
assertEquals("$D$12", refs[1].toString()); assertEquals("$D$12", refs[1].formatAsString());
assertEquals("$E$14", refs[2].toString()); assertEquals("$E$14", refs[2].formatAsString());
refs = AreaReference.generateContiguous(refDC2D); refs = AreaReference.generateContiguous(refDC2D);
assertEquals(3, refs.length); assertEquals(3, refs.length);
assertEquals(2, refs[0].getDim()); assertFalse(refs[0].isSingleCell());
assertEquals(1, refs[1].getDim()); assertTrue(refs[1].isSingleCell());
assertEquals(2, refs[2].getDim()); assertFalse(refs[2].isSingleCell());
assertEquals("$C$10:$C$11", refs[0].toString()); assertEquals("$C$10:$C$11", refs[0].formatAsString());
assertEquals("$D$12", refs[1].toString()); assertEquals("$D$12", refs[1].formatAsString());
assertEquals("$E$14:$E$20", refs[2].toString()); assertEquals("$E$14:$E$20", refs[2].formatAsString());
refs = AreaReference.generateContiguous(refDC3D); refs = AreaReference.generateContiguous(refDC3D);
assertEquals(2, refs.length); assertEquals(2, refs.length);
assertEquals(2, refs[0].getDim()); assertFalse(refs[0].isSingleCell());
assertEquals(2, refs[1].getDim()); assertFalse(refs[0].isSingleCell());
assertEquals("$C$10:$C$14", refs[0].toString()); assertEquals("Tabelle1!$C$10:$C$14", refs[0].formatAsString());
assertEquals("$D$10:$D$12", refs[1].toString()); assertEquals("Tabelle1!$D$10:$D$12", refs[1].formatAsString());
assertEquals("Tabelle1", refs[0].getCells()[0].getSheetName()); assertEquals("Tabelle1", refs[0].getFirstCell().getSheetName());
assertEquals("Tabelle1", refs[0].getCells()[1].getSheetName()); assertEquals("Tabelle1", refs[0].getLastCell().getSheetName());
assertEquals("Tabelle1", refs[1].getCells()[0].getSheetName()); assertEquals("Tabelle1", refs[1].getFirstCell().getSheetName());
assertEquals("Tabelle1", refs[1].getCells()[1].getSheetName()); assertEquals("Tabelle1", refs[1].getLastCell().getSheetName());
} }
public void testDiscontinousReference() throws Exception { public void testDiscontinousReference() throws Exception {
@ -261,22 +228,46 @@ public class TestAreaReference extends TestCase {
assertFalse(AreaReference.isContiguous(aNamedCell.getReference())); assertFalse(AreaReference.isContiguous(aNamedCell.getReference()));
AreaReference[] arefs = AreaReference.generateContiguous(aNamedCell.getReference()); AreaReference[] arefs = AreaReference.generateContiguous(aNamedCell.getReference());
assertEquals(2, arefs.length); assertEquals(2, arefs.length);
assertEquals(rawRefA, arefs[0].toString()); assertEquals(refA, arefs[0].formatAsString());
assertEquals(rawRefB, arefs[1].toString()); assertEquals(refB, arefs[1].formatAsString());
for(int i=0; i<arefs.length; i++) { for(int i=0; i<arefs.length; i++) {
CellReference[] crefs = arefs[i].getCells(); AreaReference ar = arefs[i];
for (int j=0; j<crefs.length; j++) { confirmResolveCellRef(wb, ar.getFirstCell());
// Check it turns into real stuff confirmResolveCellRef(wb, ar.getLastCell());
HSSFSheet s = wb.getSheet(crefs[j].getSheetName());
HSSFRow r = s.getRow(crefs[j].getRow());
HSSFCell c = r.getCell(crefs[j].getCol());
}
} }
} }
private static void confirmResolveCellRef(HSSFWorkbook wb, CellReference cref) {
HSSFSheet s = wb.getSheet(cref.getSheetName());
HSSFRow r = s.getRow(cref.getRow());
HSSFCell c = r.getCell(cref.getCol());
assertNotNull(c);
}
public static void main(java.lang.String[] args) { public void testSpecialSheetNames() {
junit.textui.TestRunner.run(TestAreaReference.class); AreaReference ar;
} ar = new AreaReference("'Sheet A'!A1");
confirmAreaSheetName(ar, "Sheet A", "'Sheet A'!A1");
ar = new AreaReference("'Hey! Look Here!'!A1");
confirmAreaSheetName(ar, "Hey! Look Here!", "'Hey! Look Here!'!A1");
ar = new AreaReference("'O''Toole'!A1:B2");
confirmAreaSheetName(ar, "O'Toole", "'O''Toole'!A1:B2");
ar = new AreaReference("'one:many'!A1:B2");
confirmAreaSheetName(ar, "one:many", "'one:many'!A1:B2");
}
private static void confirmAreaSheetName(AreaReference ar, String sheetName, String expectedFullText) {
CellReference[] cells = ar.getAllReferencedCells();
assertEquals(sheetName, cells[0].getSheetName());
assertEquals(expectedFullText, ar.formatAsString());
}
public static void main(String[] args) {
junit.textui.TestRunner.run(TestAreaReference.class);
}
} }

View File

@ -1,4 +1,3 @@
/* ==================================================================== /* ====================================================================
Licensed to the Apache Software Foundation (ASF) under one or more Licensed to the Apache Software Foundation (ASF) under one or more
contributor license agreements. See the NOTICE file distributed with contributor license agreements. See the NOTICE file distributed with
@ -22,87 +21,74 @@ package org.apache.poi.hssf.util;
import junit.framework.TestCase; import junit.framework.TestCase;
public class TestCellReference extends TestCase { public final class TestCellReference extends TestCase {
public TestCellReference(String s) {
super(s);
}
public void testAbsRef1(){ public void testAbsRef1(){
CellReference cf = new CellReference("$B$5"); CellReference cf = new CellReference("$B$5");
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, true, true, "$B$5");
assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",cf.isRowAbsolute());
assertTrue("col is abs",cf.isColAbsolute());
assertTrue("string is $B$5",cf.toString().equals("$B$5"));
} }
public void testAbsRef2(){ public void testAbsRef2(){
CellReference cf = new CellReference(4,1,true,true); CellReference cf = new CellReference(4,1,true,true);
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, true, true, "$B$5");
assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",cf.isRowAbsolute());
assertTrue("col is abs",cf.isColAbsolute());
assertTrue("string is $B$5",cf.toString().equals("$B$5"));
} }
public void testAbsRef3(){ public void testAbsRef3(){
CellReference cf = new CellReference("B$5"); CellReference cf = new CellReference("B$5");
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, true, false, "B$5");
assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",cf.isRowAbsolute());
assertTrue("col is rel",!cf.isColAbsolute());
assertTrue("string is B$5",cf.toString().equals("B$5"));
} }
public void testAbsRef4(){ public void testAbsRef4(){
CellReference cf = new CellReference(4,1,true,false); CellReference cf = new CellReference(4,1,true,false);
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, true, false, "B$5");
assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",cf.isRowAbsolute());
assertTrue("col is rel",!cf.isColAbsolute());
assertTrue("string is B$5",cf.toString().equals("B$5"));
} }
public void testAbsRef5(){ public void testAbsRef5(){
CellReference cf = new CellReference("$B5"); CellReference cf = new CellReference("$B5");
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, false, true, "$B5");
assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",!cf.isRowAbsolute());
assertTrue("col is rel",cf.isColAbsolute());
assertTrue("string is B$5",cf.toString().equals("$B5"));
} }
public void testAbsRef6(){ public void testAbsRef6(){
CellReference cf = new CellReference(4,1,false,true); CellReference cf = new CellReference(4,1,false,true);
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, false, true, "$B5");
assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",!cf.isRowAbsolute());
assertTrue("col is rel",cf.isColAbsolute());
assertTrue("string is B$5",cf.toString().equals("$B5"));
} }
public void testAbsRef7(){ public void testAbsRef7(){
CellReference cf = new CellReference("B5"); CellReference cf = new CellReference("B5");
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, false, false, "B5");
assertTrue("col is 1",cf.getCol()==1);
assertTrue("row is abs",!cf.isRowAbsolute());
assertTrue("col is rel",!cf.isColAbsolute());
assertTrue("string is B$5",cf.toString().equals("B5"));
} }
public void testAbsRef8(){ public void testAbsRef8(){
CellReference cf = new CellReference(4,1,false,false); CellReference cf = new CellReference(4,1,false,false);
assertTrue("row is 4",cf.getRow()==4); confirmCell(cf, null, 4, 1, false, false, "B5");
assertTrue("col is 1",cf.getCol()==1); }
assertTrue("row is abs",!cf.isRowAbsolute());
assertTrue("col is rel",!cf.isColAbsolute()); public void testSpecialSheetNames() {
assertTrue("string is B$5",cf.toString().equals("B5")); CellReference cf;
cf = new CellReference("'profit + loss'!A1");
confirmCell(cf, "profit + loss", 0, 0, false, false, "'profit + loss'!A1");
cf = new CellReference("'O''Brien''s Sales'!A1");
confirmCell(cf, "O'Brien's Sales", 0, 0, false, false, "'O''Brien''s Sales'!A1");
cf = new CellReference("'Amazing!'!A1");
confirmCell(cf, "Amazing!", 0, 0, false, false, "'Amazing!'!A1");
} }
/* package */ static void confirmCell(CellReference cf, String expSheetName, int expRow,
int expCol, boolean expIsRowAbs, boolean expIsColAbs, String expText) {
assertEquals(expSheetName, cf.getSheetName());
assertEquals("row index is wrong", expRow, cf.getRow());
assertEquals("col index is wrong", expCol, cf.getCol());
assertEquals("isRowAbsolute is wrong", expIsRowAbs, cf.isRowAbsolute());
assertEquals("isColAbsolute is wrong", expIsColAbs, cf.isColAbsolute());
assertEquals("text is wrong", expText, cf.formatAsString());
}
public static void main(String [] args) { public static void main(String [] args) {
System.out.println("Testing org.apache.poi.hssf.util.TestCellReference"); System.out.println("Testing org.apache.poi.hssf.util.TestCellReference");
junit.textui.TestRunner.run(TestCellReference.class); junit.textui.TestRunner.run(TestCellReference.class);
} }
} }