Im looking to get a column and all its row data from a DataTable object then create a new column in another data table and append it with the new column and its rows. The issue I keep encountering is the row data will come out, as will the column names, but all of the rows are appended to the same column, I'm sure im missing something obvious, infact I know I am! Any help is greatly appriciated.
void GetColumns()
{
// add the columns to the new datatable
foreach (int i in mapValues)
{
SplitData.Columns.Add(i.ToString());
}
// map values contains the index numbers of my target columns
foreach (int x in mapValues)
{
foreach (DataRow row in OrigData.Rows)
{
SplitData.Rows.Add(row[mapValues[LocalIndex]]);
}
LocalIndex++;
}
}
The DataRow.Add overload that you are using is the params one, so you are just putting your orig column data in the first column of the new DataTable.
You probably want something like:
DataRow newRow = SplitData.NewRow(); // gets a new blank row with the right schema
newRow[x.ToString()] = row[mapValues[LocalIndex]; // sets the column (that you created before) to the orig data
SplitData.Rows.Add(newRow);
as the core of your second for loop. You might as well do it in one loop too.
Although the accepted answer was totally right and I learned something from it, it turns out the DataTable.ImportRow method is exactly what I want for my needs, so just for future reference for anyone who might stumble upon this.
Related
I have data being processed by an app which needs to sort the data based on whether or not a bit is flipped. The tables are identical. The code as it stands looks something like this:
DataTable dt2 = dt1.Clone();
DataRow r = dt1.NewRow();
FillUp(ref r);
if(bitISetEarlier)
dt2.ImportRow(r);
else
dt1.ImportRow(r);
Now, a clear problem I was having is that if the row wasn't already attached to a table, ImportRow() fails silently and I end up with an empty table. When I changed this to:
if(bitISetEarlier)
dt2.Rows.Add(r);
else
dt1.Rows.Add(r);
I started getting an exception saying that a function was trying to add a row that existed for another table. So when I tried this:
if(bitISetEarlier)
if(r.RowState == DataRowState.Detached)
dt2.Rows.Add(r)
else dt2.ImportRow(r);
else
if(r.RowState == DataRowState.Detached)
dt1.Rows.Add(r)
else dt1.ImportRow(r);
the exception stopped, but any attempt to assign to dt2 still states that the row belongs to another table, but if I comment out the dt2 if statement and just attempt ImportRow(), the dt2.Rows.Count remains at 0 and no records assigned.
I need to populate the DataRow before knowing which table it belongs in, but I have no idea what columns the row will have before it hits this function. The condition that indicates which table it should go to is not stored with the data in the DataTable.
Is the problem that even though they have identical columns, NewRow() is adding an attribute to the row that makes it incompatible with the sister table? Is there a way I can get the same functionality as NewRow() (copy schema without knowing what any of the columns are ahead of time) but that I can dynamically assign? I'm aware I could probably manually construct a row that is compatible with either by wrapping it in a for loop and building out the columns every time i need the new row using the DataTable.Columns property, but I'd like to avoid doing that if possible.
I found my solution. Since I can't add the row built off of one table to the other table directly, I figured it was the DataRow object that was problematic, but the ItemArray property was probably all I needed.
if (isErrorRow)
{
//nr is the NewRow for dt1
var nr2 = dt2.NewRow();
nr2.ItemArray = nr.ItemArray;
dt2.Rows.Add(nr2);
}
This effectively cloned the rows.
I'm fairly new to C# programming. I want to take user input from DataGridView to a DataTable. However, I get ArgumentException from this code
DataTable dd=new DataTable();
foreach (DataGridViewRow dr in dataGridView1.Rows)
{
dd.Rows.Add(dr);
}
Is there any way I can do to fix it? I'd like to have alternatives to get input from dataGridView1 as well.
edit: forgot to mention, dataGridView1 has one comboBox column.
edit2: the error read "Input array is longer than the number of columns in this table."
Input array is longer than the number of columns in this table.
You have to add a column to DataTable eg: dd.Columns.Add("SomeColumnName"), before you add rows to it.
However, if there's no particular requirement to use DataTable then you should use, for example, List to store the rows. It is a much simpler data structure.
var listOfRows = gridView.Rows.Cast<DataGridViewRow>().ToList();
When I retrieve data into my DataSet, the year column is the 3rd column in my DataSet. I do not need this column after using it do so some calculations, so I remove it using the Remove method passing the column's name to the Remove method. The problem is that I retrieve the data in a foreach loop, so when I retrieve the data again, the year column is now the last column in the DataSet and when I try to access it, it throws an error saying year column was not found. My way around this was to clone by DataSet into a DataTable and then to import each row from the dataset into my DataTable, but is there a more efficient way or a way to keep the year column in it's original position.
private int GetData()
{
dataSet.GetExportData();
DataTable dt = dataSet.ExportData;
for(int i = 0; i <dataSet.ExportData; i++)
{
//Do Stuff
}
dataSet.Columns.Remove(dataSet.ExportData.YearColumn.ColumnName);
}
In the above code, when I open up a dialog and select data to export, it works the first time, but if I leave the dialog open and click the button to export again, it throws the error. If I close the dialog and reopen, it works fine. As I said before I noticed when it retrieves the data again on the button click with dataSet.GetExportData(), it puts the Year column as the last column instead of the defined position in the strongly-typed DataSet which I assume is the problem, but can't figure out how to fix it besides doing a Clone and Import.
It'd be better to be in comment, but I want to take advantage of code styling, also it's hard to say what exactly you want to achieve without sighting the code,
foreach (DataRow row in myTable.Rows)
{
//do something with year column
myTable.Columns.Remove("year");
}
above code works fine in the first iteration, but will fail afterwards, as myTable.Columns.Remove("year") removes the whole column, from the table not just from current row, and gives you: You'll get Column 'year' does not belong to table Table.exception.
Why not taking myTable.Columns.Remove("year"); out of the foreach instead?
foreach (DataRow row in myTable.Rows)
{
//do something with year column
}
myTable.Columns.Remove("year");
I have to copy rows from one table to another. In the source table I can have RowError set on rows.
When I do this:
targetTable.BeginLoadData();
targetTable.Load( new DataTableReader( sourceTable ) )
targetTable.EndLoadData();
The target table does not get row errors copied on its rows from source table.
Can anyone tell what am I supposed to do to make it work?
Thanks.
EDIT: I do not want to lose the data already present in the target table. Nor do I want to change the reference.
Try this:
targetTable = sourceTable.Copy();
Creating a reader won't give you the expected result in this case, because its (reader) goal will be extracting the value of each row, not the appendant properties.
Update:
In this case, you should:
foreach (DataRow drImport in sourceTable.Rows) {
targetTable.ImportRow(drImport);
}
Sorry, just before posting I've seen your other observation about the reference. I'm afraid you can't have the same row (same reference) assigned to two ore more tables. See this.
I have two datatables one has few rows other is empty.
I am running a loop over first one to copy some of the rows to another table.
I am getting error 'The row already belongs to another table'.
Is there any way to copy DataRows one by one to other DataTable.
thanks in advance
Use
newtable.ImportRow(oldtable.Rows[i])
where i is the desired row number.
as explained in http://support.microsoft.com/kb/308909/en-us
copy the ItemArray, of course just works when the columns are the same
var dtCopyTo = new DataTable();
foreach(var rowCopyFrom in dtCopyFrom.Rows)
{
var updatedDataRow = dtCopyTo.NewRow();
updatedDataRow.ItemArray = rowCopyFrom.ItemArray;
dtCopyTo.AddRow(updatedDataRow);
}
ps: code is typed without ide so check syntax pls