I tried to add values to DataTable columns by vertically in loops.
But output doesn't looks good as expected.
DataTables dynamictable = new DataTable()
foreach (DataColumn cl in dataTable.Columns)
{
dynamictable.Columns.Add(cl.ToString());
List<string> plainList = dataTable.AsEnumerable().Select(x => x[cl].ToString()).ToList();
for (int i=0; i< plainList.Count(); i++)
{
DataRow row = dynamictable.NewRow();
row[cl.ToString()] = plainList[i];
enryptedTable.Rows.Add(row);
}
}
Actual Output got from my code:
Expected Output:
change your code to :
DataTable dynamictable = new DataTable();
int col = 0;
foreach (DataColumn cl in dataTable.Columns)
{
dynamictable.Columns.Add(cl.ToString());
List<string> plainList = dataTable.AsEnumerable().Select(x => x[cl].ToString()).ToList();
DataRow row = null;
for (int i = 0; i < plainList.Count(); i++)
{
row = dynamictable.NewRow();
row[col] = plainList[i];
dynamictable.Rows.Add(row);
}
col++;
}
//now set dynamictable to datagridview or .....
Related
I have a data table named dt which is a SQL table converted.
All the data was sent from the server so I had to encrypt it. Now I need to decrypt every cell.
I wanted to do it like this:
foreach (DataRow row in dt.Rows)
{
for (int i = 0; i < dt.Columns.Count; i++)
{
row[i] = r.Decrypt(row[i].ToString());
}
}
Decrypt works fine but row[i] = r.Decrypt(row[i].ToString()); give me the number of the column instead of its content, how do I get the content?
to make the post make more sense.
i want row[i] = r.Decrypt(a string representing the value of row[i]);
This is the correct way to interact with a datatable
foreach(DataRow row in dt .Rows)
{
foreach(DataColumn column in dt .Columns)
{
Console.WriteLine(row[column]);
}
}
In your case you are literally passing an int to your row, because You are using count property.
** Edit
This is in case Your datarow contains an object.
DataTable dt = new DataTable();
dt.Columns.Add("Column 1");
dt.Columns.Add("Column 2");
DataRow dataRow = dt.NewRow();
dataRow.ItemArray = new object[]{"line 1 column 1", "line 1 column 2"
};
dt.Rows.Add(dataRow);
foreach (DataRow row in dt.Rows)
{
foreach (DataColumn column in dt.Columns)
{
var text = row[column.ToString()];
Console.WriteLine(text);
}
}
Result
If none of this work, We would have to see how Your data row is created.
As you mentioned that the other logic (Decrypt) is working fine and you just need to fetch the column content/values then you can try something like:
foreach(DataRow row in table.Rows)
{
foreach(DataColumn column in table.Columns)
{
// you can insert your logic to use column value row[column] here
Console.WriteLine(row[column]);
}
}
for (int i = 0; i < dt.Rows.Count ; i++)
{
for (int j = 1; j < dt.Columns.Count ; j++)
{
string cellValue = dt.Rows[i][j].ToString();
dt.Rows[i][j] = r.Decrypt(cellValue);
}
}
I have two datatables
dtTable1:
Name Id Contact
Gems A1 8888880000
George A2 0000008888
dtTable2:
Col1 Col2 Col3
XXX1 YYY1 ZZZ1
XXX2 YYY2 ZZZ2
XXX3 YYY3 ZZZ3
XXX4 YYY4 ZZZ4
My required DataTable is:
Name Id Contact Col1 Col2 Col3
Gems A1 8888880000 XXX1 YYY1 ZZZ1
George A2 0000008888 XXX2 YYY2 ZZZ2
null null null XXX3 YYY3 ZZZ3
null null null XXX4 YYY4 ZZZ4
How can I do it with C#
Here you go. Might not be pretty but does the job.
No matter which DataTable has more row it will add them.
private static DataTable MergeTables(DataTable dt1, DataTable dt2)
{
DataTable merged = new DataTable();
//copy column struct from dt1
merged = dt1.Clone();
//create columns from dt2
foreach (DataColumn col in dt2.Columns)
{
merged.Columns.Add(col.ColumnName);
}
int rows;
if (dt1.Rows.Count > dt2.Rows.Count)
{
rows = dt1.Rows.Count;
}
else
{
rows = dt2.Rows.Count;
}
for (int i = 0; i < rows; i++)
{
DataRow row = merged.NewRow();
if ( i < dt1.Rows.Count)
{
for (int c = 0; c < dt1.Columns.Count; c++)
{
row[c] = dt1.Rows[i][c];
}
}
if (i < dt2.Rows.Count)
{
for (int c2 = dt1.Columns.Count; c2 < dt2.Columns.Count + dt1.Columns.Count; c2++)
{
row[c2] = dt2.Rows[i][c2-dt1.Columns.Count];
}
}
merged.Rows.Add(row);
}
return merged;
}
DataTable mergeDataTables(DataTable dt1, DataTable dt2)
{
if(dt1.Rows.Count != dt2.Rows.Count ) throw new Exception();
var dtResult = new DataTable();
//add new columns
foreach (DataColumn col in dt1.Columns)
dtResult.Columns.Add(col.ColumnName, col.DataType);
foreach (DataColumn col in dt2.Columns)
dtResult.Columns.Add(col.ColumnName, col.DataType);
//fill data
for (int i = 0; i < dt1.Rows.Count; i++)
{
dtResult.Rows.Add(dt1.Rows[i].ItemArray.Concat(dt2.Rows[i].ItemArray).ToArray());
}
return dtResult;
}
I have changed solution of lomed.
May be this not perfect solution. But it works for the similar scenario as required in the question:
DataTable MergeDataTables(DataTable dt1, DataTable dt2)
{
var dtResult = new DataTable();
foreach (DataColumn col in dt1.Columns)
dtResult.Columns.Add(col.ColumnName, col.DataType);
foreach (DataColumn col in dt2.Columns)
dtResult.Columns.Add(col.ColumnName, col.DataType);
//cond: to check which if datatable1 is bigger
if (dt1.Rows.Count > dt2.Rows.Count)
{
for (int i = 0; i < dt1.Rows.Count; i++)
{
if (i < dt2.Rows.Count)
dtResult.Rows.Add(dt1.Rows[i].ItemArray.Concat(dt2.Rows[i].ItemArray).ToArray());
else
{
DataRow dr = dtResult.NewRow();
foreach (DataColumn col in dt1.Columns)
dr[col.ColumnName] = dt1.Rows[i][col.ColumnName];
dtResult.Rows.Add(dr);
}
}
}
//if rows equal or datatable2 is bigger
else
{
for (int i = 0; i < dt2.Rows.Count; i++)
{
if (i < dt1.Rows.Count)
dtResult.Rows.Add(dt1.Rows[i].ItemArray.Concat(dt2.Rows[i].ItemArray).ToArray());
else
{
DataRow dr = dtResult.NewRow();
foreach (DataColumn col in dt2.Columns)
dr[col.ColumnName] = dt2.Rows[i][col.ColumnName];
dtResult.Rows.Add(dr);
}
}
}
return dtResult;
}
I have two datatables, each with 1 column:
dtTempCM
dtOldTempCM
In both tables, the only column name is Column1
I also have 2 datagridviews in the form that are each bound to a datatable:
dgvCurrentCM.DataSource = dtTempCM;
dgvOldCM.DataSource = dtOldTempCM;
How can I compare each row, and highlight it in one (or both) of the datagridviews if they don't match? So far, I have this:
foreach (DataRow row1 in dtTempCM.Rows)
{
foreach (DataRow row2 in dtOldTempCM.Rows)
{
var array1 = row1.ItemArray;
var array2 = row2.ItemArray;
if (array1.SequenceEqual(array2))
{
//change row/cell color in dgvCurrentCM to red
//change row/cell color in dgvOldCM to red
}
}
}
Any ideas? Thank you!
EDIT: I tried this too, but it changes the color of every cell since it compares every row in dgvOldCM to a single row in dgvCurrentCM:
foreach (DataGridViewRow row1 in dgvCurrentCM.Rows)
{
foreach (DataGridViewRow row2 in dgvOldCM.Rows)
{
if (row1.Cells[0].Value != row2.Cells[0].Value)
{
row1.DefaultCellStyle.ForeColor = Color.Red;
row2.DefaultCellStyle.ForeColor = Color.Red;
}
}
}
I would iterate on one of the gridview, comparing to the other like this:
for (int i = 0; i < dgvCurrentCM.RowCount; i++)
{
if (dgvCurrentCM.Rows[i].Cells[0].Value != null)
{
if ((int)dgvCurrentCM.Rows[i].Cells[0].Value != (int)dgvOldCM.Rows[i].Cells[0].Value)
{
dgvCurrentCM.Rows[i].DefaultCellStyle.ForeColor = Color.Red;
dgvOldCM.Rows[i].DefaultCellStyle.ForeColor = Color.Red;
}
}
}
You can generate a Intersection of two Datatables, and then mark the rows:
DataTable dt1 = new DataTable();
DataTable dt2 = new DataTable();
dt1.Columns.Add("Col");
dt2.Columns.Add("Col");
for (int i = 0; i < 10; i++)
{
DataRow dr = dt1.NewRow();
dr["Col"] = i.ToString();
dt1.Rows.Add(dr);
}
for (int i = 5; i < 15; i++)
{
DataRow dr = dt2.NewRow();
dr["Col"] = i.ToString();
dt2.Rows.Add(dr);
}
var result = dt1.AsEnumerable().Intersect(dt2.AsEnumerable(), DataRowComparer.Default);
dataGridView1.DataSource = dt1;
dataGridView2.DataSource = dt2;
for (int i = 0; i < dataGridView1.RowCount -1; i++)
{
DataRow currRow = ((DataRowView)dataGridView1.Rows[i].DataBoundItem).Row;
if (result.Contains(currRow))
dataGridView1.Rows[i].DefaultCellStyle.ForeColor = Color.Red;
}
if (array1.SequenceEqual(array2))
{
}
else
{
//Do your action here!
}
Is it possible to convert a sqlceresultset.resultview to datatable?
Not tested, but this should do what you need:
public DataTable ResultSetToDataTable(SqlCeResultSet set)
{
DataTable dt = new DataTable();
// copy columns
for (int col = 0; col < set.FieldCount; col++)
{
dt.Columns.Add(set.GetName(col), set.GetFieldType(col));
}
// copy data
while (set.Read())
{
DataRow row = dt.NewRow();
for (int col = 0; col < set.FieldCount; col++)
{
int ordinal = set.GetOrdinal(GetName(col));
row[col] = set.GetValue(ordinal);
}
dt.Rows.Add(row);
}
return dt;
}
There's no built-in way to do this (that I know of), probably because a SqlCeResultSet does not store actual data like a DataTable does.
I want to populate GridView below with images:
<asp:GridView ID="GrdDynamic" runat="server" AutoGenerateColumns="False">
<Columns>
</Columns>
</asp:GridView>
The code below iterates through directory, then I collect image titles and want them to be populated in gridview. code in bold is not working well, gridview is only filled with the last image in list.
List<string> imagelist = new List<string>();
protected void Page_Load(object sender, EventArgs e)
{
foreach (String image in Directory.GetFiles(Server.MapPath("example/")))
{
imagelist.Add("~/example/" + Path.GetFileName(image));
}
loadDynamicGrid(imagelist);
}
private void loadDynamicGrid(List<string> list)
{
DataTable dt = new DataTable();
DataColumn dcol = new DataColumn(NAME, typeof(System.String));
dt.Columns.Add(dcol);
dcol = new DataColumn("NAME1", typeof(System.String));
dt.Columns.Add(dcol);
dcol = new DataColumn("NAME2", typeof(System.String));
dt.Columns.Add(dcol);
dcol = new DataColumn("NAME3", typeof(System.String));
dt.Columns.Add(dcol);
DataRow drow = dt.NewRow();
dt.Rows.Add();
dt.Rows.Add();
**for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
foreach (string value in list)
{
dt.Rows[i][j] = value;
}
}
}**
foreach (DataColumn col in dt.Columns)
{
ImageField bfield = new ImageField();
bfield.DataImageUrlField = NAME;
bfield.HeaderText = col.ColumnName;
GrdDynamic.Columns.Add(bfield);
}
GrdDynamic.DataSource = dt;
GrdDynamic.DataBind();
}
how to fill gridview cell-by-cell only with available amount of images?
i know it is easy, i tried various methods like: dt.Rows.Add(list); and some other attempts, but they didn't work. i'm very stupid.
i'd be glad for any help.
You're repeatedly setting every cell to every string with your foreach. You need to addess a specific element in list that will correspond to the specific cell. Try something like this:
for (int i = 0; i < dt.Rows.Count; i++)
{
for (int j = 0; j < dt.Columns.Count; j++)
{
//below line assumes list has more than i*j elements
//how you want to handle anything outside that case
//is not clear
dt.Rows[i][j] = list[(i * dt.Columns.Count) + j] ;
}
}
Edit: Reading your question more carefully, your problem is fundamentally outside of that loop. Even if you applied the above fix, you still wouldn't get what you're hoping for. What you need to do is loop over the list, and add each item in the list a row, and add that row to the table. Something like this:
int currColIndex = 0;
DataRow drow = dt.NewRow();
foreach(string value in list)
{
if(currColIndex >= dt.Columns.Count)
{
dt.Rows.Add(drow);
drow = dt.NewRow();
currColIndex = 0;
}
drow[currColIndex++] = value;
}
if(currColIndex != dt.Columns.Count)
{
dt.Rows.Add(drow);
}