list Values to dataTable - c#

I created a list from an excel document that has partnumbers on the every other starting with the first, and prices on every other row, starting with the second.
Lets say I initialize a datatable like so..
DataTable priceListTable = new DataTable();
priceListTable.Columns.Add("ItemNumber", typeof(string));
priceListTable.Columns.Add("Price", typeof(Float));
And my list (called recordList) looks this;
001-001
1.45
001-002
3.49
How do I get the first two rows of the list to fill the columns of the dataTable?

Here's one solution.
Loop over the list 2 items at a time starting from the 2nd item. This makes sure you always have a pair of items to use.
for (int i = 1; i < list.Count; i += 2)
{
DataRow row = table.NewRow();
row["ItemNumber"] = list[i-1];
row["Price"] = list[i];
table.Rows.Add(row);
}

string ItemNumber = "ItemNumber";
string Price = "Price";
DataTable priceListTable = new DataTable();
DataRow row;
priceListTable.Columns.Add(ItemNumber);
priceListTable.Columns.Add(Price);
int counter = 0;
foreach(string s in recordList)
{
myTableSize++;
}
foreach(string s in recordList)
{
if (counter < myTableSize)
{
row = priceListTable.NewRow();
row[ItemNumber] = recordList[counter];
row[Price] = recordList[counter + 1];
priceListTable.Rows.Add(row);
counter++;
counter++;
}

Related

Row already belongs to another table error when trying to add rows?

I tried this solution below:
This Row already belongs to another table error when trying to add rows?
I have a Datatable that contains 597 Columns and 20 Rows and are trying to export the data to excel. However, Excel has a maximum column count 256 and so I need to divide the source data into 3 datatables to make the export work.
Below is the code I have written.
var dtmasterdata = data.Tables[name];
for (int j = 1; j < datatableNumberCount; j++)
{
DataTable dt2 = new DataTable();
dt2.TableName = "Master_" + j;
dt2 = dtmasterdata.Copy();
foreach (DataColumn col in dtmasterdata.Columns)
{
DataColumn dtcol = new DataColumn();
dtcol = col;
dt2.Columns.Add(dtcol.ColumnName, dtcol.DataType);
}
for (int k = 0; k < dtmasterdata.Rows.Count; k++)
{
DataRow dr = dt2.NewRow();
dr = dtmasterdata.Rows[k];
dt2.ImportRow(dtmasterdata.Rows[k]);
//dt2.Rows.Add(dr.ItemArray);
}
After that I need to delete few columns like below and I want to create 3 datatables
foreach (DataColumn col in dtmasterdata.Columns)
{
if (j == 1)
{
// condition 1
if (col.Ordinal >= 255)
{
dt2.Columns.RemoveAt(col.Ordinal);
}
}
if (j == 2)
{
// condition 2.
if (col.Ordinal < 255 || col.Ordinal >= 510)
{
dt2.Columns.RemoveAt(col.Ordinal);
}
}
if (j == 3)
{
// condition 3.
if (col.Ordinal <= 510 || col.Ordinal >= 765)
{
dt2.Columns.Add(col);
}
}
}
int worksheetNumber = 1;
string worksheetNameWithNumber = "Master Data";
if (worksheetNumber > 1)
worksheetNameWithNumber = String.Format("{0}_{1}", ws1, worksheetNumber.ToString());
Infragistics.Excel.Worksheet worksheet = wb.Worksheets.Add(worksheetNameWithNumber);
Infragistics.WebUI.UltraWebGrid.UltraWebGrid masterData1 = new Infragistics.WebUI.UltraWebGrid.UltraWebGrid("masterDataGrid");
masterData1.Browser = Infragistics.WebUI.UltraWebGrid.BrowserLevel.UpLevel;
masterData1.DataSource = dt2;
masterData1.DataMember = "Master_" + j;
masterData1.DisplayLayout.HeaderStyleDefault.Font.Bold = true;
masterData1.DisplayLayout.HeaderStyleDefault.Font.Name = "Arial";
masterData1.DisplayLayout.HeaderStyleDefault.Font.Size = FontUnit.Parse("10px");
masterData1.DisplayLayout.HeaderStyleDefault.BackColor = System.Drawing.Color.LightGray;
masterData1.DisplayLayout.RowStyleDefault.Font.Name = "Arial";
masterData1.DisplayLayout.RowStyleDefault.Font.Size = FontUnit.Parse("10px");
Infragistics.WebUI.UltraWebGrid.UltraGridBand masterBand1 = new Infragistics.WebUI.UltraWebGrid.UltraGridBand();
masterData1.Bands.Add(masterBand1);
dgResults.Controls.Add(masterData1);
masterData1.DataBind();
wb.ActiveWorksheet = worksheet;
this.ugWebGridExporter.Export(masterData1, worksheet);
worksheetNumber++;
Your error is because you are trying to add a column to a datatable that already belongs to your source datatable.
dt2.Columns.Add(col);
You can't just iterate through the columns of a datatable and add them to another.
I've a solution to this, which involves cloning the source data and removing what you don't need.
1st, make 3 clones of the datatables you need. Below is an example with me creating my own source table with 596 columns. Notice that clone only takes the data table structure, no data!
var source597ColsTable = new DataTable("Source");
for (var i = 0; i <= 596; i++)
{
source597ColsTable.Columns.Add(new DataColumn("Column" + i , typeof(string)));
}
DataRow newRow = source597ColsTable.NewRow();
source597ColsTable.Rows.Add(newRow);
var cols0To199Table = source597ColsTable.Clone();
var cols200To399Table = source597ColsTable.Clone();
var cols400To596Table = source597ColsTable.Clone();
Next copy all the rows from the source table into the clones. The below is a simple function to do so.
private DataTable CopyRowsFromSource(DataTable sourceTable, DataTable destinationTable)
{
foreach (DataRow row in sourceTable.Rows)
{
destinationTable.Rows.Add(row.ItemArray);
}
return destinationTable;
}
Then call this function for each of your tables.
cols0To199Table = CopyRowsFromSource(source597ColsTable, cols0To199Table);
cols200To399Table = CopyRowsFromSource(source597ColsTable, cols200To399Table);
cols400To596Table = CopyRowsFromSource(source597ColsTable, cols400To596Table);
Finally, remove all the columns from the datatables to give you your split.
private DataTable RemoveColumns(DataTable table, int startCol, int endCol)
{
var colsToRemove = new List<DataColumn>();
for (var colCount = startCol; colCount <= endCol; colCount++)
{
colsToRemove.Add(table.Columns[colCount]);
}
foreach (DataColumn col in colsToRemove)
{
table.Columns.Remove(col);
}
return table;
}
Then call.. again for each cloned table.
cols0To199Table = RemoveColumns(cols0To199Table, 200, 596);
cols200To399Table = RemoveColumns(cols200To399Table, 0, 199);
cols200To399Table = RemoveColumns(cols200To399Table, 200, 396);
cols400To596Table = RemoveColumns(cols400To596Table, 0, 399);
After running this, you will have 3 datatables, columns 0-199, 200-399 and 400-596.
Hope that helps.
I am not sure to have really understood all of your code, but to copy a subset of columns to another datatable there is a very simple method in the DataView class named ToTable where you can list the columns you want in the new table. As added bonus, this method copies also the data in the 20 rows of your original table.
So the only difficult is to list these columns to the method.
You can proceed in this way using linq over the DataColumn collection
string[] firstCols = dtmasterdata.Columns
.Cast<DataColumn>()
.Take(255)
.Select(x => x.ColumnName).ToArray();
string[] secondCols = dtmasterdata.Columns
.Cast<DataColumn>()
.Skip(255)
.Take(255)
.Select(x => x.ColumnName).ToArray();
string[] thirdCols = dtmasterdata.Columns
.Cast<DataColumn>()
.Skip(510)
.Select(x => x.ColumnName).ToArray();
DataTable t1 = dtmasterdata.DefaultView.ToTable("Master_1", false, firstCols);
DataTable t2 = dtmasterdata.DefaultView.ToTable("Master_2", false, secondCols);
DataTable t3 = dtmasterdata.DefaultView.ToTable("Master_3", false, thirdCols);

datatable get specific column from row

I have the following:
//a datatable with some rows and columns lets say 5x5
var datatable = new DataTable();
var numberofrows = datatable.rows.count;
for (int i = 0; i < numberofrows; i++) {
//for each row, get the 3rd column
var cell = datatable.rows[i].???
}
how do I get the 3rd column for each row?
for 3rd column
var cellValue = datatable.Rows[i][2];
better, if you know the column name,
var cellValue = datatable.Rows[i]["column_name"];
If the table contains 2 columns "Property" and "Value". Contents can be inserted as follows
table.Columns.Add("Property", typeof(string));
table.Columns.Add("Value", typeof(string));
table.Rows.Add("P1", "abc");
table.Rows.Add("P2", "xyz");
To retrive contents of specific column
foreach (DataRow row in table.Rows)
{
if (row["Property"].ToString() == "P1")
{
var value = row["Value"].ToString();
}
}
we can read the particular column values by like this
foreach (DataTable table in ds.Tables)
{
if (table.TableName == "Table1")
{
for (int j = 0; j < table.Rows.Count; j++)
{
int a = Convert.ToInt32( table.Rows[j].ItemArray[3]);
int b = Convert.ToInt32(table.Rows[j].ItemArray[4]);
}
}
}
You can iterate thru the datatable and get every row, which can be thought as an array, so you can pick each element of that particular row using an index (and can also use the name of the column instead of the index, i.e.: row["column3 name"]).
foreach(DataRow row in datatable)
{
Console.WriteLine(row[2]);
}

Converting a List into Datatable

Assume that I have a list like PL = { P1, 0, 10, P2, 5, 20 } and I need to convert it a datatable like
ProcessName ArrivalTime CpuTime
P1 0 10
P2 5 20
The number of process (row count) is dynamic. And I have tried sth like this:
protected DataTable CreateDataTable()
{
int j = 0;
List<string> PL = CreateProcessList();
DataTable DT = new DataTable();
for (int i = 0; i < PL.Count - 2; i += 3)
{
DataRow ProcessRow = DT.NewRow();
DT.Rows[j][0] = PL[i].ToString();
DT.Rows[j][1] = Convert.ToInt32(PL[i + 1]);
DT.Rows[j][2] = Convert.ToInt32(PL[i + 2]);
j++;
}
DT.Columns.Add("Header", typeof(string));
DT.Columns[0].ColumnName = "ProcessName";
DT.Columns[1].ColumnName = "ArrivalTime";
DT.Columns[2].ColumnName = "CpuTime";
return DT;
}
It does not work (says that there is no row at position 0). Thanks for any idea.
Working Code After Editions:
protected DataTable CreateDataTable()
{
List<string> PL = CreateProcessList();
DataTable DT = new DataTable();
DT.Columns.Add("ProcessName", typeof(string));
DT.Columns.Add("ArrivalTime", typeof(int));
DT.Columns.Add("CpuTime", typeof(int));
for (int i = 0; i < PL.Count - 2; i += 3)
{
DataRow ProcessRow = DT.NewRow();
ProcessRow[0] = PL[i].ToString();
ProcessRow[1] = Convert.ToInt32(PL[i + 1]);
ProcessRow[2] = Convert.ToInt32(PL[i + 2]);
DT.Rows.Add(ProcessRow);
}
return DT;
}
To create a datatable in the way you have described, you need to follow a different way.
Create a datatable object
Add Columns to the datatable object by using the Add() method
use the datatable objects NewRow() method to get a DataRow object with the same schema as your datatable
populate the columns of this DataRow with the desired values
Add this DataRow to the Rows collection of your datatable object by using the Add() method
repeat step 3 to 6 until your list reaches the end.
On the second iteration of your for loop i is 3, so you're getting the 4th row of your table (at this point in time your table has 2 row). You're then getting the 4th, 5th, and 6th columns of that row (your table has 0 columns, as you haven't added any columns yet) to set their value. The corresponding index out of range errors should be telling you exactly what's wrong here.
Don't access the i-th row from the table. Just use ProcessRow to access the row; it's right there in a variable for you. Don't access the i-th column, access the 1st, 2nd, and 3rd (and add the columns before you try to populate them.
Something like this should work. Keep adding to curRow until the current iteration starts with 'P'. When it does start with 'P', add the currentRow to the data table and start a new row.
DataTable dataTable;
DataRow curRow;
... add columns to dataTable
for (var i = 0; i < PL.Count; i++) {
if (PL[i].ToString().StartsWith("P")) {
if (curRow != null)
dataTable.Rows.Add(curRow);
curRow = dataTable.NewRow();
}
... add PL[i] to curRow
}
There's a few little issues with this but they can be fixed pretty easily. A check to make sure curRow is not null before adding to data table... that sorta thing.

how to compare 2 datatable and get unique records in 3rd datatable?

I have 2 datatable let say dtData1 and dtData2. I have records in both the datatable I want to compare both the data table and want to create a new datatable let say dtData3 with uniqe records.
suppose: dtData1 has 10 records, and dtData2 has 50 records, but what ever records are there in dtData2 in that 7 records are same as dtData1. So here I want unique records in dtData3, means I want only 43 records in dtData3.
we don't know in datatable where we have the duplicate, and its possible that we will not have duplicates or its also possible that we will have all duplicate records.
So in dtData3 I need unique records
Some one please help me.
var dtData3 = dtData2.AsEnumerable().Except(dtData1.AsEnumerable(), DataRowComparer.Default);
Use this.. Probably it will help you.
Suppose you have two data table
DataTable dt1 = new DataTable();
dt1.Columns.Add("Name");
dt1.Columns.Add("ADD");
DataRow drow;
for (int i = 0; i < 10; i++)
{
drow = dt1.NewRow();
drow[0] = "NameA" + 1;
drow[1] = "Add" + 1;
dt1.Rows.Add();
}
DataTable dt2 = new DataTable();
dt2.Columns.Add("Name");
dt2.Columns.Add("ADD");
DataRow drow1;
for (int i = 0; i < 11; i++)
{
drow1 = dt2.NewRow();
drow1[0] = "Name" + 1;
drow1[1] = "Add" + 1;
dt2.Rows.Add();
}
Now To solve your problem Call :-
DataTable d3 = CompareTwoDataTable(dt1, dt2);
The method is something like this;--
public static DataTable CompareTwoDataTable(DataTable dt1, DataTable dt2)
{
dt1.Merge(dt2);
DataTable d3 = dt2.GetChanges();
return d3;
}
Then where the need to compare dtData1 and dtData2? Instead you can copy the contents from dtData2 to dtData3 starting from index7.
First Create Array variables to save unique coloumn values for datatable3. Use Foreach loop with second gridview rows. If any match then dnt save it in a array value, if dnt match then save it in arrays. and display it by attaching with third gridview.......
e.g
string[] name = new string[4];
int i=0,j=0;
foreach(GridViewRows gv in GridView1.rows)
{
if(gv.Cells[0].Text == GridView2.Rows[i].Cells[0].Text)' //if match
{
// dnt save
}
else' //if dnt match save in array for further use
{
name[j] = gv.Cells[0].Text;
j= j++;
}
i=i++;
}
After Saving unique values in Array "name"...Bind it in Third Gridview
During DataBound of third Gridview add this method...
Private void GridView3_RowDataBound(object sender,EventArgs e)
{
if(e.Row.RowState == DataControlState.DataRow)
{
foreach(string nm in name)
{
e.Rows.Cells.Add(name);
}
}
}
public DataTable CompareTwoDataTable(DataTable dtOriginalTable, DataTable dtNewTable, ArrayList columnNames)
{
DataTable filterTable = new DataTable();
filterTable = dtNewTable.Copy();
string filterCriterial;
if (columnNames.Count > 0)
{
for (int iNewTableRowCount = 0; iNewTableRowCount < dtNewTable.Rows.Count; iNewTableRowCount++)
{
filterCriterial = string.Empty;
foreach (string colName in columnNames.ToArray())
{
filterCriterial += colName.ToString() + "='" + dtNewTable.Rows[iNewTableRowCount][colName].ToString() + "' AND ";
}
filterCriterial = filterCriterial.TrimEnd((" AND ").ToCharArray());
DataRow[] dr = dtOriginalTable.Select(filterCriterial);
if (dr.Length > 0)
{
filterTable.Rows[filterTable.Rows.IndexOf(filterTable.Select(filterCriterial)[0])].Delete();
}
}
}
return filterTable;
}

How find datarows and change index of datarow in an existing datatable?

I have an existing DataTable with thousand rows and want to find the rows and set it to become top rows.
I don't know if you're able to, but I would probably add a dummy column to sort by, give the rows you want a higher value in the dummy column, and then sort by the column from bigger to smaller with a DataView.
private void ModifyTable(DataTable toModify)
{ //Add a column to sort by later.
DataColumn col = toModify.Columns.Add("DummySort", typeof(int));
col.DefaultValue = 0;
}
private void SetDummyColumnValue(DataRow dr, int value)
{ //Mark the columns you want to sort to bring to the top.
//Give values bigger than 0!
dr["DummySort"] = value;
}
private DataTable GetSortedTable(DataTable modifiedTable)
{
//Sort by the column from bigger to smaller
DataView dv = new DataView(modifiedTable);
dv.Sort = "DummySort DESC"; return dv.ToTable();
}
You can try to remove and insert row
public void MoveDataRowTo(DataRow dataRow,int destination)
{
DataTable parentTable = dataRow.Table;
int rowIndex = parentTable.Rows.IndexOf(dataRow);
if (rowIndex > 0)
{
DataRow newDataRow = parentTable.NewRow();
for (int index = 0; index < dataRow.ItemArray.Length; index++)
newDataRow[index] = dataRow[index];
parentTable.Rows.Remove(dataRow);
parentTable.Rows.InsertAt(newDataRow, destination);
dataRow = newDataRow;
}
}
DataSet dsAct = new DataSet();
OleDbDataAdapter odaTem = new OleDbDataAdapter("SELECT ActivityId, Activity FROM tbl_Activity", ocnConn);
odaTem.Fill(dsAct, "Activity");
DataRow drTem;
int i = 0;
//Rows want set to be on top is in the table "TopActivity"
foreach (DataRow dr in dsAct.Tables["TopActivity"].Rows)
{
drTem = dsAct.Tables["Activity"].NewRow();
//Clone the row
drTem.ItemArray = dsAct.Tables["Activity"].Rows.Find(dr["Activity_ID"]).ItemArray;
dsAct.Tables["Activity"].Rows.RemoveAt( dsAct.Tables["Activity"].Rows.IndexOf( dsAct.Tables["Activity"].Rows.Find(dr["Activity_ID"])));
dsAct.Tables["Activity"].Rows.InsertAt(drTem, i);
i++;
}

Categories