/* * ==================================================================== * 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.streaming; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertNull; import static org.junit.jupiter.api.Assertions.assertSame; import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.IOException; import org.apache.poi.ss.tests.usermodel.BaseTestXWorkbook; import org.apache.poi.ss.usermodel.Cell; import org.apache.poi.ss.usermodel.Row; import org.apache.poi.ss.usermodel.Sheet; import org.apache.poi.ss.util.CellReference; import org.apache.poi.xssf.DeferredSXSSFITestDataProvider; import org.apache.poi.xssf.usermodel.XSSFCell; import org.apache.poi.xssf.usermodel.XSSFRow; import org.apache.poi.xssf.usermodel.XSSFSheet; import org.apache.poi.xssf.usermodel.XSSFWorkbook; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.ValueSource; public final class TestDeferredSXSSFWorkbook extends BaseTestXWorkbook { public TestDeferredSXSSFWorkbook() { super(DeferredSXSSFITestDataProvider.instance); } @AfterEach void tearDown() { ((DeferredSXSSFITestDataProvider) _testDataProvider).cleanup(); } /** * cloning of sheets is not supported in SXSSF */ @Override @Test public void cloneSheet() throws IOException { RuntimeException e = assertThrows(RuntimeException.class, super::cloneSheet); assertEquals("Not Implemented", e.getMessage()); } /** * cloning of sheets is not supported in SXSSF */ @Override @Test public void sheetClone() { RuntimeException e = assertThrows(RuntimeException.class, super::sheetClone); assertEquals("Not Implemented", e.getMessage()); } /** * Skip this test, as SXSSF doesn't update formulas on sheet name changes. */ @Override @Disabled("SXSSF doesn't update formulas on sheet name changes, as most cells probably aren't in memory at the time") protected void setSheetName() {} @Override @Disabled("DeferredSXSSF code disposes rows in a way that breaks this test") protected void parentReferences() {} @Override @Disabled("DeferredSXSSF code disposes rows in a way that breaks this test") protected void unicodeInAll() {} @Test void existingWorkbook() throws IOException { try (XSSFWorkbook xssfWb1 = new XSSFWorkbook()) { xssfWb1.createSheet("S1"); try (DeferredSXSSFWorkbook wb1 = new DeferredSXSSFWorkbook(xssfWb1); XSSFWorkbook xssfWb2 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb1)) { assertTrue(wb1.dispose()); try (DeferredSXSSFWorkbook wb2 = new DeferredSXSSFWorkbook(xssfWb2)) { assertEquals(1, wb2.getNumberOfSheets()); Sheet sheet = wb2.getStreamingSheetAt(0); assertNotNull(sheet); assertEquals("S1", sheet.getSheetName()); assertTrue(wb2.dispose()); } } } } @Test void addToExistingWorkbook() throws IOException { try (XSSFWorkbook xssfWb1 = new XSSFWorkbook()) { xssfWb1.createSheet("S1"); Sheet sheet = xssfWb1.createSheet("S2"); Row row = sheet.createRow(1); Cell cell = row.createCell(1); cell.setCellValue("value 2_1_1"); try (DeferredSXSSFWorkbook wb1 = new DeferredSXSSFWorkbook(xssfWb1); XSSFWorkbook xssfWb2 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb1)) { assertTrue(wb1.dispose()); try (DeferredSXSSFWorkbook wb2 = new DeferredSXSSFWorkbook(xssfWb2)) { // Add a row to the existing empty sheet DeferredSXSSFSheet ssheet1 = wb2.getStreamingSheetAt(0); ssheet1.setRowGenerator((ssxSheet) -> { Row row1_1 = ssxSheet.createRow(1); Cell cell1_1_1 = row1_1.createCell(1); cell1_1_1.setCellValue("value 1_1_1"); }); // Add a row to the existing non-empty sheet DeferredSXSSFSheet ssheet2 = wb2.getStreamingSheetAt(1); ssheet2.setRowGenerator((ssxSheet) -> { Row row2_2 = ssxSheet.createRow(2); Cell cell2_2_1 = row2_2.createCell(1); cell2_2_1.setCellValue("value 2_2_1"); }); // Add a sheet with one row DeferredSXSSFSheet ssheet3 = wb2.createSheet("S3"); ssheet3.setRowGenerator((ssxSheet) -> { Row row3_1 = ssxSheet.createRow(1); Cell cell3_1_1 = row3_1.createCell(1); cell3_1_1.setCellValue("value 3_1_1"); }); try (XSSFWorkbook xssfWb3 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb2)) { assertEquals(3, xssfWb3.getNumberOfSheets()); // Verify sheet 1 XSSFSheet sheet1 = xssfWb3.getSheetAt(0); assertEquals("S1", sheet1.getSheetName()); assertEquals(1, sheet1.getPhysicalNumberOfRows()); XSSFRow row1_1 = sheet1.getRow(1); assertNotNull(row1_1); XSSFCell cell1_1_1 = row1_1.getCell(1); assertNotNull(cell1_1_1); assertEquals("value 1_1_1", cell1_1_1.getStringCellValue()); // Verify sheet 2 XSSFSheet sheet2 = xssfWb3.getSheetAt(1); assertEquals("S2", sheet2.getSheetName()); assertEquals(2, sheet2.getPhysicalNumberOfRows()); Row row2_1 = sheet2.getRow(1); assertNotNull(row2_1); Cell cell2_1_1 = row2_1.getCell(1); assertNotNull(cell2_1_1); assertEquals("value 2_1_1", cell2_1_1.getStringCellValue()); XSSFRow row2_2 = sheet2.getRow(2); assertNotNull(row2_2); XSSFCell cell2_2_1 = row2_2.getCell(1); assertNotNull(cell2_2_1); assertEquals("value 2_2_1", cell2_2_1.getStringCellValue()); // Verify sheet 3 XSSFSheet sheet3 = xssfWb3.getSheetAt(2); assertEquals("S3", sheet3.getSheetName()); assertEquals(1, sheet3.getPhysicalNumberOfRows()); XSSFRow row3_1 = sheet3.getRow(1); assertNotNull(row3_1); XSSFCell cell3_1_1 = row3_1.getCell(1); assertNotNull(cell3_1_1); assertEquals("value 3_1_1", cell3_1_1.getStringCellValue()); } } } } } @Test void inMemoryWrite() throws IOException { try (XSSFWorkbook xssfWb1 = new XSSFWorkbook()) { xssfWb1.createSheet("S1"); Sheet sheet = xssfWb1.createSheet("S2"); Row row = sheet.createRow(1); Cell cell = row.createCell(1); cell.setCellValue("value 2_1_1"); try (DeferredSXSSFWorkbook wb1 = new DeferredSXSSFWorkbook(xssfWb1); XSSFWorkbook xssfWb2 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb1)) { assertTrue(wb1.dispose()); try (DeferredSXSSFWorkbook wb2 = new DeferredSXSSFWorkbook(xssfWb2)) { // Add a row to the existing empty sheet DeferredSXSSFSheet ssheet1 = wb2.getStreamingSheetAt(0); ssheet1.setRowGenerator((ssxSheet) -> { Row row1_1 = ssxSheet.createRow(1); Cell cell1_1_1 = row1_1.createCell(1); cell1_1_1.setCellValue("value 1_1_1"); }); // Add a row to the existing non-empty sheet DeferredSXSSFSheet ssheet2 = wb2.getStreamingSheetAt(1); ssheet2.setRowGenerator((ssxSheet) -> { Row row2_2 = ssxSheet.createRow(2); Cell cell2_2_1 = row2_2.createCell(1); cell2_2_1.setCellValue("value 2_2_1"); }); // Add a sheet with one row DeferredSXSSFSheet ssheet3 = wb2.createSheet("S3"); ssheet3.setRowGenerator((ssxSheet) -> { Row row3_1 = ssxSheet.createRow(1); Cell cell3_1_1 = row3_1.createCell(1); cell3_1_1.setCellValue("value 3_1_1"); }); try (XSSFWorkbook xssfWb3 = DeferredSXSSFITestDataProvider.instance.inMemoryWriteOutAndReadBack(wb2)) { assertEquals(3, xssfWb3.getNumberOfSheets()); // Verify sheet 1 XSSFSheet sheet1 = xssfWb3.getSheetAt(0); assertEquals("S1", sheet1.getSheetName()); assertEquals(1, sheet1.getPhysicalNumberOfRows()); XSSFRow row1_1 = sheet1.getRow(1); assertNotNull(row1_1); XSSFCell cell1_1_1 = row1_1.getCell(1); assertNotNull(cell1_1_1); assertEquals("value 1_1_1", cell1_1_1.getStringCellValue()); // Verify sheet 2 XSSFSheet sheet2 = xssfWb3.getSheetAt(1); assertEquals("S2", sheet2.getSheetName()); assertEquals(2, sheet2.getPhysicalNumberOfRows()); Row row2_1 = sheet2.getRow(1); assertNotNull(row2_1); Cell cell2_1_1 = row2_1.getCell(1); assertNotNull(cell2_1_1); assertEquals("value 2_1_1", cell2_1_1.getStringCellValue()); XSSFRow row2_2 = sheet2.getRow(2); assertNotNull(row2_2); XSSFCell cell2_2_1 = row2_2.getCell(1); assertNotNull(cell2_2_1); assertEquals("value 2_2_1", cell2_2_1.getStringCellValue()); // Verify sheet 3 XSSFSheet sheet3 = xssfWb3.getSheetAt(2); assertEquals("S3", sheet3.getSheetName()); assertEquals(1, sheet3.getPhysicalNumberOfRows()); XSSFRow row3_1 = sheet3.getRow(1); assertNotNull(row3_1); XSSFCell cell3_1_1 = row3_1.getCell(1); assertNotNull(cell3_1_1); assertEquals("value 3_1_1", cell3_1_1.getStringCellValue()); } } } } } @Test void sheetdataWriter() throws IOException { try (DeferredSXSSFWorkbook wb = new DeferredSXSSFWorkbook()) { SXSSFSheet sh = wb.createSheet(); assertSame(sh.getClass(), DeferredSXSSFSheet.class); SheetDataWriter wr = sh.getSheetDataWriter(); assertNull(wr); } } @Test void removeSheet() throws IOException { try (DeferredSXSSFWorkbook wb = new DeferredSXSSFWorkbook()) { DeferredSXSSFSheet sheet1 = wb.createSheet("sheet1"); sheet1.setRowGenerator((sh) -> { Row row = sh.createRow(0); Cell cell = row.createCell(0); cell.setCellValue("sheet1"); }); DeferredSXSSFSheet sheet2 = wb.createSheet("sheet2"); sheet2.setRowGenerator((sh) -> { Row row = sh.createRow(0); Cell cell = row.createCell(0); cell.setCellValue("sheet2"); }); wb.removeSheetAt(0); try (XSSFWorkbook wb2 = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb)) { assertNull(wb2.getSheet( "sheet1")); XSSFSheet xssfSheet = wb2.getSheet( "sheet2"); assertNotNull(xssfSheet); assertEquals("sheet2", xssfSheet.getRow(0).getCell(0).getStringCellValue()); } } } @Test void gzipSheetdataWriter() throws IOException { try (DeferredSXSSFWorkbook wb = new DeferredSXSSFWorkbook()) { final int rowNum = 1000; final int sheetNum = 5; populateData(wb); try (XSSFWorkbook xwb = DeferredSXSSFITestDataProvider.instance.writeOutAndReadBack(wb)) { for (int i = 0; i < sheetNum; i++) { Sheet sh = xwb.getSheetAt(i); assertEquals("sheet" + i, sh.getSheetName()); for (int j = 0; j < rowNum; j++) { Row row = sh.getRow(j); assertNotNull(row, "row[" + j + "]"); Cell cell1 = row.getCell(0); assertEquals(new CellReference(cell1).formatAsString(), cell1.getStringCellValue()); Cell cell2 = row.getCell(1); assertEquals(i, (int) cell2.getNumericCellValue()); Cell cell3 = row.getCell(2); assertEquals(j, (int) cell3.getNumericCellValue()); } } assertTrue(wb.dispose()); } } } @ParameterizedTest @ValueSource(booleans = {false, true}) void workbookDispose(boolean compressTempFiles) throws IOException { try (DeferredSXSSFWorkbook wb = new DeferredSXSSFWorkbook()) { // compressTempFiles == false: the underlying writer is SheetDataWriter // compressTempFiles == true: the underlying writer is GZIPSheetDataWriter wb.setCompressTempFiles(compressTempFiles); populateData(wb); for (Sheet sheet : wb) { DeferredSXSSFSheet sxSheet = (DeferredSXSSFSheet) sheet; assertNull(sxSheet.getSheetDataWriter()); } assertTrue(wb.dispose()); for (Sheet sheet : wb) { DeferredSXSSFSheet sxSheet = (DeferredSXSSFSheet) sheet; assertNull(sxSheet.getSheetDataWriter()); } } } private static void populateData(DeferredSXSSFWorkbook wb) { for (int i = 0; i < 5; i++) { DeferredSXSSFSheet sheet = wb.createSheet("sheet" + i); int index = i; sheet.setRowGenerator((sh) -> { for (int j = 0; j < 1000; j++) { Row row = sh.createRow(j); Cell cell1 = row.createCell(0); cell1.setCellValue(new CellReference(cell1).formatAsString()); Cell cell2 = row.createCell(1); cell2.setCellValue(index); Cell cell3 = row.createCell(2); cell3.setCellValue(j); } }); } } @Override @Disabled("not implemented") protected void changeSheetNameWithSharedFormulas() { } }