Использование EPPlus с MemoryStream - PullRequest
43 голосов
/ 21 апреля 2011

Я использую EPPlus для создания файла XLSX в C #.Как только я создаю экземпляр ExcelPackage с потоком памяти - я получаю ошибку:

"Ошибка диска во время операции записи. (Исключение из HRESULT: 0x8003001D (STG_E_WRITEFAULT))" "

Код:

MemoryStream stream = new MemoryStream();

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

Кто-нибудь еще видел это?

Ответы [ 8 ]

62 голосов
/ 27 декабря 2012

Ни один из других ответов меня не понял (лист 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());
}
19 голосов
/ 28 ноября 2011

Я знаю, что на вопрос был дан ответ несколько месяцев назад, но так я делаю его для дальнейшего использования любым человеком, который пытается:

В 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 есть встроенная поддержка потоков.

13 голосов
/ 24 июня 2011

Если вы хотите продолжить использование потока (например, Response.OutputStream) , вы можете создать ExcelPackage с пустым конструктором и использовать SaveAs (Stream OutputStream ) метод.

9 голосов
/ 21 апреля 2011

Похоже, вы столкнулись с ошибкой в ​​обработчике ошибок конструктора ExcelPackage. Если вы попытаетесь задать пустой поток, System.IO.Packaging.Package.Open вызовет исключение, указывающее, что пакет не может быть пустым.

Этот код работает, даже если файл не существует:

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

Учитывая, что в документации по перегрузке конструктора указано, что потоку разрешено быть пустым, я бы порекомендовал поднять эту проблему в системе отслеживания проблем EPPlus.

1 голос
/ 30 марта 2018

У нас была похожая проблема при преобразовании кода, использующего версию EPPlus 4.1.1, в версию 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, мы должны были удалить используя block из функции BuildResultFile.

Кажется, я не могу найти какую-либо документацию в GitHub без объяснения, почему это изменилось или я даже правильно это реализую.

1 голос
/ 19 мая 2011

Вы можете создать ExcelPackage с пустым конструктором.Он будет обрабатывать свой собственный внутренний буфер.

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

0 голосов
/ 20 февраля 2018

Я имел дело с той же ошибкой, но ни один из других ответов не дал никакой помощи.

В конце концов, проблема была решена после добавления этого кода перед попыткой открыть файл:

Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);

Кажется, что основной причиной было то, что EPPlus не смог открыть ZIP из-за отсутствующей кодовой страницы.Я получил это на работу благодаря этому ответу StackOverflow .

0 голосов
/ 26 января 2018

Я столкнулся с той же проблемой, когда пытался открыть существующий файл 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, даже если пароль пуст, НО НЕ НУЛЯЕТ.

Однако, если вы попытаетесь инициализировать пакет для файла, который не зашифрован, у вас будет исключение:

'Поток не является допустимым / поддерживаемым зашифрованным документом.'

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...