How to remove more DataTable Columns using C#.Net? - c#

I have One DataTable may have more Columns. But "NetAmount", "TotalAmount", "Destination" are the DataTable Columns which always present in the DataTable.
Here I want to Remove the three Columns such as "NetAmount", "TotalAmount" and "Destination" from the DataTable and to take the other column values in the DataTable.
I tried like the below and get the Desired Output.
dtAttribute.Columns.Remove("NetAmount"); //dtAttribute is the Main DataTable
dtAttribute.Columns.Remove("TotalAmount");
dtAttribute.Columns.Remove("Destination");
DataTable dtItem = dtAttribute.Copy();
But it looks like very childish and lengthy. Is there any other method to do? Please give suggestions.

There's nothing wrong with your code (except that you are copying the table after removing the columns -- are you sure that this is what you want?).
If you want something more abstract (instead of repeating the same line again and again), you might consider removing the columns in a loop:
var dtItem = dtAttribute.Copy(); // if you want to keep a copy of the original table
var toRemove = new string[] {"NetAmount", "TotalAmount", "Destination"};
foreach (col in toRemove)
dtItem.Columns.Remove(col);

Instead of removing the columns, how about not putting them in the DataTable in the first place?

First select columns which you want to remove, then remove them
List<string> toRemove = dt.Columns.Cast<DataColumn>().Where(c => c.ColumnName.StartsWith("ExtraColumn")).Select(c => c.ColumnName).ToList();
foreach (var col in toRemove) dt.Columns.Remove(col);

Related

How to Merge rows data From DataTable in C#?

How to Merge rows data From DataTable in C#?
I think that this is a good use case for the LINQ Group clause. You can start with something like this:
var rowGroups = dataTable.Rows.GroupBy(row =>
new {RecptNo = row["recpt_no"], Test = row["Test"]});
foreach(var group in rowGroups)
{
//Here "group" is a collection of rows with the same rectp_no and test. Process as required.
//You could also check group.Key.RecptNo and group.Key.Test here if necessary.
}
Here's a link of that relates to your question. Hope it helps.
How to merge rows in a DataTable when data in multiple columns match?

Use DataGridView.SelectedRows as DataSource for another DataGridView

I want to use the user-selected rows from one DataGridView as the DataSource for a second DataGridView. Note both DataGridViews will have identical columns.
Obviously I can iterate over the selected rows, obtain the key values, and re-query the database for a List to use as the DataSource of the 2nd grid, but that seems lame.
Surely there is an elegant way of simply re-using the SelectedRows collection as a DataSource?
You cannot directly set collection of DataRow as datasource, you can read more details from MSDN
How about doing (bit) traditional way?
var dt = ((DataTable)dataGrid1.DataSource).Clone();
foreach (DataGridViewRow row in dataGrid1.SelectedRows)
{
dt.ImportRow(((DataTable)dataGrid1.DataSource).Rows[row.Index]);
}
dt.AcceptChanges();
dataGrid2.DataSource = dt;
Another way to do this using CopyToDataTable method.
DataTable dtable2;
DataRow[] rowArray = dataGridView1.SelectedRows;
If !(rowArray.Length == 0 )
{
dTable2 = rowArray.CopyToDataTable();
}
dataGrodView2.DataSource = dTable2;
Thanks for your replies. Seems there isn't a very simple way.
I did it this way:
MyDatGridView.SelectedRows.Cast<DataGridViewRow>().Select(dgvr => (int)dgvr.Cells[0].Value).ToList());
Then I tried to use the resulting List with a .Contains in a .Where clause.

Delete a specific row from datatable

I am trying to delete a specific row from datatable. When adding the last row, I need to delete the yellow colored rows. It is very easy to Select from a datatable like below
DataRow[] dr = dt.Select("STOK_KODU='HAMMADDE_2'");
I was wondering if there is a way like below to delete ??? Or would you advice an easy way to delete a rows from datatable?
dt.Delete("STOK_KODU='HAMMADDE_2'");
One way is to recreate the table with the rows you want to keep:
dt = dt.AsEnumerable()
.Where(row => row.Field<string>("STOK_KODU") != "HAMMADDE_2")
.CopyToDataTable()
The other is to use DataRowCollection.Remove:
DataRow[] rowsToRemove = dt.Select("STOK_KODU='HAMMADDE_2'");
foreach (var rowToDelete in rowsToRemove)
dt.Rows.Remove(rowToDelete);
The second approach is more efficient if you want to delete few rows and the table is large. The first approach using LINQ is more powerful since you can use any code but it can be less efficient.
You can access the Rows collection of the DataTable:
foreach (var row in dr)
dt.Rows.Remove(row);
try this ::
DataRow[] rows;
rows=dt.Select("STOK_KODU='HAMMADDE_2'");
foreach(DataRow r in rows)
r.Delete();
Deleting rows from an in memory DataTable object is really easy
dt.Select("STOK_KODU='HAMMADDE_2'").AsEnumerable().ToList().ForEach(x => x.Delete());
However you should consider that the Delete method simply marks the RowState to Deleted, but the rows are still in the DataTable.Rows collection. To really remove them you need to call
dt.AcceptChanges();
without this call, if you loop over the datatable rows collection, you need to check the RowState to avoid an error message stating that you cannot access the information of a deleted row
foreach(DataRow r in dt.Rows)
{
if(r.RowState != DataRowState.Deleted)
Console.WriteLine(r[0].ToString());
}

Better way to filter DataTable

I currently have a DataTable with the following columns: Date, X1, Y1, Z1, X2, Y2, Z2... Xn, Yn, Zn.
When populated, Date ALWAYS has a value, and X/Y/Z1 to X/Y/Zn can be DBNull, a string, or an int. If the entire row with the exception of Date, is DBNull, i would like to remove that particular row.
I am currently doing an exhaustive search, looping through each row with a for loop, and then with a nested for loop, checking each cell, if i do not find any data (ie. only dbnull's), i then call RemoveAt, and reset the outer loop to start at zero again.
Is there a better/less hacky way of performing this operation? The initial building of the datatable cannot be modified, this must be something that happens post building.
If I understand correctly, you want to remove a row if all columns has DbNull.Value.
Try the following to do that.
DataTable table = new DataTable();
string[] columns = table.Columns.Cast<DataColumn>()
.Select(x => x.ColumnName)
.Skip(1)//skip to ignore first column
.ToArray();
Method1:
Remove all invalid rows
var invalidRows = table.AsEnumerable()
.Where(x => columns.All(c => x.Field<object>(c) == DBNull.Value))
.ToArray();
foreach (var row in invalidRows)
{
table.Rows.Remove(row);
}
Method2: take only valid rows and make new DataTable as suggested my #Tim in comments to improve performance when you have many invalid rows
var newTable = table.AsEnumerable()
.Where(x => columns.Any(c => x.Field<object>(c) != DBNull.Value))
.CopyToDataTable();
ATTENTION : THESE ARE MY EXAMPLES>>NOT EXCATLLY FOR YOUR TABLE>>>SO CHANGE IT FOR YOURSELF
The Main Help is Here >> Help
And Then
Way one :
dtData.Select("ID=1 AND ID2=3");
Way two :
GridFieldDAO dao = new GridFieldDAO();
//Load My DataTable
DataTable dt = dao.getDT();
//Get My rows based off selection criteria
DataRow[] drs = dt.Select("(detailID = 1) AND (detailTypeID = 2)");
//make a new "results" datatable via clone to keep structure
DataTable dt2 = dt.Clone();
//Import the Rows
foreach (DataRow d in drs)
{
dt2.ImportRow(d);
}
//Bind to my new DataTable and it will only show rows based off selection
//criteria
myGrid.DataSource = dt2;
myGrid.DataBind();
And The best Way is :
DataTable tblFiltered = table.AsEnumerable()
.Where(row => row.Field<String>("Nachname") == username
&& row.Field<String>("Ort") == location)
.OrderByDescending(row => row.Field<String>("Nachname"))
.CopyToDataTable();
May be this will help you. Try this
var ordered = yourdatatable.AsEnumerable().Where(x => x.Field<DateTime>("ColumnName") != null);
if (ordered.Count() > 0)
{
yourdatatable= orderedCopyToDataTable();
}
you can do the same for other columns as well.
Or
Why don't you check for the null values in your query. check for ISNULL(columnName, value) As ColumnName. Check more details here
You can use this little Linq query:
var columnsWithoutDate = table.Columns.Cast<DataColumn>().Skip(1);
table = table.AsEnumerable()
.Where(row => columnsWithoutDate.Any(col => !row.IsNull(col)))
.CopyToDataTable();
Skip(1) returns all columns but the first, so your date column is excluded. The Where enumerates all DataRows in the table and takes all rows with at least one non-null field(see:DataRow.IsNull(column)). Finally CopyToDataTable creates a new DataTable.
I would go for something like this:
var test = from row in table.AsEnumerable()
where (!row.IsNull("col1") || !row.IsNull("col2"))
select row;
//option1
DataTable dt = test.CopyToDataTable<DataRow>();
//option2
DataTable dt2 = new DataTable();
dt2.Columns.Add("col1", typeof(String));
dt2.Columns.Add("col2", typeof(Int32));
foreach (var v in test)
{
DataRow dr = dt2.NewRow();
dr["col1"] = v.Field<String>("col1");
dr["col1"] = v.Field<Int32>("col2");
dt2.Rows.Add(dr);
}
Did you try using RowFilter of DataTable?
DataTable dt = GetData();
//set the filter
dt.DefaultView.RowFilter = "----your filter----";
//then access the DataView
foreach (DataRowView drv in dt.DefaultView)
{
//you can also get a row from rowview
DataRow dr = drv.Row;
}
Check this documentation, they also explain how to handle null values in filters.
http://msdn.microsoft.com/en-us/library/system.data.dataview.rowfilter.aspx
You can also use Select() method with same filter, refer the below answer there is a good comparison on both approach.
DataView.RowFilter Vs DataTable.Select() vs DataTable.Rows.Find()
I would not suggest using AsEnumerable() approach, though looks like simple code but it is just like doing a foreach loop on rows and having IF conditions.
DataTable filter approach should be faster than AsEnumerable() (I am not sure, but I am assuming this because DataTable is .net's powerful data structure to handle tabular data)
modified answer:
myDataTable.AsEnumerable().Where(a => a.ItemArray.Count(b=>b != DBNull.Value)==1).ToList().ForEach(row => dataTable.Rows.Remove(row));
I checked, it works.
EDIT:
in response to #Tim Schmelter comment:
1 . you need myDataTable.AsEnumerable() in C#
If you have a strongly typed DataTable, you do not. I assumed it's the case, since OP says:
The initial building of the datatable cannot be modified, this must be
something that happens post building.
Maybe I did't understand what he meant (my English sometimes fails me)
2 . count the non-null fields is incorrect since a string can be null
which is not the same as if it is DBNull.Value(also according OP's
specifications)
You are probably right. If OP says he only wants DBNull, the second condition should be removed (it's a bad habit of mine to check for null just in case)
3 . ToList creates another List which is redundant
Yes. And if there's no ToList(), ForEach() can't be used. The old fashioned foreach can be used instead, or beter for loop (since foreach doesn't like when you try to modify collection inside it). Still you have to keep your result in some way.
4 . DataRow.Delete does it not remove from the table what is desired,
but it flags it as deleted for a DataAdapter(OP's has not mentioned
that he's using one, it is also not desired).
Thank you for pointing that out.

How to remove rows from huge data table without iterating it?

I have a DataTable available with me which contains thousands of rows. There is a column called EmpID which is containing '0' for some of the rows. I want to remove them from my current DataTable and want to create a new correct DataTable. I cannot go row by row checking it since it contains huge amount of data. Give me a suggestion to overcome this problem.
the best way would be to filter it at source (if possible) - so if you are creating it from a db, exclude all 0 values in your sql query itself using a where
starting .net 2.0, ms enhanced the filtering logic on the datatable to a great extent. so if you used the dataview (on top of your datatable) and added the where clause in there and added some sort of runtime indexes on this field, it would give you the desired results without looping over all records
You can use DataTable.Select("EmpID <> 0"). This will return an array of DataRows which you can create your new DataTable from if required.
Isn't it possible to first select the rows with EmpID = 0 and then iterate over these only ?
DataTable newTable = new DataTable();
foreach (DataRow dr in oldTable.Select("EmpID = '0'")) {
newTable.Rows.Add(dr);
oldTable.Rows.Remove(dr);
}
You can try
DataRow[] temp=
table.Select("EmpID ='0'");
foreach(DataRow dr in temp)
{
table.Rows.Remove(dr);
}
table.acceptchanges();

Categories