DataRow: Select cell value by a given column name - c#

I have a problem with a DataRow that I'm really struggling with.
The datarow is read in from an Excel spreadsheet using an OleDbConnection.
If I try to select data from the DataRow using the column name, it returns DBNull even though there is data there.
But it's not quite that simple.
datarow.Table.Columns[5].ColumnName returns "my column".
datarow["my column"] returns DBNull.
datarow[5] returns 500.
datarow[datarow.Table.Columns[5].ColumnName] returns DBNull. (just to make sure its not a typo!)
I could just select things from the datarow using the column number, but I dislike doing that since if the column ordering changes, the software will break.

Which version of .NET are you using? Since .NET 3.5, there's an assembly System.Data.DataSetExtensions, which contains various useful extensions for dataTables, dataRows and the like.
You can try using
row.Field<type>("fieldName");
if that doesn't work, you can do this:
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));
}

This must be a new feature or something, otherwise I'm not sure why it hasn't been mentioned.
You can access the value in a column in a DataRow object using row["ColumnName"]:
DataRow row = table.Rows[0];
string rowValue = row["ColumnName"].ToString();

I find it easier to access it by doing the following:
for (int i = 0; i < Table.Rows.Count-1; i++) //Looping through rows
{
var myValue = Table.Rows[i]["MyFieldName"]; //Getting my field value
}

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");
EDIT: Added more
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];
}
}

On top of what Jimmy said, you can also make the select generic by using Convert.ChangeType along with the necessary null checks:
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;
}

You can get the column value in VB.net
Dim row As DataRow = fooTable.Rows(0)
Dim temp = Convert.ToString(row("ColumnName"))
And in C# you can use Jimmy's Answer, just be careful while converting it to ToString(). It can throw null exception if the data is null
instead Use Convert.ToString(your_expression) to avoid null exception reference

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

Be careful on datatype. If not match it will throw an error.
var fieldName = dataRow.Field<DataType>("fieldName");

Simple solution:
Assume sqlDt contains the DataTable, then this will give you the content of the
column named "aaa" in row is:
Dim fldContent = sqlDte.Rows(iz).ItemArray(sqlDte.Columns.Item("aaa").Ordinal)
Console.WriteLine("aaa = " & fldContent)
Edited code formatting

Related

How to compare two DataSet columns values in C#?

In below code i want to compare two dataset column's values but its not match then also getting true this condition.so how to really compare?
if (dsEmp.Tables[0].Columns["EmpName"].ToString() == dsAllTables.Tables[2].Columns["EmpName"].ToString())
{
}
You are comparing two column-names, so "EmpName" with "EmpName" which is always true. Tables[0].Columns["EmpName"] returns a DataColumn with that name and ToString returns the name of the column which is "EmpName". So that's pointless.
If you instead want to know if two tables contain the same EmpName value in one of their rows you can use LINQ:
var empRowsEmpName = dsEmp.Tables[0].AsEnumerable().Select(r => r.Field<string>("EmpName"));
var allRowsEmpName = dsAllTables.Tables[2].AsEnumerable().Select(r => r.Field<string>("EmpName"));
IEnumerable<string> allIntersectingEmpNames = empRowsEmpName.Intersect(allRowsEmpName);
if (allIntersectingEmpNames.Any())
{
}
Now you even know which EmpName values are contained in both tables. You could use a foreach-loop:
foreach(string empName in allIntersectingEmpNames)
Console.WriteLine(empName);
If you want to find out if a specific value is contained in both:
bool containsName = allIntersectingEmpNames.Contains("SampleName");
If you just want to get the first matching:
string firstIntersectingEmpName = allIntersectingEmpNames.FirstOrDefault();
if(firstIntersectingEmpName != null){
// yes, there was at least one EmpName that was in both tables
}
If you have a single row, this should work:
if (dsEmp.Tables[0].Row[0]["EmpName"].ToString() == dsAllTables.Tables[2].rows[0]["EmpName"].ToString())
{
}
For multiple rows you have to iterate through table:
for (int i = 0; i <= dsEmp.Tables[0].Rows.Count; i++)
{
for (int j = 0; j <= dsAllTables.Tables[0].Rows.Count; j++)
{
if (dsEmp.Tables[0].Rows[i]["EmpName"].ToString() == dsAllTables.Tables[2].Rows[j]["EmpName"].ToString())
{
}
}
}
I have two datatables - dtbl and mtbl, and I use this to return records that have a difference, as another DataTable.
//compare the two datatables and output any differences into a new datatable, to return
var differences = dtbl.AsEnumerable().Except(mtbl.AsEnumerable(), DataRowComparer.Default);
return differences.Any() ? differences.CopyToDataTable() : new DataTable();

comparing datarow value with a string in if

I have an application which stores a user selected value to the value in my dataset filled datatable. I need to set another column in the table based on this comparison. But the comparison is not working. It always returns false, not entering in the if condition.
foreach (DataRow dr in dsQuestions.Tables[0].Rows)
{
if (dr["Data"] == indicater[0])
{
dr["IsSelected"] = true;
}
}
indiactor[0] is a string array and dr["data"] is also of type string but it shows a warning that it needs to a string type.
The DataRow indexer returns the field at that index as object not as string.
I would recommend to use the strongly typed Field-extension method which also supports nullables:
if (dr.Field<String>("Data") == indicater[0]){}
... and the SetField method that also support nullable types:
dr.SetField("IsSelected", true);
Update if indicater[0] is really a string[] (not a single string), how do you want to compare a string with a string[]? If you for example want to check if the array contains this data:
if (indicater[0].Contains(dr.Field<String>("Data"))){}
That would also explain why it never enters the if: because == only compares strings by equality, other types which don't have overridden the ==-operator will compare only the reference. A string is never the same reference as a string[]. But you don't get a compile time error because you can compare an object with everything else.
First of all string can't compare using == you should use equals method:
foreach (DataRow dr in dsQuestions.Tables[0].Rows)
{
if (dr["Data"].tostring().Equals(indicater[0]))
{
dr["IsSelected"] = true;
}
May be useful for you
DataRow[] result = table.Select("Id = 1");
foreach (DataRow row in result)
{
if (row[0].Equals(indicater[0]))
{
//IsSelected
row[1]=true;
Console.WriteLine("{0}", row[0]);
}
}
Try this:
foreach (DataRow dr in dsQuestions.Tables[0].Rows)
{
if (dr["Data"].ToString() == indicater[0].ToString())
{
Convert.ToBoolean(dr["IsSelected"].ToString()) = true;
}
}

Find value from the dataview using column name

I am trying to find value from dataview using column name. My dataset shows value but my if condition returns false. I am working in asp.net using c#.
I have tried with different code. I am trying to get value like this
dv[0].DataView.Table.Columns[0].ToString().Contains("52")
//RETURN FALSE
OR
dv[0].Equals("52")
// //RETURN FALSE
OR
dv[0].Find("52")
// //RETURN FALSE
Following is my dataset
If "GBA_Nbr_GBAccount" column is a string type, it may contains spaces.
You should trim text before comparing. Try this
dv[0]["GBA_Nbr_GBAccount"].ToString().Trim().Equals("52");
You could use Linq to query the datatable or the dataview. For example, assuming your column is of type string:
var condition = yourDataTable.AsEnumerable()
.Any(r => r.Field<string>("GBA_Nbr_GBAccount") == "52");
var condition = yourDataView.Cast<DataRowView>()
.Any(rv => rv.Row.Field<string>("GBA_Nbr_GBAccount") == "52");
If the column was an integer, just change the Field<string> to Field<int> and compare against an integer, not a string
var condition = yourDataTable.AsEnumerable()
.Any(r => r.Field<int>("GBA_Nbr_GBAccount") == 52);
var condition = yourDataView.Cast<DataRowView>()
.Any(rv => rv.Row.Field<int>("GBA_Nbr_GBAccount") == 52);
Example application using string column:
static void Main(string[] args)
{
DataSet dataset = new DataSet();
dataset.Tables.Add(new DataTable("table1"));
dataset.Tables[0].Columns.Add(new DataColumn("Value", typeof(string)));
dataset.Tables[0].Rows.Add("10");
dataset.Tables[0].Rows.Add("52");
DataTable table = dataset.Tables[0];
DataView view = table.DefaultView;
var condition1 = table.AsEnumerable().Any(r => r.Field<string>("Value") == "52");
var condition2 = view.Cast<DataRowView>().Any(rv => rv.Row.Field<string>("Value") == "52");
Console.WriteLine(String.Format("Result querying datatable: '{0}'. Result using dataview:'{1}'", condition1, condition2));
Console.ReadLine();
}
If you are really using a string for the column, check for white spaces and apply a trim if needed.
One way to check for the existence of a specific column in a dataview would be like the following:
if (dv.Table.Columns["Name"] != null)
{
//Name column exists. Add Logic here
}
Use the DataViewManager object instead
it has a DataSet property associated with it and the dataset has all the normal dataset features. So, you can traverse the dataset.tables[index] object...
Hope it helps
Example: dv.DataViewManager.DataSet.Tables[0].Rows[0][1]
Thanks,
Sam
int rowIndex = dv.Find("52");
if (rowIndex == -1) {
Console.WriteLine("No match found.");
}
else {
Console.WriteLine("{0}, {1}",
dv(rowIndex)("GBA_Nbr_GBAccount").ToString(),
dv(rowIndex)("GBA_Nam_GBAccount").ToString());
}
I think that may be the solution to your problem, or at the very least point you in the right direction.

iterate through particular column in a datatable

I am Working in asp.net and c#.
I have a datatable in my application with one column.I want to iterate through that column values and check those values with someother value.please tell me how to do that.I tried it with foreach but its not working.
Code:
foreach (DataRow dr in dt.Rows)
{
int code = Convert.ToInt32(dt.Rows[0]["Code"]);
if (code == pcode)
{
//do something
}
else
{ }
}
Note:
dt is my datatable with column code.I want to compare all values in column code with pcode.
int code = Convert.ToInt32(dr["Code"]);
Although you might want to check for NULL also :)
Inside your loop, access dr, instead of dt.Rows[0].
You are always accessing the first row:
dt.Rows[0]["Code"] // use dr instead of dt.Rows[0]
dt is my datatable with column code.I want to compare all values in
column code with pcode.
So am i right when i assume that you want to compare all values with one variable, if all fields equal this value, a bool variable should be true, otherwise false?
You can use Linq:
var allEqual = dt.AsEnumerable()
.All(r => r.Field<int>("Code") == pcode);
Enumerable.All determines whether all elements of a sequence satisfy a condition.
foreach (DataRow dr in dt.Rows)
{
object o = dr["Code"];
if (o != DBNull.Value) // Check for null
{
int code = Convert.ToInt32(o);
if (code == pcode)
{
//do something
}
else
{ }
}
}

DataTable C# Empty column type

I am trying build a DataTable one row at a time using the following code.
foreach (var e in Project.ProjectElements[hi.FakeName].Root.Elements()) {
index = 0;
object[] obj=new object[count];
foreach (var holdingColumn in names) {
string d = e.Attribute(holdingColumn.Key).Value;
obj[index++] = d;
}
dt.Rows.Add(obj);
}
The problem is the DataTable has types tied to the columns. Sometimes im passing null (or an empty string) in that object index and it is telling me that it cant be converted properly to a DateTime (in this case). My question is what should I default this value to, or is there some way to have the DataTable ignore empty values.
Set the AllowDBNull property of the DataColumn to true, then write
if (String.IsNullOrEmpty(d))
obj[index++] = DBNull.Value;
else
obj[index++] = d;

Categories