View | Details | Raw Unified | Return to bug 60219
Collapse All | Expand All

(-)src/java/org/apache/poi/hssf/model/InternalWorkbook.java (+4 lines)
Lines 1918-1923 Link Here
1918
        return getOrCreateLinkTable().linkExternalWorkbook(name, externalWorkbook);
1918
        return getOrCreateLinkTable().linkExternalWorkbook(name, externalWorkbook);
1919
    }
1919
    }
1920
1920
1921
    public int linkExternalWorkbook(String name, String sheetNames[]) {
1922
        return getOrCreateLinkTable().linkExternalWorkbook(name, sheetNames);
1923
    }
1924
    
1921
    /** 
1925
    /** 
1922
     * Finds the first sheet name by his extern sheet index
1926
     * Finds the first sheet name by his extern sheet index
1923
     * @param externSheetIndex extern sheet index
1927
     * @param externSheetIndex extern sheet index
(-)src/java/org/apache/poi/hssf/model/LinkTable.java (-1 / +53 lines)
Lines 18-23 Link Here
18
package org.apache.poi.hssf.model;
18
package org.apache.poi.hssf.model;
19
19
20
import java.util.ArrayList;
20
import java.util.ArrayList;
21
import java.util.HashSet;
21
import java.util.Iterator;
22
import java.util.Iterator;
22
import java.util.List;
23
import java.util.List;
23
import java.util.Map;
24
import java.util.Map;
Lines 185-190 Link Here
185
	private final List<NameRecord> _definedNames;
186
	private final List<NameRecord> _definedNames;
186
	private final int _recordCount;
187
	private final int _recordCount;
187
	private final WorkbookRecordList _workbookRecordList; // TODO - would be nice to remove this
188
	private final WorkbookRecordList _workbookRecordList; // TODO - would be nice to remove this
189
	
190
	/**
191
	 * true means silently create new unreferenced workbooks
192
	 * false means raise an error if the external workbook does not exists
193
	 * 
194
	 * When true, o.a.p.hssf.usermodel.TestHSSFFormulaEvaluator.java#testXRefs 
195
	 * fails. see comment at line 263. Suggest that the preferred options is
196
	 * to go for false here
197
	 */
198
	private final boolean _autoCreateNewExternalWorkbookPolicy = false;
188
199
189
	public LinkTable(List<Record> inputList, int startIndex, WorkbookRecordList workbookRecordList, Map<String, NameCommentRecord> commentRecords) {
200
	public LinkTable(List<Record> inputList, int startIndex, WorkbookRecordList workbookRecordList, Map<String, NameCommentRecord> commentRecords) {
190
201
Lines 438-448 Link Here
438
        // Report where it went
449
        // Report where it went
439
        return extBookIndex;
450
        return extBookIndex;
440
	}
451
	}
452
	
453
	/**
454
	 * Links an external workbook that is not open (or cannot be opened)
455
	 * I wonder if this should be allowed at all. But it is the only way
456
	 * to proceed and resolve bug 60219 and bug 45970
457
	 */
458
	public int linkExternalWorkbook(String name, String[] sheetNames) {
459
        int extBookIndex = getExternalWorkbookIndex(name);
460
        
461
        if (extBookIndex == -1) {
462
            ExternalBookBlock block = new ExternalBookBlock(name, sheetNames);
463
            // Add it into the list + records
464
            extBookIndex = extendExternalBookBlocks(block);
441
465
466
            // add the created SupBookRecord before ExternSheetRecord
467
            int idx = findFirstRecordLocBySid(ExternSheetRecord.sid);
468
            if (idx == -1) {
469
                idx = _workbookRecordList.size();
470
            }
471
            _workbookRecordList.add(idx, block.getExternalBookRecord());
472
        }
473
                
474
        // Report where it went
475
        return extBookIndex;
476
	}
477
	
478
	private String[] packUniqueSheets(String sheetNames[]) {
479
	    HashSet<String> added = new HashSet<String>();
480
	    ArrayList<String> returnList = new ArrayList<String>();
481
	    for (String sheetName : sheetNames) {
482
	        if (!added.contains(sheetName)) {
483
	            added.add(sheetName);
484
	            returnList.add(sheetName);
485
	        }
486
	    }
487
	    return returnList.toArray(new String[0]);
488
	}
489
442
	public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) {
490
	public int getExternalSheetIndex(String workbookName, String firstSheetName, String lastSheetName) {
443
	    int externalBookIndex = getExternalWorkbookIndex(workbookName);
491
	    int externalBookIndex = getExternalWorkbookIndex(workbookName);
444
        if (externalBookIndex == -1) {
492
        if (externalBookIndex == -1) {
445
            throw new RuntimeException("No external workbook with name '" + workbookName + "'");
493
            if (_autoCreateNewExternalWorkbookPolicy) {
494
                externalBookIndex = linkExternalWorkbook(workbookName, packUniqueSheets(new String[] {firstSheetName, lastSheetName}));
495
            } else {
496
                throw new RuntimeException("No external workbook with name '" + workbookName + "'");
497
            }
446
        }
498
        }
447
        SupBookRecord ebrTarget = _externalBookBlocks[externalBookIndex].getExternalBookRecord();
499
        SupBookRecord ebrTarget = _externalBookBlocks[externalBookIndex].getExternalBookRecord();
448
500
(-)src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java (+17 lines)
Lines 2061-2066 Link Here
2061
    }
2061
    }
2062
2062
2063
    /**
2063
    /**
2064
     * Adds the LinkTable records required to allow formulas referencing
2065
     *  the specified external workbook to be added to this one. Allows
2066
     *  formulas such as "[MyOtherWorkbook]Sheet3!$A$5" to be added to the
2067
     *  file, for workbooks not already referenced.
2068
     * <p>This method does not require the external workbook to 
2069
     *  actually exists
2070
     *
2071
     * @param name The name the workbook will be referenced as in formulas
2072
     * @param sheetNames sheet names available in the external workbook
2073
     * @see #linkExternalWorkbook(String, Workbook)
2074
     */
2075
    @Override
2076
    public int linkExternalWorkbook(String name, String sheetNames[]) {
2077
        return this.workbook.linkExternalWorkbook(name, sheetNames);
2078
    }
2079
2080
    /**
2064
     * Is the workbook protected with a password (not encrypted)?
2081
     * Is the workbook protected with a password (not encrypted)?
2065
     */
2082
     */
2066
    public boolean isWriteProtected() {
2083
    public boolean isWriteProtected() {
(-)src/java/org/apache/poi/ss/formula/FormulaParser.java (-10 / +17 lines)
Lines 1119-1124 Link Here
1119
            return sb.toString();
1119
            return sb.toString();
1120
        }
1120
        }
1121
    }
1121
    }
1122
    
1123
    private String getBookName() {
1124
        StringBuilder sb = new StringBuilder();
1125
        GetChar();
1126
        while (look != ']') {
1127
            sb.append(look);
1128
            GetChar();
1129
        }
1130
        GetChar();
1131
        return sb.toString();
1132
    }
1122
1133
1123
    /**
1134
    /**
1124
     * Note - caller should reset {@link #_pointer} upon <code>null</code> result
1135
     * Note - caller should reset {@link #_pointer} upon <code>null</code> result
Lines 1127-1148 Link Here
1127
    private SheetIdentifier parseSheetName() {
1138
    private SheetIdentifier parseSheetName() {
1128
        String bookName;
1139
        String bookName;
1129
        if (look == '[') {
1140
        if (look == '[') {
1130
            StringBuilder sb = new StringBuilder();
1141
        	bookName = getBookName();
1131
            GetChar();
1132
            while (look != ']') {
1133
                sb.append(look);
1134
                GetChar();
1135
            }
1136
            GetChar();
1137
            bookName = sb.toString();
1138
        } else {
1142
        } else {
1139
            bookName = null;
1143
            bookName = null;
1140
        }
1144
        }
1141
1145
1142
        if (look == '\'') {
1146
        if (look == '\'') {
1147
            Match('\'');
1148
            
1149
            if (look == '[')
1150
            	bookName = getBookName();
1151
            
1143
            StringBuffer sb = new StringBuffer();
1152
            StringBuffer sb = new StringBuffer();
1144
1145
            Match('\'');
1146
            boolean done = look == '\'';
1153
            boolean done = look == '\'';
1147
            while(!done) {
1154
            while(!done) {
1148
                sb.append(look);
1155
                sb.append(look);
(-)src/java/org/apache/poi/ss/usermodel/Workbook.java (+20 lines)
Lines 436-443 Link Here
436
     *
436
     *
437
     * @param name The name the workbook will be referenced as in formulas
437
     * @param name The name the workbook will be referenced as in formulas
438
     * @param workbook The open workbook to fetch the link required information from
438
     * @param workbook The open workbook to fetch the link required information from
439
     * @see #linkExternalWorkbook(String, String[])
439
     */
440
     */
440
    int linkExternalWorkbook(String name, Workbook workbook);
441
    int linkExternalWorkbook(String name, Workbook workbook);
442
    
443
    /**
444
     * Adds the linking required to allow formulas referencing
445
     *  the specified external workbook to be added to this one.
446
     * <p>In order for formulas such as "[MyOtherWorkbook]Sheet3!$A$5"
447
     *  to be added to the file, some linking information must first
448
     *  be recorded. Once a given external workbook has been linked,
449
     *  then formulas using it can added. Each workbook needs linking
450
     *  only once.
451
     * <p>This linking only applies for writing formulas. To link things
452
     *  for evaluation, see {@link FormulaEvaluator#setupReferencedWorkbooks(java.util.Map)}
453
     * <p>This method does not require the external workbook to exist
454
     *  or be instantiated as a Workbook
455
     *
456
     * @param name The name the workbook will be referenced as in formulas
457
     * @param sheetNames sheet names that exists on external workbook
458
     * @see #linkExternalWorkbook(String, Workbook)
459
     */
460
    int linkExternalWorkbook(String name, String sheetNames[]);
441
461
442
     /**
462
     /**
443
     * Sets the printarea for the sheet provided
463
     * Sets the printarea for the sheet provided
(-)src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java (+17 lines)
Lines 1347-1352 Link Here
1347
    }
1347
    }
1348
    
1348
    
1349
    /**
1349
    /**
1350
     * <i>Not implemented for SXSSFWorkbook</i>
1351
     *
1352
     * Adds the LinkTable records required to allow formulas referencing
1353
     *  the specified external workbook to be added to this one. Allows
1354
     *  formulas such as "[MyOtherWorkbook]Sheet3!$A$5" to be added to the 
1355
     *  file, for workbooks not already referenced.
1356
     *
1357
     * @param name The name the workbook will be referenced as in formulas
1358
     * @param sheetNames Sheet names in the external workbook
1359
     */
1360
    @Override
1361
    @NotImplemented
1362
    public int linkExternalWorkbook(String name, String sheetNames[]) {
1363
        throw new RuntimeException("NotImplemented");
1364
    }
1365
    
1366
    /**
1350
     * Register a new toolpack in this workbook.
1367
     * Register a new toolpack in this workbook.
1351
     *
1368
     *
1352
     * @param toopack the toolpack to register
1369
     * @param toopack the toolpack to register
(-)src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFWorkbook.java (+15 lines)
Lines 2034-2039 Link Here
2034
    }
2034
    }
2035
2035
2036
    /**
2036
    /**
2037
     * Adds the External Link Table part and relations required to allow formulas 
2038
     *  referencing the specified external workbook to be added to this one. Allows
2039
     *  formulas such as "[MyOtherWorkbook.xlsx]Sheet3!$A$5" to be added to the 
2040
     *  file, for workbooks not already linked / referenced.
2041
     *
2042
     * @param name The name the workbook will be referenced as in formulas
2043
     * @param sheetNames Sheet names in the external workbook
2044
     */
2045
    @Override
2046
    @NotImplemented
2047
    public int linkExternalWorkbook(String name, String sheetNames[]) {
2048
        throw new RuntimeException("Not Implemented - see bugs #57184 #45970 #60219");
2049
    }
2050
2051
    /**
2037
     * Specifies a boolean value that indicates whether structure of workbook is locked. <br/>
2052
     * Specifies a boolean value that indicates whether structure of workbook is locked. <br/>
2038
     * A value true indicates the structure of the workbook is locked. Worksheets in the workbook can't be moved,
2053
     * A value true indicates the structure of the workbook is locked. Worksheets in the workbook can't be moved,
2039
     * deleted, hidden, unhidden, or renamed, and new worksheets can't be inserted.<br/>
2054
     * deleted, hidden, unhidden, or renamed, and new worksheets can't be inserted.<br/>
(-)src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java (-4 / +8 lines)
Lines 1848-1857 Link Here
1848
       assertEquals("'[$http://gagravarr.org/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
1848
       assertEquals("'[$http://gagravarr.org/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
1849
       assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
1849
       assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
1850
1850
1851
       // Link our new workbook
1852
       wb1.linkExternalWorkbook("$http://gagravarr.org/FormulaRefs2.xls", new String[] {"Sheet1"});
1853
       
1851
       // Change 4
1854
       // Change 4
1852
       row.getCell(1).setCellFormula("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2");
1855
       row.getCell(1).setCellFormula("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2");
1853
       row.getCell(1).setCellValue(123.0);
1856
       row.getCell(1).setCellValue(123.0);
1854
1857
1858
       // Link our new workbook
1859
       wb1.linkExternalWorkbook("$http://example.com/FormulaRefs.xls", new String[] {"Sheet1"});
1860
       
1855
       // Add 5
1861
       // Add 5
1856
       row = s.createRow(5);
1862
       row = s.createRow(5);
1857
       row.createCell(1, CellType.FORMULA);
1863
       row.createCell(1, CellType.FORMULA);
Lines 1858-1864 Link Here
1858
       row.getCell(1).setCellFormula("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1");
1864
       row.getCell(1).setCellFormula("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1");
1859
       row.getCell(1).setCellValue(234.0);
1865
       row.getCell(1).setCellValue(234.0);
1860
1866
1861
1862
       // Re-test
1867
       // Re-test
1863
       HSSFWorkbook wb2 = writeOutAndReadBack(wb1);
1868
       HSSFWorkbook wb2 = writeOutAndReadBack(wb1);
1864
       wb1.close();
1869
       wb1.close();
Lines 1883-1890 Link Here
1883
       assertEquals("[Formulas2.xls]Sheet1!B2", row.getCell(1).getCellFormula());
1888
       assertEquals("[Formulas2.xls]Sheet1!B2", row.getCell(1).getCellFormula());
1884
       assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
1889
       assertEquals(112.0, row.getCell(1).getNumericCellValue(), 0);
1885
1890
1886
       // TODO - Fix these so they work...
1891
       row = s.getRow(4);
1887
       /*row = s.getRow(4);
1888
       assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
1892
       assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
1889
       assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula());
1893
       assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula());
1890
       assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0);
1894
       assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0);
Lines 1892-1898 Link Here
1892
       row = s.getRow(5);
1896
       row = s.getRow(5);
1893
       assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
1897
       assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
1894
       assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
1898
       assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
1895
       assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0);*/
1899
       assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0);
1896
       
1900
       
1897
       wb2.close();
1901
       wb2.close();
1898
    }
1902
    }

Return to bug 60219