DataRow:根据给定的列名选择单元格值

63

我遇到了一个DataRow的问题,一直无法解决。

这个datarow是通过OleDbConnection从Excel电子表格中读取的。

如果我尝试使用列名从DataRow中选择数据,即使有数据存在,它也会返回DBNull。

但事情并不完全简单。

datarow.Table.Columns[5].ColumnName 返回 "my column"。
datarow["my column"] 返回 DBNull。
datarow[5] 返回 500。
datarow[datarow.Table.Columns[5].ColumnName] 返回 DBNull。(只是为了确保它不是拼写错误!)

我可以使用列号从datarow中选择数据,但我不喜欢这样做,因为如果列顺序发生变化,软件将会出错。


你的电子表格是什么样子的?顶部有空行吗?你的连接字符串是什么?你需要最少的代码来复制它,以便我们可以查看它(包括示例表格)? - Will
9个回答

82

你使用的是哪个版本的.NET?自.NET 3.5以来,有一个名为System.Data.DataSetExtensions的程序集,其中包含了一些有用的扩展方法,适用于数据表、数据行等。

你可以尝试使用

row.Field<type>("fieldName");

如果那不管用,你可以这样做:

DataTable table = new DataTable();
var myColumn = table.Columns.Cast<DataColumn>().SingleOrDefault(col => col.ColumnName == "myColumnName");
if (myColumn != null)
{
    // just some roww
    var tableRow = table.AsEnumerable().First();
    var myData = tableRow.Field<string>(myColumn);
    // or if above does not work
    myData = tableRow.Field<string>(table.Columns.IndexOf(myColumn));
}

将此标记为答案,因为它让我找出了问题所在。原来当我使用快速监视时,我输入了错误的列ID。输入正确的列ID返回了null,尽管该行中有数据。我不完全确定为什么会返回null,但我猜测这与解释数据类型有关,因为这是唯一一个具有非null值的行,并且将所有其他行中的null替换为0使其也返回了此行的正确值。 - VaticanUK
2
看看Jimmy的答案,它更简单且能够完成任务。我在使用.NET Framework 4.7.2时没有成功。 - Bernd Schuhmacher

75

这一定是一个新功能,否则我不确定为什么没有被提到。

您可以使用 row["ColumnName"] 访问 DataRow 对象中列的值:

DataRow row = table.Rows[0];
string rowValue = row["ColumnName"].ToString();

4
如果数据输入为NULL,在调用ToString时可能会引发错误。 - Zorgarath
1
@Zorgarath,确实如此。如果table没有行,您也会收到错误提示。 - Jimmy
1
谢谢。我知道这是可能的,但我记不住语法,而且通过评估也看不到它。 - John Lord

9
我发现通过以下方式更容易访问它:
        for (int i = 0; i < Table.Rows.Count-1; i++) //Looping through rows
        {
            var myValue = Table.Rows[i]["MyFieldName"]; //Getting my field value

        }

8

Hint

DataTable table = new DataTable();
table.Columns.Add("Column#1", typeof(int));
table.Columns.Add("Column#2", typeof(string));
table.Rows.Add(5, "Cell1-1");
table.Rows.Add(130, "Cell2-2");

编辑:增加更多内容

string cellValue = table.Rows[0].GetCellValueByName<string>("Column#2");

public static class DataRowExtensions
{
    public static T GetCellValueByName<T>(this DataRow row, string columnName)
    {
        int index = row.Table.Columns.IndexOf(columnName);
        return (index < 0 || index > row.ItemArray.Count()) 
                  ? default(T) 
                  : (T) row[index];        
    }
}

2

除了Jimmy说的之外,您还可以使用Convert.ChangeType以及必要的空值检查,使选择变得通用:

public T GetColumnValue<T>(DataRow row, string columnName)
  {
        T value = default(T);
        if (row.Table.Columns.Contains(columnName) && row[columnName] != null && !String.IsNullOrWhiteSpace(row[columnName].ToString()))
        {
            value = (T)Convert.ChangeType(row[columnName].ToString(), typeof(T));
        }

        return value;
  }

2
您可以在VB.net中获取列值。
Dim row As DataRow = fooTable.Rows(0)
Dim temp = Convert.ToString(row("ColumnName"))

在C#中,您可以使用Jimmy's Answer,但在将其转换为ToString()时要小心。如果数据为空,则可能会引发null异常,因此请改用Convert.ToString(your_expression)以避免null异常参考


0
for (int i=0;i < Table.Rows.Count;i++)
{
      Var YourValue = Table.Rows[i]["ColumnName"];
}

0
简单解决方案: 假设sqlDt包含DataTable,那么这将为您提供行中名为“aaa”的列的内容:
Dim fldContent = sqlDte.Rows(iz).ItemArray(sqlDte.Columns.Item("aaa").Ordinal)
Console.WriteLine("aaa = " & fldContent)   

编辑代码格式


0

在数据类型上要小心,如果不匹配会抛出错误。

var fieldName = dataRow.Field<DataType>("fieldName");

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