Visual Basic.NET - Conexión a Excel

 
Vista:
sin imagen de perfil

Conexión a Excel

Publicado por Daniel (18 intervenciones) el 20/01/2017 22:40:44
Buenas,
Estoy haciendo un programa con Visual Basic 2015,
Consiste en que el usuario tiene que ir seleccionando datos de combobox, rellenado textbox etc para que luego le muestre un resultado.
Como los cálculos son complejos y se precisa de bastantes datos, se quiere realizar una conexión a excel.
En este excel traslado los datos introducidos en el programa y realizo los cálculos para a continuación coger los resultados y traerlos de nuevo al programa. He conseguido abrir el excel que tengo e introducir valores y poder coger los resultados. El problema es que, solo soy capaz de abrir y cerrar el excel cuando pulso un button, es decir el codigo está implementado en un boton y cuando le pulso, abre el excel trabaja y rellena los campos del programa con los resultados, pero el excel se abre y cierra. Mi intención es tener el excel abierto en segundo plano (así el usuario no vería que se trabaja con ese excel y va obteniendo los resultados) Pero no soy capaz de abrirlo y mantenerlo abierto hasta que yo quiera.
He estado mirando para usar BackgroundWorker con DoWork pero no encuentro la manera.
Por ahora esto es lo que tengo. Funciona pero cada vez que quiero cambiar algun dato el programa se queda parado, ya que tiene que abrir el excel trabajar y cerrarlo.
Además, la última parte "Private Sub releaseObject(ByVal obj As Object)...." no se muy bien para que sirve.. No se si tendría que estar o no.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
Private Sub ComboBox2_TextChanged(sender As Object, e As EventArgs) Handles ComboBox2.TextChanged
 
        Dim filetest As String = "C:\Datos entrada.xlsx"
        Dim oExcel As Object
        oExcel = CreateObject("Excel.Application")
        oExcel.Workbooks.Open(filetest)
        Dim oBook As Microsoft.Office.Interop.Excel.Workbook
        Dim oSheet As Microsoft.Office.Interop.Excel.Worksheet
        oBook = oExcel.ActiveWorkbook
        oSheet = oExcel.Worksheets(3)
        'Modificamos valores 
        oSheet.Range("R59").Value = ComboBox3.Text
 
 
        TextBox9.Text = oSheet.Range("AR60").Value
        TextBox12.Text = oSheet.Range("AR59").Value
 
        'Guardamos
        oExcel.DisplayAlerts = False
        oBook.SaveAs(filetest, 51) '51 es xlsx / 1 es xls
        oBook.Close()
        oExcel.Quit()
        oBook = Nothing
        releaseObject(oExcel)
        releaseObject(oSheet)
 
 
    End Sub
 
    Private Sub releaseObject(ByVal obj As Object)
        Try
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
            obj = Nothing
        Catch ex As Exception
            obj = Nothing
        Finally
            GC.Collect()
        End Try
    End Sub

Espero me puedan ayudar.

Muchas gracias.

Saludos.
Valora esta pregunta
Me gusta: Está pregunta es útil y esta claraNo me gusta: Está pregunta no esta clara o no es útil
0
Responder
sin imagen de perfil
Val: 481
Bronce
Ha mantenido su posición en Visual Basic.NET (en relación al último mes)
Gráfica de Visual Basic.NET

Conexión a Excel

Publicado por Miguel (476 intervenciones) el 21/01/2017 09:41:29
No entiendo por qué tienes que usar Excel para procesar tus datos, en fin. Creo que no es necesario usar el BackgroundWorker en esto. A continuación te dejo una idea:

1: Creas variables globales (nivel formulario) que te sirvan para manipular los datos (Workbook o Worksheet en este caso)

2: Carga el Excel (desde algún botón) y lo pasas a la variable global para posteriormente poder realizar las respectivas manipulaciones.

3: Aquí usarías la variable global (pasar los valores, obtener, etc.)

4: Cierra el objeto Excel (desde algún botón) y lo liberas con la función "releaseObject(Object)" que tienes (para esto sirve).
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

Conexión a Excel

Publicado por Daniel (18 intervenciones) el 21/01/2017 10:37:27
Buenas,
Gracias por responder.

Ya soy capaz de abrirlo al principio y luego cerrarlo!!

Utilizo Excel porque mucha información ya la tengo en Excel. Y es lo que me han solicitado que haga.
¿Crees que hay una forma mejor de hacerlo? Si el resultado es mejor podría cambiarlo.

Gracias.
Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Diego
Val: 605
Bronce
Ha mantenido su posición en Visual Basic.NET (en relación al último mes)
Gráfica de Visual Basic.NET

Conexión a Excel

Publicado por Diego (190 intervenciones) el 21/01/2017 10:42:25
Hola, si. Mirá, una buena opcion es primero antes de declarar la clase form importar los namespaces correspondientes por ejemplo....

1
Imports Excel = Microsoft.Office.Interop.Excel

Para que al momento de abrir el form se cree una instancia, en las declaraciones globales del form que desees, tenés que crear el objeto oExcel asi.

1
Public oExcel as New Excel.Application

Ese objeto, va a abrir una instancia de Excel, hasta que vos decidas cerrarla, por ejemplo, en el evento FormClosed de tu form del siguiente modo:

1
oExcel.Quit

Respecto al release object. El tema es que vos mediante la instruccion

1
System.Runtime.InteropServices.Marshal.ReleaseComObject(oExcel)

Liberas el recurso del llamado a la aplicacion Excel. Ya que Microsoft reporto que por algun tema de compatibilidad en la automatizacion de los libros excel. Muchas veces el metodo Quit, para cerrar la aplicacion, no termina cerrando efectivamente el Excel. Así que es necesario hacer ese releaseComObject con ese fin.

Espero haberte podido orientar, aunque sea un poco mas.
Saludos y +Bytes.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
1
Comentar
sin imagen de perfil

Conexión a Excel

Publicado por Daniel (18 intervenciones) el 21/01/2017 14:00:27
Muchas gracias he seguido vuestros pasos y ahora abro y cierro el Excel sin que se quede en segundo plano.

Mi intención es abrir un Excel al principio y poder trabajar con el desde varios formularios. ¿Cómo podría hacer eso? Estoy intentándolo de mil maneras pero no me sale.. Solo obtengo errores. ¿Podría hacerlo desde un módulo?
Por ahora he puesto que al darle al botón para pasar al siguiente formulario se cierre y que si le vuelvo a pulsar "al de volver" me lo abra otra vez el Excel...
Insisto en que lo ideal sería abrirlo al principio y que se cerrase o porque le doy a la [x] propia del formulario o porque en el último formulario cierro el programa. Espero me puedan ayudar porque no se por donde tirar ya..

Este código lo único que hago es abrirlo al principio y lo que quiero es que al darle a la [x] propia del formulario me cierre el excel. Pero me genera un problema al darle a la [x]

"Excepción no controlada del tipo 'System.NullReferenceException' en Programa.exe" "
Información adicional: Referencia a objeto no establecida como instancia de un objeto."
Lo comento al final, lo he solucionado poniendo en
Private Sub ComboBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox2.SelectedIndexChanged
oSheet3.Range("R59").Value = ComboBox2.Text
End Sub
El codigo que utilizo es:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
Imports System.Data
Imports System.IO
Imports Excel = Microsoft.Office.Interop.Excel
Public Class Datos
    Public filetest As String = "C:\Datos entrada.xlsx"
    'Public oExcel As Object
    Public oBook As Microsoft.Office.Interop.Excel.Workbook
    Public oSheet As Microsoft.Office.Interop.Excel.Worksheet
    Public oSheet3 As Microsoft.Office.Interop.Excel.Worksheet
    Public oExcel As New Excel.Application
 
    Sub abrirexcel()
       oExcel = CreateObject("Excel.Application")
        oExcel.Workbooks.Open(filetest)
        oBook = oExcel.ActiveWorkbook
        oSheet = oExcel.Worksheets(2)
        oSheet3 = oExcel.Worksheets(3)
    End Sub
 Private Sub ComboBox2_SelectedIndexChanged(sender As Object, e As EventArgs) Handles ComboBox2.SelectedIndexChanged
        oSheet3.Range("R59").Value = ComboBox2.Text
    End Sub
 
  Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
        ComboBox2 = Nothing
 
        Cerrarelexcel()
    End Sub
 
 Public Sub Cerrarelexcel()
        oExcel.DisplayAlerts = False
        oBook.SaveAs(filetest, 51) '51 es xlsx / 1 es xls
        oBook.Close()
        oBook = Nothing
        oSheet = Nothing
        oSheet3 = Nothing
        oExcel.Quit()
 
        releaseObject(oExcel)
        releaseObject(oSheet)
        releaseObject(oSheet3)
    End Sub
    Private Sub releaseObject(ByVal obj As Object)
        Try
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
            obj = Nothing
        Catch ex As Exception
            obj = Nothing
        Finally
            GC.Collect()
        End Try
    End Sub
Me sale un error al cerrar desde la [x] propia del formulario.
"Excepción no controlada del tipo 'System.NullReferenceException' en Programa.exe" "
Información adicional: Referencia a objeto no establecida como instancia de un objeto."
Lo he "solucionado" poniendo en FormClosed
"ComboBox2 = Nothing"
Así no aparece el error del combobox2...
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
Imágen de perfil de Diego
Val: 605
Bronce
Ha mantenido su posición en Visual Basic.NET (en relación al último mes)
Gráfica de Visual Basic.NET

Conexión a Excel

Publicado por Diego (190 intervenciones) el 23/01/2017 03:52:36
Perfecto, si. Una opcion es ponerlo en un modulo global y hacer el oExcel public.
En los forms, a medida que se abren y se cierran, en vez de quitar la referencia a oExcel, lo que tendrías que hacer es solamente apuntar a los workbooks. Grabarlos o descartar los cambios y cerrarlos.

Para eso, deberías solo cerrar los workbooks y worksheets. Y solo ejecutas el ReleaseComObject al cerrar tu aplicación.

Otra sugerencia es que los releaseObject los hagas en el sentido inverso, es decir, primero las hojas, luego los libros y por ultimo application.

Saludos y +bytes.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar
sin imagen de perfil

Conexión a Excel

Publicado por Daniel (18 intervenciones) el 23/01/2017 10:32:49
Buenas,
Muchas gracias por la ayuda!
He modificado lo del cierre, tienes razón.
Lo de apuntar a los Workbooks no lo he entendido demasiado bien.
Este es el código que he puesto por ahora.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Imports System.Data
Imports System.IO
Imports Excel = Microsoft.Office.Interop.Excel
Module ModuleCerrarExcel
 
    Public Sub CerrarExcel()
        oExcel.DisplayAlerts = False
        'oBook.SaveAs(filetest, 51) '51 es xlsx / 1 es xls
        oSheet = Nothing
        oSheet3 = Nothing
        oBook = Nothing
 
        oBook.Close()
        oExcel.Quit()
 
        releaseObject(oSheet)
        releaseObject(oSheet3)
        releaseObject(oExcel)
 
 
    End Sub
    Private Sub releaseObject(ByVal obj As Object)
        ' Necesario para que el Excel se cierre, ya que con oExcel.Quit() puede no cerrarse.
        Try
            System.Runtime.InteropServices.Marshal.ReleaseComObject(obj)
            obj = Nothing
        Catch ex As Exception
            obj = Nothing
        Finally
            GC.Collect()
        End Try
    End Sub
 
End Module
 
Private Sub Form1_FormClosed(sender As Object, e As FormClosedEventArgs) Handles Me.FormClosed
        'Así conseguimos que cuando pulsemos la [x]sup.der se cierre la aplicación Excel con Cerrarelexcel().
        Me.Hide()
 
        CbMunicipio = Nothing
        CbPoblacion = Nothing
        ModuleCerrarExcel.CerrarExcel()

He quitado el Save ya que realmente no es necesario guardar lo que se mete al excel.
Así se cierra siempre que le de a la [x] de arriba a la derecha.
Además falta poner un botón en el último formulario( todavía no está hecho) para que también se cierre.

Muchas gracias.

Un saludo.
Valora esta respuesta
Me gusta: Está respuesta es útil y esta claraNo me gusta: Está respuesta no esta clara o no es útil
0
Comentar