使用NPOI的.xlsx文件有问题的损坏 – Excel无法打开文件“file.xlsx”,因为文件格式或文件扩展名无效

在读取或修改某些用户创build的.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);后,现在损坏iWorkbook.Write(filestream); 这里 。

用下面的代码创build一个新的.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无创build,设置,样式等。

我不能真正包含我的代码,因为这只是混淆,但为了完整起见,我在这个testing中实际上只使用NPOI的以下types和函数:

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

所以造成腐败的原因之一。 我想最终再次设置值,并像我为.xls一样工作。

有没有人经历过这个? 什么是可能导致腐败的NPOIfunction? 任何input将不胜感激。

编辑:使用NPOI v2.2.1。

我认为问题在于你正在读取和写入同一个FileStream 。 您应该使用单独的stream进行读取和写入。 试试像这样:

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