I have one asp.net datatable and I want to databind into two asp.net datalists, so I though to slice the datatable rows in two datatables both the same size if even .
Use the Take LINQ extension method to specify how many items to use.
And the Skip to jump over if needed.
var half = myList.Take(myList.Count / 2);
If you are slicing by rows, you can simply create a copy of your original data table, find a suitable half way point, and just import the rows into the copy, while deleting them from the original.
Something like the following should work:
DataTable originalTable = new DataTable();
//Load the data into your original table or wherever you get your original table from
DataTable otherTable = originalTable.Copy(); //Copys the table structure only - no data
int rowCount = originalTable.Rows.Count;
int wayPoint = rowCount / 2; //NB integer division rounds down towards 0
for(int i = 0; i <= wayPoint; i++)
{
otherTable.ImportRow(originalTable.Rows[i]); //Imports (copies) the row from the original table to the new one
originalTable.Rows[i].Delete(); //Marks row for deletion
}
originalTable.AcceptChanges(); //Removes the rows we marked for deletion
Related
I have a dataset that looks like the image. I'm trying to filter by table and get all the columns next to it and compare them against other datasets
This dataset has tables named table 1 and table 2 and when they're selected they look like the picture below. It shows the columns and I need to compare those columns against the rows from the matching table in the first dataset
I've looked at dataview but that would be a lot of work and I'm very inexperienced. I'm trying to find a way to implement a foreach loop that'll get the name of the table in the first dataset and then compare the rows in it against the columns inside the datatable in the second dataset that matched the table name from the first dataset.
Without knowing more about these DataSets (like do they have primary keys, the data types of the columns, the number of rows in each table, etc), I can only provide limited help. The following example tries to be as general as possible and avoid some basic problems:
DataSet ds1 = <<fetch dataset1>>;
DataSet ds2 = <<fetch dataset2>>;
foreach (DataTable tbl1 in ds1.Tables)
{
if (ds2.Tables.Contains(tbl1.TableName))
{
DataTable tbl2 = ds2.Tables[tbl1.TableName];
List<string> commonColumnNames = new List<string>(tbl1.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Intersect(tbl2.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
int maxRows = Math.Min(tbl1.Rows.Count, tbl2.Rows.Count);
for (int r = 0; r <= maxRows; r++)
{
foreach (string colName in commonColumnNames)
{
if (tbl1.Rows[r][colName] != tbl2.Rows[r][colName])
{
// Different value
}
}
}
}
}
Update 1: I've added comments to the following example to explain step-by-step what this code is doing. As I try to say before, since I didn't know much about your data, I had to put in extra code. This extra code is for things like: 'Does the table ABC exist in both DataSets?', 'Do the two tables have the same columns in them?', 'Do the tables have the same number of rows in them?'. Your original question did not have this information, so I made this code a little more robust to handle those unknowns.
DataSet ds1 = <<fetch dataset1>>;
DataSet ds2 = <<fetch dataset2>>;
// Loop through all of the tables in the 1st DataSet
foreach (DataTable tbl1 in ds1.Tables)
{
// If the 2nd DataSet has a table with same name as the one from the 1st DataSet
if (ds2.Tables.Contains(tbl1.TableName))
{
DataTable tbl2 = ds2.Tables[tbl1.TableName];
// Create a list of column names that the two tables have in common.
// We will only compare the values in these two tables, in this set of matching column names.
List<string> commonColumnNames = new List<string>(tbl1.Columns.Cast<DataColumn>().Select(c => c.ColumnName).Intersect(tbl2.Columns.Cast<DataColumn>().Select(c => c.ColumnName)));
// Before we start comparing the rows in the two tables, find out which one has the fewer number of rows in it.
int maxRows = Math.Min(tbl1.Rows.Count, tbl2.Rows.Count);
// If the tables have a different number of rows, then we will only compare the set of rows numbered 0-to-MinRowCount
for (int r = 0; r <= maxRows; r++)
{
// For each row, compare the values of common columns
foreach (string colName in commonColumnNames)
{
if (tbl1.Rows[r][colName] != tbl2.Rows[r][colName])
{
// Different value
}
}
}
}
}
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 wish to create an array of DataTables with the same columns. Is there a way to set the schema of all the DataTables in one shot instead of running through each DataTable and add the columns?
No, you can't do this without a loop. Even if there was a method like DataSet.CloneManyTables it would use a loop for you. A LINQ solution would also use a loop. So use following:
You can use DataTable.Clone, for example with 100 clone tables:
for (int i = 1; i <= 100; i++)
{
DataTable tClone = tSource.Clone(); // tSource is your source-table
tClone.TableName = $"{tClone.TableName}_{i + 1}";
ds.Tables.Add(tClone); // ds is your DataSet
}
The columns can have the same names but the table-name must be unique.
Background
I have a set of numbers between 1000-9999 split between two data tables both with same the Schema. One data table's schema is then cloned, and then filled with the rows from both of the original tables. This third new data table is then displayed in a datagridview.
Question
How could I then highlight the rows in the datagridview that contain rows from the first data table?
Code
private void combineTables()
{
bothIdsTbl = UsedIdsTbl.Clone();
dataGridView3.DataSource = bothIdsTbl;
for (int i = 0; i <= UnUsedIdsTbl.Rows.Count - 1; ++i)
{
bothIdsTbl.ImportRow(UnUsedIdsTbl.Rows[i]);
}
for (int i = 0; i <= UsedIdsTbl.Rows.Count - 1; ++i)
{
bothIdsTbl.ImportRow(UsedIdsTbl.Rows[i]);
}
dataGridView3.Sort(this.dataGridView3.Columns["stationid"], ListSortDirection.Ascending);
}
The best solution would be the following:
Add a "flag" column to 3rd table before filling it,
Put in that column a value indicating wheteher the row was imported or not from 1st table.
Use the CellFormatting event of the DataGridView to change
cells backcolor according to the flag column.
You can use a command named merge to combine the two datatables.
If this data came from a database you may consider a union query or any other option to combine the data or obtain all the data in one call.
I cannot get my dataGridView to update with all the tables in the dataSet. I just get one row in the dataGridView after I try to populate it.
I call this to fill my dataSet:
DataTable table = new DataTable(DateTime.Now.ToString());
table.Columns.Add("c1");
table.Columns.Add("c2");
table.Columns.Add("c3");
table.Columns.Add("c4");
table.Columns.Add("c5");
table.Columns.Add("c6");
table.Columns.Add("c7");
table.Rows.Add("s1", "s2", "s3", "s4", "s5", "s6", "s7");
dataSet1.Tables.Add(table);
dataSet1.WriteXml("MyData.xml");
The data is written fine, but if I try to read it with this I only get one row populated, even if there's multiple entries in the dataSet.
dataSet1.ReadXml("MyData.xml");
MessageBox.Show((dataSet1.GetXml()));
I get the message with the data in the correct format, with the correct number of entries.
dataGridView2.AutoGenerateColumns = true;
int i2 = 0;
while (i2 < dataSet1.Tables.Count)
{
dataGridView2.DataSource = dataSet1.Tables[i2];
i2++;
}
After this it will only show one row and not the amount of tables. The dataSet1.Tables.Count >= 2, but still only get 1 row.
Edit: It seems that each time I call this line:
dataGridView2.DataSource = dataSet1.Tables[i2];
It is deleting the previous row. Is there any way to append the row instead?
You only created one table in the data set, so your while statement only executes once:
while (i2 < dataSet1.Tables.Count)
{
...
}
Count = 1 (number of tables) because you only called dataSet1.Tables.Add(table); one time.
dataSet1.WriteXml("MyData.xml") is only writing out the schema for that single table. So reading it back in will only read back in a single table's worth of schema.
The following code appears to count the number of tables in the dataset:
while (i2 < dataSet1.Tables.Count)
Try pointing this to the table:
dataSet1.Tables["Yourtable"].Count