Проблемное повреждение файлов .xlsx с помощью NPOI — Excel не может открыть файл «file.xlsx», поскольку формат файла или расширение файла недействительны.

При чтении или изменении некоторых файлов .xlsx, созданных пользователем, я получаю следующее сообщение об ошибке:

We found a problem with some content in 'test.xlsx'. Do you want us to try to recover as much as we can? If you trust the source of this workbook, click Yes.

Нажав Да, я получаю другое сообщение:

Excel cannot open the file 'test.xlsx' because the file format or file extension is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.

Пример проблемного файла .xlsx здесь (до помещения в NPOI).

Вот тот же файл, поврежденный после чтения и записи с помощью iWorkbook.Write(filestream); здесь.

У меня нет проблем с созданием нового файла .xlsx со следующим кодом:

string newPath = @"C:\MyPath\test.xlsx";

using (FileStream fs = new FileStream(newPath, FileMode.Create, FileAccess.Write))
{
    IWorkbook wb = new XSSFWorkbook();
    wb.CreateSheet();
    ISheet s = wb.GetSheetAt(0);
    IRow r = s.CreateRow(0);
    r.CreateCell(0);
    ICell c = r.GetCell(0);
    c.SetCellValue("test");
    wb.Write(fs);
    fs.Close();
}

Это прекрасно работает.

Работает даже открытие одного из проблемных дочерних файлов .xlsx, установка его в IWorkbook и запись обратно в файл:

string newPath = @"C:\MyPath\test.xlsx";

using (FileStream fs = new FileStream(newPath, FileMode.Open, FileAccess.ReadWrite))
{
    IWorkbook wb = new XSSFWorkbook(fs);
    wb.Write(fs);
    fs.Close();
}

Однако после выполнения кода, который читает из него, получает ISheets, IRows, ICells и т. д., он повреждает файл .xlsx. Несмотря на то, что я специально удалил все, что изменяет книгу. Никаких операций создания, установки, стилей и т. д. с NPOI.

Я не могу включить свой код, потому что это может только сбить с толку, но для полноты картины я действительно использую только следующие типы и функции из NPOI во время этого теста:

IWorkbook
XSSFWorkbook
ISheet
IRow
ICell
.GetSheetAt
.GetRow
.GetCell
.LastRowNum

Так что один из них вызывает коррупцию. Я хотел бы в конечном итоге снова установить значения и заставить его работать, как у меня для .xls.

Кто-нибудь испытал это? Какие функции NPOI могут привести к повреждению? Мы будем признательны за любой вклад.

Редактировать: Использование NPOI v2.2.1.


person justiceorjustus    schedule 12.12.2016    source источник
comment
Можете ли вы загрузить куда-нибудь один из этих файлов .xlsx, чтобы мы могли на него взглянуть?   -  person Lasse V. Karlsen    schedule 12.12.2016
comment
Спасибо за ответ. Отредактировано и добавлено ufile.io/2b349 в качестве примера.   -  person justiceorjustus    schedule 12.12.2016
comment
Хорошо, а в чем проблема с этим файлом? Убедившись, что он не содержит макросов или чего-то еще, я отлично открыл его в Excel. Вы уверены, что это не связано с версией? У меня Эксель 2016.   -  person Lasse V. Karlsen    schedule 12.12.2016
comment
Это файл до того, как он будет прочитан с помощью NPOI. Я могу загрузить испорченный файл после его запуска... подождите.   -  person justiceorjustus    schedule 12.12.2016
comment
Это файл после его чтения и записи: ufile.io/9ac96 Я попробовал Excel 2010 и 2013, поэтому далеко без хорошего результата.   -  person justiceorjustus    schedule 12.12.2016
comment
Хорошо, вы можете попробовать это, запустите код, который генерирует поврежденный файл, но убедитесь, что вы удалили целевой файл перед его запуском, посмотрите, поможет ли это.   -  person Lasse V. Karlsen    schedule 12.12.2016
comment
Я думаю, что мы, возможно, нашли решение здесь. Я еще немного протестирую его после обеда, но, возможно, это произошло из-за того, что я перезаписываю файл, который я ранее открывал для чтения, и теперь сохраняю его вместе с файловым потоком. Я также успешно использую FileAccess.ReadWrite, если я перезаписываю файл. Я буду играть с изменением этого больше. Скрестив пальцы!   -  person justiceorjustus    schedule 12.12.2016


Ответы (2)


Я думаю, проблема в том, что вы читаете и пишете в один и тот же FileStream. Вы должны выполнять чтение и запись, используя отдельные потоки. Попробуйте это так:

string newPath = @"C:\MyPath\test.xlsx";

// read the workbook
IWorkbook wb;
using (FileStream fs = new FileStream(newPath, FileMode.Open, FileAccess.Read))
{
    wb = new XSSFWorkbook(fs);
}

// make changes
ISheet s = wb.GetSheetAt(0);
IRow r = s.GetRow(0) ?? s.CreateRow(0);
ICell c = r.GetCell(1) ?? r.CreateCell(1);
c.SetCellValue("test2");

// overwrite the workbook using a new stream
using (FileStream fs = new FileStream(newPath, FileMode.Create, FileAccess.Write))
{
    wb.Write(fs);
}
person Brian Rogers    schedule 13.12.2016
comment
Именно там я оказался от @Lasse V. Karlsen. Я думаю, что остались какие-то данные, которые NPOI не записали правильно и взбесили Excel. Размеры файлов после NPOI немного меньше даже без изменений. Делать то, что вы сказали, работает отлично. - person justiceorjustus; 13.12.2016
comment
Кажется, что действительно важная часть заключается в том, что мы переопределяем рабочую книгу. Просто открытие файлового потока приводит к той же ошибке. - person Brezelmann; 21.04.2021

У меня такая же проблема. В моем случае проблема была не в самой NPOI, а в ее зависимости SharpZipLib.

Я использовал NPOI 2.3.0 и SharpZipLib 1.0.0. и выдавало ту же ошибку, что и в вашем случае. Сгенерированный Excel имел размер 0 байт. Я понизил версию SharpZipLib до версии 0.86.0 в проекте, где я использовал NPOI (уровень службы), а также в проекте MVC (здесь у меня тоже был пакет SharpZipLib).

Я также удалил вручную в web.config зависимость сборки, ранее созданную для SharpZipLib:

<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
  .......
  <dependentAssembly>
    <assemblyIdentity name="ICSharpCode.SharpZipLib" publicKeyToken="1b03e6acf1164f73" culture="neutral" />
    <bindingRedirect oldVersion="0.0.0.0-1.0.0.999" newVersion="1.0.0.999" />
  </dependentAssembly>
</assemblyBinding>

Я надеюсь, что это поможет кому-то.

person IonutC    schedule 17.10.2018
comment
Большое спасибо, это действительно очень мне помогает. - person Elvin Acevedo; 30.10.2019