ClosedXML convert percentage in template - c#

I`m using closedXML to generate a simple template with 3 columns.
To create this template i`m using this code:
protected void btnTemplate_Click(object sender, EventArgs e)
{
DataTable dt = new DataTable();
var tipo = "TARGET";
if (ddlTipo.SelectedValue == "RESULTADO")
{
tipo = "RESULTADO";
}
dt.Columns.AddRange(new DataColumn[3] {
new DataColumn("BU", typeof(string)),
new DataColumn("MÉTRICA", typeof(string)),
new DataColumn(tipo,typeof(string)) });
//Exporting to Excel
//Codes for the Closed XML
using (XLWorkbook wb = new XLWorkbook())
{
var worksheet = wb.Worksheets.Add(dt, "BASE");
worksheet.Cell("C1").DataType = XLDataType.Text;
//wb.SaveAs(folderPath + "DataGridViewExport.xlsx");
string myName = ("Template.xlsx");
MemoryStream stream = GetStream(wb);// The method is defined below
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition",
"attachment; filename=" + myName);
Response.ContentType = "application/vnd.ms-excel";
Response.BinaryWrite(stream.ToArray());
Response.End();
}
}
Its working fine, the problem is in the C column, it can receive percentage, and it changed the type in the excel.
Is there a way to force in closedXML that the column C is always treated as TEXT? To not convert the numbers. i tried using worksheet.Cell("C1").DataType = XLDataType.Text; to force as text,but it doesnt`t work.

Well I never used closedXML I rater EPPLUS (version 4.5.3.3 is totally free),
But I have a lot of cases like yours, what I do is set the type of the column as text,
in closed xml you can do:
worksheet.Cell(rowIndex, columnIndex).Style.NumberFormat.Format = "#";
But there's a simpler solution that works for any Excel XML library!
Instead of creating your excel template with code you can create it manually and save on a folder in your project. Setup any attribute you want to with the Excel interface itself save it, and then open the file with closed xml and just set the values wherever you want to. Last 'save as' somewhere (dont overrite the template) and do what you need.
there is a lot benefits in doing like this:
1 - A few time to create the template (compared with coding).
2 - Reduce your code.
3 - You can place formulas easier.
4 - No need to change code to modify the template.
5 - Any one who knows a bit of Excel can change the template.

Related

mso-data-placement:same-cell not working

I am exporting data into Excel from a web page. This should be a no brainer, but there are <p> tags in the data. This causes Excel to create new rows when the data should all be in the same cell. After some research I found that mso-data-placement should do the trick, but it's not working. Excel opens, the data is displayed, but extra uncessary rows are created. Here is the code I use to export the data:
protected void doexcel()
{
string style = #"<style type='text/css'>P {mso-data-placement:same-cell; font-weight:bold;}</style>";
HttpResponse response = HttpContext.Current.Response;
// first let's clean up the response.object
response.Clear();
response.Charset = "";
//set the response mime type for excel
response.ContentType = "application/vnd.ms-excel";
Random RandomClass = new Random();
int RandomNumber = RandomClass.Next();
String filename = "a" + RandomNumber + DateTime.Now + ".xls";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"" );
// create a string writer
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
HttpContext.Current.Response.Write(style);
SqlDataSourceEmployeeAssets.ConnectionString = MyObjects.Application.CurrentContext.ConnectionString;
String sql = (string)Session["sql"];
SqlDataSourceEmployeeAssets.SelectCommand = sql;
// lCount.Text = "Query returned " + getCount(query) + " rows.";
DataGrid dge = new DataGrid();
dge.DataSource = SqlDataSourceEmployeeAssets;
dge.DataBind();
dge.RenderControl(htw);
response.Write(sw.ToString());
response.End();
}
}
}
This is an example of the raw data in the database that is giving me grief:
<P>4/13/2011 : Cheng "Jonathan" Vaing is with BSES Graffiti Unit.</P><P>4/13/2011 : Cheng "Jonathan" Vaing is with</P>
Suggestions?
I tried a couple of other things
I went straight to the data and added the mso-data-placement attribute to the paragraph tag inline. Still didn't work. The data looked like this
<P style="mso-data-placement:same-cell> my data </p>
I tried other mso-* attributes, that didn't work either. For example, I changed my stylesheet to look like this
<style type='text/css'>P {mso-highlight:yellow}</style>";
Why oh why doesn't Excel recognize my mso-* attributes?!?!
There is a solution but it is not clean.
After the dge.DataBind, place the following code. This will encode the text of each cell
foreach (DataGridItem dgi in dge.Items)
{
foreach (TableCell cell in dgi.Cells)
{
cell.Text = WebUtility.HtmlEncode(cell.Text);;
}
}
The Excel file, when opened, should show the raw data with the markup, all in one cell.
I found that this works because Excel actually encodes the text, as well. To see what Excel does in action, do the following:
Create a new workbook in Excel (I am using Office 2013).
In the first cell, paste the raw data (as you have it displayed). Do this by first pressing F2 (insert into cell), then paste the text.
Save the workbook as an HTML file (or web page).
Using windows explorer, go to the folder location of where you saved the file. There should be a hidden folder (i think it is hidden) with the same name as your file. For example, if your workbook is Book1.htm, there should be a folder labeled Book1_files.
In this folder, there should be an HTM file with the name sheet001.htm. Open this file in notepad (or any text editor...not excel or word)
Locate your raw data. You will see that the text is not showing the HTML markup, rather it is showing the encoded version.
Hope this helps.

Exporting data from c# to word document

I have a grid in c# filled with data. One of the columns in that grid contains letters (followed by numbers) sorted alphabetically, like this:
A124
A256
A756
B463
B978
D322
etc.
I need to export this data in a word document (.doc or .docx format).
This is what i did to export a signle grid:
var dt = FuntionThatReturnsDatatables();
var gd = new GridView
{
DataSource = dt
};
gd.DataBind();
HttpContext.Current.Response.Clear();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.AddHeader("content-disposition", "attachment;
filename=" + "List" + DateTime.Now.ToString("dd.MM.yyyy") + ".doc");
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
HttpContext.Current.Response.ContentType = "application/ms-word";
HttpContext.Current.Response.Charset = "UTF-8";
HttpContext.Current.Response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());
var oStringWriter = new StringWriter();
var oHtmlTextWriter = new HtmlTextWriter(oStringWriter);
gd.RenderControl(oHtmlTextWriter);
HttpContext.Current.Response.Output.Write(oStringWriter.ToString());
HttpContext.Current.Response.Flush();
HttpContext.Current.Response.End();
But now I have to follow this logic:
- For every letter from grid a new table with title should be created like this:
Table A:
A124
A256
A756
Each new table should start from a new page, like this:
Table A:
A124,
A256,
A756,
//new page
Table B:
B463,
B978,
//new page
Table D:
D322,
etc.
Pages in that word document need to be numbered.
Is there any way to write a code in c# to do this or is there some library/plugin that can accomplish this task ?
Some examples would be appreciated.
You should be able to use OpenXML SDK from Microsoft to achieve this.
Reference: http://msdn.microsoft.com/en-us/library/bb448854.aspx
Reference Sample:
http://blogs.msdn.com/b/acoat/archive/2010/06/19/document-creation-and-conversion-with-the-openxml-sdk-and-sharepoint-2010-word-automation-services.aspx
http://blogs.msdn.com/b/acoat/archive/2011/04/06/document-creation-and-conversion-with-the-openxml-sdk-and-sharepoint-2010-word-automation-services-part-2.aspx
What version of Word do you need to work with? If it's a version that can handle the .docx file format, i.e. 2007 and later, then you can generate those files directly. In fact, the easiest way to do that is create a .docx file in Word that you use as a kind of template, and then programmatically manipulate the xml in that file.
For more information, see
http://msdn.microsoft.com/en-us/magazine/cc163526.aspx
http://msdn.microsoft.com/en-us/library/system.io.packaging.aspx

Stop Date Auto-Format when Exporting from DataGrid to Excel in C#

I am currently formatting a Date for a specific Excel file Export from a DataSet/DataGrid.
The Date is formatted like so:
DateTime date = Convert.ToDateTime(entry.Date);
string formatdate = String.Format("{0:yyyy/MM/dd}", date);
Once creating the DataSet is said and done, I use the following code to Export the DataSet to an Excel file:
public static void ExportDStoExcel(DataSet ds, string filename)
{
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.Charset = "";
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
response.Write(sw.ToString());
response.End();
}
}
}
My only problem is once I export this to Excel, Excel Auto-Formats the Dates like this: MM/DD/YYYY instead of YYYY/MM/DD.
I understand this could be achieved manually by opening in Excel, but the Export is being built into an Automated System and needs to be hard coded.
Is there any way of bypassing Excel's DateTime Auto-Formatting?
I had the same issue and solved it by adding a non breaking space (&nbsp) in front of the text. Stopped Excel from auto-formatting. Not the cleanest solution but did the trick for me...
Right now you are just outputting HTML table, that Excel interprets how it likes. You'd have bring yourself down to Excel's level to be able to specify column's properties (set type to Text instead of General).
This means that you need to generate actual xls file (there are various libraries out there for that). Or (if restriction to Office 2010 is acceptable) got with Open XML format which you can write with regular .NET API.
You can style excel cells with mso-number-format
mso-number-format:"\\#"
\# will tell excel to treat all data in text format only. So auto format won't happen.
Please update your code like this:
response.ContentType = "application/vnd.ms-excel";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
response.Write("<html xmlns:x=\"urn:schemas-microsoft-com:office:excel\">");
response.Write("<head><style> td {mso-number-format:\\#;} </style></head><body>");
using (StringWriter sw = new StringWriter())
{
using (HtmlTextWriter htw = new HtmlTextWriter(sw))
{
DataGrid dg = new DataGrid();
dg.DataSource = ds.Tables[0];
dg.DataBind();
dg.RenderControl(htw);
response.Write(sw.ToString());
response.Write("</body></html>");
response.End();
}
}
OR
you can try with specific date format also.
Refer: http://cosicimiento.blogspot.in/2008/11/styling-excel-cells-with-mso-number.html
mso-number-format:"yyyy\/mm\/dd"

Generate Excel Spreadsheet from CSV (ASP.NET C#) [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
Create Excel (.XLS and .XLSX) file from C#
I have some code that generates a zip file that contains multiple CSV files and streams it back to the user (no file is saved on the server). However, I want to create an excel workbook instead (can be traditional xls or Office Open XML xlsx format) with each CSV 'file' being a spreadsheet.
How can I do this, without resorting to Office Automation on the server or a commercial 3rd party component?
You can use OleDB to generate simple tables in Excel files.
Note that you will need to generate a temp file on the server.
Example.
Note that their example is incorrect and needs to use an OleDbConnectionStringBuilder, like this:
OleDbConnectionStringBuilder builder = new OleDbConnectionStringBuilder();
if (isOpenXML)
builder.Provider = "Microsoft.ACE.OLEDB.12.0";
else
builder.Provider = "Microsoft.Jet.OLEDB.4.0";
builder.DataSource = fileName;
builder["Extended Properties"] = "Extended Properties=\"Excel 8.0;HDR=YES;\""
using (var con = new OleDbConnection(builder.ToString())) {
...
}
The XML format for Excel is quite simple and there's absolutely no need to do any automation.
The full reference is up on MSDN: http://msdn.microsoft.com/en-us/library/aa140066(office.10).aspx
Response.ContentType = "application/vnd.ms-excel";
The ContentType property specifies the HTTP content type for the response. If no ContentType is specified, the default is text/HTML.
Get all your data in a DataGrid and then get it from it can be done with:
DataGrid.RenderControl
Outputs server control content to a provided HtmlTextWriter object and stores tracing information about the control if tracing is enabled.
SqlConnection cn = new SqlConnection("yourconnectionstring");
cn.Open();
SqlDataAdapter da = new SqlDataAdapter("SELECT * FROM Users", cn);
DataTable dt = new DataTable();
da.Fill(dt);
DataGrid dg = new DataGrid();
dg.DataSource = dt;
dg.DataBind();
System.IO.StringWriter tw = new System.IO.StringWriter();
System.Web.UI.HtmlTextWriter hw = new System.Web.UI.HtmlTextWriter(tw);
dg.RenderControl(hw);
cn.Close();
Response.Clear();
Response.ContentType = "application/vnd.ms-excel";
this.EnableViewState = false;
Response.Write(tw.ToString());
Response.End();
You can write the excel xml by yourself. Here is a nice lib for the task, maybe it is something for you.
// Edit
Link: http://www.carlosag.net/Tools/ExcelXmlWriter/Generator.aspx

Export HTML Table in asp.net MVC

I trying to export an HTML table named Table that is dynamically binded to ViewData.Model in C#. I have a method called export that is called based on another method's actions. so everything before that is set up.. I just don't know how to export the data to a CSV or Excel file.. So when the I step inside the Export method I don't know what next to do to export the table. Can someone help me
public void Export(List<data> List)
{
//the list is the rows that are checked and need to be exported
StringWriter sw = new StringWriter();
//I don't believe any of this syntax is right, but if they have Excel export to excel and if not export to csv "|" delimeted
for(int i=0; i<List.Count;i++)
{
sw.WriteLine(List[i].ID+ "|" + List[i].Date + "|" + List[i].Description);
}
Response.AddHeader("Content-Disposition", "attachment; filename=test.csv");
Response.ContentType = "application/ms-excel";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
Response.Write(sw);
Response.End();
}
I don't quite understand the whole "export an HTML table named Table that is dynamically binded to ViewData.Model" so I'll just ignore that and focus on your Export(List<data> list) method. Btw, you never really mentioned what was going wrong and where.
I see you had written "if they have Excel export to excel and if not export to csv" - I would personally just export it as a CSV file in both cases because excel can handle csv files no problem.
So with that in mind, here would be my export method based on your code.
public void Export(List<DataType> list)
{
StringWriter sw = new StringWriter();
//First line for column names
sw.WriteLine("\"ID\",\"Date\",\"Description\"");
foreach(DataType item in list)
{
sw.WriteLine(string.format("\"{0}\",\"{1}\",\"{2}\"",
item.ID,
item.Date,
item.Description));
}
Response.AddHeader("Content-Disposition", "attachment; filename=test.csv");
Response.ContentType = "text/csv";
Response.ContentEncoding = System.Text.Encoding.GetEncoding("utf-8");
Response.Write(sw);
Response.End();
}
This is an excellent example, but I think that need a globalization modification.
String ltListSeparator = CultureInfo.CurrentUICulture.TextInfo.ListSeparator;
sw.WriteLine(string.format("{0}" + ltListSeparator + "{1}" + ltListSeparator + "{2}", item.ID, item.Date, item.Description));
I think your controller action method will need to wrap the data items in an html table which you may want to do any way you like, So your html+ data will be stored in a string and then you could do something like below- (its not exacly built for MVC but its easy to modify for it).
Response.ClearContent();
Response.AddHeader("content-disposition", attachment);
Response.ContentType = "application/ms-excel";
Response.Write(yourDataAndHtmlAsString);
Response.End();
CSV is a simple format and can be built up easily as a string.
http://en.wikipedia.org/wiki/Comma-separated_values
You could create an excel spreadsheet of what you think the end product should look like, save as CSV, open it in notepad and try and replicate it using a string builder.

Categories