Unable to Save Excel File using NPOI Library - asp.net

I am having some difficulties exporting excel file using NPOI dll through ASP.NET page.
Basically, I am able to populate the cells with no exception, however right at the few last steps where I need to export out the excel, it throws an exception when it tries to run Response.End.
Dim ms As New MemoryStream
xlWorkbook.Write(ms)
Response.ContentType = "application/vnd.ms-excel"
Response.AddHeader("content-disposition", "attachment;filename=M4_Control_Chart.xls")
Response.Clear()
Response.BinaryWrite(ms.GetBuffer())
Response.End()
I dont get a lot of information from the exception, it just says "Unable to evaluate expression"
Does anyone have any idea how to fix this?
Thanks.

Flush your stream before you read the buffer: ms.Flush()

Related

Unreadable excel content Epplus

I am making a Post request and receiving the response from an end point, through which i receive the excel content.
I have used this end point before and tried binding a email worker, which works fine. (Conforming end point response is clear).
Now with a different requirement, i need to make the post call to this end point and download the excel file.xlsx file hence generated is corrupted and i excel tries to recover it once the file is downloaded.
Have gone thorugh different threads and tried almost everything.
Nothing seems to work.
try 1:
Response.Clear();
stream.Flush();
stream.Seek(0, SeekOrigin.Begin);
return File(stream, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", fileName.Replace("\"", String.Empty));
And while debugging i have made sure to close the response. (Response.End()).
Have even added the explicit headers
Response.AddHeader("content-disposition", "attachment; filename=\"" fileName".xlsx\"");
Response.ContentType = "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet";
Try 2
have explicity written the memoryStream to the response.
Response.BinaryWrite(tgtBytes);
Have ensured Response.Clear before writing to response and making sure of memoryStream.dispose and Response.End.
Have even used. Response.ClearHeaders().
Try - 3.
Instead of MemoryStream, tried with filestream, saving in a file and downloading from the File written. Problem still Persists.
I am getting a binaryStream as response and no encoding in done as it isn't hex value.
Either the stream is corrupted ( which is likely not the case, as i use the end point for different requirements) or the response is corrupted.
how should i check what is the exact cause ??
Please Let me know what else can i try.

FileUpload control in asp/VB.net cannot access the file because it is being used by another process

Error message:
The process cannot access the file 'C:\SampleProjectName\mytestcsv.csv' because it is being used by another process.
I am trying to read numerous files (CSV, XML, HTML) in asp/VB.net using the fileupload (file upload) control.
I'm saving the file using Server.MapPath so I can process the file in another procedure. It's very odd, but sometimes I can browse and upload the same file over and over with no issues, but sometimes it immediately fails.
I've found that I can ultimately kill the WebDev.WebServer40.exe it releases whatever lock is present. This is annoying, but fine for my debugging... but unacceptable for endusers.
My fileupload code:
If fuImport.HasFile Then
If (System.IO.File.Exists(Server.MapPath("myhtml.html"))) Then
System.IO.File.Delete(Server.MapPath("myhtml.html"))
End If
Dim dtFromHTML As New Data.DataTable
Dim dtFromSQL As New Data.DataTable
Try
fuImport.SaveAs(Server.MapPath("mytestcsv.csv"))
'Process data here
ProcessCSVData(Server.MapPath("mytestcsv.csv"))
Catch ex As Exception
Response.Write("error: " & ex.Message)
Finally
fuImport.PostedFile.InputStream.Flush()
fuImport.PostedFile.InputStream.Close()
fuImport.FileContent.Dispose()
End Try
'Other things happen here
Else
Response.Write("no file...")
End If
Any ideas would be appreciated.
Use FileShare.Read to read a file even if it is opened exclusively by an another process.
You may not be releasing the file in your code for access. You should use the keyword "using".
Read this post:
The process cannot access the file because it is being used by another process - using static class
and this:
http://msdn.microsoft.com/en-us/library/htd05whh.aspx
I am not a VB.NET coder but try something along the lines of:
Using {fuImport.SaveAs(Server.MapPath("mytestcsv.csv")) }
ProcessCSVData(Server.MapPath("mytestcsv.csv"))
End Using
The next procedure that uses file...
Try closing input stream before accessing the file:
UPDATED To use temp filename
Dim sTempName = Path.GetRandomFileName
fuImport.SaveAs(Server.MapPath(sTempName))
'close before accessing saved file
fuImport.PostedFile.InputStream.Close()
'Process data here
ProcessCSVData(Server.MapPath(sTempName)

how can i create a true, binary excel file using pure asp

is it possible to create a binary excel file in asp classic?
the common method is using this
Response.ContentType = "application/octet-stream"
Response.AddHeader "Content-Disposition", "attachment; filename=test.txt"
which is not a "true" excel file
In .net you could use the Microsoft.Office.Interop.Excel namespace - very easy to use, if you have access to .net i'd certainly go for that.
You say "in pure asp" - if this means without com objects etc - i dont think it's possible.
If however you wish to persevere with classic asp with the option of using a com object you can create full binary spreadsheets using the Interop com object - to do this you will need Excel installed on the webserver.
For example, to open a blank excel file on disk (i.e. a template), change a value and save the finished file:
'#### Ready Excel
Set ExcelApp = CreateObject("Excel.Application")
ExcelApp.Application.Visible = True
'#### Open a blank Excel File
Set ExcelBook = ExcelApp.workbooks.Open("d:\wwwroot2\blankTemplate.xls")
'#### Select a sheet and change the value of a cell
ExcelBook.Worksheets("SheetName").Cells(1, 1).Value = "Lorem Ipsum"
'#### Switch between sheets
ExcelBook.Worksheets("AnotherSheetName").Select
'#### Save the finished file with a different name (to leave the template ready for easy re-use)
ExcelBook.SaveAs "d:\wwwroot2\FinishedFile.xls"
'#### Tidy up
ExcelBook.Close
ExcelApp.Application.Quit
Set ExcelApp = Nothing
Set ExcelBook = Nothing
Good thing about this method is the interop com object mimics VBA methods etc very closely, so if your ever unsure how to do something, record a macro in excel, view the raw vba, the code it produces, specifically the methods and parameters would be very similar in most cases to the code you would use for the com object.

How can I export my ASP.NET page to Excel?

How can I export the data in my webapp to an Excel sheet from ASP.NET (VB.NET,SQL 2005)?
change the contenttype of your ASP.Net page
Response.ContentType = "application/ms-excel"
One of my most popular blogs is how to generate an Excel document from .NET code, using the Excel XML markup (this is not OpenXML, it's standard Excel XML) - http://www.aaron-powell.com/linq-to-xml-to-excel
I also link off to an easier way to do it with VB 9.
Although this is .NET 3.5 code it could easily be done in .NET 2.0 using XmlDocument and creating the nodes that way.
Then it's just a matter to set the right response headers and streaming back in the response.
SpreadsheetGear for .NET will do it. You can find a bunch of live ASP.NET samples with C# & VB.NET source on this page.
Disclaimer: I own SpreadsheetGear LLC
If you can display your data in a GridView control, it inherently supports "right-click-->Export to Excel" without having to write any code whatsoever.
SQL Server Reporting services would be the best way to export data from an application into Excel.
If you dont have access to / dont wan't to use reporting services depending on the data you want to extract / format possibly using a CSV structure instead of Excel may be easiest.
Use the Microsoft.Office.Interop.Excel dlls to create excel files with your data and then provide links to download the files using Hunter Daley's download method...
As a general solution, you may want to consider writing handler (ashx) for exporting -- and pass either the query parameters to recreate the query to generate the data or an identifier to get the data from the cache (if cached). Depending on whether CSV is sufficient for your Excel export you could just format the data and send it back, setting the ContentType as #Hunter suggests or use the primary interop assemblies (which would require Excel on the server) to construct a real Excel spreadsheet and serialize it to the response stream.
I prefer to use a OLEDB connection string.
Provider=Microsoft.Jet.OLEDB.4.0;Data Source=C:\Excel.xls;Extended Properties="Excel 8.0;HDR=Yes;IMEX=1";
Not sure about exporting a page but if you just want to export a dataset or datatable
HttpContext.Current.Response.Clear()
HttpContext.Current.Response.AddHeader("content-disposition", String.Format("attachment; filename={0}", fileName))
HttpContext.Current.Response.ContentType = "application/ms-excel"
Dim sw As StringWriter = New StringWriter
Dim htw As HtmlTextWriter = New HtmlTextWriter(sw)
Dim table As Table = New Table
table.RenderControl(htw)
' render the htmlwriter into the response
HttpContext.Current.Response.Write(sw.ToString)
HttpContext.Current.Response.End()
I use almost the same exact code as CodeKiwi. I would use that if you have a DataTable and want to stream it to the client browser.
If you want a file, you could also do a simple loop through each row/column, create a CSV file and I guess provide a link to the client - you can use a file extension of CSV or XLS. Or if you stream the resulting file to the client it will prompt them if they want to open or save it to disk.
The interops are (well were last time I tried them) great for small datasets, but didn't scale well - horrifically slow for larger datasets.

Response.Write DataTable Data to Text File, ASP.net Hangs

Very odd problem as this is working perfectly on our old Classic ASP site. We are basically querying the database and exporting around 2200 lines of text to a Text File through Response.Write to be output to a dialog box and allows the user to save the file.
Response.Clear()
Response.ClearContent()
Response.ClearHeaders()
Dim fileName As String = "TECH" & test & ".txt"
Response.AddHeader("Content-Disposition", String.Format("attachment; filename={0}", fileName))
Response.ContentType = "text/plain"
Response.Write(strHeader)
Dim sw As New IO.StringWriter()
Dim dtRow As DataRow
For Each dtRow In dt3.Rows
sw.Write(dtRow.Item("RECORD") & vbCrLf)
Next
Response.Write(sw.ToString)
Response.Write(strTrailer & intRecCount)
Response.End()
I can either use StringWriter or simply use Response.Write(dt.Rows(i).Item("RECORD").toString
Either way, the Export is causing a horrendous hang on our development site. My local machine causes no hang and is almost instantaneous. The recordset isn't very large, and the lines it is writing are small.
Anyone have any idea why this would be hanging? It does EVENTUALLY allow for a save and display the file, but it's well over 3-4 minutes.
Attach a remote debugger and find where its hanging?
You need to figure out if its the string writer loop, or the actual query code (which is not provided here).
Sounds like maybe you're overflowing the output buffer. Perhaps add a counter in there to flush every few hundred lines.
Also, the Response object basically does most of the work for a StringWriter for you. Using the StringWriter as an intermediary is probably redundant.
Both using StringWriter and DataTable are overkill.
Why not use directly SqlReader to get the results from the database, and while reading the reader, write directly to the output stream? Much faster, and much less memory consumed.
As an answer to your second question - why the ASP was working OK, I doubt that there you have stored the same content 3 times in memory in order to output it (in the DataTable, in the StringWriter and in the output buffer). My ASP is a little bit rusty, but I would guess that there you are using database reader of some sort.
Also, better employ some logging infrastructure (NLog, log4net), so you can output some timing about which operation delays how much, as an alternative to attaching a remote debugger.

Resources