From 7f6ba5513c318cccb81a23ffc2e61855416ad8c6 Mon Sep 17 00:00:00 2001 From: Nick Burch Date: Thu, 24 Jul 2014 21:25:45 +0000 Subject: [PATCH] Rename some of the internal HSSF sheet lookup methods which deal with external sheet indicies, to make it clear when they return the first sheet name/index, and add support for getting the last one too (will be the same as the first if not a range) git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1613305 13f79535-47bb-0310-9956-ffa450edef68 --- .../poi/hssf/model/InternalWorkbook.java | 31 ++++++++++----- .../org/apache/poi/hssf/model/LinkTable.java | 38 ++++++++++++++----- .../usermodel/HSSFEvaluationWorkbook.java | 11 +++++- .../apache/poi/hssf/usermodel/HSSFName.java | 4 +- .../poi/hssf/usermodel/HSSFWorkbook.java | 2 +- .../poi/ss/formula/EvaluationWorkbook.java | 14 +++++++ .../ss/formula/FormulaRenderingWorkbook.java | 14 +++++-- .../formula/ptg/ExternSheetNameResolver.java | 21 ++++++++-- .../usermodel/XSSFEvaluationWorkbook.java | 6 ++- .../TestEventWorkbookBuilder.java | 6 +-- 10 files changed, 113 insertions(+), 34 deletions(-) diff --git a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java index 0479a0b8e..115bdd4a6 100644 --- a/src/java/org/apache/poi/hssf/model/InternalWorkbook.java +++ b/src/java/org/apache/poi/hssf/model/InternalWorkbook.java @@ -85,6 +85,7 @@ import org.apache.poi.hssf.record.common.UnicodeString; import org.apache.poi.hssf.util.HSSFColor; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalName; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; +import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheetRange; import org.apache.poi.ss.formula.FormulaShifter; import org.apache.poi.ss.formula.ptg.Area3DPtg; import org.apache.poi.ss.formula.ptg.NameXPtg; @@ -1803,30 +1804,42 @@ public final class InternalWorkbook { return linkTable; } - /** finds the sheet name by his extern sheet index + /** + * Finds the first sheet name by his extern sheet index * @param externSheetIndex extern sheet index - * @return sheet name. + * @return first sheet name. */ - public String findSheetNameFromExternSheet(int externSheetIndex){ - - int indexToSheet = linkTable.getIndexToInternalSheet(externSheetIndex); - if (indexToSheet < 0) { + public String findSheetFirstNameFromExternSheet(int externSheetIndex){ + int indexToSheet = linkTable.getFirstInternalSheetIndexForExtIndex(externSheetIndex); + return findSheetNameFromIndex(indexToSheet); + } + public String findSheetLastNameFromExternSheet(int externSheetIndex){ + int indexToSheet = linkTable.getLastInternalSheetIndexForExtIndex(externSheetIndex); + return findSheetNameFromIndex(indexToSheet); + } + private String findSheetNameFromIndex(int internalSheetIndex) { + if (internalSheetIndex < 0) { // TODO - what does '-1' mean here? //error check, bail out gracefully! return ""; } - if (indexToSheet >= boundsheets.size()) { + if (internalSheetIndex >= boundsheets.size()) { // Not sure if this can ever happen (See bug 45798) return ""; // Seems to be what excel would do in this case } - return getSheetName(indexToSheet); + return getSheetName(internalSheetIndex); } + public ExternalSheet getExternalSheet(int externSheetIndex) { String[] extNames = linkTable.getExternalBookAndSheetName(externSheetIndex); if (extNames == null) { return null; } - return new ExternalSheet(extNames[0], extNames[1]); + if (extNames.length == 2) { + return new ExternalSheet(extNames[0], extNames[1]); + } else { + return new ExternalSheetRange(extNames[0], extNames[1], extNames[2]); + } } public ExternalName getExternalName(int externSheetIndex, int externNameIndex) { String nameName = linkTable.resolveNameXText(externSheetIndex, externNameIndex, this); diff --git a/src/java/org/apache/poi/hssf/model/LinkTable.java b/src/java/org/apache/poi/hssf/model/LinkTable.java index 3b04d0d84..a117aef4a 100644 --- a/src/java/org/apache/poi/hssf/model/LinkTable.java +++ b/src/java/org/apache/poi/hssf/model/LinkTable.java @@ -359,15 +359,28 @@ final class LinkTable { return null; } // Sheet name only applies if not a global reference - int shIx = _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex); - String usSheetName = null; - if(shIx >= 0) { - usSheetName = ebr.getSheetNames()[shIx]; + int shIx1 = _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex); + int shIx2 = _externSheetRecord.getLastSheetIndexFromRefIndex(extRefIndex); + String firstSheetName = null; + String lastSheetName = null; + if(shIx1 >= 0) { + firstSheetName = ebr.getSheetNames()[shIx1]; + } + if (shIx2 >= 0) { + lastSheetName = ebr.getSheetNames()[shIx2]; + } + if (shIx1 == shIx2) { + return new String[] { + ebr.getURL(), + firstSheetName + }; + } else { + return new String[] { + ebr.getURL(), + firstSheetName, + lastSheetName + }; } - return new String[] { - ebr.getURL(), - usSheetName, - }; } public int getExternalSheetIndex(String workbookName, String sheetName) { @@ -411,9 +424,16 @@ final class LinkTable { * @param extRefIndex as from a {@link Ref3DPtg} or {@link Area3DPtg} * @return -1 if the reference is to an external book */ - public int getIndexToInternalSheet(int extRefIndex) { + public int getFirstInternalSheetIndexForExtIndex(int extRefIndex) { return _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex); } + /** + * @param extRefIndex as from a {@link Ref3DPtg} or {@link Area3DPtg} + * @return -1 if the reference is to an external book + */ + public int getLastInternalSheetIndexForExtIndex(int extRefIndex) { + return _externSheetRecord.getLastSheetIndexFromRefIndex(extRefIndex); + } /** * @deprecated Was prevously used for removing sheets, which we now do differently diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java index 748b42a43..6b9ddaa7e 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFEvaluationWorkbook.java @@ -132,6 +132,10 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E // Not actually sheet based at all - is workbook scoped return null; } + + // Is it a single local sheet, or a range? + // TODO + // Look up the local sheet String sheetName = getSheetName(localSheetIndex); sheet = new ExternalSheet(null, sheetName); @@ -154,8 +158,11 @@ public final class HSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E return _iBook.resolveNameXText(n.getSheetRefIndex(), n.getNameIndex()); } - public String getSheetNameByExternSheet(int externSheetIndex) { - return _iBook.findSheetNameFromExternSheet(externSheetIndex); + public String getSheetFirstNameByExternSheet(int externSheetIndex) { + return _iBook.findSheetFirstNameFromExternSheet(externSheetIndex); + } + public String getSheetLastNameByExternSheet(int externSheetIndex) { + return _iBook.findSheetLastNameFromExternSheet(externSheetIndex); } public String getNameText(NamePtg namePtg) { return _iBook.getNameRecord(namePtg.getIndex()).getNameText(); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFName.java b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java index b5a83eee9..f8c8af479 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFName.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFName.java @@ -21,8 +21,8 @@ import org.apache.poi.hssf.model.HSSFFormulaParser; import org.apache.poi.hssf.model.InternalWorkbook; import org.apache.poi.hssf.record.NameCommentRecord; import org.apache.poi.hssf.record.NameRecord; -import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.formula.FormulaType; +import org.apache.poi.ss.formula.ptg.Ptg; import org.apache.poi.ss.usermodel.Name; /** @@ -66,7 +66,7 @@ public final class HSSFName implements Name { public String getSheetName() { int indexToExternSheet = _definedNameRec.getExternSheetNumber(); - return _book.getWorkbook().findSheetNameFromExternSheet(indexToExternSheet); + return _book.getWorkbook().findSheetFirstNameFromExternSheet(indexToExternSheet); } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 5c85368ca..32a8391cd 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -675,7 +675,7 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss @Deprecated public String findSheetNameFromExternSheet(int externSheetIndex){ // TODO - don't expose internal ugliness like externSheet indexes to the user model API - return workbook.findSheetNameFromExternSheet(externSheetIndex); + return workbook.findSheetFirstNameFromExternSheet(externSheetIndex); } /** * @deprecated for POI internal use only (formula rendering). This method is likely to diff --git a/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java b/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java index 855ae5929..23474e87f 100644 --- a/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java +++ b/src/java/org/apache/poi/ss/formula/EvaluationWorkbook.java @@ -89,6 +89,20 @@ public interface EvaluationWorkbook { return _sheetName; } } + class ExternalSheetRange extends ExternalSheet { + private final String _lastSheetName; + public ExternalSheetRange(String workbookName, String firstSheetName, String lastSheetName) { + super(workbookName, firstSheetName); + this._lastSheetName = lastSheetName; + } + + public String getFirstSheetName() { + return getSheetName(); + } + public String getLastSheetName() { + return _lastSheetName; + } + } class ExternalName { private final String _nameName; private final int _nameNumber; diff --git a/src/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java b/src/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java index 0234ae65b..f918be4eb 100644 --- a/src/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java +++ b/src/java/org/apache/poi/ss/formula/FormulaRenderingWorkbook.java @@ -17,9 +17,9 @@ package org.apache.poi.ss.formula; +import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; import org.apache.poi.ss.formula.ptg.NamePtg; import org.apache.poi.ss.formula.ptg.NameXPtg; -import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; /** * Abstracts a workbook for the purpose of converting formula to text.
@@ -29,12 +29,20 @@ import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; * @author Josh Micich */ public interface FormulaRenderingWorkbook { - /** * @return null if externSheetIndex refers to a sheet inside the current workbook */ ExternalSheet getExternalSheet(int externSheetIndex); - String getSheetNameByExternSheet(int externSheetIndex); + + /** + * @return the name of the (first) sheet referred to by the given external sheet index + */ + String getSheetFirstNameByExternSheet(int externSheetIndex); + /** + * @return the name of the (last) sheet referred to by the given external sheet index + */ + String getSheetLastNameByExternSheet(int externSheetIndex); + String resolveNameXText(NameXPtg nameXPtg); String getNameText(NamePtg namePtg); } diff --git a/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java b/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java index a6cb76022..a61d1d575 100644 --- a/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java +++ b/src/java/org/apache/poi/ss/formula/ptg/ExternSheetNameResolver.java @@ -18,6 +18,7 @@ package org.apache.poi.ss.formula.ptg; import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheet; +import org.apache.poi.ss.formula.EvaluationWorkbook.ExternalSheetRange; import org.apache.poi.ss.formula.FormulaRenderingWorkbook; import org.apache.poi.ss.formula.SheetNameFormatter; @@ -42,14 +43,26 @@ final class ExternSheetNameResolver { sb = new StringBuffer(sheetName.length() + cellRefText.length() + 4); SheetNameFormatter.appendFormat(sb, sheetName); } + if (externalSheet instanceof ExternalSheetRange) { + ExternalSheetRange r = (ExternalSheetRange)externalSheet; + if (! r.getFirstSheetName().equals(r.getLastSheetName())) { + sb.append(':'); + SheetNameFormatter.appendFormat(sb, r.getLastSheetName()); + } + } } else { - String sheetName = book.getSheetNameByExternSheet(field_1_index_extern_sheet); - sb = new StringBuffer(sheetName.length() + cellRefText.length() + 4); - if (sheetName.length() < 1) { + String firstSheetName = book.getSheetFirstNameByExternSheet(field_1_index_extern_sheet); + String lastSheetName = book.getSheetLastNameByExternSheet(field_1_index_extern_sheet); + sb = new StringBuffer(firstSheetName.length() + cellRefText.length() + 4); + if (firstSheetName.length() < 1) { // What excel does if sheet has been deleted sb.append("#REF"); // note - '!' added just once below } else { - SheetNameFormatter.appendFormat(sb, sheetName); + SheetNameFormatter.appendFormat(sb, firstSheetName); + if (! firstSheetName.equals(lastSheetName)) { + sb.append(':'); + sb.append(lastSheetName); + } } } sb.append('!'); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java index d9486e3bc..84f6366fe 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFEvaluationWorkbook.java @@ -256,10 +256,14 @@ public final class XSSFEvaluationWorkbook implements FormulaRenderingWorkbook, E return _uBook.getSheetIndex(sheetName); } - public String getSheetNameByExternSheet(int externSheetIndex) { + public String getSheetFirstNameByExternSheet(int externSheetIndex) { int sheetIndex = convertFromExternalSheetIndex(externSheetIndex); return _uBook.getSheetName(sheetIndex); } + public String getSheetLastNameByExternSheet(int externSheetIndex) { + // XSSF does multi-sheet references differently, so this is the same as the first + return getSheetFirstNameByExternSheet(externSheetIndex); + } public String getNameText(NamePtg namePtg) { return _uBook.getNameAt(namePtg.getIndex()).getNameName(); diff --git a/src/testcases/org/apache/poi/hssf/eventusermodel/TestEventWorkbookBuilder.java b/src/testcases/org/apache/poi/hssf/eventusermodel/TestEventWorkbookBuilder.java index 1b02cf241..37b77423b 100644 --- a/src/testcases/org/apache/poi/hssf/eventusermodel/TestEventWorkbookBuilder.java +++ b/src/testcases/org/apache/poi/hssf/eventusermodel/TestEventWorkbookBuilder.java @@ -78,9 +78,9 @@ public final class TestEventWorkbookBuilder extends TestCase { assertEquals(3, listener.getStubWorkbook().getNumSheets()); InternalWorkbook ref = listener.getStubWorkbook(); - assertEquals("Sh3", ref.findSheetNameFromExternSheet(0)); - assertEquals("Sheet1", ref.findSheetNameFromExternSheet(1)); - assertEquals("S2", ref.findSheetNameFromExternSheet(2)); + assertEquals("Sh3", ref.findSheetFirstNameFromExternSheet(0)); + assertEquals("Sheet1", ref.findSheetFirstNameFromExternSheet(1)); + assertEquals("S2", ref.findSheetFirstNameFromExternSheet(2)); } public void testFormulas() {