From 690b1d72acf9e4f0ff4e07b128542f8d7f2187f5 Mon Sep 17 00:00:00 2001 From: ABykiev Date: Wed, 2 Aug 2023 22:37:16 +0300 Subject: [PATCH] Fix leaveOpen option of SXSSFWorkbook This PR closes #1140 --- ooxml/XSSF/Streaming/SXSSFWorkbook.cs | 5 ++- .../XSSF/Streaming/SXSSFWorkbookTests.cs | 45 +++++++++++++++---- 2 files changed, 39 insertions(+), 11 deletions(-) diff --git a/ooxml/XSSF/Streaming/SXSSFWorkbook.cs b/ooxml/XSSF/Streaming/SXSSFWorkbook.cs index ab4172873..45ff5adcd 100644 --- a/ooxml/XSSF/Streaming/SXSSFWorkbook.cs +++ b/ooxml/XSSF/Streaming/SXSSFWorkbook.cs @@ -434,7 +434,7 @@ private XSSFSheet GetSheetFromZipEntryName(string sheetRef) return null; } - private void InjectData(FileInfo zipfile, Stream outStream) + private void InjectData(FileInfo zipfile, Stream outStream, bool leaveOpen) { // don't use ZipHelper.openZipFile here - see #59743 ZipFile zip = new ZipFile(zipfile.FullName); @@ -443,6 +443,7 @@ private void InjectData(FileInfo zipfile, Stream outStream) ZipOutputStream zos = new ZipOutputStream(outStream); try { + zos.IsStreamOwner = !leaveOpen; zos.UseZip64 = UseZip64.Off; //ZipEntrySource zipEntrySource = new ZipFileZipEntrySource(zip); //var en = zipEntrySource.Entries; @@ -773,7 +774,7 @@ public void Write(Stream stream, bool leaveOpen = false) //Substitute the template entries with the generated sheet data files - InjectData(tmplFile, stream); + InjectData(tmplFile, stream, leaveOpen); } finally { diff --git a/testcases/ooxml/XSSF/Streaming/SXSSFWorkbookTests.cs b/testcases/ooxml/XSSF/Streaming/SXSSFWorkbookTests.cs index c964be03e..b882c058b 100644 --- a/testcases/ooxml/XSSF/Streaming/SXSSFWorkbookTests.cs +++ b/testcases/ooxml/XSSF/Streaming/SXSSFWorkbookTests.cs @@ -132,8 +132,8 @@ public void IfSettingSheetNameShouldChangeTheSheetNameAtTheSpecifiedIndex() { _objectToTest = new SXSSFWorkbook(); _objectToTest.CreateSheet("test1"); - _objectToTest.SetSheetName(0,"renamed"); - + _objectToTest.SetSheetName(0, "renamed"); + Assert.AreEqual("renamed", _objectToTest.GetSheetAt(0).SheetName); } @@ -172,7 +172,7 @@ public void IfCreatingASheetShouldCreateASheetInTheXssfWorkbookWithTheGivenName( var sheet = _objectToTest.CreateSheet("test"); Assert.NotNull(sheet); - Assert.AreEqual("test",sheet.SheetName); + Assert.AreEqual("test", sheet.SheetName); } [Test] @@ -235,7 +235,7 @@ public void IfGivenThePositionOfAnExistingSheetShouldRemoveThatSheet() [Test] public void IfAFontIsCreatedItShouldBeReturnedAndAddedToTheExistingWorkbook() { - _objectToTest=new SXSSFWorkbook(); + _objectToTest = new SXSSFWorkbook(); var font = _objectToTest.CreateFont(); Assert.NotNull(font); @@ -277,10 +277,10 @@ public void IfWriting10x10CellsShouldWriteNumericValuesForCells() var sheets = 1; var rows = 10; var cols = 10; - AddCells(_objectToTest, sheets,rows,cols,CellType.Numeric); + AddCells(_objectToTest, sheets, rows, cols, CellType.Numeric); var savePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "numericTest.xlsx"); WriteFile(savePath, _objectToTest); - + Assert.True(File.Exists(savePath)); File.Delete(savePath); } @@ -294,7 +294,7 @@ public void IfOpeningExistingWorkbookShouldWriteAllPreviouslyExistingColumns() var cols = 10; AddCells(_objectToTest, sheets, rows, cols, CellType.Numeric); var savePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "numericTest.xlsx"); - var reSavePath = Path.Combine(TestContext.CurrentContext.TestDirectory , "numericTest2.xlsx"); + var reSavePath = Path.Combine(TestContext.CurrentContext.TestDirectory, "numericTest2.xlsx"); WriteFile(savePath, _objectToTest); Assert.True(File.Exists(savePath)); @@ -462,13 +462,13 @@ private void AddCells(IWorkbook wb, int sheets, int rows, int columns, CellType var row = sheet.CreateRow(k); for (int i = 0; i < columns; i++) { - WriteCellValue(row, type, i, i); + WriteCellValue(row, type, i, i); } } } } - + private void WriteFile(string saveAsPath, SXSSFWorkbook wb) { //Passing SXSSFWorkbook because IWorkbook does not implement .Dispose which cleans ups temporary files. @@ -507,5 +507,32 @@ private void WriteCellValue(IRow row, CellType type, int col, object val) row.CreateCell(col).SetCellFormula("SUM(A1:A2)"); } } + + [Test] + public void StreamShouldBeLeavedOpen() + { + using (SXSSFWorkbook workbook = new SXSSFWorkbook()) + { + ISheet sheet = workbook.CreateSheet("Sheet1"); + + // Write a large number of rows and columns to cause OutOfMemoryException + for (int rowNumber = 0; rowNumber < 10; rowNumber++) // Increase this number for more rows + { + IRow row = sheet.CreateRow(rowNumber); + for (int colNumber = 0; colNumber < 100; colNumber++) // Increase this number for more columns + { + ICell cell = row.CreateCell(colNumber); + cell.SetCellValue($"Row {rowNumber + 1}, Column {colNumber + 1}"); + } + } + + // Write the workbook data to a MemoryStream + using (var stream = new MemoryStream()) + { + workbook.Write(stream, true); + Assert.IsTrue(stream.CanRead); + } + } + } } }