git-svn-id: https://svn.apache.org/repos/asf/poi/branches/xssf_structured_references@1747627 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_15_BETA2
@@ -68,7 +68,6 @@ public interface EvaluationWorkbook { | |||
*/ | |||
ExternalName getExternalName(String nameName, String sheetName, int externalWorkbookNumber); | |||
EvaluationName getName(NamePtg namePtg); | |||
EvaluationName getName(String name, int sheetIndex); | |||
String resolveNameXText(NameXPtg ptg); |
@@ -145,17 +145,20 @@ public final class FormulaParser { | |||
} | |||
/** | |||
* Parse a formula into a array of tokens | |||
* Side effect: creates name (Workbook.createName) if formula contains unrecognized names (names are likely UDFs) | |||
* Parse a formula into an array of tokens | |||
* Side effect: creates name ({@link org.apache.poi.ss.usermodel.Workbook#createName}) | |||
* if formula contains unrecognized names (names are likely UDFs) | |||
* | |||
* @param formula the formula to parse | |||
* @param workbook the parent workbook | |||
* @param formulaType the type of the formula, see {@link FormulaType} | |||
* @param sheetIndex the 0-based index of the sheet this formula belongs to. | |||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means that | |||
* the scope of the name will be ignored and the parser will match names only by name | |||
* @param rowIndex - the related cell's row index in 0-based form (-1 if the formula is not cell related) | |||
* used to handle structured references that have the "#This Row" quantifier. | |||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means that | |||
* the scope of the name will be ignored and the parser will match names only by name | |||
* Use rowIndex=-1 or {@link #parseStructuredReference(String, FormulaParsingWorkbook, int, int) if formula | |||
* does not contain structured references. | |||
* | |||
* @return array of parsed tokens | |||
* @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid | |||
@@ -165,7 +168,22 @@ public final class FormulaParser { | |||
fp.parse(); | |||
return fp.getRPNPtg(formulaType); | |||
} | |||
/** | |||
* Parse a formula into an array of tokens | |||
* Side effect: creates name ({@link org.apache.poi.ss.usermodel.Workbook#createName}) | |||
* if formula contains unrecognized names (names are likely UDFs) | |||
* | |||
* @param formula the formula to parse | |||
* @param workbook the parent workbook | |||
* @param formulaType the type of the formula, see {@link FormulaType} | |||
* @param sheetIndex the 0-based index of the sheet this formula belongs to. | |||
* The sheet index is required to resolve sheet-level names. <code>-1</code> means that | |||
* the scope of the name will be ignored and the parser will match names only by name | |||
* | |||
* @return array of parsed tokens | |||
* @throws FormulaParseException if the formula has incorrect syntax or is otherwise invalid | |||
*/ | |||
public static Ptg[] parse(String formula, FormulaParsingWorkbook workbook, int formulaType, int sheetIndex) { | |||
return parse(formula, workbook, formulaType, sheetIndex, -1); | |||
} | |||
@@ -180,7 +198,8 @@ public final class FormulaParser { | |||
* @return the area that being represented by the structured reference. | |||
*/ | |||
public static Area3DPxg parseStructuredReference(String tableText, FormulaParsingWorkbook workbook, int rowIndex) { | |||
Ptg[] arr = FormulaParser.parse(tableText, workbook, 0, 0, rowIndex); | |||
final int sheetIndex = -1; //don't care? | |||
Ptg[] arr = FormulaParser.parse(tableText, workbook, FormulaType.CELL, sheetIndex, rowIndex); | |||
if (arr.length != 1 || !(arr[0] instanceof Area3DPxg) ) { | |||
throw new IllegalStateException("Illegal structured reference"); | |||
} | |||
@@ -588,14 +607,14 @@ public final class FormulaParser { | |||
* @param tableName | |||
* @return | |||
*/ | |||
private ParseNode parseStructuredReference(String tableName){ | |||
private ParseNode parseStructuredReference(String tableName) { | |||
if ( ! (_ssVersion.equals(SpreadsheetVersion.EXCEL2007)) ) { | |||
throw new FormulaParseException("Strctured references work only on XSSF (Excel 2007)!"); | |||
throw new FormulaParseException("Structured references work only on XSSF (Excel 2007+)!"); | |||
} | |||
Table tbl = _book.getTable(tableName); | |||
if (tbl == null) { | |||
throw new FormulaParseException("Illegal table name!"); | |||
throw new FormulaParseException("Illegal table name!"); | |||
} | |||
String sheetName = tbl.getSheetName(); | |||
@@ -845,11 +864,9 @@ public final class FormulaParser { | |||
if (look == '(') { | |||
return function(name); | |||
} | |||
//TODO Livshen's code | |||
if(look == '['){ | |||
return parseStructuredReference(name); | |||
} | |||
//TODO End of Livshen's code | |||
if (name.equalsIgnoreCase("TRUE") || name.equalsIgnoreCase("FALSE")) { | |||
return new ParseNode(BoolPtg.valueOf(name.equalsIgnoreCase("TRUE"))); | |||
} | |||
@@ -875,7 +892,7 @@ public final class FormulaParser { | |||
// defined names may begin with a letter or underscore or backslash | |||
if (!Character.isLetter(look) && look != '_' && look != '\\') { | |||
throw expected("number, string, defined name, or table"); | |||
throw expected("number, string, defined name, or data table"); | |||
} | |||
while (isValidDefinedNameChar(look)) { | |||
sb.append(look); |
@@ -299,15 +299,6 @@ public final class WorkbookEvaluator { | |||
try { | |||
Ptg[] ptgs = _workbook.getFormulaTokens(srcCell); | |||
// System.out.println("====="); | |||
// XSSFCell c = ((XSSFEvaluationCell)srcCell).getXSSFCell(); | |||
// System.out.println("Formula is "+ c); | |||
// System.out.println("The cell is " + c.getSheet().getSheetName()+"!"+c.getReference()); | |||
// System.out.println("Evaluation tokens : "); // TODO Dlivshen remove | |||
// for (Ptg ptg : ptgs) { // TODO Dlivshen remove | |||
// System.out.println(ptg); // TODO Dlivshen remove | |||
// } // TODO Dlivshen remove | |||
// System.out.println("======"); // TODO Dlivshen remove | |||
if (evalListener == null) { | |||
result = evaluateFormula(ec, ptgs); | |||
} else { | |||
@@ -319,9 +310,9 @@ public final class WorkbookEvaluator { | |||
tracker.updateCacheResult(result); | |||
} | |||
catch (NotImplementedException e) { | |||
throw addExceptionInfo(e, sheetIndex, rowIndex, columnIndex); | |||
throw addExceptionInfo(e, sheetIndex, rowIndex, columnIndex); | |||
} catch (RuntimeException re) { | |||
if (re.getCause() instanceof WorkbookNotFoundException && _ignoreMissingWorkbooks) { | |||
if (re.getCause() instanceof WorkbookNotFoundException && _ignoreMissingWorkbooks) { | |||
logInfo(re.getCause().getMessage() + " - Continuing with cached value!"); | |||
switch(srcCell.getCachedFormulaResultType()) { | |||
case Cell.CELL_TYPE_NUMERIC: |
@@ -96,9 +96,6 @@ public final class Indirect implements FreeRefFunction { | |||
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('!'); | |||
@@ -119,17 +116,19 @@ public final class Indirect implements FreeRefFunction { | |||
refText = text.substring(plingPos + 1); | |||
} | |||
String refStrPart1; | |||
String refStrPart2; | |||
if (Table.isStructuredReference.matcher(refText).matches()) { // The argument is structured reference | |||
if (Table.isStructuredReference.matcher(refText).matches()) { | |||
// The argument is structured reference | |||
Area3DPxg areaPtg = null; | |||
try{ | |||
try { | |||
areaPtg = FormulaParser.parseStructuredReference(refText, (FormulaParsingWorkbook) ec.getWorkbook(), ec.getRowIndex()); | |||
} catch(FormulaParseException e) { | |||
} catch (FormulaParseException e) { | |||
return ErrorEval.REF_INVALID; | |||
} | |||
return ec.getArea3DEval(areaPtg); | |||
} else { // The argumnet is regular reference | |||
} else { | |||
// The argument is regular reference | |||
String refStrPart1; | |||
String refStrPart2; | |||
int colonPos = refText.indexOf(':'); | |||
if (colonPos < 0) { | |||
refStrPart1 = refText.trim(); |
@@ -315,6 +315,10 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork | |||
return _uBook.createName(); | |||
} | |||
private static String caseInsensitive(String s) { | |||
return s.toUpperCase(Locale.ROOT); | |||
} | |||
/* | |||
* TODO: data tables are stored at the workbook level in XSSF, but are bound to a single sheet. | |||
* The current code structure has them hanging off XSSFSheet, but formulas reference them | |||
@@ -336,7 +340,7 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork | |||
for (Sheet sheet : _uBook) { | |||
for (XSSFTable tbl : ((XSSFSheet)sheet).getTables()) { | |||
String lname = tbl.getName().toLowerCase(Locale.ROOT); | |||
String lname = caseInsensitive(tbl.getName()); | |||
_tableCache.put(lname, tbl); | |||
} | |||
} | |||
@@ -356,7 +360,7 @@ public abstract class BaseXSSFEvaluationWorkbook implements FormulaRenderingWork | |||
@Override | |||
public XSSFTable getTable(String name) { | |||
if (name == null) return null; | |||
String lname = name.toLowerCase(Locale.ROOT); | |||
String lname = caseInsensitive(name); | |||
return getTableCache().get(lname); | |||
} | |||
@@ -550,7 +550,7 @@ public final class XSSFCell implements Cell { | |||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); | |||
//validate through the FormulaParser | |||
FormulaParser.parse(formula, fpb, formulaType, wb.getSheetIndex(getSheet()), -1); | |||
FormulaParser.parse(formula, fpb, formulaType, wb.getSheetIndex(getSheet()), getRowIndex()); | |||
CTCellFormula f = CTCellFormula.Factory.newInstance(); | |||
f.setStringValue(formula); |
@@ -26,6 +26,7 @@ import java.util.ArrayList; | |||
import java.util.Arrays; | |||
import java.util.HashMap; | |||
import java.util.List; | |||
import java.util.Locale; | |||
import org.apache.poi.POIXMLDocumentPart; | |||
import org.apache.poi.openxml4j.opc.PackagePart; | |||
@@ -33,6 +34,7 @@ import org.apache.poi.openxml4j.opc.PackageRelationship; | |||
import org.apache.poi.ss.usermodel.Table; | |||
import org.apache.poi.ss.util.CellReference; | |||
import org.apache.poi.xssf.usermodel.helpers.XSSFXmlColumnPr; | |||
import org.apache.poi.util.StringUtil; | |||
import org.apache.xmlbeans.XmlException; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTable; | |||
import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTTableColumn; | |||
@@ -121,20 +123,22 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { | |||
* @return true if the Table element contain mappings | |||
*/ | |||
public boolean mapsTo(long id){ | |||
boolean maps =false; | |||
List<XSSFXmlColumnPr> pointers = getXmlColumnPrs(); | |||
for (XSSFXmlColumnPr pointer: pointers) { | |||
if (pointer.getMapId()==id) { | |||
maps=true; | |||
break; | |||
return true; | |||
} | |||
} | |||
return maps; | |||
return false; | |||
} | |||
/** | |||
* caches table columns for performance. | |||
* Updated via updateHeaders | |||
* @since 3.15 beta 2 | |||
*/ | |||
private CTTableColumn[] getTableColumns() { | |||
if (ctColumns == null) { | |||
ctColumns = ctTable.getTableColumns().getTableColumnArray(); | |||
@@ -146,6 +150,7 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { | |||
* | |||
* Calculates the xpath of the root element for the table. This will be the common part | |||
* of all the mapping's xpaths | |||
* Note: this function caches the result for performance. To flush the cache {@link #updateHeaders()} must be called. | |||
* | |||
* @return the xpath of the table's root element | |||
*/ | |||
@@ -176,10 +181,8 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { | |||
} | |||
} | |||
commonXPath = ""; | |||
for (int i = 1 ; i< commonTokens.length;i++) { | |||
commonXPath +="/"+commonTokens[i]; | |||
} | |||
commonTokens[0] = ""; | |||
commonXPath = StringUtil.join(commonTokens, "/"); | |||
} | |||
return commonXPath; | |||
@@ -188,6 +191,7 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { | |||
/** | |||
* Note this list is static - once read, it does not notice later changes to the underlying column structures | |||
* To clear the cache, call {@link #updateHeaders} | |||
* @return List of XSSFXmlColumnPr | |||
*/ | |||
public List<XSSFXmlColumnPr> getXmlColumnPrs() { | |||
@@ -297,7 +301,7 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { | |||
* Headers <em>must</em> be in sync, otherwise Excel will display a | |||
* "Found unreadable content" message on startup. | |||
*/ | |||
public void updateHeaders(){ | |||
public void updateHeaders() { | |||
XSSFSheet sheet = (XSSFSheet)getParent(); | |||
CellReference ref = getStartCellReference(); | |||
if(ref == null) return; | |||
@@ -317,43 +321,80 @@ public class XSSFTable extends POIXMLDocumentPart implements Table { | |||
} | |||
ctColumns = null; | |||
columnMap = null; | |||
xmlColumnPr = null; | |||
commonXPath = null; | |||
} | |||
} | |||
private static String caseInsensitive(String s) { | |||
return s.toUpperCase(Locale.ROOT); | |||
} | |||
/** | |||
* Gets the relative column index of a column in this table having the header name <code>column</code>. | |||
* The column index is relative to the left-most column in the table, 0-indexed. | |||
* Returns <code>-1</code> if <code>column</code> is not a header name in table. | |||
* | |||
* Note: this function caches column names for performance. To flush the cache (because columns | |||
* have been moved or column headers have been changed), {@link #updateHeaders()} must be called. | |||
* | |||
* @since 3.15 beta 2 | |||
*/ | |||
public int findColumnIndex(String column) { | |||
if (columnMap == null) { | |||
columnMap = new HashMap<String, Integer>(getTableColumns().length); | |||
// FIXME: replace with org.apache.commons.collections.map.CaseInsensitiveMap | |||
int count = getTableColumns().length; | |||
columnMap = new HashMap<String, Integer>(count); | |||
for (int i=0; i < getTableColumns().length; i++) { | |||
columnMap.put(getTableColumns()[i].getName().toUpperCase(), Integer.valueOf(i)); | |||
for (int i=0; i < count; i++) { | |||
String columnName = getTableColumns()[i].getName(); | |||
columnMap.put(caseInsensitive(columnName), i); | |||
} | |||
} | |||
// Table column names with special characters need a single quote escape | |||
// but the escape is not present in the column definition | |||
Integer idx = columnMap.get(column.replace("'", "").toUpperCase()); | |||
Integer idx = columnMap.get(caseInsensitive(column.replace("'", ""))); | |||
return idx == null ? -1 : idx.intValue(); | |||
} | |||
/** | |||
* @since 3.15 beta 2 | |||
*/ | |||
public String getSheetName() { | |||
return getXSSFSheet().getSheetName(); | |||
} | |||
/** | |||
* @since 3.15 beta 2 | |||
*/ | |||
public boolean isHasTotalsRow() { | |||
return ctTable.getTotalsRowShown(); | |||
} | |||
/** | |||
* @since 3.15 beta 2 | |||
*/ | |||
public int getStartColIndex() { | |||
return getStartCellReference().getCol(); | |||
} | |||
/** | |||
* @since 3.15 beta 2 | |||
*/ | |||
public int getStartRowIndex() { | |||
return getStartCellReference().getRow(); | |||
} | |||
/** | |||
* @since 3.15 beta 2 | |||
*/ | |||
public int getEndColIndex() { | |||
return getEndCellReference().getCol(); | |||
} | |||
/** | |||
* @since 3.15 beta 2 | |||
*/ | |||
public int getEndRowIndex() { | |||
return getEndCellReference().getRow(); | |||
} |
@@ -113,7 +113,8 @@ public final class XSSFFormulaUtils { | |||
String formula = name.getRefersToFormula(); | |||
if (formula != null) { | |||
int sheetIndex = name.getSheetIndex(); | |||
Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.NAMEDRANGE, sheetIndex, -1); | |||
int rowIndex = -1; //don't care | |||
Ptg[] ptgs = FormulaParser.parse(formula, _fpwb, FormulaType.NAMEDRANGE, sheetIndex, rowIndex); | |||
for (Ptg ptg : ptgs) { | |||
updatePtg(ptg, oldName, newName); | |||
} |
@@ -134,8 +134,9 @@ public final class XSSFRowShifter { | |||
XSSFName name = wb.getNameAt(i); | |||
String formula = name.getRefersToFormula(); | |||
int sheetIndex = name.getSheetIndex(); | |||
final int rowIndex = -1; //don't care, named ranges are not allowed to include structured references | |||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex, -1); | |||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.NAMEDRANGE, sheetIndex, rowIndex); | |||
if (shifter.adjustFormula(ptgs, sheetIndex)) { | |||
String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); | |||
name.setRefersToFormula(shiftedFmla); | |||
@@ -218,10 +219,11 @@ public final class XSSFRowShifter { | |||
XSSFSheet sheet = row.getSheet(); | |||
XSSFWorkbook wb = sheet.getWorkbook(); | |||
int sheetIndex = wb.getSheetIndex(sheet); | |||
final int rowIndex = row.getRowNum(); | |||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); | |||
try { | |||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, -1); | |||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, rowIndex); | |||
String shiftedFmla = null; | |||
if (shifter.adjustFormula(ptgs, sheetIndex)) { | |||
shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); | |||
@@ -238,6 +240,7 @@ public final class XSSFRowShifter { | |||
public void updateConditionalFormatting(FormulaShifter shifter) { | |||
XSSFWorkbook wb = sheet.getWorkbook(); | |||
int sheetIndex = wb.getSheetIndex(sheet); | |||
final int rowIndex = -1; //don't care, structured references not allowed in conditional formatting | |||
XSSFEvaluationWorkbook fpb = XSSFEvaluationWorkbook.create(wb); | |||
CTWorksheet ctWorksheet = sheet.getCTWorksheet(); | |||
@@ -283,7 +286,7 @@ public final class XSSFRowShifter { | |||
String[] formulaArray = cfRule.getFormulaArray(); | |||
for (int i = 0; i < formulaArray.length; i++) { | |||
String formula = formulaArray[i]; | |||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, -1); | |||
Ptg[] ptgs = FormulaParser.parse(formula, fpb, FormulaType.CELL, sheetIndex, rowIndex); | |||
if (shifter.adjustFormula(ptgs, sheetIndex)) { | |||
String shiftedFmla = FormulaRenderer.toFormulaString(fpb, ptgs); | |||
cfRule.setFormulaArray(i, shiftedFmla); |
@@ -42,7 +42,7 @@ import java.util.Arrays; | |||
public final class TestXSSFFormulaParser { | |||
private static Ptg[] parse(FormulaParsingWorkbook fpb, String fmla) { | |||
return FormulaParser.parse(fmla, fpb, FormulaType.CELL, -1, -1); | |||
return FormulaParser.parse(fmla, fpb, FormulaType.CELL, -1); | |||
} | |||
@Test |
@@ -1197,7 +1197,7 @@ public final class TestFormulaParser { | |||
String formula = "Sheet1!$B$2:$C$3,OFFSET(Sheet1!$E$2:$E$4,1,Sheet1!$A$1),Sheet1!$D$6"; | |||
HSSFWorkbook wb = new HSSFWorkbook(); | |||
wb.createSheet("Sheet1"); | |||
Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1,-1); | |||
Ptg[] ptgs = FormulaParser.parse(formula, HSSFEvaluationWorkbook.create(wb), FormulaType.CELL, -1); | |||
confirmTokenClasses(ptgs, | |||
// TODO - AttrPtg.class, // Excel prepends this | |||
@@ -1486,8 +1486,8 @@ public final class TestFormulaParser { | |||
confirmParseError(wb, "A1:ROUND(B1,1)", "The RHS of the range operator ':' at position 3 is not a proper reference."); | |||
confirmParseError(wb, "Sheet1!!!", "Parse error near char 7 '!' in specified formula 'Sheet1!!!'. Expected number, string, defined name, or table"); | |||
confirmParseError(wb, "Sheet1!.Name", "Parse error near char 7 '.' in specified formula 'Sheet1!.Name'. Expected number, string, defined name, or table"); | |||
confirmParseError(wb, "Sheet1!!!", "Parse error near char 7 '!' in specified formula 'Sheet1!!!'. Expected number, string, defined name, or data table"); | |||
confirmParseError(wb, "Sheet1!.Name", "Parse error near char 7 '.' in specified formula 'Sheet1!.Name'. Expected number, string, defined name, or data table"); | |||
confirmParseError(wb, "Sheet1!Sheet1", "Specified name 'Sheet1' for sheet Sheet1 not found"); | |||
confirmParseError(wb, "Sheet1!F:Sheet1!G", "'Sheet1!F' is not a proper reference."); | |||
confirmParseError(wb, "Sheet1!F..foobar", "Complete area reference expected after sheet name at index 11."); |
@@ -51,7 +51,7 @@ public final class TestArrayRecord extends TestCase { | |||
assertEquals("MAX(C1:C2-D1:D2)", FormulaRenderer.toFormulaString(null, ptg)); | |||
//construct a new ArrayRecord with the same contents as r1 | |||
Ptg[] fmlaPtg = FormulaParser.parse("MAX(C1:C2-D1:D2)", null, FormulaType.ARRAY, 0, -1); | |||
Ptg[] fmlaPtg = FormulaParser.parse("MAX(C1:C2-D1:D2)", null, FormulaType.ARRAY, 0); | |||
ArrayRecord r2 = new ArrayRecord(Formula.create(fmlaPtg), new CellRangeAddress8Bit(1, 1, 1, 1)); | |||
byte[] ser = r2.serialize(); | |||
//serialize and check that the data is the same as in r1 |
@@ -107,7 +107,7 @@ public final class TestSharedFormulaRecord extends TestCase { | |||
SharedFormula sf = new SharedFormula(SpreadsheetVersion.EXCEL97); | |||
sharedFormula = FormulaParser.parse("A2", fpb, FormulaType.CELL, -1, -1); | |||
sharedFormula = FormulaParser.parse("A2", fpb, FormulaType.CELL, -1); | |||
convertedFormula = sf.convertSharedFormulas(sharedFormula, 0, 0); | |||
confirmOperandClasses(sharedFormula, convertedFormula); | |||
//conversion relative to [0,0] should return the original formula | |||
@@ -123,7 +123,7 @@ public final class TestSharedFormulaRecord extends TestCase { | |||
//one row down and one cell right | |||
assertEquals("B3", FormulaRenderer.toFormulaString(fpb, convertedFormula)); | |||
sharedFormula = FormulaParser.parse("SUM(A1:C1)", fpb, FormulaType.CELL, -1, -1); | |||
sharedFormula = FormulaParser.parse("SUM(A1:C1)", fpb, FormulaType.CELL, -1); | |||
convertedFormula = sf.convertSharedFormulas(sharedFormula, 0, 0); | |||
confirmOperandClasses(sharedFormula, convertedFormula); | |||
assertEquals("SUM(A1:C1)", FormulaRenderer.toFormulaString(fpb, convertedFormula)); |