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;
Related
DataTable dt = new DataTable();
var dr = dt1.Date;
String rr = Convert.ToString(dr);
DataColumn dc1=new DataColumn();
dc1.ColumnName = rr; dt.Columns.Add(dc1);
And if i add datarow after this like
dt.Rows.Add("hello","hello1","hello2");
dataGrid1.ItemsSource = dt.DefaultView;
the data is not displayed in the grid .
If i comment the line
dc1.ColumnName = rr;
the values are displayed properly
But i want the colmn name to be the date that is "dt1" here
pleae note that the dt1 are the date values which is dynamic and it will be incremented in each loop.
like
dt1 = dt1.AddDays(1);
Please help
Without seeing your Xaml for the data grid it's difficult to be sure but I imagine that you've specified a field name for the date column in your xaml.
To resolve this, you'll need to set AutoGenerateColumns=True and let the grid automatically find the field name.
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.
How can I copy 1 data column from 1 data table to a new datatable. When I try to do it, I get the error Column 'XXX' already belongs to another DataTable.?
dataColumn = datatable1.Columns[1];
datatable2 = new DataTable();
datatable2.Columns.Add(dataColumn);
Thanks in Advance
You cannot copy DataColumns. What you'll need to do is create a new DataColumn in the new datatable with the same data type as in the old datatable's column, and then you need to run a FOR loop to bring in all the data from the old datatable to the new datatable.
See the following code. This assumes that the datatables have exactly the same number of rows.
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
dt2.Columns.Add("ColumnA", dt1.Columns["ColumnA"].DataType);
for (int i = 0; i < dt1.Rows.Count; i++)
{
dt2.Rows[i]["ColumnA"] = dt1.Rows[i]["ColumnA"];
}
Also, If the data you are copying are reference types and not value types you might want to see if a .Clone() method is available for the type, or make one yourself. Just doing 'this = that' in the FOR loop will not work on reference types.
You cannot copy a DataColumn. (DataColumns are very tightly coupled with their tables)
Instead, you can add a new column with the same name and datatype.
You might be looking for DataTable.Clone(), which will create a structual copy of an entire table. (With the same schema, but no data)
Just a thought, are your DataTables both in the same DataSet?
If so, you can create a named DataRelation between the columns of two tables (think foreign key).
Then you can add a Calculated DataColumn to your table that has its Expression property set to "Child(RelationName).ColumnName" or "Parent(RelationName).ColumnName" depending on the direction of the relationship.
This will give you the same effect as copying the column, but I believe it only evaluates it lazily. So maybe it will give you what you need.
There is an example here of how this works. The example uses the Sum aggregate function, but you just need to reference the column name and it will duplicate it in your DataTable
myDataSet.Relations.Add(
"Orders2OrderLines",
myDataSet.Tables["Orders"].Columns["OrderID"],
myDataSet.Tables["OrderLines"].Columns["OrderID"]);
ordersTable.Columns.Add("OrderTotal", typeof(decimal), "Sum(Child(Orders2OrderLines).ExtendedPrice)");
HTH
The problem is caused by the c# can not reuse the object instance created and uses it on multiples DataTables. For this it is necessary to create a new object DataCollumn for each loop iteration.
foreach (DataTable table in DATASET.Tables)
{
DataColumn yourDataCollumn = new DataColumn("Name of DataCollumn", typeof(Your data type));
// your logic here
}
Hope it's help...
I used the below to merge two tables using mostly LINQ and only looping through the rows at the end. I wouldn't call it pretty but it does work. Using the join to prevent some of the assumptions listed above.
DataTable tableOne = getTableOne();
DataTable tableTwo = getTableTwo();
var oneColumns = tableOne.Columns.Cast<DataColumn>()
.Select(p => new Column(p.ColumnName, DataType))
.ToArray();
var twoColumns = tableTwo.Columns.Cast<DataColumn>()
.Select(p => new DataColumn(p.ColumnName, p.DataType))
.ToArray();
var matches = (from a in tableOne.AsEnumerable()
join b in tableTwo.AsEnumerable() on a["column_name"] equals b["column_name"]
select a.ItemArray.Concat(b.ItemArray)).ToArray();
DataTable merged = new DataTable();
merged.Columns.AddRange(oneColumns);
merged.Columns.AddRange(twoColumns);
foreach (var m in matches) { merged.Rows.Add(m.ToArray()); }
No looping required , Refer this , Hope this should solve your problem...
DataTable dt = new DataTable();
//fill the dt here
DataTable dt2 = new DataTable();
string[] strCols = {"Column Name to copy"};
dt2 = dt.DefaultView.ToTable("newTableName", false, strCols);
Is it possible to use a wildcard in a DataTable.Select(filter) call if the data type of the column is an Int32?
DataTable table = new DataTable();
DataColumn column = new DataColumn("Name", typeof(String));
DataColumn column = new DataColumn("Age", typeof(Int32));
table.Select("Name like 'b%'); // Works
table.Select("Age like '3%'); // Does NOT work.
This actually works in MySQL, so I just wondered if its possible in a DataTable.
You should be able to convert to a string and then use wildcards:
table.Select("Convert(Age, 'System.String') like '3%');
See http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression.aspx for valid expressions.
Yes but use an asterisk instead of a percentage sign for the wildcard
The syntax for the data table select statement is the same as for a data column expression - see http://msdn.microsoft.com/en-us/library/system.data.datacolumn.expression.aspx for all the supported syntax options
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.