Using ASP.NET with Excel Files - asp.net

I want to create an excel file from a web page in ASP.NET, I'm using the Microsoft.Office.Interop.Excel library, but I can't delete the file create on the side of the server, because I get in trouble with the times. I want to know if there is a way to create an Excel file with data of a database for example, and then that the client can download that file without saturate the server.
Actually I'm using this code in VB after the file is create in the server, but it doesn't work like I want:
Dim p As Process = New Process()
p.StartInfo = New ProcessStartInfo()
p.StartInfo.UseShellExecute = True
p.StartInfo.FileName = "taskkill.exe"
p.StartInfo.Arguments = "/F /IM EXCEL.exe"
p.Start()
p.WaitForExit()
Thread.Sleep(24)
Response.ContentType = "application/vnd.ms-excel"
Response.AppendHeader("Content-Disposition", "attachment; filename=Reporte.xlsx")
Response.TransmitFile(Server.MapPath("~/Resources/" & HiddenField1.Value.ToString() & ".xlsx"))
'Thread.Sleep(10000)
'Dim fso, f2
'fso = CreateObject("Scripting.FileSystemObject")
'f2 = fso.GetFile(Server.MapPath("~/Resources/" & HiddenField1.Value.ToString() & ".xlsx"))
'f2.Delete()
'Thread.Sleep(24)
Response.End()
Thanks

You might consider using something other than Excel to create the file you want to send.
For example, there is Carlos Aguilar Mares's free Excel XML library: http://www.carlosag.net/tools/excelxmlwriter/.
Also, some reporting tools like SQL Server Reporting Services have the option of exporting native Excel files. That's one way to generate an Excel file, complete with formatting.
Finally, Excel can read other types of files, such as CSV and HTML files. Those are a lot easier to produce and don't require Excel itself to generate.
A good run-through of the options: Generating an Excel file in ASP.NET

Automating excel on a server is not officially supported by Microsoft and I suggest you find an alternative. Microsoft has a lot of good information on this topic here: http://support.microsoft.com/kb/257757.
All current versions of Microsoft Office were designed, tested, and
configured to run as end-user products on a client workstation. They
assume an interactive desktop and user profile. They do not provide
the level of reentrancy or security that is necessary to meet the
needs of server-side components that are designed to run unattended.
Microsoft does not currently recommend, and does not support,
Automation of Microsoft Office applications from any unattended,
non-interactive client application or component (including ASP,
ASP.NET, DCOM, and NT Services), because Office may exhibit unstable
behavior and/or deadlock when Office is run in this environment.
If you are building a solution that runs in a server-side context, you
should try to use components that have been made safe for unattended
execution. Or, you should try to find alternatives that allow at least
part of the code to run client-side. If you use an Office application
from a server-side solution, the application will lack many of the
necessary capabilities to run successfully. Additionally, you will be
taking risks with the stability of your overall solution.
They even offer suggestions on how to avoid using them:
Most server-side Automation tasks involve document creation or
editing. Office 2007 supports new Open XML file formats that let
developers create, edit, read, and transform file content on the
server side. These file formats use the System.IO.Package.IO namespace
in the Microsoft .NET 3.x Framework to edit Office files without using
the Office client applications themselves. This is the recommended and
supported method for handling changes to Office files from a service.
They also have tutorials on using the APIs:
http://msdn.microsoft.com/en-us/library/bb739834.aspx
http://msdn.microsoft.com/en-us/library/bb727373.aspx

We use EPPlus to generate our excel documents.
It gives you quite a bit of control over the output and it's very fast. As John said, automating Excel on the server through a web site is completely unsupported by MS and they suggest you use alternatives.

Related

Word VBA / Macro run on server Application.Run, ASP.NET, DCOM

I am not a coder but need a task done.
We have a website that builds a word doc file using ckeditor based on answers from clients.
This documents needs afterwards to be formatted (TA/TC functions of word) which cannot be done with ckeditor.
Therefore we have a VBA/ macro that needs to be run in MS word after the doc file is generated.
I want to automate this step and have the VBA/macro run, before the doc is send to client.
So from my understanding, you have to take the CKeditor doc, run the macro on the server, and store it in the current database..
Possible or not?
This should not be done server-side. Working with Office applications server-side is not supported - Office applications are end-user applications. They can easily appear to "hang" when used, due to waiting for user input.
More information about using Office on a server can be found here
Possible: theoretically, yes, but impossible for anyone to guarantee as the code and document content are unknown. But, theoretically, if it works on a desktop it can work when run on a server.
The more "correct" way to manipulate Office documents on a server is to work directly with the Office Open XML files, instead of opening them in the application interface. The file formats were designed for this scenario and execution is also much faster. I'm guessing, however, since TC and TA fields are mentioned that the macro also builds TOCs? If yes, then the document would also have to be opened in order to generate the TOC (update the field). Server-side, that would mean using Word Automation Services, which is part of SharePoint.

Retrieving the COM class factory for component with CLSID on excel file reading

i have a asp.net project that reads the excel file and retrieves its data using Microsoft excel 16 object library and Microsoft office 16 object library .. every thing is fine on developing machine and i can read the data ...... but after i published the website and upload it on somee.com for free hosting ... the part that i upload the excel goes well but in reading data part i got this error
System.Runtime.InteropServices.COMException: Retrieving the COM class
factory for component with CLSID
{00024500-0000-0000-C000-000000000046} failed due to the following
error: 80040154 Class not registered (Exception from HRESULT:
0x80040154 (REGDB_E_CLASSNOTREG)).
i searched for the cause and i think the problem is about excel library that may not supported by host or something like that ... thank you if you help me to figure it.
You're breaking the cardinal rule of Office Automation -- don't do it on a server. Period.
It is possible to install Office on a server, and it's even possible to manually register some things to get it to do just enough to make your web application work once or twice while you're testing. But as soon as that application is moved into a production environment, it's going to start failing -- consistently or intermittently -- and can even cause your web application to hang entirely. Office is a set of applications, not a set of data manipulation libraries. Everything about it is designed as if a user is running it from within an interactive session - it creates windows for a lot of operations, and it is inherently multi-process. Your server is running in a non-interactive session, and the rules for window management are different under this scenario. There's really no way to make Office automation safe in a server application, especially a server that's hosting multiple applications/sites and/or is high-traffic.
The "correct" way to do this is to use a library that treats Office documents purely as data structures. A library that does this can read and manipulate the data in the document without invoking Office to do so. An analogy would be XML documents -- you use an XML API like .NET's XmlDocument or XDocument to read data from files, manipulate it in memory and store it back to disk. This is very different than trying to automate the operations that a user would perform with some visual XML editor application.
I would recommend you check out the Open XML SDK, a library provided by Microsft for exactly this purpose. All Office 2007+ documents are stored in an open format called Open XML. This library is coded around the specifications for that file format.

How to push data from excel to SQL Server?

I have written a simple ASP.NET MVC 2 application that stores data and can dynamically create excel files using Microsoft's openXML for excel files.
What is the best way to push changes the user makes in excel to my database? I know it can be done via file upload, but this is rather obtrusive to the end user to navigate to my site, select upload, and then select their file.
Is there a way to do 1 click publishing from the excel file using VBA? VBA can interact with the database directly, but this seems dangerous from a data security standpoint, and duplication of logic.
Do web services work with the MVC architecture? How do I get a vba macro enabled document to send itself to the server?
For anyone out there looking for a fix, I ended up using vba's InternetExplorer.Application object and interacting with an upload form on my site.
For more info on the upload form check out:
http://haacked.com/archive/2010/07/16/uploading-files-with-aspnetmvc.aspx
For more info on VBA and the InternetExplorer.Application object check out:
www.motobit.com/tips/detpg_uploadvbaie/
You might take a look at Sql server integration services for bulk upload of data into sql server. The integration services once created can be run using a normal c# desktop program or using a windows service.
But you might
need to make sure this happens in the background and will have to be
an asynchronous task.
also need to make sure it is properly secured
by not giving direct execute access to any other users
I'm assuming that this is for a specific user. I've done something very similar to what you are describing before.
Tell the user to save the excel file in their DropBox and share the file with you.
Have the server listen for changes to this file and run a server side routine to import the data.
Disclaimer: This is not a secure solution, but it's easy and will get the job done.

Run a Virus Scan While Uploading files in ASP.NET

I have developed a web based application in ASP.NET and C# where users have the facility to upload files on the server through this application I want the application to Scan the uploaded files for viruses before saving on the server. Same like when we attach files with our email in Yahoo. Please guide me how I can achieve this functionality Any API which can be integrated in ASP.NET application or any other way you can suggest. We can purchase the licensed version of a product which can achieve this. I have googled but did not find specific results.
Thanks in advance!
First of all the file must be saved onto the server before you can scan it. If you notice Yahoo will upload the file first - but not allow the attachment to be sent until scanned.
Then you can use an antivirus with a command line interface or some other kind of API. Both of these can be called via C# and should provide the functionality you require. Parhaps write a wrapper class that takes a file and returns true or false depending on whether a virus was detected.
Other applications that provide you with a command line interface:
Microsoft Security Essentials
clamAv
I believe MS AV provides better results.
Just purchase antivirus software that has a command-line interface (several popular packages include this). Once the file has been uploaded, run the scan.
I would think, in order to upload and scan at the same time, you might need to implement your own antivirus software as I'm not familiar with any package that would provide that sort of interface.
I run a shareware site. It doesn't work as you described, but I download each file to my local computer and run a scan on them. You would be doing something similar.

Killing Excel.EXE on server [duplicate]

This question already has answers here:
Closed 11 years ago.
Possible Duplicate:
How to properly clean up Excel interop objects in C#
Suppose a ASP.NET web application generates automated Excel Reports on the server. How do we kill a server-side Excel.EXE once the processing is over. I am raising this purposely, because I believe that the Garbage Collecter does not clean the Excel executable even after the Excel file is closed.
Any pointers would be helpful?
Sorry to say this, and I'm not trying to be smart, but... don't put office on the server!!!
That's if I've understood correctly! :)
EDIT: Even though I've been marked down for this, I will never ever advocate running Office on the server - it has proven way too much of a pain in the ass for me in the past.
Having said that, the same now goes for me and Crystal Reports ;-)
I agree with not running Office on a server. Not that I have any choice in the matter :)
One thing to keep in mind with the taskkill option, is that unless you specifically plan for it (aka - singleton), you may have multiple copies of Excel (or any other Office app) running, and unintentionally close the wrong instance.
Also note that per http://support.microsoft.com/kb/257757
Microsoft does not currently
recommend, and does not support,
Automation of Microsoft Office
applications from any unattended,
non-interactive client application or
component (including ASP, ASP.NET,
DCOM, and NT Services), because Office
may exhibit unstable behavior and/or
deadlock when Office is run in this
environment.
As an alternative, there is a product called Aspose Cells that offers a product that is designed to allow you to programmatically work with an Excel sheet in a server environment. As a disclaimer, I have never personally used this product, but I have heard about it from several people I worked with in the past.
I've had more time to think about this answer, and would now recommend using an XML approach with the Open XML Office spreadsheet format.
Heres some good links to get started on building a office document with code.
http://msdn.microsoft.com/en-us/magazine/cc163478.aspx
http://msdn.microsoft.com/en-us/library/bb735940(office.12).aspx
Just use SSIS on SQL Server. It provides the ability to export to Excel.
Don't run office on the server. Alteranatively waste money on aspose or spreadsheetgear.
GC does work your just not using it properly follow this pattern...
private void killExcel()
{
xlApp.Quit();
Marshal.ReleaseCOMObject(xlApp);
if(xlApp != null)
{
xlApp = null;
}
GC.WaitForPendingFinalizers();
GC.Collect();
GC.WaitForPendingFinalizers();
GC.Collect();
}
get your Excel operational class to implement IDisposable, and then stick killExcel() in the Dispose method.
UPDATE: Also note that sometimes dev will still see Excel.exe running in task manager. Before assuming the above code isn't working, check that the process that is running the code is also closed. In the case of a VSTO or COM addin, check that Word/powerpoint/other excel instance is also closed as there is still a GC root back to the launching process. Once that is closed the Excel.exe process will close.
Are you using VSTO? You can close the Excel app after you finished with excelobject.Quit(); It worked for me, but I don't use Excel on server-side anymore.
You can have a look on Excel's XML schema to build the Excel file without Excel itself. Check out CarlosAg Excel Writer, which does exactly the same.
I've had a similar problem. While 'taskkill excel.exe' or enumerating all "excel" processes and killing them does work, this kills ALL running Excel processes. You're better off killing only the instance you're currently working with.
Here's the code I used to accomplish that. It uses a PInvoke (see here) to get the ProcessID from the Excel.Application instance (Me.ExcelInstance in the example below).
Dim ExcelPID As Integer
GetWindowThreadProcessId(New IntPtr(Me.ExcelInstance.Hwnd), ExcelPID)
If ExcelPID > 0 Then
Dim ExcelProc As Process = Process.GetProcessById(ExcelPID)
If ExcelProc IsNot Nothing Then ExcelProc.Kill()
End If
Please not this might not work on all platforms because of the PInvoke... To date, this is the only method I have found to be reliable. I have also tried to find the correct PID by enumarating all Excel processes and comparing the Process.MainModule.BaseAddress to the Excel.Application.Hinstance.
'DO NOT USE THIS METHOD, for demonstration only
For Each p as Process in ExcelProcesses
Dim BaseAddr As Integer = p.MainModule.BaseAddress.ToInt32()
If BaseAddr = Me.ExcelInstance.Hinstance Then
p.Kill()
Exit For
End If
Next
This is not a reliable way to find the correct process, as the BaseAddress sometimes seems to be the same for several processes (resulting in killing the wrong PID).
The command you need is "taskkill".
http://technet.microsoft.com/en-us/library/bb491009.aspx
> taskkill excel.exe
:). I jotted down my skirmish with Excel here. It also has some links that I found after some heavy searching. Hope it helps.
Basically Excel is a pain even though it can be automated.
I also would not recommend using office apps on a server except for data access to mdb files.
I can definitely understand that there are times where it is necessary. In thoses cases
I would recommend the following:
Create a separate server where that is the only function. (Let's you reboot with minimum impact).
Have the server implement a mechanism of queuing requests
Keep a single thread processing the queue. This gives you the ability to keep track of the office app, kill it if necessary, and continue on without impacting any queued up jobs or other applications.
If you absolutely need to do it on the same server, then at least implement the above in it's own app pool.
Limiting yourself keeping a queue of work and only one instance of Excel (or any other office app) let's you kill it with abandon with TaskKill or .Kill() and not lose work.
I believe if you keep it to a single thread then you would rarely have a need to kill it.
I have used spreadsheetgear to generate XL reports on the server and it works really well. We don't have to worry about the EXCEL process..
I had a similar problem and used the following code:
System.Diagnostics.Process[] procs = System.Diagnostics.Process.GetProcesses();
for (int i = 0; i < procs.Length; i++)
{
if(procs[i].ProcessName == "EXCEL")
{
procs[i].Kill();
}
}
This worked pretty well, but I would really think about working with Office on a server.
I actually had a question that was similar to this awhile back - Check for hung Office process when using Office Automation - some of the responses to that question might be useful for you.
Also, I have to agree with what everyone else is saying in regards to keeping any Office products off of a server; however, since you are doing Excel, it might be feasible for you to generate Excel XML documents. You can do this without having to do any Office automation and the process is fairly straightforward. For simple grid based spreadsheets I have found it to be a bit easier than trying to automate it using Excel. The Office Open XML is quite powerful and allows for more complex reports are possible as well some more effort.
You need safely dispose all COM interop objects after you end your work. By "all" I mean absolutely all: collections property values and so on. I've created stack object and pushed objects during their setup:
Stack<object> comObjectsToRelease = new Stack<object>();
...
Log("Creating VBProject object.");
VBProject vbProject = workbook.VBProject;
comObjectsToRelease.Push(vbProject);
...
finally
{
if(excel != null)
{
Log("Quiting Excel.");
excel.Quit();
excel = null;
}
while (comObjectsToRelease.Count > 0)
{
Log("Releasing {0} COM object.", comObjectsToRelease.GetType().Name);
Marshal.FinalReleaseComObject(comObjectsToRelease.Pop());
}
Log("Invoking garbage collection.");
GC.Collect();
}
If Excel is still there you have to kill it manually.
The best approach is to use a purpose built library such as the one from Aspose to generate the spreadsheets or populate templates. The next best approach is to use the xml formats for office if practical for your needs. A lightweight approach that is sometimes suitable is to create an HTML file with one table in it and name it with an .xls extension. Excel will happily read that, but it is very limited in what it can do.
Those are the options I've used (but not much). There's also a thing called Microsoft Office Sharepoint Server, but I've no idea how much it really lets you do.
That said, your problem is happening because when you invoke the regular Excel libraries, you're actually spinning up Excel completely independently of .Net and actually just working with a proxy library to talk to it. This is pretty much the same kind of thing you'd have with WCF and a service. You wouldn't expect the service to die just because the client application was done using it. Worse, Excel is an unmanaged resource and will not be disposed/ finalized/ garbage collected at all. The .Net Runtime doesn't know about Excel, it just knows about those proxies. Application.quit is what you need and also you may need to explicitly release the com objects that are created.

Resources