我正在使用 EPPlus 在 C# 中生成 XLSX 文件。当我使用内存流实例化 ExcelPackage 时,我收到错误:
“写入操作期间发生磁盘错误。(HRESULT 异常:0x8003001D (STG_E_WRITEFAULT))”
代码是:
MemoryStream stream = new MemoryStream();
using (ExcelPackage package = new ExcelPackage(stream))
{
...
}
还有其他人看过这个吗?
其他答案都没有让我完全明白(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());
}
我知道这个问题在几个月前就已经得到了回答,但我就是这样做的,以供将来尝试的人参考:
在 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 内置了对流的支持。
如果您想继续使用流(例如 Response.OutputStream),您可以使用空构造函数创建 ExcelPackage 并使用 SaveAs(Stream OutputStream) 方法。
看起来您在 ExcelPackage 构造函数的错误处理程序中遇到了错误。如果您尝试为其提供一个空流,
System.IO.Packaging.Package.Open
会引发异常指示,表明包不能为空。
即使文件不存在,此代码也可以工作:
var file = new FileInfo("test.xlsx");
using (ExcelPackage package = new ExcelPackage(file))
{
}
鉴于构造函数重载的文档表明流允许为空,我建议在 EPPlus 问题跟踪器中提出此问题。
您可以使用空构造函数创建 ExcelPackage。它将处理自己的内部缓冲区。
http://epplus.codeplex.com/wikipage?title=WebapplicationExample
将使用 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 中找到任何有关此更改的原因或我是否正确实现的文档。
当我尝试打开现有的 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 流。
但是,如果您尝试初始化未加密的文件的包,您将遇到异常:
“该流不是有效/受支持的加密文档。”
我正在处理同样的错误,但其他答案都没有提供任何帮助。
最终,在尝试打开文件之前添加此代码后,问题得到解决:
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
根本原因似乎是 EPPlus 由于缺少代码页而无法打开 ZIP。 感谢这个 StackOverflow 答案,我才得以实现。