/* ==================================================================== 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 static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.util.List; import org.apache.poi.EncryptedDocumentException; import org.apache.poi.POIDataSamples; import org.apache.poi.POIXMLDocumentPart; import org.apache.poi.hssf.usermodel.HSSFWorkbook; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.openxml4j.opc.PackagePart; import org.apache.poi.openxml4j.opc.PackagingURIHelper; import org.apache.poi.poifs.filesystem.NPOIFSFileSystem; import org.apache.poi.poifs.filesystem.POIFSFileSystem; import org.apache.poi.ss.formula.WorkbookEvaluator; import org.apache.poi.ss.formula.eval.ErrorEval; import org.apache.poi.ss.formula.eval.ValueEval; import org.apache.poi.ss.formula.functions.Function; import org.apache.poi.ss.usermodel.BaseTestBugzillaIssues; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.CellStyle; import org.apache.poi.ss.usermodel.CellValue; import org.apache.poi.ss.usermodel.ClientAnchor; import org.apache.poi.ss.usermodel.Comment; import org.apache.poi.ss.usermodel.CreationHelper; import org.apache.poi.ss.usermodel.DataFormatter; import org.apache.poi.ss.usermodel.Drawing; import org.apache.poi.ss.usermodel.Font; import org.apache.poi.ss.usermodel.FormulaError; import org.apache.poi.ss.usermodel.FormulaEvaluator; 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.Workbook; import org.apache.poi.ss.usermodel.WorkbookFactory; import org.apache.poi.ss.util.AreaReference; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.XSSFITestDataProvider; import org.apache.poi.xssf.XSSFTestDataSamples; import org.apache.poi.xssf.model.CalculationChain; import org.apache.poi.xssf.usermodel.extensions.XSSFCellFill; import org.junit.Ignore; import org.junit.Test; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTCols; import org.openxmlformats.schemas.spreadsheetml.x2006.main.CTWorksheet; public final class TestXSSFBugs extends BaseTestBugzillaIssues { public TestXSSFBugs() { super(XSSFITestDataProvider.instance); } /** * test writing a file with large number of unique strings, * open resulting file in Excel to check results! */ @Test public void bug15375_2() { bug15375(1000); } /** * Named ranges had the right reference, but * the wrong sheet name */ @Test public void bug45430() { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("45430.xlsx"); assertFalse(wb.isMacroEnabled()); assertEquals(3, wb.getNumberOfNames()); assertEquals(0, wb.getNameAt(0).getCTName().getLocalSheetId()); assertFalse(wb.getNameAt(0).getCTName().isSetLocalSheetId()); assertEquals("SheetA!$A$1", wb.getNameAt(0).getRefersToFormula()); assertEquals("SheetA", wb.getNameAt(0).getSheetName()); assertEquals(0, wb.getNameAt(1).getCTName().getLocalSheetId()); assertFalse(wb.getNameAt(1).getCTName().isSetLocalSheetId()); assertEquals("SheetB!$A$1", wb.getNameAt(1).getRefersToFormula()); assertEquals("SheetB", wb.getNameAt(1).getSheetName()); assertEquals(0, wb.getNameAt(2).getCTName().getLocalSheetId()); assertFalse(wb.getNameAt(2).getCTName().isSetLocalSheetId()); assertEquals("SheetC!$A$1", wb.getNameAt(2).getRefersToFormula()); assertEquals("SheetC", wb.getNameAt(2).getSheetName()); // Save and re-load, still there XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb); assertEquals(3, nwb.getNumberOfNames()); assertEquals("SheetA!$A$1", nwb.getNameAt(0).getRefersToFormula()); } /** * We should carry vba macros over after save */ @Test public void bug45431() throws Exception { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("45431.xlsm"); OPCPackage pkg = wb.getPackage(); assertTrue(wb.isMacroEnabled()); // Check the various macro related bits can be found PackagePart vba = pkg.getPart( PackagingURIHelper.createPartName("/xl/vbaProject.bin") ); assertNotNull(vba); // And the drawing bit PackagePart drw = pkg.getPart( PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") ); assertNotNull(drw); // Save and re-open, both still there XSSFWorkbook nwb = XSSFTestDataSamples.writeOutAndReadBack(wb); OPCPackage nPkg = nwb.getPackage(); assertTrue(nwb.isMacroEnabled()); vba = nPkg.getPart( PackagingURIHelper.createPartName("/xl/vbaProject.bin") ); assertNotNull(vba); drw = nPkg.getPart( PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") ); assertNotNull(drw); // And again, just to be sure nwb = XSSFTestDataSamples.writeOutAndReadBack(nwb); nPkg = nwb.getPackage(); assertTrue(nwb.isMacroEnabled()); vba = nPkg.getPart( PackagingURIHelper.createPartName("/xl/vbaProject.bin") ); assertNotNull(vba); drw = nPkg.getPart( PackagingURIHelper.createPartName("/xl/drawings/vmlDrawing1.vml") ); assertNotNull(drw); } @Test public void bug47504() { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("47504.xlsx"); assertEquals(1, wb.getNumberOfSheets()); XSSFSheet sh = wb.getSheetAt(0); XSSFDrawing drawing = sh.createDrawingPatriarch(); List rels = drawing.getRelations(); assertEquals(1, rels.size()); assertEquals("Sheet1!A1", rels.get(0).getPackageRelationship().getTargetURI().getFragment()); // And again, just to be sure wb = XSSFTestDataSamples.writeOutAndReadBack(wb); assertEquals(1, wb.getNumberOfSheets()); sh = wb.getSheetAt(0); drawing = sh.createDrawingPatriarch(); rels = drawing.getRelations(); assertEquals(1, rels.size()); assertEquals("Sheet1!A1", rels.get(0).getPackageRelationship().getTargetURI().getFragment()); } /** * Excel will sometimes write a button with a textbox * containing >br< (not closed!). * Clearly Excel shouldn't do this, but test that we can * read the file despite the naughtyness */ @Test public void bug49020() throws Exception { /*XSSFWorkbook wb =*/ XSSFTestDataSamples.openSampleWorkbook("BrNotClosed.xlsx"); } /** * ensure that CTPhoneticPr is loaded by the ooxml test suite so that it is included in poi-ooxml-schemas */ @Test public void bug49325() throws Exception { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("49325.xlsx"); CTWorksheet sh = wb.getSheetAt(0).getCTWorksheet(); assertNotNull(sh.getPhoneticPr()); } /** * Names which are defined with a Sheet * should return that sheet index properly */ @Test public void bug48923() throws Exception { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("48923.xlsx"); assertEquals(4, wb.getNumberOfNames()); Name b1 = wb.getName("NameB1"); Name b2 = wb.getName("NameB2"); Name sheet2 = wb.getName("NameSheet2"); Name test = wb.getName("Test"); assertNotNull(b1); assertEquals("NameB1", b1.getNameName()); assertEquals("Sheet1", b1.getSheetName()); assertEquals(-1, b1.getSheetIndex()); assertNotNull(b2); assertEquals("NameB2", b2.getNameName()); assertEquals("Sheet1", b2.getSheetName()); assertEquals(-1, b2.getSheetIndex()); assertNotNull(sheet2); assertEquals("NameSheet2", sheet2.getNameName()); assertEquals("Sheet2", sheet2.getSheetName()); assertEquals(-1, sheet2.getSheetIndex()); assertNotNull(test); assertEquals("Test", test.getNameName()); assertEquals("Sheet1", test.getSheetName()); assertEquals(-1, test.getSheetIndex()); } /** * Problem with evaluation formulas due to * NameXPtgs. * Blows up on: * IF(B6= (ROUNDUP(B6,0) + ROUNDDOWN(B6,0))/2, MROUND(B6,2),ROUND(B6,0)) * * TODO: delete this test case when MROUND and VAR are implemented */ @Test public void bug48539() throws Exception { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("48539.xlsx"); assertEquals(3, wb.getNumberOfSheets()); // Try each cell individually XSSFFormulaEvaluator eval = new XSSFFormulaEvaluator(wb); for(int i=0; i rels0 = sh0.getRelations(); List rels1 = sh1.getRelations(); assertEquals(1, rels0.size()); assertEquals(1, rels1.size()); assertEquals(rels0.get(0).getPackageRelationship(), rels1.get(0).getPackageRelationship()); } /** * Add comments to Sheet 1, when Sheet 2 already has * comments (so /xl/comments1.xml is taken) */ @Test public void bug51850() { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("51850.xlsx"); XSSFSheet sh1 = wb.getSheetAt(0); XSSFSheet sh2 = wb.getSheetAt(1); // Sheet 2 has comments assertNotNull(sh2.getCommentsTable(false)); assertEquals(1, sh2.getCommentsTable(false).getNumberOfComments()); // Sheet 1 doesn't (yet) assertNull(sh1.getCommentsTable(false)); // Try to add comments to Sheet 1 CreationHelper factory = wb.getCreationHelper(); Drawing drawing = sh1.createDrawingPatriarch(); ClientAnchor anchor = factory.createClientAnchor(); anchor.setCol1(0); anchor.setCol2(4); anchor.setRow1(0); anchor.setRow2(1); Comment comment1 = drawing.createCellComment(anchor); comment1.setString( factory.createRichTextString("I like this cell. It's my favourite.")); comment1.setAuthor("Bob T. Fish"); Comment comment2 = drawing.createCellComment(anchor); comment2.setString( factory.createRichTextString("This is much less fun...")); comment2.setAuthor("Bob T. Fish"); Cell c1 = sh1.getRow(0).createCell(4); c1.setCellValue(2.3); c1.setCellComment(comment1); Cell c2 = sh1.getRow(0).createCell(5); c2.setCellValue(2.1); c2.setCellComment(comment2); // Save and re-load wb = XSSFTestDataSamples.writeOutAndReadBack(wb); sh1 = wb.getSheetAt(0); sh2 = wb.getSheetAt(1); // Check the comments assertNotNull(sh2.getCommentsTable(false)); assertEquals(1, sh2.getCommentsTable(false).getNumberOfComments()); assertNotNull(sh1.getCommentsTable(false)); assertEquals(2, sh1.getCommentsTable(false).getNumberOfComments()); } /** * Sheet names with a , in them */ @Test public void bug51963() throws Exception { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("51963.xlsx"); XSSFSheet sheet = wb.getSheetAt(0); assertEquals("Abc,1", sheet.getSheetName()); Name name = wb.getName("Intekon.ProdCodes"); assertEquals("'Abc,1'!$A$1:$A$2", name.getRefersToFormula()); AreaReference ref = new AreaReference(name.getRefersToFormula()); assertEquals(0, ref.getFirstCell().getRow()); assertEquals(0, ref.getFirstCell().getCol()); assertEquals(1, ref.getLastCell().getRow()); assertEquals(0, ref.getLastCell().getCol()); } /** * Sum across multiple workbooks * eg =SUM($Sheet1.C1:$Sheet4.C1) * DISABLED As we can't currently evaluate these */ @Ignore public void bug48703() throws Exception { XSSFWorkbook wb = XSSFTestDataSamples.openSampleWorkbook("48703.xlsx"); XSSFSheet sheet = wb.getSheetAt(0); // Contains two forms, one with a range and one a list XSSFRow r1 = sheet.getRow(0); XSSFRow r2 = sheet.getRow(1); XSSFCell c1 = r1.getCell(1); XSSFCell c2 = r2.getCell(1); assertEquals(20.0, c1.getNumericCellValue(), 0); assertEquals("SUM(Sheet1!C1,Sheet2!C1,Sheet3!C1,Sheet4!C1)", c1.getCellFormula()); assertEquals(20.0, c2.getNumericCellValue(), 0); assertEquals("SUM(Sheet1:Sheet4!C1)", c2.getCellFormula()); // Try evaluating both XSSFFormulaEvaluator eval = new XSSFFormulaEvaluator(wb); eval.evaluateFormulaCell(c1); eval.evaluateFormulaCell(c2); assertEquals(20.0, c1.getNumericCellValue(), 0); assertEquals(20.0, c2.getNumericCellValue(), 0); } /** * Bugzilla 51710: problems reading shared formuals from .xlsx */ @Test public void bug51710() { Workbook wb = XSSFTestDataSamples.openSampleWorkbook("51710.xlsx"); final String[] columns = {"A","B","C","D","E","F","G","H","I","J","K","L","M","N"}; final int rowMax = 500; // bug triggers on row index 59 Sheet sheet = wb.getSheetAt(0); // go through all formula cells for (int rInd = 2; rInd <= rowMax; rInd++) { Row row = sheet.getRow(rInd); for (int cInd = 1; cInd <= 12; cInd++) { Cell cell = row.getCell(cInd); String formula = cell.getCellFormula(); CellReference ref = new CellReference(cell); //simulate correct answer String correct = "$A" + (rInd + 1) + "*" + columns[cInd] + "$2"; assertEquals("Incorrect formula in " + ref.formatAsString(), correct, formula); } } } /** * Bug 53101: */ @Test public void bug5301(){ Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("53101.xlsx"); FormulaEvaluator evaluator = workbook.getCreationHelper().createFormulaEvaluator(); // A1: SUM(B1: IZ1) double a1Value = evaluator.evaluate(workbook.getSheetAt(0).getRow(0).getCell(0)).getNumberValue(); // Assert assertEquals(259.0, a1Value, 0.0); // KY: SUM(B1: IZ1) /*double ky1Value =*/ evaluator.evaluate(workbook.getSheetAt(0).getRow(0).getCell(310)).getNumberValue(); // Assert assertEquals(259.0, a1Value, 0.0); } @Test public void bug54436(){ Workbook workbook = XSSFTestDataSamples.openSampleWorkbook("54436.xlsx"); if(!WorkbookEvaluator.getSupportedFunctionNames().contains("GETPIVOTDATA")){ Function func = new Function() { public ValueEval evaluate(ValueEval[] args, int srcRowIndex, int srcColumnIndex) { return ErrorEval.NA; } }; WorkbookEvaluator.registerFunction("GETPIVOTDATA", func); } workbook.getCreationHelper().createFormulaEvaluator().evaluateAll(); } /** * Password Protected .xlsx files should give a helpful * error message when called via WorkbookFactory. * (You need to supply a password explicitly for them) */ @Test(expected=EncryptedDocumentException.class) public void bug55692_stream() throws Exception { // Directly on a Stream WorkbookFactory.create(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); } @Test(expected=EncryptedDocumentException.class) public void bug55692_poifs() throws Exception { // Via a POIFSFileSystem POIFSFileSystem fsP = new POIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); WorkbookFactory.create(fsP); } @Test(expected=EncryptedDocumentException.class) public void bug55692_npoifs() throws Exception { // Via a NPOIFSFileSystem NPOIFSFileSystem fsNP = new NPOIFSFileSystem(POIDataSamples.getPOIFSInstance().openResourceAsStream("protect.xlsx")); WorkbookFactory.create(fsNP); } @Test public void bug53282() { Workbook wb = XSSFTestDataSamples.openSampleWorkbook("53282b.xlsx"); Cell c = wb.getSheetAt(0).getRow(1).getCell(0); assertEquals("#@_#", c.getStringCellValue()); assertEquals("http://invalid.uri", c.getHyperlink().getAddress()); } }