Why conversion from Gridview to datatable fails? - c#

I have been trying to convert GRIDVIEW to DataTable but it doesn't give me data, it only gives me HEADERS of GridView but not the data inside it. Why ? I am using template fields in gridview
Calling it from event:
DataTable dt = GetDataTable(GridView DenominationsWiseTransactions);
Conversion function:
DataTable GetDataTable(GridView dtg)
{
DataTable dt = new DataTable();
// add the columns to the datatable
if (dtg.HeaderRow != null)
{
for (int i = 0; i < dtg.HeaderRow.Cells.Count; i++)
{
dt.Columns.Add(dtg.HeaderRow.Cells[i].Text);
}
}
// add each of the data rows to the table
foreach (GridViewRow row in dtg.Rows)
{
DataRow dr;
dr = dt.NewRow();
for (int i = 0; i < row.Cells.Count; i++)
{
dr[i] = row.Cells[i].Text.Replace(" ", "");
}
dt.Rows.Add(dr);
}
return dt;
}

So, when you are looping through the rows in the datagrid, it will include headers, the rows and the footer.
To see just the data rows you need to do something like:
if (e.Row.RowType == DataControlRowType.DataRow)
{ //convert that row }
Your conversion line might need some work, but at least you'll only need to concern yourself with datarows now.

Related

How to dynamically delete rows in DataList c# asp

Looking for a way to dynamically delete rows from a datalist, providing a user a way to 'clean up' their input interface. The asp datalist gets loaded from SQL, then the user gets to manipulate the table before sending it on to another database.
I have a functioning 'addRows' by using a datatable session variable, adding rows to it then re-binding to the datalist, however I can't seem to get the same function with deleting rows.
Current logic is to use datalist 'delRows' command, get current typed-in or modified data from the asp datalist, assign it to a datatable, loop thru datatable and delete rows where certain fields are empty, then re-bind datatable to asp datalist.
Current code workup, but cannot get dt filled, error "dt = null" :
if (e.CommandName == "delRows")
{
DataList DataList1 = (DataList)FindControl("DataList1"); //find datalist in current state
Session["dataList1"] = DataList1; //assign datalist to session variable
DataTable dt = Session["dataList1"] as DataTable; //populate datatable with datalist session
for (int i = dt.Rows.Count - 1; i >= 0; i--)
{
DataRow dr = dt.Rows[i];
string check = dr["item_no"].ToString();
if (check == String.Empty)
{
dr.Delete();
}
}
DataList1.DataSource = dt;
DataList1.DataBind();
}
Hopefully there is a better way to accomplish this! Not to mention working....
For any future info seekers: Had to loop thru table to get most current textbox text into dt, then modify dt datatable in code behind, then rebind dt to datalist.
protected void doDataTable(string command, int e)
{
DataTable dt = new DataTable();
dt.Columns.Add("no", typeof(string));
dt.Columns.Add("desc", typeof(string));
dt.Columns.Add("code", typeof(string));
dt.Columns.Add("measure", typeof(string));
dt.Columns.Add("qty", typeof(int));
dt.Columns.Add("price", typeof(double));
foreach (DataListItem item in DataList4.Items)
{
string no = ((TextBox)item.FindControl("no")).Text;
string desc = ((TextBox)item.FindControl("desc")).Text;
string code = ((TextBox)item.FindControl("code")).Text;
string measure = ((TextBox)item.FindControl("measure")).Text;
int qty = Convert.ToInt16(((TextBox)item.FindControl("qty")).Text);
double price = Convert.ToDouble(((TextBox)item.FindControl("price")).Text.TrimStart('$'));
dt.Rows.Add(no, desc, code, measure, qty, price);
}
if (command == "add")
{
DataRow dr = dt.NewRow();
dt.Rows.Add(dr);
DataList4.DataSource = dt;
DataList4.DataBind();
}
else if (command == "del")
{
dt.Rows[e].Delete();
DataList4.DataSource = dt;
DataList4.DataBind();
}
}
Called with:
protected void DataList1_ItemCommand(object source, DataListCommandEventArgs e)
{
if (e.CommandName == "addRow")
{
doDataTable("add", e.Item.ItemIndex);
}
if (e.CommandName == "delRows")
{
doDataTable("del", e.Item.ItemIndex);
}
}

SQL query to DataTable to include headers

Up until now, I had a utility class that contained a function called "getTable", which took a string query and returned a datatable. Now I'm trying to get these queries to be returned via excel. Simply copying the contents of the datatable to excel works fine - however there's no header row on the spreadsheet to explain what each column is.
Below is my attempt:
public static DataTable getTable(String sql, bool includeHeaderRow)
{
DataTable table = new DataTable();
using (SqlDataAdapter adpt = new SqlDataAdapter(sql, getConn()))
{
adpt.Fill(table);
if (includeHeaderRow)
{
DataRow headerRow = table.NewRow();
for (int i = 0; i < table.Columns.Count; i++)
{
headerRow[i] = table.Columns[i].ColumnName;
}
table.Rows.InsertAt(headerRow, 0);
}
}
return table;
}
The above almost works, but an exception is thrown when I try and write a column name (obviously a string) into a non-string column of the datatable.
Any ideas for an easy way to achieve this?
Of course the code may give error, because as you told you are assigning none compatible datatypes into one column with specific datatype, columns at Datatable accepts specific datatypes now if you try to change the column datatype to object by creating a copy of table(cloning it) I think the problem will fix:
public static DataTable getTable(String sql, bool includeHeaderRow)
{
DataTable table = new DataTable();
using (SqlDataAdapter adpt = new SqlDataAdapter(sql, getConn()))
{
adpt.Fill(table);
if (includeHeaderRow)
{
DataTable dt = table.Clone();
for (int i = 0; i < table.Columns.Count; i++)
{
dt.Columns[i].DataType = typeof(Object);
}
foreach (DataRow row in table.Rows)
{
dt.ImportRow(row);
}
DataRow headerRow = dt.NewRow();
for (int i = 0; i < table.Columns.Count; i++)
{
headerRow[i] = table.Columns[i].ColumnName;
}
dt.Rows.InsertAt(headerRow, 0);
}
}
return dt;
}

Pulling Column count and header text with auto generated columns in a gridview

I am rewriting one the functions within my team’s primary library and one of those functions is to export a Gridview to an Excel spread sheet. I already have a function to export a DataSet to Excel, so all I need to do is convert a gridview to a DataSet. No problem right? All was well until I found that the GridView object’s columns collect is empty and the header text is null when using auto generated columns.
I know that MS has said that you surrender how the gridview renders that data, but I can’t find anything that shows how I might capture the column collection. I’d like this Library to be as flexible as possible.
Here is my function as it stands now...
public static MemoryStream GridViewToXLSX(GridView Gridview, Options options = null)
{
DataSet ds = new DataSet();
DataTable dt = new DataTable();
for (int i = 0; i < Gridview.Columns.Count; i++)
{
dt.Columns.Add(Gridview.Columns[i].HeaderText);
}
foreach (GridViewRow row in Gridview.Rows)
{
DataRow dr = dt.NewRow();
for (int j = 0; j < Gridview.Columns.Count; j++)
{
dr[Gridview.Columns[j].HeaderText] = row.Cells[j].Text;
}
dt.Rows.Add(dr);
}
ds.Tables.Add(dt);
return DataSetToXLSX(ds, options);
}
Alternatively you can try this sample code, instead of Column.count, you can count the number of cells in the HeaderRow of the GridView.
This is just a sample, not actual code
GridViewRow headerRow = gv.HeaderRow;
int count = headerRow.Cells.Count

Create function GetAllChechedBox with text and value and insert in new DataTable

I want to take the text and value from selected and not selected elements from CheckBoxList and insert in datatable
MultiCheckCombo Reference
Now I want to get text and value from this checklist,
I think it would be comfortable to place in a DataTable
public DataTable GetAllChechedBox()
{
var dt = new DataTable();
for (int i = 0; i < chkList.Items.Count; i++)
{
if (chkList.Items[i].Selected)
{
dt.Columns.Add("Name");
dt.Columns.Add("Value");
// how add all checked with value and text in this datatable?
}
}
return dt;
}
/also want to take a function with text and value for unselected elements/
Instead of chkList.Items[i].Selected, use chkList.Items[i].Checked....plus
add column outside loop
public DataTable GetAllChechedBox()
{
var dt = new DataTable();
dt.Columns.Add("Name");
dt.Columns.Add("Value");
for (int i = 0; i < chkList.Items.Count; i++)
{
if (chkList.Items[i].Checked)
{
dt.Rows.Add();
dt.Rows[dt.Rows.Count-1]["Name"] = chkList.Items[i].Value;
dt.Rows[dt.Rows.Count-1]["Value"] = chkList.Items[i].Text;
}
}
return dt;
}

How to get columns from a datarow?

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
}

Categories