I have a html content which I would like to export as excel file. My function for exporting to excel looks like this:
public ActionResult ExportToExcel(string htmlToExport)
{
using (ExcelPackage ep = new ExcelPackage())
{
string fileTemplate = "test.xlsx";
using (FileStream stream = new FileStream(HttpContext.Server.MapPath("~/") + ConfigurationManager.AppSettings["templatePath"] + fileTemplate, FileMode.Open))
{
ep.Load(stream);
}
ExcelWorksheet ws = ep.Workbook.Worksheets.First();
Response.AppendHeader("Content-Disposition", fileTemplate);
return File(ep.GetAsByteArray(), "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
}
}
Is there a way to paste html to excel file? If I do this manually, everything is OK. I would like to do this on the server side and return excel file with pasted html inside. Is this possible?
Of course it's possible. My code sample is below;
public ActionResult BankAccountReport(BankAccountsInfoFilter bankAccountsInfoFilter)
{
var bankAccountInfos = service.GetBankAccounts(bankAccountsInfoFilter);
DetailReportExport(bankAccountInfos);
return new EmptyResult();
}
[NonAction]
public void DetailReportExport(List<BankAccountViewModel> bankAccountInfos)
{
string html = RenderPartialViewToString("_BankAccountDetailReport", bankAccountInfos);
Response.ClearContent();
Response.AddHeader("content-disposition", "attachment; filename=BankAccountInfoDetailReport.xls");
Response.ContentType = "application/excel";
Response.AddHeader("content-language", "tr-TR");
Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.BinaryWrite(System.Text.Encoding.UTF8.GetPreamble());
Response.Write(html);
}
Related
I'm getting this error in ExcelPackage.GetAsByteArray() while exporting excel. I have tried everything as UTF-8 encoding etc but nothing works.
Below is my code
public void function Export()
{
ExcelPackage package = ExportUtil.GetMacroEnabledExtract(ds, extractName, "Comments");
Response.Clear();
HttpContext.Current.Response.ClearContent();
HttpContext.Current.Response.ClearHeaders();
HttpContext.Current.Response.Buffer = true;
HttpContext.Current.Response.ContentEncoding = System.Text.Encoding.UTF8;
Response.ContentType = "application/vnd.ms-excel";
Response.AddHeader("Content-Disposition", "attachment;filename=\"" + ExportUtil.getFileName(extractName, ".xlsm") + "\"");
Response.BinaryWrite(package.GetAsByteArray());
Response.End();
}
export function
public static ExcelPackage GetMacroEnabledExtract(DataSet ds, string extractName, string dataSheetName)
{
string appDataPath = HostingEnvironment.MapPath(#"~/App_Data");
string filePath = Path.Combine(appDataPath, "MacroTemplate.xlsm");
FileInfo templateFile = new FileInfo(filePath);
ExcelPackage package = new ExcelPackage(templateFile, false);
string fileName = getFileName(extractName, ".xlsm");
createDataWorkSheetMacroEnabled(package, ds.Tables[0], dataSheetName, templateFile); //Sheet 1
return package;
}
private static void createDataWorkSheetMacroEnabled(ExcelPackage package, DataTable table, string worksheetName, FileInfo file)
{
ExcelWorksheet wsData = package.Workbook.Worksheets[1];
wsData.Cells["A1"].LoadFromDataTable(table, true);
ExcelTextFormat format = new ExcelTextFormat();
format.Encoding = new UTF8Encoding();
wsData.Cells.LoadFromText(file, format);
}
How to download an excel in a chrome browser having options as Open, Save and Cancel as I used closed Xml in C#?
public FileResult ExportToExcel(List<MyStudentList_Result> StudentList)
{
List<string[]> titles = new List<string[]> { new string[] { "name", "Number", "Type", "syllabus", "Title", "Added" } };
byte[] fileStream = ExportToExcel(StudentList, "StudentList", titles);
string mimeType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AppendHeader("Content-Disposition", "inline; filename=" + "StudentList.xlsx");
return File(fileStream, mimeType);
}
public byte[] ExportToExcel(List<MystudentList_Result> StudentList, string worksheetTitle, List<string[]> titles)
{
var wb = new XLWorkbook(); //create workbook
var ws = wb.Worksheets.Add(worksheetTitle); //add worksheet to workbook
var rangeTitle = ws.Cell(1, 1).InsertData(titles); //insert titles to first row
rangeTitle.AddToNamed("Titles");
var titlesStyle = wb.Style;
titlesStyle.Font.Bold = true; //font must be bold
// titlesStyle.Alignment.Horizontal = XLAlignmentHorizontalValues.Center; //align text to center
wb.NamedRanges.NamedRange("Titles").Ranges.Style = titlesStyle; //attach style to the range
if (StudentList!= null && StudentList.Count() > 0)
{
//insert data to from second row on
ws.Cell(2, 1).InsertData(StudentList);
ws.Columns().AdjustToContents();
}
//save file to memory stream and return it as byte array
using (var ms = new MemoryStream())
{
wb.SaveAs(ms);
return ms.ToArray();
}
}
You can guide what the browser does with the Content-Disposition header. For saving the file you should use attachment:
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
I am trying to download Excel file using web API but I am unable to download file in postman where as I am able to download Excel file when I enter URL in browser though while opening file I get warning message like below :
When i hit endpoint using POSTMAN then file get corrupted and it is showing junk characters.
Code :
protected virtual byte[] ExportToXlsx<T>(IEnumerable<T> itemsToExport)
{
using (var stream = new MemoryStream())
{
using (var xlPackage = new ExcelPackage())
{
// get handles to the worksheets
var worksheet = xlPackage.Workbook.Worksheets.Add(typeof(T).Name);
//create Headers and format them
var manager = new PropertyManager<T>(itemsToExport.First());
manager.WriteCaption(worksheet, SetCaptionStyle);
var row = 2;
foreach (var items in itemsToExport)
{
manager.CurrentObject = items;
manager.WriteToXlsx(worksheet, row++, false);
}
xlPackage.Save();
}
return stream.ToArray();
}
}
private readonly IServiceContext ctx;
public void Download(string guid)
{
var bytes = ExportToXlsx(list);
ctx.reqobj.HttpContext.Response.Headers.Add("Content-Disposition", "attachment; filename=\"demo.xlsx\"");
ctx.reqobj.HttpContext.Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
ctx.reqobj.HttpContext.Response.Body.Write(bytes, 0, bytes.Length);
}
Note : I am using OfficeOpenXml for Excel file creation.
I will appreciate any help.
Update :
Try using "Send and download" instead of "Send"
https://www.getpostman.com/docs/v6/postman/sending_api_requests/responses
Postman doesn't download any file just return you the data that the server or your service provides. i have a project that download an excel to with the OpenXML here is an example with which you can guide with some styles to.
[HttpGet]
public void DownloadTable(int id)
{
List<Employee> all = db.Employees.Where(x => x.ManagerId == id).ToList();
String file = "Example.xlsx";
String path = Path.Combine(HttpContext.Current.Server.MapPath("~/App_Data"), file);
List<string[]> headerRow = new List<string[]>() { new string[] { "EmployeeId", "Name", "Shift", "Timestamp" } };
string headerRange = "A2:" + Char.ConvertFromUtf32(headerRow[0].Length + 64) + "2";
ExcelPackage excel = new ExcelPackage();
excel.Workbook.Worksheets.Add("Employees");
var page = excel.Workbook.Worksheets["Employees"];
page.Cells["A1:D1"].Merge = true;
page.Cells["A1:D1"].Value = "Supervisor: " + all.FirstOrDefault().Manager + " - " + id;
page.Cells["A1:D1"].Style.Font.Bold = true;
page.Cells[headerRange].LoadFromArrays(headerRow);
int z = 3;
foreach (Reporte r in all)
{
page.Cells["A" + z].Value = r.Id;
page.Cells["B" + z].Value = r.Name;
page.Cells["C" + z].Value = r.Shift;
page.Cells["D" + z].Value = r.Timestamp;
z++;
}
page.Cells["D3:D" + z].Style.Numberformat.Format = "dddd dd MMMM YYYY";
page.Cells["A2:D2"].AutoFilter = true;
page.Cells["A1:D" + z].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
page.Cells["A1:D" + z].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
page.Cells["A2:D" + z].AutoFitColumns();
page.Cells["A1:D1"].Style.Fill.PatternType = ExcelFillStyle.Solid;
page.Cells["A1:D1"].Style.Fill.BackgroundColor.SetColor(Color.FromArgb(1, 183, 222, 232));
FileInfo excelFile = new FileInfo(path);
excel.SaveAs(excelFile);
System.Web.HttpResponse response = System.Web.HttpContext.Current.Response;
response.ClearContent();
response.Clear();
response.ContentType = "text/plain";
response.AddHeader("Content-Disposition",
"attachment; filename=" + file + ";");
response.TransmitFile(path);
response.Flush();
response.End();
File.Delete(path);
}
The stream needs to be passed to the package.
Right now nothing is being given to the package,
//...
using (var xlPackage = new ExcelPackage())
//...
So nothing is being saved to the stream, which is why the error is shown when trying to open the file.
There is no need to convert the memory stream to an array. Return the stream and pass that along for the response.
protected virtual Stream ExportToXlsx<T>(IEnumerable<T> itemsToExport) {
var stream = new MemoryStream();
using (var xlPackage = new ExcelPackage(stream)) { //<<< pass stream
// get handles to the worksheets
var worksheet = xlPackage.Workbook.Worksheets.Add(typeof(T).Name);
//create Headers and format them
var manager = new PropertyManager<T>(itemsToExport.First());
manager.WriteCaption(worksheet, SetCaptionStyle);
var row = 2;
foreach (var items in itemsToExport) {
manager.CurrentObject = items;
manager.WriteToXlsx(worksheet, row++, false);
}
xlPackage.Save();
}
return stream;
}
A controller action to return the file would look like this
public IActionResult Download(string guid) {
//...get list
var file = ExportToXlsx(list);
var contentType = "application/vnd.openxmlformats";
var fileName = "demo.xlsx";
return File(file, contentType, fileName); //returns a FileStreamResult
}
It was indicated in comments that the above is done in a support method.
Using the same approach
private readonly IServiceContext ctx;
//...
public void Download(string guid) {
//...get list
using(var fileStream = ExportToXlsx(list)) {
if (fileStream.CanSeek && fileStream.Position != 0) {
fileStream.Seek(0, SeekOrigin.Begin);
}
var contentType = "application/vnd.openxmlformats";
var fileName = "demo.xlsx";
var response = ctx.reqobj.HttpContext.Response;
response.Headers.Add("Content-Disposition", $"attachment; filename=\"{fileName}\"");
response.Headers.Add("Content-Length", fileStream.Length.ToString());
response.ContentType = contentType;
fileStream.CopyTo(response.Body);
}
}
the generated file is copied over to the body of the response.
As for postman, the tool is simply showing the content return in the response. It does not try to download the actual file as an attachment.
I'm trying to have a website export a .xlsm file and I can't seem to find anything that helps. Here's a simple example I'm using to test building a .xlsx file (which works).
#using OfficeOpenXml;
<html>
<body>
<div id="page-wrapper">
#{
// Change file extension to xlsm to test
string fileExtension = "xlsm";
ExcelPackage p = new ExcelPackage();
p.Workbook.Worksheets.Add("Worksheet Name");
int LatestWorksheetNumber = p.Workbook.Worksheets.Count;
ExcelWorksheet ws = p.Workbook.Worksheets[LatestWorksheetNumber];
ws.Cells[1, 1].Value = "Test";
//Generate A File
Byte[] bin = p.GetAsByteArray();
string filename = "filename";
try
{
//Download the file as an attachment
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.Cookies.Clear();
string ContentType = "";
if (fileExtension == "xlsx")
{
ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
else
{
ContentType = "application/vnd.ms-excel.sheet.macroEnabled.12";
}
Response.GetType();
Response.ContentType = ContentType;
Response.AddHeader("content-disposition", "attachment; filename=" + filename + "." + fileExtension);
Response.BinaryWrite(bin);
Response.End();
<p>File Created</p>
}
catch (Exception e)
{
<p>#e.Message</p>
}
}
</div>
</body>
</html>
After changing the file extension to .xlsm the file is generated but when I try to open the file in Excel I get an error saying that the extension isn't correct. I thought the only thing I would have to change would be the content type header but that's obviously not the issue. What else am I missing??? Any guidance would be appreciated!
Xiaoy312 nailed the issue! Adding p.Workbook.CreateVBAProject(); before Byte[] bin = p.GetAsByteArray(); solved my issue! Everything else stayed the same but Excel will actually open the files now! Here's my final code for anyone who has the same issue:
#using OfficeOpenXml;
<html>
<body>
<div id="page-wrapper">
#{
// Change file extension to xlsm to test
string FileExtension = "xlsm";
ExcelPackage p = new ExcelPackage();
p.Workbook.Worksheets.Add("Worksheet Name");
int LatestWorksheetNumber = p.Workbook.Worksheets.Count;
ExcelWorksheet ws = p.Workbook.Worksheets[LatestWorksheetNumber];
ws.Cells[1, 1].Value = "Test";
p.Workbook.CreateVBAProject();
//Generate A File
Byte[] bin = p.GetAsByteArray();
string filename = "filename";
try
{
//Download the file as an attachment
Response.Clear();
Response.ClearContent();
Response.ClearHeaders();
Response.Cookies.Clear();
string ContentType = "";
if (FileExtension == "xlsx")
{
ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
}
else
{
ContentType = "application/vnd.ms-excel.sheet.macroEnabled.12";
}
Response.GetType();
Response.ContentType = ContentType;
Response.AddHeader("content-disposition", "attachment; filename=" + filename + "." + FileExtension);
Response.BinaryWrite(bin);
Response.End();
<p>File Created</p>
}
catch (Exception e)
{
<p>#e.Message</p>
}
}
</div>
</body>
</html>
I am getting the following error:
, value hexadecimal 0x02, caracter not valid.
using this code:
using (XLWorkbook wb = new XLWorkbook())
{
wb.Worksheets.Add(dt1);
Response.Clear();
Response.Buffer = true;
Response.Charset ="";
Response.ContentType = "application/vnd.openxmlformats- officedocument.spreadsheetml.sheet";
//Response.AddHeader("content-disposition", "attachment;filename=GridView.xlsx");
Response.AddHeader("content-disposition", "attachment;filename=" + filename);
using (MemoryStream MyMemoryStream = new MemoryStream())
{
wb.SaveAs(MyMemoryStream);
MyMemoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}
I have tried different ways, but I still get the same error. "dt1" is filled from stored procedure.
to use ClosedXML I am currently doing the following and I call this method to open the Excel from a web page.
to call the ExportToExcel_SomeReport you would do it like this I create a public static class called Extensions
Extensions.ExportToXcel_SomeReport(dt1, fileName, this.Page);//Call the method on your button click
//this will be in the static public class you create
internal static void ExportToXcel_SomeReport(DataTable dt, string fileName, Page page)
{
var recCount = dt.Rows.Count;
fileName = string.Format(fileName, DateTime.Now.ToString("MMddyyyy_hhmmss"));
var xlsx = new XLWorkbook();
var ws = xlsx.Worksheets.Add("Some Custom Report");
ws.Style.Font.Bold = true;
ws.Cell("C5").Value = "Some Custom Header Report";
ws.Cell("C5").Style.Font.FontColor = XLColor.Black;
ws.Cell("C5").Style.Font.SetFontSize(16.0);
ws.Cell("E5").Value = DateTime.Now.ToString("MM/dd/yyyy HH:mm");
ws.Range("C5:E5").Style.Font.SetFontSize(16.0);
ws.Cell("A7").Value = string.Format("{0} Records", recCount);
ws.Style.Font.Bold = false;
ws.Cell(9, 1).InsertTable(dt.AsEnumerable());
ws.Row(9).InsertRowsBelow(1);
// ws.Style.Font.FontColor = XLColor.Gray;
ws.Columns("1-8").AdjustToContents();
ws.Tables.Table(0).ShowAutoFilter = true;
ws.Style.Alignment.Horizontal = XLAlignmentHorizontalValues.Center;
DynaGenExcelFile(fileName, page, xlsx);
}
private static void DynaGenExcelFile(string fileName, Page page, XLWorkbook xlsx)
{
page.Response.ClearContent();
page.Response.ClearHeaders();
page.Response.ContentType = "application/vnd.ms-excel";
page.Response.AppendHeader("Content-Disposition", string.Format("attachment;filename={0}.xls", fileName));
using (MemoryStream memoryStream = new MemoryStream())
{
xlsx.SaveAs(memoryStream);
memoryStream.WriteTo(page.Response.OutputStream);
memoryStream.Close();
}
page.Response.Flush();
page.Response.End();
}