My requirement is to open an excel file which is under Attachment folder. So I took the reference from here and used abatishchev answer for my requirement. So I tried that in my below code.
public void ExportExcel()
{
string str_lwpc_query = string.Empty;
str_lwpc_query = "select company_name 'COMPANY NAME',Deputed_Company_Name 'DEPUTED COMPANY NAME',emp_card_no 'EMP CODE',emp_name 'EMPLOYEE NAME',LWP,'' Remarks, " +
"Adj_Days Gain_Loss_LOP_Days, VAL_DAY LOP_Days_Desc, month, year from XXACL_EMP_INFO_LWP_OTDAYS_HRS_V " +
"where emp_type='C' and month = '3' and year = '2015' ";
DataTable Dt_lwpc = new DataTable();
Dt_lwpc = CF.ExecuteDT(str_lwpc_query);
DataSet DS_lwpc = new DataSet();
DS_lwpc.Tables.Add(Dt_lwpc);
DS_lwpc.Tables[0].TableName = "Employee loss of pay for consultant Details";
var directory = Server.MapPath("~/Attachment/");
ExcelLibrary.DataSetHelper.CreateWorkbook(directory + "Employee_lwpc_Details.xls", DS_lwpc);
Microsoft.Office.Interop.Excel.Application excel = new Microsoft.Office.Interop.Excel.Application();
ExcelLibrary.Office.Excel.Workbook wb = excel.Workbooks.Open(ExcelLibrary.DataSetHelper.CreateWorkbook(directory + "Employee_lwpc_Details.xls", DS_lwpc));
}
but I get error in the last line as
The best overloaded method match for Microsoft.Office.Interop.Excel.Workbooks.Open(string, object, object, object, ...........) has some invalid arguments
kindly suggest what is wrong
If you want users of your website to open an excel file that you've created on server, than you don't need to open it there - just send it to the user. Replace the last two lines of code with this:
string filePath = directory + "Employee_lwpc_Details.xls";
Response.ContentType = "Application/vnd.ms-excel";
Response.AppendHeader("content-disposition",
"attachment; filename=" + "Employee_lwpc_Details.xls");
Response.TransmitFile(filePath);
Response.End();
Microsoft.Office.Interop.Excel.Workbooks.Open takes a filename and a number of additional parameters, see the MSDN documentation here. The CreateWorkbook method that you're calling is not returning the required arguments for Open.
Related
I have an Entity Framework project, I have tables named
dbo.patient
dbo.doctor
dbo.disease
These three tables are interconnected.
I need to convert the patient data with doctor name and disease name into an Excel format file... what do I have to do to accomplish this?
I have no idea how to do it...
Can anyone provide steps?
Should I create a stored procedure? How to convert data to Excel format?
Can I do it without using a stored procedure?
You can use free and opensource library called EPPlus for that.
Here is the Link :
EPPlus-Create advanced Excel spreadsheets
Here is how to do that ..
Step 1 :
Run following command on the Package Manager console :
PM > install-package epplus
Step 2 :
This is the method for exporting data :
Note : You can replace the data with your actual data after retrieving it from the server by using EF query.
public void ExportListUsingEPPlus()
{
//this is the data retrieval point you have to replace with your data
var data = new[]{
new{ Name="Myname", Email="myna#google.com"},
new{ Name="yourname", Email="your#yahoo.com"},
new{ Name="saman", Email="saman#yahoo.com"},
};
ExcelPackage excel = new ExcelPackage();
var workSheet = excel.Workbook.Worksheets.Add("Sheet1");
workSheet.Cells[1, 1].LoadFromCollection(data, true);
using (var memoryStream = new MemoryStream())
{
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Contact.xlsx");
excel.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.End();
}
}
You can export data in html or csv format and let Excel do the conversion. This has it's own pitfalls.
For example, with csv, if you have text data that looks like a date or a number, Excel will convert it to a date or a number. When this might happen, I put a tab character into the data to stop it.
And, with html, if you tell the browser that it should be opened using Excel, the user gets a warning that the format isn't Excel.
Nonetheless, I have used these techniques to do simple exports in my MVC application without resorting to a library.
To set the response to Excel (for html output):
protected void SetResponseToExcel(string fileName)
{
HttpContext.Response.Clear();
HttpContext.Response.AddHeader("content-disposition",
"attachment;filename=" + fileName);
HttpContext.Response.Charset = "";
HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Response.ContentType = "application/vnd.ms-excel";
}
To set the response to csv:
protected void SetResponseToText(string fileName)
{
HttpContext.Response.Clear();
HttpContext.Response.AddHeader("content-disposition",
"attachment;filename=" + fileName);
HttpContext.Response.Charset = "";
HttpContext.Response.Cache.SetCacheability(HttpCacheability.NoCache);
HttpContext.Response.ContentType = "text/csv";
}
To do the export:
public ActionResult MyExport()
{
SetResponseToText("MyFilename.csv");
Response.Write(String.Format("\"{0}\",...,{26}",
"Heading 1", ..., Environment.NewLine));
Response.Flush();
IEnumerable<MyClass> exportData = _MyService.GetMyData();
foreach (var row in exportData)
{
Response.Write(String.Format("\"{0}\"...,{26}",
"\t" + row.Field1, //tab character to force Excel to treat it as text
row.Field2, ..., Environment.NewLine));
}
Response.Flush();
Response.End();
return null;
}
I have a method that currently exports the results of a stored procedure to a CSV file. I've been tasked with altering it to export to XLS but I'm having some trouble.
The code:
protected void ExportFundingSummaryToExcelSA(Object sender, EventArgs e)
{
const string fileName = "METT Dashboard - Funding Summary";
const string rowFormat = "{0},{1},{2},{3},{4},{5}\n";
Response.Clear();
Response.Buffer = true;
Response.AddHeader("content-disposition", "attachment;filename=" + fileName + ".csv");
Response.Charset = "";
Response.ContentType = "text/csv";
GetCompanyGroupCode();
var sb = new StringBuilder();
sb.AppendFormat(rowFormat, "Sector", "Product Line", "Program Number", "Program Description","Participating Companies", "Gross");
var customerId = CurrentUser.Company.Id;
var year = 2015;
// Set Title Row
Response.Write(year + " Products Lines for: " + CurrentUser.Company.Name + " (" + customerId + ")\n");
// Set Generated Date (Report Created on: 9/29/2004 3:33:32 PM)
Response.Write("Report Created on: " + System.DateTime.Now.ToString() + "\n\n\n");
var fundingData = GetFundingData();
if (fundingData != null)
{
if (fundingData.Summary != null && fundingData.Summary.Count > 0)
{
var summaries = MoveSetAsidesDown(fundingData.Summary);
for (var i = 0; i < summaries.Count; i++)
{
if (fundingData.Programs != null && fundingData.Programs.Count > 0)
{
foreach (var program in fundingData.Programs)
{
if (program.PlId == summaries[i].PlId)
{
sb.AppendFormat(rowFormat,
SharePointUtil.ToCsvFriendly(summaries[i].SectorName),
SharePointUtil.ToCsvFriendly(summaries[i].PlName),
SharePointUtil.ToCsvFriendly(program.TargetId.ToString()),
SharePointUtil.ToCsvFriendly(program.TargetName),
SharePointUtil.ToCsvFriendly(program.ParticipantsCount.ToString()),
SharePointUtil.ToCsvFriendly(program.AmountAllocated.ToString("$###,###,###,##0")));
}
}
}
}
}
}
Response.Write(sb.ToString());
Response.Flush();
Response.End();
}
The big catch is the data manipulation once the data comes back from GetFundingData, I have to do it like that because our DBA is out and I need to knock this out. I thought I'd be able to just change the content type but that blows it up. Any help would be appreciated.
I think the problem is your trying to use CSV formatting to create a XLS file. CSV uses a text based formatting with commas separating the data. XLS uses a binary style of formatting. Because XLS is a Microsoft file format, you will need to use Excel's Object Library to create the files. I do not know if you have the option, but if you can include EPPlus in your application, EPPlus can create, open, and edit XLSX files. XLSX is not XLS, but any version of Excel after the 2007 version can read both types.
[Edit]
Thank you Scott Chamberlain for pointing out that TrevorGoodchild is using a Sharepoint web service. As Scott Chamberlain has pointed out in his comment above, Open XML SDK is an option when using an IIS web service. In addition, because EPPlus does not use COM Interop it may also be usable in your application.
I'm trying to use EPPlus to create a report inside an ASP.NET application. I tried using the code provided into samples package but I'm having some troubles.
The following code is executed without error:
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample1");
_ws.Cells["A1"].Value = "COD. CONV.";
_ws.Cells["A1"].Style.Font.Bold = true;
_ws.Cells["A1"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
_ws.Cells["B1"].Value = "RAGIONE SOCIALE";
_ws.Cells["B1"].Style.Font.Bold = true;
_ws.Cells["B1"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
_ws.Cells["C1"].Value = "COMMERCIALE A";
_ws.Cells["C1"].Style.Font.Bold = true;
_ws.Cells["C1"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
_ws.Cells["D1"].Value = "PROVINCIA";
_ws.Cells["D1"].Style.Font.Bold = true;
_ws.Cells["D1"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
_ws.Cells["E1"].Value = "ZONA";
_ws.Cells["E1"].Style.Font.Bold = true;
_ws.Cells["E1"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
_ws.Cells["F1"].Value = "TELEFONO";
_ws.Cells["F1"].Style.Font.Bold = true;
_ws.Cells["F1"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
_ws.Cells["G1"].Value = "EMAIL";
_ws.Cells["G1"].Style.Font.Bold = true;
_ws.Cells["G1"].Style.Border.Bottom.Style = OfficeOpenXml.Style.ExcelBorderStyle.Thick;
int _i = 2;
foreach (DataRow _drRow in dtAnagrafiche.Rows)
{
_ws.Cells["A"+_i.ToString()].Value = _drRow["codice"].ToString();
_ws.Cells["B"+_i.ToString()].Value = _drRow["Nome"].ToString();
_ws.Cells["C"+_i.ToString()].Value = "";
_ws.Cells["D"+_i.ToString()].Value = _drRow["Provincia"].ToString();
_ws.Cells["E"+_i.ToString()].Value = _drRow["Zona"].ToString();
_ws.Cells["F"+_i.ToString()].Value = _drRow["Telefono"].ToString();
_ws.Cells["G"+_i.ToString()].Value = _drRow["Email"].ToString();
_i++;
}
Response.BinaryWrite(_pck.GetAsByteArray());
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Lista_Anagrafiche.xlsx");
but the resulting file cannot be opened by Microsoft office if not 'recovered', other MS Office compatibile applications (i.e. OpenOffice) cannot open the file.
I can provide the output file if needed.
https://drive.google.com/file/d/0B-lPXYt7laDrbUFKbFZEWEwxckk/view?usp=sharing
BTW I'm using the last (4.0.5) EPPlus package obtained trough nuget, and running it in ASP.NET 4.5 web appplication.
You're missing a call to Response.End(). Without this, you're sending the response with the binary payload (the .xlsx file), which is coming over correctly, then the .aspx page that you're coding this under is being sent in the payload as well. Proof here as shown in a hex editor.
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Lista_Anagrafiche.xlsx");
Response.BinaryWrite(_pck.GetAsByteArray());
Response.End();
Should do the trick.
As an aside, I would suggest saving the file, then doing a Response.Redirect() to the URL of the file, instead, but that's unrelated to this specific issue.
EDIT: Notably, in normal circumstances, I would suggest avoiding Response.End(), but, that is the quickest way to solve the problem you've coded yourself into. I would suggest looking for better ways to serve up these files in general, as per my above suggestion to Response.Redirect() to a saved location of the file.
Try changing your code to the following notice how I am using the string.Format function to create the filename + extension
you need to declare a constant fileName. if worse comes to worse change the .xlsx to .xls
Response.Clear();
Response.ClearHeaders();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AppendHeader("Content-Disposition", string.Format("attachment;filename={0}.xlsx", fileName));
Response.BinaryWrite(_pck.GetAsByteArray());
Response.Flush();
Response.End();
Using ASP.NET web page, I am exporting some data to excel spreadsheet (XLSX). The code is running fine when I run it using Visual Studio (it is exporting a XLSX file with correct data), but the same code fails when deployed to Testing Server.
It is not throwing any error, it simply exports a blank XLSX file.
Note: While debugging in the test server, I found that the data is getting fetched and temp file is also getting created properly, but the data is not getting written to the temp file (the weird thing is it doesn't through any error).
Added later
After doing some more research, I have found that there is no issue with small record set (say 1000, 2000). But when tried with ~20K records, I get a blank file.
I have been burning myself for last 2 days, someone rescue me :) ...
Code
string templateFile = #"C:\Templates\ExportFile.xlsx";
string tempFileName = Path.Combine(#"C:\Temp\", Path.GetRandomFileName());
tempFileName = Path.ChangeExtension(tempFileName, ".xlsx");
File.Copy(templateFile, tempFileName);
List<Customer> customerList = FetchCustomers();
DataTable dataTableObj = new DataTable("Customers$");
dataTableObj.Columns.Add(new DataColumn("CustomerID"));
dataTableObj.Columns.Add(new DataColumn("FirstName"));
dataTableObj.Columns.Add(new DataColumn("LastName"));
dataTableObj.Columns.Add(new DataColumn("CreatedDate"));
foreach (Customer customerObj in customerList)
{
DataRow dataRowObj = dataTableObj.NewRow();
dataRowObj["CustomerID"] = customerObj.CustomerID;
dataRowObj["FirstName"] = customerObj.FirstName;
dataRowObj["LastName"] = customerObj.LastName;
dataRowObj["CreatedDate"] = customerObj.CreatedDate;
dataTableObj.Rows.Add(dataRowObj);
}
using (OleDbConnection oleDbConnectionObj = new OleDbConnection("Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + tempFileName + ";Extended Properties=\"Excel 12.0 Xml;HDR=YES;\""))
{
OleDbCommand insertCommand = new OleDbCommand();
insertCommand.Connection = oleDbConnectionObj;
insertCommand.CommandText = #"INSERT INTO [Customers$] ([CustomerID], [FirstName], [LastName], [CreatedDate]) VALUES (?, ?, ?, ?)";
insertCommand.Parameters.Add("CustomerID", OleDbType.Numeric, 0, "CustomerID");
insertCommand.Parameters.Add("FirstName", OleDbType.VarChar, 0, "FirstName");
insertCommand.Parameters.Add("LastName", OleDbType.VarChar, 0, "LastName");
insertCommand.Parameters.Add("CreatedDate", OleDbType.Date, 0, "CreatedDate");
DataSet dataSetObj = new DataSet();
dataSetObj.Tables.Add(dataTableObj);
OleDbDataAdapter dataAdapter = new OleDbDataAdapter();
dataAdapter.InsertCommand = insertCommand;
dataAdapter.Update(dataSetObj, "Customers$");
}
Response.Clear();
Response.Buffer = true;
Response.ContentType = "application/vnd.ms-excel";
Response.Charset = "";
Response.AddHeader("Content-Disposition", "attachment; filename=Customers.xlsx");
Response.WriteFile(tempFileName);
Response.Flush();
Response.End();
Finally it got resolved!!!
While creating large XLSX file (greater then ~1MB), OLEDB Provider tries to create temp file at Local Settings\Temporary Internet Files\Content.MSO\ for the APP POOL account. If the folder doesn't exists or the APP POOL account doesn't have proper permission, then it fails without throwing errors (no idea why it doesn't throw error).
In my case Content.MSO folder was missing at C:\Documents and Settings\Default User\Local Settings\Temporary Internet Files.
I created the folder and gave the modify permission to NETWORK SERVICES..... and "Voila!" - everything started working.
Thanks to the below 2 links, they saved me days...:)
Microsoft ACE OLEDB connection creating empty Excel when there are 166,110 rows
http://www.rapidsnail.com/developer/topic/2011/109/2/65194/excel-writes-secret-use-oledb-write-data-to-excel-more-than-13571-line-file-for-blank.aspx
I have a template excel file to generate excel files from it.
My code is as follows (This part is to create a new excel file from the template):
string currentFN = PropertyFinalResult[0].Fecha;
string fixCurrentFN = currentFN.Replace('/', '_');
string currentTime = DateTime.Now.ToLongTimeString();
string fixCurrentTime = currentTime.Replace(':', '_');
string addToFileName = fixCurrentTime.Replace(' ', '_');
string newFN = fixCurrentFN + "-" + addToFileName;
string SourceFile = Request.PhysicalApplicationPath + "Template\\ExcelTemplate.xlsx";
string DestFile = Request.PhysicalApplicationPath + "Template\\" + newFN + ".xlsx";
//To keep FileName for posterior deletion
Session["sDestFile"] = DestFile;
try
{
File.Copy(SourceFile, DestFile);
}
catch (Exception ex)
{
lblErrorSavingToDB.Text = "Error: " + ex.Message;
lblErrorSavingToDB.Visible = true;
}
after that I open the new excel file, insert the records in it and then, stream the file to the user by doing this:
//Streaming file to client
string fileName = newFN + ".xlsx";
Response.Redirect("../Template/" + fileName);
Now, my question is, whether the user save or not the file, when should I delete the generated file? I would prefer once the user closes the popup window regarding Open or Save the file. But how to know when the user closes that window?
You can use TransmitFile and then close once the transmission is over. Example:
try
{
Response.ContentType = "application/octet-stream";
Response.AddHeader("content-disposition", "attachment;filename=\"" + Path.GetFileName(path.FullName) + "\"");
Response.AddHeader("content-length", path.Length.ToString());
Response.TransmitFile(path.FullName);
Response.Flush();
}
finally
{
File.Delete(Server.MapPath("~/"+tpacode+".zip"));
}
When to delete the files (or maybe it's better to say "how long to keep the files") is a question that is best answered by your application's business rules.
In the past, in low-traffic applications, I've used a "clean-up" routine to delete files older than a certain threshold. That clean-up gets performed when a new file is created, and at that time any file in the designated folder that was older than the threshold would be deleted.