将 EPPlus 与 MemoryStream 结合使用

问题描述 投票:0回答:8

我正在使用 EPPlus 在 C# 中生成 XLSX 文件。当我使用内存流实例化 ExcelPackage 时,我收到错误:

“写入操作期间发生磁盘错误。(HRESULT 异常:0x8003001D (STG_E_WRITEFAULT))”

代码是:

MemoryStream stream = new MemoryStream();

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

还有其他人看过这个吗?

c# excel epplus
8个回答
82
投票

其他答案都没有让我完全明白(Excel工作表总是空的),但这对我有用:

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

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

    var stream = new MemoryStream(package.GetAsByteArray());
}

27
投票

我知道这个问题在几个月前就已经得到了回答,但我就是这样做的,以供将来尝试的人参考:

在 VB.NET 中:

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

在 C# 中:

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

据我所知,C# 代码应该是正确的。 ExcelPackage 内置了对流的支持。


15
投票

如果您想继续使用流(例如 Response.OutputStream),您可以使用空构造函数创建 ExcelPackage 并使用 SaveAs(Stream OutputStream) 方法。


9
投票

看起来您在 ExcelPackage 构造函数的错误处理程序中遇到了错误。如果您尝试为其提供一个空流,

System.IO.Packaging.Package.Open
会引发异常指示,表明包不能为空。

即使文件不存在,此代码也可以工作:

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

鉴于构造函数重载的文档表明流允许为空,我建议在 EPPlus 问题跟踪器中提出此问题。


1
投票

您可以使用空构造函数创建 ExcelPackage。它将处理自己的内部缓冲区。

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


1
投票

将使用 4.1.1 版本 EPPlus 的代码转换为 4.5.1 版本时,我们遇到了类似的问题。

最初,我们使用以下模式:

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
}

还有我们的 ExcelBuilder 类,BuildResultFile 函数:

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

为了在 4.5.1 中使用此功能,我们必须从

BuildResultFile
函数中删除 using 块。

我似乎无法在 GitHub 中找到任何有关此更改的原因或我是否正确实现的文档。


0
投票

当我尝试打开现有的 Excel 文件并花了几天时间使用它时,我遇到了同样的问题。 就我而言,由于加密,我收到了提到的异常“写入操作期间发生磁盘错误。(来自 HRESULT 的异常:0x8003001D (STG_E_WRITEFAULT))”。

我能够通过传递密码读取 .xlsx 文件。 就我而言,空字符串“”就足够了。

在您的情况下,请尝试使用带有密码的构造函数来初始化包:

public ExcelPackage(Stream newStream, string Password)

package = new ExcelPackage(stream, "");

查看 ExcelPackage 源代码 http://epplus.codeplex.com/SourceControl/latest#EPPlus/ExcelPackage.cs

有一个方法

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

用于加载excel文件。

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);
 }

...

即使密码为空,但不为空,代码也会尝试解密 Excel 流。

但是,如果您尝试初始化未加密的文件的包,您将遇到异常:

“该流不是有效/受支持的加密文档。”


0
投票

我正在处理同样的错误,但其他答案都没有提供任何帮助。

最终,在尝试打开文件之前添加此代码后,问题得到解决:

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

根本原因似乎是 EPPlus 由于缺少代码页而无法打开 ZIP。 感谢这个 StackOverflow 答案,我才得以实现。

© www.soinside.com 2019 - 2024. All rights reserved.