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(ストリームOutputStream)メソッド。
ExcelPackageコンストラクターのエラーハンドラーでバグが発生しているようです。空のストリームを与えようとすると、System.IO.Packaging.Package.Open
は、パッケージを空にできないことを示す例外を表示します。
このコードは、ファイルが存在しない場合でも機能します。
var file = new FileInfo("test.xlsx");
using (ExcelPackage package = new ExcelPackage(file))
{
}
コンストラクターオーバーロードのドキュメントで、ストリームを空にすることが許可されていることが示されているため、EPPlus課題トラッカーでこの問題を提起することをお勧めします。
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 w/r/tでこれが変更された理由や、これを正しく実装している場合でもドキュメントを見つけることができないようです。
空のコンストラクターでExcelPackageを作成できます。独自の内部バッファを処理します。
http://epplus.codeplex.com/wikipage?title=WebapplicationExample
既存の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ストリームの復号化を試みますが、NULLではありません。
ただし、暗号化されていないファイルのパッケージを初期化しようとすると、例外が発生します。
「ストリームは有効/サポートされている暗号化文書ではありません。」
私は同じエラーに対処していましたが、他の答えはどれも助けになりませんでした。
最後に、このコードを追加してからファイルを開こうとすると、問題は解決しました。
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
根本的な原因は、コードページが見つからないためにEPPlusがZipを開けなかったためと思われます。 このStackOverflowの回答 に感謝します。