This question already has answers here:
How to 'foreach' a column in a DataTable using C#?
(7 answers)
Closed 6 years ago.
I have a DataTable which contains column names and rows. Now as per my requirement I have to get only row value without giving the column names as I have done now.Here is the code.
data = employees.AsEnumerable().Select(row=> new List<string>
{
row.Field<string>("EmployeeName"),
row.Field<string>("Company")
})
In the above code employees is DataTable. How to do it.I have to get the row values into data variable as shown in code.
Update
data = employees.AsEnumerable().Select(row=> new List<string>
{
foreach(DataRow row in employees.Rows)
{
foreach(DataColumn col in employees.Columns)
data.Add(row[col.Ordinal].ToString());
}
})
You could simply use this syntax
data = employees.AsEnumerable().Select(row=> new List<string>
{
row[0].ToString(),
row[1].ToString()
});
Where 0 is the index of the column EmployeeName and 1 is the index of the column Company (if your query is something like SELECT EmployeeName, Company from ....)
But, in my opinion, this is really a step backwards. Using column names preserves your code from the order in which the columns are loaded from the database table.
EDIT
If you want to loop over every row and for every row on every column you could use this code (at this point there is no much sense in using IEnumerable extensions)
With foreach:
foreach(DataRow row in employees.Rows)
foreach(DataColumn col in employees.Columns)
data.Add(row[col.ColumnName].ToString());
// or
// data.Add(row[col.Ordinal].ToString());
With standard loop
for(int r = 0; r < employees.Rows.Count; r++)
for(int c = 0; c < employees.Columns.Count; c++)
data.Add(employees.Rows[r][c].ToString());
maybe you can use that?
var dt = new DataTable();
dt.AsEnumerable().Select(row => new List<string>
{
row.Field<string>(0),
row.Field<string>(1)
});
Related
I have more than 9000 rows and 18 columns in my datagridview. I have to read the columns from an external datatable. If I find a match between column names, I have to copy all values from the datatable column into the datagridview column. My problem is, I cannot iterate over these rows for 18 times for more than 9000 rows and write for every iteration the value in the datagridview cell because it is too slow. Is there any valid alternative?
I add some code below so that you can understand better my question. Here I'm iterating the columns first, then the rows. Sorry for the indentation but I'm having problems in copy paste code on StackOverflow.
dgvMappatura is my dataGridView, dtExcel is my DataTable
foreach (DataColumn col in dtExcel.Columns)
{
if (col.ColumnName.Equals(nome_colonna_origine))
{
foreach (DataRow drExcel in dtExcel.Rows)
{
// some code to add values to datagridview from the datatable column
}
}
}
See if following is faster :
DataTable dt = new DataTable();
foreach (DataRow row in dt.AsEnumerable())
{
var matches = row.ItemArray.Select((x, i) => new { name = x.ToString(), index = i }).GroupBy(x => x.name).Where(x => x.Count() > 1).ToArray();
}
I have an existing datatable called _longDataTable containing data. Now, I want to duplicate each row and in each duplicate of the row, I want to set only the value in the SheetCode column according to a value from a different datatable called values, see code below. For example, the values datatable contains 1, 2 and 3, then I want each row of _longDataTable to be duplicated three times and in each of the duplicated rows, I want the Sheet Code column to have values 1, 2 and 3 respectively. My code now looks like below:
foreach (DataRow sheets in _longDataTable.Rows)
{
for(int k = 0; k < number_of_sheets; k++)
{
var newRowSheets = _longDataTable.NewRow();
newRowSheets.ItemArray = sheets.ItemArray;
newRowSheets["SheetCode"] = values.Rows[k]["Sheet Code"];
//add edited row to long datatable
_longDataTable.Rows.Add(newRowSheets);
}
}
However, I get the following error:
Collection was modified; enumeration operation might not execute.
Does anyone know where this error comes from and how to solve my problem?
you get enumeration error because you are iterating through a collection which is changing in the loop(new rows added to it),
as you said in the comment, you get out of memory exception because you are iterating on the _longDataTable, then you add rows to it, the iteration never reach to end and you will get out of memory exception.
I assume this can help you:
//assume _longDataTable has two columns : column1 and SheetCode
var _longDataTable = new DataTable();
var duplicatedData = new DataTable();
duplicatedData.Columns.Add("Column1");
duplicatedData.Columns.Add("SheetCode");
foreach (DataRow sheets in _longDataTable.Rows)
{
for (int k = 0; k < number_of_sheets; k++)
{
var newRowSheets = duplicatedData.NewRow();
newRowSheets.ItemArray = sheets.ItemArray;
newRowSheets["SheetCode"] = values.Rows[k]["Sheet Code"];
newRowSheets["Column1"] = "anything";
//add edited row to long datatable
duplicatedData.Rows.Add(newRowSheets);
}
}
_longDataTable.Merge(duplicatedData);
do not modify _longDataTable, add rows to the temp table (with the same schema) and after the iteration merge two data tables.
I want to remove unwanted columns from a datatable and arrange the order of the columns in pre-defined order
For example, my table columns are like below,
Col2|Col1|Col3|Test|Test1|Col5|Col4|Some col name|Col6
I want to remove Test, Test1 and Some col name and reorder by datatable into below format
Col1|Col2|Col3|Col4|Col5|Col6
// I need the below columns
List<string> tableColumns = new List<string>();
tableColumns.Add("Col1");
tableColumns.Add("Col2");
tableColumns.Add("Col3");
tableColumns.Add("Col4");
tableColumns.Add("Col5");
tableColumns.Add("Col6");
List<DataColumn> tblColumns = MyDataTable.Columns.Cast<DataColumn>().ToList();
//Remove unwanted columns
foreach (DataColumn col in tblColumns)
{
if (!tableColumns.Contains(col.ColumnName.Trim()))
{
MyDataTable.Columns.Remove(col);
}
}
Now how do I re-order the columns in the below order?
Col1|Col2|Col3|Col4|Col5|Col6
I tried like in the below code, but it fails if all items in tableColumns doesn’t exists in datatable.
Also some times data table column name has some empty space (ex “ Col1”)
foreach (var col in tableColumns)
{
MyDataTable.Columns[col].SetOrdinal(tableColumns.IndexOf(col));
}
Which is the best way to remove unwanted columns and re-arrange the columns?
After you remove the unwanted columns, here is how you can order them:
int index = 0;
foreach (var col in
MyDataTable.Columns
.Cast<DataColumn>()
.OrderBy(x => tableColumns.IndexOf(x.ColumnName))
.ToList())
{
col.SetOrdinal(index);
index ++;
}
This selects the columns from the DataTable, and orders them by their corresponding index in the tableColumns list.
Then it invokes SetOrdinal on each one of them, incrementing the index each time.
I think your columns may have random order like Col2,Col1,Col3. And you want to rearrange and remove the unwanted columns, like Col1,Col2,Col3.
string[] srr = new string[]{"Col2","Col1","Col3","Test","Test1","Col6","Col4","Some col name","Col5"};
DataTable MyDataTable = new DataTable();
foreach(string col in srr)
{
MyDataTable.Columns.Add(col);
}
List<string> arrayNames = (from DataColumn x in MyDataTable.Columns
select x.ColumnName).ToList();
foreach(var col in arrayNames)
{
if(!col.Contains("Col"))
{
MyDataTable.Columns.Remove(col);
}
else
{
int result = Convert.ToInt32(Regex.Match(col.ToString(), #"\d+$").Value);
MyDataTable.Columns[col].SetOrdinal(result-1);
}
}
This will remove the columns like Test,Test1,some col name ie. columns which don't have the word "Col" (change the logic according to your program). Then by using regex it will extract the numbers from column names. ie 1 from "Col1", then rearrange the columns according to it.
I have a datatable has data like this format
........ IVR........
.........IVR........
.........IVR........
.........City1......
.........City1......
.........City1......
.........City2......
.........City2......
.........City2......
I want to take the last row of each value. in order words, the rows that are bold now
The challenge is that i wan these three rows in a datatable. I tried to search on internet but i didn't know what is the name of this feature. could you help me please
You can GroupBy() and then select last row with the help of the Last() method.
var result = from b in myDataTable.AsEnumerable()
group b by b.Field<string>("Your_Column_Name") into g
select g.Last();
DataTable filtered = myDataTable.Clone();
foreach(DataRow row in result)
{
filtered.ImportRow(row);
}
Clone clones the structure of the DataTable, including all DataTable schemas and constraints.
This can be implemented in a simple loop using a Dictionary to hold found rows:
var cRows = new Dictionary<string, DataRow>(StringComparer.InvariantCultureIgnoreCase);
foreach (DataRow oRow in oTable.Rows)
{
var sKey = oRow["KeyValue"].ToString();
if (!cRows.ContainsKey(sKey))
{
cRows.Add(sKey, oRow);
}
else
{
cRows[sKey] = oRow;
}
}
This approach will store the last row for each unique value in the column that you nominate.
To move the selected rows into a new DataTable:
var oNewTable = oTable.Clone();
foreach (var oRow in cRows.Values)
{
oNewTable.Rows.Add(oRow);
}
Clone just clones the structure of the current table, not the rows.
This question already has answers here:
Best way to remove duplicate entries from a data table
(11 answers)
Closed 9 years ago.
Im trying to delete rows from DataTable AllItems with rows from DataTables Items; The purpose of this to get items from DataTable AllItems which are not inside DataTable Items
All these rows Fiiled from same Excel file which contains several columns and are equal.
I have tried using foreach loop:
foreach(DataRow dr in AllItems.Rows)
{
if (Items.Contains(dr))
{
AllItems.Rows.Remove(dr);
}
But I get following error: Table doesn't have primary key.
Does anyone knows how i can delete these rows?
You have a few choices here:
1. Add a Primary Key
you can add a primary key to your data table when creating it.
Assuming you had a column called "Id" then you would do it this way:
AllItems.PrimaryKey = new DataColumn[] { workTable.Columns["Id"] };}
Or, for cases where your primary key is a composite key (multiple columns):
AllItems.PrimaryKey = new DataColumn[] {
workTable.Columns["Id"],
workTable.Columns["Name"] };}
This would then allow Contains to work correctly.
2. Use a DataView
You can use a DataView to filter out the distinct rows;
DataView view = new DataView(AllItems);
DataTable distinctValues = view.ToTable(true, "Column1", "Column2" , ..., "ColumnN");
3. Find Matching Rows using Select
Or you can rely on the Select method to test if a corresponding row exists in the Items DataTable based on a statement that's like a SQL WHEREclause:
List<DataRow> rowsToRemove = new List<DataRow>();
foreach(DataRow allItemRow in AllItems.Rows)
{
if(Items.Select(String.Format("Id = {0}"),
allItemRow.Field<Int32>("Id")).Length == 0)
{
rowsToRemove.Add(allItemRow);
}
}
rowsToRemove.ForEach(x => x.Delete());
AllItems.AcceptChanges();
Note that it's important NOT to remove rows while you are iterating the collection of Rows in AllItems - instead, collect these rows, and remove them afterwards.
4. Filter on the way in
Also note, and I haven't tried it, but, depending on how you are selecting the rows out of Excel, you may be able to use the SQL DISTINCT clause; if you are using ODBC to load data from Excel then you could try filtering at source.
You may try this:
var exceptItems = AllItems.Rows.Cast<DataRow>()
.Except(Items.Rows.Cast<DataRow>(), DataRowComparer.Default)
.ToList();
As an alternative, if you want to keep working with the allItems data table after removing the items rows from it, you may try this (assuming that you have the column Id in both data tables, which uniquely identifies a row per data table):
var exceptItems = AllItems.Rows.Cast<DataRow>()
.Select((i, index) => new { id = i["Id"], index })
.Intersect(Items.Rows.Cast<DataRow>()
.Select((i, index) => new { id = i["Id"], index }))
.ToList();
for (int i = exceptItems.Count()-1; i >= 0; i--)
{
AllItems.Rows.RemoveAt(exceptItems[i].index);
}
Here's a nicer arrangement of the last example above:
AllItems.Rows.Cast<DataRow>()
.Select((i, index) => new { id = i["Id"], index })
.Intersect(Items.Rows.Cast<DataRow>()
.Select((i, index) => new { id = i["Id"], index }))
.OrderByDescending(i => i.index)
.ToList()
.ForEach(i => AllItems.Rows.RemoveAt(i.index));