Error while reading and saving the excel file on serverside - c#

I have tried the below coding for generating excel file on serverside.
C# CODING:
public void ReadandOpenExcel(DirectoryInfo outputDir)
{
//FileInfo newFile = new FileInfo(outputDir.FullName + #"\New Microsoft Excel Worksheet.xlsx");
var ExistFile = Server.MapPath("~/excelsample.xlsx");
var File = new FileInfo(ExistFile);
using (ExcelPackage package = new ExcelPackage(File))
{
package.Load(new FileStream(ExistFile, FileMode.Open));
ExcelWorksheet workSheet = package.Workbook.Worksheets["Sheet1"];
workSheet.Cells["A8"].Value = "kevin";
package.Save();
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("Content-Disposition", "attachment; filename=ProposalRequest.xslx");
**Response.BinaryWrite(package.GetAsByteArray());**
// myMemoryStream.WriteTo(Response.OutputStream); //works too
Response.Flush();
Response.Close();
}
}
While running the above code i got an error as : " Package object was closed and disposed, so cannot carry out operations on this object or any stream opened on a part of this package."
ERROR On This Line:
Response.BinaryWrite(package.GetAsByteArray());
Make some way for this coding to move on.
Thanks in advance.

Does it work if you get the bytes before you do the Save ?
Byte[] bin = package.GetAsByteArray();
package.Save();
And then use that value in the Binarywrite;
Response.BinaryWrite(bin);
Maybe it is getting closed on the .Save() call ?

Related

Can't download excel file from C#

I'm working on adding Export functionality to an existing site. I've created an Excel file, and I'm able to output it to my local directory, but when I try pushing the file to the user using Response, nothing happens. I've viewed several differnet articles and Stack questions, and none seem to be different from what I have, or work when I apply them.
Here is the code I currently have:
public void Export () {
//Create instance of the database
ExportContext eDB = new ExportContext();
var query = (from x in eDB.EMPLOYEES
select x);
IEnumerable<EMPLOYEES> employees = query.ToList();
//Set filename to Table + date/time
string fileName = "EMPLOYEES" + DateTime.Now.ToShortTimeString() + ".xlsx";
//Create excel package
ExcelPackage excel = new ExcelPackage();
var worksheet = excel.Workbook.Worksheets.Add("Employees");
worksheet.Cells[1, 1].LoadFromCollection(employees, true);
using (var memoryStream = new MemoryStream()) {
//Output the file to the user via download
Response.Buffer = false;
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=" + fileName);
excel.SaveAs(memoryStream);
memoryStream.WriteTo(Response.OutputStream);
Response.Flush();
Response.Close();
Response.End();
}
}
Any help will be appreciated. Thanks.

EPPlus Excel File Not Working with Password

I am creating an Excel file with my MVC application. Depending on a configuration setting, the file will generate requiring a password or without. I can get the file to generate perfect without. But if I implement a password, I get this error:
Excel cannot open the file '' because the file format is not valid. Verify that the file has not been corrupted and that the file extension matches the format of the file.
Any help would be appreciated. Here is my code:
private void ViewExcelPackageFile(Dataset dtList, string filename)
{
//
var contenttype = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
// generate password with another function if configuration requires a password
Response.Clear();
Response.ContentType = contenttype;
Response.AddHeader("content-disposition", "attachment;filename=" + filename);
Response.Cache.SetCacheability(HttpCacheability.NoCache);
using (var stream = new MemoryStream())
{
using (ExcelPackage package = new ExcelPackage())
{
var workbook = package.Workbook;
foreach (var data in dtList)
{
ExcelWorksheet ws = workbook.Worksheets.Add(data.TableName.Replace('/', ' '));
ws.Cells["A1"].LoadFromDataTable(data, true);
}
if (password.Length > 0)
{
package.SaveAs(stream, password);
}
else
{
package.SaveAs(stream);
}
Response.BinaryWrite(stream.ToArray());
Response.Flush();
Response.End();
}
}
}
Please correct anything I'm doing wrong, but again, if I don't apply a password, it works fine. TIA!
Try the following
if (!string.IsNullOrEmpty(password))
{
package.Encryption.Password = password;
}
And then instead of using a MemoryStream, get the bytes directly.
Response.BinaryWrite(package.GetAsByteArray());

Open ExcelPackage Object with Excel application without saving it on local file path

I have a text file with some information and I convert it to ExcelPackage Object using EPPlus, now I want to know if there is a way to open this object with excel without saving it to a local file? if is not possible can I use a temp directory to save it into a file, and then open it?
If you are talking about a windows app, you could just use something like System.IO.Path.GetTempPath(). You can get more info from here:
How to get temporary folder for current user
So, something like this:
[TestMethod]
public void TempFolderTest()
{
var path = Path.Combine(Path.GetTempPath(), "temp.xlsx");
var tempfile = new FileInfo(path);
if (tempfile.Exists)
tempfile.Delete();
//Save the file
using (var pck = new ExcelPackage(tempfile))
{
var ws = pck.Workbook.Worksheets.Add("Demo");
ws.Cells[1, 2].Value = "Excel Test";
pck.Save();
}
//open the file
Process.Start(tempfile.FullName);
}
if you are talking web you shouldn't need to save it all, just send it via Response:
using (ExcelPackage pck = new ExcelPackage())
{
var ws = pck.Workbook.Worksheets.Add("Demo");
ws.Cells[1, 2].Value = "Excel Test";
var fileBytes = pck.GetAsByteArray();
Response.Clear();
Response.AppendHeader("Content-Length", fileBytes.Length.ToString());
Response.AppendHeader("Content-Disposition",
String.Format("attachment; filename=\"{0}\"; size={1}; creation-date={2}; modification-date={2}; read-date={2}"
, "temp.xlsx"
, fileBytes.Length
, DateTime.Now.ToString("R"))
);
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.BinaryWrite(fileBytes);
Response.End();
}

Unable to access file from server through code

I had written a code to first get an SSRS report and write to excel and save in a folder on server , manipulate the same excel through code and then save it again and then render it in excel for download.
The code was working fine but then suddenly I started getting the error:
The process cannot access the file 'G:\TestEnvironment\
TestSite_ForDeveloper\
Reports\10697696.xls' because it is being used by another process.
What could be the issue?
Following is the code used:
//Getting SSRS report
//code
//Saving SSRS report result in excel
try
{
Microsoft.Office.Interop.Excel.Workbook workbook;
Microsoft.Office.Interop.Excel.Worksheet NwSheet;
appExl = new Microsoft.Office.Interop.Excel.Application();
string serverPath = Server.MapPath(".");
string filenameToLoad = serverPath + "\\Page1Reports\\" + Session["UserAccentureID"].ToString() + ".xls";
FileStream fileStream = new FileStream(filenameToLoad, FileMode.Create, FileAccess.ReadWrite, FileShare.Read);
fileStream.Write(result, 0, result.Length);
fileStream.Close();
//Manipulation of file
//Done something
workbook.Save();
workbook.Close();
appExl.Quit();
System.IO.FileInfo file = new System.IO.FileInfo(filenameToLoad);
//Rendering again to excel download
if (file.Exists)
{
string lblrptname = "Page1SLScoreCardReport_" + ddlFiscalWeek.SelectedValue.ToString();
Response.Clear();
Response.ClearHeaders();
Response.Charset = "";
Response.ContentType = "Application/vnd.xls";
Response.AddHeader("content-disposition", "attachment;filename=" + lblrptname + ".xls");
Response.AddHeader("Cache-Control", "max-age=0");
Response.WriteFile(file.FullName);
}
}
catch (Exception ex)
{
AlnErrorHandler.HandleError(ex);
}
finally
{
if (appExl != null )
appExl.Quit();
}
maybe check Processes under Task Manager to see if any extra EXCEL.EXE processes are running? Excel will run in the background and hold on to your file if not exited properly and cause all kinds of confusion (at least it did for me ;) ).

Generating an excel file with EPPlus is failing

When I try to generate an Excel file using EPPlus, Excel give me the following error message:
Excel cannot open the file 'myfilename.xlsx' because the file format or file extension is not valid. Verify the the file has not been corrupted and that the file extension matches the format of the file.
Here's my code:
public ActionResult Index()
{
using (ExcelPackage package = new ExcelPackage())
{
// I populate the worksheet here. I'm 90% sure this is fine
// because the stream file size changes based on what I pass to it.
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
var cd = new System.Net.Mime.ContentDisposition
{
Inline = false,
FileName = fileName
};
Response.AppendHeader("Content-Disposition", cd.ToString());
return File(stream, contentType, fileName);
}
}
Any idea what I'm doing wrong?
All you need to do is reset the stream position. stream.Position = 0;
You shouldn't write directly to the Response, it's not the MVC way. It doesn't follow the correct MVC pipeline and it tightly couples your controller action code to the Response object.
When you add a file name as the 3rd parameter in File(), MVC automatically adds the correct Content-Disposition header... so you shouldn't need to add it manually.
The short of it is, this is what you want:
public ActionResult Index()
{
using (ExcelPackage package = new ExcelPackage())
{
// I populate the worksheet here. I'm 90% sure this is fine
// because the stream file size changes based on what I pass to it.
var stream = new MemoryStream();
package.SaveAs(stream);
string fileName = "myfilename.xlsx";
string contentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
stream.Position = 0;
return File(stream, contentType, fileName);
}
}
Your code doesn't show stream being written to the HttpResponse - presumably being done in the File method which you haven't posted.
One way that does work is the following:
Response.Clear();
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader(
"content-disposition", String.Format(CultureInfo.InvariantCulture, "attachment; filename={0}", fileName));
Response.BinaryWrite(package.GetAsByteArray());
Response.End();
Similar to Joe's answer, I still had to call Response.ClearHeaders():
protected void btnDownload_Click(object sender, EventArgs e)
{
ExcelPackage pck = new ExcelPackage();
var ws = pck.Workbook.Worksheets.Add("Sample2");
ws.Cells["A1"].Value = "Sample 2";
ws.Cells["A1"].Style.Font.Bold = true;
var shape = ws.Drawings.AddShape("Shape1", eShapeStyle.Rect);
shape.SetPosition(50, 200);
shape.SetSize(200, 100);
shape.Text = "Sample 2 outputs the sheet using the Response.BinaryWrite method";
Response.Clear();
Response.ClearHeaders();
Response.BinaryWrite(pck.GetAsByteArray());
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Response.AddHeader("content-disposition", "attachment; filename=Sample2.xlsx");
Response.End();
}

Categories

Resources