diff options
author | PJ Fanning <fanningpj@apache.org> | 2017-10-31 10:24:47 +0000 |
---|---|---|
committer | PJ Fanning <fanningpj@apache.org> | 2017-10-31 10:24:47 +0000 |
commit | aa9b57774f628bd3a67dcc6afa94f7e128bfa8a7 (patch) | |
tree | 650e203f4c432a160d1f16a4a7c682925c4da3ce /src/java/org/apache/poi/hssf | |
parent | cb28546f501a5802e250ff1fc07383472b1cbac7 (diff) | |
download | poi-aa9b57774f628bd3a67dcc6afa94f7e128bfa8a7.tar.gz poi-aa9b57774f628bd3a67dcc6afa94f7e128bfa8a7.zip |
use StringBuilder in more places
git-svn-id: https://svn.apache.org/repos/asf/poi/trunk@1813869 13f79535-47bb-0310-9956-ffa450edef68
Diffstat (limited to 'src/java/org/apache/poi/hssf')
-rw-r--r-- | src/java/org/apache/poi/hssf/model/LinkTable.java | 1002 |
1 files changed, 504 insertions, 498 deletions
diff --git a/src/java/org/apache/poi/hssf/model/LinkTable.java b/src/java/org/apache/poi/hssf/model/LinkTable.java index b55e7b952f..53ef5d6e96 100644 --- a/src/java/org/apache/poi/hssf/model/LinkTable.java +++ b/src/java/org/apache/poi/hssf/model/LinkTable.java @@ -41,137 +41,139 @@ import org.apache.poi.ss.usermodel.Workbook; /** * Link Table (OOO pdf reference: 4.10.3 ) <p> - * + * <p> * The main data of all types of references is stored in the Link Table inside the Workbook Globals * Substream (4.2.5). The Link Table itself is optional and occurs only if there are any * references in the document. - * <p> - * - * In BIFF8 the Link Table consists of - * <ul> - * <li>zero or more EXTERNALBOOK Blocks<p> - * each consisting of - * <ul> - * <li>exactly one EXTERNALBOOK (0x01AE) record</li> - * <li>zero or more EXTERNALNAME (0x0023) records</li> - * <li>zero or more CRN Blocks<p> - * each consisting of - * <ul> - * <li>exactly one XCT (0x0059)record</li> - * <li>zero or more CRN (0x005A) records (documentation says one or more)</li> - * </ul> - * </li> - * </ul> - * </li> - * <li>zero or one EXTERNSHEET (0x0017) record</li> - * <li>zero or more DEFINEDNAME (0x0018) records</li> - * </ul> + * <p> + * <p> + * In BIFF8 the Link Table consists of + * <ul> + * <li>zero or more EXTERNALBOOK Blocks<p> + * each consisting of + * <ul> + * <li>exactly one EXTERNALBOOK (0x01AE) record</li> + * <li>zero or more EXTERNALNAME (0x0023) records</li> + * <li>zero or more CRN Blocks<p> + * each consisting of + * <ul> + * <li>exactly one XCT (0x0059)record</li> + * <li>zero or more CRN (0x005A) records (documentation says one or more)</li> + * </ul> + * </li> + * </ul> + * </li> + * <li>zero or one EXTERNSHEET (0x0017) record</li> + * <li>zero or more DEFINEDNAME (0x0018) records</li> + * </ul> */ final class LinkTable { - // TODO make this class into a record aggregate - private static final class CRNBlock { - - private final CRNCountRecord _countRecord; - private final CRNRecord[] _crns; - - public CRNBlock(RecordStream rs) { - _countRecord = (CRNCountRecord) rs.getNext(); - int nCRNs = _countRecord.getNumberOfCRNs(); - CRNRecord[] crns = new CRNRecord[nCRNs]; - for (int i = 0; i < crns.length; i++) { - crns[i] = (CRNRecord) rs.getNext(); - } - _crns = crns; - } - public CRNRecord[] getCrns() { - return _crns.clone(); - } - } - - private static final class ExternalBookBlock { - private final SupBookRecord _externalBookRecord; - private ExternalNameRecord[] _externalNameRecords; - private final CRNBlock[] _crnBlocks; - - public ExternalBookBlock(RecordStream rs) { - _externalBookRecord = (SupBookRecord) rs.getNext(); - List<Object> temp = new ArrayList<>(); - while(rs.peekNextClass() == ExternalNameRecord.class) { - temp.add(rs.getNext()); - } - _externalNameRecords = new ExternalNameRecord[temp.size()]; - temp.toArray(_externalNameRecords); - - temp.clear(); - - while(rs.peekNextClass() == CRNCountRecord.class) { - temp.add(new CRNBlock(rs)); - } - _crnBlocks = new CRNBlock[temp.size()]; - temp.toArray(_crnBlocks); - } - - /** - * Create a new block for external references. - */ - public ExternalBookBlock(String url, String[] sheetNames) { - _externalBookRecord = SupBookRecord.createExternalReferences(url, sheetNames); - _crnBlocks = new CRNBlock[0]; - } - - /** - * Create a new block for internal references. It is called when constructing a new LinkTable. - * - * @see org.apache.poi.hssf.model.LinkTable#LinkTable(int, WorkbookRecordList) - */ - public ExternalBookBlock(int numberOfSheets) { - _externalBookRecord = SupBookRecord.createInternalReferences((short)numberOfSheets); - _externalNameRecords = new ExternalNameRecord[0]; - _crnBlocks = new CRNBlock[0]; - } - - /** - * Create a new block for registering add-in functions - * - * @see org.apache.poi.hssf.model.LinkTable#addNameXPtg(String) - */ - public ExternalBookBlock() { - _externalBookRecord = SupBookRecord.createAddInFunctions(); - _externalNameRecords = new ExternalNameRecord[0]; - _crnBlocks = new CRNBlock[0]; - } - - public SupBookRecord getExternalBookRecord() { - return _externalBookRecord; - } - - public String getNameText(int definedNameIndex) { - return _externalNameRecords[definedNameIndex].getText(); - } - - public int getNameIx(int definedNameIndex) { - return _externalNameRecords[definedNameIndex].getIx(); - } - - /** - * Performs case-insensitive search - * @return -1 if not found - */ - public int getIndexOfName(String name) { - for (int i = 0; i < _externalNameRecords.length; i++) { - if(_externalNameRecords[i].getText().equalsIgnoreCase(name)) { - return i; - } - } - return -1; - } + // TODO make this class into a record aggregate + private static final class CRNBlock { + + private final CRNCountRecord _countRecord; + private final CRNRecord[] _crns; + + public CRNBlock(RecordStream rs) { + _countRecord = (CRNCountRecord) rs.getNext(); + int nCRNs = _countRecord.getNumberOfCRNs(); + CRNRecord[] crns = new CRNRecord[nCRNs]; + for (int i = 0; i < crns.length; i++) { + crns[i] = (CRNRecord) rs.getNext(); + } + _crns = crns; + } + + public CRNRecord[] getCrns() { + return _crns.clone(); + } + } + + private static final class ExternalBookBlock { + private final SupBookRecord _externalBookRecord; + private ExternalNameRecord[] _externalNameRecords; + private final CRNBlock[] _crnBlocks; + + public ExternalBookBlock(RecordStream rs) { + _externalBookRecord = (SupBookRecord) rs.getNext(); + List<Object> temp = new ArrayList<>(); + while (rs.peekNextClass() == ExternalNameRecord.class) { + temp.add(rs.getNext()); + } + _externalNameRecords = new ExternalNameRecord[temp.size()]; + temp.toArray(_externalNameRecords); + + temp.clear(); + + while (rs.peekNextClass() == CRNCountRecord.class) { + temp.add(new CRNBlock(rs)); + } + _crnBlocks = new CRNBlock[temp.size()]; + temp.toArray(_crnBlocks); + } + + /** + * Create a new block for external references. + */ + public ExternalBookBlock(String url, String[] sheetNames) { + _externalBookRecord = SupBookRecord.createExternalReferences(url, sheetNames); + _crnBlocks = new CRNBlock[0]; + } + + /** + * Create a new block for internal references. It is called when constructing a new LinkTable. + * + * @see org.apache.poi.hssf.model.LinkTable#LinkTable(int, WorkbookRecordList) + */ + public ExternalBookBlock(int numberOfSheets) { + _externalBookRecord = SupBookRecord.createInternalReferences((short) numberOfSheets); + _externalNameRecords = new ExternalNameRecord[0]; + _crnBlocks = new CRNBlock[0]; + } + + /** + * Create a new block for registering add-in functions + * + * @see org.apache.poi.hssf.model.LinkTable#addNameXPtg(String) + */ + public ExternalBookBlock() { + _externalBookRecord = SupBookRecord.createAddInFunctions(); + _externalNameRecords = new ExternalNameRecord[0]; + _crnBlocks = new CRNBlock[0]; + } + + public SupBookRecord getExternalBookRecord() { + return _externalBookRecord; + } + + public String getNameText(int definedNameIndex) { + return _externalNameRecords[definedNameIndex].getText(); + } + + public int getNameIx(int definedNameIndex) { + return _externalNameRecords[definedNameIndex].getIx(); + } + + /** + * Performs case-insensitive search + * + * @return -1 if not found + */ + public int getIndexOfName(String name) { + for (int i = 0; i < _externalNameRecords.length; i++) { + if (_externalNameRecords[i].getText().equalsIgnoreCase(name)) { + return i; + } + } + return -1; + } public int getNumberOfNames() { return _externalNameRecords.length; } - public int addExternalName(ExternalNameRecord rec){ + public int addExternalName(ExternalNameRecord rec) { ExternalNameRecord[] tmp = new ExternalNameRecord[_externalNameRecords.length + 1]; System.arraycopy(_externalNameRecords, 0, tmp, 0, _externalNameRecords.length); tmp[tmp.length - 1] = rec; @@ -181,245 +183,243 @@ final class LinkTable { } private ExternalBookBlock[] _externalBookBlocks; - private final ExternSheetRecord _externSheetRecord; - private final List<NameRecord> _definedNames; - private final int _recordCount; - private final WorkbookRecordList _workbookRecordList; // TODO - would be nice to remove this - - public LinkTable(List<Record> inputList, int startIndex, WorkbookRecordList workbookRecordList, Map<String, NameCommentRecord> commentRecords) { - - _workbookRecordList = workbookRecordList; - RecordStream rs = new RecordStream(inputList, startIndex); - - List<ExternalBookBlock> temp = new ArrayList<>(); - while(rs.peekNextClass() == SupBookRecord.class) { - temp.add(new ExternalBookBlock(rs)); - } - - _externalBookBlocks = new ExternalBookBlock[temp.size()]; - temp.toArray(_externalBookBlocks); - temp.clear(); - - if (_externalBookBlocks.length > 0) { - // If any ExternalBookBlock present, there is always 1 of ExternSheetRecord - if (rs.peekNextClass() != ExternSheetRecord.class) { - // not quite - if written by google docs - _externSheetRecord = null; - } else { - _externSheetRecord = readExtSheetRecord(rs); - } - } else { - _externSheetRecord = null; - } - - _definedNames = new ArrayList<>(); - // collect zero or more DEFINEDNAMEs id=0x18, - // with their comments if present - while(true) { - Class<? extends Record> nextClass = rs.peekNextClass(); - if (nextClass == NameRecord.class) { - NameRecord nr = (NameRecord)rs.getNext(); - _definedNames.add(nr); - } - else if (nextClass == NameCommentRecord.class) { - NameCommentRecord ncr = (NameCommentRecord)rs.getNext(); - commentRecords.put(ncr.getNameText(), ncr); - } - else { - break; - } - } - - _recordCount = rs.getCountRead(); - _workbookRecordList.getRecords().addAll(inputList.subList(startIndex, startIndex + _recordCount)); - } - - private static ExternSheetRecord readExtSheetRecord(RecordStream rs) { - List<ExternSheetRecord> temp = new ArrayList<>(2); - while(rs.peekNextClass() == ExternSheetRecord.class) { - temp.add((ExternSheetRecord) rs.getNext()); - } - - int nItems = temp.size(); - if (nItems < 1) { - throw new RuntimeException("Expected an EXTERNSHEET record but got (" - + rs.peekNextClass().getName() + ")"); - } - if (nItems == 1) { - // this is the normal case. There should be just one ExternSheetRecord - return temp.get(0); - } - // Some apps generate multiple ExternSheetRecords (see bug 45698). - // It seems like the best thing to do might be to combine these into one - ExternSheetRecord[] esrs = new ExternSheetRecord[nItems]; - temp.toArray(esrs); - return ExternSheetRecord.combine(esrs); - } - - public LinkTable(int numberOfSheets, WorkbookRecordList workbookRecordList) { - _workbookRecordList = workbookRecordList; - _definedNames = new ArrayList<>(); - _externalBookBlocks = new ExternalBookBlock[] { - new ExternalBookBlock(numberOfSheets), - }; - _externSheetRecord = new ExternSheetRecord(); - _recordCount = 2; - - // tell _workbookRecordList about the 2 new records - - SupBookRecord supbook = _externalBookBlocks[0].getExternalBookRecord(); - - int idx = findFirstRecordLocBySid(CountryRecord.sid); - if(idx < 0) { - throw new RuntimeException("CountryRecord not found"); - } - _workbookRecordList.add(idx+1, _externSheetRecord); - _workbookRecordList.add(idx+1, supbook); - } - - /** - * TODO - would not be required if calling code used RecordStream or similar - */ - public int getRecordCount() { - return _recordCount; - } - - - /** - * @param builtInCode a BUILTIN_~ constant from {@link NameRecord} - * @param sheetNumber 1-based sheet number - */ - public NameRecord getSpecificBuiltinRecord(byte builtInCode, int sheetNumber) { - Iterator<NameRecord> iterator = _definedNames.iterator(); - while (iterator.hasNext()) { - NameRecord record = iterator.next(); - - //print areas are one based - if (record.getBuiltInName() == builtInCode && record.getSheetNumber() == sheetNumber) { - return record; - } - } - - return null; - } - - public void removeBuiltinRecord(byte name, int sheetIndex) { - //the name array is smaller so searching through it should be faster than - //using the findFirstXXXX methods - NameRecord record = getSpecificBuiltinRecord(name, sheetIndex); - if (record != null) { - _definedNames.remove(record); - } - // TODO - do we need "Workbook.records.remove(...);" similar to that in Workbook.removeName(int namenum) {}? - } - - public int getNumNames() { - return _definedNames.size(); - } - - public NameRecord getNameRecord(int index) { - return _definedNames.get(index); - } - - public void addName(NameRecord name) { - _definedNames.add(name); - - // TODO - this is messy - // Not the most efficient way but the other way was causing too many bugs - int idx = findFirstRecordLocBySid(ExternSheetRecord.sid); - if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid); - if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid); - int countNames = _definedNames.size(); - _workbookRecordList.add(idx+countNames, name); - } - - public void removeName(int namenum) { - _definedNames.remove(namenum); - } - - /** - * checks if the given name is already included in the linkTable - */ - public boolean nameAlreadyExists(NameRecord name) - { - // Check to ensure no other names have the same case-insensitive name - for ( int i = getNumNames()-1; i >=0; i-- ) { - NameRecord rec = getNameRecord(i); - if (rec != name) { - if (isDuplicatedNames(name, rec)) - return true; - } - } - return false; - } - - private static boolean isDuplicatedNames(NameRecord firstName, NameRecord lastName) { - return lastName.getNameText().equalsIgnoreCase(firstName.getNameText()) - && isSameSheetNames(firstName, lastName); - } - private static boolean isSameSheetNames(NameRecord firstName, NameRecord lastName) { - return lastName.getSheetNumber() == firstName.getSheetNumber(); - } - - public String[] getExternalBookAndSheetName(int extRefIndex) { - int ebIx = _externSheetRecord.getExtbookIndexFromRefIndex(extRefIndex); - SupBookRecord ebr = _externalBookBlocks[ebIx].getExternalBookRecord(); - if (!ebr.isExternalReferences()) { - return null; - } - // Sheet name only applies if not a global reference - int shIx1 = _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex); + private final ExternSheetRecord _externSheetRecord; + private final List<NameRecord> _definedNames; + private final int _recordCount; + private final WorkbookRecordList _workbookRecordList; // TODO - would be nice to remove this + + public LinkTable(List<Record> inputList, int startIndex, WorkbookRecordList workbookRecordList, Map<String, NameCommentRecord> commentRecords) { + + _workbookRecordList = workbookRecordList; + RecordStream rs = new RecordStream(inputList, startIndex); + + List<ExternalBookBlock> temp = new ArrayList<>(); + while (rs.peekNextClass() == SupBookRecord.class) { + temp.add(new ExternalBookBlock(rs)); + } + + _externalBookBlocks = new ExternalBookBlock[temp.size()]; + temp.toArray(_externalBookBlocks); + temp.clear(); + + if (_externalBookBlocks.length > 0) { + // If any ExternalBookBlock present, there is always 1 of ExternSheetRecord + if (rs.peekNextClass() != ExternSheetRecord.class) { + // not quite - if written by google docs + _externSheetRecord = null; + } else { + _externSheetRecord = readExtSheetRecord(rs); + } + } else { + _externSheetRecord = null; + } + + _definedNames = new ArrayList<>(); + // collect zero or more DEFINEDNAMEs id=0x18, + // with their comments if present + while (true) { + Class<? extends Record> nextClass = rs.peekNextClass(); + if (nextClass == NameRecord.class) { + NameRecord nr = (NameRecord) rs.getNext(); + _definedNames.add(nr); + } else if (nextClass == NameCommentRecord.class) { + NameCommentRecord ncr = (NameCommentRecord) rs.getNext(); + commentRecords.put(ncr.getNameText(), ncr); + } else { + break; + } + } + + _recordCount = rs.getCountRead(); + _workbookRecordList.getRecords().addAll(inputList.subList(startIndex, startIndex + _recordCount)); + } + + private static ExternSheetRecord readExtSheetRecord(RecordStream rs) { + List<ExternSheetRecord> temp = new ArrayList<>(2); + while (rs.peekNextClass() == ExternSheetRecord.class) { + temp.add((ExternSheetRecord) rs.getNext()); + } + + int nItems = temp.size(); + if (nItems < 1) { + throw new RuntimeException("Expected an EXTERNSHEET record but got (" + + rs.peekNextClass().getName() + ")"); + } + if (nItems == 1) { + // this is the normal case. There should be just one ExternSheetRecord + return temp.get(0); + } + // Some apps generate multiple ExternSheetRecords (see bug 45698). + // It seems like the best thing to do might be to combine these into one + ExternSheetRecord[] esrs = new ExternSheetRecord[nItems]; + temp.toArray(esrs); + return ExternSheetRecord.combine(esrs); + } + + public LinkTable(int numberOfSheets, WorkbookRecordList workbookRecordList) { + _workbookRecordList = workbookRecordList; + _definedNames = new ArrayList<>(); + _externalBookBlocks = new ExternalBookBlock[]{ + new ExternalBookBlock(numberOfSheets), + }; + _externSheetRecord = new ExternSheetRecord(); + _recordCount = 2; + + // tell _workbookRecordList about the 2 new records + + SupBookRecord supbook = _externalBookBlocks[0].getExternalBookRecord(); + + int idx = findFirstRecordLocBySid(CountryRecord.sid); + if (idx < 0) { + throw new RuntimeException("CountryRecord not found"); + } + _workbookRecordList.add(idx + 1, _externSheetRecord); + _workbookRecordList.add(idx + 1, supbook); + } + + /** + * TODO - would not be required if calling code used RecordStream or similar + */ + public int getRecordCount() { + return _recordCount; + } + + + /** + * @param builtInCode a BUILTIN_~ constant from {@link NameRecord} + * @param sheetNumber 1-based sheet number + */ + public NameRecord getSpecificBuiltinRecord(byte builtInCode, int sheetNumber) { + Iterator<NameRecord> iterator = _definedNames.iterator(); + while (iterator.hasNext()) { + NameRecord record = iterator.next(); + + //print areas are one based + if (record.getBuiltInName() == builtInCode && record.getSheetNumber() == sheetNumber) { + return record; + } + } + + return null; + } + + public void removeBuiltinRecord(byte name, int sheetIndex) { + //the name array is smaller so searching through it should be faster than + //using the findFirstXXXX methods + NameRecord record = getSpecificBuiltinRecord(name, sheetIndex); + if (record != null) { + _definedNames.remove(record); + } + // TODO - do we need "Workbook.records.remove(...);" similar to that in Workbook.removeName(int namenum) {}? + } + + public int getNumNames() { + return _definedNames.size(); + } + + public NameRecord getNameRecord(int index) { + return _definedNames.get(index); + } + + public void addName(NameRecord name) { + _definedNames.add(name); + + // TODO - this is messy + // Not the most efficient way but the other way was causing too many bugs + int idx = findFirstRecordLocBySid(ExternSheetRecord.sid); + if (idx == -1) idx = findFirstRecordLocBySid(SupBookRecord.sid); + if (idx == -1) idx = findFirstRecordLocBySid(CountryRecord.sid); + int countNames = _definedNames.size(); + _workbookRecordList.add(idx + countNames, name); + } + + public void removeName(int namenum) { + _definedNames.remove(namenum); + } + + /** + * checks if the given name is already included in the linkTable + */ + public boolean nameAlreadyExists(NameRecord name) { + // Check to ensure no other names have the same case-insensitive name + for (int i = getNumNames() - 1; i >= 0; i--) { + NameRecord rec = getNameRecord(i); + if (rec != name) { + if (isDuplicatedNames(name, rec)) + return true; + } + } + return false; + } + + private static boolean isDuplicatedNames(NameRecord firstName, NameRecord lastName) { + return lastName.getNameText().equalsIgnoreCase(firstName.getNameText()) + && isSameSheetNames(firstName, lastName); + } + + private static boolean isSameSheetNames(NameRecord firstName, NameRecord lastName) { + return lastName.getSheetNumber() == firstName.getSheetNumber(); + } + + public String[] getExternalBookAndSheetName(int extRefIndex) { + int ebIx = _externSheetRecord.getExtbookIndexFromRefIndex(extRefIndex); + SupBookRecord ebr = _externalBookBlocks[ebIx].getExternalBookRecord(); + if (!ebr.isExternalReferences()) { + return null; + } + // Sheet name only applies if not a global reference + int shIx1 = _externSheetRecord.getFirstSheetIndexFromRefIndex(extRefIndex); int shIx2 = _externSheetRecord.getLastSheetIndexFromRefIndex(extRefIndex); - String firstSheetName = null; + 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[] { + 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 }; - } - } - - private int getExternalWorkbookIndex(String workbookName) { - for (int i=0; i<_externalBookBlocks.length; i++) { - SupBookRecord ebr = _externalBookBlocks[i].getExternalBookRecord(); - if (!ebr.isExternalReferences()) { - continue; - } - if (workbookName.equals(ebr.getURL())) { // not sure if 'equals()' works when url has a directory - return i; - } - } - return -1; - } - - public int linkExternalWorkbook(String name, Workbook externalWorkbook) { + } + } + + private int getExternalWorkbookIndex(String workbookName) { + for (int i = 0; i < _externalBookBlocks.length; i++) { + SupBookRecord ebr = _externalBookBlocks[i].getExternalBookRecord(); + if (!ebr.isExternalReferences()) { + continue; + } + if (workbookName.equals(ebr.getURL())) { // not sure if 'equals()' works when url has a directory + return i; + } + } + return -1; + } + + public int linkExternalWorkbook(String name, Workbook externalWorkbook) { int extBookIndex = getExternalWorkbookIndex(name); if (extBookIndex != -1) { // Already linked! return extBookIndex; } - + // Create a new SupBookRecord String[] sheetNames = new String[externalWorkbook.getNumberOfSheets()]; - for (int sn=0; sn<sheetNames.length; sn++) { + for (int sn = 0; sn < sheetNames.length; sn++) { sheetNames[sn] = externalWorkbook.getSheetName(sn); } String url = "\000" + name; ExternalBookBlock block = new ExternalBookBlock(url, sheetNames); - + // Add it into the list + records extBookIndex = extendExternalBookBlocks(block); @@ -429,54 +429,55 @@ final class LinkTable { idx = _workbookRecordList.size(); } _workbookRecordList.add(idx, block.getExternalBookRecord()); - + // Setup links for the sheets - for (int sn=0; sn<sheetNames.length; sn++) { + for (int sn = 0; sn < sheetNames.length; sn++) { _externSheetRecord.addRef(extBookIndex, sn, sn); } - + // Report where it went return extBookIndex; - } + } - public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) { - int externalBookIndex = getExternalWorkbookIndex(workbookName); + public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) { + int externalBookIndex = getExternalWorkbookIndex(workbookName); if (externalBookIndex == -1) { throw new RuntimeException("No external workbook with name '" + workbookName + "'"); } SupBookRecord ebrTarget = _externalBookBlocks[externalBookIndex].getExternalBookRecord(); - int firstSheetIndex = getSheetIndex(ebrTarget.getSheetNames(), firstSheetName); + int firstSheetIndex = getSheetIndex(ebrTarget.getSheetNames(), firstSheetName); int lastSheetIndex = getSheetIndex(ebrTarget.getSheetNames(), lastSheetName); // Find or add the external sheet record definition for this - int result = _externSheetRecord.getRefIxForSheet(externalBookIndex, firstSheetIndex, lastSheetIndex); - if (result < 0) { - result = _externSheetRecord.addRef(externalBookIndex, firstSheetIndex, lastSheetIndex); - } - return result; - } - - private static int getSheetIndex(String[] sheetNames, String sheetName) { - for (int i = 0; i < sheetNames.length; i++) { - if (sheetNames[i].equals(sheetName)) { - return i; - } - - } - throw new RuntimeException("External workbook does not contain sheet '" + sheetName + "'"); - } - - /** - * @param extRefIndex as from a {@link Ref3DPtg} or {@link Area3DPtg} - * @return -1 if the reference is to an external book - */ - public int getFirstInternalSheetIndexForExtIndex(int extRefIndex) { + int result = _externSheetRecord.getRefIxForSheet(externalBookIndex, firstSheetIndex, lastSheetIndex); + if (result < 0) { + result = _externSheetRecord.addRef(externalBookIndex, firstSheetIndex, lastSheetIndex); + } + return result; + } + + private static int getSheetIndex(String[] sheetNames, String sheetName) { + for (int i = 0; i < sheetNames.length; i++) { + if (sheetNames[i].equals(sheetName)) { + return i; + } + + } + throw new RuntimeException("External workbook does not contain sheet '" + sheetName + "'"); + } + + /** + * @param extRefIndex as from a {@link Ref3DPtg} or {@link Area3DPtg} + * @return -1 if the reference is to an external book + */ + public int getFirstInternalSheetIndexForExtIndex(int extRefIndex) { if (extRefIndex >= _externSheetRecord.getNumOfRefs() || extRefIndex < 0) { return -1; } - return _externSheetRecord.getFirstSheetIndexFromRefIndex(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 @@ -488,117 +489,120 @@ final class LinkTable { return _externSheetRecord.getLastSheetIndexFromRefIndex(extRefIndex); } - public void removeSheet(int sheetIdx) { - _externSheetRecord.removeSheet(sheetIdx); - } + public void removeSheet(int sheetIdx) { + _externSheetRecord.removeSheet(sheetIdx); + } + + public int checkExternSheet(int sheetIndex) { + return checkExternSheet(sheetIndex, sheetIndex); + } - 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(); - if (ebr.isInternalReferences()) { - thisWbIndex = i; - break; - } - } - if (thisWbIndex < 0) { - throw new RuntimeException("Could not find 'internal references' EXTERNALBOOK"); - } - - //Trying to find reference to this sheet - int i = _externSheetRecord.getRefIxForSheet(thisWbIndex, firstSheetIndex, lastSheetIndex); - if (i>=0) { - return i; - } - //We haven't found reference to this sheet - return _externSheetRecord.addRef(thisWbIndex, firstSheetIndex, lastSheetIndex); - } - - /** - * copied from Workbook - */ - private int findFirstRecordLocBySid(short sid) { - int index = 0; - for (Record record : _workbookRecordList.getRecords()) { - if (record.getSid() == sid) { - return index; - } - index ++; - } - return -1; - } - - public String resolveNameXText(int refIndex, int definedNameIndex, InternalWorkbook workbook) { + int thisWbIndex = -1; // this is probably always zero + for (int i = 0; i < _externalBookBlocks.length; i++) { + SupBookRecord ebr = _externalBookBlocks[i].getExternalBookRecord(); + if (ebr.isInternalReferences()) { + thisWbIndex = i; + break; + } + } + if (thisWbIndex < 0) { + throw new RuntimeException("Could not find 'internal references' EXTERNALBOOK"); + } + + //Trying to find reference to this sheet + int i = _externSheetRecord.getRefIxForSheet(thisWbIndex, firstSheetIndex, lastSheetIndex); + if (i >= 0) { + return i; + } + //We haven't found reference to this sheet + return _externSheetRecord.addRef(thisWbIndex, firstSheetIndex, lastSheetIndex); + } + + /** + * copied from Workbook + */ + private int findFirstRecordLocBySid(short sid) { + int index = 0; + for (Record record : _workbookRecordList.getRecords()) { + if (record.getSid() == sid) { + return index; + } + index++; + } + return -1; + } + + public String resolveNameXText(int refIndex, int definedNameIndex, InternalWorkbook workbook) { int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex); int firstTabIndex = _externSheetRecord.getFirstSheetIndexFromRefIndex(refIndex); - if (firstTabIndex == -1) { - // The referenced sheet could not be found + if (firstTabIndex == -1) { + // The referenced sheet could not be found throw new RuntimeException("Referenced sheet could not be found"); - } - - // Does it exist via the external book block? - ExternalBookBlock externalBook = _externalBookBlocks[extBookIndex]; - if (externalBook._externalNameRecords.length > definedNameIndex) { + } + + // Does it exist via the external book block? + ExternalBookBlock externalBook = _externalBookBlocks[extBookIndex]; + if (externalBook._externalNameRecords.length > definedNameIndex) { return _externalBookBlocks[extBookIndex].getNameText(definedNameIndex); - } else if (firstTabIndex == -2) { - // Workbook scoped name, not actually external after all - NameRecord nr = getNameRecord(definedNameIndex); - int sheetNumber = nr.getSheetNumber(); - - StringBuilder text = new StringBuilder(64); - if (sheetNumber > 0) { - String sheetName = workbook.getSheetName(sheetNumber-1); - SheetNameFormatter.appendFormat(text, sheetName); - text.append("!"); - } - text.append(nr.getNameText()); - return text.toString(); - } else { - throw new ArrayIndexOutOfBoundsException( - "Ext Book Index relative but beyond the supported length, was " + - extBookIndex + " but maximum is " + _externalBookBlocks.length - ); - } - } - public int resolveNameXIx(int refIndex, int definedNameIndex) { - int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex); - return _externalBookBlocks[extBookIndex].getNameIx(definedNameIndex); - } - - /** - * Finds the external name definition for the given name, - * optionally restricted by externsheet index, and returns - * (if found) as a NameXPtg. - * @param sheetRefIndex The Extern Sheet Index to look for, or -1 if any - */ - public NameXPtg getNameXPtg(String name, int sheetRefIndex) { - // first find any external book block that contains the name: - for (int i = 0; i < _externalBookBlocks.length; i++) { - int definedNameIndex = _externalBookBlocks[i].getIndexOfName(name); - if (definedNameIndex < 0) { - continue; - } - - // Found one - int thisSheetRefIndex = findRefIndexFromExtBookIndex(i); - if (thisSheetRefIndex >= 0) { - // Check for the sheet index match, if requested - if (sheetRefIndex == -1 || thisSheetRefIndex == sheetRefIndex) { - return new NameXPtg(thisSheetRefIndex, definedNameIndex); - } - } - } - return null; - } + } else if (firstTabIndex == -2) { + // Workbook scoped name, not actually external after all + NameRecord nr = getNameRecord(definedNameIndex); + int sheetNumber = nr.getSheetNumber(); + + StringBuilder text = new StringBuilder(64); + if (sheetNumber > 0) { + String sheetName = workbook.getSheetName(sheetNumber - 1); + SheetNameFormatter.appendFormat(text, sheetName); + text.append("!"); + } + text.append(nr.getNameText()); + return text.toString(); + } else { + throw new ArrayIndexOutOfBoundsException( + "Ext Book Index relative but beyond the supported length, was " + + extBookIndex + " but maximum is " + _externalBookBlocks.length + ); + } + } + + public int resolveNameXIx(int refIndex, int definedNameIndex) { + int extBookIndex = _externSheetRecord.getExtbookIndexFromRefIndex(refIndex); + return _externalBookBlocks[extBookIndex].getNameIx(definedNameIndex); + } + + /** + * Finds the external name definition for the given name, + * optionally restricted by externsheet index, and returns + * (if found) as a NameXPtg. + * + * @param sheetRefIndex The Extern Sheet Index to look for, or -1 if any + */ + public NameXPtg getNameXPtg(String name, int sheetRefIndex) { + // first find any external book block that contains the name: + for (int i = 0; i < _externalBookBlocks.length; i++) { + int definedNameIndex = _externalBookBlocks[i].getIndexOfName(name); + if (definedNameIndex < 0) { + continue; + } + + // Found one + int thisSheetRefIndex = findRefIndexFromExtBookIndex(i); + if (thisSheetRefIndex >= 0) { + // Check for the sheet index match, if requested + if (sheetRefIndex == -1 || thisSheetRefIndex == sheetRefIndex) { + return new NameXPtg(thisSheetRefIndex, definedNameIndex); + } + } + } + return null; + } /** * Register an external name in this workbook * - * @param name the name to register - * @return a NameXPtg describing this name + * @param name the name to register + * @return a NameXPtg describing this name */ public NameXPtg addNameXPtg(String name) { int extBlockIndex = -1; @@ -650,6 +654,7 @@ final class LinkTable { int ix = _externSheetRecord.getRefIxForSheet(extBlockIndex, fakeSheetIdx, fakeSheetIdx); return new NameXPtg(ix, nameIndex); } + private int extendExternalBookBlocks(ExternalBookBlock newBlock) { ExternalBookBlock[] tmp = new ExternalBookBlock[_externalBookBlocks.length + 1]; System.arraycopy(_externalBookBlocks, 0, tmp, 0, _externalBookBlocks.length); @@ -660,29 +665,30 @@ final class LinkTable { } private int findRefIndexFromExtBookIndex(int extBookIndex) { - return _externSheetRecord.findRefIndexFromExtBookIndex(extBookIndex); - } - - /** - * Changes an external referenced file to another file. - * A formular in Excel which refers a cell in another file is saved in two parts: - * The referenced file is stored in an reference table. the row/cell information is saved separate. - * This method invokation will only change the reference in the lookup-table itself. - * @param oldUrl The old URL to search for and which is to be replaced - * @param newUrl The URL replacement - * @return true if the oldUrl was found and replaced with newUrl. Otherwise false - */ - public boolean changeExternalReference(String oldUrl, String newUrl) { - for(ExternalBookBlock ex : _externalBookBlocks) { - SupBookRecord externalRecord = ex.getExternalBookRecord(); - if (externalRecord.isExternalReferences() - && externalRecord.getURL().equals(oldUrl)) { - - externalRecord.setURL(newUrl); - return true; - } - } - return false; - } + return _externSheetRecord.findRefIndexFromExtBookIndex(extBookIndex); + } + + /** + * Changes an external referenced file to another file. + * A formular in Excel which refers a cell in another file is saved in two parts: + * The referenced file is stored in an reference table. the row/cell information is saved separate. + * This method invokation will only change the reference in the lookup-table itself. + * + * @param oldUrl The old URL to search for and which is to be replaced + * @param newUrl The URL replacement + * @return true if the oldUrl was found and replaced with newUrl. Otherwise false + */ + public boolean changeExternalReference(String oldUrl, String newUrl) { + for (ExternalBookBlock ex : _externalBookBlocks) { + SupBookRecord externalRecord = ex.getExternalBookRecord(); + if (externalRecord.isExternalReferences() + && externalRecord.getURL().equals(oldUrl)) { + + externalRecord.setURL(newUrl); + return true; + } + } + return false; + } } |