Export data with images to Excel - asp.net

I am exporting data with images to Excel by using the following code.
Code
protected void ExportToExcel(object sender, EventArgs e)
{
//Get the data from database into datatable
string strQuery = "select CustomerID, ContactName, City, PostalCode, display_picture" +
" from customers";
SqlCommand cmd = new SqlCommand(strQuery);
DataTable dt = GetData(cmd);
//Create a dummy GridView
GridView GridView1 = new GridView();
GridView1.AllowPaging = false;
GridView1.DataSource = dt;
GridView1.DataBind();
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition",
"attachment;filename=DataTable.xls");
Response.Charset = "";
Response.ContentType = "application/vnd.ms-excel";
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
for (int i = 0; i .textmode { mso-number-format:\#; } ";
Response.Write(style);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
}
The Excel is downloading properly. But the problem is when I am filtering the data in the Excel. The images in the Excel are in Move but don't size with cells property. How to make the images with the property, Move and size with cells?

Your code doesn't create an Excel file at all, it creates an HTML table and sends it with a fake content type, that of the old binary Excel format (xls). Excel isn't fooled, it detects that this is an HTML table and tries to import it using default settings. This can break for any number of reasons.
It's far easier and cheaper to create a real Excel file with a library like EPPlus. For starters, you can fill a sheet directly from a DataTable  :
protected void ExportToExcel(object sender, EventArgs e)
{
///...
DataTable dt = GetData(cmd);
using (ExcelPackage pck = new ExcelPackage())
{
//Create the worksheet
var ws = pck.Workbook.Worksheets.Add("Demo");
//Load the datatable into the sheet, starting from cell A1.
//Print the column names on row 1
ws.Cells["A1"].LoadFromDataTable(dt, true);
//That's it!
//Write it back to the client
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=ExcelDemo.xlsx");
Response.BinaryWrite(pck.GetAsByteArray());
}
}
You can add pictures with the Drawings.AddPicture method :
ExcelPicture pic = ws.Drawings.AddPicture("pic1", new FileInfo("PathToMyImage.png"));
The result is an xlsx file which is a package of compressed XML files. This means it's actually smaller than the HTML table or CSV files that are often generated instead of actual Excel files.

EasyXLS is a library that also exports xlsx and xls files with images.
//Create a workbook
ExcelDocument workbook = new ExcelDocument();
//Add a worksheet
ExcelWorksheet worksheet = new ExcelWorksheet("Gridview");
workbook.easy_addWorksheet(worksheet);
//Add the gridview to the worksheet
DataSet dataSet = new DataSet();
dataSet.Tables.Add((DataTable)GridView1.DataSource);
worksheet.easy_insertDataSet(dataSet);
//Add an image
worksheet.easy_addImage("image.jpg", "A10");
//Exporting gridview with image
workbook.easy_WriteXLSXFile("DataTable.xlsx");
More about inserting images, you can find at:
http://www.easyxls.com/manual/basics/excel-image-import-export.html
If the image bytes are loaded from database, you will need to temporary save the image locally on machine.
You can also check how to export gridview to excel to see more about formatting the data.

Related

ASP.Net Open office XML Set the values of a cell

I am using ASP.Net and Open office XML and I have been able to set the headers of the excel file.
However, I want to set the value to cells from say D2 to D1000 in a drop down fashion i.e. that the user can only select from a predefined list of values as in a drop down list.
How do I accomplish this?
The code for creating the excel is
List<ExcelExport> mpList = new List<ExcelExport>();
DataTable dt = ListToDataTable(mpList);
string attachment = string.Format("attachment;filename={0}-{1}.xlsx", ddlHealthFacility.SelectedItem.Text + " Excel export ", " ");
using (ExcelPackage pck = new ExcelPackage())
{
//Create the worksheet
ExcelWorksheet ws = pck.Workbook.Worksheets.Add("Monthly Plan");
ws.Cells["A1"].LoadFromDataTable(dt, true);
Byte[] fileBytes = pck.GetAsByteArray();
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", attachment);
Response.Charset = "";
Response.ContentType = "application/vnd.ms-excel";
StringWriter sw = new StringWriter();
Response.BinaryWrite(fileBytes);
Response.End();
}

Gridview not getting last row in the Excel file

I wrote a code to fetch the gridview to the Excel. Everything is working fine except a row in the gridview. When i export gridview to excel, then last row doesnot includes in the excel file. When i scanned my whole code, then i found a code which is creating a problem. Here is the code :
protected void OnDataBound(object sender, EventArgs e)
{
GridViewRow row = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Normal);
TableHeaderCell cell = new TableHeaderCell();
cell.Text = "A";
cell.ColumnSpan = 9;
row.Controls.Add(cell);
gv.HeaderRow.Parent.Controls.AddAt(0, row);
}
This code is used to add new header to the gridview of merged cells. After removing this code, everything works fine. But i need that code.
Export to excel code :
Response.Clear();
Response.AddHeader("content-disposition", "attachment;filename=Rept" + DateTime.Now.ToString("yyyy_MM_ddThh_mm_ss_") + ".xls");
Response.Charset = "";
Response.ContentType = "application/vnd.xls";
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
System.Web.UI.HtmlControls.HtmlForm form = new System.Web.UI.HtmlControls.HtmlForm();
Controls.Add(form);
form.Controls.Add(gvpanel);
form.RenderControl(htmlWrite);
Response.Write(stringWrite.ToString());
Response.End();
How to solve this issue ?
I haven't find the solution anywhere, which makes me to provide this solution.
When you create a header row & also you need to export to excel, below code solves of missing the last row.
Create your dynamic header row using RowCreated Event.
protected void Grid_RowCreated(object sender, GridViewRowEventArgs e)
{
if (e.Row.RowType == DataControlRowType.Header)
{
GridViewRow HeaderRow = new GridViewRow(0, 0, DataControlRowType.Header, DataControlRowState.Insert);
TableCell HeaderCell1 = new TableCell();
HeaderCell1.Text = "Solved your Issue";
HeaderCell1.ColumnSpan = 10;
HeaderRow.Cells.Add(HeaderCell1);
Grid.Controls[0].Controls.Add(HeaderRow);
}
}
and now you can call your ExportToExcel method:
private void ExportToExcel(GridView gv, string exportfilename)
{
string filename = exportfilename + ".xls";
System.IO.StringWriter tw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter(tw);
gv.RenderControl(hw);
//Write the HTML back to the browser.
Response.ContentType = "application/vnd.ms-excel";
Response.AppendHeader("Content-Disposition", "attachment; filename=" + filename + "");
this.EnableViewState = false;
Response.Write(tw.ToString());
Response.Flush();
Response.End();
}
You can use an excel spreadsheet as a data source to your GridView and connect to it like any other database:
How To Query and Display Excel Data by Using ASP.NET, ADO.NET, and Visual Basic .NET

Exporting from repeater to excel

I have been able to populate a repeater but the only problem I'm having is to export it to an excel sheet.
There are no data displayed in the excel file .
What I'm thinking is that because of some postback when I click the export button, the data on the repeater gets deleted or something.
Here is the code :
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition",
"attachment;filename=GridViewExport.xls");
Response.Charset = "";
Response.ContentType = "application/vnd.ms-excel";
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
Table tb = new Table();
TableRow tr1 = new TableRow();
TableCell cell1 = new TableCell();
cell1.Controls.Add(Repeater1);
tr1.Cells.Add(cell1);
tb.Rows.Add(tr1);
tb.RenderControl(hw);
//style to format numbers to string
string style = #"<style> .textmode { mso-number-format:\#; } </style>";
Response.Write(style);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
For exporting data in Excel format I would recommend using EPPlus library instead of writing strings.
EPPlus is a .net library that reads and writes Excel 2007/2010 files
using the Open Office Xml format (xlsx). 
EPPlus supports: Cell Ranges, Cell styling (Border, Color, Fill, Font,
Number, Alignments), Charts, Pictures, Shapes, Comments, Tables,
Protection, Encryption, Pivot tables, Data validation
I think "Repeater1" and table "tb" must be attached to Page (Page.Controls.Add(tb)).
Try to:
render controls to string var rendered=RenderControlToString(tb);
then clear response Response.Clear();
then write rendered string Response.Write(rendered);
public static string RenderControlToString(Control c)
{
StringBuilder sb = new StringBuilder();
StringWriter sw = new StringWriter(sb);
HtmlTextWriter htmlWriter = new HtmlTextWriter(sw);
c.RenderControl(htmlWriter);
sw.Close();
htmlWriter.Close();
return sb.ToString();
}

Download multiple excel files from the DataTable

I am trying to execute a query using for loop. For each loop it should download an excel file. The solution works perfectly, but only the first file is downloaded and the other two files are not downloaded. I have also attached the complete code below.
protected void Page_Load(object sender, EventArgs e)
{
}
protected void Btn_Click(object sender, EventArgs e)
{
DataTable it = GetList();
foreach(DataRow dr in it.Rows)
{
string a = dr[0].ToString();
for (int i = 0; i < 3; i++)
{
string inm = it.Rows[i][0].ToString();
DataTable gt = GetData(inm);
ExportToSpreadsheet(gt, "Samples");
}
}
}
public DataTable GetData(string i)
{
SqlCommand command = null;
SqlConnection conn = null;
conn = new SqlConnection(ConfigurationManager.ConnectionStrings["ConnectionString"].ConnectionString);
conn.Open();
command = new SqlCommand("SELECT id, name, class FROM StudentTable WHERE (id = " + i + ") ORDER BY name";
DataTable dt = new DataTable();
SqlDataAdapter ada = new SqlDataAdapter(command);
ada.Fill(dt);
return dt;
}
public static void ExportToSpreadsheet(DataTable table, string name)
{
HttpContext context = HttpContext.Current;
context.Response.ClearContent();
context.Response.ContentType = "text/vnd.ms-excel";
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + name + ".xls");
string tab = "";
foreach (DataColumn dc in table.Columns)
{
context.Response.Write(tab + dc.ColumnName);
tab = "\t";
}
context.Response.Write("\n");
context.Response.Write("\n");
int i;
foreach (DataRow dr in table.Rows)
{
tab = "";
for (i = 0; i < table.Columns.Count; i++)
{
context.Response.Write(tab + dr[i].ToString());
tab = "\t";
}
context.Response.Write("\n");
}
context.Response.End();
}
I have seen posts similar to this. Some people have recommended that, zip files can be created on the server and download multiple excel files in "zip" folder. If it is possible, how can I implement it to the above solution?
You're calling response.end after creating the first file - which aborts the rest of the process.
I don't think you'll be able to create 3 excel files for download using this method.
As an alternative you could create 3 CSV files on disk, then use a zip library to zip them up.
see zipping files
Or you could use JET with an Excel connection string and use SQL Insert statements to push your data into an empty excel file. And use a different worksheet for each of your tables
write to excel with JET (but this limits you to 32bit)
Or you could use a third part control to write an excel file with the three tables as worksheets
Infragistics excel control
But if I were you - I'd just present the user with 3 different links they could click on.

Exporting to excel loses the date format

I am exporting the contents of SP to excel. One of the columns brings the date format as 08/2015 but when exporting to excel, the format gets changed to Aug-2015.
I did a google on the same and found that including the below code does the trick;
string style = #"<style> .text { mso-number-format:\#; } </style> ";
The exporting to excel (dataset to excel) works below;
/// <summary>
/// This method can be used for exporting data to excel from dataset
/// </summary>
/// <param name="dgrExport">System.Data.DataSet</param>
/// <param name="response">System.Web.Httpresponse</param>
public static void DataSetToExcel(System.Data.DataSet dtExport, System.Web.HttpResponse response, string strFileName)
{
string style = #"<style> .text { mso-number-format:\#; } </style> ";
//Clean up the response Object
response.Clear();
response.Charset = "";
//Set the respomse MIME type to excel
response.ContentType = "application/vnd.ms-excel";
//Opens the attachment in new window
response.AddHeader("Content-Disposition", "attachment; filename=" + strFileName.ToString() + ".xls;");
response.ContentEncoding = Encoding.Unicode;
response.BinaryWrite(Encoding.Unicode.GetPreamble());
//Create a string writer
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
//Create an htmltextwriter which uses the stringwriter
System.Web.UI.HtmlTextWriter htmlWrite = new System.Web.UI.HtmlTextWriter(stringWrite);
//Instantiate the datagrid
System.Web.UI.WebControls.GridView dgrExport = new System.Web.UI.WebControls.GridView();
//Set input datagrid to dataset table
dgrExport.DataSource = dtExport.Tables[0];
//bind the data with datagrid
dgrExport.DataBind();
//Make header text bold
dgrExport.HeaderStyle.Font.Bold = true;
//bind the modified datagrid
dgrExport.DataBind();
//Tell the datagrid to render itself to our htmltextwriter
dgrExport.RenderControl(htmlWrite);
response.Write(style);
//Output the HTML
response.Write(stringWrite.ToString());
response.End();
}
Where am i making a mistake? please guide!
Thanks!
Problem is not with the Date format, Excel converts the data as per the DataType (Default is GENERAL) of CELL. To prevent the data conversion you have to provide the data type (TEXT) along with the data.
you have used the correct code, but style sheet .text is not applied on your data. Apply the style sheet on ALL the <TD> tags. It will 100% work and will retain your data as is you will provide (Date- 08/2015, 0001 or any data).
string style = #"<style> TD { mso-number-format:\#; } </style> ";
Here is some sample code.
Response.AddHeader("content-disposition", "attachment; filename=Report.xls");
Response.Charset = "";
Response.ContentType = "application/vnd.xls";
System.IO.StringWriter stringWrite = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter htmlWrite = new HtmlTextWriter(stringWrite);
DataGrid g = new DataGrid();
DataTable d = new System.Data.DataTable();
d = (DataTable)Session["ReportData"];
g.DataSource = d;
g.DataBind();
foreach (DataGridItem i in g.Items)
{
foreach (TableCell tc in i.Cells)
tc.Attributes.Add("class", "text");
}
g.RenderControl(htmlWrite);
string style = #"<style> .text { mso-number-format:\#; } </style> ";
Response.Write(style);
Response.Write(stringWrite.ToString());
Response.End();
I don't really understand a fair bit of the code (not fluent in asp.net) but I will say that if you want to force text in an excel sheet you need to define the target area as text before putting your data in there.
If my understanding of the code is correct this:
response.Write(style);
Needs to be before this.
dgrExport.RenderControl(htmlWrite);
Edit: Perhaps an alternate solution
The bit of google code you have found sets the format of the cells as text. In all likelyhood you want excel to treat the date as a date which has a display format of MM/YYYY.
maybe try replacing this:
string style = #"<style> .text { mso-number-format:\#; } </style> "
with
string style = #"<style> .text { mso-number-format:\mm/yyyy; } </style> "
I am not sure if / or \ is an escape character in ASP.net so the exact snytax might be different. In excel terms number format # means text and mm/yyyy will mean a date with the display format that you want.

Resources