DataTable expression refering to other DataTable column - c#

I have 2 DataTables, DT1 and DT2.
DT1 has columns A1, B1 and DT2 has columns A2, B2.
I'd like to add an expression to A1like A1 = A2 + B2
Is this possible to do without joining or merging the 2 DataTables, this is similar to the way spreadsheets operate?.
Is there any other way to do this, any other data structures or techniques apart from DataTable that would get this done?.
I see that a DataTable won't be able the deduce from a string the tables that the columns belong to?
Is it possible that we can add these 2 DataTables to a DataSet and then do the expression referring to tables present in the DataSet.
Edit:
I have used addition as an example however the expressions can have multiple combinations of math and logic operators and sometimes basic math functions.

See code below
DataTable dt1 = new DataTable();
dt1.Columns.Add("ID", typeof(string));
dt1.Columns.Add("A1", typeof(int));
dt1.Columns.Add("B1", typeof(int));
DataTable dt2 = new DataTable();
dt2.Columns.Add("ID", typeof(string));
dt2.Columns.Add("A2", typeof(int));
dt2.Columns.Add("B2", typeof(int));
DataSet ds = new DataSet()
ds.Tables.Add(dt1);
ds.Tables.Add(dt2);
foreach(DataRow row in dt1.AsEnumerable())
{
DataRow match = dt2.AsEnumerable().Where(x => x.Field<string>("ID") == row.Field<string>("ID")).First();
row["A1"] = match.Field<int>("A2") + match.Field<int>("B2");
}

Related

How to add column to datatable from another datatable

I have two data tables dt1 and dt2, both share a common column. How to map the common column and add a new column with data to data table dt1.
DataTable dt1=new DataTable();
DataTable dt2=new DataTable();
sqlDataAdapter da1=new sqlDataAdapter("select col1,col2,col3,col4 from table",connection);
dataset ds1=new dataset();
da1.fill(ds);
dt1=ds.tables[0];
similarly for dt2 the select statement is "select col1,somecol from sometable" rest is the same as dt1.
for dt1 the output is: and the output for dt2
col1 col2 col3 col4 col1 somecol
1 2 3 4 1 true
2 5 6 ... 2 false..
i tried like below:
datatable dtTotal=new datatable();
dtTotal=dt1.clone();
foreach(datacolumn col in dt2.columns)
{
if(col.columnname=="somecol")
{
dtTotal.columns.add("somecol");
dtTotal.columns["somecol"].Datatype=col.Datatype;
}
}
foreach(datarow dr in dt1.rows)
{
dtTotal.importrows(dr);
}
//here a column is added but i don't understand how to import data into that column
I want to have a outpu like below:
col1 col2 col3 col4 somecol
1 2 3 4 true
2 5 6 7 false...
I cannot write a simple join while selecting the the data itself, because the dt2 data is coming from more complex calculations. so I have to do it at datatable level only.
if number of rows in dt1 doesnt match with number of rows in dt2 then dt2 should be added new rows with default value false.
You can use the DataTable.Merge method. The command dt1.Merge(dt2) adds to dt1 the additional columns and the additional data records from dt2. The data from dt2 will overwrite the data from dt1 that share the same primary key value and the same column name.
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
// Fill the data tables
...
// Set the default value for boolean column
dt2.Columns[4].DefaultValue = false;
// Set the primary keys
dt1.PrimaryKey = new DataColumn[] { dt1.Columns[0] }; // Use the appropriate column index
dt2.PrimaryKey = new DataColumn[] { dt2.Columns[0] }; // Use the appropriate column index
// Merge the two data tables in dt1
dt1.Merge(dt2);

Comparing two datatables in C# and finding new, matching and non-macting records

I have two data tables, Datatable1 and Datatable2. Datatable1 is subset of the other. I want to find out which rows are new, which of them are matching and which of them non-matching. Want to add a new row in Datatable1 with values - new, matching, and non-matching. Please suggest an optimized way to do this.
For Example:
Datatable1:
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name1", typeof(string));
table.Columns.Add("Name2", typeof(string));
//New
table.Rows.Add(25, "Ciya", "David");
table.Rows.Add(51, "Kiya", "Cecil");
//Matching
table.Rows.Add(50, "Bina", "Cecil");
//Non matching
table.Rows.Add(21, "Riya", "Janet");
table.Rows.Add(10, "Rita", "Christoff");
Datatable2:
DataTable table = new DataTable();
table.Columns.Add("ID", typeof(int));
table.Columns.Add("Name1", typeof(string));
table.Columns.Add("Name2", typeof(string));
table.Rows.Add(10, "Lisa", "Christoff");
table.Rows.Add(21, "Combivent", "Janet");
table.Rows.Add(50, "Bina", "Cecil");
You can try with the Linq methods which are available for Enumerable types like Intersect, Except. Here is an example of doing this.
// Get matching rows from the two tables
IEnumerable<DataRow> matchingRows = table1.AsEnumerable().Intersect(table2.AsEnumerable());
// Get rows those are present in table2 but not in table1
IEnumerable<DataRow> rowsNotInTableA = table2.AsEnumerable().Except(table1.AsEnumerable());

Changing the value of datatable expression column

I need to set a column's value in a datatable as the sum of other two columns in a datatable.I tried expression column and is working fine . But the problem is that the value of expression column is not getting updated always.Suppose A,B are two columns in the datatable and the sum of these two columns should be shown in Column 'C'.When when the value of B is changed then the value of columns 'C' is also getting changed.But not when column 'A' is changed
DataTable dt1 = new DataTable();
dt1.Columns.Add("A", typeof(decimal));
dt1.Columns.Add("B", typeof(decimal));
dt1.Columns.Add("C", typeof(decimal), "A+B");
myGridView.Datasource = dt1;
This is an educated guess without seeing your code but it seems as though if you are using Compute then you quite possibly shouldn't use an expression column for this, rather you should use a DataColumn... Taken from here
"If you must perform an operation on two or more columns, you should create a DataColumn, set its Expression property to an appropriate expression, and use an aggregate expression on the resulting column. In that case, given a DataColumn with the name "total", and the Expression property set to this: "Quantity * UnitPrice"
Should go like this:
DataTable dt1 = new DataTable();
dt1.Columns.Add("A", typeof(decimal));
dt1.Columns.Add("B", typeof(decimal));
dt1.Columns.Add("C", typeof(decimal));
foreach (DataRow dr in dt1.Rows)
{
dr[2] = Convert.ToDecimal(dr[0]) + Convert.ToDecimal(dr[1]);
}
myGridView.Datasource = dt1;

Adding column wise data in datatable

I am trying to add column wise data in C#, for e.g.
I have four columns in datatable i.e. No, productoriginal, productmedium, productmedium and productlarge.
first i want to fill ABC then i want to No then Product then productoriginal then productmedium and productlarge
below is my code
DataTable dt = new DataTable();
dt.Columns.Add("No", typeof(Int));
dt.Columns.Add("productoriginal", typeof(string));
dt.Columns.Add("productmedium", typeof(string));
dt.Columns.Add("productlarge", typeof(string));
how do i proceed further ?
If you're looking to add rows to the DataTable, there is a good example on MSDN, but the basics of it is this:
DataRow row = dt.NewRow();
row["No"] = "Value for No here";
row["productoriginal"] = "Value for productoriginal here";
dt.Rows.Add(row);
Take a look into MSDN here.
As mentioned, this is just an example, I'm sure you can amend it as you need to.

row headers on a datatable - to be displayed in a datagridview

Is there anyway to store row header information in a datatable so that when i bind it to a datagridview, it will automatically display both the column and row headers in c#?
Linqpad Demo-Program
As far as i understood you would like to add the column name as values into the datatable / the datagridview. The following is a Linqpad-Program you can easily copy paste into Linqpad to play around. The code adds the column-names to the first row to the datatable. You can easily bind this datatable to a gridview - but beware that each column of the datatable must be of type string.
void Main()
{
GetDataTable().Dump();
}
public DataTable GetDataTable()
{
var dt = new DataTable();
dt.Columns.Add("Id", typeof(string)); // dt.Columns.Add("Id", typeof(int));
dt.Columns["Id"].Caption ="my id";
dt.Columns.Add("Name", typeof(string));
dt.Columns.Add("Job", typeof(string));
dt.Rows.Add(GetHeaders(dt));
dt.Rows.Add(1, "Janeway", "Captain");
dt.Rows.Add(2, "Seven Of Nine", "nobody knows");
dt.Rows.Add(3, "Doctor", "Medical Officer");
return dt;
}
public DataRow GetHeaders(DataTable dt)
{
DataRow dataRow = dt.NewRow();
string[] columnNames = dt.Columns.Cast<DataColumn>()
.Select(x => x.ColumnName)
.ToArray();
columnNames.Dump();
dataRow.ItemArray = columnNames;
return dataRow;
}
Update 2019-06 with additional explanation and alternative code
The method GetHeaders is not the simplest option to get the headers.
Previoulsy the extension method Cast<TResult>(IEnumerable) was used on the DataColumnCollection-Class An alternative would be to just iterate over the collection - this what is done In GetHeadersNew T
public DataRow GetHeadersNew(DataTable dt)
{
DataRow row = dt.NewRow();
DataColumnCollection columns = dt.Columns;
for (int i = 0 ;i <columns.Count ;i++)
{
row[i] = columns[i].ColumnName;
}
return row;
}
This is likely more efficient because less objects and methods are involved.
As long as you can create them with the code based on the data in the row I would just add them at run time using c#. Add a column to the datatable and run through it with a foreach loop. As long as there are not too many rows this code will execute very quickly:
DataTable dt = new DataTable();
// code here to get your datatable
dt.Columns.Add("rowheader");
foreach (DataRow r in dt.Rows)
{
r["rowheader"] = "my nice row header";
}
Then output the new column rowheader as the first cell in the grid.
Another solution is to use the sql query to return an 'extra' column in the result set. for example:
Select *, 'my nice row header' as rowheader from myTable
In this way you make SQL do all the work.

Categories