ExcelMapper icon indicating copy to clipboard operation
ExcelMapper copied to clipboard

Error on saving multiple sheets

Open bh-schmidt opened this issue 3 years ago • 3 comments

Can we save multiple worksheets in the same memory stream?

I am receiving the following exception:

NPOI.OpenXml4Net.Exceptions.OpenXML4NetRuntimeException: Fail to save: an error occurs while saving the package : Must support writing (Parameter 'baseOutputStream')
 ---> System.ArgumentException: Must support writing (Parameter 'baseOutputStream')
   at ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream..ctor(Stream baseOutputStream, Deflater deflater, Int32 bufferSize)
   at ICSharpCode.SharpZipLib.Zip.Compression.Streams.DeflaterOutputStream..ctor(Stream baseOutputStream, Deflater deflater)
   at ICSharpCode.SharpZipLib.Zip.ZipOutputStream..ctor(Stream baseOutputStream)
   at NPOI.OpenXml4Net.OPC.ZipPackage.SaveImpl(Stream outputStream)
   --- End of inner exception stack trace ---
   at NPOI.OpenXml4Net.OPC.ZipPackage.SaveImpl(Stream outputStream)
   at NPOI.OpenXml4Net.OPC.OPCPackage.Save(Stream outputStream)
   at NPOI.POIXMLDocument.Write(Stream stream)
   at Ganss.Excel.ExcelMapper.Save[T](Stream stream, IEnumerable`1 objects, String sheetName, Boolean xlsx, Func`3 valueConverter)

Code:

var versions= new List<Version>() { new Version { MyProperty = 1 } };
var portfolios = new List<Portfolio>() { new Portfolio { MyProperty = 1 } };

var mapper = new ExcelMapper();
var stream = new MemoryStream();

mapper.Save(stream, versions, "Versions");
mapper.Save(stream, portfolios, "Portfolios");

var bytes = stream.ToArray();

The exception is thrown at

mapper.Save(stream, portfolios, "Portfolios");

bh-schmidt avatar Aug 17 '22 14:08 bh-schmidt

Try writing to Stream.Null on all calls to Save() except the last one. The internal workbook object will be updated on each call but only the last call to Save() will actually write the whole workbook to the target stream.

mganss avatar Aug 17 '22 16:08 mganss

Nice, it worked! Thanks for the help! I would like to implement a method AddSheet(IEnumerable<T> objects, string sheetName) that does the same, just to be easier to use, do you agree with that @mganss?

bh-schmidt avatar Aug 17 '22 18:08 bh-schmidt

@bh-schmidt Generally, yes. But I wouldn't use the Stream.Null hack but rather refactor the core Save() method to not call Workbook.Write() at the end:

https://github.com/mganss/ExcelMapper/blob/2d36c9b94110e1c45c0ed4f7020c95a0eee33ea2/ExcelMapper/ExcelMapper.cs#L1026-L1069

mganss avatar Aug 18 '22 10:08 mganss