From 1690ec2d1915cf30fefd4f0e65ce017e0b86b7d6 Mon Sep 17 00:00:00 2001 From: Andreas Beeker Date: Wed, 28 Sep 2016 21:01:40 +0000 Subject: [PATCH] merge trunk to branch git-svn-id: https://svn.apache.org/repos/asf/poi/branches/hssf_cryptoapi@1762709 13f79535-47bb-0310-9956-ffa450edef68 --- KEYS | 99 +++++++++++++++ build.gradle | 21 ++++ build.xml | 4 +- doap_POI.rdf | 7 ++ sonar/examples/pom.xml | 2 +- sonar/excelant/pom.xml | 2 +- sonar/main/pom.xml | 2 +- sonar/ooxml-schema-encryption/pom.xml | 2 +- sonar/ooxml-schema-security/pom.xml | 2 +- sonar/ooxml-schema/pom.xml | 2 +- sonar/ooxml/pom.xml | 2 +- sonar/pom.xml | 2 +- sonar/scratchpad/pom.xml | 2 +- .../hssf/usermodel/examples/InCellLists.java | 54 ++++----- .../org/apache/poi/TestAllFiles.java | 1 + .../poi/hssf/usermodel/HSSFDataFormat.java | 3 +- .../hssf/usermodel/HSSFFormulaEvaluator.java | 87 +++++++++++-- .../poi/hssf/usermodel/HSSFWorkbook.java | 3 +- .../poi/poifs/nio/FileBackedDataSource.java | 23 ++-- .../poi/ss/formula/functions/Bin2Dec.java | 2 +- .../apache/poi/ss/usermodel/CellStyle.java | 96 +++++++-------- .../apache/poi/ss/usermodel/CellValue.java | 40 ++++-- .../org/apache/poi/ss/usermodel/Workbook.java | 29 ++--- .../org/apache/poi/ss/util/SheetUtil.java | 19 ++- .../org/apache/poi/util/CommonsLogger.java | 12 +- .../util/DefaultTempFileCreationStrategy.java | 15 ++- src/java/org/apache/poi/util/NullLogger.java | 17 ++- .../org/apache/poi/util/POILogFactory.java | 2 +- src/java/org/apache/poi/util/POILogger.java | 17 ++- .../org/apache/poi/util/SystemOutLogger.java | 6 +- .../poi/extractor/ExtractorFactory.java | 5 +- .../poi/poifs/crypt/dsig/SignatureConfig.java | 2 +- .../java/org/apache/poi/util/OOXMLLite.java | 1 + .../apache/poi/xslf/usermodel/XSLFShape.java | 6 +- .../poi/xssf/streaming/SXSSFWorkbook.java | 18 ++- .../usermodel/BaseXSSFFormulaEvaluator.java | 74 +++++++++++- .../usermodel/XSSFPivotCacheDefinition.java | 40 +++++- .../poi/xssf/usermodel/XSSFPivotTable.java | 32 ++--- .../apache/poi/xssf/usermodel/XSSFSheet.java | 114 +++++++++++++++--- .../xssf/usermodel/helpers/ColumnHelper.java | 1 + .../usermodel/helpers/XSSFRowShifter.java | 3 +- .../poi/extractor/TestExtractorFactory.java | 14 +++ .../poi/poifs/crypt/TestSignatureInfo.java | 7 +- .../poi/ss/formula/functions/TestProper.java | 1 - ...Table.java => BaseTestXSSFPivotTable.java} | 107 +++------------- .../poi/xssf/usermodel/TestXSSFBugs.java | 37 ++++++ .../usermodel/TestXSSFFormulaEvaluation.java | 11 -- .../usermodel/TestXSSFPivotTableName.java | 112 +++++++++++++++++ .../xssf/usermodel/TestXSSFPivotTableRef.java | 111 +++++++++++++++++ .../poi/xssf/usermodel/TestXSSFSheet.java | 23 +++- .../usermodel/TestXSSFSheetShiftRows.java | 53 +++++++- .../src/org/apache/poi/hmef/Attachment.java | 2 + .../poi/hwpf/converter/WordToFoUtils.java | 16 +-- .../apache/poi/hwpf/usermodel/TestBugs.java | 17 +++ src/testcases/org/apache/poi/POITestCase.java | 59 +++++++++ .../apache/poi/hssf/usermodel/TestBugs.java | 4 +- .../filesystem/TestPOIFSDocumentPath.java | 10 +- .../poi/poifs/macros/TestVBAMacroReader.java | 20 ++- .../poi/ss/formula/atp/TestIfError.java | 2 +- .../ss/usermodel/BaseTestBugzillaIssues.java | 3 - .../ss/usermodel/BaseTestSheetShiftRows.java | 30 ++++- .../BaseTestSheetUpdateArrayFormulas.java | 2 +- .../org/apache/poi/util/DummyPOILogger.java | 5 +- .../org/apache/poi/util/TestPOILogger.java | 4 +- test-data/diagram/44501a.vsd | Bin test-data/diagram/44501b.vsd | Bin test-data/diagram/44501d.vsd | Bin test-data/document/57843.doc | Bin 0 -> 8192 bytes test-data/document/60158.docm | Bin 0 -> 15617 bytes .../hsmf/logsat.com_signatures_valid.msg | Bin ...g_workarea_downloadasset.aspx_id=5864.pptx | Bin ...538ba7a204-programa_alianca_12-04-2007.ppt | Bin ...r.com.tvcamboriu.www_pps_Pensar_5b1_5d.ppt | Bin test-data/spreadsheet/45565.xls | Bin 0 -> 13824 bytes test-data/spreadsheet/59687.xlsx | Bin 0 -> 9580 bytes .../TestShiftRowSharedFormula.xlsx | Bin 0 -> 8431 bytes test-data/spreadsheet/Themes2.xls | Bin ...1B954F-5C07F98E_ooe_stat_download_bp10.xls | Bin ..._0011d159-1eeb-4b63-8833-867b0926e5f3.xlsx | Bin .../spreadsheet/noSharedStringTable.xlsx | Bin 80 files changed, 1166 insertions(+), 355 deletions(-) create mode 100644 build.gradle rename src/ooxml/testcases/org/apache/poi/xssf/usermodel/{TestXSSFPivotTable.java => BaseTestXSSFPivotTable.java} (74%) create mode 100644 src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableName.java create mode 100644 src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableRef.java mode change 100755 => 100644 test-data/diagram/44501a.vsd mode change 100755 => 100644 test-data/diagram/44501b.vsd mode change 100755 => 100644 test-data/diagram/44501d.vsd create mode 100644 test-data/document/57843.doc create mode 100644 test-data/document/60158.docm mode change 100755 => 100644 test-data/hsmf/logsat.com_signatures_valid.msg mode change 100755 => 100644 test-data/slideshow/aascu.org_workarea_downloadasset.aspx_id=5864.pptx mode change 100755 => 100644 test-data/slideshow/br.com.diversas.palestras_Nelson_20-_20Temas_20Diversos_20XXXVI_pmrg_462538ba7a204-programa_alianca_12-04-2007.ppt mode change 100755 => 100644 test-data/slideshow/br.com.tvcamboriu.www_pps_Pensar_5b1_5d.ppt create mode 100644 test-data/spreadsheet/45565.xls create mode 100644 test-data/spreadsheet/59687.xlsx create mode 100644 test-data/spreadsheet/TestShiftRowSharedFormula.xlsx mode change 100755 => 100644 test-data/spreadsheet/Themes2.xls mode change 100755 => 100644 test-data/spreadsheet/at.gv.land-oberoesterreich.www_cps_rde_xbcr_SID-4A1B954F-5C07F98E_ooe_stat_download_bp10.xls mode change 100755 => 100644 test-data/spreadsheet/craftonhills.edu_programreview_report.aspx_goalpriorityreport_0011d159-1eeb-4b63-8833-867b0926e5f3.xlsx mode change 100755 => 100644 test-data/spreadsheet/noSharedStringTable.xlsx diff --git a/KEYS b/KEYS index 6767cb00a3..adc245d131 100644 --- a/KEYS +++ b/KEYS @@ -2386,3 +2386,102 @@ cCRRHYCeAZDU5UMxi0nonfT+060i2rLPSd7o0bstG7gb1pD99rKxL57M7uy+WBnk YobtRLhWHvHyWS4dKqiteeTwAqG2ZFOq98KCu1LXMKj42HqwOtB3L23HlhqVyA== =8e4G -----END PGP PUBLIC KEY BLOCK----- +pub 4096R/8BABDD6C 2015-10-10 [expires: 2017-10-09] +uid Javen O'Neal +uid Javen O'Neal +sub 4096R/309424B4 2015-10-10 [expires: 2017-10-09] + +-----BEGIN PGP PUBLIC KEY BLOCK----- +Version: GnuPG v2.0.22 (GNU/Linux) + +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 +2Nr+AmDDs6ZOEI5zhwxioePw/Cg= +=9lKb +-----END PGP PUBLIC KEY BLOCK----- diff --git a/build.gradle b/build.gradle new file mode 100644 index 0000000000..20f98e8205 --- /dev/null +++ b/build.gradle @@ -0,0 +1,21 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +// For help converting an Ant build to a Gradle build, see +// https://docs.gradle.org/current/userguide/ant.html + +ant.importBuild 'build.xml' diff --git a/build.xml b/build.xml index d3623395d9..975cf5c50c 100644 --- a/build.xml +++ b/build.xml @@ -40,7 +40,7 @@ under the License. The Apache POI project Ant build. - + @@ -78,7 +78,7 @@ under the License. JVM system properties for running tests, user.language and user.country are required as we have locale-sensitive formatters --> - + diff --git a/doap_POI.rdf b/doap_POI.rdf index 5369344cd0..08106f476a 100644 --- a/doap_POI.rdf +++ b/doap_POI.rdf @@ -35,6 +35,13 @@ Java + + + Apache POI 3.15 + 2016-09-21 + 3.15 + + Apache POI 3.14 diff --git a/sonar/examples/pom.xml b/sonar/examples/pom.xml index ea53c05970..cac1dc446c 100644 --- a/sonar/examples/pom.xml +++ b/sonar/examples/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT poi-examples jar diff --git a/sonar/excelant/pom.xml b/sonar/excelant/pom.xml index a7b9408dc4..2cbeec7280 100644 --- a/sonar/excelant/pom.xml +++ b/sonar/excelant/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT poi-excelant jar diff --git a/sonar/main/pom.xml b/sonar/main/pom.xml index 36422a83c8..26a8f2ba40 100644 --- a/sonar/main/pom.xml +++ b/sonar/main/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT poi-main jar diff --git a/sonar/ooxml-schema-encryption/pom.xml b/sonar/ooxml-schema-encryption/pom.xml index cbb2eff7d3..d704a6525d 100644 --- a/sonar/ooxml-schema-encryption/pom.xml +++ b/sonar/ooxml-schema-encryption/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT .. poi-ooxml-schema-encryption diff --git a/sonar/ooxml-schema-security/pom.xml b/sonar/ooxml-schema-security/pom.xml index a822c73435..7aae600f41 100644 --- a/sonar/ooxml-schema-security/pom.xml +++ b/sonar/ooxml-schema-security/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT .. poi-ooxml-schema-security diff --git a/sonar/ooxml-schema/pom.xml b/sonar/ooxml-schema/pom.xml index 5e2b9fef56..e1d6526da9 100644 --- a/sonar/ooxml-schema/pom.xml +++ b/sonar/ooxml-schema/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT .. poi-ooxml-schema diff --git a/sonar/ooxml/pom.xml b/sonar/ooxml/pom.xml index 27636cdfa1..305695ff1a 100644 --- a/sonar/ooxml/pom.xml +++ b/sonar/ooxml/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT poi-ooxml jar diff --git a/sonar/pom.xml b/sonar/pom.xml index 8e2a9fc42f..5acb3a5da2 100644 --- a/sonar/pom.xml +++ b/sonar/pom.xml @@ -3,7 +3,7 @@ org.apache.poi poi-parent pom - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT Apache POI - the Java API for Microsoft Documents Maven build of Apache POI for Sonar checks http://poi.apache.org/ diff --git a/sonar/scratchpad/pom.xml b/sonar/scratchpad/pom.xml index 6760762d67..91ede69a1c 100644 --- a/sonar/scratchpad/pom.xml +++ b/sonar/scratchpad/pom.xml @@ -6,7 +6,7 @@ org.apache.poi poi-parent - 3.16-beta1-SNAPSHOT + 3.15-beta4-SNAPSHOT poi-scratchpad jar diff --git a/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java b/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java index a666c6ab7b..e1d4cbcbf8 100644 --- a/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java +++ b/src/examples/src/org/apache/poi/hssf/usermodel/examples/InCellLists.java @@ -67,27 +67,21 @@ public class InCellLists { * the Excel spreadsheet file this code will create. */ public void demonstrateMethodCalls(String outputFilename) throws IOException { - HSSFWorkbook workbook = null; - HSSFSheet sheet = null; - HSSFRow row = null; - HSSFCell cell = null; - ArrayList multiLevelListItems = null; - ArrayList listItems = null; + HSSFWorkbook workbook = new HSSFWorkbook(); try { - workbook = new HSSFWorkbook(); - sheet = workbook.createSheet("In Cell Lists"); - row = sheet.createRow(0); + HSSFSheet sheet = workbook.createSheet("In Cell Lists"); + HSSFRow row = sheet.createRow(0); // Create a cell at A1 and insert a single, bulleted, item into // that cell. - cell = row.createCell(0); + HSSFCell cell = row.createCell(0); this.bulletedItemInCell(workbook, "List Item", cell); // Create a cell at A2 and insert a plain list - that is one // whose items are neither bulleted or numbered - into that cell. row = sheet.createRow(1); cell = row.createCell(0); - listItems = new ArrayList(); + ArrayList listItems = new ArrayList(); listItems.add("List Item One."); listItems.add("List Item Two."); listItems.add("List Item Three."); @@ -131,7 +125,7 @@ public class InCellLists { // to preserve order. row = sheet.createRow(4); cell = row.createCell(0); - multiLevelListItems = new ArrayList(); + ArrayList multiLevelListItems = new ArrayList(); listItems = new ArrayList(); listItems.add("ML List Item One - Sub Item One."); listItems.add("ML List Item One - Sub Item Two."); @@ -189,9 +183,7 @@ public class InCellLists { ioEx.printStackTrace(System.out); } finally { - if (workbook != null) { - workbook.close(); - } + workbook.close(); } } @@ -236,7 +228,7 @@ public class InCellLists { * will be written. */ public void listInCell(HSSFWorkbook workbook, ArrayList listItems, HSSFCell cell) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); HSSFCellStyle wrapStyle = workbook.createCellStyle(); wrapStyle.setWrapText(true); for(String listItem : listItems) { @@ -269,7 +261,7 @@ public class InCellLists { HSSFCell cell, int startingValue, int increment) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); int itemNumber = startingValue; // Note that again, an HSSFCellStye object is required and that // it's wrap text property should be set to 'true' @@ -278,7 +270,7 @@ public class InCellLists { // Note that the basic method is identical to the listInCell() method // with one difference; a number prefixed to the items text. for(String listItem : listItems) { - buffer.append(String.valueOf(itemNumber) + ". "); + buffer.append(itemNumber).append(". "); buffer.append(listItem); buffer.append("\n"); itemNumber += increment; @@ -303,7 +295,7 @@ public class InCellLists { public void bulletedListInCell(HSSFWorkbook workbook, ArrayList listItems, HSSFCell cell) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); // Note that again, an HSSFCellStye object is required and that // it's wrap text property should be set to 'true' HSSFCellStyle wrapStyle = workbook.createCellStyle(); @@ -339,8 +331,7 @@ public class InCellLists { public void multiLevelListInCell(HSSFWorkbook workbook, ArrayList multiLevelListItems, HSSFCell cell) { - StringBuffer buffer = new StringBuffer(); - ArrayList lowerLevelItems = null; + StringBuilder buffer = new StringBuilder(); // Note that again, an HSSFCellStye object is required and that // it's wrap text property should be set to 'true' HSSFCellStyle wrapStyle = workbook.createCellStyle(); @@ -353,7 +344,7 @@ public class InCellLists { buffer.append("\n"); // and then an ArrayList whose elements encapsulate the text // for the lower level list items. - lowerLevelItems = multiLevelListItem.getLowerLevelItems(); + ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { for(String item : lowerLevelItems) { buffer.append(InCellLists.TAB); @@ -401,10 +392,8 @@ public class InCellLists { int highLevelIncrement, int lowLevelStartingValue, int lowLevelIncrement) { - StringBuffer buffer = new StringBuffer(); + StringBuilder buffer = new StringBuilder(); int highLevelItemNumber = highLevelStartingValue; - int lowLevelItemNumber = 0; - ArrayList lowerLevelItems = null; // Note that again, an HSSFCellStye object is required and that // it's wrap text property should be set to 'true' HSSFCellStyle wrapStyle = workbook.createCellStyle(); @@ -413,20 +402,20 @@ public class InCellLists { for(MultiLevelListItem multiLevelListItem : multiLevelListItems) { // For each element in the ArrayList, get the text for the high // level list item...... - buffer.append(String.valueOf(highLevelItemNumber)); + buffer.append(highLevelItemNumber); buffer.append(". "); buffer.append(multiLevelListItem.getItemText()); buffer.append("\n"); // and then an ArrayList whose elements encapsulate the text // for the lower level list items. - lowerLevelItems = multiLevelListItem.getLowerLevelItems(); + ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { - lowLevelItemNumber = lowLevelStartingValue; + int lowLevelItemNumber = lowLevelStartingValue; for(String item : lowerLevelItems) { buffer.append(InCellLists.TAB); - buffer.append(String.valueOf(highLevelItemNumber)); + buffer.append(highLevelItemNumber); buffer.append("."); - buffer.append(String.valueOf(lowLevelItemNumber)); + buffer.append(lowLevelItemNumber); buffer.append(" "); buffer.append(item); buffer.append("\n"); @@ -459,8 +448,7 @@ public class InCellLists { public void multiLevelBulletedListInCell(HSSFWorkbook workbook, ArrayList multiLevelListItems, HSSFCell cell) { - StringBuffer buffer = new StringBuffer(); - ArrayList lowerLevelItems = null; + StringBuilder buffer = new StringBuilder(); // Note that again, an HSSFCellStye object is required and that // it's wrap text property should be set to 'true' HSSFCellStyle wrapStyle = workbook.createCellStyle(); @@ -475,7 +463,7 @@ public class InCellLists { buffer.append("\n"); // and then an ArrayList whose elements encapsulate the text // for the lower level list items. - lowerLevelItems = multiLevelListItem.getLowerLevelItems(); + ArrayList lowerLevelItems = multiLevelListItem.getLowerLevelItems(); if(!(lowerLevelItems == null) && !(lowerLevelItems.isEmpty())) { for(String item : lowerLevelItems) { buffer.append(InCellLists.TAB); diff --git a/src/integrationtest/org/apache/poi/TestAllFiles.java b/src/integrationtest/org/apache/poi/TestAllFiles.java index e364c9f28a..6def523dbf 100644 --- a/src/integrationtest/org/apache/poi/TestAllFiles.java +++ b/src/integrationtest/org/apache/poi/TestAllFiles.java @@ -232,6 +232,7 @@ public class TestAllFiles { EXPECTED_FAILURES.add("spreadsheet/43493.xls"); EXPECTED_FAILURES.add("spreadsheet/46904.xls"); EXPECTED_FAILURES.add("document/Bug50955.doc"); + EXPECTED_FAILURES.add("document/57843.doc"); EXPECTED_FAILURES.add("slideshow/PPT95.ppt"); EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DCTermsNamespaceLimitedUseFAIL.docx"); EXPECTED_FAILURES.add("openxml4j/OPCCompliance_CoreProperties_DoNotUseCompatibilityMarkupFAIL.docx"); diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java index 6eecc7b2c9..23fe8cad76 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFDataFormat.java @@ -20,7 +20,6 @@ package org.apache.poi.hssf.usermodel; import java.util.Arrays; import java.util.Iterator; import java.util.List; -import java.util.Locale; import java.util.Vector; import org.apache.poi.hssf.model.InternalWorkbook; @@ -90,7 +89,7 @@ public final class HSSFDataFormat implements DataFormat { public short getFormat(String pFormat) { // Normalise the format string String format; - if (pFormat.toUpperCase(Locale.ROOT).equals("TEXT")) { + if (pFormat.equalsIgnoreCase("TEXT")) { format = "@"; } else { format = pFormat; diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java index 20c7ffa1e4..fa5082635d 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFFormulaEvaluator.java @@ -32,7 +32,6 @@ import org.apache.poi.ss.formula.udf.UDFFinder; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.FormulaEvaluator; -import org.apache.poi.ss.usermodel.RichTextString; import org.apache.poi.ss.usermodel.Workbook; /** @@ -80,11 +79,6 @@ public class HSSFFormulaEvaluator extends BaseFormulaEvaluator { public static HSSFFormulaEvaluator create(HSSFWorkbook workbook, IStabilityClassifier stabilityClassifier, UDFFinder udfFinder) { return new HSSFFormulaEvaluator(workbook, stabilityClassifier, udfFinder); } - - @Override - protected RichTextString createRichTextString(String str) { - return new HSSFRichTextString(str); - } /** @@ -140,10 +134,87 @@ public class HSSFFormulaEvaluator extends BaseFormulaEvaluator { public void notifySetFormula(Cell cell) { _bookEvaluator.notifyUpdateCell(new HSSFEvaluationCell((HSSFCell)cell)); } - + + /** + * If cell contains formula, it evaluates the formula, and saves the result of the formula. The + * cell remains as a formula cell. If the cell does not contain formula, rather than throwing an + * exception, this method returns {@link CellType#_NONE} and leaves the cell unchanged. + * + * Note that the type of the formula result is returned, so you know what kind of + * cached formula result is also stored with the formula. + *
+     * CellType evaluatedCellType = evaluator.evaluateFormulaCell(cell);
+     * 
+ * Be aware that your cell will hold both the formula, and the result. If you want the cell + * replaced with the result of the formula, use {@link #evaluateInCell(org.apache.poi.ss.usermodel.Cell)} + * @param cell The cell to evaluate + * @return {@link CellType#_NONE} for non-formula cells, or the type of the formula result + * @since POI 3.15 beta 3 + * @deprecated POI 3.15 beta 3. Will be deleted when we make the CellType enum transition. See bug 59791. + */ + @Internal + @Override + public CellType evaluateFormulaCellEnum(Cell cell) { + if (cell == null || cell.getCellTypeEnum() != CellType.FORMULA) { + return CellType._NONE; + } + CellValue cv = evaluateFormulaCellValue(cell); + // cell remains a formula cell, but the cached value is changed + setCellValue(cell, cv); + return cv.getCellType(); + } + + /** + * If cell contains formula, it evaluates the formula, and + * puts the formula result back into the cell, in place + * of the old formula. + * Else if cell does not contain formula, this method leaves + * the cell unchanged. + * Note that the same instance of HSSFCell is returned to + * allow chained calls like: + *
+     * int evaluatedCellType = evaluator.evaluateInCell(cell).getCellType();
+     * 
+ * Be aware that your cell value will be changed to hold the + * result of the formula. If you simply want the formula + * value computed for you, use {@link #evaluateFormulaCellEnum(Cell)}} + */ @Override public HSSFCell evaluateInCell(Cell cell) { - return (HSSFCell) super.evaluateInCell(cell); + if (cell == null) { + return null; + } + HSSFCell result = (HSSFCell) cell; + if (cell.getCellTypeEnum() == CellType.FORMULA) { + CellValue cv = evaluateFormulaCellValue(cell); + setCellValue(cell, cv); + setCellType(cell, cv); // cell will no longer be a formula cell + } + return result; + } + + private static void setCellValue(Cell cell, CellValue cv) { + CellType cellType = cv.getCellType(); + switch (cellType) { + case BOOLEAN: + cell.setCellValue(cv.getBooleanValue()); + break; + case ERROR: + cell.setCellErrorValue(cv.getErrorValue()); + break; + case NUMERIC: + cell.setCellValue(cv.getNumberValue()); + break; + case STRING: + cell.setCellValue(new HSSFRichTextString(cv.getStringValue())); + break; + case BLANK: + // never happens - blanks eventually get translated to zero + case FORMULA: + // this will never happen, we have already evaluated the formula + default: + throw new IllegalStateException("Unexpected cell value type (" + cellType + ")"); + } } /** diff --git a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java index 2800904af1..b4339587b9 100644 --- a/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java +++ b/src/java/org/apache/poi/hssf/usermodel/HSSFWorkbook.java @@ -963,8 +963,9 @@ public final class HSSFWorkbook extends POIDocument implements org.apache.poi.ss * Get the HSSFSheet object at the given index. * @param index of the sheet number (0-based physical & logical) * @return HSSFSheet at the provided index + * @throws IllegalArgumentException if the index is out of range (index + * < 0 || index >= getNumberOfSheets()). */ - @Override public HSSFSheet getSheetAt(int index) { diff --git a/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java b/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java index 47637daa3a..32a8701fb8 100644 --- a/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java +++ b/src/java/org/apache/poi/poifs/nio/FileBackedDataSource.java @@ -88,27 +88,26 @@ public class FileBackedDataSource extends DataSource { throw new IndexOutOfBoundsException("Position " + position + " past the end of the file"); } - // Do we read or map (for read/write? + // Do we read or map (for read/write)? ByteBuffer dst; - int worked = -1; if (writable) { dst = channel.map(FileChannel.MapMode.READ_WRITE, position, length); - worked = 0; - // remember the buffer for cleanup if necessary - buffersToClean.add(dst); + + // remember this buffer for cleanup + buffersToClean.add(dst); } else { - // Read + // allocate the buffer on the heap if we cannot map the data in directly channel.position(position); dst = ByteBuffer.allocate(length); - worked = IOUtils.readFully(channel, dst); - } - // Check - if(worked == -1) { - throw new IndexOutOfBoundsException("Position " + position + " past the end of the file"); + // Read the contents and check that we could read some data + int worked = IOUtils.readFully(channel, dst); + if(worked == -1) { + throw new IndexOutOfBoundsException("Position " + position + " past the end of the file"); + } } - // Ready it for reading + // make it ready for reading dst.position(0); // All done diff --git a/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java b/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java index 9617877ca6..cb206051c0 100644 --- a/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java +++ b/src/java/org/apache/poi/ss/formula/functions/Bin2Dec.java @@ -84,7 +84,7 @@ public class Bin2Dec extends Fixed1ArgFunction implements FreeRefFunction { //Add 1 to obtained number sum++; - value = "-" + String.valueOf(sum); + value = "-" + sum; } } catch (NumberFormatException e) { return ErrorEval.NUM_ERROR; diff --git a/src/java/org/apache/poi/ss/usermodel/CellStyle.java b/src/java/org/apache/poi/ss/usermodel/CellStyle.java index df3d572598..1eab8dec19 100644 --- a/src/java/org/apache/poi/ss/usermodel/CellStyle.java +++ b/src/java/org/apache/poi/ss/usermodel/CellStyle.java @@ -26,308 +26,308 @@ public interface CellStyle { * @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#GENERAL} instead. */ @Removal(version="3.17") - static final short ALIGN_GENERAL = 0x0; //HorizontalAlignment.GENERAL.getCode(); + short ALIGN_GENERAL = 0x0; //HorizontalAlignment.GENERAL.getCode(); /** * left-justified horizontal alignment * @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#LEFT} instead. */ @Removal(version="3.17") - static final short ALIGN_LEFT = 0x1; //HorizontalAlignment.LEFT.getCode(); + short ALIGN_LEFT = 0x1; //HorizontalAlignment.LEFT.getCode(); /** * center horizontal alignment * @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#CENTER} instead. */ @Removal(version="3.17") - static final short ALIGN_CENTER = 0x2; //HorizontalAlignment.CENTER.getCode(); + short ALIGN_CENTER = 0x2; //HorizontalAlignment.CENTER.getCode(); /** * right-justified horizontal alignment * @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#RIGHT} instead. */ @Removal(version="3.17") - static final short ALIGN_RIGHT = 0x3; //HorizontalAlignment.RIGHT.getCode(); + short ALIGN_RIGHT = 0x3; //HorizontalAlignment.RIGHT.getCode(); /** * fill? horizontal alignment * @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#FILL} instead. */ @Removal(version="3.17") - static final short ALIGN_FILL = 0x4; //HorizontalAlignment.FILL.getCode(); + short ALIGN_FILL = 0x4; //HorizontalAlignment.FILL.getCode(); /** * justified horizontal alignment * @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#JUSTIFY} instead. */ @Removal(version="3.17") - static final short ALIGN_JUSTIFY = 0x5; //HorizontalAlignment.JUSTIFY.getCode(); + short ALIGN_JUSTIFY = 0x5; //HorizontalAlignment.JUSTIFY.getCode(); /** * center-selection? horizontal alignment * @deprecated POI 3.15 beta 3. Use {@link HorizontalAlignment#CENTER_SELECTION} instead. */ @Removal(version="3.17") - static final short ALIGN_CENTER_SELECTION = 0x6; //HorizontalAlignment.CENTER_SELECTION.getCode(); + short ALIGN_CENTER_SELECTION = 0x6; //HorizontalAlignment.CENTER_SELECTION.getCode(); /** * top-aligned vertical alignment * @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#TOP} instead. */ @Removal(version="3.17") - static final short VERTICAL_TOP = 0x0; //VerticalAlignment.TOP.getCode(); + short VERTICAL_TOP = 0x0; //VerticalAlignment.TOP.getCode(); /** * center-aligned vertical alignment * @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#CENTER} instead. */ @Removal(version="3.17") - static final short VERTICAL_CENTER = 0x1; //VerticalAlignment.CENTER.getCode(); + short VERTICAL_CENTER = 0x1; //VerticalAlignment.CENTER.getCode(); /** * bottom-aligned vertical alignment * @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#BOTTOM} instead. */ @Removal(version="3.17") - static final short VERTICAL_BOTTOM = 0x2; //VerticalAlignment.BOTTOM.getCode(); + short VERTICAL_BOTTOM = 0x2; //VerticalAlignment.BOTTOM.getCode(); /** * vertically justified vertical alignment * @deprecated POI 3.15 beta 3. Use {@link VerticalAlignment#JUSTIFY} instead. */ @Removal(version="3.17") - static final short VERTICAL_JUSTIFY = 0x3; //VerticalAlignment.JUSTIFY.getCode(); + short VERTICAL_JUSTIFY = 0x3; //VerticalAlignment.JUSTIFY.getCode(); /** * No border * @deprecated 3.15 beta 2. Use {@link BorderStyle#NONE} instead. */ @Removal(version="3.17") - static final short BORDER_NONE = 0x0; //BorderStyle.NONE.getCode(); + short BORDER_NONE = 0x0; //BorderStyle.NONE.getCode(); /** * Thin border * @deprecated 3.15 beta 2. Use {@link BorderStyle#THIN} instead. */ @Removal(version="3.17") - static final short BORDER_THIN = 0x1; //BorderStyle.THIN.getCode(); + short BORDER_THIN = 0x1; //BorderStyle.THIN.getCode(); /** * Medium border * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM} instead. */ @Removal(version="3.17") - static final short BORDER_MEDIUM = 0x2; //BorderStyle.MEDIUM.getCode(); + short BORDER_MEDIUM = 0x2; //BorderStyle.MEDIUM.getCode(); /** * dash border * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASHED} instead. */ @Removal(version="3.17") - static final short BORDER_DASHED = 0x3; //BorderStyle.DASHED.getCode(); + short BORDER_DASHED = 0x3; //BorderStyle.DASHED.getCode(); /** * dot border * @deprecated 3.15 beta 2. Use {@link BorderStyle#DOTTED} instead. */ @Removal(version="3.17") - static final short BORDER_DOTTED = 0x4; //BorderStyle.DOTTED.getCode(); + short BORDER_DOTTED = 0x4; //BorderStyle.DOTTED.getCode(); /** * Thick border * @deprecated 3.15 beta 2. Use {@link BorderStyle#THICK} instead. */ @Removal(version="3.17") - static final short BORDER_THICK = 0x5; //BorderStyle.THICK.getCode(); + short BORDER_THICK = 0x5; //BorderStyle.THICK.getCode(); /** * double-line border * @deprecated 3.15 beta 2. Use {@link BorderStyle#DOUBLE} instead. */ @Removal(version="3.17") - static final short BORDER_DOUBLE = 0x6; //BorderStyle.DOUBLE.getCode(); + short BORDER_DOUBLE = 0x6; //BorderStyle.DOUBLE.getCode(); /** * hair-line border * @deprecated 3.15 beta 2. Use {@link BorderStyle#HAIR} instead. */ @Removal(version="3.17") - static final short BORDER_HAIR = 0x7; //BorderStyle.HAIR.getCode(); + short BORDER_HAIR = 0x7; //BorderStyle.HAIR.getCode(); /** * Medium dashed border * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASHED} instead. */ @Removal(version="3.17") - static final short BORDER_MEDIUM_DASHED = 0x8; //BorderStyle.MEDIUM_DASHED.getCode(); + short BORDER_MEDIUM_DASHED = 0x8; //BorderStyle.MEDIUM_DASHED.getCode(); /** * dash-dot border * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT} instead. */ @Removal(version="3.17") - static final short BORDER_DASH_DOT = 0x9; //BorderStyle.DASH_DOT.getCode(); + short BORDER_DASH_DOT = 0x9; //BorderStyle.DASH_DOT.getCode(); /** * medium dash-dot border * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT} instead. */ @Removal(version="3.17") - static final short BORDER_MEDIUM_DASH_DOT = 0xA; //BorderStyle.MEDIUM_DASH_DOT.getCode(); + short BORDER_MEDIUM_DASH_DOT = 0xA; //BorderStyle.MEDIUM_DASH_DOT.getCode(); /** * dash-dot-dot border * @deprecated 3.15 beta 2. Use {@link BorderStyle#DASH_DOT_DOT} instead. */ @Removal(version="3.17") - static final short BORDER_DASH_DOT_DOT = 0xB; //BorderStyle.DASH_DOT_DOT.getCode(); + short BORDER_DASH_DOT_DOT = 0xB; //BorderStyle.DASH_DOT_DOT.getCode(); /** * medium dash-dot-dot border * @deprecated 3.15 beta 2. Use {@link BorderStyle#MEDIUM_DASH_DOT_DOT} instead. */ @Removal(version="3.17") - static final short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; //BorderStyle.MEDIUM_DASH_DOT_DOT.getCode(); + short BORDER_MEDIUM_DASH_DOT_DOT = 0xC; //BorderStyle.MEDIUM_DASH_DOT_DOT.getCode(); /** * slanted dash-dot border * @deprecated 3.15 beta 2. Use {@link BorderStyle#SLANTED_DASH_DOT} instead. */ @Removal(version="3.17") - static final short BORDER_SLANTED_DASH_DOT = 0xD; //BorderStyle.SLANTED_DASH_DOT.getCode(); + short BORDER_SLANTED_DASH_DOT = 0xD; //BorderStyle.SLANTED_DASH_DOT.getCode(); /** * Fill Pattern: No background * @deprecated 3.15 beta 3. Use {@link FillPatternType#NO_FILL} instead. */ @Removal(version="3.17") - static final short NO_FILL = 0; //FillPatternType.NO_FILL.getCode(); + short NO_FILL = 0; //FillPatternType.NO_FILL.getCode(); /** * Fill Pattern: Solidly filled * @deprecated 3.15 beta 3. Use {@link FillPatternType#SOLID_FOREGROUND} instead. */ @Removal(version="3.17") - static final short SOLID_FOREGROUND = 1; //FillPatternType.SOLID_FOREGROUND.getCode(); + short SOLID_FOREGROUND = 1; //FillPatternType.SOLID_FOREGROUND.getCode(); /** * Fill Pattern: Small fine dots * @deprecated 3.15 beta 3. Use {@link FillPatternType#FINE_DOTS} instead. */ @Removal(version="3.17") - static final short FINE_DOTS = 2; //FillPatternType.FINE_DOTS.getCode(); + short FINE_DOTS = 2; //FillPatternType.FINE_DOTS.getCode(); /** * Fill Pattern: Wide dots * @deprecated 3.15 beta 3. Use {@link FillPatternType#ALT_BARS} instead. */ @Removal(version="3.17") - static final short ALT_BARS = 3; //FillPatternType.ALT_BARS.getCode(); + short ALT_BARS = 3; //FillPatternType.ALT_BARS.getCode(); /** * Fill Pattern: Sparse dots * @deprecated 3.15 beta 3. Use {@link FillPatternType#SPARSE_DOTS} instead. */ @Removal(version="3.17") - static final short SPARSE_DOTS = 4; //FillPatternType.SPARSE_DOTS.getCode(); + short SPARSE_DOTS = 4; //FillPatternType.SPARSE_DOTS.getCode(); /** * Fill Pattern: Thick horizontal bands * @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_HORZ_BANDS} instead. */ @Removal(version="3.17") - static final short THICK_HORZ_BANDS = 5; //FillPatternType.THICK_HORZ_BANDS.getCode(); + short THICK_HORZ_BANDS = 5; //FillPatternType.THICK_HORZ_BANDS.getCode(); /** * Fill Pattern: Thick vertical bands * @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_VERT_BANDS} instead. */ @Removal(version="3.17") - static final short THICK_VERT_BANDS = 6; //FillPatternType.THICK_VERT_BANDS.getCode(); + short THICK_VERT_BANDS = 6; //FillPatternType.THICK_VERT_BANDS.getCode(); /** * Fill Pattern: Thick backward facing diagonals * @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_BACKWARD_DIAG} instead. */ @Removal(version="3.17") - static final short THICK_BACKWARD_DIAG = 7; //FillPatternType.THICK_BACKWARD_DIAG.getCode(); + short THICK_BACKWARD_DIAG = 7; //FillPatternType.THICK_BACKWARD_DIAG.getCode(); /** * Fill Pattern: Thick forward facing diagonals * @deprecated 3.15 beta 3. Use {@link FillPatternType#THICK_FORWARD_DIAG} instead. */ @Removal(version="3.17") - static final short THICK_FORWARD_DIAG = 8; //FillPatternType.THICK_FORWARD_DIAG.getCode(); + short THICK_FORWARD_DIAG = 8; //FillPatternType.THICK_FORWARD_DIAG.getCode(); /** * Fill Pattern: Large spots * @deprecated 3.15 beta 3. Use {@link FillPatternType#BIG_SPOTS} instead. */ @Removal(version="3.17") - static final short BIG_SPOTS = 9; //FillPatternType.BIG_SPOTS.getCode(); + short BIG_SPOTS = 9; //FillPatternType.BIG_SPOTS.getCode(); /** * Fill Pattern: Brick-like layout * @deprecated 3.15 beta 3. Use {@link FillPatternType#BRICKS} instead. */ @Removal(version="3.17") - static final short BRICKS = 10; //FillPatternType.BRICKS.getCode(); + short BRICKS = 10; //FillPatternType.BRICKS.getCode(); /** * Fill Pattern: Thin horizontal bands * @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_HORZ_BANDS} instead. */ @Removal(version="3.17") - static final short THIN_HORZ_BANDS = 11; //FillPatternType.THIN_HORZ_BANDS.getCode(); + short THIN_HORZ_BANDS = 11; //FillPatternType.THIN_HORZ_BANDS.getCode(); /** * Fill Pattern: Thin vertical bands * @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_VERT_BANDS} instead. */ @Removal(version="3.17") - static final short THIN_VERT_BANDS = 12; //FillPatternType.THIN_VERT_BANDS.getCode(); + short THIN_VERT_BANDS = 12; //FillPatternType.THIN_VERT_BANDS.getCode(); /** * Fill Pattern: Thin backward diagonal * @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_BACKWARD_DIAG} instead. */ @Removal(version="3.17") - static final short THIN_BACKWARD_DIAG = 13; //FillPatternType.THIN_BACKWARD_DIAG.getCode(); + short THIN_BACKWARD_DIAG = 13; //FillPatternType.THIN_BACKWARD_DIAG.getCode(); /** * Fill Pattern: Thin forward diagonal * @deprecated 3.15 beta 3. Use {@link FillPatternType#THIN_FORWARD_DIAG} instead. */ @Removal(version="3.17") - static final short THIN_FORWARD_DIAG = 14; //FillPatternType.THIN_FORWARD_DIAG.getCode(); + short THIN_FORWARD_DIAG = 14; //FillPatternType.THIN_FORWARD_DIAG.getCode(); /** * Fill Pattern: Squares * @deprecated 3.15 beta 3. Use {@link FillPatternType#SQUARES} instead. */ @Removal(version="3.17") - static final short SQUARES = 15; //FillPatternType.SQUARES.getCode(); + short SQUARES = 15; //FillPatternType.SQUARES.getCode(); /** * Fill Pattern: Diamonds * @deprecated 3.15 beta 3. Use {@link FillPatternType#DIAMONDS} instead. */ @Removal(version="3.17") - static final short DIAMONDS = 16; //FillPatternType.DIAMONDS.getCode(); + short DIAMONDS = 16; //FillPatternType.DIAMONDS.getCode(); /** * Fill Pattern: Less Dots * @deprecated 3.15 beta 3. Use {@link FillPatternType#LESS_DOTS} instead. */ @Removal(version="3.17") - static final short LESS_DOTS = 17; //FillPatternType.LESS_DOTS.getCode(); + short LESS_DOTS = 17; //FillPatternType.LESS_DOTS.getCode(); /** * Fill Pattern: Least Dots * @deprecated 3.15 beta 3. Use {@link FillPatternType#LEAST_DOTS} instead. */ @Removal(version="3.17") - static final short LEAST_DOTS = 18; //FillPatternType.LEAST_DOTS.getCode(); + short LEAST_DOTS = 18; //FillPatternType.LEAST_DOTS.getCode(); /** * get the index within the Workbook (sequence within the collection of ExtnededFormat objects) @@ -353,7 +353,7 @@ public interface CellStyle { /** * Get the format string */ - public String getDataFormatString(); + String getDataFormatString(); /** * set the font for this style @@ -870,17 +870,17 @@ public interface CellStyle { * to be of the same type (HSSFCellStyle or * XSSFCellStyle) */ - public void cloneStyleFrom(CellStyle source); + void cloneStyleFrom(CellStyle source); /** * Controls if the Cell should be auto-sized * to shrink to fit if the text is too long */ - public void setShrinkToFit(boolean shrinkToFit); + void setShrinkToFit(boolean shrinkToFit); /** * Should the Cell be auto-sized by Excel to shrink * it to fit if this text is too long? */ - public boolean getShrinkToFit(); + boolean getShrinkToFit(); } diff --git a/src/java/org/apache/poi/ss/usermodel/CellValue.java b/src/java/org/apache/poi/ss/usermodel/CellValue.java index 301accfca8..b10210882a 100644 --- a/src/java/org/apache/poi/ss/usermodel/CellValue.java +++ b/src/java/org/apache/poi/ss/usermodel/CellValue.java @@ -18,6 +18,8 @@ package org.apache.poi.ss.usermodel; import org.apache.poi.ss.formula.eval.ErrorEval; +import org.apache.poi.util.Internal; +import org.apache.poi.util.Removal; /** * Mimics the 'data view' of a cell. This allows formula evaluator @@ -47,12 +49,15 @@ public final class CellValue { public CellValue(double numberValue) { this(CellType.NUMERIC, numberValue, false, null, 0); } + public static CellValue valueOf(boolean booleanValue) { return booleanValue ? TRUE : FALSE; } + public CellValue(String stringValue) { this(CellType.STRING, 0.0, false, stringValue, 0); } + public static CellValue getError(int errorCode) { return new CellValue(CellType.ERROR, 0.0, false, null, errorCode); } @@ -64,30 +69,44 @@ public final class CellValue { public boolean getBooleanValue() { return _booleanValue; } + /** * @return Returns the numberValue. */ public double getNumberValue() { return _numberValue; } + /** * @return Returns the stringValue. */ public String getStringValue() { return _textValue; } + + /** + * Return the cell type. + * + * @return the cell type + * @since POI 3.15 + * @deprecated POI 3.15 + * Will be renamed to getCellTypeEnum() when we make the CellType enum transition in POI 4.0. See bug 59791. + */ + @Internal(since="POI 3.15 beta 3") + @Removal(version="4.2") + public CellType getCellTypeEnum() { + return _cellType; + } + /** - * @return Returns the cellType. - * @since POI 3.15 - */ - public CellType getCellTypeEnum() { - return _cellType; - } - /** - * @return Returns the cellType. + * Return the cell type. + * + * Will return {@link CellType} in version 4.0 of POI. + * For forwards compatibility, do not hard-code cell type literals in your code. + * + * @return the cell type + * * @deprecated POI 3.15. Use {@link #getCellTypeEnum()} instead. - * In the future, the signature of this method will be changed to return a - * {@link CellType}. */ @Deprecated public int getCellType() { @@ -100,6 +119,7 @@ public final class CellValue { public byte getErrorValue() { return (byte) _errorCode; } + public String toString() { StringBuffer sb = new StringBuffer(64); sb.append(getClass().getName()).append(" ["); diff --git a/src/java/org/apache/poi/ss/usermodel/Workbook.java b/src/java/org/apache/poi/ss/usermodel/Workbook.java index e52615fb1a..f5043b727f 100644 --- a/src/java/org/apache/poi/ss/usermodel/Workbook.java +++ b/src/java/org/apache/poi/ss/usermodel/Workbook.java @@ -35,22 +35,22 @@ import org.apache.poi.ss.usermodel.Row.MissingCellPolicy; public interface Workbook extends Closeable, Iterable { /** Extended windows meta file */ - public static final int PICTURE_TYPE_EMF = 2; + int PICTURE_TYPE_EMF = 2; /** Windows Meta File */ - public static final int PICTURE_TYPE_WMF = 3; + int PICTURE_TYPE_WMF = 3; /** Mac PICT format */ - public static final int PICTURE_TYPE_PICT = 4; + int PICTURE_TYPE_PICT = 4; /** JPEG format */ - public static final int PICTURE_TYPE_JPEG = 5; + int PICTURE_TYPE_JPEG = 5; /** PNG format */ - public static final int PICTURE_TYPE_PNG = 6; + int PICTURE_TYPE_PNG = 6; /** Device independent bitmap */ - public static final int PICTURE_TYPE_DIB = 7; + int PICTURE_TYPE_DIB = 7; /** @@ -58,14 +58,14 @@ public interface Workbook extends Closeable, Iterable { * * @see #setSheetHidden(int, int) */ - public static final int SHEET_STATE_VISIBLE = 0; + int SHEET_STATE_VISIBLE = 0; /** * Indicates the book window is hidden, but can be shown by the user via the user interface. * * @see #setSheetHidden(int, int) */ - public static final int SHEET_STATE_HIDDEN = 1; + int SHEET_STATE_HIDDEN = 1; /** * Indicates the sheet is hidden and cannot be shown in the user interface (UI). @@ -77,7 +77,7 @@ public interface Workbook extends Closeable, Iterable { * * @see #setSheetHidden(int, int) */ - public static final int SHEET_STATE_VERY_HIDDEN = 2; + int SHEET_STATE_VERY_HIDDEN = 2; /** * Convenience method to get the active sheet. The active sheet is is the sheet @@ -169,7 +169,7 @@ public interface Workbook extends Closeable, Iterable { int getSheetIndex(Sheet sheet); /** - * Sreate an Sheet for this Workbook, adds it to the sheets and returns + * Create a Sheet for this Workbook, adds it to the sheets and returns * the high level representation. Use this to create new sheets. * * @return Sheet representing the new sheet. @@ -217,7 +217,7 @@ public interface Workbook extends Closeable, Iterable { * See {@link org.apache.poi.ss.util.WorkbookUtil#createSafeSheetName(String nameProposal)} * for a safe way to create valid names *

- * @param sheetname sheetname to set for the sheet. + * @param sheetname The name to set for the sheet. * @return Sheet representing the new sheet. * @throws IllegalArgumentException if the name is null or invalid * or workbook already contains a sheet with this name @@ -253,6 +253,8 @@ public interface Workbook extends Closeable, Iterable { * * @param index of the sheet number (0-based physical & logical) * @return Sheet at the provided index + * @throws IllegalArgumentException if the index is out of range (index + * < 0 || index >= getNumberOfSheets()). */ Sheet getSheetAt(int index); @@ -617,7 +619,7 @@ public interface Workbook extends Closeable, Iterable { * workbook values when the workbook is opened * @since 3.8 */ - public void setForceFormulaRecalculation(boolean value); + void setForceFormulaRecalculation(boolean value); /** * Whether Excel will be asked to recalculate all formulas when the workbook is opened. @@ -632,6 +634,5 @@ public interface Workbook extends Closeable, Iterable { * @return SpreadsheetVersion enum * @since 3.14 beta 2 */ - public SpreadsheetVersion getSpreadsheetVersion(); - + SpreadsheetVersion getSpreadsheetVersion(); } diff --git a/src/java/org/apache/poi/ss/util/SheetUtil.java b/src/java/org/apache/poi/ss/util/SheetUtil.java index d64dbeba82..f234380fe9 100644 --- a/src/java/org/apache/poi/ss/util/SheetUtil.java +++ b/src/java/org/apache/poi/ss/util/SheetUtil.java @@ -128,7 +128,7 @@ public class SheetUtil { // We should only be checking merged regions if useMergedCells is true. Why are we doing this for-loop? int colspan = 1; for (CellRangeAddress region : sheet.getMergedRegions()) { - if (containsCell(region, row.getRowNum(), column)) { + if (region.isInRange(row.getRowNum(), column)) { if (!useMergedCells) { // If we're not using merged cells, skip this one and move on to the next. return -1; @@ -151,8 +151,8 @@ public class SheetUtil { if (cellType == CellType.STRING) { RichTextString rt = cell.getRichStringCellValue(); String[] lines = rt.getString().split("\\n"); - for (int i = 0; i < lines.length; i++) { - String txt = lines[i] + defaultChar; + for (String line : lines) { + String txt = line + defaultChar; AttributedString str = new AttributedString(txt); copyAttributes(font, str, 0, txt.length()); @@ -193,7 +193,7 @@ public class SheetUtil { * @param defaultCharWidth the width of a character using the default font in a workbook * @param colspan the number of columns that is spanned by the cell (1 if the cell is not part of a merged region) * @param style the cell style, which contains text rotation and indention information needed to compute the cell width - * @param width the minimum best-fit width. This algorithm will only return values greater than or equal to the minimum width. + * @param minWidth the minimum best-fit width. This algorithm will only return values greater than or equal to the minimum width. * @param str the text contained in the cell * @return the best fit cell width */ @@ -219,8 +219,7 @@ public class SheetUtil { } // frameWidth accounts for leading spaces which is excluded from bounds.getWidth() final double frameWidth = bounds.getX() + bounds.getWidth(); - final double width = Math.max(minWidth, ((frameWidth / colspan) / defaultCharWidth) + style.getIndention()); - return width; + return Math.max(minWidth, ((frameWidth / colspan) / defaultCharWidth) + style.getIndention()); } /** @@ -273,13 +272,12 @@ public class SheetUtil { AttributedString str = new AttributedString(String.valueOf(defaultChar)); copyAttributes(defaultFont, str, 0, 1); TextLayout layout = new TextLayout(str.getIterator(), fontRenderContext); - int defaultCharWidth = (int) layout.getAdvance(); - return defaultCharWidth; + return (int) layout.getAdvance(); } /** * Compute width of a single cell in a row - * Convenience method for {@link getCellWidth} + * Convenience method for {@link #getCellWidth} * * @param row the row that contains the cell of interest * @param column the column number of the cell whose width is to be calculated @@ -334,7 +332,7 @@ public class SheetUtil { private static void copyAttributes(Font font, AttributedString str, int startIdx, int endIdx) { str.addAttribute(TextAttribute.FAMILY, font.getFontName(), startIdx, endIdx); str.addAttribute(TextAttribute.SIZE, (float)font.getFontHeightInPoints()); - if (font.getBoldweight() == Font.BOLDWEIGHT_BOLD) str.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIdx, endIdx); + if (font.getBold()) str.addAttribute(TextAttribute.WEIGHT, TextAttribute.WEIGHT_BOLD, startIdx, endIdx); if (font.getItalic() ) str.addAttribute(TextAttribute.POSTURE, TextAttribute.POSTURE_OBLIQUE, startIdx, endIdx); if (font.getUnderline() == Font.U_SINGLE ) str.addAttribute(TextAttribute.UNDERLINE, TextAttribute.UNDERLINE_ON, startIdx, endIdx); } @@ -348,6 +346,7 @@ public class SheetUtil { * @return true if the range contains the cell [rowIx, colIx] * @deprecated 3.15 beta 2. Use {@link CellRangeAddressBase#isInRange(int, int)}. */ + @Deprecated public static boolean containsCell(CellRangeAddress cr, int rowIx, int colIx) { return cr.isInRange(rowIx, colIx); } diff --git a/src/java/org/apache/poi/util/CommonsLogger.java b/src/java/org/apache/poi/util/CommonsLogger.java index 1cbb9628ca..a204fde17a 100644 --- a/src/java/org/apache/poi/util/CommonsLogger.java +++ b/src/java/org/apache/poi/util/CommonsLogger.java @@ -30,7 +30,7 @@ import org.apache.commons.logging.LogFactory; */ public class CommonsLogger extends POILogger { - private static LogFactory _creator = LogFactory.getFactory(); + private static final LogFactory _creator = LogFactory.getFactory(); private Log log = null; @Override @@ -46,8 +46,10 @@ public class CommonsLogger extends POILogger * @param obj1 The object to log. */ @Override - public void log(final int level, final Object obj1) + protected void _log(final int level, final Object obj1) { + // FIXME: What happens if level is in between two levels (an even number)? + // Should this be `if (level >= FATAL) ...`? if(level==FATAL) { if(log.isFatalEnabled()) @@ -100,9 +102,11 @@ public class CommonsLogger extends POILogger * @param exception An exception to be logged */ @Override - public void log(final int level, final Object obj1, + protected void _log(final int level, final Object obj1, final Throwable exception) { + // FIXME: What happens if level is in between two levels (an even number)? + // Should this be `if (level >= FATAL) ...`? if(level==FATAL) { if(log.isFatalEnabled()) @@ -174,6 +178,8 @@ public class CommonsLogger extends POILogger @Override public boolean check(final int level) { + // FIXME: What happens if level is in between two levels (an even number)? + // Should this be `if (level >= FATAL) ...`? if(level==FATAL) { if(log.isFatalEnabled()) diff --git a/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java b/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java index ef9e8443a4..6f44752873 100644 --- a/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java +++ b/src/java/org/apache/poi/util/DefaultTempFileCreationStrategy.java @@ -83,15 +83,22 @@ public class DefaultTempFileCreationStrategy implements TempFileCreationStrategy } /** - * Attempt to create a directory + * Attempt to create a directory, including any necessary parent directories. + * Does nothing if directory already exists. * - * @param directory - * @throws IOException + * @param directory the directory to create + * @throws IOException if unable to create temporary directory or it is not a directory */ private void createTempDirectory(File directory) throws IOException { - if (!(directory.exists() || directory.mkdirs()) || !directory.isDirectory()) { + // create directory if it doesn't exist + final boolean dirExists = (directory.exists() || directory.mkdirs()); + + if (!dirExists) { throw new IOException("Could not create temporary directory '" + directory + "'"); } + else if (!directory.isDirectory()) { + throw new IOException("Could not create temporary directory. '" + directory + "' exists but is not a directory."); + } } @Override diff --git a/src/java/org/apache/poi/util/NullLogger.java b/src/java/org/apache/poi/util/NullLogger.java index fe0979cfef..e21adfaa7f 100644 --- a/src/java/org/apache/poi/util/NullLogger.java +++ b/src/java/org/apache/poi/util/NullLogger.java @@ -23,6 +23,7 @@ package org.apache.poi.util; * calls as cheap as possible by performing lazy evaluation of the log * message.

*/ +@Internal public class NullLogger extends POILogger { @Override public void initialize(final String cat) { @@ -37,7 +38,7 @@ public class NullLogger extends POILogger { */ @Override - public void log(final int level, final Object obj1) { + protected void _log(final int level, final Object obj1) { // do nothing } @@ -49,7 +50,19 @@ public class NullLogger extends POILogger { * @param exception An exception to be logged */ @Override - public void log(int level, Object obj1, final Throwable exception) { + protected void _log(int level, Object obj1, final Throwable exception) { + // do nothing + } + + /** + * Log a message. Lazily appends Object parameters together. + * If the last parameter is a {@link Throwable} it is logged specially. + * + * @param level One of DEBUG, INFO, WARN, ERROR, FATAL + * @param objs the objects to place in the message + */ + @Override + public void log(int level, Object... objs) { // do nothing } diff --git a/src/java/org/apache/poi/util/POILogFactory.java b/src/java/org/apache/poi/util/POILogFactory.java index ba2551de7b..1e34ccd29b 100644 --- a/src/java/org/apache/poi/util/POILogFactory.java +++ b/src/java/org/apache/poi/util/POILogFactory.java @@ -35,7 +35,7 @@ public final class POILogFactory { /** * Map of POILogger instances, with classes as keys */ - private static Map _loggers = new HashMap(); + private static final Map _loggers = new HashMap(); /** * A common instance of NullLogger, as it does nothing diff --git a/src/java/org/apache/poi/util/POILogger.java b/src/java/org/apache/poi/util/POILogger.java index 04198bfbab..c54c754255 100644 --- a/src/java/org/apache/poi/util/POILogger.java +++ b/src/java/org/apache/poi/util/POILogger.java @@ -54,7 +54,7 @@ public abstract class POILogger { * @param level One of DEBUG, INFO, WARN, ERROR, FATAL * @param obj1 The object to log. This is converted to a string. */ - abstract protected void log(int level, Object obj1); + abstract protected void _log(int level, Object obj1); /** * Log a message @@ -63,11 +63,20 @@ public abstract class POILogger { * @param obj1 The object to log. This is converted to a string. * @param exception An exception to be logged */ - abstract protected void log(int level, Object obj1, final Throwable exception); + abstract protected void _log(int level, Object obj1, final Throwable exception); /** * Check if a logger is enabled to log at the specified level + * This allows code to avoid building strings or evaluating functions in + * the arguments to log. + * + * An example: + *

+     * if (logger.check(POILogger.INFO)) {
+     *     logger.log(POILogger.INFO, "Avoid concatenating " + " strings and evaluating " + functions());
+     * }
+     * 
* * @param level One of DEBUG, INFO, WARN, ERROR, FATAL */ @@ -98,9 +107,9 @@ public abstract class POILogger { // somehow this ambiguity works and doesn't lead to a loop, // but it's confusing ... if (lastEx == null) { - log(level, msg); + _log(level, msg); } else { - log(level, msg, lastEx); + _log(level, msg, lastEx); } } } diff --git a/src/java/org/apache/poi/util/SystemOutLogger.java b/src/java/org/apache/poi/util/SystemOutLogger.java index 36d96ca038..457f25410c 100644 --- a/src/java/org/apache/poi/util/SystemOutLogger.java +++ b/src/java/org/apache/poi/util/SystemOutLogger.java @@ -42,9 +42,9 @@ public class SystemOutLogger extends POILogger * @param obj1 The object to log. */ @Override - public void log(final int level, final Object obj1) + protected void _log(final int level, final Object obj1) { - log(level, obj1, null); + _log(level, obj1, null); } /** @@ -56,7 +56,7 @@ public class SystemOutLogger extends POILogger */ @Override @SuppressForbidden("uses printStackTrace") - public void log(final int level, final Object obj1, + protected void _log(final int level, final Object obj1, final Throwable exception) { if (check(level)) { System.out.println("[" + _cat + "]" + LEVEL_STRINGS_SHORT[Math.min(LEVEL_STRINGS_SHORT.length-1, level)] + " " + obj1); diff --git a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java index a67e83e246..cdd35b3594 100644 --- a/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java +++ b/src/ooxml/java/org/apache/poi/extractor/ExtractorFactory.java @@ -33,7 +33,6 @@ import org.apache.poi.hsmf.datatypes.AttachmentChunks; import org.apache.poi.hsmf.extractor.OutlookTextExtactor; import org.apache.poi.hssf.extractor.ExcelExtractor; import org.apache.poi.hwpf.extractor.WordExtractor; -import org.apache.poi.openxml4j.exceptions.InvalidFormatException; import org.apache.poi.openxml4j.exceptions.OpenXML4JException; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; @@ -123,7 +122,7 @@ public class ExtractorFactory { return OLE2ExtractorFactory.getPreferEventExtractor(); } - public static POITextExtractor createExtractor(File f) throws IOException, InvalidFormatException, OpenXML4JException, XmlException { + public static POITextExtractor createExtractor(File f) throws IOException, OpenXML4JException, XmlException { NPOIFSFileSystem fs = null; try { fs = new NPOIFSFileSystem(f); @@ -163,7 +162,7 @@ public class ExtractorFactory { } } - public static POITextExtractor createExtractor(InputStream inp) throws IOException, InvalidFormatException, OpenXML4JException, XmlException { + public static POITextExtractor createExtractor(InputStream inp) throws IOException, OpenXML4JException, XmlException { // Figure out the kind of stream // If clearly doesn't do mark/reset, wrap up if (! inp.markSupported()) { diff --git a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java index 25efc1e559..6779d8a210 100644 --- a/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java +++ b/src/ooxml/java/org/apache/poi/poifs/crypt/dsig/SignatureConfig.java @@ -64,7 +64,7 @@ public class SignatureConfig { private static final POILogger LOG = POILogFactory.getLogger(SignatureConfig.class); - public static interface SignatureConfigurable { + public interface SignatureConfigurable { void setSignatureConfig(SignatureConfig signatureConfig); } diff --git a/src/ooxml/java/org/apache/poi/util/OOXMLLite.java b/src/ooxml/java/org/apache/poi/util/OOXMLLite.java index b320771238..afb60f600e 100644 --- a/src/ooxml/java/org/apache/poi/util/OOXMLLite.java +++ b/src/ooxml/java/org/apache/poi/util/OOXMLLite.java @@ -96,6 +96,7 @@ public final class OOXMLLite { "BaseTestXSheet", "BaseTestXRow", "BaseTestXCell", + "BaseTestXSSFPivotTable", "TestSXSSFWorkbook\\$\\d", "TestSXSSFWorkbook\\$NullOutputStream", "TestUnfixedBugs", diff --git a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java index 0c4e4971d5..70df3f806a 100644 --- a/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java +++ b/src/ooxml/java/org/apache/poi/xslf/usermodel/XSLFShape.java @@ -134,7 +134,7 @@ public abstract class XSLFShape implements Shape { if (this instanceof PlaceableShape) { PlaceableShape ps = (PlaceableShape)this; - ps.setAnchor(((PlaceableShape)sh).getAnchor()); + ps.setAnchor(sh.getAnchor()); } @@ -257,7 +257,7 @@ public abstract class XSLFShape implements Shape { * Different types of placeholders are allowed and can be specified by using the placeholder * type attribute for this element * - * @param placeholder + * @param placeholder The shape to use as placeholder or null if no placeholder should be set. */ protected void setPlaceholder(Placeholder placeholder) { String xquery = "declare namespace p='"+PML_NS+"' .//*/p:nvPr"; @@ -494,7 +494,7 @@ public abstract class XSLFShape implements Shape { int idx = (int)fillRef.getIdx(); CTSchemeColor phClr = fillRef.getSchemeClr(); CTStyleMatrix matrix = theme.getXmlObject().getThemeElements().getFmtScheme(); - XmlObject styleLst = null; + final XmlObject styleLst; int childIdx; if (idx >= 1 && idx <= 999) { childIdx = idx-1; diff --git a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java index 331ad9a0fd..6b9ce374fb 100644 --- a/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java +++ b/src/ooxml/java/org/apache/poi/xssf/streaming/SXSSFWorkbook.java @@ -907,7 +907,9 @@ public class SXSSFWorkbook implements Workbook { try { sheet.getSheetDataWriter().close(); } catch (IOException e) { - // ignore exception here + logger.log(POILogger.WARN, + "An exception occurred while closing sheet data writer for sheet " + + sheet.getSheetName() + ".", e); } } @@ -926,11 +928,8 @@ public class SXSSFWorkbook implements Workbook { @Override public void write(OutputStream stream) throws IOException { - for (SXSSFSheet sheet : _xFromSxHash.values()) - { - sheet.flushRows(); - } - + flushSheets(); + //Save the template File tmplFile = TempFile.createTempFile("poi-sxssf-template", ".xlsx"); try @@ -956,6 +955,13 @@ public class SXSSFWorkbook implements Workbook { } } + protected void flushSheets() throws IOException { + for (SXSSFSheet sheet : _xFromSxHash.values()) + { + sheet.flushRows(); + } + } + /** * Dispose of temporary files backing this workbook on disk. * Calling this method will render the workbook unusable. diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java index 780126c3d5..11fe3efadf 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/BaseXSSFFormulaEvaluator.java @@ -28,7 +28,7 @@ import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.CellValue; -import org.apache.poi.ss.usermodel.RichTextString; +import org.apache.poi.util.Internal; /** * Internal POI use only - parent of XSSF and SXSSF formula evaluators @@ -52,6 +52,78 @@ public abstract class BaseXSSFFormulaEvaluator extends BaseFormulaEvaluator { _bookEvaluator.notifyUpdateCell(new XSSFEvaluationCell((XSSFCell)cell)); } + /** + * If cell contains formula, it evaluates the formula, + * and saves the result of the formula. The cell + * remains as a formula cell. + * Else if cell does not contain formula, this method leaves + * the cell unchanged. + * Note that the type of the formula result is returned, + * so you know what kind of value is also stored with + * the formula. + *
+     * CellType evaluatedCellType = evaluator.evaluateFormulaCellEnum(cell);
+     * 
+ * Be aware that your cell will hold both the formula, + * and the result. If you want the cell replaced with + * the result of the formula, use {@link #evaluate(org.apache.poi.ss.usermodel.Cell)} } + * @param cell The cell to evaluate + * @return The type of the formula result (the cell's type remains as CellType.FORMULA however) + * If cell is not a formula cell, returns {@link CellType#_NONE} rather than throwing an exception. + * @since POI 3.15 beta 3 + * @deprecated POI 3.15 beta 3. Will be deleted when we make the CellType enum transition. See bug 59791. + */ + @Internal(since="POI 3.15 beta 3") + public CellType evaluateFormulaCellEnum(Cell cell) { + if (cell == null || cell.getCellTypeEnum() != CellType.FORMULA) { + return CellType._NONE; + } + CellValue cv = evaluateFormulaCellValue(cell); + // cell remains a formula cell, but the cached value is changed + setCellValue(cell, cv); + return cv.getCellType(); + } + + /** + * If cell contains formula, it evaluates the formula, and + * puts the formula result back into the cell, in place + * of the old formula. + * Else if cell does not contain formula, this method leaves + * the cell unchanged. + */ + protected void doEvaluateInCell(Cell cell) { + if (cell == null) return; + if (cell.getCellTypeEnum() == CellType.FORMULA) { + CellValue cv = evaluateFormulaCellValue(cell); + setCellType(cell, cv); // cell will no longer be a formula cell + setCellValue(cell, cv); + } + } + + private static void setCellValue(Cell cell, CellValue cv) { + CellType cellType = cv.getCellType(); + switch (cellType) { + case BOOLEAN: + cell.setCellValue(cv.getBooleanValue()); + break; + case ERROR: + cell.setCellErrorValue(cv.getErrorValue()); + break; + case NUMERIC: + cell.setCellValue(cv.getNumberValue()); + break; + case STRING: + cell.setCellValue(new XSSFRichTextString(cv.getStringValue())); + break; + case BLANK: + // never happens - blanks eventually get translated to zero + case FORMULA: + // this will never happen, we have already evaluated the formula + default: + throw new IllegalStateException("Unexpected cell value type (" + cellType + ")"); + } + } + /** * Turns a XSSFCell / SXSSFCell into a XSSFEvaluationCell */ diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java index 8ab465aff1..26735c782c 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotCacheDefinition.java @@ -28,10 +28,13 @@ import javax.xml.namespace.QName; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; +import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; +import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.Beta; @@ -41,6 +44,7 @@ import org.apache.xmlbeans.XmlOptions; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCacheField; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCacheFields; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotCacheDefinition; +import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheetSource; public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{ @@ -116,6 +120,40 @@ public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{ out.close(); } + /** + * Find the 2D base data area for the pivot table, either from its direct reference or named table/range. + * @return AreaReference representing the current area defined by the pivot table + * @throws IllegalArgumentException if the ref attribute is not contiguous or the name attribute is not found. + */ + @Beta + public AreaReference getPivotArea(Workbook wb) throws IllegalArgumentException { + final CTWorksheetSource wsSource = ctPivotCacheDefinition.getCacheSource().getWorksheetSource(); + + final String ref = wsSource.getRef(); + final String name = wsSource.getName(); + + if (ref == null && name == null) throw new IllegalArgumentException("Pivot cache must reference an area, named range, or table."); + + // this is the XML format, so tell the reference that. + if (ref != null) return new AreaReference(ref, SpreadsheetVersion.EXCEL2007); + + if (name != null) { + // named range or table? + final Name range = wb.getName(name); + if (range != null) return new AreaReference(range.getRefersToFormula(), SpreadsheetVersion.EXCEL2007); + // not a named range, check for a table. + // do this second, as tables are sheet-specific, but named ranges are not, and may not have a sheet name given. + final XSSFSheet sheet = (XSSFSheet) wb.getSheet(wsSource.getSheet()); + for (XSSFTable table : sheet.getTables()) { + if (table.getName().equals(name)) { //case-sensitive? + return new AreaReference(table.getStartCellReference(), table.getEndCellReference()); + } + } + } + + throw new IllegalArgumentException("Name '" + name + "' was not found."); + } + /** * Generates a cache field for each column in the reference area for the pivot table. * @param sheet The sheet where the data i collected from @@ -123,7 +161,7 @@ public class XSSFPivotCacheDefinition extends POIXMLDocumentPart{ @Beta protected void createCacheFields(Sheet sheet) { //Get values for start row, start and end column - AreaReference ar = new AreaReference(ctPivotCacheDefinition.getCacheSource().getWorksheetSource().getRef()); + AreaReference ar = getPivotArea(sheet.getWorkbook()); CellReference firstCell = ar.getFirstCell(); CellReference lastCell = ar.getLastCell(); int columnStart = firstCell.getCol(); diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java index bf85f65de1..e6f91afde7 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFPivotTable.java @@ -30,11 +30,11 @@ import javax.xml.namespace.QName; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackageRelationship; -import org.apache.poi.ss.SpreadsheetVersion; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.DataConsolidateFunction; import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Workbook; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.util.Beta; @@ -214,13 +214,8 @@ public class XSSFPivotTable extends POIXMLDocumentPart { } protected AreaReference getPivotArea() { - AreaReference pivotArea = new AreaReference( - getPivotCacheDefinition() - .getCTPivotCacheDefinition() - .getCacheSource() - .getWorksheetSource() - .getRef(), - SpreadsheetVersion.EXCEL2007); + final Workbook wb = getDataSheet().getWorkbook(); + AreaReference pivotArea = getPivotCacheDefinition().getPivotArea(wb); return pivotArea; } @@ -419,12 +414,13 @@ public class XSSFPivotTable extends POIXMLDocumentPart { /** * Creates cacheSource and workSheetSource for pivot table and sets the source reference as well assets the location of the pivot table - * @param source Source for data for pivot table * @param position Position for pivot table in sheet * @param sourceSheet Sheet where the source will be collected from + * @param refConfig an configurator that knows how to configure pivot table references */ @Beta - protected void createSourceReferences(AreaReference source, CellReference position, Sheet sourceSheet){ + protected void createSourceReferences(CellReference position, Sheet sourceSheet, PivotTableReferenceConfigurator refConfig){ + //Get cell one to the right and one down from position, add both to AreaReference and set pivot table location. AreaReference destination = new AreaReference(position, new CellReference(position.getRow()+1, position.getCol()+1)); @@ -448,9 +444,8 @@ public class XSSFPivotTable extends POIXMLDocumentPart { worksheetSource.setSheet(sourceSheet.getSheetName()); setDataSheet(sourceSheet); - String[] firstCell = source.getFirstCell().getCellRefParts(); - String[] lastCell = source.getLastCell().getCellRefParts(); - worksheetSource.setRef(firstCell[2]+firstCell[1]+':'+lastCell[2]+lastCell[1]); + refConfig.configureReference(worksheetSource); + if (worksheetSource.getName() == null && worksheetSource.getRef() == null) throw new IllegalArgumentException("Pivot table source area reference or name must be specified."); } @Beta @@ -465,11 +460,20 @@ public class XSSFPivotTable extends POIXMLDocumentPart { int firstColumn = sourceArea.getFirstCell().getCol(); int lastColumn = sourceArea.getLastCell().getCol(); CTPivotField pivotField; - for(int i = 0; i<=lastColumn-firstColumn; i++) { + for(int i = firstColumn; i<=lastColumn; i++) { pivotField = pivotFields.addNewPivotField(); pivotField.setDataField(false); pivotField.setShowAll(false); } pivotFields.setCount(pivotFields.sizeOfPivotFieldArray()); } + + protected static interface PivotTableReferenceConfigurator { + + /** + * Configure the name or area reference for the pivot table + * @param wsSource CTWorksheetSource that needs the pivot source reference assignment + */ + public void configureReference(CTWorksheetSource wsSource); + } } diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java index d72dca445e..bc2f071bea 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/XSSFSheet.java @@ -64,8 +64,10 @@ import org.apache.poi.ss.usermodel.Footer; import org.apache.poi.ss.usermodel.Header; import org.apache.poi.ss.usermodel.IgnoredErrorType; import org.apache.poi.ss.usermodel.IndexedColors; +import org.apache.poi.ss.usermodel.Name; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; +import org.apache.poi.ss.usermodel.Table; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellRangeAddress; @@ -80,6 +82,7 @@ import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import org.apache.poi.util.Removal; import org.apache.poi.xssf.model.CommentsTable; +import org.apache.poi.xssf.usermodel.XSSFPivotTable.PivotTableReferenceConfigurator; import org.apache.poi.xssf.usermodel.helpers.ColumnHelper; import org.apache.poi.xssf.usermodel.helpers.XSSFIgnoredErrorHelper; import org.apache.poi.xssf.usermodel.helpers.XSSFRowShifter; @@ -1925,15 +1928,17 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } // Performance optimization: explicit boxing is slightly faster than auto-unboxing, though may use more memory - final Integer rownumI = new Integer(row.getRowNum()); // NOSONAR - int idx = _rows.headMap(rownumI).size(); - _rows.remove(rownumI); + final int rowNum = row.getRowNum(); + final Integer rowNumI = new Integer(rowNum); // NOSONAR + // this is not the physical row number! + final int idx = _rows.headMap(rowNumI).size(); + _rows.remove(rowNumI); worksheet.getSheetData().removeRow(idx); // also remove any comment located in that row if(sheetComments != null) { for (CellAddress ref : getCellComments().keySet()) { - if (ref.getRow() == idx) { + if (ref.getRow() == rowNum) { sheetComments.removeComment(ref); } } @@ -4158,27 +4163,56 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } /** - * Create a pivot table and set area of source, source sheet and a position for pivot table - * @param source Area from where data will be collected - * @param position A reference to the cell where the table will start - * @param sourceSheet The sheet where source will be collected from + * Create a pivot table using the AreaReference range on sourceSheet, at the given position. + * If the source reference contains a sheet name, it must match the sourceSheet + * @param source location of pivot data + * @param position A reference to the top left cell where the pivot table will start + * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name + * @throws IllegalArgumentException if source references a sheet different than sourceSheet * @return The pivot table */ @Beta - public XSSFPivotTable createPivotTable(AreaReference source, CellReference position, Sheet sourceSheet) { + public XSSFPivotTable createPivotTable(final AreaReference source, CellReference position, Sheet sourceSheet) { final String sourceSheetName = source.getFirstCell().getSheetName(); if(sourceSheetName != null && !sourceSheetName.equalsIgnoreCase(sourceSheet.getSheetName())) { throw new IllegalArgumentException("The area is referenced in another sheet than the " + "defined source sheet " + sourceSheet.getSheetName() + "."); } + + return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() { + public void configureReference(CTWorksheetSource wsSource) { + final String[] firstCell = source.getFirstCell().getCellRefParts(); + final String firstRow = firstCell[1]; + final String firstCol = firstCell[2]; + final String[] lastCell = source.getLastCell().getCellRefParts(); + final String lastRow = lastCell[1]; + final String lastCol = lastCell[2]; + final String ref = firstCol+firstRow+':'+lastCol+lastRow; //or just source.formatAsString() + wsSource.setRef(ref); + } + }); + } + + /** + * Create a pivot table using the AreaReference or named/table range on sourceSheet, at the given position. + * If the source reference contains a sheet name, it must match the sourceSheet. + * @param sourceRef location of pivot data - mutually exclusive with SourceName + * @param sourceName range or table name for pivot data - mutually exclusive with SourceRef + * @param position A reference to the top left cell where the pivot table will start + * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name + * @throws IllegalArgumentException if source references a sheet different than sourceSheet + * @return The pivot table + */ + private XSSFPivotTable createPivotTable(CellReference position, Sheet sourceSheet, PivotTableReferenceConfigurator refConfig) { + XSSFPivotTable pivotTable = createPivotTable(); //Creates default settings for the pivot table pivotTable.setDefaultPivotTableDefinition(); //Set sources and references - pivotTable.createSourceReferences(source, position, sourceSheet); + pivotTable.createSourceReferences(position, sourceSheet, refConfig); - //Create cachefield/s and empty SharedItems + //Create cachefield/s and empty SharedItems - must be after creating references pivotTable.getPivotCacheDefinition().createCacheFields(sourceSheet); pivotTable.createDefaultDataColumns(); @@ -4186,9 +4220,10 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { } /** - * Create a pivot table and set area of source and a position for pivot table - * @param source Area from where data will be collected - * @param position A reference to the cell where the table will start + * Create a pivot table using the AreaReference range, at the given position. + * If the source reference contains a sheet name, that sheet is used, otherwise this sheet is assumed as the source sheet. + * @param source location of pivot data + * @param position A reference to the top left cell where the pivot table will start * @return The pivot table */ @Beta @@ -4201,6 +4236,57 @@ public class XSSFSheet extends POIXMLDocumentPart implements Sheet { return createPivotTable(source, position, this); } + /** + * Create a pivot table using the Name range reference on sourceSheet, at the given position. + * If the source reference contains a sheet name, it must match the sourceSheet + * @param source location of pivot data + * @param position A reference to the top left cell where the pivot table will start + * @param sourceSheet The sheet containing the source data, if the source reference doesn't contain a sheet name + * @throws IllegalArgumentException if source references a sheet different than sourceSheet + * @return The pivot table + */ + @Beta + public XSSFPivotTable createPivotTable(final Name source, CellReference position, Sheet sourceSheet) { + if(source.getSheetName() != null && !source.getSheetName().equals(sourceSheet.getSheetName())) { + throw new IllegalArgumentException("The named range references another sheet than the " + + "defined source sheet " + sourceSheet.getSheetName() + "."); + } + + return createPivotTable(position, sourceSheet, new PivotTableReferenceConfigurator() { + public void configureReference(CTWorksheetSource wsSource) { + wsSource.setName(source.getNameName()); + } + }); + } + + /** + * Create a pivot table using the Name range, at the given position. + * If the source reference contains a sheet name, that sheet is used, otherwise this sheet is assumed as the source sheet. + * @param source location of pivot data + * @param position A reference to the top left cell where the pivot table will start + * @return The pivot table + */ + @Beta + public XSSFPivotTable createPivotTable(Name source, CellReference position) { + return createPivotTable(source, position, getWorkbook().getSheet(source.getSheetName())); + } + + /** + * Create a pivot table using the Table, at the given position. + * Tables are required to have a sheet reference, so no additional logic around reference sheet is needed. + * @param source location of pivot data + * @param position A reference to the top left cell where the pivot table will start + * @return The pivot table + */ + @Beta + public XSSFPivotTable createPivotTable(final Table source, CellReference position) { + return createPivotTable(position, getWorkbook().getSheet(source.getSheetName()), new PivotTableReferenceConfigurator() { + public void configureReference(CTWorksheetSource wsSource) { + wsSource.setName(source.getName()); + } + }); + } + /** * Returns all the pivot tables for this Sheet */ diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java index 1e51e5e3f7..b27100656b 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/ColumnHelper.java @@ -319,6 +319,7 @@ public class ColumnHelper { } public int getIndexOfColumn(CTCols cols, CTCol searchCol) { + if (cols == null || searchCol == null) return -1; int i = 0; for (CTCol col : cols.getColArray()) { if (col.getMin() == searchCol.getMin() && col.getMax() == searchCol.getMax()) { diff --git a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java index d11ed1fa81..e55b014a7f 100644 --- a/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java +++ b/src/ooxml/java/org/apache/poi/xssf/usermodel/helpers/XSSFRowShifter.java @@ -147,7 +147,8 @@ public final class XSSFRowShifter extends RowShifter { } - if (f.isSetRef()) { //Range of cells which the formula applies to. + //Range of cells which the formula applies to. + if (f.isSetRef()) { String ref = f.getRef(); String shiftedRef = shiftFormula(row, ref, shifter); if (shiftedRef != null) f.setRef(shiftedRef); diff --git a/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java b/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java index 9d206f7197..26fe68a632 100644 --- a/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java +++ b/src/ooxml/testcases/org/apache/poi/extractor/TestExtractorFactory.java @@ -16,6 +16,7 @@ ==================================================================== */ package org.apache.poi.extractor; +import static org.apache.poi.POITestCase.assertContains; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; @@ -37,6 +38,7 @@ import org.apache.poi.hdgf.extractor.VisioTextExtractor; import org.apache.poi.hpbf.extractor.PublisherTextExtractor; import org.apache.poi.hslf.extractor.PowerPointExtractor; import org.apache.poi.hsmf.extractor.OutlookTextExtactor; +import org.apache.poi.hssf.HSSFTestDataSamples; import org.apache.poi.hssf.OldExcelFormatException; import org.apache.poi.hssf.extractor.EventBasedExcelExtractor; import org.apache.poi.hssf.extractor.ExcelExtractor; @@ -1019,4 +1021,16 @@ public class TestExtractorFactory { // expected here } } + + // This bug is currently open. This test will fail with "expected error not thrown" when the bug has been fixed. + // When this happens, change this from @Test(expected=...) to @Test + // bug 45565: text within TextBoxes is extracted by ExcelExtractor and WordExtractor + @Test(expected=AssertionError.class) + public void test45565() throws Exception { + POITextExtractor extractor = ExtractorFactory.createExtractor(HSSFTestDataSamples.getSampleFile("45565.xls")); + String text = extractor.getText(); + assertContains(text, "testdoc"); + assertContains(text, "test phrase"); + extractor.close(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java index 77c91cdcae..202b9e18e9 100644 --- a/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java +++ b/src/ooxml/testcases/org/apache/poi/poifs/crypt/TestSignatureInfo.java @@ -55,6 +55,7 @@ import org.apache.poi.POIDataSamples; import org.apache.poi.POITestCase; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackageAccess; +import org.apache.poi.openxml4j.opc.PackageRelationshipTypes; import org.apache.poi.poifs.crypt.dsig.DigestInfo; import org.apache.poi.poifs.crypt.dsig.SignatureConfig; import org.apache.poi.poifs.crypt.dsig.SignatureInfo; @@ -99,7 +100,7 @@ public class TestSignatureInfo { public static void initBouncy() throws IOException { CryptoFunctions.registerBouncyCastle(); - /*** TODO : set cal to now ... only set to fixed date for debugging ... */ + // Set cal to now ... only set to fixed date for debugging ... cal = LocaleUtil.getLocaleCalendar(LocaleUtil.TIMEZONE_UTC); assertNotNull(cal); // cal.set(2014, 7, 6, 21, 42, 12); @@ -403,7 +404,9 @@ public class TestSignatureInfo { // verify Iterator spIter = si.getSignatureParts().iterator(); - assertTrue(spIter.hasNext()); + assertTrue("Had: " + si.getSignatureConfig().getOpcPackage(). + getRelationshipsByType(PackageRelationshipTypes.DIGITAL_SIGNATURE_ORIGIN), + spIter.hasNext()); SignaturePart sp = spIter.next(); boolean valid = sp.validate(); assertTrue(valid); diff --git a/src/ooxml/testcases/org/apache/poi/ss/formula/functions/TestProper.java b/src/ooxml/testcases/org/apache/poi/ss/formula/functions/TestProper.java index a24fd88795..921dc445eb 100644 --- a/src/ooxml/testcases/org/apache/poi/ss/formula/functions/TestProper.java +++ b/src/ooxml/testcases/org/apache/poi/ss/formula/functions/TestProper.java @@ -31,7 +31,6 @@ import org.apache.poi.xssf.usermodel.XSSFFormulaEvaluator; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import junit.framework.AssertionFailedError; -import junit.framework.TestCase; import org.junit.Test; import static org.junit.Assert.assertEquals; diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTable.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/BaseTestXSSFPivotTable.java similarity index 74% rename from src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTable.java rename to src/ooxml/testcases/org/apache/poi/xssf/usermodel/BaseTestXSSFPivotTable.java index 851ca33d62..445812566f 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTable.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/BaseTestXSSFPivotTable.java @@ -16,16 +16,13 @@ ==================================================================== */ package org.apache.poi.xssf.usermodel; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; -import static org.junit.Assert.fail; +import static org.junit.Assert.*; import java.io.IOException; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellType; import org.apache.poi.ss.usermodel.DataConsolidateFunction; -import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.XSSFITestDataProvider; @@ -38,97 +35,27 @@ import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotFields; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTPivotTableDefinition; import org.openxmlformats.schemas.spreadsheetml.x2006.main.STDataConsolidateFunction; -public class TestXSSFPivotTable { +public abstract class BaseTestXSSFPivotTable { private static final XSSFITestDataProvider _testDataProvider = XSSFITestDataProvider.instance; - private XSSFWorkbook wb; - private XSSFPivotTable pivotTable; - private XSSFPivotTable offsetPivotTable; - private Cell offsetOuterCell; + protected XSSFWorkbook wb; + protected XSSFPivotTable pivotTable; + protected XSSFPivotTable offsetPivotTable; + protected Cell offsetOuterCell; + /** + * required to set up the test pivot tables and cell reference, either by name or reference. + * @see junit.framework.TestCase#setUp() + */ @Before - public void setUp(){ - wb = new XSSFWorkbook(); - XSSFSheet sheet = wb.createSheet(); - - Row row1 = sheet.createRow(0); - // Create a cell and put a value in it. - Cell cell = row1.createCell(0); - cell.setCellValue("Names"); - Cell cell2 = row1.createCell(1); - cell2.setCellValue("#"); - Cell cell7 = row1.createCell(2); - cell7.setCellValue("Data"); - Cell cell10 = row1.createCell(3); - cell10.setCellValue("Value"); - - Row row2 = sheet.createRow(1); - Cell cell3 = row2.createCell(0); - cell3.setCellValue("Jan"); - Cell cell4 = row2.createCell(1); - cell4.setCellValue(10); - Cell cell8 = row2.createCell(2); - cell8.setCellValue("Apa"); - Cell cell11 = row1.createCell(3); - cell11.setCellValue(11.11); - - Row row3 = sheet.createRow(2); - Cell cell5 = row3.createCell(0); - cell5.setCellValue("Ben"); - Cell cell6 = row3.createCell(1); - cell6.setCellValue(9); - Cell cell9 = row3.createCell(2); - cell9.setCellValue("Bepa"); - Cell cell12 = row1.createCell(3); - cell12.setCellValue(12.12); - - AreaReference source = new AreaReference("A1:C2", _testDataProvider.getSpreadsheetVersion()); - pivotTable = sheet.createPivotTable(source, new CellReference("H5")); - - XSSFSheet offsetSheet = wb.createSheet(); - - Row tableRow_1 = offsetSheet.createRow(1); - offsetOuterCell = tableRow_1.createCell(1); - offsetOuterCell.setCellValue(-1); - Cell tableCell_1_1 = tableRow_1.createCell(2); - tableCell_1_1.setCellValue("Row #"); - Cell tableCell_1_2 = tableRow_1.createCell(3); - tableCell_1_2.setCellValue("Exponent"); - Cell tableCell_1_3 = tableRow_1.createCell(4); - tableCell_1_3.setCellValue("10^Exponent"); - - Row tableRow_2 = offsetSheet.createRow(2); - Cell tableCell_2_1 = tableRow_2.createCell(2); - tableCell_2_1.setCellValue(0); - Cell tableCell_2_2 = tableRow_2.createCell(3); - tableCell_2_2.setCellValue(0); - Cell tableCell_2_3 = tableRow_2.createCell(4); - tableCell_2_3.setCellValue(1); - - Row tableRow_3= offsetSheet.createRow(3); - Cell tableCell_3_1 = tableRow_3.createCell(2); - tableCell_3_1.setCellValue(1); - Cell tableCell_3_2 = tableRow_3.createCell(3); - tableCell_3_2.setCellValue(1); - Cell tableCell_3_3 = tableRow_3.createCell(4); - tableCell_3_3.setCellValue(10); - - Row tableRow_4 = offsetSheet.createRow(4); - Cell tableCell_4_1 = tableRow_4.createCell(2); - tableCell_4_1.setCellValue(2); - Cell tableCell_4_2 = tableRow_4.createCell(3); - tableCell_4_2.setCellValue(2); - Cell tableCell_4_3 = tableRow_4.createCell(4); - tableCell_4_3.setCellValue(100); - - AreaReference offsetSource = new AreaReference(new CellReference("C2"), new CellReference("E4")); - offsetPivotTable = offsetSheet.createPivotTable(offsetSource, new CellReference("C6")); - } + public abstract void setUp(); @After public void tearDown() throws IOException { - XSSFWorkbook wb2 = _testDataProvider.writeOutAndReadBack(wb); - wb.close(); - wb2.close(); + if (wb != null) { + XSSFWorkbook wb2 = _testDataProvider.writeOutAndReadBack(wb); + wb.close(); + wb2.close(); + } } /** @@ -155,6 +82,7 @@ public class TestXSSFPivotTable { assertEquals(0, (int)pivotTable.getRowLabelColumns().get(0)); assertEquals(1, (int)pivotTable.getRowLabelColumns().get(1)); } + /** * Verify that it's not possible to create a row label outside of the referenced area. */ @@ -314,6 +242,7 @@ public class TestXSSFPivotTable { /** * Verify that it's possible to create a new filter */ + @Test public void testAddReportFilter() { int columnIndex = 0; diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java index e695f385f9..7fb1b507d5 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFBugs.java @@ -3091,4 +3091,41 @@ public final class TestXSSFBugs extends BaseTestBugzillaIssues { assertEquals("09 Mar 2016", result); } + + // This bug is currently open. When this bug is fixed, it should not throw an AssertionError + @Test(expected=AssertionError.class) + public void test55076_collapseColumnGroups() throws Exception { + Workbook wb = new XSSFWorkbook(); + Sheet sheet = wb.createSheet(); + + // this column collapsing bug only occurs when the grouped columns are different widths + sheet.setColumnWidth(1, 400); + sheet.setColumnWidth(2, 600); + sheet.setColumnWidth(3, 800); + + assertEquals(400, sheet.getColumnWidth(1)); + assertEquals(600, sheet.getColumnWidth(2)); + assertEquals(800, sheet.getColumnWidth(3)); + + sheet.groupColumn(1, 3); + sheet.setColumnGroupCollapsed(1, true); + + assertEquals(0, sheet.getColumnOutlineLevel(0)); + assertEquals(1, sheet.getColumnOutlineLevel(1)); + assertEquals(1, sheet.getColumnOutlineLevel(2)); + assertEquals(1, sheet.getColumnOutlineLevel(3)); + assertEquals(0, sheet.getColumnOutlineLevel(4)); + + // none of the columns should be hidden + // column group collapsing is a different concept + for (int c=0; c<5; c++) { + assertFalse("Column " + c, sheet.isColumnHidden(c)); + } + + assertEquals(400, sheet.getColumnWidth(1)); + assertEquals(600, sheet.getColumnWidth(2)); + assertEquals(800, sheet.getColumnWidth(3)); + + wb.close(); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java index 84a4aa6800..6dcaef9603 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFFormulaEvaluation.java @@ -682,15 +682,4 @@ public final class TestXSSFFormulaEvaluation extends BaseTestFormulaEvaluator { value = evaluator.evaluate(cell); assertEquals(1, value.getNumberValue(), 0.001); } - - @Test - public void evaluateInCellReturnsSameDataType() throws IOException { - XSSFWorkbook wb = new XSSFWorkbook(); - wb.createSheet().createRow(0).createCell(0); - XSSFFormulaEvaluator evaluator = wb.getCreationHelper().createFormulaEvaluator(); - XSSFCell cell = wb.getSheetAt(0).getRow(0).getCell(0); - XSSFCell same = evaluator.evaluateInCell(cell); - assertSame(cell, same); - wb.close(); - } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableName.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableName.java new file mode 100644 index 0000000000..8df2a663da --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableName.java @@ -0,0 +1,112 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.util.CellReference; +import org.junit.Before; + +/** + * Test pivot tables created by named range + */ +public class TestXSSFPivotTableName extends BaseTestXSSFPivotTable { + + @Override + @Before + public void setUp(){ + wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + + Row row1 = sheet.createRow(0); + // Create a cell and put a value in it. + Cell cell = row1.createCell(0); + cell.setCellValue("Names"); + Cell cell2 = row1.createCell(1); + cell2.setCellValue("#"); + Cell cell7 = row1.createCell(2); + cell7.setCellValue("Data"); + Cell cell10 = row1.createCell(3); + cell10.setCellValue("Value"); + + Row row2 = sheet.createRow(1); + Cell cell3 = row2.createCell(0); + cell3.setCellValue("Jan"); + Cell cell4 = row2.createCell(1); + cell4.setCellValue(10); + Cell cell8 = row2.createCell(2); + cell8.setCellValue("Apa"); + Cell cell11 = row1.createCell(3); + cell11.setCellValue(11.11); + + Row row3 = sheet.createRow(2); + Cell cell5 = row3.createCell(0); + cell5.setCellValue("Ben"); + Cell cell6 = row3.createCell(1); + cell6.setCellValue(9); + Cell cell9 = row3.createCell(2); + cell9.setCellValue("Bepa"); + Cell cell12 = row1.createCell(3); + cell12.setCellValue(12.12); + + XSSFName namedRange = sheet.getWorkbook().createName(); + namedRange.setRefersToFormula(sheet.getSheetName() + "!" + "A1:C2"); + pivotTable = sheet.createPivotTable(namedRange, new CellReference("H5")); + + XSSFSheet offsetSheet = wb.createSheet(); + + Row tableRow_1 = offsetSheet.createRow(1); + offsetOuterCell = tableRow_1.createCell(1); + offsetOuterCell.setCellValue(-1); + Cell tableCell_1_1 = tableRow_1.createCell(2); + tableCell_1_1.setCellValue("Row #"); + Cell tableCell_1_2 = tableRow_1.createCell(3); + tableCell_1_2.setCellValue("Exponent"); + Cell tableCell_1_3 = tableRow_1.createCell(4); + tableCell_1_3.setCellValue("10^Exponent"); + + Row tableRow_2 = offsetSheet.createRow(2); + Cell tableCell_2_1 = tableRow_2.createCell(2); + tableCell_2_1.setCellValue(0); + Cell tableCell_2_2 = tableRow_2.createCell(3); + tableCell_2_2.setCellValue(0); + Cell tableCell_2_3 = tableRow_2.createCell(4); + tableCell_2_3.setCellValue(1); + + Row tableRow_3= offsetSheet.createRow(3); + Cell tableCell_3_1 = tableRow_3.createCell(2); + tableCell_3_1.setCellValue(1); + Cell tableCell_3_2 = tableRow_3.createCell(3); + tableCell_3_2.setCellValue(1); + Cell tableCell_3_3 = tableRow_3.createCell(4); + tableCell_3_3.setCellValue(10); + + Row tableRow_4 = offsetSheet.createRow(4); + Cell tableCell_4_1 = tableRow_4.createCell(2); + tableCell_4_1.setCellValue(2); + Cell tableCell_4_2 = tableRow_4.createCell(3); + tableCell_4_2.setCellValue(2); + Cell tableCell_4_3 = tableRow_4.createCell(4); + tableCell_4_3.setCellValue(100); + + namedRange = sheet.getWorkbook().createName(); + namedRange.setRefersToFormula("C2:E4"); + namedRange.setSheetIndex(sheet.getWorkbook().getSheetIndex(sheet)); + offsetPivotTable = offsetSheet.createPivotTable(namedRange, new CellReference("C6")); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableRef.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableRef.java new file mode 100644 index 0000000000..ec0c5c6c1a --- /dev/null +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFPivotTableRef.java @@ -0,0 +1,111 @@ +/* ==================================================================== + Licensed to the Apache Software Foundation (ASF) under one or more + contributor license agreements. See the NOTICE file distributed with + this work for additional information regarding copyright ownership. + The ASF licenses this file to You under the Apache License, Version 2.0 + (the "License"); you may not use this file except in compliance with + the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, software + distributed under the License is distributed on an "AS IS" BASIS, + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + See the License for the specific language governing permissions and + limitations under the License. +==================================================================== */ + +package org.apache.poi.xssf.usermodel; + +import org.apache.poi.ss.SpreadsheetVersion; +import org.apache.poi.ss.usermodel.Cell; +import org.apache.poi.ss.usermodel.Row; +import org.apache.poi.ss.util.AreaReference; +import org.apache.poi.ss.util.CellReference; +import org.junit.Before; + +/** + * Test pivot tables created by area reference + */ +public class TestXSSFPivotTableRef extends BaseTestXSSFPivotTable { + + @Override + @Before + public void setUp(){ + wb = new XSSFWorkbook(); + XSSFSheet sheet = wb.createSheet(); + + Row row1 = sheet.createRow(0); + // Create a cell and put a value in it. + Cell cell = row1.createCell(0); + cell.setCellValue("Names"); + Cell cell2 = row1.createCell(1); + cell2.setCellValue("#"); + Cell cell7 = row1.createCell(2); + cell7.setCellValue("Data"); + Cell cell10 = row1.createCell(3); + cell10.setCellValue("Value"); + + Row row2 = sheet.createRow(1); + Cell cell3 = row2.createCell(0); + cell3.setCellValue("Jan"); + Cell cell4 = row2.createCell(1); + cell4.setCellValue(10); + Cell cell8 = row2.createCell(2); + cell8.setCellValue("Apa"); + Cell cell11 = row1.createCell(3); + cell11.setCellValue(11.11); + + Row row3 = sheet.createRow(2); + Cell cell5 = row3.createCell(0); + cell5.setCellValue("Ben"); + Cell cell6 = row3.createCell(1); + cell6.setCellValue(9); + Cell cell9 = row3.createCell(2); + cell9.setCellValue("Bepa"); + Cell cell12 = row1.createCell(3); + cell12.setCellValue(12.12); + + AreaReference source = new AreaReference("A1:C2", SpreadsheetVersion.EXCEL2007); + pivotTable = sheet.createPivotTable(source, new CellReference("H5")); + + XSSFSheet offsetSheet = wb.createSheet(); + + Row tableRow_1 = offsetSheet.createRow(1); + offsetOuterCell = tableRow_1.createCell(1); + offsetOuterCell.setCellValue(-1); + Cell tableCell_1_1 = tableRow_1.createCell(2); + tableCell_1_1.setCellValue("Row #"); + Cell tableCell_1_2 = tableRow_1.createCell(3); + tableCell_1_2.setCellValue("Exponent"); + Cell tableCell_1_3 = tableRow_1.createCell(4); + tableCell_1_3.setCellValue("10^Exponent"); + + Row tableRow_2 = offsetSheet.createRow(2); + Cell tableCell_2_1 = tableRow_2.createCell(2); + tableCell_2_1.setCellValue(0); + Cell tableCell_2_2 = tableRow_2.createCell(3); + tableCell_2_2.setCellValue(0); + Cell tableCell_2_3 = tableRow_2.createCell(4); + tableCell_2_3.setCellValue(1); + + Row tableRow_3= offsetSheet.createRow(3); + Cell tableCell_3_1 = tableRow_3.createCell(2); + tableCell_3_1.setCellValue(1); + Cell tableCell_3_2 = tableRow_3.createCell(3); + tableCell_3_2.setCellValue(1); + Cell tableCell_3_3 = tableRow_3.createCell(4); + tableCell_3_3.setCellValue(10); + + Row tableRow_4 = offsetSheet.createRow(4); + Cell tableCell_4_1 = tableRow_4.createCell(2); + tableCell_4_1.setCellValue(2); + Cell tableCell_4_2 = tableRow_4.createCell(3); + tableCell_4_2.setCellValue(2); + Cell tableCell_4_3 = tableRow_4.createCell(4); + tableCell_4_3.setCellValue(100); + + AreaReference offsetSource = new AreaReference(new CellReference("C2"), new CellReference("E4")); + offsetPivotTable = offsetSheet.createPivotTable(offsetSource, new CellReference("C6")); + } +} diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java index 3f7be066d1..24c1d72375 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheet.java @@ -1581,7 +1581,7 @@ public final class TestXSSFSheet extends BaseTestXSheet { System.out.println("Array formulas currently unsupported"); // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() /* - assertEquals("[Array Formula] N7 cell type", CellType.FORMULA, cell.getCellType()); + assertEquals("[Array Formula] N7 cell type", CellType.FORMULA, cell.getCellTypeEnum()); assertEquals("[Array Formula] N7 cell formula", "{SUM(H7:J7*{1,2,3})}", cell.getCellFormula()); */ @@ -1792,12 +1792,12 @@ public final class TestXSSFSheet extends BaseTestXSheet { // System.out.println("Array formulas currently unsupported"); /* // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() - assertEquals("[Array Formula] N10 cell type", CellType.FORMULA, cell.getCellType()); + assertEquals("[Array Formula] N10 cell type", CellType.FORMULA, cell.getCellTypeEnum()); assertEquals("[Array Formula] N10 cell formula", "{SUM(H10:J10*{1,2,3})}", cell.getCellFormula()); cell = CellUtil.getCell(destRow2, col); // FIXME: Array Formula set with Sheet.setArrayFormula() instead of cell.setFormula() - assertEquals("[Array Formula] N11 cell type", CellType.FORMULA, cell.getCellType()); + assertEquals("[Array Formula] N11 cell type", CellType.FORMULA, cell.getCellTypeEnum()); assertEquals("[Array Formula] N11 cell formula", "{SUM(H11:J11*{1,2,3})}", cell.getCellFormula()); */ @@ -2020,4 +2020,21 @@ public final class TestXSSFSheet extends BaseTestXSheet { } } + + // bug 59687: XSSFSheet.RemoveRow doesn't handle row gaps properly when removing row comments + @Test + public void testRemoveRowWithCommentAndGapAbove() throws IOException { + final Workbook wb = _testDataProvider.openSampleWorkbook("59687.xlsx"); + final Sheet sheet = wb.getSheetAt(0); + + // comment exists + CellAddress commentCellAddress = new CellAddress("A4"); + assertNotNull(sheet.getCellComment(commentCellAddress)); + + assertEquals("Wrong starting # of comments", 1, sheet.getCellComments().size()); + + sheet.removeRow(sheet.getRow(commentCellAddress.getRow())); + + assertEquals("There should not be any comments left!", 0, sheet.getCellComments().size()); + } } diff --git a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java index 3e2cd54030..fa4c77fbf8 100644 --- a/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java +++ b/src/ooxml/testcases/org/apache/poi/xssf/usermodel/TestXSSFSheetShiftRows.java @@ -17,6 +17,8 @@ package org.apache.poi.xssf.usermodel; +import static org.apache.poi.POITestCase.skipTest; +import static org.apache.poi.POITestCase.testPassesNow; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; @@ -35,7 +37,7 @@ import org.apache.poi.ss.util.CellAddress; import org.apache.poi.ss.util.CellUtil; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; -import org.junit.Ignore; +import org.apache.xmlbeans.impl.values.XmlValueDisconnectedException; import org.junit.Test; public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows { @@ -377,7 +379,9 @@ public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows { wb.close(); } - @Ignore("Bug 59733 - shiftRows() causes org.apache.xmlbeans.impl.values.XmlValueDisconnectedException") + // This test is written as expected-to-fail and should be rewritten + // as expected-to-pass when the bug is fixed. + //@Ignore("Bug 59733 - shiftRows() causes org.apache.xmlbeans.impl.values.XmlValueDisconnectedException") @Test public void bug59733() throws IOException { Workbook workbook = new XSSFWorkbook(); @@ -399,9 +403,50 @@ public final class TestXSSFSheetShiftRows extends BaseTestSheetShiftRows { at org.apache.poi.xssf.usermodel.XSSFRow.getRowNum(XSSFRow.java:363) at org.apache.poi.xssf.usermodel.TestXSSFSheetShiftRows.bug59733(TestXSSFSheetShiftRows.java:393) */ - sheet.removeRow(sheet.getRow(0)); - assertEquals(1, sheet.getRow(1).getRowNum()); + // FIXME: remove try, catch, and testPassesNow, skipTest when test passes + try { + sheet.removeRow(sheet.getRow(0)); + assertEquals(1, sheet.getRow(1).getRowNum()); + testPassesNow(59733); + } catch (XmlValueDisconnectedException e) { + skipTest(e); + } + workbook.close(); + } + + private static String getCellFormula(Sheet sheet, String address) { + CellAddress cellAddress = new CellAddress(address); + Row row = sheet.getRow(cellAddress.getRow()); + assertNotNull(row); + Cell cell = row.getCell(cellAddress.getColumn()); + assertNotNull(cell); + assertEquals(CellType.FORMULA, cell.getCellTypeEnum()); + return cell.getCellFormula(); + } + + // This test is written as expected-to-fail and should be rewritten + // as expected-to-pass when the bug is fixed. + @Test + public void testSharedFormulas() throws Exception { + XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("TestShiftRowSharedFormula.xlsx"); + XSSFSheet sheet = wb.getSheetAt(0); + assertEquals("SUM(C2:C4)", getCellFormula(sheet, "C5")); + assertEquals("SUM(D2:D4)", getCellFormula(sheet, "D5")); + assertEquals("SUM(E2:E4)", getCellFormula(sheet, "E5")); + + sheet.shiftRows(3, sheet.getLastRowNum(), 1); + // FIXME: remove try, catch, and testPassesNow, skipTest when test passes + try { + assertEquals("SUM(C2:C5)", getCellFormula(sheet, "C6")); + assertEquals("SUM(D2:D5)", getCellFormula(sheet, "D6")); + assertEquals("SUM(E2:E5)", getCellFormula(sheet, "E6")); + testPassesNow(59983); + } catch (AssertionError e) { + skipTest(e); + } + + wb.close(); } } diff --git a/src/scratchpad/src/org/apache/poi/hmef/Attachment.java b/src/scratchpad/src/org/apache/poi/hmef/Attachment.java index 89b063c263..59c90a4dc0 100644 --- a/src/scratchpad/src/org/apache/poi/hmef/Attachment.java +++ b/src/scratchpad/src/org/apache/poi/hmef/Attachment.java @@ -137,6 +137,8 @@ public final class Attachment { /** * Returns the contents of the attachment. + * + * @throws IllegalArgumentException if there is no AttachmentData available in this Attachment */ public byte[] getContents() { TNEFAttribute contents = getAttribute(TNEFProperty.ID_ATTACHDATA); diff --git a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoUtils.java b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoUtils.java index e901de8216..32cf161a5c 100644 --- a/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoUtils.java +++ b/src/scratchpad/src/org/apache/poi/hwpf/converter/WordToFoUtils.java @@ -154,37 +154,37 @@ public class WordToFoUtils extends AbstractWordUtils { block.setAttribute( "text-indent", - String.valueOf( paragraph.getFirstLineIndent() - / TWIPS_PER_PT ) + paragraph.getFirstLineIndent() + / TWIPS_PER_PT + "pt" ); } if ( paragraph.getIndentFromLeft() != 0 ) { block.setAttribute( "start-indent", - String.valueOf( paragraph.getIndentFromLeft() - / TWIPS_PER_PT ) + paragraph.getIndentFromLeft() + / TWIPS_PER_PT + "pt" ); } if ( paragraph.getIndentFromRight() != 0 ) { block.setAttribute( "end-indent", - String.valueOf( paragraph.getIndentFromRight() - / TWIPS_PER_PT ) + paragraph.getIndentFromRight() + / TWIPS_PER_PT + "pt" ); } if ( paragraph.getSpacingBefore() != 0 ) { block.setAttribute( "space-before", - String.valueOf( paragraph.getSpacingBefore() / TWIPS_PER_PT ) + paragraph.getSpacingBefore() / TWIPS_PER_PT + "pt" ); } if ( paragraph.getSpacingAfter() != 0 ) { block.setAttribute( "space-after", - String.valueOf( paragraph.getSpacingAfter() / TWIPS_PER_PT ) + paragraph.getSpacingAfter() / TWIPS_PER_PT + "pt" ); } } diff --git a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java index 6a69aab8a3..b4591ad455 100644 --- a/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java +++ b/src/scratchpad/testcases/org/apache/poi/hwpf/usermodel/TestBugs.java @@ -32,11 +32,13 @@ import org.apache.poi.hwpf.model.PlexOfField; import org.apache.poi.hwpf.model.SubdocumentType; import org.apache.poi.hwpf.model.io.HWPFOutputStream; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; +import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.util.IOUtils; import org.apache.poi.util.POILogFactory; import org.apache.poi.util.POILogger; import java.io.ByteArrayOutputStream; +import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.io.InputStream; @@ -901,4 +903,19 @@ public class TestBugs extends TestCase HWPFDocument hwpfDocument2 = HWPFTestDataSamples.writeOutAndReadBack(hwpfDocument); assertNotNull(hwpfDocument2); } + + public void test57843() throws IOException { + try { + File f = POIDataSamples.getDocumentInstance().getFile("57843.doc"); + boolean readOnly = true; + POIFSFileSystem fs = new POIFSFileSystem(f, readOnly); + HWPFOldDocument doc = new HWPFOldDocument(fs); + assertNotNull(doc); + doc.close(); + fs.close(); + fixed("57843"); + } catch (ArrayIndexOutOfBoundsException e) { + // expected until this bug is fixed + } + } } diff --git a/src/testcases/org/apache/poi/POITestCase.java b/src/testcases/org/apache/poi/POITestCase.java index 786c6e1124..a8cc8e1db6 100644 --- a/src/testcases/org/apache/poi/POITestCase.java +++ b/src/testcases/org/apache/poi/POITestCase.java @@ -23,6 +23,7 @@ import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; +import static org.junit.Assume.assumeTrue; import java.lang.reflect.AccessibleObject; import java.lang.reflect.Field; @@ -174,4 +175,62 @@ public final class POITestCase { } } } + + /** + * Rather than adding {@literal @}Ignore to known-failing tests, + * write the test so that it notifies us if it starts passing. + * This is useful for closing related or forgotten bugs. + * + * An Example: + *
+     * public static int add(int a, int b) {
+     *     // a known bug in behavior that has not been fixed yet
+     *     raise UnsupportedOperationException("add");
+     * }
+     * 
+     * {@literal @}Test
+     * public void knownFailingUnitTest() {
+     *     try {
+     *         assertEquals(2, add(1,1));
+     *         // this test fails because the assumption that this bug had not been fixed is false
+     *         testPassesNow(12345);
+     *     } catch (UnsupportedOperationException e) {
+     *         // test is skipped because the assumption that this bug had not been fixed is true
+     *         skipTest(e);
+     *     }
+     * }
+     * 
+     * Once passing, this unit test can be rewritten as:
+     * {@literal @}Test
+     * public void knownPassingUnitTest() {
+     *     assertEquals(2, add(1,1));
+     * }
+     * 
+     * If you have a better idea how to simplify test code while still notifying
+     * us when a previous known-failing test now passes, please improve these.
+     * As a bonus, a known-failing test that fails should not be counted as a
+     * passing test.
+     * 
+     * One possible alternative is to expect the known exception, but without
+     * a clear message that it is a good thing to no longer get the expected
+     * exception once the test passes.
+     * {@literal @}Test(expected=UnsupportedOperationException.class)
+     * public void knownFailingUnitTest() {
+     *     assertEquals(2, add(1,1));
+     * }
+     *
+     * @param e  the exception that was caught that will no longer
+     * be raised when the bug is fixed 
+     */
+    public static void skipTest(Throwable e) {
+        assumeTrue("This test currently fails with " + e, false);
+    }
+    /**
+     * @see #skipTest(Throwable)
+     *
+     * @param bug  the bug number corresponding to a known bug in bugzilla
+     */
+    public static void testPassesNow(int bug) {
+        fail("This test passes now. Please update the unit test and bug " + bug + ".");
+    }
 }
diff --git a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
index 2ce6e1de8a..65042127e8 100644
--- a/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
+++ b/src/testcases/org/apache/poi/hssf/usermodel/TestBugs.java
@@ -1885,12 +1885,12 @@ public final class TestBugs extends BaseTestBugzillaIssues {
 
        // TODO - Fix these so they work...
        /*row = s.getRow(4);
-       assertEquals(CellType.FORMULA, row.getCell(1).getCellType());
+       assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
        assertEquals("'[$http://gagravarr.org/FormulaRefs2.xls]Sheet1'!B2", row.getCell(1).getCellFormula());
        assertEquals(123.0, row.getCell(1).getNumericCellValue(), 0);
 
        row = s.getRow(5);
-       assertEquals(CellType.FORMULA, row.getCell(1).getCellType());
+       assertEquals(CellType.FORMULA, row.getCell(1).getCellTypeEnum());
        assertEquals("'[$http://example.com/FormulaRefs.xls]Sheet1'!B1", row.getCell(1).getCellFormula());
        assertEquals(234.0, row.getCell(1).getNumericCellValue(), 0);*/
        
diff --git a/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java b/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java
index fef200fdcb..0ca0304381 100644
--- a/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java
+++ b/src/testcases/org/apache/poi/poifs/filesystem/TestPOIFSDocumentPath.java
@@ -227,7 +227,7 @@ public final class TestPOIFSDocumentPath extends TestCase {
         {
             for (int k = 0; k < paths.length; k++)
             {
-                assertEquals(String.valueOf(j) + "<>" + String.valueOf(k),
+                assertEquals(j + "<>" + k,
                              paths[ j ], paths[ k ]);
             }
         }
@@ -274,13 +274,13 @@ public final class TestPOIFSDocumentPath extends TestCase {
             {
                 if (k == j)
                 {
-                    assertEquals(String.valueOf(j) + "<>"
-                                 + String.valueOf(k), fullPaths[ j ],
+                    assertEquals(j + "<>"
+                                 + k, fullPaths[ j ],
                                                       builtUpPaths[ k ]);
                 }
                 else
                 {
-                    assertTrue(String.valueOf(j) + "<>" + String.valueOf(k),
+                    assertTrue(j + "<>" + k,
                                !(fullPaths[ j ].equals(builtUpPaths[ k ])));
                 }
             }
@@ -306,7 +306,7 @@ public final class TestPOIFSDocumentPath extends TestCase {
         {
             for (int j = 0; j < badPaths.length; j++)
             {
-                assertTrue(String.valueOf(j) + "<>" + String.valueOf(k),
+                assertTrue(j + "<>" + k,
                            !(fullPaths[ k ].equals(badPaths[ j ])));
             }
         }
diff --git a/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java b/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java
index 2d98a4f38d..614b4effaf 100644
--- a/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java
+++ b/src/testcases/org/apache/poi/poifs/macros/TestVBAMacroReader.java
@@ -18,10 +18,10 @@
 package org.apache.poi.poifs.macros;
 
 import static org.apache.poi.POITestCase.assertContains;
+import static org.apache.poi.POITestCase.skipTest;
+import static org.apache.poi.POITestCase.testPassesNow;
 import static org.junit.Assert.assertFalse;
 import static org.junit.Assert.assertNotNull;
-import static org.junit.Assert.fail;
-import static org.junit.Assume.assumeTrue;
 
 import java.io.File;
 import java.io.FileInputStream;
@@ -268,16 +268,28 @@ public class TestVBAMacroReader {
     public void bug59858() throws IOException {
         try {
             fromFile(POIDataSamples.getSpreadSheetInstance(), "59858.xls");
-            fail("This test passes now. Please update the unit test and bug 59858.");
+            testPassesNow(59858);
         } catch (IOException e) {
             if (e.getMessage().matches("Module offset for '.+' was never read.")) {
                 //e.printStackTrace();
                 // NPE when reading module.offset in VBAMacroReader.readMacros (approx line 258)
-                assumeTrue("This test currently fails. See stdout.", false);
+                skipTest(e);
             } else {
                 // something unexpected failed
                 throw e;
             }
         }
     }
+    
+    // This test is written as expected-to-fail and should be rewritten
+    // as expected-to-pass when the bug is fixed.
+    @Test
+    public void bug60158() throws IOException {
+        try {
+            fromFile(POIDataSamples.getDocumentInstance(), "60158.docm");
+            testPassesNow(60158);
+        } catch (ArrayIndexOutOfBoundsException e) {
+            skipTest(e);
+        }
+    }
 }
diff --git a/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java b/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java
index ebf6951f01..3a0a5b9b76 100644
--- a/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java
+++ b/src/testcases/org/apache/poi/ss/formula/atp/TestIfError.java
@@ -84,7 +84,7 @@ public class TestIfError extends TestCase {
         
         
         assertEquals("Checks that the cell is numeric",
-        		CellType.STRING, evaluator.evaluate(cell2).getCellTypeEnum());        
+        		CellType.STRING, evaluator.evaluate(cell2).getCellTypeEnum());
         assertEquals("Rounds -10 to a nearest multiple of -3 (-9)",
                 "Error in calculation", evaluator.evaluate(cell2).getStringValue());
         
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java
index f9725ba8ae..7e41827a75 100644
--- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java
+++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestBugzillaIssues.java
@@ -33,12 +33,9 @@ import java.awt.font.FontRenderContext;
 import java.awt.font.TextAttribute;
 import java.awt.font.TextLayout;
 import java.awt.geom.Rectangle2D;
-import java.io.FileInputStream;
 import java.io.IOException;
 import java.text.AttributedString;
-import java.util.ArrayList;
 import java.util.HashMap;
-import java.util.List;
 import java.util.Map;
 
 import static org.junit.Assert.*;
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java
index efae0d80c6..556e89b43a 100644
--- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java
+++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetShiftRows.java
@@ -17,6 +17,8 @@
 
 package org.apache.poi.ss.usermodel;
 
+import static org.apache.poi.POITestCase.skipTest;
+import static org.apache.poi.POITestCase.testPassesNow;
 import static org.junit.Assert.assertEquals;
 import static org.junit.Assert.assertNotNull;
 import static org.junit.Assert.assertNull;
@@ -295,7 +297,7 @@ public abstract class BaseTestSheetShiftRows {
         wb.close();
     }
 
-    @Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
+    //@Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
     @Test
     public final void shiftWithMergedRegions_bug56454() throws IOException {
         Workbook wb = _testDataProvider.createWorkbook();
@@ -328,7 +330,15 @@ public abstract class BaseTestSheetShiftRows {
         expectedMergedRegions.add(A4_B8);
         expectedMergedRegions.add(C4_D8);
         
-        assertEquals(expectedMergedRegions, sheet.getMergedRegions());
+        // This test is written as expected-to-fail and should be rewritten
+        // as expected-to-pass when the bug is fixed.
+        // FIXME: remove try, catch, and testPassesNow, skipTest when test passes
+        try {
+            assertEquals(expectedMergedRegions, sheet.getMergedRegions());
+            testPassesNow(56454);
+        } catch (AssertionError e) {
+            skipTest(e);
+        }
         wb.close();
     }
     
@@ -589,7 +599,7 @@ public abstract class BaseTestSheetShiftRows {
         read.close();
     }
     
-    @Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
+    //@Ignore("bug 56454: Incorrectly handles merged regions that do not contain column 0")
     @Test
     public void shiftRowsWithMergedRegionsThatDoNotContainColumnZero() throws IOException {
         Workbook wb = _testDataProvider.createWorkbook();
@@ -614,9 +624,17 @@ public abstract class BaseTestSheetShiftRows {
         // C5:D7 will be shifted down with same size
         sheet.shiftRows(4, sheet.getLastRowNum(), 1);
 
-        assertEquals(2, sheet.getNumMergedRegions());
-        assertEquals(CellRangeAddress.valueOf("A4:B8"), sheet.getMergedRegion(0));
-        assertEquals(CellRangeAddress.valueOf("C5:D8"), sheet.getMergedRegion(1));
+        // This test is written as expected-to-fail and should be rewritten
+        // as expected-to-pass when the bug is fixed.
+        // FIXME: remove try, catch, and testPassesNow, skipTest when test passes
+        try {
+            assertEquals(2, sheet.getNumMergedRegions());
+            assertEquals(CellRangeAddress.valueOf("A4:B8"), sheet.getMergedRegion(0));
+            assertEquals(CellRangeAddress.valueOf("C5:D8"), sheet.getMergedRegion(1));
+            testPassesNow(56454);
+        } catch (AssertionError e) {
+            skipTest(e);
+        }
         
         wb.close();
     }
diff --git a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java
index 5e2ad4a8df..bbd95cccdc 100644
--- a/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java
+++ b/src/testcases/org/apache/poi/ss/usermodel/BaseTestSheetUpdateArrayFormulas.java
@@ -570,7 +570,7 @@ public abstract class BaseTestSheetUpdateArrayFormulas {
             assertEquals(cra.formatAsString(), mcell.getArrayFormulaRange().formatAsString());
             assertEquals("A2:A4*B2:B4", mcell.getCellFormula());
             assertTrue(mcell.isPartOfArrayFormulaGroup());
-            assertEquals(CellType.FORMULA, mcell.getCellType());
+            assertEquals(CellType.FORMULA, mcell.getCellTypeEnum());
         }
 
         */
diff --git a/src/testcases/org/apache/poi/util/DummyPOILogger.java b/src/testcases/org/apache/poi/util/DummyPOILogger.java
index c8566fe663..7da48ce269 100644
--- a/src/testcases/org/apache/poi/util/DummyPOILogger.java
+++ b/src/testcases/org/apache/poi/util/DummyPOILogger.java
@@ -23,6 +23,7 @@ import java.util.List;
  * POILogger which logs into an ArrayList, so that 
  *  tests can see what got logged
  */
+@Internal
 public class DummyPOILogger extends POILogger {
 	public Listlogged = new ArrayList(); 
 
@@ -39,12 +40,12 @@ public class DummyPOILogger extends POILogger {
 	public void initialize(String cat) {}
 
     @Override
-	public void log(int level, Object obj1) {
+	protected void _log(int level, Object obj1) {
 		logged.add(level + " - " + obj1);
 	}
 
     @Override
-	public void log(int level, Object obj1, Throwable exception) {
+	protected void _log(int level, Object obj1, Throwable exception) {
 		logged.add(level + " - " + obj1 + " - " + exception);
 	}
 }
diff --git a/src/testcases/org/apache/poi/util/TestPOILogger.java b/src/testcases/org/apache/poi/util/TestPOILogger.java
index 3914b76436..6650ed9e66 100644
--- a/src/testcases/org/apache/poi/util/TestPOILogger.java
+++ b/src/testcases/org/apache/poi/util/TestPOILogger.java
@@ -65,13 +65,13 @@ public final class TestPOILogger extends POILogger {
     }
 
     @Override
-    public void log(int level, Object obj1) {
+    protected void _log(int level, Object obj1) {
         lastLog = (obj1 == null) ? "" : obj1.toString();
         lastEx = null;
     }
 
     @Override
-    public void log(int level, Object obj1, Throwable exception) {
+    protected void _log(int level, Object obj1, Throwable exception) {
         lastLog = (obj1 == null) ? "" : obj1.toString();
         lastEx = exception;
     }
diff --git a/test-data/diagram/44501a.vsd b/test-data/diagram/44501a.vsd
old mode 100755
new mode 100644
diff --git a/test-data/diagram/44501b.vsd b/test-data/diagram/44501b.vsd
old mode 100755
new mode 100644
diff --git a/test-data/diagram/44501d.vsd b/test-data/diagram/44501d.vsd
old mode 100755
new mode 100644
diff --git a/test-data/document/57843.doc b/test-data/document/57843.doc
new file mode 100644
index 0000000000000000000000000000000000000000..57be6c6ed1ce6efb034dad41b5ad3638f5269d36
GIT binary patch
literal 8192
zcmeHM-)|g89UuQnW7=(#6igKHFlr@8(Dkrm;wB(bJ2nn!$ie*l6aUO@sPf%wsw&v$m$zPlX8srrxzul4op
z&X4cU&-XiXyLW$m{G+#je(LvZ==uhmVE1>X*^$2fG29dR>lnj~;`#p0&Q96OaC>+?
zMjrSWx{f1w6vK)r=1+i*f~G;A0X+$N3KW2z2GQKZ>+$!%HKy_B7-!#P8Ct`7i0;9!
z88)?>^HdM^z04n9|3Q3bY!Z{+DkqMyWynuin_XoM_Qt-;M-84}<753%7&T{9U!&~2
z4(WzPYz1w|a%dvGA4aVi)px3tPd1Srqvj0vO`+rDvqf)VwS;WP)}e!D$?)`jpJ&+E
z7}aFT;r}Lo@#Q~wzgKNP!zs4mtxlQnvA+!Ko8BkX%tpEG>iy?NO
z=<#9Ye}?mnK^$hSlgg}bTJ$V8Qs^b@%lo+=kWg{?1A6BBiRdgrfK`a&ewNgGrx}m
z-{;GHs&9ndr$gcYx=yfSH!s^a(9*SE`&o>Cr<`|?md>T$#e8aSmg}gU!}AB_^FdoI
z8MqF*Zq&R@aH{+^JYET@#;cZ2+(+^2YU}~cs})r{%yIa6*u&L$wZ3Yr{>P=Q^!{|)
zZwaH5h`*xSiS7n-bF=68s;l$mM3^nfFD9L+&Yz!Km^~L<5-O9nqmo3{`05ote|BMZ
zAvisM?(7*pKR^G%g%>Z(2Jx0>wAheIVs-A~dL~`4B14%rq~UWf*7(`k+1VgiGj;y5
zZ19V@jcfdp?nskq!*!FpSn>@goTP`m=}U=y9oqOF`xf=!VmA{N%lN|E^s7Xk)J+I)PEUqr+F&toUbZl9p)zBkx1SU;a1D&Jd0{UaG7_7#n@{Ka@MgF
zd^1eOjv}%azakpi2nREzBO7ZZDXX5v!
zb)!RRt%hg$s!kA31^zA;u7*X05*sp8VELdf%Q|i64hAp7a-BezZmg|@ttu6!hgL^<
z=scUR&du>i8F*1+1o|rLL>7`Gu1nq}B`Jta@07L#BG93sw)0GiQDRatB^|kKYaosm
zIz*@)>rC=2C)m^h7w`ERUlAP@@zZc8#FHCaMnri9mZfi>sc{8oXIy42z!mm%m5VuG
z08KY#7-u@sEpm0DLoAEP<=0e4NhA103C9E51?Eb3L!SsSYh{)j-Ox^jKtuyRp==$c##!9C4SX3+{%;Dnhimyn*zxsv~WElrE$)Jlau~U1QYk{B?Gs)O(@)fzL$Wo6EaDh!#d~O24krWhyH*p8T>&rLcF21IbT18#3(31oJoaGunv7MU`^?-Dx
zHATq7+&Y~iUz-jdkYwLi;Hntj@XzEonCfjR3j#?Cf+e2jurbwG6q0P&Y*N91Mo5g@
z7lN+NQ8XJK*2Kh%^(YpJks|6L;z$Z&PM##JCA{T}9Gx6tP7~FDRoICDid1C1ig`N`$VRV}#{uH7Tas%9G>ilQ$uv!|
zw4sqQvtK6_pkt~tY$PbCr+slC)%)k|VI)!(h?LP8axemJBt)Z%_bUTu0@b@L5fs{E
zP!IwCswN~=z$FC``-$_<+k=*pPuS
z!c1+z0L!Hd>!l|Mq%g2cB~~@5X1SL3d%aj06^iHP#fCP
z_86dk7=%Z3MbF2mtQLabs+?)D1)*x``nFGG%FU7s0%mWkQ44Vj_1)T)p{mv8g5s%{kWe{QDDu^)91rY{rgMI<}5cDh1Z$ZBU
z31mtG^e$dz-v+&hk4Eo0lkS2NCtEhnA!&Y81xg+PeH!~
zeE=f7{hPip{+XKBzqEhz&tl5R=5M3M?y+&=d9N7z6Pp}(nizQMpEbVC)kdK5%^Kkj`14|?+6Dk
zdUJ#~j)-&l#t|yf697}*9mU(5&&_-vs%>KLxBOKc3$AG#IM`F@9cLT8w4oFBCts<7^U4-#W<{EM+nJ2d@V@Fg!`}4ll<30}-)x{r~^~

literal 0
HcmV?d00001

diff --git a/test-data/document/60158.docm b/test-data/document/60158.docm
new file mode 100644
index 0000000000000000000000000000000000000000..2b7908fe3ced68a794f1dfda7153604d453296c0
GIT binary patch
literal 15617
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
bZ_|jJBt1dHSj(|3Bm8^HX0UO&C~4yGxx;eUic
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

literal 0
HcmV?d00001

diff --git a/test-data/spreadsheet/TestShiftRowSharedFormula.xlsx b/test-data/spreadsheet/TestShiftRowSharedFormula.xlsx
new file mode 100644
index 0000000000000000000000000000000000000000..d8ac0c6e2e650e7cbe896cb589a16f7d11507c59
GIT binary patch
literal 8431
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