none
Leer hojas de un excel RRS feed

  • Pregunta

  • Hola,

    Estoy intentando leer las hojas que contiene un excel, y por más que miro páginas no consigo que me las lea, siempre me muestra como nombre "tables" cuando tendría que tener hoja1 y hoja 2.

    Este es el código que tengo.

    No uso el api de office sino que lo hago con el oledb.

      Dim oledbConn = New OleDbConnection(sConnectionString)
            Dim oledbCmd = New OleDbCommand(sqlExcel, oledbConn)
    
            Dim i As Integer
            Dim a As Integer
            Try
               
                oledbConn.Open()
    
                If ConnectionState.Open Then
                    Dim DAdapter = New OleDbDataAdapter(oledbCmd)
                    Dim LS_SQL As String
                    Dim c As Integer
                    Dim table As DataTable = CType(oledbConn, OleDbConnection).GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)
                    Dim nombrehojas(table.Rows.Count) As String
    
    
    
                    For c = 0 To table.Rows.Count
                        nombrehojas(c) = table.Rows.Item(c).Table.TableName.ToString
    
                    Next

    lunes, 4 de febrero de 2013 9:09

Respuestas

  • "dankito" escribió:

    > Estoy intentando leer las hojas que contiene un excel, y por más que
    > miro páginas no consigo que me las lea, siempre me muestra como
    > nombre "tables" cuando tendría que tener hoja1 y hoja 2.
    >
    >   Dim table As DataTable = _
    >   CType(oledbConn, OleDbConnection).GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)

    > AL final lo que he hecho ha sido usar la API de Excel para recoger
    > los nombres de las hojas pero me gustaría saber si hay forma de
    > recorrer celda por celda desde esa API y si hay forma de volcar
    > los datos directamente a un datatable en vez de celda por celda.

    Hola:

    No es necesario utilizar la API de Excel (la biblioteca de objetos de Microsoft Excel), para obtener los nombres de las hojas de cálculo de un libro de Excel, porque con el ISAM de Excel del motor de datos Microsoft Jet o Microsoft ACE lo puedes hacer de una manera muchísimo más eficaz. Eso sí, hay que saber hacerlo bien, tal y como muestro a continuación:

    Imports System.Data.OleDb
    
        Private Function GetTables(fileName As String) As List(Of String)
    
            ' Construimos la cadena de conexión con el libro de Excel especificado
            '
            Dim connString As String = _
                "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                "Extended Properties='Excel 8.0;';" & _
                "Data Source=" & fileName
    
            Try
                ' Establecemos la conexión
                '
                Using cnn As New OleDbConnection(connString)
    
                    ' Hay que abrir explícitamente la conexión.
                    '
                    cnn.Open()
    
                    Using dt As DataTable = cnn.GetSchema("TABLES")
    
                        Dim query As IEnumerable(Of String) = _
                                From row As DataRow In dt.Rows.Cast(Of DataRow)() _
                                Where CStr(row.Item("TABLE_TYPE")).ToUpperInvariant() = "TABLE" _
                                Order By row.Item("TABLE_NAME") _
                                Select CStr(row.Item("TABLE_NAME"))
    
                        Return query.ToList()
    
                    End Using
    
                End Using
    
            Catch
                ' Devuelvo la excepción al llamador.
                Throw
    
            End Try
    
        End Function

    Si por casualidad deseas obtener las hojas de un libro de Excel versión 2007 o superior, utiliza la siguiente cadena de conexión:

            Dim connString As String = _
                "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                "Extended Properties='Excel 12.0 Xml;';" & _
                "Data Source=" & fileName

    Cuando desees obtener el nombre de las hojas de un libro concreto, llamarías a la función de la siguiente manera:

            Try
                ListBox1.DataSource = GetTables("C:\Mis documentos\Libro1.xls")
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try

    En éste caso te aparecerán los nombres en un control ListBox. Te advierto que los nombres de las hojas finalizarán con el carácter $, que es como el ISAM de Excel reconoce los nombres de las hojas de cálculo existentes en un libro de trabajo, y si el nombre de la hoja contiene espacios en blanco, el nombre aparecerá también limitado por comillas simples. Si no deseas que te aparezcan esos caracteres, entonces tendrás que recorres cada elemento de la lista para eliminarlos:

            Try
                Dim hojas As List(Of String) = GetTables("C:\Mis documentos\Libro1.xls")
    
                For Each hoja As String In hojas
    
                    If (hoja.Contains("$"c)) Then
                        hoja = hoja.Replace("$", String.Empty)
                    End If
    
                    If (hoja.Contains("'"c)) Then
                        hoja = hoja.Replace("'", String.Empty)
                    End If
    
                    ListBox1.Items.Add(hoja)
                Next
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try

    ¡Eso es todo! Adapta el ejemplo a tus necesidades.

    Un saludo


    Enrique Martínez
      [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.



    martes, 5 de febrero de 2013 15:28
    Moderador

Todas las respuestas

  • Buenas,

    Para hacer eso, yo lo hago de la siguiente manera (adjunto trozo de codigo)

            Try
    
                Dim conexion As System.Data.OleDb.OleDbConnection
                Dim DtSet As System.Data.DataSet
                Dim comando As System.Data.OleDb.OleDbDataAdapter
                conexion = New System.Data.OleDb.OleDbConnection("provider=Microsoft.Jet.OLEDB.4.0; Data Source='c:\excel.xls'; Extended Properties=Excel 8.0;")
                comando = New System.Data.OleDb.OleDbDataAdapter("select * from [Hoja1$]", conexion)
                DtSet = New System.Data.DataSet
                comando.Fill(DtSet)
                conexion.Close()
    
            Catch ex As Exception
    
            End Try

    En el ejemplo aqui puesto pilla un excel 2003 de c:\ llamado excel.xsl, si el tuyo es 2007 la cadena de conexion cambia un poco.

    Puedes comprobar que el dataset se llena perfectamente con los datos de la tabla del excel.

    Saludos.


    EDITO: Creo que la cadena de conexion para 2007 es algo así:
     Dim excelConnectionString As String = "Provider=Microsoft.ACE.OLEDB.12.0;Data Source=" + FicheroExcel + ";Extended Properties=""Excel 12.0 Xml;HRD=NO"""
    

    • Editado Jnavero lunes, 4 de febrero de 2013 12:09
    lunes, 4 de febrero de 2013 12:07
  • hola

    veo que quieres hacer uso del schema de ado.net para recuperar los worksheet de excel como si fueran tablas

    Read schema information from Excel worksheets with ADO.NET

    http://social.msdn.microsoft.com/Forums/es/vbes/thread/f73118e2-bac0-4146-b3c2-52c854bd191c

    -----

    algo que no me convernce es que tengas que hacer esto

     CType(oledbConn, OleDbConnection)

    porque haces un CType si se uspone que oledbConn es del tipo al cual estas conviertiendo?

    saludos


    Leandro Tuttini

    Blog
    Buenos Aires
    Argentina

    lunes, 4 de febrero de 2013 13:36
  • Hago el CType porque no se por qué no me lo reconoce si no hago el CType, es algo muy raro...

    AL final lo que he hecho ha sido usar la API de Excel para recoger los nombres de las hojas pero me gustaría saber si hay forma de recorrer celda por celda desde esa API y si hay forma de volcar los datos directamente a un datatable en vez de celda por celda.

    No sé si me explico. Con el método Ado.net puedo hacer un datatable de una hoja y volcarlo todo a la vez sin recorrer las celdas.

    Me gustaría saber si puedo hacer lo mismo pero con la API de Excel.

    Muchas gracias por la ayuda que me habeis prestado los dos!!!

    un saludo!!

    martes, 5 de febrero de 2013 10:33
  • "dankito" escribió:

    > Estoy intentando leer las hojas que contiene un excel, y por más que
    > miro páginas no consigo que me las lea, siempre me muestra como
    > nombre "tables" cuando tendría que tener hoja1 y hoja 2.
    >
    >   Dim table As DataTable = _
    >   CType(oledbConn, OleDbConnection).GetOleDbSchemaTable(OleDbSchemaGuid.Tables, Nothing)

    > AL final lo que he hecho ha sido usar la API de Excel para recoger
    > los nombres de las hojas pero me gustaría saber si hay forma de
    > recorrer celda por celda desde esa API y si hay forma de volcar
    > los datos directamente a un datatable en vez de celda por celda.

    Hola:

    No es necesario utilizar la API de Excel (la biblioteca de objetos de Microsoft Excel), para obtener los nombres de las hojas de cálculo de un libro de Excel, porque con el ISAM de Excel del motor de datos Microsoft Jet o Microsoft ACE lo puedes hacer de una manera muchísimo más eficaz. Eso sí, hay que saber hacerlo bien, tal y como muestro a continuación:

    Imports System.Data.OleDb
    
        Private Function GetTables(fileName As String) As List(Of String)
    
            ' Construimos la cadena de conexión con el libro de Excel especificado
            '
            Dim connString As String = _
                "Provider=Microsoft.Jet.OLEDB.4.0;" & _
                "Extended Properties='Excel 8.0;';" & _
                "Data Source=" & fileName
    
            Try
                ' Establecemos la conexión
                '
                Using cnn As New OleDbConnection(connString)
    
                    ' Hay que abrir explícitamente la conexión.
                    '
                    cnn.Open()
    
                    Using dt As DataTable = cnn.GetSchema("TABLES")
    
                        Dim query As IEnumerable(Of String) = _
                                From row As DataRow In dt.Rows.Cast(Of DataRow)() _
                                Where CStr(row.Item("TABLE_TYPE")).ToUpperInvariant() = "TABLE" _
                                Order By row.Item("TABLE_NAME") _
                                Select CStr(row.Item("TABLE_NAME"))
    
                        Return query.ToList()
    
                    End Using
    
                End Using
    
            Catch
                ' Devuelvo la excepción al llamador.
                Throw
    
            End Try
    
        End Function

    Si por casualidad deseas obtener las hojas de un libro de Excel versión 2007 o superior, utiliza la siguiente cadena de conexión:

            Dim connString As String = _
                "Provider=Microsoft.ACE.OLEDB.12.0;" & _
                "Extended Properties='Excel 12.0 Xml;';" & _
                "Data Source=" & fileName

    Cuando desees obtener el nombre de las hojas de un libro concreto, llamarías a la función de la siguiente manera:

            Try
                ListBox1.DataSource = GetTables("C:\Mis documentos\Libro1.xls")
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try

    En éste caso te aparecerán los nombres en un control ListBox. Te advierto que los nombres de las hojas finalizarán con el carácter $, que es como el ISAM de Excel reconoce los nombres de las hojas de cálculo existentes en un libro de trabajo, y si el nombre de la hoja contiene espacios en blanco, el nombre aparecerá también limitado por comillas simples. Si no deseas que te aparezcan esos caracteres, entonces tendrás que recorres cada elemento de la lista para eliminarlos:

            Try
                Dim hojas As List(Of String) = GetTables("C:\Mis documentos\Libro1.xls")
    
                For Each hoja As String In hojas
    
                    If (hoja.Contains("$"c)) Then
                        hoja = hoja.Replace("$", String.Empty)
                    End If
    
                    If (hoja.Contains("'"c)) Then
                        hoja = hoja.Replace("'", String.Empty)
                    End If
    
                    ListBox1.Items.Add(hoja)
                Next
    
            Catch ex As Exception
                ' Se ha producido un error
                MessageBox.Show(ex.Message)
    
            End Try

    ¡Eso es todo! Adapta el ejemplo a tus necesidades.

    Un saludo


    Enrique Martínez
      [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.



    martes, 5 de febrero de 2013 15:28
    Moderador
  • Muchas gracias por la respuesta voy a probarlo.

    Una pregunta, como puedo leer todos los datos usando la librería de excel igual que se hace con oledb y como puedo recorrerlo uno a uno para ir comparando si teng que subir esa fila a la base de datos o si no me interesa hacerlo?

    Muchas gracias!!

    miércoles, 6 de febrero de 2013 7:45
  • "dankito" preguntó:

    > como puedo leer todos los datos usando la librería de excel
    > igual que se hace con oledb y como puedo recorrerlo uno a
    > uno para ir comparando si teng que subir esa fila a la base
    > de datos o si no me interesa hacerlo?

    Me imagino que referenciando un objeto WorkSheet y posteriormente recorriendo, uno a uno, los objetos Range existentes en la hoja.

    Pero para ello, mejor será que consultes los foros de Excel, y lo que te expliquen allí, intenta adaptarlo a tu aplicación de Visual Basic .NET.

    Desde luego, y siempre y cuando los datos se encuentren debidamente tabulados (en filas y columnas), personalmente no se me va a ocurrir utilizar la biblioteca de Excel para ese trabajo, pudiéndolo hacer de una manera muchísimo más fácil y eficaz, mediante el ISAM de Excel de los motores de datos Microsoft Jet o Microsoft ACE, dependiendo de la versión del libro de Excel que se desee utilizar.

    Por cierto, si la respuesta anterior te ha sido de utilidad, no dudes en marcarla como satisfactoria. ¿De acuerdo?


    Enrique Martínez
      [MS MVP - VB]

    Nota informativa: La información contenida en este mensaje, así como el código fuente incluido en el mismo, se proporciona «COMO ESTÁ», sin garantías de ninguna clase, y no otorga derecho alguno. Usted asume cualquier riesgo al poner en práctica, utilizar o ejecutar lo recomendado o sugerido en el presente mensaje.

    Si esta respuesta le ha resultado útil, recuerde marcarla como satisfactoria.

    Si usas Visual Basic .NET y deseas ser productivo y feliz, activa la instrucción Option Strict.

    miércoles, 6 de febrero de 2013 8:21
    Moderador