Tuesday, December 8, 2009

How to programmatically create an Excel Spreadsheet in ASP.net/ C#

The Problem: You need to create a dynamic excel spreadsheet in C#/ASP.net. There are several ways to accomplish this, but this is one I use when I don't need to specify the column names order to any great detail. I've included it in the How To Fix series simply because it took me more than 15 minutes to find the code, and rules are rules.

The Cause: No cause really, this is a method. The cause of hte problem was being a bit disorganized today.

The Solution: Just copy and paste the following code into your C# code behind and let her rip! Utility.dsGrab is just a function that returns a dataset.
DataTable dt = new DataTable();
DataSet ds = Utility.dsGrab("SampleDataSet");
dt = ds.Tables[0];
GridView gv = new GridView();

if (dt.Rows.Count > 0)
{
gv.DataSource = dt;
gv.DataBind();
System.IO.StringWriter oStringWriter =
new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter oHtmlTextWriter =
new HtmlTextWriter(oStringWriter);
Response.ClearContent();
Response.ContentType = "application/ms-excel";
Response.AddHeader("Content-Disposition", "attachment;
filename=SampleExcel.xls");
Response.Charset = "";
Response.Buffer = true;
EnableViewState = false;
gv.RenderControl(oHtmlTextWriter);
Response.Write(oStringWriter.ToString());
Response.End();
}

That's it! It won't open up in the browser window either.

Labels: , ,

Friday, October 30, 2009

How to fix dropdown boxes in asp.net datagrids

OK, this problem isn't silverlight, but I did encounter it in my day job. In fact, I've encountered it several times, so I thought I would write it up so I can find it again.

The Problem: You write a web page that contains an updatable datagrid, which, when in EditMode, contains a dropdown list containing lookup items. The DropdownBox does not populate, and (later when you get it working) the proper listitem is not selected.

The Cause: Since the DropDownBox down not existing when the page loads, there is nothing to bind.

The Solution: You have to attach your events to some non-standard page events to get it to work. The relevant part of the .aspx page is below (put this in your datagrid)

<asp:TemplateColumn HeaderText="Tactic Category">
<HeaderStyle Font-Size="Large" Font-Bold="true" />
<ItemTemplate>
<%#DataBinder.Eval(Container.DataItem,"TacticCatName")%>
</ItemTemplate>
<EditItemTemplate>
<%--Notice the GetCat() routine here as the datasource.--%>
<asp:DropDownList id="ddTacticCatList" runat="server" DataSource="<%# GetCat() %>" DataTextField="TacticCatName" DataValueField="TacticCatID">
</asp:DropDownList>
</EditItemTemplate>
</asp:TemplateColumn>

Your code-behind page should look like this (in C#)
private void MainCode()
{
string strID = Request.QueryString["id"].ToString();
//custom code to get the relevant dataset for the entire datgrid
DataSet ds = LMR.TacticSubCatList(strID);
//custom code to bind to the datagrid
Utility.DGDSNullCheck(ds, dgTacticSubCatList, lblTacticSubCatList, "There are no tactic subcategories in the database at this time.");
}
protected void Page_Load(object sender, EventArgs e)
{
if (!IsPostBack)
{
MainCode();
}
}

protected void dgTacticSubCatList_EditCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
//grab the index
dgTacticSubCatList.EditItemIndex = e.Item.ItemIndex;
MainCode();
}

protected void dgTacticSubCatList_UpdateCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
//get the id value of the selected datagrid item
int intTacticSubCatID = (int)dgTacticSubCatList.DataKeys[(int)e.Item.ItemIndex];

//this gets our textbox, also in the datagrid
TextBox EditText = null;
EditText=(TextBox)e.Item.FindControl("tbTacticSubCatName");
string strEditText = Convert.ToString(EditText.Text);

//get the value of our dropdown list
DropDownList dd = (DropDownList)e.Item.FindControl("ddTacticCatList");
string strTacticCatID = dd.SelectedValue.ToString();
//do our database update
LMR.TacticSubCatEdit(intTacticSubCatID.ToString(),strTacticCatID,strEditText);
//reset the datagrid
dgTacticSubCatList.EditItemIndex = -1;
//give feedback and rebind
lblFeedback.Text = "Your changes have been applied.";
MainCode();
}

protected void dgTacticSubCatList_CancelCommand(object source, System.Web.UI.WebControls.DataGridCommandEventArgs e)
{
dgTacticSubCatList.EditItemIndex = -1;
MainCode();
}
protected DataTable GetCat()
{
//here is where we get the dataset to populate the dropdown list - it does have to go in an independant function
DataSet ds = LMR.TacticCatList();
return ds.Tables[0];
}

protected void dgTacticSubCatList_ItemDataBound(object sender, DataGridItemEventArgs e)
{
if (e.Item.ItemType == ListItemType.EditItem)
{
//we set the selcted index in the ItemDataBound event
string strID = Request.QueryString["id"].ToString();
string strSubCatID = dgTacticSubCatList.DataKeys[(int)e.Item.ItemIndex].ToString();
Holder.TacticSubCat tsc = LMR.GetTacticSubCat(strSubCatID);
DropDownList dd = (DropDownList)e.Item.FindControl("ddTacticCatList");
dd.SelectedIndex =dd.Items.IndexOf(dd.Items.FindByValue(strID));
}
}

That's all there is to it. The tricky parts are putting the initial dropdown population in a separate function, and setting the index in the ItemDataBound event.

Labels: , ,