diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index 45c1612461..1e88e94b07 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -1871,17 +1871,31 @@ public final class InternalWorkbook { return linkTable.getLastInternalSheetIndexForExtIndex(externSheetNumber); } - /** returns the extern sheet number for specific sheet number , - * if this sheet doesn't exist in extern sheet , add it - * @param sheetNumber sheet number + /** + * Returns the extern sheet number for specific sheet number. + * If this sheet doesn't exist in extern sheet, add it + * @param sheetNumber local sheet number * @return index to extern sheet */ public short checkExternSheet(int sheetNumber){ return (short)getOrCreateLinkTable().checkExternSheet(sheetNumber); } + /** + * Returns the extern sheet number for specific range of sheets. + * If this sheet range doesn't exist in extern sheet, add it + * @param firstSheetNumber first local sheet number + * @param lastSheetNumber last local sheet number + * @return index to extern sheet + */ + public short checkExternSheet(int firstSheetNumber, int lastSheetNumber){ + return (short)getOrCreateLinkTable().checkExternSheet(firstSheetNumber, lastSheetNumber); + } public int getExternalSheetIndex(String workbookName, String sheetName) { - return getOrCreateLinkTable().getExternalSheetIndex(workbookName, sheetName); + return getOrCreateLinkTable().getExternalSheetIndex(workbookName, sheetName, sheetName); + } + public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) { + return getOrCreateLinkTable().getExternalSheetIndex(workbookName, firstSheetName, lastSheetName); } diff --git a/src/java/org/apache/poi/hssf/model/LinkTable.java b/src/java/org/apache/poi/hssf/model/LinkTable.java index a01b287161..7277da2e6c 100644 --- a/src/java/org/apache/poi/hssf/model/LinkTable.java +++ b/src/java/org/apache/poi/hssf/model/LinkTable.java @@ -383,7 +383,7 @@ final class LinkTable { } } - public int getExternalSheetIndex(String workbookName, String sheetName) { + public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) { SupBookRecord ebrTarget = null; int externalBookIndex = -1; for (int i=0; i<_externalBookBlocks.length; i++) { @@ -400,12 +400,13 @@ final class LinkTable { if (ebrTarget == null) { throw new RuntimeException("No external workbook with name '" + workbookName + "'"); } - int sheetIndex = getSheetIndex(ebrTarget.getSheetNames(), sheetName); + int firstSheetIndex = getSheetIndex(ebrTarget.getSheetNames(), firstSheetName); + int lastSheetIndex = getSheetIndex(ebrTarget.getSheetNames(), lastSheetName); - int result = _externSheetRecord.getRefIxForSheet(externalBookIndex, sheetIndex); + int result = _externSheetRecord.getRefIxForSheet(externalBookIndex, firstSheetIndex, lastSheetIndex); if (result < 0) { throw new RuntimeException("ExternSheetRecord does not contain combination (" - + externalBookIndex + ", " + sheetIndex + ")"); + + externalBookIndex + ", " + firstSheetIndex + ", " + lastSheetIndex + ")"); } return result; } @@ -454,6 +455,9 @@ final class LinkTable { } public int checkExternSheet(int sheetIndex) { + return checkExternSheet(sheetIndex, sheetIndex); + } + public int checkExternSheet(int firstSheetIndex, int lastSheetIndex) { int thisWbIndex = -1; // this is probably always zero for (int i=0; i<_externalBookBlocks.length; i++) { SupBookRecord ebr = _externalBookBlocks[i].getExternalBookRecord(); @@ -467,12 +471,12 @@ final class LinkTable { } //Trying to find reference to this sheet - int i = _externSheetRecord.getRefIxForSheet(thisWbIndex, sheetIndex); + int i = _externSheetRecord.getRefIxForSheet(thisWbIndex, firstSheetIndex, lastSheetIndex); if (i>=0) { return i; } //We haven't found reference to this sheet - return _externSheetRecord.addRef(thisWbIndex, sheetIndex, sheetIndex); + return _externSheetRecord.addRef(thisWbIndex, firstSheetIndex, lastSheetIndex); } /** @@ -612,7 +616,8 @@ final class LinkTable { int numberOfNames = extBlock.getNumberOfNames(); // a new name is inserted in the end of the SupBookRecord, after the last name _workbookRecordList.add(supLinkIndex + numberOfNames, extNameRecord); - int ix = _externSheetRecord.getRefIxForSheet(extBlockIndex, -2 /* the scope is workbook*/); + int fakeSheetIdx = -2; /* the scope is workbook*/ + int ix = _externSheetRecord.getRefIxForSheet(extBlockIndex, fakeSheetIdx, fakeSheetIdx); return new NameXPtg(ix, nameIndex); } diff --git a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java index 846c9c2a6b..636b6b0da0 100644 --- a/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java +++ b/src/java/org/apache/poi/hssf/record/ExternSheetRecord.java @@ -276,14 +276,15 @@ public class ExternSheetRecord extends StandardRecord { return _list.size() - 1; } - public int getRefIxForSheet(int externalBookIndex, int sheetIndex) { + public int getRefIxForSheet(int externalBookIndex, int firstSheetIndex, int lastSheetIndex) { int nItems = _list.size(); for (int i = 0; i < nItems; i++) { RefSubRecord ref = getRef(i); if (ref.getExtBookIndex() != externalBookIndex) { continue; } - if (ref.getFirstSheetIndex() == sheetIndex && ref.getLastSheetIndex() == sheetIndex) { + if (ref.getFirstSheetIndex() == firstSheetIndex && + ref.getLastSheetIndex() == lastSheetIndex) { return i; } } diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java index 84eb528d55..5136babe2d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java @@ -30,7 +30,9 @@ import org.apache.poi.ss.formula.FormulaParseException; import org.apache.poi.ss.formula.FormulaParsingWorkbook; import org.apache.poi.ss.formula.FormulaRenderingWorkbook; import org.apache.poi.ss.formula.FormulaType; +import org.apache.poi.ss.formula.NameIdentifier; import org.apache.poi.ss.formula.SheetIdentifier; +import org.apache.poi.ss.formula.SheetRangeIdentifier; import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.NamePtg; import org.apache.poi.ss.formula.ptg.NameXPtg; @@ -69,7 +71,25 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E public int getExternalSheetIndex(String workbookName, String sheetName) { return _iBook.getExternalSheetIndex(workbookName, sheetName); } - + public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) { + return _iBook.getExternalSheetIndex(workbookName, firstSheetName, lastSheetName); + } + + public int getExternalSheetIndex(String workbookName, NameIdentifier sheetName) { + return getExternalSheetIndex(workbookName, sheetName.getName()); + } + public int getExternalSheetIndex(String workbookName, NameIdentifier firstSheetName, NameIdentifier lastSheetName) { + return getExternalSheetIndex(workbookName, firstSheetName.getName(), lastSheetName.getName()); + } + public int getExternalSheetIndex(NameIdentifier sheetName) { + return getExternalSheetIndex(sheetName.getName()); + } + public int getExternalSheetIndex(NameIdentifier firstSheetName, NameIdentifier lastSheetName) { + int firstSheetIndex = _uBook.getSheetIndex(firstSheetName.getName()); + int lastSheetIndex = _uBook.getSheetIndex(lastSheetName.getName()); + return _iBook.checkExternSheet(firstSheetIndex, lastSheetIndex); + } + public Ptg get3DReferencePtg(CellReference cr, SheetIdentifier sheet) { int extIx = getSheetExtIx(sheet); return new Ref3DPtg(cr, extIx); @@ -235,11 +255,25 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E if (sheetIden == null) { extIx = -1; } else { - String sName = sheetIden.getSheetIdentifier().getName(); + NameIdentifier sheetName = sheetIden.getSheetIdentifier(); + NameIdentifier lastSheetName = null; + + if (sheetIden instanceof SheetRangeIdentifier) { + lastSheetName = ((SheetRangeIdentifier)sheetIden).getLastSheetIdentifier(); + } + if (sheetIden.getBookName() == null) { - extIx = getExternalSheetIndex(sName); + if (lastSheetName == null) { + extIx = getExternalSheetIndex(sheetName); + } else { + extIx = getExternalSheetIndex(sheetName, lastSheetName); + } } else { - extIx = getExternalSheetIndex(sheetIden.getBookName(), sName); + if (lastSheetName == null) { + extIx = getExternalSheetIndex(sheetIden.getBookName(), sheetName); + } else { + extIx = getExternalSheetIndex(sheetIden.getBookName(), sheetName, lastSheetName); + } } } return extIx; diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java index 222da5cd62..bf86a004cb 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaParser.java @@ -283,16 +283,15 @@ public final class TestXSSFFormulaParser { // Check things parse as expected: - // Note - Ptgs will only show one sheet, the formula - // parser stuff looks up the second later + // TODO Fix it so that the Pxgs get the second sheet too! // SUM to one cell over 3 workbooks, relative reference ptgs = parse(fpb, "SUM(Sheet1:Sheet3!A1)"); assertEquals(2, ptgs.length); if (wb instanceof HSSFWorkbook) { - assertEquals(Ref3DPtg.class, ptgs[0].getClass()); - assertEquals("Sheet1!A1", toFormulaString(ptgs[0], fpb)); + assertEquals(Ref3DPtg.class, ptgs[0].getClass()); + assertEquals("Sheet1:Sheet3!A1", toFormulaString(ptgs[0], fpb)); } else { assertEquals(Ref3DPxg.class, ptgs[0].getClass()); assertEquals("Sheet1!A1", toFormulaString(ptgs[0], fpb)); @@ -305,8 +304,8 @@ public final class TestXSSFFormulaParser { ptgs = parse(fpb, "MAX(Sheet1:Sheet3!A$1)"); assertEquals(2, ptgs.length); if (wb instanceof HSSFWorkbook) { - assertEquals(Ref3DPtg.class, ptgs[0].getClass()); - assertEquals("Sheet1!A$1", toFormulaString(ptgs[0], fpb)); + assertEquals(Ref3DPtg.class, ptgs[0].getClass()); + assertEquals("Sheet1:Sheet3!A$1", toFormulaString(ptgs[0], fpb)); } else { assertEquals(Ref3DPxg.class, ptgs[0].getClass()); assertEquals("Sheet1!A$1", toFormulaString(ptgs[0], fpb)); @@ -319,14 +318,20 @@ public final class TestXSSFFormulaParser { ptgs = parse(fpb, "MIN(Sheet1:Sheet3!$A$1)"); assertEquals(2, ptgs.length); if (wb instanceof HSSFWorkbook) { - assertEquals(Ref3DPtg.class, ptgs[0].getClass()); - assertEquals("Sheet1!$A$1", toFormulaString(ptgs[0], fpb)); + assertEquals(Ref3DPtg.class, ptgs[0].getClass()); + assertEquals("Sheet1:Sheet3!$A$1", toFormulaString(ptgs[0], fpb)); } else { assertEquals(Ref3DPxg.class, ptgs[0].getClass()); assertEquals("Sheet1!$A$1", 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 cell + Cell newF = s1.getRow(0).createCell(10, Cell.CELL_TYPE_FORMULA); + newF.setCellFormula("SUM(Sheet2:Sheet3!A1)"); + assertEquals("SUM(Sheet2:Sheet3!A1)", newF.getCellFormula()); } } private static String toFormulaString(Ptg ptg, FormulaParsingWorkbook wb) { diff --git a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java index f780bde0e6..4546de31ad 100644 --- a/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java +++ b/src/testcases/org/apache/poi/hssf/model/TestFormulaParser.java @@ -476,10 +476,9 @@ public final class TestFormulaParser extends TestCase { assertEquals("\'Test Sheet\'!A1", formula); // Now both - // TODO Implement remaining logic for #55906 cell.setCellFormula("Cash_Flow:\'Test Sheet\'!A1"); formula = cell.getCellFormula(); -// assertEquals("Cash_Flow:\'Test Sheet\'!A1", formula); + assertEquals("Cash_Flow:\'Test Sheet\'!A1", formula); } /**