No quotef for first value in csv - c#

I am trying to make a very simple CSV file, everything works except one tiny thing : when the file get opened in Excel, the very first value of each entry isn't quoted, e.g :
username,"fullname","fullname#company.com"
And here is the code :
StringBuilder sb = new StringBuilder();
// Get user info
foreach (User u in listUsers)
{
sb.AppendFormat("\"{0}\",\"{1}\",\"{2}\"\r\n", u.Username, u.Fullname, u.EMail);
}
// Generate csv
Response.Clear();
Response.ContentType = "text/csv";
Response.AddHeader("content-disposition", "attachment; filename=\"" + "UsersExport.csv" + "\"");
Response.Write(sb.ToString());
Response.End();
Any idea?

Related

Trying to open a pdf file in a new Tab on Chrome browser - not happening

I have Get Method which I am expecting to open a pdf file in a new browser tab, but its not happening - below is the code
public void GetDoc(int id)
{
string fileInfo = "ID=[" + id + "] ";
try
{
var file = this.DomainLogicUnitOfWork.UploadedDocumentManager.GetById(id);
fileInfo = "FILENAME=[" + file.FileName + "]";
Response.Clear();
Response.ContentType = file.FileContentType;
Response.AppendHeader("content-disposition", "attachment; filename=" + file.FileName);
Response.OutputStream.Write(file.DocumentImage, 0, file.DocumentImage.Length);
Response.Output.Flush();
Response.End();
}
catch (Exception ex)
{
LogHandler.LogError(4617, "Error Downloading Document " + fileInfo, ex);
throw ex;
}
}
My url is opening correctly: http://localhost:xcxcxcx/Upload/GetDoc?id=1088 and it gives a warning when click on the start of the browser address and one more thing is the Word and other documents are being downloaded fine - means they are working fine but problem is just with PDF files. Any suggestions or ideas -
thank you all friends.
enclosing within the double quotes resolved the problem like in this one: Response.AppendHeader("content-disposition", $"attachment; filename=\"{file.FileName}\"");

Export to Excel not working

Having some trouble exporting to downloadable Excel content, using AngularJS & ASP.NET MVC. My end results is nothing happens.
Sample ASP.NET Controller method:
[HttpPost]
public ActionResult ExportToExcel(Model form)
{
var gv = new GridView();
gv.DataSource = _service.getSomeStuff(form);
gv.DataBind();
Response.ClearContent();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment; filename=Stuff.xls");
Response.ContentType = "application/ms-excel";
Response.Charset = "";
var sw = new StringWriter();
var htw = new HtmlTextWriter(sw);
gv.RenderControl(htw);
Response.Output.Write(sw.ToString());
Response.Flush();
Response.End();
byte[] temp = System.Text.Encoding.UTF8.GetBytes(sw.ToString());
return File(temp, "application/ms-excel");
}
Angular Controller Method: -> triggered via ng-click handler
function exportToExcel() {
$http.post('/Controller/ExportToExcel/', vm.Model)
.success(function (data) {
})
.error(function (data) {
alerts.error(data);
});
}
View:
click me
Any suggestions of what I might be doing wrong?
I have done something like this, without the need for AJAX or any JS. Tweaking the Razor code is all that is required.
Secondly, my personal suggestion would be to not convert to Excel file at all. The reason being, the user is required to have Office on his local machine. It also means, should you upload your project to a website, that server machine will need Office installed in order to produce your excel file.
That being said, I would suggest just using a CSV file. If a user has Office installed, they would be able to use Excel to view the file like any spreadsheet.
Here is some code that will create a CSV called Export.csv from a dbset in your dbcontext, done using StringBuilder and Reflection.
public ActionResult Export()
{
StringBuilder str = new StringBuilder();
var tmp = db.Users.FirstOrDefault();
Type comp = tmp.GetType(); // get type
foreach (PropertyInfo prop in comp.GetProperties())
{
str.Append(prop.Name + ","); //set column names
}
str.Replace(",", "\n", str.Length - 1, 1);
foreach (object item in db.Users)
{
foreach (PropertyInfo prop in item.GetType().GetProperties())
{
try
{
string a = prop.GetValue(item, null).ToString();
str.Append(a + ",");
}
catch (NullReferenceException)
{
str.Append("null" + ","); //for nulls, append string with "null"
}
}
str.Replace(",", "\n", str.Length - 1, 1);
}
string csv = str.ToString();
return File(new System.Text.UTF8Encoding().GetBytes(csv), "text/csv", "Export.csv");
}
You can then access download the file with a link on your view like this:
click me
Hope this helps.

Export CSV file to Excel 2007

I have some code for sending a data result to the user as CSV.
This works fine with Excel 2013 but in Excel 2007, it won't split into columns, but rather as data inserted into only one column.
Is there a way of telling Excel how to split the text (it's separated by ; ) ?
Here is my code:
public async Task ExcelResultList(int id)
{
var asString = await Resolver.Resolve<IHandoutManager>().GetResultListAsStringAsync(id);
var handout = await Resolver.Resolve<IHandoutManager>().GetHandout(id);
var filename = string.Format("{0} registrations - {1:yyyy-MM-dd}.csv", handout.Name, DateTime.Now);
var contenttype = "application/csv";
Response.Clear();
Response.ContentType = contenttype;
Response.AddHeader("content-disposition", "attachment;filename=" + filename);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
Response.ContentEncoding = Encoding.Unicode;
Response.Write(asString);
Response.End();
}
To make sure that you are using the correct ListSeparator ("," or ";") use this
System.Globalization.CultureInfo.CurrentCulture.TextInfo.ListSeparator
But since you only have access to the server side, then you can include this javascript in any of your pages,
function getListSeparator() {
var list = ['a', 'b'], str;
if (list.toLocaleString) {
str = list.toLocaleString();
if (str.indexOf(';') > 0 && str.indexOf(',') == -1) {
return ';';
}
}
return ',';
}
The key is in the toLocaleString method that uses the system list separator of the client side
You could use JavaScript to get the list separator and set it in a cookie which you could then detect from your server to generate the file as needed
And also have you try changing the contenttype to
application/vnd.openxmlformats-officedocument.spreadsheetml.sheet
or
application/vnd.ms-excel

Generate PDF using wkhtmltopdf.exe in c#

I am generating PDF using wkhtmltopdf.exe with below code.
string url = HttpContext.Current.Request.Url.AbsoluteUri;
//string[] strarry = sPath.Split('/');
//int lengh = strarry.Length;
var pdfUrl = HtmlToPdf(pdfOutputLocation: "~/PDF/", outputFilenamePrefix: "DT", urls: new string[] { url });
WebClient req = new WebClient();
HttpResponse response = HttpContext.Current.Response;
response.Clear();
response.ClearContent();
response.ClearHeaders();
response.Buffer = true;
Response.ContentType = "application/pdf";
response.AddHeader("Content-Disposition", "attachment;filename=\"" + pdfUrl.ToString().Substring(6) + "\"");
byte[] data = req.DownloadData(Server.MapPath(pdfUrl.ToString()));
response.BinaryWrite(data);
File.Delete(Server.MapPath(pdfUrl.ToString()));
response.End();
and
public static string HtmlToPdf(string pdfOutputLocation, string outputFilenamePrefix, string[] urls,
string[] options = null,
string pdfHtmlToPdfExePath = "C:\\Program Files\\wkhtmltopdf\\wkhtmltopdf.exe")
{
string urlsSeparatedBySpaces = string.Empty;
try
{
//Determine inputs
if ((urls == null) || (urls.Length == 0))
throw new Exception("No input URLs provided for HtmlToPdf");
else
urlsSeparatedBySpaces = String.Join(" ", urls); //Concatenate URLs
string outputFolder = pdfOutputLocation;
string outputFilename = outputFilenamePrefix + "_" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss-fff") + ".PDF"; // assemble destination PDF file name
var p = new System.Diagnostics.Process()
{
StartInfo =
{
FileName = pdfHtmlToPdfExePath,
Arguments = ((options == null) ? "" : String.Join(" ", options)) + " " + urlsSeparatedBySpaces + " " + outputFilename,
UseShellExecute = false, // needs to be false in order to redirect output
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true, // redirect all 3, as it should be all 3 or none
WorkingDirectory = HttpContext.Current.Server.MapPath(outputFolder)
}
};
p.Start();
// read the output here...
var output = p.StandardOutput.ReadToEnd();
var errorOutput = p.StandardError.ReadToEnd();
// ...then wait n milliseconds for exit (as after exit, it can't read the output)
p.WaitForExit(60000);
// read the exit code, close process
int returnCode = p.ExitCode;
p.Close();
// if 0 or 2, it worked so return path of pdf
if ((returnCode == 0) || (returnCode == 2))
return outputFolder + outputFilename;
else
throw new Exception(errorOutput);
//Response.ContentType = "application/pdf";
//Response.AddHeader("content-length", theData.Length.ToString());
//if (Request.QueryString["attachment"] != null)
// Response.AddHeader("content-disposition", "attachment; filename=ExampleSite.pdf");
//else
// Response.AddHeader("content-disposition", "inline; filename=ExampleSite.pdf");
//Response.BinaryWrite(theData);
//HttpContext.Current.ApplicationInstance.CompleteRequest();
}
catch (Exception exc)
{
throw new Exception("Problem generating PDF from HTML, URLs: " + urlsSeparatedBySpaces + ", outputFilename: " + outputFilenamePrefix, exc);
}
}
From above code the PDF is generating well.but I have two pages with the same URL for LogIn and Logout User.for example lets say www.xyz/pdf/brason .This same URL is used for LogIn and LogOut User but content will be different depending upon the User LogIn or Logout.
Now when I LogIn and try to generate the PDF using above code It always show me the content of Logout User Page.I am not sure how can i solve this issue.
I think if I understood correctly this is because wkhtmltopdf that is calling the page is not logged in. Wkhtmltopdf is kind of like creating a new incognito browser window without any login cookies/session so the page correctly thinks it's not logged in. You could maby check by debugging the request that the server gets when wkhtmltopdf calls it.
If this is the issue it can be difficult to solve. The solution depends on your login system and what you can do to go around the issue. If you can duplicate the login by using cookies you could maby set the login cookie yourself, see http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf_0.10.0_rc2-doc.html#Page%20Options for more info on how to set cookie.
Another option would be to first create a request from a system that returns the logged in HTML and then save that to a file/stream and feed that file/stream to wkhtmltopdf (I'm guessing you could do that using HttpContext.Current.Request or something, I don't know).
Another workaround would be to create a duplicate page of the logged in page that looks exactly like the logged in page but really isn't - this page would just be used to fool wkhtmltopdf. Something like www.xyz/pdf/brason?foolwkhtmltopdf=true and then use that by calling something like if(url.ToLower() == "www.xyz/pdf/brason") {url="www.xyz/pdf/brason?foolwkhtmltopdf=true"; }. This could be a security risk depending on what information is shown though.
Hope this helps!
i think you need to save the output of the page before you convert to html. Because this calls the url directly and you are not signed in when it calls it convert to pdf the response gotten for its request
i had the same problem trying to convert a webform to pdf but with the values filled so i saved the response as html and the gave wkhtmltopdf the saved path as parameter
Response.ContentType = "application/pdf";
Response.AddHeader("content-disposition", "attachment;filename=TestPage.pdf");
Response.Cache.SetCacheability(HttpCacheability.NoCache);
StringWriter sw = new StringWriter();
HtmlTextWriter hw = new HtmlTextWriter(sw);
this.Page.RenderControl(hw);
StringReader sr = new StringReader(sw.ToString());
string htmlpath =Server.MapPath("~/htmloutput.html");
if (File.Exists(htmlpath))
{
File.Delete(htmlpath);
}
File.Create(htmlpath).Dispose();
using (TextWriter tw = new StreamWriter(htmlpath))
{
tw.WriteLine(sw.ToString());
tw.Close();
}
string path = Server.MapPath("~/wkhtmltopdf-page.pdf");
PdfConvert.ConvertHtmlToPdf(new Codaxy.WkHtmlToPdf.PdfDocument
{
Url = htmlpath,
HeaderLeft = "[title]",
HeaderRight = "[date] [time]",
FooterCenter = "Page [page] of [topage]"
}, new PdfOutput
{
OutputFilePath = path
});
you can call this on a button click event. Only tested this on asp.net webforms. on asp.net mvc you need some other way to get the views html output

Two datatables export at two different Excel CSV files

You se finally I have 2 datatables filled with different data, now I have a button that allows me to send one datatable to a .CSV Excel file like this:
string name="Dat_Agrup";
HttpContext context = HttpContext.Current;
context.Response.Clear();
foreach (System.Data.DataColumn column in _myDataTable.Columns)
{
context.Response.Write("name"+ ",");
}
context.Response.Write(Environment.NewLine);
foreach (System.Data.DataRow row in _myDataTable.Rows)
{
for (int i = 0; i < _myDataTable.Columns.Count; i++)
{
context.Response.Write(row[i].ToString().Replace(",", string.Empty) + ",");
}
context.Response.Write(Environment.NewLine);
}
context.Response.ContentType = "text/csv";
context.Response.AppendHeader("Content-Disposition", "attachment; filename=" + name + ".csv");
context.Response.End();
Now this code works perfect it maybe missing some lines like where I declare the datatable but just trust me it works :D, now if I want to save the second datatable using the same code in the same action_button is those not work, i use this next code:
string name2="Centroids";
HttpContext context2 = HttpContext.Current;
context2.Response.Clear();
foreach (System.Data.DataRow row in _myDataTable2.Rows)
{
for (int i = 0; i < _myDataTable2.Columns.Count; i++)
{
context2.Response.Write(row[i].ToString().Replace(",", string.Empty) + ",");
}
context2.Response.Write(Environment.NewLine);
}
context2.Response.ContentType = "text2/csv";
context2.Response.AppendHeader("Content-Disposition", "attachment; filename=" + name2 + ".csv");
context2.Response.End();
It only save the first datatable and ignores the rest of the code can anyone explain the reason or why this happens, much appreciated any kind of help.
The reason is this line in your first code snippet:
context.Response.End();
The HttpResponse.End() method "stops execution of the page, and raises the EndRequest event."
If you'd like to continue processing the code, you can't call that method until the end.

Categories