I have some DataGridViews on a form, and would like to get a XML string from it.
But for some reason it gives "Exception thrown: 'System.NullReferenceException'" at the point of return.
When I look inside the foreach rows, it has the data I have put in.
What is the problem here?
public string DataGridViewToXML(DataGridView DGV)
{
DataTable DT = new DataTable();
foreach (DataGridViewColumn col in DGV.Columns) { DT.Columns.Add(col.Name); }
foreach (DataGridViewRow row in DGV.Rows)
{
DataRow dRow = DT.NewRow();
foreach (DataGridViewCell cell in row.Cells) { dRow[cell.ColumnIndex] = cell.Value; }
DT.Rows.Add(dRow);
}
return DT.DataSet.GetXml();
}
You haven't told as at what line it trows it but as i get it you copy all data from DGV to DT so you can parse DataSet.GetXml();?
If that is the case why you just do not do:
public string DataGridViewToXML(DataGridView DGV)
{
return (DGV.DataSource as DataTable).DataSet.GetXml();
}
I know it doesn't solve your null error but why would you solve it when you have easier way of doing you command. Other way tell me at what line error drops and i will try explaining why it happens.
Related
I have the following datagridview.
I need to filter and save rows separately that match Valid and Invalid property of the status column.
It do not have a datasource.So i'm creating a DataTable,filtering it and saving the results.But the filtering is not working as intended and contains results that does not match the expression
DataTable dt = new DataTable();
//Populating Virtual Table
foreach (DataGridViewColumn col in dataGridView4.Columns)
{
dt.Columns.Add(col.Name);
}
foreach (DataGridViewRow row in dataGridView4.Rows)
{
DataRow dRow = dt.NewRow();
foreach (DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
dt.Rows.Add(dRow);
}
Now creating a Filtered Table containing results where column named Status equals "Valid"
filtered = dt.Copy();
DataTable filteredResults = new DataTable();
DataTable filteredResults2 = new DataTable();
// filtered.Columns.Remove("Status");
var expression = string.Format("Status LIKE '%{0}%'", "Valid");
if (filtered.Select(expression).Any())
{
filteredResults = filtered.Select(expression).CopyToDataTable();
}
But the filtered data table contains elements which has the Status column value "Invalid".What i'm i doing wrong ? Please advice.
You are using LIKE in your expression. LIKE checks to see if the value contains the specified value. Use = instead.
How to print items from dataGridview , to rdlc Report.
The items in the dataGridView are filled manually, and not from database, that's why this gives me issues.
p.s i know there are ways to print it with PrintForm but i want to print it with .rdlc.
Tryed with DataTable but it doenst show me the right colums on the
RDLC Dataset
DataSet ds = new DataSet();
DataTable dt = new DataTable("ProdFromDGV");
foreach (DataGridViewColumn col in dataGridView1.Columns)
{
dt.Columns.Add(col.HeaderText);
}
foreach (DataGridViewRow row in dataGridView1.Rows)
{
DataRow dRow = dt.NewRow();
foreach (DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
dt.Rows.Add(dRow);
}
ds.Tables.Add(dt);
dt.WriteXml("table.xml");`
I may well be looking at this problem backwards but I am curious none the less. Is there a way to build a DataTable from what is currently displayed in the DataGridView?
To be clear, I know you can do this DataTable data = (DataTable)(dgvMyMembers.DataSource); however that includes hidden columns. I would like to build it from the displayed columns only.
Hope that makes sense.
So I ended up trying a combination of a couple of answers as that seemed best. Below is what I am trying. Basically I am creating the DataTable from the DataSource and then working backwards based on if a column is visible or not. However, after it removes a column I get a Collection was modified; enumeration operation may not execute on the next iteration of the foreach.
I am confused as I am not trying to modify the DataGridView, only the DataTable so what's up?
DataTable data = GetDataTableFromDGV(dgvMyMembers);
private DataTable GetDataTableFromDGV(DataGridView dgv)
{
var dt = ((DataTable)dgv.DataSource).Copy();
foreach (DataGridViewColumn column in dgv.Columns)
{
if (!column.Visible)
{
dt.Columns.Remove(column.Name);
}
}
return dt;
}
Well, you can do
DataTable data = (DataTable)(dgvMyMembers.DataSource);
and then use
data.Columns.Remove(...);
I think it's the fastest way. This will modify data source table, if you don't want it, then copy of table is reqired. Also be aware that DataGridView.DataSource is not necessarily of DataTable type.
I don't know anything provided by the Framework (beyond what you want to avoid) that would do what you want but (as I suspect you know) it would be pretty easy to create something simple yourself:
private DataTable GetDataTableFromDGV(DataGridView dgv) {
var dt = new DataTable();
foreach (DataGridViewColumn column in dgv.Columns) {
if (column.Visible) {
// You could potentially name the column based on the DGV column name (beware of dupes)
// or assign a type based on the data type of the data bound to this DGV column.
dt.Columns.Add();
}
}
object[] cellValues = new object[dgv.Columns.Count];
foreach (DataGridViewRow row in dgv.Rows) {
for (int i = 0; i < row.Cells.Count; i++) {
cellValues[i] = row.Cells[i].Value;
}
dt.Rows.Add(cellValues);
}
return dt;
}
one of best solution enjoyed it ;)
public DataTable GetContentAsDataTable(bool IgnoreHideColumns=false)
{
try
{
if (dgv.ColumnCount == 0) return null;
DataTable dtSource = new DataTable();
foreach (DataGridViewColumn col in dgv.Columns)
{
if (IgnoreHideColumns & !col.Visible) continue;
if (col.Name == string.Empty) continue;
dtSource.Columns.Add(col.Name, col.ValueType);
dtSource.Columns[col.Name].Caption = col.HeaderText;
}
if (dtSource.Columns.Count == 0) return null;
foreach (DataGridViewRow row in dgv.Rows)
{
DataRow drNewRow = dtSource.NewRow();
foreach (DataColumn col in dtSource .Columns)
{
drNewRow[col.ColumnName] = row.Cells[col.ColumnName].Value;
}
dtSource.Rows.Add(drNewRow);
}
return dtSource;
}
catch { return null; }
}
First convert you datagridview's data to List, then convert List to DataTable
public static DataTable ToDataTable<T>( this List<T> list) where T : class {
Type type = typeof(T);
var ps = type.GetProperties ( );
var cols = from p in ps
select new DataColumn ( p.Name , p.PropertyType );
DataTable dt = new DataTable();
dt.Columns.AddRange(cols.ToArray());
list.ForEach ( (l) => {
List<object> objs = new List<object>();
objs.AddRange ( ps.Select ( p => p.GetValue ( l , null ) ) );
dt.Rows.Add ( objs.ToArray ( ) );
} );
return dt;
}
I want to get a DataTable from DataGridView of the Grid values.
In other words DataTable same as DataGridView Values
Might be a nicer way to do it but otherwise it would be fairly trivial to just loop through the DGV and create the DataTable manually.
Something like this might work:
DataTable dt = new DataTable();
foreach(DataGridViewColumn col in dgv.Columns)
{
dt.Columns.Add(col.Name);
}
foreach(DataGridViewRow row in dgv.Rows)
{
DataRow dRow = dt.NewRow();
foreach(DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
dt.Rows.Add(dRow);
}
You can cast the DataSource object from the DataGridView to a DataTable
DataTable dt = new DataTable();
dt = (DataTable)dataGridView1.DataSource;
you can use the following code also, this code fill not effect on your DataGridView when you do some add or delete rows in the datatable
DataTable dt = new DataTable();
dt = Ctype(dataGridView1.DataSource,DataTable).copy();
You can try as follow:
using System.Data;
using System.Windows.Forms;
namespace BLL
{
public class Class_DataGridview_To_DataTable
{
public static DataTable UDF_Convert_DataGridView_To_Datatable(DataGridView ImpGrd)
{
DataTable ExportDataTable = new DataTable();
foreach (DataGridViewColumn col in ImpGrd.Columns)
{
ExportDataTable.Columns.Add(col.Name);
}
foreach (DataGridViewRow row in ImpGrd.Rows)
{
DataRow dRow = ExportDataTable.NewRow();
foreach (DataGridViewCell cell in row.Cells)
{
dRow[cell.ColumnIndex] = cell.Value;
}
ExportDataTable.Rows.Add(dRow);
}
return ExportDataTable;
}
}
}
I have a row collection (DataRow[] rows). And I want to import all rows to another DataTable (DataTable dt).
But how?
Code
DataTable dt;
if (drs.Length>0)
{
dt = new DataTable();
foreach (DataRow row in drs)
{
dt.Columns.Add(row???????)
}
// If it possible, something like that => dt.Columns.AddRange(????????)
for(int i = 0; i < drs.Length; i++)
{
dt.ImportRow(drs[i]);
}
}
Assuming the rows all have the same structure, the easiest option is to clone the old table, omitting the data:
DataTable dt = drs[0].Table.Clone();
Alternatively, something like:
foreach(DataColumn col in drs[0].Table.Columns)
{
dt.Columns.Add(col.ColumnName, col.DataType, col.Expression);
}
If your DataRows is from a Data Table with Columns defined in it,
DataRow[] rows;
DataTable table = new DataTable();
var columns = rows[0].Table.Columns;
table.Columns.AddRange(columns.Cast<DataColumn>().ToArray());
foreach (var row in rows)
{
table.Rows.Add(row.ItemArray);
}
How about
DataTable dt = new DataTable;
foreach(DataRow dr in drs)
{
dt.ImportRow(dr);
}
Note this only works if drs is a DataRowCollection. Detached rows (not in a DataRowCollection are ignored).
Don't forget to call AcceptChanges.
Try this:
// Assuming you have a DataRow object named row:
foreach(DataColumn col in row.Table.Columns)
{
// Do whatever you need to with these columns
}