52

I am using EPPlus to generate an XLSX file in C#. As soon as I instantiate the ExcelPackage with a memory stream - I get the error:

"A disk error occurred during a write operation. (Exception from HRESULT: 0x8003001D (STG_E_WRITEFAULT))"

Code is:

MemoryStream stream = new MemoryStream();

using (ExcelPackage package = new ExcelPackage(stream))
{
    ...
}

Has anyone else seen this?

Pure.Krome
  • 84,693
  • 113
  • 396
  • 647
dan
  • 5,664
  • 8
  • 45
  • 59
  • 1
    It might of been an error with the library, it works now :) Posted how I did it. – Reigo Hein Nov 28 '11 at 11:37
  • If your getting this error when opening an existing Excel file via a MemoryStream (from a database or something), then it can mean your Excel file is invalid (in my case I was opening a random XML file rather than an XLSX) – Mike Wade Jun 10 '15 at 16:19

8 Answers8

82

None of the other answers quite got me there (the Excel worksheet was always empty), but this worked for me:

using (var package = new ExcelPackage())
{
    var worksheet = package.Workbook.Worksheets.Add("Worksheet Name");

    worksheet.Cells["A1"].LoadFromCollection(data);

    var stream = new MemoryStream(package.GetAsByteArray());
}
Noah Heldman
  • 6,724
  • 3
  • 40
  • 40
  • 13
    What did your `data` contain? A worksheet? A CSV file? A workbook? This answer is lacking critical information. – Suncat2000 Jun 13 '17 at 18:01
  • 2
    `LoadFromCollection` is overloaded, but the version with one parameter takes an `IEnumerable` for which the generic type represents the Excel columns that will be loaded, and each member of the IEnumerable becomes an Excel row. The official CodePlex site is having issues, and will be shut down, but here's an example of the file that has the implementations of `LoadFromCollection`: https://github.com/pruiz/EPPlus/blob/master/EPPlus/ExcelRangeBase.cs. In my case, `data` was an `IEnumerable`, where the `Person` class had properties like `FirstName`, `LastName`, and `Email`. – Noah Heldman Jun 13 '17 at 21:39
  • After I download the excel file I generated, its content is not readable. It contains weird chars like `PK�HU�H��3[Content_Types].xml���J1�_e�U��D���U�>�` as if some encoding problems occurred. Does anyone face with the same issue? – RaZzLe Aug 18 '22 at 06:10
26

I know the question was answered months before, but this is how I do it for future reference to anyone trying:

In VB.NET:

Dim stream As New MemoryStream
Using package As New ExcelPackage(stream)
    'Here goes the ExcelPackage code etc 
    package.Save()
End Using

In C#:

MemoryStream stream = new MemoryStream();
using (ExcelPackage package = new ExcelPackage(stream))
{
    //Here goes the ExcelPackage code etc
    package.Save()
}

The C# code should be correct, as far as I know. And the ExcelPackage has built-in support for streams.

Nat Ritmeyer
  • 5,634
  • 8
  • 45
  • 58
Reigo Hein
  • 741
  • 9
  • 21
  • So you have to create a file before you can read a stream or populate a "ExcelPackage"? Do you know why or is this just a bug? – Suncat2000 Jun 13 '17 at 17:47
14

If you want to continue using a stream (e.g. Response.OutputStream) you can create an ExcelPackage with an empty constructor and use the SaveAs(Stream OutputStream) method.

Danny
  • 437
  • 4
  • 11
9

It looks like you're hitting a bug in the error handler of the ExcelPackage constructor. If you try and give it an empty stream, System.IO.Packaging.Package.Open raises an exception indication that a package cannot be empty.

This code works, even if the file doesn't exist:

var file = new FileInfo("test.xlsx");
using (ExcelPackage package = new ExcelPackage(file))
{
}

Given that the documentation for the constructor overload indicates that the stream is allowed to be empty, I'd recommend raising this issue in the EPPlus issue tracker.

Mike Goatly
  • 7,380
  • 2
  • 32
  • 33
  • However, the question gets a +1 because this looks like it could be a useful library :) – Mike Goatly Apr 21 '11 at 13:15
  • It comes highly recommended: http://stackoverflow.com/questions/151005/create-excel-xls-and-xlsx-file-from-c (first answer - see comments) – dan May 03 '11 at 00:25
1

We had a similar issue when converting code that used the 4.1.1 version of EPPlus to the 4.5.1 version.

Originally, we were using the following pattern:

using (var ms = new MemoryStream())
{
    new ExcelBuilder().BuildResultFile(result, ms);
    ms.Position = 0;    // <-- Cannot access a closed Stream error thrown here
    // Send Excel file to Azure storage
}

And our ExcelBuilder class, BuildResultFile function:

public void BuildResultFile(List<ResultSet> resultSets, Stream stream)
{
    using (var package = new ExcelPackage(stream))
    {
        // Create Excel file from resultSets
        package.Save();
    }
}

In order to make this work with 4.5.1 we had to remove using block from the BuildResultFile function.

I can't seem to find any documentation on in GitHub w/r/t why this changed or if I am even implementing this correctly.

1

You can create an ExcelPackage with an empty constructor. It will handle its own internal buffer.

http://epplus.codeplex.com/wikipage?title=WebapplicationExample

Hamid
  • 11
  • 1
0

I faced with the same issue when tried to open existing excel file and spent couple days with it. In my case I received mentioned exception "A disk error occurred during a write operation. (Exception from HRESULT: 0x8003001D (STG_E_WRITEFAULT))" due to encryption.

I was able to read .xlsx file by passing password. In my case empty string "" was enough.

in your case please try to initialize package using constructor with password:

public ExcelPackage(Stream newStream, string Password)

package = new ExcelPackage(stream, "");

Have a look into ExcelPackage source code http://epplus.codeplex.com/SourceControl/latest#EPPlus/ExcelPackage.cs

There is a method

private void Load(Stream input, Stream output, string Password) 

which is used to load excel file.

private void Load(Stream input, Stream output, string Password) 

...

if (Password != null)

{
  Stream encrStream = new MemoryStream();
  CopyStream(input, ref encrStream);
  EncryptedPackageHandler eph = new EncryptedPackageHandler();
  Encryption.Password = Password;
  ms = eph.DecryptPackage((MemoryStream)encrStream, Encryption);
}
else
{
  ms = new MemoryStream();
  CopyStream(input, ref ms);
 }

...

Code will try to decrypt excel stream even if password is empty, BUT NOT NULL.

However if you try to initialize package for file that is not encrypted you will have exception:

'The stream is not an valid/supported encrypted document.'

Artem
  • 19
  • 2
  • You *don't* need to use the constructor with the password to write to a stream. The library itself has changed a *LOT* in the last 6 years. Back then it used different libraries for compression – Panagiotis Kanavos Jan 26 '18 at 11:11
  • I don't modify excel file, only reading. In my case exception message is misleading. It does not say anything about encryption. I use latest version of EPPlus library v4.1.1. And loading file using password, even empty one, fixed my issue: using (var package = new ExcelPackage()) { using (var stream = File.OpenRead(excelFilePath)) { package.Load(stream, ""); } } – Artem Jan 26 '18 at 11:53
0

I was dealing with the same error, but none of the other answers provided any help.

In the end, the problem was solved after adding this code before trying to open the file:

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

It seems that the root cause was that EPPlus could not open the ZIP because of a missing code page. I got this to work thank to this StackOverflow answer.