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:
Dominik Stadler 2016-12-31 16:53:16 +00:00
parent 1350ad3eb3
commit 102c0d2173
5 changed files with 50 additions and 43 deletions

View File

@ -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

View File

@ -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();

View File

@ -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);

View File

@ -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", },

View File

@ -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();
} }