git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1613437 13f79535-47bb-0310-9956-ffa450edef68tags/REL_3_11_BETA1
package org.apache.poi.ss.formula.ptg; | package org.apache.poi.ss.formula.ptg; | ||||
import org.apache.poi.ss.formula.SheetIdentifier; | |||||
import org.apache.poi.ss.formula.SheetNameFormatter; | import org.apache.poi.ss.formula.SheetNameFormatter; | ||||
import org.apache.poi.ss.formula.SheetRangeIdentifier; | |||||
import org.apache.poi.ss.util.AreaReference; | import org.apache.poi.ss.util.AreaReference; | ||||
import org.apache.poi.util.LittleEndianOutput; | import org.apache.poi.util.LittleEndianOutput; | ||||
*/ | */ | ||||
public final class Area3DPxg extends AreaPtgBase implements Pxg { | public final class Area3DPxg extends AreaPtgBase implements Pxg { | ||||
private int externalWorkbookNumber = -1; | private int externalWorkbookNumber = -1; | ||||
private String sheetName; | |||||
private String firstSheetName; | |||||
private String lastSheetName; | |||||
public Area3DPxg(int externalWorkbookNumber, String sheetName, String arearef) { | |||||
public Area3DPxg(int externalWorkbookNumber, SheetIdentifier sheetName, String arearef) { | |||||
this(externalWorkbookNumber, sheetName, new AreaReference(arearef)); | this(externalWorkbookNumber, sheetName, new AreaReference(arearef)); | ||||
} | } | ||||
public Area3DPxg(int externalWorkbookNumber, String sheetName, AreaReference arearef) { | |||||
public Area3DPxg(int externalWorkbookNumber, SheetIdentifier sheetName, AreaReference arearef) { | |||||
super(arearef); | super(arearef); | ||||
this.externalWorkbookNumber = externalWorkbookNumber; | this.externalWorkbookNumber = externalWorkbookNumber; | ||||
this.sheetName = sheetName; | |||||
this.firstSheetName = sheetName.getSheetIdentifier().getName(); | |||||
if (sheetName instanceof SheetRangeIdentifier) { | |||||
this.lastSheetName = ((SheetRangeIdentifier)sheetName).getLastSheetIdentifier().getName(); | |||||
} else { | |||||
this.lastSheetName = null; | |||||
} | |||||
} | } | ||||
public Area3DPxg(String sheetName, String arearef) { | |||||
public Area3DPxg(SheetIdentifier sheetName, String arearef) { | |||||
this(sheetName, new AreaReference(arearef)); | this(sheetName, new AreaReference(arearef)); | ||||
} | } | ||||
public Area3DPxg(String sheetName, AreaReference arearef) { | |||||
public Area3DPxg(SheetIdentifier sheetName, AreaReference arearef) { | |||||
this(-1, sheetName, arearef); | this(-1, sheetName, arearef); | ||||
} | } | ||||
sb.append("] "); | sb.append("] "); | ||||
} | } | ||||
sb.append("sheet=").append(getSheetName()); | sb.append("sheet=").append(getSheetName()); | ||||
if (lastSheetName != null) { | |||||
sb.append(" : "); | |||||
sb.append("sheet=").append(lastSheetName); | |||||
} | |||||
sb.append(" ! "); | sb.append(" ! "); | ||||
sb.append(formatReferenceAsString()); | sb.append(formatReferenceAsString()); | ||||
sb.append("]"); | sb.append("]"); | ||||
return externalWorkbookNumber; | return externalWorkbookNumber; | ||||
} | } | ||||
public String getSheetName() { | public String getSheetName() { | ||||
return sheetName; | |||||
return firstSheetName; | |||||
} | |||||
public String getLastSheetName() { | |||||
return lastSheetName; | |||||
} | } | ||||
public void setSheetName(String sheetName) { | public void setSheetName(String sheetName) { | ||||
this.sheetName = sheetName; | |||||
this.firstSheetName = sheetName; | |||||
} | |||||
public void setLastSheetName(String sheetName) { | |||||
this.lastSheetName = sheetName; | |||||
} | } | ||||
public String format2DRefAsString() { | public String format2DRefAsString() { | ||||
sb.append(externalWorkbookNumber); | sb.append(externalWorkbookNumber); | ||||
sb.append(']'); | sb.append(']'); | ||||
} | } | ||||
SheetNameFormatter.appendFormat(sb, sheetName); | |||||
SheetNameFormatter.appendFormat(sb, firstSheetName); | |||||
if (lastSheetName != null) { | |||||
sb.append(':'); | |||||
SheetNameFormatter.appendFormat(sb, lastSheetName); | |||||
} | |||||
sb.append('!'); | sb.append('!'); | ||||
sb.append(formatReferenceAsString()); | sb.append(formatReferenceAsString()); | ||||
return sb.toString(); | return sb.toString(); |
public int getExternalWorkbookNumber() { | public int getExternalWorkbookNumber() { | ||||
return externalWorkbookNumber; | return externalWorkbookNumber; | ||||
} | } | ||||
public String getSheetName() { // TODO Rename to getFirstSheetName | |||||
public String getSheetName() { | |||||
return firstSheetName; | return firstSheetName; | ||||
} | } | ||||
public String getLastSheetName() { | public String getLastSheetName() { | ||||
return lastSheetName; | return lastSheetName; | ||||
} | } | ||||
public void setSheetName(String sheetName) { // TODO Rename to setFirstSheetName | |||||
public void setSheetName(String sheetName) { | |||||
this.firstSheetName = sheetName; | this.firstSheetName = sheetName; | ||||
} | } | ||||
public void setLastSheetName(String sheetName) { | public void setLastSheetName(String sheetName) { |
} | } | ||||
} | } | ||||
public Ptg get3DReferencePtg(AreaReference area, SheetIdentifier sheet) { | public Ptg get3DReferencePtg(AreaReference area, SheetIdentifier sheet) { | ||||
String sheetName = sheet._sheetIdentifier.getName(); | |||||
if (sheet._bookName != null) { | if (sheet._bookName != null) { | ||||
int bookIndex = resolveBookIndex(sheet._bookName); | int bookIndex = resolveBookIndex(sheet._bookName); | ||||
return new Area3DPxg(bookIndex, sheetName, area); | |||||
return new Area3DPxg(bookIndex, sheet, area); | |||||
} else { | } else { | ||||
return new Area3DPxg(sheetName, area); | |||||
return new Area3DPxg(sheet, area); | |||||
} | } | ||||
} | } | ||||
Cell sumF = s1.getRow(2).getCell(0); | Cell sumF = s1.getRow(2).getCell(0); | ||||
assertNotNull(sumF); | assertNotNull(sumF); | ||||
assertEquals("SUM(Sheet1:Sheet3!A1)", sumF.getCellFormula()); | assertEquals("SUM(Sheet1:Sheet3!A1)", sumF.getCellFormula()); | ||||
assertEquals("66", evaluator.evaluate(sumF).formatAsString()); | |||||
assertEquals("66.0", evaluator.evaluate(sumF).formatAsString()); | |||||
// Various Stats formulas on numbers | // Various Stats formulas on numbers | ||||
Cell avgF = s1.getRow(2).getCell(1); | Cell avgF = s1.getRow(2).getCell(1); | ||||
assertNotNull(avgF); | assertNotNull(avgF); | ||||
assertEquals("AVERAGE(Sheet1:Sheet3!A1)", avgF.getCellFormula()); | assertEquals("AVERAGE(Sheet1:Sheet3!A1)", avgF.getCellFormula()); | ||||
assertEquals("22", evaluator.evaluate(avgF).formatAsString()); | |||||
assertEquals("22.0", evaluator.evaluate(avgF).formatAsString()); | |||||
Cell minF = s1.getRow(3).getCell(1); | Cell minF = s1.getRow(3).getCell(1); | ||||
assertNotNull(minF); | assertNotNull(minF); | ||||
assertEquals("MIX(Sheet1:Sheet3!A$1)", minF.getCellFormula()); | assertEquals("MIX(Sheet1:Sheet3!A$1)", minF.getCellFormula()); | ||||
assertEquals("11", evaluator.evaluate(minF).formatAsString()); | |||||
assertEquals("11.0", evaluator.evaluate(minF).formatAsString()); | |||||
Cell maxF = s1.getRow(4).getCell(1); | Cell maxF = s1.getRow(4).getCell(1); | ||||
assertNotNull(maxF); | assertNotNull(maxF); | ||||
assertEquals("MAX(Sheet1:Sheet3!A$1)", maxF.getCellFormula()); | assertEquals("MAX(Sheet1:Sheet3!A$1)", maxF.getCellFormula()); | ||||
assertEquals("33", evaluator.evaluate(maxF).formatAsString()); | |||||
assertEquals("33.0", evaluator.evaluate(maxF).formatAsString()); | |||||
Cell countF = s1.getRow(5).getCell(1); | Cell countF = s1.getRow(5).getCell(1); | ||||
assertNotNull(countF); | assertNotNull(countF); | ||||
assertEquals("COUNT(Sheet1:Sheet3!A$1)", countF.getCellFormula()); | assertEquals("COUNT(Sheet1:Sheet3!A$1)", countF.getCellFormula()); | ||||
assertEquals("3", evaluator.evaluate(countF).formatAsString()); | |||||
assertEquals("3.0", evaluator.evaluate(countF).formatAsString()); | |||||
// Various CountAs on Strings | // Various CountAs on Strings | ||||
Cell countA_1F = s1.getRow(2).getCell(2); | Cell countA_1F = s1.getRow(2).getCell(2); | ||||
assertNotNull(countA_1F); | assertNotNull(countA_1F); | ||||
assertEquals("COUNTA(Sheet1:Sheet3!C1)", countA_1F.getCellFormula()); | assertEquals("COUNTA(Sheet1:Sheet3!C1)", countA_1F.getCellFormula()); | ||||
assertEquals("3", evaluator.evaluate(countA_1F).formatAsString()); | |||||
assertEquals("3.0", evaluator.evaluate(countA_1F).formatAsString()); | |||||
Cell countA_2F = s1.getRow(2).getCell(3); | Cell countA_2F = s1.getRow(2).getCell(3); | ||||
assertNotNull(countA_2F); | assertNotNull(countA_2F); | ||||
assertEquals("COUNTA(Sheet1:Sheet3!D1)", countA_2F.getCellFormula()); | assertEquals("COUNTA(Sheet1:Sheet3!D1)", countA_2F.getCellFormula()); | ||||
assertEquals("0", evaluator.evaluate(countA_2F).formatAsString()); | |||||
assertEquals("0.0", evaluator.evaluate(countA_2F).formatAsString()); | |||||
Cell countA_3F = s1.getRow(2).getCell(4); | Cell countA_3F = s1.getRow(2).getCell(4); | ||||
assertNotNull(countA_3F); | assertNotNull(countA_3F); | ||||
assertEquals("COUNTA(Sheet1:Sheet3!E1)", countA_3F.getCellFormula()); | assertEquals("COUNTA(Sheet1:Sheet3!E1)", countA_3F.getCellFormula()); | ||||
assertEquals("3", evaluator.evaluate(countA_3F).formatAsString()); | |||||
assertEquals("3.0", evaluator.evaluate(countA_3F).formatAsString()); | |||||
} | } | ||||
} | } | ||||
} | } |
import org.apache.poi.ss.formula.FormulaRenderingWorkbook; | import org.apache.poi.ss.formula.FormulaRenderingWorkbook; | ||||
import org.apache.poi.ss.formula.FormulaType; | import org.apache.poi.ss.formula.FormulaType; | ||||
import org.apache.poi.ss.formula.WorkbookDependentFormula; | import org.apache.poi.ss.formula.WorkbookDependentFormula; | ||||
import org.apache.poi.ss.formula.ptg.Area3DPtg; | |||||
import org.apache.poi.ss.formula.ptg.Area3DPxg; | import org.apache.poi.ss.formula.ptg.Area3DPxg; | ||||
import org.apache.poi.ss.formula.ptg.AreaPtg; | import org.apache.poi.ss.formula.ptg.AreaPtg; | ||||
import org.apache.poi.ss.formula.ptg.AttrPtg; | import org.apache.poi.ss.formula.ptg.AttrPtg; | ||||
/** | /** | ||||
* A handful of functions (such as SUM, COUNTA, MIN) support | * A handful of functions (such as SUM, COUNTA, MIN) support | ||||
* multi-sheet references (eg Sheet1:Sheet3!A1 = Cell A1 from | * multi-sheet references (eg Sheet1:Sheet3!A1 = Cell A1 from | ||||
* Sheets 1 through Sheet 3). | |||||
* Sheets 1 through Sheet 3) and multi-sheet area references | |||||
* (eg Sheet1:Sheet3!A1:B2 = Cells A1 through B2 from Sheets | |||||
* 1 through Sheet 3). | |||||
* This test, based on common test files for HSSF and XSSF, checks | * This test, based on common test files for HSSF and XSSF, checks | ||||
* that we can read and parse these kinds of references | * that we can read and parse these kinds of references | ||||
* (but not evaluate - that's elsewhere in the test suite) | * (but not evaluate - that's elsewhere in the test suite) | ||||
assertNotNull(maxF); | assertNotNull(maxF); | ||||
assertEquals("MAX(Sheet1:Sheet3!A$1)", maxF.getCellFormula()); | assertEquals("MAX(Sheet1:Sheet3!A$1)", maxF.getCellFormula()); | ||||
Cell sumFA = s1.getRow(2).getCell(7); | |||||
assertNotNull(sumFA); | |||||
assertEquals("SUM(Sheet1:Sheet3!A1:B2)", sumFA.getCellFormula()); | |||||
Cell avgFA = s1.getRow(2).getCell(8); | |||||
assertNotNull(avgFA); | |||||
assertEquals("AVERAGE(Sheet1:Sheet3!A1:B2)", avgFA.getCellFormula()); | |||||
Cell maxFA = s1.getRow(4).getCell(8); | |||||
assertNotNull(maxFA); | |||||
assertEquals("MAX(Sheet1:Sheet3!A$1:B$2)", maxFA.getCellFormula()); | |||||
Cell countFA = s1.getRow(5).getCell(8); | |||||
assertNotNull(countFA); | |||||
assertEquals("COUNT(Sheet1:Sheet3!$A$1:$B$2)", countFA.getCellFormula()); | |||||
// Create a formula parser | // Create a formula parser | ||||
FormulaParsingWorkbook fpb = null; | FormulaParsingWorkbook fpb = null; | ||||
if (wb instanceof HSSFWorkbook) | if (wb instanceof HSSFWorkbook) | ||||
assertEquals("MIN", toFormulaString(ptgs[1], fpb)); | assertEquals("MIN", toFormulaString(ptgs[1], fpb)); | ||||
// Check we can round-trip - try to set a new one to a new cell | |||||
// SUM to a range of cells over 3 workbooks | |||||
ptgs = parse(fpb, "SUM(Sheet1:Sheet3!A1:B2)"); | |||||
assertEquals(2, ptgs.length); | |||||
if (wb instanceof HSSFWorkbook) { | |||||
assertEquals(Area3DPtg.class, ptgs[0].getClass()); | |||||
} else { | |||||
assertEquals(Area3DPxg.class, ptgs[0].getClass()); | |||||
} | |||||
assertEquals("Sheet1:Sheet3!A1:B2", toFormulaString(ptgs[0], fpb)); | |||||
assertEquals(AttrPtg.class, ptgs[1].getClass()); | |||||
assertEquals("SUM", toFormulaString(ptgs[1], fpb)); | |||||
// MIN to a range of cells over 3 workbooks, absolute reference | |||||
ptgs = parse(fpb, "MIN(Sheet1:Sheet3!$A$1:$B$2)"); | |||||
assertEquals(2, ptgs.length); | |||||
if (wb instanceof HSSFWorkbook) { | |||||
assertEquals(Area3DPtg.class, ptgs[0].getClass()); | |||||
} else { | |||||
assertEquals(Area3DPxg.class, ptgs[0].getClass()); | |||||
} | |||||
assertEquals("Sheet1:Sheet3!$A$1:$B$2", toFormulaString(ptgs[0], fpb)); | |||||
assertEquals(FuncVarPtg.class, ptgs[1].getClass()); | |||||
assertEquals("MIN", toFormulaString(ptgs[1], fpb)); | |||||
// Check we can round-trip - try to set a new one to a new single cell | |||||
Cell newF = s1.getRow(0).createCell(10, Cell.CELL_TYPE_FORMULA); | Cell newF = s1.getRow(0).createCell(10, Cell.CELL_TYPE_FORMULA); | ||||
newF.setCellFormula("SUM(Sheet2:Sheet3!A1)"); | newF.setCellFormula("SUM(Sheet2:Sheet3!A1)"); | ||||
assertEquals("SUM(Sheet2:Sheet3!A1)", newF.getCellFormula()); | assertEquals("SUM(Sheet2:Sheet3!A1)", newF.getCellFormula()); | ||||
// Check we can round-trip - try to set a new one to a cell range | |||||
newF = s1.getRow(0).createCell(11, Cell.CELL_TYPE_FORMULA); | |||||
newF.setCellFormula("MIN(Sheet1:Sheet2!A1:B2)"); | |||||
assertEquals("MIN(Sheet1:Sheet2!A1:B2)", newF.getCellFormula()); | |||||
} | } | ||||
} | } | ||||
private static String toFormulaString(Ptg ptg, FormulaParsingWorkbook wb) { | private static String toFormulaString(Ptg ptg, FormulaParsingWorkbook wb) { |
HSSFCell cell = row.createCell(0); | HSSFCell cell = row.createCell(0); | ||||
String formula = null; | String formula = null; | ||||
// References to a single cell: | |||||
// One sheet | // One sheet | ||||
cell.setCellFormula("Cash_Flow!A1"); | cell.setCellFormula("Cash_Flow!A1"); | ||||
formula = cell.getCellFormula(); | formula = cell.getCellFormula(); | ||||
cell.setCellFormula("Cash_Flow:\'Test Sheet\'!A1"); | cell.setCellFormula("Cash_Flow:\'Test Sheet\'!A1"); | ||||
formula = cell.getCellFormula(); | formula = cell.getCellFormula(); | ||||
assertEquals("Cash_Flow:\'Test Sheet\'!A1", formula); | assertEquals("Cash_Flow:\'Test Sheet\'!A1", formula); | ||||
// References to a range (area) of cells: | |||||
// One sheet | |||||
cell.setCellFormula("Cash_Flow!A1:B2"); | |||||
formula = cell.getCellFormula(); | |||||
assertEquals("Cash_Flow!A1:B2", formula); | |||||
// Then the other | |||||
cell.setCellFormula("\'Test Sheet\'!A1:B2"); | |||||
formula = cell.getCellFormula(); | |||||
assertEquals("\'Test Sheet\'!A1:B2", formula); | |||||
// Now both | |||||
cell.setCellFormula("Cash_Flow:\'Test Sheet\'!A1:B2"); | |||||
formula = cell.getCellFormula(); | |||||
assertEquals("Cash_Flow:\'Test Sheet\'!A1:B2", formula); | |||||
} | } | ||||
/** | /** |