Comparing each column value in DataRow without using for/each loop - c#

Is there a way to achieve the same below output without using for/each loop? (using lambda expression?)
DataRow leftDataRow = GetReferenceDataRow();
DataTable table = GetTableForComparison():
List<NonMatchingValue> listColumnsWithDiscrepancies = new List<NonMatchingValue>();
foreach (DataRow row in table.Rows)
{
for (int index = 0; index < table.Columns.Count; index++)
{
if (leftDataRow[index].ToString() != row[index].ToString())
{
listColumnsWithDiscrepancies.Add(new NonMatchingValue {
FieldSource = leftDataRow.Tables.Columns[index].ColumnName,
FieldTarget = row.Table.Columns[index].ColumnName
ValueSource = leftDataRow[index].ToString(),
ValueTarget = row[index].ToString(),
IsEqual = leftDataRow[index].Equal(row[index])
});
}
}
}
The structure/number of columns of leftDataRow and rows in the table is identical.
// Sample Output:
FieldSource | FieldTarget | ValueSource | ValueTarget | IsEqual
-------------------------------------------------------------------------------
Column1 | Column1 | X | Y | False
Column2 | Column2 | A | A | True

Related

Copy row from datatable to another where there are common column headers

I have two datatables, I am trying to copy row from one table to another, I have tried this. the thing is that my tables are not exactly the same, both tables have common headers, but to the second table have more columns, therefore I need "smart" copy, i.e to copy the row according to the column header name.
d1:
+--------+--------+--------+
| ID | aaa | bbb |
+--------+--------+--------+
| 23 | value1 | value2 | <----copy this row
d2:
+--------+--------+--------+--------+
| ID | ccc | bbb | aaa |
+--------+--------+--------+--------+
| 23 | | value2 | value1 | <----I need this result
but this code:
string rowID=23;
DataRow[] result = dt1.Select($"ID = {rowID}");
dt2.Rows.Add(result[0].ItemArray);
gives:
d2:
+--------+--------+--------+--------+
| ID | ccc | bbb | aaa |
+--------+--------+--------+--------+
| 23 | value1 | value2 | | <---- :( NOT what I need
I think this is your homework, but here you have some simple and not very smart solution:
private DataTable DTCopySample()
{
int cnt = 0;
DataTable dt1 = new DataTable();
dt1.Columns.Add("ID");
dt1.Columns.Add("aaa");
dt1.Columns.Add("bbb");
DataTable dt2 = new DataTable();
dt2.Columns.Add("ID");
dt2.Columns.Add("ccc");
dt2.Columns.Add("bbb");
dt2.Columns.Add("aaa");
dt1.Rows.Add();
dt1.Rows[0]["ID"] = "23";
dt1.Rows[0]["aaa"] = "val1";
dt1.Rows[0]["bbb"] = "val2";
dt1.Rows.Add();
dt1.Rows[1]["ID"] = "99";
dt1.Rows[1]["aaa"] = "val99";
dt1.Rows[1]["bbb"] = "val98";
string colName = string.Empty;
foreach (DataRow row in dt1.Rows)
{
dt2.Rows.Add();
foreach (DataColumn col in dt1.Columns)
{
dt2.Rows[cnt][col.ColumnName] = row[col.ColumnName].ToString();
}
cnt++;
}
return dt2;
}
There are more smart and better solutions, but this is fast-written (2 mins) and works.
Remeber, that you have not specified columns datatypes or anything else, so I assumed there are strings everywhere for creating simple sample.

DataTable.Select() to display summation of records in datatable

In my C# project in a DataTable, I need to sum a few columns and display the aggregated record and I am unable to create filter query for that.
Records like:
|Col1|Col2|Col3|Col4|
| A | X | 10 | 10 |
| A | X | 10 | 20 |
| A | Y | 12 | 12 |
| A | Y | 10 | 10 |
Result will be:
|Col1|Col2|Col3|Col4|
| A | X | 20 | 30 |
| A | Y | 22 | 22 |
I have to use DataTable.Select("filter condition").
var result = (from DataRow s in yourDataTable.Select("filter conditions").AsEnumerable()
group s by new {g1 = s.Field<string>("Col1"), g2 = s.Field<string>("Col2") } into g
select new
{
Col1 = g.Key.g1,
Col2 = g.Key.g2,
Col3 = g.sum(r => r.Field<decimal>("Col3")),
Col4 = g.sum(r => r.Field<decimal>("Col4")),
}).ToList();
And if you want result as DataTable type, you can convert list to DataTable Like below:
var resultAsDataTable = ConvertListToDataTable(result);
public static DataTable ConvertListToDataTable<T>(IList<T> data)
{
PropertyDescriptorCollection props =
TypeDescriptor.GetProperties(typeof(T));
DataTable table = new DataTable();
for (int i = 0; i < props.Count; i++)
{
PropertyDescriptor prop = props[i];
table.Columns.Add(prop.Name, prop.PropertyType);
}
object[] values = new object[props.Count];
foreach (T item in data)
{
for (int i = 0; i < values.Length; i++)
{
values[i] = props[i].GetValue(item);
}
table.Rows.Add(values);
}
return table;
}

How to remove empty values in a DataTable rows and merge

I am trying to figure out a good way to remove empty values from rows and merge row2 to row1, row4 to row2 in a datatable.
DataTable with Empty rows to merge
---------------------
| Column1 | Column2 |
----------------------
ROW1 | XYZ | |
ROW2 | | ABC |
ROW3 | MNQ | |
ROW4 | | PQR |
Final datatable with merged rows
_____________________
| Column1 | Column2 |
----------------------
ROW1 | XYZ | ABC |
ROW2 | MNQ | PQR |
Can somebody help me accomplish this in C#?
Try to create two array that will store a column1 value and column2 value.
In loop go through all datatable rows and insert all not empty rows from column1 to array1 and rows from column2 to array2. Then on the end create new datatable that will have rows taked from array1 and array2.
For example in pseudocode.
var array1;
var array2;
for(var row in datatable)
{
if(row[column1] != null or empty)array1.push(row[column1].value);
if(row[column2] != null or empty)array2.push(row[column2].value);
}
and in the end (first check what array is biger).For example i assuming that array1 is bigger;
var newDatatable;
for(int i=0; i<array1.count; i++)
{
var row = new row;
newDatatable.row[column1].addRowValue(array1[i])
if(array2.count < i){
newDatatable.row[column2].addRowValue(array2[i])
}
}

Grid view Row Data Bound putting data in a particular cell

I have 3 tables Customer, Address and Matching_Customer_Address.
Customer has column Name and Address has column City. They have some other columns as well but I don't need them. The Name and the City column contains this kind of data.
NAME City
---------- -----------
John New York
---------- ----------
Karin Hamburg
--------- ----------
Jona Tokyo
--------- ----------
Martin
Matching_Customer_Address contains the IDs of both tables which have a match between them.
I have a Grid view and I bind this GridView1 with datatable dt. dt is in this format:
Data table dt first column is "Match" and rest of the columns are from Address.City and rows are from Customer.Name.
As Gridview1 is bind with dt so grid view is like this.
Match | New York| Hamburg | Tokyo |
----- | --------| ------- | ------ |
John | | | |
----- | ------- | ------- | ------ |
Karin | | | |
----- | ------- | ------- | ------ |
Jona | | | |
----- | ------- | ------- | ------ |
Martin| | | |
----- | ------- | ------- | ------ |
Now by using the table Matching_Customer_Address I want to put a character "X" in GridView1 cell. I am using RowDataBound event to do this task but I don't know how I should proceed.
I am trying to do
e.Row.Cells[].Text = "X";
I know how to access the Matching_Customer_Address table here But I don't know how to put an X in a particular cell if a match is found. I am very new to C#.
Here is the code to bind data with gridview.
DataTable dt = new DataTable();
SqlDataAdapter da_Customer, da_Address;
DataSet ds_Customer = new DataSet();
DataSet ds_Address = new DataSet();
SqlConnection con;
con = new SqlConnection("Data Source=local;Initial Catalog=Test;Integrated Security=True");
da_Customer= new SqlDataAdapter("Select Name from Customer ", con);
da_Customer.Fill(ds_Customer, "Name");
da_Address = new SqlDataAdapter("Select City from Address ", con);
da_Address .Fill(ds_Address, "City");
int lengthofAddress = ds_Address.Tables[0].Select("City is not null").Length;
string[] getCols_City = new string[lengthofAddress];
int lengthofCustomer = ds_Customer.Tables[0].Select("Customer is not null").Length;
string[] getRows_Customer = new string[lengthofCustomer];
//added first column of dt.
dt.Columns.Add(new DataColumn("Name", typeof(string)));
// This loop is getting rows from table City and adding them as column of dt.
for (int x = 0; x < (lengthofAddress); x++)
{
string mystring = (ds_Address.Tables[0].Rows[x]["City"].ToString());
getRows_Customer[x] = mystring;
dt.Columns.Add(getRows_Customer[x]);
}
// This loop is getting rows from table Customer and adding them as Rows of dt.
for (int x = 0; x < (lengthofCustomer); x++)
{
getRows_Customer[x] = (ds_Customer.Tables[0].Rows[x]["Name"].ToString());
dt.Rows.Add(getRows_Customer[x]);
}
GridView1.DataSource = dt;
GridView1.DataBind();
Aspx Code is here :
<asp:GridView ID="GridView1" runat="server" BackColor="White" BorderColor="#3366CC"
BorderWidth="1px" CellPadding="4" Font-Names="Arial" Font-Size="Small" Width="100%"
BorderStyle="None" OnRowEditing="GridView1_RowEditing" onrowdatabound="GridView1_RowDataBound" >
<HeaderStyle CssClass="GridviewScrollHeader" />
<RowStyle CssClass="GridviewScrollItem" />
<PagerStyle CssClass="GridviewScrollPager" />
</asp:GridView>
Put the logic to find matches into the data table building logic that you posted, like this:
// This loop is getting rows from table Customer and adding them as Rows of dt.
for (int x = 0; x < (lengthofCustomer); x++)
{
// Build the pieces of data for your row here
// Name
// Loop through each city
for (int y = 0; y < (lengthofAddress); y++)
{
// Determine if each city is a match or not,
// if so then put "X" in that row's cell here
}
}
Now when you bind your grid with the data table, you will not need to handle the RowDataBound event, because the X will be in the right cell(s) already.
UPDATE:
To put values into a new data table row, you need to create a new row and then apply the cell values via the index of the row, like this:
DataRow row;
// Create new DataRow objects and add to DataTable.
for(int i = 0; i < 10; i++)
{
row = YourDataTable.NewRow();
row["Name"] = theName;
// Loop through each city
for (int y = 0; y < (lengthofAddress); y++)
{
// Determine if each city is a match or not,
// if so then put "X" in that row's cell here
if(match)
{
row[y+1] = "X";
}
}
YourDataTable.Rows.Add(row);
}
UPDATE 2:
If the rows for each person in the match column already exist, then loop through each row like this:
foreach(DataRow row in TheTable.Rows)
{
// Loop through each city
for (int y = 0; y < (lengthofAddress); y++)
{
// Determine if each city is a match or not,
// if so then put "X" in that row's cell here
if(match)
{
row[y+1] = "X";
}
}
}

How to learn and show gridview rows includes "?" data

There is a gridview which includes 6 columns. I bound the data to some columns. For example, 3 and 5 th columns have data.
I want to show There is 2 data in first columns if there is 3 data in separate columns I want to write 3 in the first column.
Column1 | Column2 | Column3 | Column4 | Column5 | Column6
2 | | stack | | overflow |
4 | sta | ck | over | flow |
1 | | | | | stcvrflw
How can I do it?
I populate the grid
e.Row.Cells[i].Text = html;
and html variable includes < table>.... some values come from db.
After you populate the grid:
for (int i = 0; i < gv.Rows.Count; i++)
{
valueCount=0;
for (int j = 1; j < gv.Columns.Count; j++)
{
if (gv.Rows[i].Cells[j].ToString()!="")
valueCount++;
}
gv.Rows[i].Cells[0].Text =valueCount.ToString();
}

Categories

Resources