如何使用NPOI在C#中通过列名获取Excel单元格的值

3

我在代码中有以下情况,其中单元格的值是通过列号获取的。

但是我想根据列名分配单元格的值,因为我从一个数组中分配值,而该数组中的列名与Excel表格中的列标题顺序不同。

if (row.GetCell(columnNumber) != null)
      ICell cell = row.GetCell(columnNumber);

请问有什么方法可以通过列名获取单元格的值吗?

5个回答

2

在我的情况下,我需要使用xls文件中第一行的列名称来更新数据库表。在@stevenh的提示下,我做了以下操作:

                System.Collections.IEnumerator rows = sheet.GetRowEnumerator();

                rows.MoveNext();
                IRow r = (HSSFRow)rows.Current;
                int z = r.LastCellNum - 1;
                DataTable dt = new DataTable();

                for (int j = 0; j < z; j++)
                {
                    ICell cell = r.GetCell(j);
                    dt.Columns.Add(cell.StringCellValue);                    
                }

                rows.Reset();
                while (rows.MoveNext())
                {
                //... get the rest of the data....

对我来说,这很简单。


1
尽管这篇文章已经有一个月了,但我也遇到了在NPOI中将列名转换为列位置(反之亦然)的问题。
在这篇文章如何使用NPOI获取Excel单元格地址(A1,A2)的值中找到了答案,使用NPOI.SS.Util.CellReference。
CellReference允许您进行双向转换。 您可以传递字符串单元格引用(例如,“AA1”)以获取位置,或者传递行和列以获取字符串(在CellRefParts数组中)。

0
我建议您放弃使用NPOI,改用EPPlus。我曾经花了3天时间使用NPOI自动创建一些Excel文件,结果发现如果要添加列,必须手动移动每个单元格并处理空单元格,因为NPOI返回空对象。而在EPPlus中,只需简单地这样做即可。
worksheet.Cells["columnname"]

EPPlus是优秀的 - 但它无法处理*.xls文件。我们中的一些人被迫使用过时的.xls文件,并且需要使用NPOI。 - bagofmilk
@bagofmilk 要么你说服客户使用免费的替代品(如openoffice、libreoffice、WPS office等),要么以一个非常小的费用使用任何第三方商业库,这些库可以为你完成所有无聊的工作。与学习曲线、缺失文档和在NPOI上浪费的时间相比,你将在几天内就能收回这个价格,并且能够永久使用它的巨大好处。 - Liquid Core
是的,但我的当前问题与程序有关,特别是AutoCAD Electrical 2019。一家主要CAD软件开发商的最新版本提供*.xls格式的数据,而我没有权利让他们知道整个世界已经超越了2003年。 - bagofmilk
@bagofmilk 试着查看是否有任何xls第三方库可以为您完成工作。我记得曾经能够通过其中一个试用版本找到解决方案,该版本在商业项目中提供免费使用,但对于您可以读取/导出的行数和工作表数量有限制。或者购买一个。或者,祝你好运学习NPOI,它是迄今为止我见过的文档最差的库,完全依靠那些不得不通过试错来提供示例的可怜家伙。另外,我忘了,如果他们安装了Microsoft Office,请直接指向Microsoft.Interop API。 - Liquid Core
@Dave也许你可以提供你的代码,而不是一个泛泛的错误报告? - Liquid Core

0
你可以做以下操作:
1. 读取表头行,并将数据保存在一个以表头名称为键、索引为值的字典中。 2. 从字典中获取(或尝试获取)值。
代码示例如下:
Dictionary<string, int> indices = 
    headersRow.Cells
              .Select(x => new { x.StringCellValue, x.ColumnIndex })
              .ToDictionary(x => x.StringCellValue, x => x.ColumnIndex);

for (var rowIndex = 1; rowIndex <= sheet.LastRowNum; rowIndex++)
{
    var row = sheet.GetRow(rowIndex);

    var hasSuchHeader = indices.TryGetValue(name, out int cellIndex);
    if (hasSuchHeader)
    {
        var cell = row.GetCell(cellIndex);
    }
}

-1

这是一个比较宽泛的问题,没有看到你所处理的数据示例或者你想要的最终结果,但是以下是一些启发性的想法:

你可以为每一列设置单独的指定,并按照特定顺序对这些列进行排序,以保持整个表格的完整性。这可以通过读取第一行并将每一列分配给一个变量来实现。

或者

你可以记录哪些列包含什么信息,并按照数据结构(如二叉搜索树或哈希)的顺序对信息进行排序,以组织数据并保留其结构。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接