Browse Source

whitespace (tabs to spaces)

git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xssf_structured_references@1747625 13f79535-47bb-0310-9956-ffa450edef68
tags/REL_3_15_BETA2
Javen O'Neal 8 years ago
parent
commit
e97e241ac2

+ 1
- 1
src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java View File

@@ -6,7 +6,7 @@
(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
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,

+ 38
- 38
src/java/org/apache/poi/ss/formula/FormulaParsingWorkbook.java View File

@@ -32,51 +32,51 @@ import org.apache.poi.ss.util.CellReference;
* @author Josh Micich
*/
public interface FormulaParsingWorkbook {
/**
* named range name matching is case insensitive
*/
EvaluationName getName(String name, int sheetIndex);
/**
* Return the underlying workbook
*/
Name createName();
/**
* named range name matching is case insensitive
*/
EvaluationName getName(String name, int sheetIndex);
/**
* Return the underlying workbook
*/
Name createName();

/**
* XSSF Only - gets a table that exists in the worksheet
*/
Table getTable(String name);
/**
* Return an external name (named range, function, user-defined function) Ptg
*/
Ptg getNameXPtg(String name, SheetIdentifier sheet);
/**
* Produce the appropriate Ptg for a 3d cell reference
*/
Ptg get3DReferencePtg(CellReference cell, SheetIdentifier sheet);
/**
* XSSF Only - gets a table that exists in the worksheet
*/
Table getTable(String name);
/**
* Return an external name (named range, function, user-defined function) Ptg
*/
Ptg getNameXPtg(String name, SheetIdentifier sheet);
/**
* Produce the appropriate Ptg for a 3d cell reference
*/
Ptg get3DReferencePtg(CellReference cell, SheetIdentifier sheet);

/**
* Produce the appropriate Ptg for a 3d area reference
*/
Ptg get3DReferencePtg(AreaReference area, SheetIdentifier sheet);

/**
* gets the externSheet index for a sheet from this workbook
*/
int getExternalSheetIndex(String sheetName);
/**
* gets the externSheet index for a sheet from an external workbook
* @param workbookName e.g. "Budget.xls"
* @param sheetName a name of a sheet in that workbook
*/
int getExternalSheetIndex(String workbookName, String sheetName);
/**
* gets the externSheet index for a sheet from this workbook
*/
int getExternalSheetIndex(String sheetName);
/**
* gets the externSheet index for a sheet from an external workbook
* @param workbookName e.g. "Budget.xls"
* @param sheetName a name of a sheet in that workbook
*/
int getExternalSheetIndex(String workbookName, String sheetName);

/**
* Returns an enum holding spreadhseet properties specific to an Excel version (
* max column and row numbers, max arguments to a function, etc.)
*/
SpreadsheetVersion getSpreadsheetVersion();
/**
* Returns an enum holding spreadhseet properties specific to an Excel version (
* max column and row numbers, max arguments to a function, etc.)
*/
SpreadsheetVersion getSpreadsheetVersion();

}

+ 223
- 223
src/java/org/apache/poi/ss/formula/OperationEvaluationContext.java View File

@@ -46,199 +46,199 @@ import org.apache.poi.ss.util.CellReference.NameType;
* For POI internal use only
*/
public final class OperationEvaluationContext {
public static final FreeRefFunction UDF = UserDefinedFunction.instance;
private final EvaluationWorkbook _workbook;
private final int _sheetIndex;
private final int _rowIndex;
private final int _columnIndex;
private final EvaluationTracker _tracker;
private final WorkbookEvaluator _bookEvaluator;
public static final FreeRefFunction UDF = UserDefinedFunction.instance;
private final EvaluationWorkbook _workbook;
private final int _sheetIndex;
private final int _rowIndex;
private final int _columnIndex;
private final EvaluationTracker _tracker;
private final WorkbookEvaluator _bookEvaluator;

public OperationEvaluationContext(WorkbookEvaluator bookEvaluator, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum,
int srcColNum, EvaluationTracker tracker) {
_bookEvaluator = bookEvaluator;
_workbook = workbook;
_sheetIndex = sheetIndex;
_rowIndex = srcRowNum;
_columnIndex = srcColNum;
_tracker = tracker;
}
public OperationEvaluationContext(WorkbookEvaluator bookEvaluator, EvaluationWorkbook workbook, int sheetIndex, int srcRowNum,
int srcColNum, EvaluationTracker tracker) {
_bookEvaluator = bookEvaluator;
_workbook = workbook;
_sheetIndex = sheetIndex;
_rowIndex = srcRowNum;
_columnIndex = srcColNum;
_tracker = tracker;
}

public EvaluationWorkbook getWorkbook() {
return _workbook;
}
public EvaluationWorkbook getWorkbook() {
return _workbook;
}

public int getRowIndex() {
return _rowIndex;
}
public int getRowIndex() {
return _rowIndex;
}

public int getColumnIndex() {
return _columnIndex;
}
public int getColumnIndex() {
return _columnIndex;
}

SheetRangeEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
return createExternSheetRefEvaluator(ptg.getExternSheetIndex());
}
SheetRangeEvaluator createExternSheetRefEvaluator(String firstSheetName, String lastSheetName, int externalWorkbookNumber) {
SheetRangeEvaluator createExternSheetRefEvaluator(ExternSheetReferenceToken ptg) {
return createExternSheetRefEvaluator(ptg.getExternSheetIndex());
}
SheetRangeEvaluator createExternSheetRefEvaluator(String firstSheetName, String lastSheetName, int externalWorkbookNumber) {
ExternalSheet externalSheet = _workbook.getExternalSheet(firstSheetName, lastSheetName, externalWorkbookNumber);
return createExternSheetRefEvaluator(externalSheet);
}
SheetRangeEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex);
SheetRangeEvaluator createExternSheetRefEvaluator(int externSheetIndex) {
ExternalSheet externalSheet = _workbook.getExternalSheet(externSheetIndex);
return createExternSheetRefEvaluator(externalSheet);
}
SheetRangeEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) {
WorkbookEvaluator targetEvaluator;
int otherFirstSheetIndex;
int otherLastSheetIndex = -1;
if (externalSheet == null || externalSheet.getWorkbookName() == null) {
// sheet is in same workbook
targetEvaluator = _bookEvaluator;
if(externalSheet == null) {
otherFirstSheetIndex = 0;
} else {
otherFirstSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
}
if (externalSheet instanceof ExternalSheetRange) {
String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
otherLastSheetIndex = _workbook.getSheetIndex(lastSheetName);
}
} else {
// look up sheet by name from external workbook
String workbookName = externalSheet.getWorkbookName();
try {
targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
} catch (WorkbookNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
otherFirstSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName());
}
SheetRangeEvaluator createExternSheetRefEvaluator(ExternalSheet externalSheet) {
WorkbookEvaluator targetEvaluator;
int otherFirstSheetIndex;
int otherLastSheetIndex = -1;
if (externalSheet == null || externalSheet.getWorkbookName() == null) {
// sheet is in same workbook
targetEvaluator = _bookEvaluator;
if(externalSheet == null) {
otherFirstSheetIndex = 0;
} else {
otherFirstSheetIndex = _workbook.getSheetIndex(externalSheet.getSheetName());
}
if (externalSheet instanceof ExternalSheetRange) {
String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
otherLastSheetIndex = _workbook.getSheetIndex(lastSheetName);
}
} else {
// look up sheet by name from external workbook
String workbookName = externalSheet.getWorkbookName();
try {
targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
} catch (WorkbookNotFoundException e) {
throw new RuntimeException(e.getMessage(), e);
}
otherFirstSheetIndex = targetEvaluator.getSheetIndex(externalSheet.getSheetName());
if (externalSheet instanceof ExternalSheetRange) {
String lastSheetName = ((ExternalSheetRange)externalSheet).getLastSheetName();
otherLastSheetIndex = targetEvaluator.getSheetIndex(lastSheetName);
}
if (otherFirstSheetIndex < 0) {
throw new RuntimeException("Invalid sheet name '" + externalSheet.getSheetName()
+ "' in bool '" + workbookName + "'.");
}
}
if (otherLastSheetIndex == -1) {
// Reference to just one sheet
otherLastSheetIndex = otherFirstSheetIndex;
}
SheetRefEvaluator[] evals = new SheetRefEvaluator[otherLastSheetIndex-otherFirstSheetIndex+1];
for (int i=0; i<evals.length; i++) {
int otherSheetIndex = i+otherFirstSheetIndex;
evals[i] = new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
}
return new SheetRangeEvaluator(otherFirstSheetIndex, otherLastSheetIndex, evals);
}
if (otherFirstSheetIndex < 0) {
throw new RuntimeException("Invalid sheet name '" + externalSheet.getSheetName()
+ "' in bool '" + workbookName + "'.");
}
}
if (otherLastSheetIndex == -1) {
// Reference to just one sheet
otherLastSheetIndex = otherFirstSheetIndex;
}
SheetRefEvaluator[] evals = new SheetRefEvaluator[otherLastSheetIndex-otherFirstSheetIndex+1];
for (int i=0; i<evals.length; i++) {
int otherSheetIndex = i+otherFirstSheetIndex;
evals[i] = new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
}
return new SheetRangeEvaluator(otherFirstSheetIndex, otherLastSheetIndex, evals);
}

/**
* @return <code>null</code> if either workbook or sheet is not found
*/
private SheetRefEvaluator createExternSheetRefEvaluator(String workbookName, String sheetName) {
WorkbookEvaluator targetEvaluator;
if (workbookName == null) {
targetEvaluator = _bookEvaluator;
} else {
if (sheetName == null) {
throw new IllegalArgumentException("sheetName must not be null if workbookName is provided");
}
try {
targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
} catch (WorkbookNotFoundException e) {
return null;
}
}
int otherSheetIndex = sheetName == null ? _sheetIndex : targetEvaluator.getSheetIndex(sheetName);
if (otherSheetIndex < 0) {
return null;
}
return new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
}
/**
* @return <code>null</code> if either workbook or sheet is not found
*/
private SheetRefEvaluator createExternSheetRefEvaluator(String workbookName, String sheetName) {
WorkbookEvaluator targetEvaluator;
if (workbookName == null) {
targetEvaluator = _bookEvaluator;
} else {
if (sheetName == null) {
throw new IllegalArgumentException("sheetName must not be null if workbookName is provided");
}
try {
targetEvaluator = _bookEvaluator.getOtherWorkbookEvaluator(workbookName);
} catch (WorkbookNotFoundException e) {
return null;
}
}
int otherSheetIndex = sheetName == null ? _sheetIndex : targetEvaluator.getSheetIndex(sheetName);
if (otherSheetIndex < 0) {
return null;
}
return new SheetRefEvaluator(targetEvaluator, _tracker, otherSheetIndex);
}

public SheetRangeEvaluator getRefEvaluatorForCurrentSheet() {
SheetRefEvaluator sre = new SheetRefEvaluator(_bookEvaluator, _tracker, _sheetIndex);
return new SheetRangeEvaluator(_sheetIndex, sre);
}
public SheetRangeEvaluator getRefEvaluatorForCurrentSheet() {
SheetRefEvaluator sre = new SheetRefEvaluator(_bookEvaluator, _tracker, _sheetIndex);
return new SheetRangeEvaluator(_sheetIndex, sre);
}



/**
* Resolves a cell or area reference dynamically.
* @param workbookName the name of the workbook containing the reference. If <code>null</code>
* the current workbook is assumed. Note - to evaluate formulas which use multiple workbooks,
* a {@link CollaboratingWorkbooksEnvironment} must be set up.
* @param sheetName the name of the sheet containing the reference. May be <code>null</code>
* (when <tt>workbookName</tt> is also null) in which case the current workbook and sheet is
* assumed.
* @param refStrPart1 the single cell reference or first part of the area reference. Must not
* be <code>null</code>.
* @param refStrPart2 the second part of the area reference. For single cell references this
* parameter must be <code>null</code>
* @param isA1Style specifies the format for <tt>refStrPart1</tt> and <tt>refStrPart2</tt>.
* Pass <code>true</code> for 'A1' style and <code>false</code> for 'R1C1' style.
* TODO - currently POI only supports 'A1' reference style
* @return a {@link RefEval} or {@link AreaEval}
*/
public ValueEval getDynamicReference(String workbookName, String sheetName, String refStrPart1,
String refStrPart2, boolean isA1Style) {
if (!isA1Style) {
throw new RuntimeException("R1C1 style not supported yet");
}
SheetRefEvaluator se = createExternSheetRefEvaluator(workbookName, sheetName);
if (se == null) {
return ErrorEval.REF_INVALID;
}
SheetRangeEvaluator sre = new SheetRangeEvaluator(_sheetIndex, se);
// ugly typecast - TODO - make spreadsheet version more easily accessible
SpreadsheetVersion ssVersion = ((FormulaParsingWorkbook)_workbook).getSpreadsheetVersion();
/**
* Resolves a cell or area reference dynamically.
* @param workbookName the name of the workbook containing the reference. If <code>null</code>
* the current workbook is assumed. Note - to evaluate formulas which use multiple workbooks,
* a {@link CollaboratingWorkbooksEnvironment} must be set up.
* @param sheetName the name of the sheet containing the reference. May be <code>null</code>
* (when <tt>workbookName</tt> is also null) in which case the current workbook and sheet is
* assumed.
* @param refStrPart1 the single cell reference or first part of the area reference. Must not
* be <code>null</code>.
* @param refStrPart2 the second part of the area reference. For single cell references this
* parameter must be <code>null</code>
* @param isA1Style specifies the format for <tt>refStrPart1</tt> and <tt>refStrPart2</tt>.
* Pass <code>true</code> for 'A1' style and <code>false</code> for 'R1C1' style.
* TODO - currently POI only supports 'A1' reference style
* @return a {@link RefEval} or {@link AreaEval}
*/
public ValueEval getDynamicReference(String workbookName, String sheetName, String refStrPart1,
String refStrPart2, boolean isA1Style) {
if (!isA1Style) {
throw new RuntimeException("R1C1 style not supported yet");
}
SheetRefEvaluator se = createExternSheetRefEvaluator(workbookName, sheetName);
if (se == null) {
return ErrorEval.REF_INVALID;
}
SheetRangeEvaluator sre = new SheetRangeEvaluator(_sheetIndex, se);
// ugly typecast - TODO - make spreadsheet version more easily accessible
SpreadsheetVersion ssVersion = ((FormulaParsingWorkbook)_workbook).getSpreadsheetVersion();

NameType part1refType = classifyCellReference(refStrPart1, ssVersion);
switch (part1refType) {
case BAD_CELL_OR_NAMED_RANGE:
return ErrorEval.REF_INVALID;
case NAMED_RANGE:
NameType part1refType = classifyCellReference(refStrPart1, ssVersion);
switch (part1refType) {
case BAD_CELL_OR_NAMED_RANGE:
return ErrorEval.REF_INVALID;
case NAMED_RANGE:
EvaluationName nm = ((FormulaParsingWorkbook)_workbook).getName(refStrPart1, _sheetIndex);
if(!nm.isRange()){
throw new RuntimeException("Specified name '" + refStrPart1 + "' is not a range as expected.");
}
return _bookEvaluator.evaluateNameFormula(nm.getNameDefinition(), this);
}
if (refStrPart2 == null) {
// no ':'
switch (part1refType) {
case COLUMN:
case ROW:
return ErrorEval.REF_INVALID;
case CELL:
CellReference cr = new CellReference(refStrPart1);
return new LazyRefEval(cr.getRow(), cr.getCol(), sre);
}
throw new IllegalStateException("Unexpected reference classification of '" + refStrPart1 + "'.");
}
NameType part2refType = classifyCellReference(refStrPart1, ssVersion);
switch (part2refType) {
case BAD_CELL_OR_NAMED_RANGE:
return ErrorEval.REF_INVALID;
case NAMED_RANGE:
throw new RuntimeException("Cannot evaluate '" + refStrPart1
+ "'. Indirect evaluation of defined names not supported yet");
}
}
if (refStrPart2 == null) {
// no ':'
switch (part1refType) {
case COLUMN:
case ROW:
return ErrorEval.REF_INVALID;
case CELL:
CellReference cr = new CellReference(refStrPart1);
return new LazyRefEval(cr.getRow(), cr.getCol(), sre);
}
throw new IllegalStateException("Unexpected reference classification of '" + refStrPart1 + "'.");
}
NameType part2refType = classifyCellReference(refStrPart1, ssVersion);
switch (part2refType) {
case BAD_CELL_OR_NAMED_RANGE:
return ErrorEval.REF_INVALID;
case NAMED_RANGE:
throw new RuntimeException("Cannot evaluate '" + refStrPart1
+ "'. Indirect evaluation of defined names not supported yet");
}

if (part2refType != part1refType) {
// LHS and RHS of ':' must be compatible
return ErrorEval.REF_INVALID;
}
int firstRow, firstCol, lastRow, lastCol;
switch (part1refType) {
case COLUMN:
if (part2refType != part1refType) {
// LHS and RHS of ':' must be compatible
return ErrorEval.REF_INVALID;
}
int firstRow, firstCol, lastRow, lastCol;
switch (part1refType) {
case COLUMN:
firstRow =0;
if (part2refType.equals(NameType.COLUMN))
{
@@ -252,7 +252,7 @@ public final class OperationEvaluationContext {
lastCol = parseColRef(refStrPart2);
}
break;
case ROW:
case ROW:
// support of cell range in the form of integer:integer
firstCol = 0;
if (part2refType.equals(NameType.ROW))
@@ -265,61 +265,61 @@ public final class OperationEvaluationContext {
firstRow = parseRowRef(refStrPart1);
lastRow = parseRowRef(refStrPart2);
}
break;
case CELL:
CellReference cr;
cr = new CellReference(refStrPart1);
firstRow = cr.getRow();
firstCol = cr.getCol();
cr = new CellReference(refStrPart2);
lastRow = cr.getRow();
lastCol = cr.getCol();
break;
default:
throw new IllegalStateException("Unexpected reference classification of '" + refStrPart1 + "'.");
}
return new LazyAreaEval(firstRow, firstCol, lastRow, lastCol, sre);
}
break;
case CELL:
CellReference cr;
cr = new CellReference(refStrPart1);
firstRow = cr.getRow();
firstCol = cr.getCol();
cr = new CellReference(refStrPart2);
lastRow = cr.getRow();
lastCol = cr.getCol();
break;
default:
throw new IllegalStateException("Unexpected reference classification of '" + refStrPart1 + "'.");
}
return new LazyAreaEval(firstRow, firstCol, lastRow, lastCol, sre);
}

private static int parseRowRef(String refStrPart) {
return CellReference.convertColStringToIndex(refStrPart);
}
private static int parseRowRef(String refStrPart) {
return CellReference.convertColStringToIndex(refStrPart);
}

private static int parseColRef(String refStrPart) {
return Integer.parseInt(refStrPart) - 1;
}
private static int parseColRef(String refStrPart) {
return Integer.parseInt(refStrPart) - 1;
}

private static NameType classifyCellReference(String str, SpreadsheetVersion ssVersion) {
int len = str.length();
if (len < 1) {
return CellReference.NameType.BAD_CELL_OR_NAMED_RANGE;
}
return CellReference.classifyCellReference(str, ssVersion);
}
private static NameType classifyCellReference(String str, SpreadsheetVersion ssVersion) {
int len = str.length();
if (len < 1) {
return CellReference.NameType.BAD_CELL_OR_NAMED_RANGE;
}
return CellReference.classifyCellReference(str, ssVersion);
}

public FreeRefFunction findUserDefinedFunction(String functionName) {
return _bookEvaluator.findUserDefinedFunction(functionName);
}
public FreeRefFunction findUserDefinedFunction(String functionName) {
return _bookEvaluator.findUserDefinedFunction(functionName);
}

public ValueEval getRefEval(int rowIndex, int columnIndex) {
SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
return new LazyRefEval(rowIndex, columnIndex, sre);
}
public ValueEval getRef3DEval(Ref3DPtg rptg) {
SheetRangeEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex());
return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
}
public ValueEval getRefEval(int rowIndex, int columnIndex) {
SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
return new LazyRefEval(rowIndex, columnIndex, sre);
}
public ValueEval getRef3DEval(Ref3DPtg rptg) {
SheetRangeEvaluator sre = createExternSheetRefEvaluator(rptg.getExternSheetIndex());
return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
}
public ValueEval getRef3DEval(Ref3DPxg rptg) {
SheetRangeEvaluator sre = createExternSheetRefEvaluator(
rptg.getSheetName(), rptg.getLastSheetName(), rptg.getExternalWorkbookNumber());
return new LazyRefEval(rptg.getRow(), rptg.getColumn(), sre);
}
public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex,
int lastRowIndex, int lastColumnIndex) {
SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre);
}
public ValueEval getAreaEval(int firstRowIndex, int firstColumnIndex,
int lastRowIndex, int lastColumnIndex) {
SheetRangeEvaluator sre = getRefEvaluatorForCurrentSheet();
return new LazyAreaEval(firstRowIndex, firstColumnIndex, lastRowIndex, lastColumnIndex, sre);
}
public ValueEval getArea3DEval(Area3DPtg aptg) {
SheetRangeEvaluator sre = createExternSheetRefEvaluator(aptg.getExternSheetIndex());
return new LazyAreaEval(aptg.getFirstRow(), aptg.getFirstColumn(),
@@ -348,8 +348,8 @@ public final class OperationEvaluationContext {
);
return getExternalNameXEval(externName, workbookName);
}
public ValueEval getNameXEval(NameXPxg nameXPxg) {
ExternalSheet externSheet = _workbook.getExternalSheet(nameXPxg.getSheetName(), null, nameXPxg.getExternalWorkbookNumber());
public ValueEval getNameXEval(NameXPxg nameXPxg) {
ExternalSheet externSheet = _workbook.getExternalSheet(nameXPxg.getSheetName(), null, nameXPxg.getExternalWorkbookNumber());
if(externSheet == null || externSheet.getWorkbookName() == null) {
// External reference to our own workbook's name
return getLocalNameXEval(nameXPxg);
@@ -363,8 +363,8 @@ public final class OperationEvaluationContext {
nameXPxg.getExternalWorkbookNumber()
);
return getExternalNameXEval(externName, workbookName);
}
}
private ValueEval getLocalNameXEval(NameXPxg nameXPxg) {
// Look up the sheet, if present
int sIdx = -1;
@@ -383,7 +383,7 @@ public final class OperationEvaluationContext {
return new FunctionNameEval(name);
}
}
private ValueEval getLocalNameXEval(NameXPtg nameXPtg) {
private ValueEval getLocalNameXEval(NameXPtg nameXPtg) {
String name = _workbook.resolveNameXText(nameXPtg);
// Try to parse it as a name
@@ -406,11 +406,11 @@ public final class OperationEvaluationContext {
// Must be an external function
return new FunctionNameEval(name);
}
}
public int getSheetIndex() {
return _sheetIndex;
}
}
public int getSheetIndex() {
return _sheetIndex;
}
private ValueEval getExternalNameXEval(ExternalName externName, String workbookName) {
try {
// Fetch the workbook this refers to, and the name as defined with that

+ 534
- 534
src/java/org/apache/poi/ss/formula/WorkbookEvaluator.java
File diff suppressed because it is too large
View File


+ 181
- 181
src/java/org/apache/poi/ss/formula/functions/Indirect.java View File

@@ -49,78 +49,78 @@ public final class Indirect implements FreeRefFunction {

public static final FreeRefFunction instance = new Indirect();

private Indirect() {
// enforce singleton
}
private Indirect() {
// enforce singleton
}

public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
if (args.length < 1) {
return ErrorEval.VALUE_INVALID;
}
public ValueEval evaluate(ValueEval[] args, OperationEvaluationContext ec) {
if (args.length < 1) {
return ErrorEval.VALUE_INVALID;
}

boolean isA1style;
String text;
try {
ValueEval ve = OperandResolver.getSingleValue(args[0], ec.getRowIndex(), ec
.getColumnIndex());
text = OperandResolver.coerceValueToString(ve);
switch (args.length) {
case 1:
isA1style = true;
break;
case 2:
isA1style = evaluateBooleanArg(args[1], ec);
break;
default:
return ErrorEval.VALUE_INVALID;
}
} catch (EvaluationException e) {
return e.getErrorEval();
}
boolean isA1style;
String text;
try {
ValueEval ve = OperandResolver.getSingleValue(args[0], ec.getRowIndex(), ec
.getColumnIndex());
text = OperandResolver.coerceValueToString(ve);
switch (args.length) {
case 1:
isA1style = true;
break;
case 2:
isA1style = evaluateBooleanArg(args[1], ec);
break;
default:
return ErrorEval.VALUE_INVALID;
}
} catch (EvaluationException e) {
return e.getErrorEval();
}

return evaluateIndirect(ec, text, isA1style);
}
return evaluateIndirect(ec, text, isA1style);
}

private static boolean evaluateBooleanArg(ValueEval arg, OperationEvaluationContext ec)
throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(arg, ec.getRowIndex(), ec.getColumnIndex());
private static boolean evaluateBooleanArg(ValueEval arg, OperationEvaluationContext ec)
throws EvaluationException {
ValueEval ve = OperandResolver.getSingleValue(arg, ec.getRowIndex(), ec.getColumnIndex());

if (ve == BlankEval.instance || ve == MissingArgEval.instance) {
return false;
}
// numeric quantities follow standard boolean conversion rules
// for strings, only "TRUE" and "FALSE" (case insensitive) are valid
return OperandResolver.coerceValueToBoolean(ve, false).booleanValue();
}
if (ve == BlankEval.instance || ve == MissingArgEval.instance) {
return false;
}
// numeric quantities follow standard boolean conversion rules
// for strings, only "TRUE" and "FALSE" (case insensitive) are valid
return OperandResolver.coerceValueToBoolean(ve, false).booleanValue();
}

private static ValueEval evaluateIndirect(final OperationEvaluationContext ec, String text,
boolean isA1style) {
ec.getRowIndex();
ec.getColumnIndex();
private static ValueEval evaluateIndirect(final OperationEvaluationContext ec, String text,
boolean isA1style) {
ec.getRowIndex();
ec.getColumnIndex();

// Search backwards for '!' because sheet names can contain '!'
int plingPos = text.lastIndexOf('!');
// Search backwards for '!' because sheet names can contain '!'
int plingPos = text.lastIndexOf('!');

String workbookName;
String sheetName;
String refText; // whitespace around this gets trimmed OK
if (plingPos < 0) {
workbookName = null;
sheetName = null;
refText = text;
} else {
String[] parts = parseWorkbookAndSheetName(text.subSequence(0, plingPos));
if (parts == null) {
return ErrorEval.REF_INVALID;
}
workbookName = parts[0];
sheetName = parts[1];
refText = text.substring(plingPos + 1);
}
String workbookName;
String sheetName;
String refText; // whitespace around this gets trimmed OK
if (plingPos < 0) {
workbookName = null;
sheetName = null;
refText = text;
} else {
String[] parts = parseWorkbookAndSheetName(text.subSequence(0, plingPos));
if (parts == null) {
return ErrorEval.REF_INVALID;
}
workbookName = parts[0];
sheetName = parts[1];
refText = text.substring(plingPos + 1);
}

String refStrPart1;
String refStrPart2;
String refStrPart1;
String refStrPart2;
if (Table.isStructuredReference.matcher(refText).matches()) { // The argument is structured reference
Area3DPxg areaPtg = null;
try{
@@ -130,128 +130,128 @@ public final class Indirect implements FreeRefFunction {
}
return ec.getArea3DEval(areaPtg);
} else { // The argumnet is regular reference
int colonPos = refText.indexOf(':');
if (colonPos < 0) {
refStrPart1 = refText.trim();
refStrPart2 = null;
} else {
refStrPart1 = refText.substring(0, colonPos).trim();
refStrPart2 = refText.substring(colonPos + 1).trim();
}
return ec.getDynamicReference(workbookName, sheetName, refStrPart1, refStrPart2, isA1style);
int colonPos = refText.indexOf(':');
if (colonPos < 0) {
refStrPart1 = refText.trim();
refStrPart2 = null;
} else {
refStrPart1 = refText.substring(0, colonPos).trim();
refStrPart2 = refText.substring(colonPos + 1).trim();
}
return ec.getDynamicReference(workbookName, sheetName, refStrPart1, refStrPart2, isA1style);
}
}
}

/**
* @return array of length 2: {workbookName, sheetName,}. Second element will always be
* present. First element may be null if sheetName is unqualified.
* Returns <code>null</code> if text cannot be parsed.
*/
private static String[] parseWorkbookAndSheetName(CharSequence text) {
int lastIx = text.length() - 1;
if (lastIx < 0) {
return null;
}
if (canTrim(text)) {
return null;
}
char firstChar = text.charAt(0);
if (Character.isWhitespace(firstChar)) {
return null;
}
if (firstChar == '\'') {
// workbookName or sheetName needs quoting
// quotes go around both
if (text.charAt(lastIx) != '\'') {
return null;
}
firstChar = text.charAt(1);
if (Character.isWhitespace(firstChar)) {
return null;
}
String wbName;
int sheetStartPos;
if (firstChar == '[') {
int rbPos = text.toString().lastIndexOf(']');
if (rbPos < 0) {
return null;
}
wbName = unescapeString(text.subSequence(2, rbPos));
if (wbName == null || canTrim(wbName)) {
return null;
}
sheetStartPos = rbPos + 1;
} else {
wbName = null;
sheetStartPos = 1;
}
/**
* @return array of length 2: {workbookName, sheetName,}. Second element will always be
* present. First element may be null if sheetName is unqualified.
* Returns <code>null</code> if text cannot be parsed.
*/
private static String[] parseWorkbookAndSheetName(CharSequence text) {
int lastIx = text.length() - 1;
if (lastIx < 0) {
return null;
}
if (canTrim(text)) {
return null;
}
char firstChar = text.charAt(0);
if (Character.isWhitespace(firstChar)) {
return null;
}
if (firstChar == '\'') {
// workbookName or sheetName needs quoting
// quotes go around both
if (text.charAt(lastIx) != '\'') {
return null;
}
firstChar = text.charAt(1);
if (Character.isWhitespace(firstChar)) {
return null;
}
String wbName;
int sheetStartPos;
if (firstChar == '[') {
int rbPos = text.toString().lastIndexOf(']');
if (rbPos < 0) {
return null;
}
wbName = unescapeString(text.subSequence(2, rbPos));
if (wbName == null || canTrim(wbName)) {
return null;
}
sheetStartPos = rbPos + 1;
} else {
wbName = null;
sheetStartPos = 1;
}

// else - just sheet name
String sheetName = unescapeString(text.subSequence(sheetStartPos, lastIx));
if (sheetName == null) { // note - when quoted, sheetName can
// start/end with whitespace
return null;
}
return new String[] { wbName, sheetName, };
}
// else - just sheet name
String sheetName = unescapeString(text.subSequence(sheetStartPos, lastIx));
if (sheetName == null) { // note - when quoted, sheetName can
// start/end with whitespace
return null;
}
return new String[] { wbName, sheetName, };
}

if (firstChar == '[') {
int rbPos = text.toString().lastIndexOf(']');
if (rbPos < 0) {
return null;
}
CharSequence wbName = text.subSequence(1, rbPos);
if (canTrim(wbName)) {
return null;
}
CharSequence sheetName = text.subSequence(rbPos + 1, text.length());
if (canTrim(sheetName)) {
return null;
}
return new String[] { wbName.toString(), sheetName.toString(), };
}
// else - just sheet name
return new String[] { null, text.toString(), };
}
if (firstChar == '[') {
int rbPos = text.toString().lastIndexOf(']');
if (rbPos < 0) {
return null;
}
CharSequence wbName = text.subSequence(1, rbPos);
if (canTrim(wbName)) {
return null;
}
CharSequence sheetName = text.subSequence(rbPos + 1, text.length());
if (canTrim(sheetName)) {
return null;
}
return new String[] { wbName.toString(), sheetName.toString(), };
}
// else - just sheet name
return new String[] { null, text.toString(), };
}

/**
* @return <code>null</code> if there is a syntax error in any escape sequence
* (the typical syntax error is a single quote character not followed by another).
*/
private static String unescapeString(CharSequence text) {
int len = text.length();
StringBuilder sb = new StringBuilder(len);
int i = 0;
while (i < len) {
char ch = text.charAt(i);
if (ch == '\'') {
// every quote must be followed by another
i++;
if (i >= len) {
return null;
}
ch = text.charAt(i);
if (ch != '\'') {
return null;
}
}
sb.append(ch);
i++;
}
return sb.toString();
}
/**
* @return <code>null</code> if there is a syntax error in any escape sequence
* (the typical syntax error is a single quote character not followed by another).
*/
private static String unescapeString(CharSequence text) {
int len = text.length();
StringBuilder sb = new StringBuilder(len);
int i = 0;
while (i < len) {
char ch = text.charAt(i);
if (ch == '\'') {
// every quote must be followed by another
i++;
if (i >= len) {
return null;
}
ch = text.charAt(i);
if (ch != '\'') {
return null;
}
}
sb.append(ch);
i++;
}
return sb.toString();
}

private static boolean canTrim(CharSequence text) {
int lastIx = text.length() - 1;
if (lastIx < 0) {
return false;
}
if (Character.isWhitespace(text.charAt(0))) {
return true;
}
if (Character.isWhitespace(text.charAt(lastIx))) {
return true;
}
return false;
}
private static boolean canTrim(CharSequence text) {
int lastIx = text.length() - 1;
if (lastIx < 0) {
return false;
}
if (Character.isWhitespace(text.charAt(0))) {
return true;
}
if (Character.isWhitespace(text.charAt(lastIx))) {
return true;
}
return false;
}
}

+ 4
- 4
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFCell.java View File

@@ -406,9 +406,9 @@ public final class XSSFCell implements Cell {
if (cachedValueType != expectedTypeCode) {
throw typeMismatch(expectedTypeCode, cachedValueType, true);
}
}
}

/**
/**
* Set a string value for the cell.
*
* @param str value to set the cell to. For formulas we'll set the formula
@@ -925,8 +925,8 @@ public final class XSSFCell implements Cell {
throw new IllegalArgumentException("Illegal cell type: " + cellType);
}
if (cellType != CELL_TYPE_FORMULA && _cell.isSetF()) {
_cell.unsetF();
}
_cell.unsetF();
}
}

/**

+ 90
- 90
src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java View File

@@ -1762,7 +1762,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
* Get the document's embedded files.
*/
@Override
public List<PackagePart> getAllEmbedds() throws OpenXML4JException {
public List<PackagePart> getAllEmbedds() throws OpenXML4JException {
List<PackagePart> embedds = new LinkedList<PackagePart>();

for(XSSFSheet sheet : sheets){
@@ -1929,7 +1929,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
*/
@Internal
public MapInfo getMapInfo(){
return mapInfo;
return mapInfo;
}

/**
@@ -1946,92 +1946,92 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
throw new RuntimeException("Not Implemented - see bug #57184");
}

/**
* Specifies a boolean value that indicates whether structure of workbook is locked. <br/>
* A value true indicates the structure of the workbook is locked. Worksheets in the workbook can't be moved,
* deleted, hidden, unhidden, or renamed, and new worksheets can't be inserted.<br/>
* A value of false indicates the structure of the workbook is not locked.<br/>
*
* @return true if structure of workbook is locked
*/
public boolean isStructureLocked() {
return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockStructure();
}
/**
* Specifies a boolean value that indicates whether the windows that comprise the workbook are locked. <br/>
* A value of true indicates the workbook windows are locked. Windows are the same size and position each time the
* workbook is opened.<br/>
* A value of false indicates the workbook windows are not locked.
*
* @return true if windows that comprise the workbook are locked
*/
public boolean isWindowsLocked() {
return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockWindows();
}
/**
* Specifies a boolean value that indicates whether the workbook is locked for revisions.
*
* @return true if the workbook is locked for revisions.
*/
public boolean isRevisionLocked() {
return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockRevision();
}
/**
* Locks the structure of workbook.
*/
public void lockStructure() {
safeGetWorkbookProtection().setLockStructure(true);
}
/**
* Unlocks the structure of workbook.
*/
public void unLockStructure() {
safeGetWorkbookProtection().setLockStructure(false);
}
/**
* Locks the windows that comprise the workbook.
*/
public void lockWindows() {
safeGetWorkbookProtection().setLockWindows(true);
}
/**
* Unlocks the windows that comprise the workbook.
*/
public void unLockWindows() {
safeGetWorkbookProtection().setLockWindows(false);
}
/**
* Locks the workbook for revisions.
*/
public void lockRevision() {
safeGetWorkbookProtection().setLockRevision(true);
}
/**
* Unlocks the workbook for revisions.
*/
public void unLockRevision() {
safeGetWorkbookProtection().setLockRevision(false);
}
/**
* Sets the workbook password.
*
* @param password if null, the password will be removed
* @param hashAlgo if null, the password will be set as XOR password (Excel 2010 and earlier)
* otherwise the given algorithm is used for calculating the hash password (Excel 2013)
*/
public void setWorkbookPassword(String password, HashAlgorithm hashAlgo) {
/**
* Specifies a boolean value that indicates whether structure of workbook is locked. <br/>
* A value true indicates the structure of the workbook is locked. Worksheets in the workbook can't be moved,
* deleted, hidden, unhidden, or renamed, and new worksheets can't be inserted.<br/>
* A value of false indicates the structure of the workbook is not locked.<br/>
*
* @return true if structure of workbook is locked
*/
public boolean isStructureLocked() {
return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockStructure();
}
/**
* Specifies a boolean value that indicates whether the windows that comprise the workbook are locked. <br/>
* A value of true indicates the workbook windows are locked. Windows are the same size and position each time the
* workbook is opened.<br/>
* A value of false indicates the workbook windows are not locked.
*
* @return true if windows that comprise the workbook are locked
*/
public boolean isWindowsLocked() {
return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockWindows();
}
/**
* Specifies a boolean value that indicates whether the workbook is locked for revisions.
*
* @return true if the workbook is locked for revisions.
*/
public boolean isRevisionLocked() {
return workbookProtectionPresent() && workbook.getWorkbookProtection().getLockRevision();
}
/**
* Locks the structure of workbook.
*/
public void lockStructure() {
safeGetWorkbookProtection().setLockStructure(true);
}
/**
* Unlocks the structure of workbook.
*/
public void unLockStructure() {
safeGetWorkbookProtection().setLockStructure(false);
}
/**
* Locks the windows that comprise the workbook.
*/
public void lockWindows() {
safeGetWorkbookProtection().setLockWindows(true);
}
/**
* Unlocks the windows that comprise the workbook.
*/
public void unLockWindows() {
safeGetWorkbookProtection().setLockWindows(false);
}
/**
* Locks the workbook for revisions.
*/
public void lockRevision() {
safeGetWorkbookProtection().setLockRevision(true);
}
/**
* Unlocks the workbook for revisions.
*/
public void unLockRevision() {
safeGetWorkbookProtection().setLockRevision(false);
}
/**
* Sets the workbook password.
*
* @param password if null, the password will be removed
* @param hashAlgo if null, the password will be set as XOR password (Excel 2010 and earlier)
* otherwise the given algorithm is used for calculating the hash password (Excel 2013)
*/
public void setWorkbookPassword(String password, HashAlgorithm hashAlgo) {
if (password == null && !workbookProtectionPresent()) return;
setPassword(safeGetWorkbookProtection(), password, hashAlgo, "workbook");
}
}

/**
* Validate the password against the stored hash, the hashing method will be determined
@@ -2074,9 +2074,9 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
}
}
private boolean workbookProtectionPresent() {
return workbook.isSetWorkbookProtection();
}
private boolean workbookProtectionPresent() {
return workbook.isSetWorkbookProtection();
}

private CTWorkbookProtection safeGetWorkbookProtection() {
if (!workbookProtectionPresent()){
@@ -2084,7 +2084,7 @@ public class XSSFWorkbook extends POIXMLDocument implements Workbook {
}
return workbook.getWorkbookProtection();
}
/**
*
* Returns the locator of user-defined functions.

+ 166
- 166
src/testcases/org/apache/poi/hssf/record/TestSharedFormulaRecord.java View File

@@ -38,67 +38,67 @@ import org.apache.poi.util.LittleEndianInput;
*/
public final class TestSharedFormulaRecord extends TestCase {

/**
* A sample spreadsheet known to have one sheet with 4 shared formula ranges
*/
private static final String SHARED_FORMULA_TEST_XLS = "SharedFormulaTest.xls";
/**
* Binary data for an encoded formula. Taken from attachment 22062 (bugzilla 45123/45421).
* The shared formula is in Sheet1!C6:C21, with text "SUMPRODUCT(--(End_Acct=$C6),--(End_Bal))"
* This data is found at offset 0x1A4A (within the shared formula record).
* The critical thing about this formula is that it contains shared formula tokens (tRefN*,
* tAreaN*) with operand class 'array'.
*/
private static final byte[] SHARED_FORMULA_WITH_REF_ARRAYS_DATA = {
0x1A, 0x00,
0x63, 0x02, 0x00, 0x00, 0x00,
0x6C, 0x00, 0x00, 0x02, (byte)0x80, // tRefNA
0x0B,
0x15,
0x13,
0x13,
0x63, 0x03, 0x00, 0x00, 0x00,
0x15,
0x13,
0x13,
0x42, 0x02, (byte)0xE4, 0x00,
};
/**
* The method <tt>SharedFormulaRecord.convertSharedFormulas()</tt> converts formulas from
* 'shared formula' to 'single cell formula' format. It is important that token operand
* classes are preserved during this transformation, because Excel may not tolerate the
* incorrect encoding. The formula here is one such example (Excel displays #VALUE!).
*/
public void testConvertSharedFormulasOperandClasses_bug45123() {
LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
int encodedLen = in.readUShort();
Ptg[] sharedFormula = Ptg.readTokens(encodedLen, in);
/**
* A sample spreadsheet known to have one sheet with 4 shared formula ranges
*/
private static final String SHARED_FORMULA_TEST_XLS = "SharedFormulaTest.xls";
/**
* Binary data for an encoded formula. Taken from attachment 22062 (bugzilla 45123/45421).
* The shared formula is in Sheet1!C6:C21, with text "SUMPRODUCT(--(End_Acct=$C6),--(End_Bal))"
* This data is found at offset 0x1A4A (within the shared formula record).
* The critical thing about this formula is that it contains shared formula tokens (tRefN*,
* tAreaN*) with operand class 'array'.
*/
private static final byte[] SHARED_FORMULA_WITH_REF_ARRAYS_DATA = {
0x1A, 0x00,
0x63, 0x02, 0x00, 0x00, 0x00,
0x6C, 0x00, 0x00, 0x02, (byte)0x80, // tRefNA
0x0B,
0x15,
0x13,
0x13,
0x63, 0x03, 0x00, 0x00, 0x00,
0x15,
0x13,
0x13,
0x42, 0x02, (byte)0xE4, 0x00,
};
/**
* The method <tt>SharedFormulaRecord.convertSharedFormulas()</tt> converts formulas from
* 'shared formula' to 'single cell formula' format. It is important that token operand
* classes are preserved during this transformation, because Excel may not tolerate the
* incorrect encoding. The formula here is one such example (Excel displays #VALUE!).
*/
public void testConvertSharedFormulasOperandClasses_bug45123() {
LittleEndianInput in = TestcaseRecordInputStream.createLittleEndian(SHARED_FORMULA_WITH_REF_ARRAYS_DATA);
int encodedLen = in.readUShort();
Ptg[] sharedFormula = Ptg.readTokens(encodedLen, in);

SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL97);
Ptg[] convertedFormula = sf.convertSharedFormulas(sharedFormula, 100, 200);
RefPtg refPtg = (RefPtg) convertedFormula[1];
assertEquals("$C101", refPtg.toFormulaString());
if (refPtg.getPtgClass() == Ptg.CLASS_REF) {
throw new AssertionFailedError("Identified bug 45123");
}
confirmOperandClasses(sharedFormula, convertedFormula);
}
private static void confirmOperandClasses(Ptg[] originalPtgs, Ptg[] convertedPtgs) {
assertEquals(originalPtgs.length, convertedPtgs.length);
for (int i = 0; i < convertedPtgs.length; i++) {
Ptg originalPtg = originalPtgs[i];
Ptg convertedPtg = convertedPtgs[i];
if (originalPtg.getPtgClass() != convertedPtg.getPtgClass()) {
throw new ComparisonFailure("Different operand class for token[" + i + "]",
String.valueOf(originalPtg.getPtgClass()), String.valueOf(convertedPtg.getPtgClass()));
}
}
}
Ptg[] convertedFormula = sf.convertSharedFormulas(sharedFormula, 100, 200);
RefPtg refPtg = (RefPtg) convertedFormula[1];
assertEquals("$C101", refPtg.toFormulaString());
if (refPtg.getPtgClass() == Ptg.CLASS_REF) {
throw new AssertionFailedError("Identified bug 45123");
}
confirmOperandClasses(sharedFormula, convertedFormula);
}
private static void confirmOperandClasses(Ptg[] originalPtgs, Ptg[] convertedPtgs) {
assertEquals(originalPtgs.length, convertedPtgs.length);
for (int i = 0; i < convertedPtgs.length; i++) {
Ptg originalPtg = originalPtgs[i];
Ptg convertedPtg = convertedPtgs[i];
if (originalPtg.getPtgClass() != convertedPtg.getPtgClass()) {
throw new ComparisonFailure("Different operand class for token[" + i + "]",
String.valueOf(originalPtg.getPtgClass()), String.valueOf(convertedPtg.getPtgClass()));
}
}
}

public void testConvertSharedFormulas() {
HSSFWorkbook wb = new HSSFWorkbook();
@@ -138,111 +138,111 @@ public final class TestSharedFormulaRecord extends TestCase {
}

/**
* Make sure that POI preserves {@link SharedFormulaRecord}s
*/
public void testPreserveOnReserialize() {
HSSFWorkbook wb;
HSSFSheet sheet;
HSSFCell cellB32769;
HSSFCell cellC32769;
// Reading directly from XLS file
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
cellB32769 = sheet.getRow(32768).getCell(1);
cellC32769 = sheet.getRow(32768).getCell(2);
// check reading of formulas which are shared (two cells from a 1R x 8C range)
assertEquals("B32770*2", cellB32769.getCellFormula());
assertEquals("C32770*2", cellC32769.getCellFormula());
confirmCellEvaluation(wb, cellB32769, 4);
confirmCellEvaluation(wb, cellC32769, 6);
// Confirm this example really does have SharedFormulas.
// there are 3 others besides the one at A32769:H32769
assertEquals(4, countSharedFormulas(sheet));
// Re-serialize and check again
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
cellB32769 = sheet.getRow(32768).getCell(1);
cellC32769 = sheet.getRow(32768).getCell(2);
assertEquals("B32770*2", cellB32769.getCellFormula());
confirmCellEvaluation(wb, cellB32769, 4);
assertEquals(4, countSharedFormulas(sheet));
}
public void testUnshareFormulaDueToChangeFormula() {
HSSFWorkbook wb;
HSSFSheet sheet;
HSSFCell cellB32769;
HSSFCell cellC32769;
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
cellB32769 = sheet.getRow(32768).getCell(1);
cellC32769 = sheet.getRow(32768).getCell(2);
// Updating cell formula, causing it to become unshared
cellB32769.setCellFormula("1+1");
confirmCellEvaluation(wb, cellB32769, 2);
// currently (Oct 2008) POI handles this by exploding the whole shared formula group
assertEquals(3, countSharedFormulas(sheet)); // one less now
// check that nearby cell of the same group still has the same formula
assertEquals("C32770*2", cellC32769.getCellFormula());
confirmCellEvaluation(wb, cellC32769, 6);
}
public void testUnshareFormulaDueToDelete() {
HSSFWorkbook wb;
HSSFSheet sheet;
HSSFCell cell;
final int ROW_IX = 2;
// changing shared formula cell to blank
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX).getCell(1).getCellFormula());
cell = sheet.getRow(ROW_IX).getCell(1);
cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
assertEquals(3, countSharedFormulas(sheet));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX+1).getCell(1).getCellFormula());
// deleting shared formula cell
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX).getCell(1).getCellFormula());
cell = sheet.getRow(ROW_IX).getCell(1);
sheet.getRow(ROW_IX).removeCell(cell);
assertEquals(3, countSharedFormulas(sheet));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX+1).getCell(1).getCellFormula());
}
private static void confirmCellEvaluation(HSSFWorkbook wb, HSSFCell cell, double expectedValue) {
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
CellValue cv = fe.evaluate(cell);
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
assertEquals(expectedValue, cv.getNumberValue(), 0.0);
}
/**
* @return the number of {@link SharedFormulaRecord}s encoded for the specified sheet
*/
private static int countSharedFormulas(HSSFSheet sheet) {
Record[] records = RecordInspector.getRecords(sheet, 0);
int count = 0;
for (int i = 0; i < records.length; i++) {
Record rec = records[i];
if(rec instanceof SharedFormulaRecord) {
count++;
}
}
return count;
}
* Make sure that POI preserves {@link SharedFormulaRecord}s
*/
public void testPreserveOnReserialize() {
HSSFWorkbook wb;
HSSFSheet sheet;
HSSFCell cellB32769;
HSSFCell cellC32769;
// Reading directly from XLS file
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
cellB32769 = sheet.getRow(32768).getCell(1);
cellC32769 = sheet.getRow(32768).getCell(2);
// check reading of formulas which are shared (two cells from a 1R x 8C range)
assertEquals("B32770*2", cellB32769.getCellFormula());
assertEquals("C32770*2", cellC32769.getCellFormula());
confirmCellEvaluation(wb, cellB32769, 4);
confirmCellEvaluation(wb, cellC32769, 6);
// Confirm this example really does have SharedFormulas.
// there are 3 others besides the one at A32769:H32769
assertEquals(4, countSharedFormulas(sheet));
// Re-serialize and check again
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
cellB32769 = sheet.getRow(32768).getCell(1);
cellC32769 = sheet.getRow(32768).getCell(2);
assertEquals("B32770*2", cellB32769.getCellFormula());
confirmCellEvaluation(wb, cellB32769, 4);
assertEquals(4, countSharedFormulas(sheet));
}
public void testUnshareFormulaDueToChangeFormula() {
HSSFWorkbook wb;
HSSFSheet sheet;
HSSFCell cellB32769;
HSSFCell cellC32769;
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
cellB32769 = sheet.getRow(32768).getCell(1);
cellC32769 = sheet.getRow(32768).getCell(2);
// Updating cell formula, causing it to become unshared
cellB32769.setCellFormula("1+1");
confirmCellEvaluation(wb, cellB32769, 2);
// currently (Oct 2008) POI handles this by exploding the whole shared formula group
assertEquals(3, countSharedFormulas(sheet)); // one less now
// check that nearby cell of the same group still has the same formula
assertEquals("C32770*2", cellC32769.getCellFormula());
confirmCellEvaluation(wb, cellC32769, 6);
}
public void testUnshareFormulaDueToDelete() {
HSSFWorkbook wb;
HSSFSheet sheet;
HSSFCell cell;
final int ROW_IX = 2;
// changing shared formula cell to blank
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX).getCell(1).getCellFormula());
cell = sheet.getRow(ROW_IX).getCell(1);
cell.setCellType(HSSFCell.CELL_TYPE_BLANK);
assertEquals(3, countSharedFormulas(sheet));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX+1).getCell(1).getCellFormula());
// deleting shared formula cell
wb = HSSFTestDataSamples.openSampleWorkbook(SHARED_FORMULA_TEST_XLS);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX).getCell(1).getCellFormula());
cell = sheet.getRow(ROW_IX).getCell(1);
sheet.getRow(ROW_IX).removeCell(cell);
assertEquals(3, countSharedFormulas(sheet));
wb = HSSFTestDataSamples.writeOutAndReadBack(wb);
sheet = wb.getSheetAt(0);
assertEquals("A$1*2", sheet.getRow(ROW_IX+1).getCell(1).getCellFormula());
}
private static void confirmCellEvaluation(HSSFWorkbook wb, HSSFCell cell, double expectedValue) {
HSSFFormulaEvaluator fe = new HSSFFormulaEvaluator(wb);
CellValue cv = fe.evaluate(cell);
assertEquals(HSSFCell.CELL_TYPE_NUMERIC, cv.getCellType());
assertEquals(expectedValue, cv.getNumberValue(), 0.0);
}
/**
* @return the number of {@link SharedFormulaRecord}s encoded for the specified sheet
*/
private static int countSharedFormulas(HSSFSheet sheet) {
Record[] records = RecordInspector.getRecords(sheet, 0);
int count = 0;
for (int i = 0; i < records.length; i++) {
Record rec = records[i];
if(rec instanceof SharedFormulaRecord) {
count++;
}
}
return count;
}
}

Loading…
Cancel
Save