Bug 60219: FormulaParser can't parse external references when sheet name is quoted
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1776796 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
1350ad3eb3
commit
102c0d2173
@ -115,7 +115,7 @@ public final class FormulaParser {
|
|||||||
* Tracks whether the run of whitespace preceding "look" could be an
|
* Tracks whether the run of whitespace preceding "look" could be an
|
||||||
* intersection operator. See GetChar.
|
* intersection operator. See GetChar.
|
||||||
*/
|
*/
|
||||||
private boolean _inIntersection = false;
|
private boolean _inIntersection;
|
||||||
|
|
||||||
private final FormulaParsingWorkbook _book;
|
private final FormulaParsingWorkbook _book;
|
||||||
private final SpreadsheetVersion _ssVersion;
|
private final SpreadsheetVersion _ssVersion;
|
||||||
@ -133,7 +133,7 @@ public final class FormulaParser {
|
|||||||
* This class is recommended only for single threaded use.
|
* This class is recommended only for single threaded use.
|
||||||
*
|
*
|
||||||
* If you have a {@link org.apache.poi.hssf.usermodel.HSSFWorkbook}, and not a
|
* If you have a {@link org.apache.poi.hssf.usermodel.HSSFWorkbook}, and not a
|
||||||
* {@link org.apache.poi.hssf.model.Workbook}, then use the convenience method on
|
* {@link org.apache.poi.ss.usermodel.Workbook}, then use the convenience method on
|
||||||
* {@link org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator}
|
* {@link org.apache.poi.hssf.usermodel.HSSFFormulaEvaluator}
|
||||||
*/
|
*/
|
||||||
private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex, int rowIndex) {
|
private FormulaParser(String formula, FormulaParsingWorkbook book, int sheetIndex, int rowIndex) {
|
||||||
@ -298,7 +298,7 @@ public final class FormulaParser {
|
|||||||
|
|
||||||
/** Get a Number */
|
/** Get a Number */
|
||||||
private String GetNum() {
|
private String GetNum() {
|
||||||
StringBuffer value = new StringBuffer();
|
StringBuilder value = new StringBuilder();
|
||||||
|
|
||||||
while (IsDigit(this.look)){
|
while (IsDigit(this.look)){
|
||||||
value.append(this.look);
|
value.append(this.look);
|
||||||
@ -670,7 +670,7 @@ public final class FormulaParser {
|
|||||||
GetChar();
|
GetChar();
|
||||||
}
|
}
|
||||||
// parse column quantifier
|
// parse column quantifier
|
||||||
String startColumnName = null;
|
String startColumnName;
|
||||||
String endColumnName = null;
|
String endColumnName = null;
|
||||||
int nColQuantifiers = 0;
|
int nColQuantifiers = 0;
|
||||||
int savePtr1 = _pointer;
|
int savePtr1 = _pointer;
|
||||||
@ -1112,14 +1112,21 @@ public final class FormulaParser {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public String toString() {
|
public String toString() {
|
||||||
StringBuilder sb = new StringBuilder(64);
|
return getClass().getName() + " [" + _rep + "]";
|
||||||
sb.append(getClass().getName()).append(" [");
|
|
||||||
sb.append(_rep);
|
|
||||||
sb.append("]");
|
|
||||||
return sb.toString();
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private String getBookName() {
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
|
GetChar();
|
||||||
|
while (look != ']') {
|
||||||
|
sb.append(look);
|
||||||
|
GetChar();
|
||||||
|
}
|
||||||
|
GetChar();
|
||||||
|
return sb.toString();
|
||||||
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Note - caller should reset {@link #_pointer} upon <code>null</code> result
|
* Note - caller should reset {@link #_pointer} upon <code>null</code> result
|
||||||
* @return The sheet name as an identifier <code>null</code> if '!' is not found in the right place
|
* @return The sheet name as an identifier <code>null</code> if '!' is not found in the right place
|
||||||
@ -1127,22 +1134,18 @@ public final class FormulaParser {
|
|||||||
private SheetIdentifier parseSheetName() {
|
private SheetIdentifier parseSheetName() {
|
||||||
String bookName;
|
String bookName;
|
||||||
if (look == '[') {
|
if (look == '[') {
|
||||||
StringBuilder sb = new StringBuilder();
|
bookName = getBookName();
|
||||||
GetChar();
|
|
||||||
while (look != ']') {
|
|
||||||
sb.append(look);
|
|
||||||
GetChar();
|
|
||||||
}
|
|
||||||
GetChar();
|
|
||||||
bookName = sb.toString();
|
|
||||||
} else {
|
} else {
|
||||||
bookName = null;
|
bookName = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (look == '\'') {
|
if (look == '\'') {
|
||||||
StringBuffer sb = new StringBuffer();
|
|
||||||
|
|
||||||
Match('\'');
|
Match('\'');
|
||||||
|
|
||||||
|
if (look == '[')
|
||||||
|
bookName = getBookName();
|
||||||
|
|
||||||
|
StringBuilder sb = new StringBuilder();
|
||||||
boolean done = look == '\'';
|
boolean done = look == '\'';
|
||||||
while(!done) {
|
while(!done) {
|
||||||
sb.append(look);
|
sb.append(look);
|
||||||
@ -1232,7 +1235,7 @@ public final class FormulaParser {
|
|||||||
boolean result = CellReference.classifyCellReference(str, _ssVersion) == NameType.CELL;
|
boolean result = CellReference.classifyCellReference(str, _ssVersion) == NameType.CELL;
|
||||||
|
|
||||||
if(result){
|
if(result){
|
||||||
/**
|
/*
|
||||||
* Check if the argument is a function. Certain names can be either a cell reference or a function name
|
* Check if the argument is a function. Certain names can be either a cell reference or a function name
|
||||||
* depending on the contenxt. Compare the following examples in Excel 2007:
|
* depending on the contenxt. Compare the following examples in Excel 2007:
|
||||||
* (a) LOG10(100) + 1
|
* (a) LOG10(100) + 1
|
||||||
@ -1323,7 +1326,7 @@ public final class FormulaParser {
|
|||||||
* Adds a name (named range or user defined function) to underlying workbook's names table
|
* Adds a name (named range or user defined function) to underlying workbook's names table
|
||||||
* @param functionName
|
* @param functionName
|
||||||
*/
|
*/
|
||||||
private final void addName(String functionName) {
|
private void addName(String functionName) {
|
||||||
final Name name = _book.createName();
|
final Name name = _book.createName();
|
||||||
name.setFunction(true);
|
name.setFunction(true);
|
||||||
name.setNameName(functionName);
|
name.setNameName(functionName);
|
||||||
@ -1766,7 +1769,7 @@ public final class FormulaParser {
|
|||||||
* return Int or Number Ptg based on size of input
|
* return Int or Number Ptg based on size of input
|
||||||
*/
|
*/
|
||||||
private static Ptg getNumberPtgFromString(String number1, String number2, String exponent) {
|
private static Ptg getNumberPtgFromString(String number1, String number2, String exponent) {
|
||||||
StringBuffer number = new StringBuffer();
|
StringBuilder number = new StringBuilder();
|
||||||
|
|
||||||
if (number2 == null) {
|
if (number2 == null) {
|
||||||
number.append(number1);
|
number.append(number1);
|
||||||
@ -1808,7 +1811,7 @@ public final class FormulaParser {
|
|||||||
private String parseStringLiteral() {
|
private String parseStringLiteral() {
|
||||||
Match('"');
|
Match('"');
|
||||||
|
|
||||||
StringBuffer token = new StringBuffer();
|
StringBuilder token = new StringBuilder();
|
||||||
while (true) {
|
while (true) {
|
||||||
if (look == '"') {
|
if (look == '"') {
|
||||||
GetChar();
|
GetChar();
|
||||||
@ -1975,7 +1978,7 @@ public final class FormulaParser {
|
|||||||
|
|
||||||
//{--------------------------------------------------------------}
|
//{--------------------------------------------------------------}
|
||||||
//{ Parse and Translate an Assignment Statement }
|
//{ Parse and Translate an Assignment Statement }
|
||||||
/**
|
/*
|
||||||
procedure Assignment;
|
procedure Assignment;
|
||||||
var Name: string[8];
|
var Name: string[8];
|
||||||
begin
|
begin
|
||||||
|
@ -33,7 +33,6 @@ import org.apache.poi.ss.formula.ptg.StringPtg;
|
|||||||
import org.apache.poi.xssf.XSSFTestDataSamples;
|
import org.apache.poi.xssf.XSSFTestDataSamples;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFEvaluationWorkbook;
|
||||||
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
import org.apache.poi.xssf.usermodel.XSSFWorkbook;
|
||||||
import org.junit.Ignore;
|
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -189,7 +188,6 @@ public class TestFormulaParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// bug 60219: FormulaParser can't parse external references when sheet name is quoted
|
// bug 60219: FormulaParser can't parse external references when sheet name is quoted
|
||||||
@Ignore
|
|
||||||
@Test
|
@Test
|
||||||
public void testParseExternalReferencesWithQuotedSheetName() throws Exception {
|
public void testParseExternalReferencesWithQuotedSheetName() throws Exception {
|
||||||
XSSFWorkbook wb = new XSSFWorkbook();
|
XSSFWorkbook wb = new XSSFWorkbook();
|
||||||
|
@ -218,7 +218,7 @@ public final class TestFormulaParser {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private final static void assertEqualsIgnoreCase(String expected, String actual) {
|
private static void assertEqualsIgnoreCase(String expected, String actual) {
|
||||||
assertEquals(expected.toLowerCase(Locale.ROOT), actual.toLowerCase(Locale.ROOT));
|
assertEquals(expected.toLowerCase(Locale.ROOT), actual.toLowerCase(Locale.ROOT));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -414,7 +414,7 @@ public final class TestFormulaParser {
|
|||||||
HSSFSheet sheet = wb.createSheet("Test");
|
HSSFSheet sheet = wb.createSheet("Test");
|
||||||
HSSFRow row = sheet.createRow(0);
|
HSSFRow row = sheet.createRow(0);
|
||||||
HSSFCell cell = row.createCell(0);
|
HSSFCell cell = row.createCell(0);
|
||||||
String formula = null;
|
String formula;
|
||||||
|
|
||||||
cell.setCellFormula("1.3E21/3");
|
cell.setCellFormula("1.3E21/3");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
@ -488,7 +488,7 @@ public final class TestFormulaParser {
|
|||||||
HSSFSheet sheet = wb.createSheet("Test");
|
HSSFSheet sheet = wb.createSheet("Test");
|
||||||
HSSFRow row = sheet.createRow(0);
|
HSSFRow row = sheet.createRow(0);
|
||||||
HSSFCell cell = row.createCell(0);
|
HSSFCell cell = row.createCell(0);
|
||||||
String formula = null;
|
String formula;
|
||||||
|
|
||||||
// starts from decimal point
|
// starts from decimal point
|
||||||
|
|
||||||
@ -530,7 +530,7 @@ public final class TestFormulaParser {
|
|||||||
HSSFSheet sheet = wb.createSheet("Test");
|
HSSFSheet sheet = wb.createSheet("Test");
|
||||||
HSSFRow row = sheet.createRow(0);
|
HSSFRow row = sheet.createRow(0);
|
||||||
HSSFCell cell = row.createCell(0);
|
HSSFCell cell = row.createCell(0);
|
||||||
String formula = null;
|
String formula;
|
||||||
|
|
||||||
cell.setCellFormula("A1.A2");
|
cell.setCellFormula("A1.A2");
|
||||||
formula = cell.getCellFormula();
|
formula = cell.getCellFormula();
|
||||||
@ -557,7 +557,7 @@ public final class TestFormulaParser {
|
|||||||
HSSFSheet sheet = wb.createSheet("Test");
|
HSSFSheet sheet = wb.createSheet("Test");
|
||||||
HSSFRow row = sheet.createRow(0);
|
HSSFRow row = sheet.createRow(0);
|
||||||
HSSFCell cell = row.createCell(0);
|
HSSFCell cell = row.createCell(0);
|
||||||
String formula = null;
|
String formula;
|
||||||
|
|
||||||
|
|
||||||
// References to a single cell:
|
// References to a single cell:
|
||||||
@ -718,8 +718,8 @@ public final class TestFormulaParser {
|
|||||||
assertEquals(65534.6, np.getValue(), 0);
|
assertEquals(65534.6, np.getValue(), 0);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test
|
||||||
public void testMissingArgs() {
|
public void testMissingArgs() {
|
||||||
|
|
||||||
confirmTokenClasses("if(A1, ,C1)",
|
confirmTokenClasses("if(A1, ,C1)",
|
||||||
RefPtg.class,
|
RefPtg.class,
|
||||||
AttrPtg.class, // tAttrIf
|
AttrPtg.class, // tAttrIf
|
||||||
@ -1327,8 +1327,7 @@ public final class TestFormulaParser {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* TODO - delete equiv test:
|
* See the related/similar test: {@link BaseTestBugzillaIssues#bug42448()}
|
||||||
* {@link BaseTestBugzillaIssues#test42448()}
|
|
||||||
*/
|
*/
|
||||||
@Test
|
@Test
|
||||||
public void testParseAbnormalSheetNamesAndRanges_bug42448() throws IOException {
|
public void testParseAbnormalSheetNamesAndRanges_bug42448() throws IOException {
|
||||||
@ -1373,11 +1372,10 @@ public final class TestFormulaParser {
|
|||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnionOfFullCollFullRowRef() throws IOException {
|
public void testUnionOfFullCollFullRowRef() throws IOException {
|
||||||
Ptg[] ptgs;
|
parseFormula("3:4");
|
||||||
ptgs = parseFormula("3:4");
|
Ptg[] ptgs = parseFormula("$Z:$AC");
|
||||||
ptgs = parseFormula("$Z:$AC");
|
|
||||||
confirmTokenClasses(ptgs, AreaPtg.class);
|
confirmTokenClasses(ptgs, AreaPtg.class);
|
||||||
ptgs = parseFormula("B:B");
|
parseFormula("B:B");
|
||||||
|
|
||||||
ptgs = parseFormula("$11:$13");
|
ptgs = parseFormula("$11:$13");
|
||||||
confirmTokenClasses(ptgs, AreaPtg.class);
|
confirmTokenClasses(ptgs, AreaPtg.class);
|
||||||
|
@ -115,7 +115,7 @@ public final class TestWorkbook {
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/*
|
||||||
* register the two test UDFs in a UDF finder, to be passed to the evaluator
|
* register the two test UDFs in a UDF finder, to be passed to the evaluator
|
||||||
*/
|
*/
|
||||||
UDFFinder udff1 = new DefaultUDFFinder(new String[] { "myFunc", },
|
UDFFinder udff1 = new DefaultUDFFinder(new String[] { "myFunc", },
|
||||||
|
@ -1836,17 +1836,26 @@ public final class TestBugs extends BaseTestBugzillaIssues {
|
|||||||
assertEquals("'[$http://gagravarr.org/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
|
assertEquals("'[$http://gagravarr.org/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
|
||||||
assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
|
assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
|
||||||
|
|
||||||
|
// Link our new workbook
|
||||||
|
Workbook externalWb1 = new HSSFWorkbook();
|
||||||
|
externalWb1.createSheet("Sheet1");
|
||||||
|
wb1.linkExternalWorkbook("$http://gagravarr.org/FormulaRefs2.xls", externalWb1);
|
||||||
|
|
||||||
// Change 4
|
// Change 4
|
||||||
row.getCell(1).setCellFormula("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2");
|
row.getCell(1).setCellFormula("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2");
|
||||||
row.getCell(1).setCellValue(123.0);
|
row.getCell(1).setCellValue(123.0);
|
||||||
|
|
||||||
|
// Link our new workbook
|
||||||
|
Workbook externalWb2 = new HSSFWorkbook();
|
||||||
|
externalWb2.createSheet("Sheet1");
|
||||||
|
wb1.linkExternalWorkbook("$http://example.com/FormulaRefs.xls", externalWb2);
|
||||||
|
|
||||||
// Add 5
|
// Add 5
|
||||||
row = s.createRow(5);
|
row = s.createRow(5);
|
||||||
row.createCell(1, CellType.FORMULA);
|
row.createCell(1, CellType.FORMULA);
|
||||||
row.getCell(1).setCellFormula("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1");
|
row.getCell(1).setCellFormula("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1");
|
||||||
row.getCell(1).setCellValue(234.0);
|
row.getCell(1).setCellValue(234.0);
|
||||||
|
|
||||||
|
|
||||||
// Re-test
|
// Re-test
|
||||||
HSSFWorkbook wb2 = writeOutAndReadBack(wb1);
|
HSSFWorkbook wb2 = writeOutAndReadBack(wb1);
|
||||||
wb1.close();
|
wb1.close();
|
||||||
@ -1871,8 +1880,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
|
|||||||
assertEquals("[Formulas2.xls]Sheet1!B2", row.getCell(1).getCellFormula());
|
assertEquals("[Formulas2.xls]Sheet1!B2", row.getCell(1).getCellFormula());
|
||||||
assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
|
assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
|
||||||
|
|
||||||
// TODO - Fix these so they work...
|
row = s.getRow(4);
|
||||||
/*row = s.getRow(4);
|
|
||||||
assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
|
assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
|
||||||
assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula());
|
assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula());
|
||||||
assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0);
|
assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0);
|
||||||
@ -1880,7 +1888,7 @@ public final class TestBugs extends BaseTestBugzillaIssues {
|
|||||||
row = s.getRow(5);
|
row = s.getRow(5);
|
||||||
assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
|
assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
|
||||||
assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
|
assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
|
||||||
assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0);*/
|
assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0);
|
||||||
|
|
||||||
wb2.close();
|
wb2.close();
|
||||||
}
|
}
|
||||||
|
Loading…
Reference in New Issue
Block a user