问题的现象就是,只要不修改xlsx,一直写入或者再次写入xlsx,追加内容都是不会有问题的。但是只要你修改了xlsx,用excle2010或者2007修改了xlsx的内容里面的列宽,或者行高,或者进行其他的操作。再次用NPOI往这个xlsx里面追加内容的时候,就会损坏这个xlsx文件。也就是说,NPOI在读取xlsx,如果这个xlsx不是由xlsx原始生成的,或者是原本是NPOI生成的,但是用户中途进行了修改,哪怕是改动了一丁点儿,比如列宽,行高,那么再次写入的时候xlsx就被写坏了,无法用EXCLE打开,打开会提示当前文件含有格式不正确的数据。
总结一句话:读写高级版本的xlsx不要使用NPOI, 而要使用EPPLUS。血的教训。被坑了半天时间。
如果是网站生成数据格式,供用户下载,用下面代码,NPOI没有问题,如果是反复读写的场景,甚至还有用户修改这个excle文件的话,比如电脑端NPOI对这个文件读写,用户在手机端修改同一个文件,建议用EPPLUS.下面是NPOI追加数据的代码。
public static IWorkbook LoadWorkbook(string filePath) { IWorkbook workbook; using (var fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read)) //读入excel模板 { if (filePath.EndsWith("xlsx")) { return workbook = new XSSFWorkbook(fileStream); } else { return workbook = new HSSFWorkbook(fileStream); } } } private void SaveToExcle() { try { string currentPath = Environment.CurrentDirectory; IWorkbook workbook = LoadWorkbook(currentPath + "\1.xlsx"); ISheet sheet = workbook.GetSheetAt(0); //获取工作表 IRow row = sheet.GetRow(0); //得到表头 using (FileStream fout = new FileStream(currentPath + "\1.xlsx", FileMode.Open, FileAccess.Write, FileShare.ReadWrite)) { row = sheet.CreateRow((sheet.LastRowNum + 1)); //在工作表中添加一行 ICell cell1 = row.CreateCell(0); cell1.SetCellValue(label_enghlis.Text); //赋值 ICell cell2 = row.CreateCell(1); cell2.SetCellValue(textBox1.Text); //赋值 ICell cell3 = row.CreateCell(2); cell3.SetCellValue(label_Rank.Text); //赋值 fout.Flush(); workbook.Write(fout); } workbook = null; textBox1.Text = string.Empty; } catch (Exception e) { MessageBox.Show(e.Message); } }
以上只要你用excle2007或者excle2010修改excle就问题。
下面是用的EPPLUS,初始化,创建一个xlsx文件,并且初始化,给sheet名字,表头标题赋值。
winform初始化,在根目录创建xlsx文件。需要Nuget引入Epplus。using OfficeOpenXml;
下面是winform初始化,用Epplus组件在根目录建立xlsx文件。
if (!File.Exists(currentPath + "\1.xlsx")) //不存在则创建
{
FileInfo newFile = new FileInfo(currentPath + @"1.xlsx");
using (ExcelPackage package = new ExcelPackage(newFile))
{
// add a new worksheet to the empty workbook
ExcelWorksheet worksheet = package.Workbook.Worksheets.Add("单词本");
//Add the headers
worksheet.Cells[1, 1].Value = "单词";
worksheet.Cells[1, 2].Value = "词义";
worksheet.Cells[1, 3].Value = "词频";
package.Save();
}
}
下面是Epplus追加数据到xlsx的代码:
private void SaveToXlsX()
{
try
{
string currentPath = Environment.CurrentDirectory;
// ok, we can run the real code of the sample now
if (File.Exists(currentPath + "\1.xlsx")) //如果存在则直接打开
{
FileInfo newFile = new FileInfo(currentPath + @"1.xlsx");
using (ExcelPackage package = new ExcelPackage(newFile))
{
// add a new worksheet to the empty workbook
ExcelWorksheet worksheet = package.Workbook.Worksheets[1];
//获得最后一行,这里其实获取的是总行数,追加数据的话,需要+1
int lastRow = worksheet.Dimension.End.Row;
worksheet.Cells[lastRow+1, 1].Value = label_enghlis.Text;
worksheet.Cells[lastRow+1, 2].Value = textBox1.Text;
worksheet.Cells[lastRow+1, 3].Value = label_Rank.Text;
package.Save();
}
}
textBox1.Text = string.Empty;
}
catch (Exception e)
{
MessageBox.Show(e.Message);
}
}
真正往xlsx追加数据。
excel07以上的版本支持最大行数104 8576行 ,百万行数据。如果是用追加的方式可能会更好。