No se cierra el proceso excel VB.NET Excel 2007 VS 2010

Iniciado por Yaldabaot, 22 Octubre 2015, 00:46 AM

0 Miembros y 1 Visitante están viendo este tema.

Yaldabaot

Hola,

Estoy utilizando un archivo de excel, todo bien simplemente que cuando quiero terminar y/o cerrar el archivo de excel pues no se cierra.

Acá lo asigno
Código (vbnet) [Seleccionar]


objeto_excel = New LibroExcel() 'Crea un nuevo libro
                    objeto_excel.xApplication = New Excel.Application() 'Crea una nueva aplicación

                    objeto_excel.xApplication.DisplayAlerts = False
                    objeto_excel.XWorkBook = objeto_excel.xApplication.Workbooks.Open(Arch) 'Realiza una nueva aplicación con un nuevo libro a abrir.
                    objeto_excel.XWorksheet = objeto_excel.XWorkBook.Worksheets.Item(1) 'Asigna la hoja de excel
                    objeto_excel.ficheros = fichero



Acá lo cierro ( Código forzoso pues no cierra!!!)

Código (vbnet) [Seleccionar]



Try

            If IsFileOpen(fichero) = False Then
                End
                GC.Collect()
            Else

                obj_excel.XWorksheet = Nothing
                GC.Collect()

                obj_excel.XWorkBook.Close()
                obj_excel.XWorkBook = Nothing

                GC.Collect()

                obj_excel.xApplication.Quit()
                obj_excel.xApplication = Nothing

                GC.Collect()

                obj_excel.ficheros = Nothing

                GC.Collect()

                releaseObject(obj_excel)

                End
            End If

        Catch ex As Exception
            MsgBox("Hubo un problema cerrando el programa y/o el archivo.")
            End
        End Try




Acá la clase libro

Código (vbnet) [Seleccionar]


  Private xlApp As Excel.Application
    Private xlWorksheet As Excel.Worksheet
    Private xlworkbook As Excel.Workbook
    Private fichero As String

    'Propiedades accesoras

    Public Property xApplication() As Excel.Application
        Get
            Return Me.xlApp
        End Get
        Set(ByVal Value As Excel.Application)
            Me.xlApp = Value
        End Set
    End Property


    Public Property XWorkBook() As Excel.Workbook
        Get
            Return Me.xlworkbook
        End Get
        Set(ByVal Value As Excel.Workbook)
            Me.xlworkbook = Value
        End Set
    End Property

    Public Property XWorksheet() As Excel.Worksheet
        Get
            Return Me.xlWorksheet
        End Get
        Set(ByVal Value As Excel.Worksheet)
            Me.xlWorksheet = Value
        End Set
    End Property

    Public Property ficheros() As String
        Get
            Return Me.fichero
        End Get
        Set(ByVal Value As String)
            Me.fichero = Value
        End Set
    End Property









Nunca me contestan -_-

Yaldabaot

Tengo esta forma pero me vuela todos los exceles y es muy violenta, alguno sabrá de otra manera o que está haciendo mal?

Código (vbnet) [Seleccionar]


Sub KillAllExcels()

        Try



            Dim proc As System.Diagnostics.Process



            For Each proc In System.Diagnostics.Process.GetProcessesByName("EXCEL")

                If proc.MainWindowTitle.Trim.Length = 0 Then

                    'proc.GetCurrentProcess.StartInfo

                    proc.Kill()

                End If

            Next

        Catch ex As Exception

            My.Computer.FileSystem.WriteAllText("C:\errores.log", Format(Now, "01/MM/yyy HH:mm") & " - " & ex.Message & vbCrLf, True)

        End Try

    End Sub
Nunca me contestan -_-

Eleкtro

#2
No me manejo con la inter-operabilidad de Office, pero en general lo que estás haciendo es incorrecto, creo que el fallo lo cometes en estas dos órdenes:

Citar
Código (vbnet,4,5) [Seleccionar]
objeto_excel = New LibroExcel() 'Crea un nuevo libro
objeto_excel.xApplication = New Excel.Application() 'Crea una nueva aplicación
objeto_excel.xApplication.DisplayAlerts = False
objeto_excel.XWorkBook = objeto_excel.xApplication.Workbooks.Open(Arch) 'Realiza una nueva aplicación con un nuevo libro a abrir.
objeto_excel.XWorksheet = objeto_excel.XWorkBook.Worksheets.Item(1) 'Asigna la hoja de excel
objeto_excel.ficheros = fichero

Al usar órdenes de ese tipo con llamadas a más de un miembro (referencia.miembro1.miembro2()) estás generando residuos/objetos RCW (Runtime Callable Wrapper) tanto para el primero como para el segundo, y estos deberías liberarlos al terminar con Excel, pero sin una referencia al objeto no puedes liberarlos.



Por ende, la forma en la que se debe trabajar un objeto COM, en tu caso la interop de Office/Excel, sería la siguiente:

Código (vbnet) [Seleccionar]
Dim excelApp as Excel.Application = objeto_excel.xApplication

Dim workbooks As ...? = excelApp.Workbooks
Dim workbook As Excel.Workbook = workbooks.Open(Arch)

Dim xWorkBook As Excel.Workbook = excelApp.XWorkBook
Dim worksheets As Excel.Worksheets = xWorkBook.Worksheets
Dim worksheet As Excel.Worksheet = worksheets.Item(1)


Reemplaza "...?" por lo correspondiente, como ya digo yo no uso Office, pero esto es aplicable de forma general.

Una vez hayas corregido eso, guardas los cambios en el archivo y seguidamente cierras de forma normal:
Código (vbnet) [Seleccionar]
xWorkBook.Save()
xWorkBook.Close(SaveChanges:=False)
excelApp.Quit()


Y por último, liberas los objetos:
Código (vbnet) [Seleccionar]
Marshal.ReleaseComObject(workbook)
Marshal.ReleaseComObject(workbooks)

Marshal.ReleaseComObject(worksheet)
Marshal.ReleaseComObject(worksheets)
Marshal.ReleaseComObject(xWorkBook)

Marshal.ReleaseComObject(excelApp)





Citar
Código (vbnet) [Seleccionar]
Try
   If IsFileOpen(fichero) = False Then
       End
       GC.Collect()
   Else

       obj_excel.XWorksheet = Nothing
       GC.Collect()

       obj_excel.XWorkBook.Close()
       obj_excel.XWorkBook = Nothing

       GC.Collect()

       obj_excel.xApplication.Quit()
       obj_excel.xApplication = Nothing

       GC.Collect()

       obj_excel.ficheros = Nothing

       GC.Collect()

       releaseObject(obj_excel)

       End
   End If

Catch ex As Exception
   MsgBox("Hubo un problema cerrando el programa y/o el archivo.")
   End
End Try

Por si no ha quedado claro, ten en cuenta que no debes invocar al GarbageCollector a lo loco como estás haciendo (y hacerlo despues de un "End", ¿en serio para qué? xD), ya que eso no te servirá para nada positivo y menos con código no administrado...

En todo caso prueba así:

Código (vbnet) [Seleccionar]
Try
   If IsFileOpen(fichero) Then
           xWorkBook.Save()
   xWorkBook.Close(SaveChanges:=False)
   excelApp.Quit()
   End If

Catch ex As Exception
   MsgBox("Hubo un problema cerrando el programa y/o el archivo." & Environment.NewLine & ex.toString)

Finally
Marshal.ReleaseComObject(workbook)
Marshal.ReleaseComObject(workbooks)
Marshal.ReleaseComObject(worksheet)
Marshal.ReleaseComObject(worksheets)
Marshal.ReleaseComObject(xWorkBook)
Marshal.ReleaseComObject(excelApp)

   Me.Close() ' Cierra el Form principal de forma normal... no uses el keyword "End".

End Try


Espero que esto te pueda servir para solucionar el problema.

Saludos!




Fuente(s):









Yaldabaot

Gracias Elektro, lo probaré y te estaré contando como me fue, muchas gracias por dedicar tiempo a la respuesta.
Nunca me contestan -_-

Yaldabaot

Elektro no soy de los que molesta por cada nada, solo que le he dado vueltas y no entiendo tu código, viste que lo que utiliza es una clase?, lo que lleno son sus atributos, al final ocupo utilizar ese objeto pues todo el proyecto utiliza ese objeto.

Con respecto al end, ese código es de un botón el cuál es para salir del programa, el END es para salir, talvez el orden esté mal, si lo está pues estoy anuente a recibir opiniones o críticas-


Código (vbnet) [Seleccionar]



    Dim excelApp as Excel.Application = objeto_excel.xApplication
     
    Dim workbooks As ...? = excelApp.Workbooks
    Dim workbook As Excel.Workbook = workbooks.Open(Arch)
     
    Dim xWorkBook As Excel.Workbook = excelApp.XWorkBook
    Dim worksheets As Excel.Worksheets = xWorkBook.Worksheets
    Dim worksheet As Excel.Worksheet = worksheets.Item(1)

Nunca me contestan -_-

Yaldabaot

Mira agregué esto en el código de la clase LibroExcel pero sigue sin cerrarse :(


Código (vbnet) [Seleccionar]


Public Sub New(ByVal fichero As String)

       xlApp = New Excel.Application

       xlworkbook = xlApp.Workbooks.Open(fichero)
       xlWorksheet = xlApp.Worksheets.Item(1)

   End Sub


   Public Sub liberar_Excel()


       xlworkbook.Save()
       xlworkbook.Close()
       xlApp.Quit()


       Marshal.ReleaseComObject(xlworkbook)
       Marshal.ReleaseComObject(xlWorksheet)
       Marshal.ReleaseComObject(xlApp)


   End Sub


Nunca me contestan -_-

Yaldabaot

Elektro ya lo logré!!

Este fue el constructor de la clase LibroExcel que utilicé

Código (vbnet) [Seleccionar]


'Constructores

    Public Sub New(ByVal fichero As String)

        xlApp = New Excel.Application

        xlworkbook = xlApp.Workbooks.Open(fichero)
        xlWorksheet = xlApp.Worksheets.Item(1)

       

    End Sub



Acá le asigno el atributo ficheros

Código (vbnet) [Seleccionar]



  objeto_excel = New LibroExcel(fichero) 'Crea un nuevo libro


                    objeto_excel.xApplication.DisplayAlerts = False
                    objeto_excel.ficheros = fichero





Acá termino el maldito proceso pega -.- (cómo me costó.........)


Código (vbnet) [Seleccionar]



Try

            If IsFileOpen(fichero) = True Then


                obj_excel.XWorkBook.Save()
                obj_excel.XWorkBook.Close()


                obj_excel.xApplication.Workbooks.Close()
                obj_excel.xApplication.Quit()


                obj_excel.xApplication = Nothing
                obj_excel.XWorkBook = Nothing
                obj_excel.XWorksheet = Nothing
                obj_excel.ficheros = Nothing

            Else

                releaseObject(obj_excel)

            End If

        Catch ex As Exception
            MsgBox("Hubo un problema cerrando el programa y/o el archivo.")
        Finally
            End
        End Try
    End Sub




Agrego que el método file open le hice un cambio, donde no me estaba agarrando el path completo del archivo.

Sugerencias, dudas, críticas estamos a la orden,

GRACIAS ELEKTRO.

Nunca me contestan -_-

Eleкtro

#7
Cita de: Yaldabaotno soy de los que molesta por cada nada

Personálmente no creo que molestes, tienes dudas y necesitas respuestas nada más (aunque llego un poco tarde a responderlas xD).




Cita de: Yaldabaot en 22 Octubre 2015, 23:31 PMCon respecto al end, ese código es de un botón el cuál es para salir del programa, el END es para salir, talvez el orden esté mal, si lo está pues estoy anuente a recibir opiniones o críticas-

El keyword End es para salir, si, pero mejor dicho es para finalizar la ejecución de la aplicación de forma inmediata o anómala.

Cita de: https://msdn.microsoft.com/en-us/library/0wt87xba.aspx

No se debería utilizar End sin una razón de peso, en WinForms lo apropiado siempre es cerrar el form principal llamando al método Form.Close (o en su defecto utilizar el método Application.Exit el cual cierra todos los Forms abiertos de forma normal). Si por alguna razón no se cierra, se debe tratar de averiguar el por qué y corregirlo en lugar de ignorarlo por las malas con End.

De todas formas yo te hice aquél comentario entre paréntesis por que si finalizas la ejecución de la app entonces no tiene sentido añadir más instrucciones despues de la orden End simplemente por que no se van a procesar.




Cita de: Yaldabaot en 22 Octubre 2015, 23:31 PMno entiendo tu código, viste que lo que utiliza es una clase?, lo que lleno son sus atributos, al final ocupo utilizar ese objeto pues todo el proyecto utiliza ese objeto.

Código (vbnet) [Seleccionar]

   Dim excelApp as Excel.Application = objeto_excel.xApplication
   
   Dim workbooks As ...? = excelApp.Workbooks
   Dim workbook As Excel.Workbook = workbooks.Open(Arch)
   
   Dim xWorkBook As Excel.Workbook = excelApp.XWorkBook
   Dim worksheets As Excel.Worksheets = xWorkBook.Worksheets
   Dim worksheet As Excel.Worksheet = worksheets.Item(1)



Con ese código solo intentaba indicarte las referencias que debes manejar por separado (6 objetos distintos), no como debes hacerlo. Obviamente lo deberías adaptar a la estructura que tienes montada en tu class.

Me alegro que lo hayas solucionado, aunque no has seguido esa indicación que hice pero no importa. Solo revisa que en el administrador de tareas realmente no se queda el proceso del excel corriendo de forma "invisible", y si pasa entonces aplica eso que dije.

Saludos








Yaldabaot

Gracias Elektro, acaté tus recomendaciones, lo que pasa en el caso de lo que me dijiste del código donde me corregiste (y pues tienes razón), estrictamente debo usar esa clase, pues en TODO el proyecto se apoya en ese objeto y sobretodo sus atributos en el caso de xlworkbook, xlworksheet y xlapplication, ficheros también, entonces cuando utilizo ese objeto los demás métodos se apoyen en él, puesto que el archivo excel se encuentra en background y la idea es que apenas se salga de la aplicación el user pues el archivo efectivamente se cierre.

Y si ves bien, si agarré parte de tus recomendaciones, ¿ Cómo no voy a agarrar tus recomendaciones? si eres un GRAN conocedor!. ¿ Y en donde? Pues en la parte del save y saveworkbook, me puse a pensar sobre el cierre abrupto y como sabrás el Excel cuando se cierra de esa manera pues tiene como un respaldo, eso podría también generar que se conserve el excel en memoria, por tanto el guardado le quita esa posibilidad.

Otra recomendación que acaté es el cierre que me dices, considero que es importante no forzar el cierre.


Con respecto al proceso de EXCEL que no se cierra, efectivamente tengo el administrador de tareas casi que a la par mía y del visual studio y pues corroboré que si cierra.

Un saludo, que estés bien.

Nunca me contestan -_-