使用 NPOI 写入文件

Writing a file using NPOI

尝试从 DLL 执行此操作时,我无法使用 NPOI 将对 xlsx 的更改保存到磁盘。

我有一组数据,目前存储在数据库中,还有一个用于它的自制 ORM。本地开发的 ORM 位于其自己的 DLL 中。我想编写一个实用程序,它使用 ORM 将数据的子集提取到 read/write 它。我正在使用 NPOI (v2.1.3.0) 来完成它。

实用程序调用如下所示:

    private void Test_Click(object sender, RoutedEventArgs e)
    {
        var model = new ExcelDal(this.filename);
        model.Clients.Save(new Client { 
              DateOfBirth = DateTime.Now, DisplayName = "Test", Male = true
        });
    }

而且我希望我会得到一个 xlsx,其中 sheet 名为 "Client",文本列为 "DateOfBirth"、"DisplayName" 和 "Male".确实创建了一个文件,但尝试打开它失败了。另一方面,如果我用这个替换那个代码,我得到的正是预期的结果:

    private void Test_Click(object sender, RoutedEventArgs e)
    {
        IWorkbook workbook = new XSSFWorkbook();
        ISheet sheet = workbook.CreateSheet("Client");
        MainWindow.Create(sheet, 0, "DateOfBirth", "DisplayName", "Male");
        MainWindow.Create(sheet, 1, "1900/1/1", "Test", "true");

        FileMode mode = File.Exists(this.filename) ? FileMode.Truncate : FileMode.Create;

        using (FileStream fs = new FileStream(this.filename, mode, FileAccess.ReadWrite))
        {
            workbook.Write(fs);
        }
    }

    private static void Create(ISheet sheet, int rowNum, params string[] values)
    {
        IRow row = sheet.CreateRow(rowNum);
        for (int i = 0; i < values.Length; i++)
        {
            ICell cell = row.CreateCell(i);
            cell.SetCellValue(values[i]);
        }
    }

到目前为止尝试的故障排除步骤:

这是设置单元格值的代码(请注意,值在实际保存时已经被 toString() 处理):

    public void SetValue(IRow row, string column, string value)
    {
        int columnIndex = this.GetColumnIndex(column);
        ICell cell = ColumnMapping.GetOrCreateCell(row, columnIndex);
        cell.SetCellValue(value);
    }

    private static ICell GetOrCreateCell(IRow row, int columnIndex)
    {
        return row.GetCell(columnIndex) ?? row.CreateCell(columnIndex);
    }

保存文件的代码如下所示:

    public void Save()
    {
        FileMode mode = File.Exists(this.filename) ? FileMode.Truncate : FileMode.Create;

        using (FileStream fs = new FileStream(this.filename, mode, FileAccess.ReadWrite))
        {
            this.workbook.Write(fs);
        }
    }

我无法检测到任何差异。唯一可能的情况是,一种是通过上述 ORM 间接使用 NPOI,另一种是直接使用它。

我无法找到使用 NPOI 可靠地完成此操作的方法。该实用程序创建的文件总是损坏。我切换到 EPPlus for xlsx。生成的代码如下所示:

public void SetValue(int row, string column, string value)
{
    row += 2;   //EPPlus is 1-index based, and the first row is the heading
    int columnIndex = this.GetColumnIndex(column);
    this.excelSheet.SetValue(row, columnIndex, value);
}

保存文件的相应代码如下所示:

public void Dispose()
{
    //ExcelPackage is gone once it is written out.  It must be re-created.
    this.excelPackage.SaveAs(new FileInfo(this.filename));
    this.excelPackage.Dispose();
}

所以,实现方式是加一个Flush(),把当前的ExcelPackage处理掉,然后把当前内存中的所有ExcelSheet,再从写出来的文件里全部重新初始化。