I have exported table values to excel file through GridView using below C# code.
Response.ContentType = "application/vnd.xls";
Response.AddHeader("content-disposition","attachment;filename="+filename+".xls");
It was working well until recent security update from Microsoft [security update for microsoft excel 2010 kb3115322].
After the update, I am unable to view the content of Excel file. It is showing blank excel.
After uninstalling the update I can view the Excel but I need a solution through C# code.
Thanks in advance.
Yes due to Microsoft new security update issue is rising to current excel files format. So for solving and for a quick solution you should make csv (comma separated file) instead of xls so excel application will open the csv by ',' seperator.
Note : I faced this issue in my Php application , and I solved by making xls file with PHPExcel library.I hope you may find something like PHPExcel for C# as well.
Thanks. Feel free to comment.
I run into the same problem. My solution was to rewrite all Excel exports with ExcelPack. And I used XLSX and no longer XLS.
just in case rewriting is an option for you.
https://excelpackage.codeplex.com/
ExcelPackage package = new ExcelPackage();
ExcelWorksheet ws = package.Workbook.Worksheets[1];
//header
ws.Cells[1, 1].Value = "Column1";
ws.Cells[1, 2].Value = "Column2";
ws.Cells[1, 3].Value = "Column3";
ws.Cells[1, 4].Value = "Column4";
ws.Cells[1, 5].Value = "Column5";
//content
int i = 1;
foreach (Item item in list)
{
i++;
ws.Cells[i, 1].Value = item.Prop1;
ws.Cells[i, 2].Value = item.Prop2;
// format datetime
ws.Cells[i, 3].Value = item.Prop3.ToString("yyyy-MM-dd");
ws.Cells[i, 4].Value = item.Prop4;
ws.Cells[i, 5].Value = item.Prop5;
}
using (var memoryStream = new MemoryStream())
{
response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
response.AddHeader("content-disposition", $"attachment; filename=Filename.xlsx");
package.SaveAs(memoryStream);
memoryStream.WriteTo(response.OutputStream);
response.Flush();
response.End();
}
Related
I am using this code to create an excel instance which is used for making a report
excel = new Microsoft.Office.Interop.Excel.Application();
excel.Visible = true;
excel.DisplayAlerts = false;
worKbooK = excel.Workbooks.Add(XlWBATemplate.xlWBATWorksheet);
worKsheeT = worKbooK.Worksheets[1]; ;
worKsheeT.Name = "Report";
iCountW = 2;
worKsheeT.Cells[1, 1] = "S.No";
worKsheeT.Cells[1, 2] = "Weld Stud/Nut Name";
worKsheeT.Cells[1, 3] = "Weld Spot Clearance Status";
worKsheeT.Cells[1, 4] = "Weld Spot Name";
worKsheeT.Cells[1, 5] = "Coord-X";
worKsheeT.Cells[1, 6] = "Coord-Y";
worKsheeT.Cells[1, 7] = "Coord-Z";
// Some Code
// Some more code
// No more code
After updating the data rows of this report I am using the below code for saving the excel workbook which is not letting me save the workbook.
string filename = Environment.GetFolderPath(Environment.SpecialFolder.CommonDesktopDirectory) + "\\" + "Trial_StudNut.xlsx";
if (!System.IO.File.Exists(filename))
{
worKbooK.SaveAs(filename, Excel.XlSaveAsAccessMode.xlNoChange);
}
Can someone help me with what am I missing to avoid exceptions while saving the workbook?
Edit: I am getting the following
(HRESULT: 0x800A03EC Error while saving Excel file)
The code is getting inside the condition and then falling into the exception.
I want to insert value on my excel ,but i have a problem when i run my application, its create a new file excel ,doesnt insert value into existing file,
using (ExcelPackage excel = new ExcelPackage())
{
excel.Workbook.Worksheets.Add("Worksheet1");
// Target a worksheet
var worksheet = excel.Workbook.Worksheets["Worksheet1"];
worksheet.Cells[1, 1].Value = "Name";
worksheet.Cells[2, 1].Value = "ID";
FileInfo excelFile = new FileInfo(#"E:\ExcelTest.xls");
excel.SaveAs(excelFile);
I want my Program insert into existing file ,not create a new one,
how i can solve this?
The EPPlus Wiki Getting Started covered this exact scenario.
FileInfo excelFile = new FileInfo(#"E:\ExcelTest.xls");
using (ExcelPackage excel = new ExcelPackage(excelFile))
{
// Target a worksheet
var worksheet = excel.Workbook.Worksheets["Worksheet1"];
worksheet.Cells[1, 1].Value = "Name";
worksheet.Cells[2, 1].Value = "ID";
excel.Save();
}
I am trying to overwrite data in excel sheet. The way I do it is by deleting the content from the the sheet and then writing range of data. The problem is when I write the data it deletes the cell format and then places my numbers as text.
is there a way to keep the format which the user has defined so when I write data it uses the same format?
You can Use the Microsoft.Office.Interop.Excel dll file. Add it in your project reference and in your Code as Using using Excel = Microsoft.Office.Interop.Excel;
Then check the below code. Also to you this dll there should be Microsoft Excel Installed in the machine where this code is going to run.
Excel.Application excel = new Excel.Application();
excel.DisplayAlerts = false;
excel.Workbooks.Add();
Excel.Worksheet worksheet = excel.ActiveSheet;
int rowIndex = 2 ;
worksheet.Cells[1, "A"] = "List Title";
worksheet.Cells[1, "B"] = "Item Count";
Console.WriteLine("Copying the contents to Excel");
foreach (var list in listCollection)
{
worksheet.Cells[rowIndex, "A"] = list.Title;
worksheet.Cells[rowIndex, "B"] = list.ItemCount;
rowIndex++;
//Console.Write("List Title: {0}", list.Title);
//Console.WriteLine("\t"+"Item Count:"+list.ItemCount);
}
string fileName = string.Format(#"C:\FileName.xlsx");
worksheet.SaveAs(fileName);
Console.WriteLine("Export Completed");
Console.ReadLine();
excel.Quit();
GC.Collect();
I have a few different dictionaries with different categories of information and I need to output them all into an xls or csv file with multiple spreadsheets. Currently, I have to download each excel file for a specific date range individually and then copy and paste them together so they're on different sheets of the same file. Is there any way to download all of them together in one document? Currently, I use the following code to output their files:
writeCsvToStream(
organize.ToDictionary(k => k.Key, v => v.Value as IacTransmittal), writer
);
ms.Seek(0, SeekOrigin.Begin);
Response.Clear();
Response.AddHeader("Content-Disposition", "attachment; filename=" + fileName);
Response.AddHeader("Content-Length", ms.Length.ToString());
Response.ContentType = "application/octet-stream";
ms.CopyTo(Response.OutputStream);
Response.End();
where writeCsvToStream just creates the text for the individual file.
There are some different options you could use.
ADO.NET Excel driver - with this API you can populate data into Excel documents using SQL style syntax. Each worksheet in the workbook is a table, each column header in a worksheet is a column in that table etc.
Here is a code project article on the exporting to Excel using ADO.NET:
http://www.codeproject.com/Articles/567155/Work-with-MS-Excel-and-ADO-NET
The ADO.NET approach is safe to use in a multi-user, web app environment.
Use OpenXML to export the data
OpenXML is a schema definition for different types of documents and the later versions of Excel (the ones that use .xlsx, .xlsm etc. instead of just .xls) use this format for the documents. The OpenXML schema is huge and somewhat cumbersome, however you can do pretty much anything with it.
Here is a code project article on exporting data to Excel using OpenXML:
http://www.codeproject.com/Articles/692121/Csharp-Export-data-to-Excel-using-OpenXML-librarie
The OpenXML approach is safe to use in a multi-user, web app environment.
A third approach is to use COM automation which is the same as programmatically running an instance of the Excel desktop application and using COM to control the actions of that instance.
Here is an article on that topic:
http://support.microsoft.com/kb/302084
Note that this third approach (office automation) is not safe in a multi-user, web app environment. I.e. it should not be used on a server, only from standalone desktop applications.
If you're open to learning a new library, I highly recommend EPPlus.
I'm making a few assumptions here since you didn't post much code to translate, but an example of usage may look like this:
using OfficeOpenXml;
using OfficeOpenXml.Style;
public static void WriteXlsOutput(Dictionary<string, IacTransmittal> collection) //accepting one dictionary as a parameter
{
using (FileStream outFile = new FileStream("Example.xlsx", FileMode.Create))
{
using (ExcelPackage ePackage = new ExcelPackage(outFile))
{
//group the collection by date property on your class
foreach (IGrouping<DateTime, IacTransmittal> collectionByDate in collection
.OrderBy(i => i.Value.Date.Date)
.GroupBy(i => i.Value.Date.Date)) //assuming the property is named Date, using Date property of DateTIme so we only create new worksheets for individual days
{
ExcelWorksheet eWorksheet = ePackage.Workbook.Worksheets.Add(collectionByDate.Key.Date.ToString("yyyyMMdd")); //add a new worksheet for each unique day
Type iacType = typeof(IacTransmittal);
PropertyInfo[] iacProperties = iacType.GetProperties();
int colCount = iacProperties.Count(); //number of properties determines how many columns we need
//set column headers based on properties on your class
for (int col = 1; col <= colCount; col++)
{
eWorksheet.Cells[1, col].Value = iacProperties[col - 1].Name ; //assign the value of the cell to the name of the property
}
int rowCounter = 2;
foreach (IacTransmittal iacInfo in collectionByDate) //iterate over each instance of this class in this igrouping
{
int interiorColCount = 1;
foreach (PropertyInfo iacProp in iacProperties) //iterate over properties on the class
{
eWorksheet.Cells[rowCounter, interiorColCount].Value = iacProp.GetValue(iacInfo, null); //assign cell values by getting the value of each property in the class
interiorColCount++;
}
rowCounter++;
}
}
ePackage.Save();
}
}
}
Thanks for the ideas! I was eventually able to figure out the following
using Excel = Microsoft.Office.Interop.Excel;
Excel.Application ExcelApp = new Excel.Application();
Excel.Workbook ExcelWorkBook = null;
Excel.Worksheet ExcelWorkSheet = null;
ExcelApp.Visible = true;
ExcelWorkBook = ExcelApp.Workbooks.Add(Excel.XlWBATemplate.xlWBATWorksheet);
List<string> SheetNames = new List<string>()
{ "Sheet1", "Sheet2", "Sheet3", "Sheet4", "Sheet5", "Sheet6", "Sheet7"};
string [] headers = new string []
{ "Field 1", "Field 2", "Field 3", "Field 4", "Field 5" };
for (int i = 0; i < SheetNames.Count; i++)
ExcelWorkBook.Worksheets.Add(); //Adding New sheet in Excel Workbook
for (int k = 0; k < SheetNames.Count; k++ )
{
int r = 1; // Initialize Excel Row Start Position = 1
ExcelWorkSheet = ExcelWorkBook.Worksheets[k + 1];
//Writing Columns Name in Excel Sheet
for (int col = 1; col < headers.Length + 1; col++)
ExcelWorkSheet.Cells[r, col] = headers[col - 1];
r++;
switch (k)
{
case 0:
foreach (var kvp in Sheet1)
{
ExcelWorkSheet.Cells[r, 1] = kvp.Value.Field1;
ExcelWorkSheet.Cells[r, 2] = kvp.Value.Field2;
ExcelWorkSheet.Cells[r, 3] = kvp.Value.Field3;
ExcelWorkSheet.Cells[r, 4] = kvp.Value.Field4;
ExcelWorkSheet.Cells[r, 5] = kvp.Value.Field5;
r++;
}
break;
}
ExcelWorkSheet.Name = SheetNames[k];//Renaming the ExcelSheets
}
//Activate the first worksheet by default.
((Excel.Worksheet)ExcelApp.ActiveWorkbook.Sheets[1]).Activate();
//Save As the excel file.
ExcelApp.ActiveWorkbook.SaveCopyAs(#"out_My_Book1.xls");
I have the following method that eventually creates a CSV file and returns the file as a response to a client request.
How can I change the column width to autofit and have alternate coloring of rows?
public static void ExportToCSV(DataTable dt, HttpResponseBase response, string filename)
{
response.AddHeader("content-disposition", "attachment; filename=" + filename);
response.ClearContent();
response.ContentType = "application/vnd.ms-excel";
response.Charset = "UTF-8";
response.ContentEncoding = System.Text.Encoding.Unicode;
response.BinaryWrite(System.Text.Encoding.Unicode.GetPreamble());
string tab = "";
foreach (DataColumn dc in dt.Columns)
{
if (!dc.ColumnName.StartsWith("_"))
{
response.Write(tab + dc.ColumnName);
tab = "\t";
}
}
response.Write("\n");
int i;
foreach (DataRow dr in dt.Rows)
{
tab = "";
for (i = 0; i < dt.Columns.Count; i++)
{
if (!dr.Table.Columns[i].ColumnName.StartsWith("_"))
{
response.Write(Utils.StripHTML(tab + dr[i].ToString().Replace("\n", " ").Replace("\t", " ")));
tab = "\t";
}
}
response.Write("\n");
}
response.End();
}
CSV file is just plain text where values are separated by an agreed separator (usually comma, hence the name, in your case it's TAB character).
Excel has a support for CSV files in such way it represent every value in separate column. This is only visual representation but the file has no actual columns, and cannot contain any form of formatting.
You'd need to change the format of the file to Excel format, and create it that way. You could use Excel interop or writing it as an excel XML file. I'd recommend second option. For a working example of Excel XML you can check this CodeProject example.
You are currently creating a delimited text file.
As the file is a normal text file, it can not have any formatting applied.
Your requirements are to generate an excel file with formatting and certain width, as such this can only be achieved by producing an excel file directly.
This can be done using interop or by outputting the xml required, but some kind of excel library is probably easier to implement without worrying about the details. I personally prefer EPPlus. It is a useful library for creating Excel spreadsheet for excel 2007 onwards. You can install the library using nugget or via a download from the website.
The following gives a quick overview of how to achieve this.
public static void ExportToCSV(DataTable dt, HttpResponseBase response, string filename)
{
response.AddHeader("content-disposition", "attachment; filename=" + filename);
response.ClearContent();
response.ContentType = "application/vnd.ms-excel";
response.Charset = "UTF-8";
response.ContentEncoding = System.Text.Encoding.Unicode;
response.BinaryWrite(System.Text.Encoding.Unicode.GetPreamble());
ExcelPackage package = new ExcelPackage();
package.Workbook.Properties.Comments = "Demo Excel Generation";
package.Workbook.Worksheets.Add("DemoSheet");
ExcelWorksheet sheet = package.Workbook.Worksheets["DemoSheet"];
bool altColour = false;
for (int i = 1; i < 10; i++)
{
for (int j = 1; j < 10; j++)
{
sheet.Cells[i, j].Value = string.Format("{0} - {1}", i, j);
sheet.Row(j).Style.Fill.PatternType = ExcelFillStyle.Solid;
sheet.Row(j).Style.Fill.BackgroundColor.SetColor(altColour ? Color.Gold : Color.Goldenrod);
altColour = !altColour;
}
sheet.Column(i).AutoFit(5f); // Set minimum width to 5 points
}
//package.File = new System.IO.FileInfo(#"C:\test.xlsx");
//package.Save();
package.SaveAs(response.OutputStream);
Response.End();
}
Another library is ClosedXML which has (in my opinion) a nicer syntax than other possibilities by allowing to chain methods. For example:
XLWorkbook workbook = new XLWorkbook("test.xlsx");
IXLWorksheet worksheet = workbook.AddWorksheet("Sheet1");
worksheet.Cell(1, 1).SetValue("Test").Style.Font.SetBold(true);
worksheet.AdjustToContent(); // this changes the column width to fit the content
workbook.Save();