Colaboraciones en el Guille

Procesos Excel en ASP.NET

Permisos y eliminación de Procesos excel.exe en aplicaciones Web

 

Fecha: 09/Ene/2006 (08/01/2006)
Autor: Jorge Ojeda García - ([email protected])

 



Introducción

En los últimos tiempos se han incrementado las aplicaciones realizadas en office, casi es un hecho insólito que una empresa grande no tenga dentro de su suite de software a Microsoft Excel como herramienta casi de "cabecera".
Ello ha traído como consecuencia que muchas de nuestras aplicaciones tengan una cierta interacción con este producto, tal es el caso de las aplicaciones web.

Quien no se ha topado alguna vez con la necesidad de poder hacer algún "upload" a un archivo Excel y poder extraer los datos que contenga dicho archivo, creo que la mayoría de uds ya lo han realizado, pues bien, el motivo de este articulo es mostrarles la solución a algunos problemas que me han estado persiguiendo los últimos días, primero, que no podía trabajar con el objeto Excel, porque no tenia los permisos suficientes como para crear el ActiveX (bueno ese mas o menos el mensaje que me salia) y segundo, que el proceso EXCEL.EXE no desaparecía de mi Administrador de Tareas al ser ejecutado, es mas, cada vez que mi aplicación web hacia esa operación, un proceso nuevo era creado, y no es por exagerar pero he conocido de una empresa que un fin de semana tenían 134 procesos EXCEL.EXE ejecutándose, pues, en este articulo tratare de manera sencilla el explicarles como hacer para que estas cosas no sucedan.

Permisos para crear procesos EXCEL.EXE

Entonces, primero vayamos a la raíz del problema, mi usuario desea que mi aplicación web (ASP.NET) pueda leer archivos Excel que tiene un formato especifico.

Hoja excel

Hasta ahí todo parece sencillo para lo cual realizo el siguiente código en VB.NET.

Private Sub btnCargar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
				Handles btnCargar.Click
    ' Al presionar este boton se realizara el upload del archivo que se haya elegido
    Dim oXL As Excel.Application
     oXL = CreateObject("Excel.Application")
     oXL.Visible = False     
     oWB = oXL.Workbooks.Open(btnExaminar.Value)
     oSheet = oWB.ActiveSheet

     ' Como prueba inicial solo pintaremos los datos de la primera fila de datos
     txtValorColumna1.Text = oSheet.Cells(3, 1).value     
     txtValorColumna2.Text = oSheet.Cells(3, 2).value
	  
     If Not oWB Is Nothing Then
         oWB.Close()
         oXL.Quit()
         oXL = Nothing : oWB = Nothing : oSheet = Nothing
     End If

     System.GC.Collect()
End Sub

Hasta este momento solo estamos tratando de instanciar el objeto Excel dentro de nuestro servidor, con el primer problema que nos encontramos es que cuado tratamos de ejecutar este código, salta el siguiente error:

"cannot create activex component "

Como podemos apreciar el usuario con el que se esta ejecutando el programa no tiene suficientes permisos com para poder crear el objeto Excel, para poder solucionar ese inconveniente se debe seguir los siguientes paso:

Run comcnfg

Servicio Componentes

Menu contextual Excel app

Identidad

Permisos

Con esto pasos nos aseguramos que se pueda iniciar con cualquier usuario nuestro objeto Excel.

Eliminando procesos EXCEL.EXE

Con estos pasos ya se debió haber solucionado el primer inconveniente, ahora volvamos a nuestro código original, ahora si lo compilamos y ejecutamos.

El resultado es el siguiente:

Pantalla Inicial

Hasta ahí todo marcha de lo mas normal, tenemos el código que cumple con nuestro requerimiento, y funciona de lo mejor, pero.... hay algo que no nos hemos percatado, es que cuando vemos nuestro "Administrador de Tareas" vemos que el proceso EXCEL.EXE de cada llamada no esta siendo eliminada (No siempre pasa esto, pero es mas seguro seguir las instrucciones siguientes).

View process

Si vemos nuestro código nos damos cuenta que hemos creado 3 objetos de Excel: Application, Workbook y Worksheet, los cuales debes ser destruidos para poder eliminar el proceso Excel, además de eliminar todas las referencias de estos objetos COM, para ello utilizamos el método "System.Runtime.InteropServices.Marshal.ReleaseComObject(object)" de la siguiente forma:

Private Sub btnCargar_Click(ByVal sender As System.Object, ByVal e As System.EventArgs) _
				Handles btnCargar.Click
     ' Al presionar este boton se realizara el upload del archivo que se haya elegido
     Dim oXL As Excel.Application
     Dim oWB As Excel.Workbook
     Dim oSheet As Excel.Worksheet
    
     oXL = CreateObject("Excel.Application")
     oXL.Visible = False
     oWB = oXL.Workbooks.Open(btnExaminar.Value)
     oSheet = oWB.ActiveSheet
     
     ' Como prueba inicial solo pintaremos lo que haya en la primera celda
     Response.Write(oSheet.Cells(1, 1).value)

     If Not oWB Is Nothing Then
          ' Hago un bucle de eliminaciones de las referencias de cada objeto
	  ' que tiene relacion con el EXCEL
          EiminaReferencias(oSheet)
          oXL.Workbooks(1).Close(False)
          EiminaReferencias(oWB)
          oXL.Quit()
          EiminaReferencias(oXL)
     End If

     System.GC.Collect()
End Sub

Private Sub EiminaReferencias(ByRef Referencias As Object)
     Try
     'Bucle de eliminacion
          Do Until _
               System.Runtime.InteropServices.Marshal.ReleaseComObject(Referencias) <= 0
               Loop
          Catch
     Finally
          Referencias = Nothing
     End Try
End Sub

Si vemos de nuevo nuestro Administrador de Tareas nos percataremos que ahora si se van eliminando los procesos Excel que hayamos instanciado.

Conclusiones


Espacios de nombres usados en el código de este artículo:

Microsoft.Office.Interop
System.GC
System.Runtime.InteropServices.Marshal

 


Fichero con el código de ejemplo: joga_ProcesosExcelASPNET.zip - 14.0 KB

(MD5 checksum: 7D95E5B007E29D3659A50B9163205EF8)


ir al índice principal del Guille