本文主要介绍我用NPOI生成Excel文件所报过的错,以及是如何解决的。
目录
内容未写入
你是否也遇到过这样的情况,代码不报错、跟着断点走,内容也还是在,但是一打开Excel里面空空如也。此时,你可以检查以下几个地方。
-
文件流是否有问题
写入时总共要两个FileStream,一个用于给RWorkbook赋值,一个用于写入(注意我们这里使用的是File.Create,用File.OpenWrite也会导致不成功)。如下列代码所示
static IWorkbook RWorkbook = null;
//给workBook赋值
public static void initWorkBook()
{
using (FileStream fs = new FileStream(QueryParm.filePath, FileMode.Open, FileAccess.ReadWrite))
{
try
{
RWorkbook = new XSSFWorkbook(fs);
}
catch (Exception e)
{
//出错执行的代码...
}
}
}
//写入
public static void SaveExcel()
{
using (FileStream fsWrite = File.Create(QueryParm.filePath))
{
try
{
RWorkbook.Write(fsWrite);
}
catch (IOException e)
{
//出错执行的代码...
}
}
}
-
是否存在该单元格
当我们编辑单元格内容时,首先需要确保能够获取到该单元格。然而,有时我们可能会忽略确认单元格是否存在。尽管我们肉眼可以看到单元格,但可能无法对其进行操作。如果手动编辑该单元格并使用代码覆盖它,则可以成功编写。因此,在此处我们需要进行判断。如果无法获取该单元格,则直接创建一个新的单元格(对于已有格式的表格),而对于空表格,则无需进行判断并直接创建一个新的单元格。如下列代码所示
//省略获取sheet的代码....
//获取单元格行数,row为行数
IRow sheetRow = sheet.GetRow(row);
if (sheetRow == null)
{
sheetRow = sheet.CreateRow(row);
}
//获取单元格,col为列数
ICell sheetCell = sheetRow.GetCell(col);
if (sheetCol == null)
{
sheetCell = sheetRow.CreateCell(col);
}
//若果说我要修改第二行第三列的单元格则把row改为2,col改为3
sheetCell .SetCellValue("修改的内容");
-
表格中已编辑好的公式不生效
表格文件中已经定好了函数公式,通过NPOI把数据写入文件后,公式没有被触发。首先我们要先检查数据类型,写进去的是int还是string;其次修改后将ISheet的ForceFormulaRecalculation 属性设置为true,如:sheet.ForceFormulaRecalculation = true;
ForceFormulaRecalculation:这是一个 NPOI 的特性,它允许你强制 Excel 重新计算所有单元格的公式。在 HSSFWorkbook 和 NPOI.SS.UserModel.ISheet 中有一个 ForceFormulaRecalculation 属性。设置该属性为 true 可以强制重新计算所有单元格的公式。
进程被占用
-
检查FileStream是否关闭
可以用using将要使用到FileStream的代码部分包起来,这样运行完就会自动释放。
using (FileStream fs = File.Create(QueryParm.filePath)) { //要用到fs的部分代码 }
-
检查FileStream是否被重复调用
作者之前就是每改一个单元格的格子就写入一次,从而引发了这个问题。最好的解决方案就是把要改的单元格全部set好后再调用写入的方法,这样不仅能解决解决被占用的问题还能大大提升程序的运行速度。
保存大量数据时,内存溢出
分批次导入,每次保存时都释放内存
比如说我们要保存十万条数据,我们可以每3000条保存一次,保存好后可以释放WorkBook的内存,这里需要注意的是,释放内存后记得重新给WorkBook和Sheet赋值,要不然会找不到sheet,
给WorkBook释放内存我使用的是Workbook.Clear();属性,如果找不到该属性,大概率是版本没有,我测试过Close();,没有效果,我这里使用的是2.0.6.0版本。
数据处理片段:
//写入数据方法,这里展示的是片段
try
{
// 创建标题行
IRow dataRowTitle = sheet.CreateRow(0);
for (int c = 0; c < dt.Columns.Count; c++)
{
string colName = dt.Columns[c].ColumnName;
dataRowTitle.CreateCell(c).SetCellValue(colName);
}
int counter = 0;
for (int i = 0; i < dt.Rows.Count; i++)
{
IRow dataRow = sheet.CreateRow(i + 1);
for (int j = 0; j < dt.Columns.Count; j++)
{
string content = dt.Rows[i][j].ToString();
dataRow.CreateCell(j).SetCellValue(content);
}
counter += 1;
//每3000次和最后一次调用保存的方法
if (counter % 3000 == 0 || counter == dt.Rows.Count)
{
SaveExcel();
initWorkBook();
sheet = RWorkbook.GetSheet(sheetIndex.ToString());
}
}
}
catch (Exception e)
{
//错误执行片段
}
写入Excel片段
public static void SaveExcel()
{
using (FileStream fsWrite = File.Create(QueryParm.filePath))
{
try
{
RWorkbook.Write(fsWrite);
}
catch (IOException e)
{
//错误执行片段
}
}
//清除缓存
RWorkbook.Clear();
}
以上就是我的一些报错总结,欢迎留言探讨。