De un DGV a una MDB

Debido a la insistencia de algunos lectores de este blog, me complace retomar un antiguo ejemplo donde rellenamos un DGV con los datos de una hoja XLS y posteriormente creamos una BD con la tabla correspondiente y en formato MDB. Por lo tanto seguro que con las nuevas herramientas podremos realizar tareas similares con mucho menos código, por eso matizo que se trata de un ejemplo reanimado de 2005 al 2010 J

Las versiones tanto de la XLS como la MDB corresponden al 97-2003. Para poder ejecutar este ejemplo necesitas crear un nuevo proyecto ‘Winforms’ en VB y simplemente copiar y pegar el código en el ‘form1’.

Tenéis que tener en cuenta para que funcione necesitas guardar tu hoja en la carpeta del proyecto ‘Bin/Debug’ (o reléase) según estés compilando y con el nombre ‘Libro1.xls’.

No dudéis en contactar conmigo para aclarar cualquier duda, además si necesitas el proyecto el completo estaré encantado de facilitártelo (Lo tengo para Visual Studio 2010).

Espero vuestras valoraciones.
Happy reentrada!
Pep Lluis,

' --------------------------------------------------------------------------------------------
' * AVISO IMPORTANTE * Este programa es propiedad (c)2010 Pep Lluis Bano.
' * AVISO IMPORTANTE * Se autoriza su uso, solo con fines formativos.
' 
' EL USO DE ESTA APLICACION IMPLICA LA ACEPTACION DE LAS CONDICIONES DE USO QUE SE APLICAN
' AL PROGRAMARIO "Open Source", ESTE PROGRAMA SE PROPORCIONA "COMO ESTA", NO OBLIGANDO AL 
' AUTOR A CONTRAER COMPROMISO ALGUNO PARA CON QUIENES LO UTILICEN, ASI COMO DECLINANDO 
' CUALQUIER REPONSABILIDAD DIRECTA O INDIRECTA, CONTRAIDA POR LOS MISMOS EN SU UTILIZACION 
' FUERA DE LOS PROPOSITOS PARA EL QUE FUE ESCRITO Y DISEÑADO.
'
' CUALQUIER MODIFICACIÓN Y DISTRIBUCION DEL MISMO DEBERA CONTENER Y CITAR SU FUENTE Y ORIGEN.
'
' ASI MISMO EL AUTOR AGRADECERA CUALQUIER COMENTARIO o CORRECCION QUE LOS LECTORES CONSIDEREN
' CONTRIBUYENDO ESTOS ULTIMOS A MEJORAR LA APLICACION CON FINES FORMATIVOS.
' CONSIDEREN ENVIAR SUS COMENTARIOS ulizando la opcion [Contact]
' --------------------------------------------------------------------------------------------

Imports
 ADOX
Imports System.Data.OleDb
Imports System.Text.RegularExpressions

Public Class Form1
    'Definir conexion,adaptador y Dataset
    Private MiXlsConexion As OleDbConnection
    Private MiXlsAdaptador As OleDbDataAdapter
    Private MiXlsDataSet As New DataSet()
    Private MiXlsDGV As New DataGridView

    Private MiMdbConexion As New OleDbConnection
    Private MiMdbAdaptador As New OleDbDataAdapter
    Private MiMdbDataSet As New DataSet()

    Private Mienlazador As New BindingSource
    Private MiMdbDGV As New DataGridView

    Private Sub Form1_FormClosing(ByVal sender As ObjectByVal e As System.Windows.Forms.FormClosingEventArgsHandles Me.FormClosing
        MiMdbConexion.Close()
    End Sub

    Private Sub Form1_Load() Handles MyBase.Load
        Dim MiXlsEtiqueta As New Label
        MiXlsEtiqueta.Text = "Contenido de la Hoja Excel"
        MiXlsEtiqueta.TextAlign = ContentAlignment.MiddleCenter
        MiXlsEtiqueta.BorderStyle = BorderStyle.Fixed3D
        MiXlsEtiqueta.BackColor = Color.Green
        MiXlsEtiqueta.ForeColor = Color.White
        MiXlsEtiqueta.Dock = DockStyle.Top

        Dim MiXlsDGBPanel As New Panel
        MiXlsDGBPanel.AutoSize = True
        MiXlsDGV.Dock = DockStyle.Top
        MiXlsDGBPanel.Controls.AddRange(New Control() {MiXlsDGV, MiXlsEtiqueta})


        Dim MiMdbEtiqueta As New Label
        MiMdbEtiqueta.Text = "Contenido de la BD resultante"
        MiMdbEtiqueta.TextAlign = ContentAlignment.MiddleCenter
        MiMdbEtiqueta.BorderStyle = BorderStyle.Fixed3D
        MiMdbEtiqueta.BackColor = Color.Maroon
        MiMdbEtiqueta.ForeColor = Color.White
        MiMdbEtiqueta.Dock = DockStyle.Top

        Dim MiMdbDGBPanel As New Panel
        MiMdbDGBPanel.AutoSize = True
        MiMdbDGV.Dock = DockStyle.Top
        MiMdbDGBPanel.Controls.AddRange(New Control() {MiMdbDGV, MiMdbEtiqueta})

        Dim BotonDeActualizar As New Button
        BotonDeActualizar.Dock = DockStyle.Bottom
        BotonDeActualizar.Text = "Generar Archivo MDB"

        Me.AutoSize = True
        Me.Text = "De XLS a MDB"
        MiXlsDGBPanel.Dock = DockStyle.Top
        MiMdbDGBPanel.Dock = DockStyle.Top
        Me.Controls.AddRange(New Control() {MiMdbDGBPanel, MiXlsDGBPanel, BotonDeActualizar})
        AddHandler BotonDeActualizar.Click, AddressOf GenerarMdb

        LeerXls()
    End Sub

    Private Sub LeerXls()
        'Abrir y llenar el DGV con la hoja de excel
        MiXlsConexion = New OleDbConnection _
        ("Provider=Microsoft.Jet.OLEDB.4.0;" + _
         "Extended Properties = 'Excel 8.0';" + _
         "Data Source=|DataDirectory|\libro1.xls;")
        MiXlsAdaptador = New OleDbDataAdapter("SELECT * FROM [Hoja1$]", MiXlsConexion)
        MiXlsConexion.Open()
        MiXlsAdaptador.Fill(MiXlsDataSet)
        MiXlsDGV.DataSource = MiXlsDataSet.Tables(0)
    End Sub

    Private Sub GenerarMdb()
        'Eliminar la BD1 si existe
        If My.Computer.FileSystem.FileExists("Bd1.mdb"Then
            My.Computer.FileSystem.DeleteFile("Bd1.mdb")
        End If
        '
        Dim Nombrede_MiBd = "Bd1.mdb"
        Dim NombreDe_MiTabla = "Detalles"
        ' Para crear una nueva BD de Access, me viene a la
        ' memoria la funcion Catalog del ADOX.DLL
        Dim Catalogo As New ADOX.Catalog()
        Catalogo.Create("Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Nombrede_MiBd)
        '
        ' Una vez creado el nuevo catalogo añadiremos 
        ' la tabla utilizando el suministrador OLEDB
        MiXlsConexion = New OleDb.OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source =" & Nombrede_MiBd)
        '
        ' Obtenendremos el esquema de la nueva BD
        MiXlsConexion.Open()
        Dim MiEsquema As DataTable = MiXlsConexion.GetOleDbSchemaTable(OleDb.OleDbSchemaGuid.Tables, _
                New Object() {NothingNothing, NombreDe_MiTabla, "Detalles"})
        '
        ' El ultimo paso sera crear la estructura en funcion a las columnas de la hoja
        Dim Campos As String = "Create Table [" + NombreDe_MiTabla + "] ("
        For Each col As DataGridViewTextBoxColumn In MiXlsDGV.Columns
            If Campos.EndsWith(")"Or Campos.EndsWith("Key"Then Campos += ", "
            Campos += "[" + Regex.Replace(col.DataPropertyName, " ""_") + "] Text(50)"
        Next
        Campos += ")"
        Dim MiMandato As New OleDbCommand(Campos, MiXlsConexion)
        MiMandato.ExecuteNonQuery()
        MiXlsConexion.Close()
        '
        ' Añadir todos las filas como registros a la BD
        MiMdbConexion = New OleDb.OleDbConnection("PROVIDER=Microsoft.Jet.OLEDB.4.0;Data Source =" & Nombrede_MiBd)
        MiMdbAdaptador = New OleDbDataAdapter("SELECT * FROM Detalles", MiMdbConexion)
        Dim commandbuilder As New OleDb.OleDbCommandBuilder(Me.MiMdbAdaptador)
        MiMdbConexion.Open()
        MiMdbAdaptador.Fill(MiMdbDataSet)

        Dim Registro As DataRow
        For Each row As DataGridViewRow In MiXlsDGV.Rows
            If row.Index < MiXlsDGV.RowCount - 1 Then
                Registro = MiMdbDataSet.Tables(0).NewRow
                For Each col As DataGridViewColumn In MiXlsDGV.Columns
                    'Añadir una entrada por celda
                    Registro(col.Index) = row.Cells(col.Index).Value
                Next
                'Añadir una linea por fila
                MiMdbDataSet.Tables(0).Rows.Add(Registro)
            End If
        Next
        MiMdbAdaptador.Update(MiMdbDataSet)
        MiMdbDGV.DataSource = MiMdbDataSet.Tables(0)
        MiMdbConexion.Close()
    End Sub
End Class

El proveedor ‘Microsoft.Jet.OLEDB.4.0’ no está registrado en el equipo local

Sorprendentemente continúan llegando inquietudes preguntando cómo se abre una BD de Access en las nuevas versiones de VB.  Algunos asiduos a este formato han sufrido el desconcertante mensaje… no está en el equipo local? Cuando la realidad es que no esta implementado!

Para dar una buena explicación, recibimos este mensaje cuando utilizamos ‘OLEDB’ en un sistema X64 y ese es el detalle. No existe una implementación de ‘OLEDB’ para 64 bits.

La única solución es desarrollar en 32Bits, aunque esto ultimo NO signifique que tengamos que reinstalar el sistema operativo… tan solo nesitaremos seleccionar ‘X86’ como ‘CPU de destino’ en las ‘Opciones de Compilación Avanzadas’ de la pestaña ‘Compilar’ en las propiedades de ‘My Project’

Espero que esto os ahorre alguna que otra hora de busqueda.
Pep Lluis,

Error de sintaxis en la instrucción INSERT INTO.

Este es uno de los textos de error que mas amenudo se enfrenta a los que intentan actualizar la informacion enlazada de un DGV’s y una MDB.

Aunque en muchos otros foros/post se advierte de debemos utilizar nombres de campo que no esten reservados, caemos y volvemos a caer en el error de usar nombres con caracteres no admitidos. Un simple espacio al nombrar el campo provocara una excepcion tanto en la operación de ‘INSERT’ Como ‘UPDATE’. Suerte que a grandes males… grandes remedios J

Ejemplo :   el Nombre ‘Columna A’ generara una excepcion
Sin embargo  el nombre ‘Columna_A’ no genera ninguna excepcion… asi de simple.

Os recuerdo el enlace con la lista de palabras reservadas que no pueden utilizarse para nombrar los campos de una MDB que posteriormente utilizaremos enlazada con un DataGridView y un ‘OleDb.OleDbCommandBuilder(MiMdbAdaptador)’

http://support.microsoft.com/kb/248738

En caso contrario las únicas opciones disponibles para continuar utilizando dichos nombres, será construir el’INSERT’… ‘UPDATE’ commands de forma manual o utilizar la opción de ‘Origen de Datos’ generado por Visual Studio.

Saludos,
Pep Lluis,

De XLS a MDB

Desde la aparición de VB.NET y a pesar de las grandes prestaciones SQL Express frente al extinto MSDE, una de las inquietudes que en más ocasiones he visto solicitadas por los desarrolladores, ha sido la portabilidad y la manejabilidad de formatos MDB, XLS, TXT, como moneda de cambio entre aplicaciones, a pesar de todo, supongo que continuamos dependiendo de los antiguos compañeros de viaje.

Son muchas las ocasiones en que se pregunta cómo convertir el contenido de un ‘DataGridBView’ a una Base de datos Access o transportar el contenido de una tabla a un Excel. Creo que este ejercicio puede ser útil como punto de entradilla a ese tipo de aplicaciones “Atípicas” J.  Así que finalmente me he decidido por investigar un poquito para poder llegar a ciertas conclusiones y limitaciones del trabajo con MDB’s usando VB 9. Aquí os dejo una muestra de los resultados, ya sabéis que no es habitual en mí, pero no he tenido tiempo de comentar el código y ponerlo bonito, a pesar de ello a todos los que tengáis un especial interés, os animo a contactar, para poder enviaros el proyecto de pruebas.

Veamos entonces como procesar una hoja de cálculo de Excel para crear un nuevo catalogo en una BD, diseñando la tabla a partir de las columnas del ‘DGV’ y rellenándola con el contenido de celdas.

Evidentemente el punto de partida será esta bonita hoja:

Un Simple XLS

 el segundo paso … Nuestro POgrama pa leer lescel!

    Private Sub LeerXls()
        ‘Abrir y llenar el DGV con la hoja de excel
        MiXlsConexion = New OleDbConnection _
        (“Provider=Microsoft.Jet.OLEDB.4.0;” + _
         “Extended Properties = ‘Excel 8.0’;” + _
         “Data Source=|DataDirectory|\libro1.xls;”)
        MiXlsAdaptador = New OleDbDataAdapter(“SELECT * FROM [Hoja1$]”, MiXlsConexion)
        MiXlsConexion.Open()
        MiXlsAdaptador.Fill(MiXlsDataSet)
        MiXlsDGV.DataSource = MiXlsDataSet.Tables(0)
    End Sub

Nuestra Aplicacion

Al pulsar sobre “Generar Archivo” obtendremos …



‘ crear estructura de la tabla en funcion a columnas de la hoja
Dim Campos As String = “Create Table [“ + NombreDe_MiTabla + “] (“
For Each col As DataGridViewTextBoxColumn In MiXlsDGV.Columns
     If Campos.EndsWith(“)”) Then Campos += “, “
     Campos += “[“ + Regex.Replace(col.DataPropertyName, ” “, “_”) + “] Text(50)”
Next
Campos += “)”
Dim MiMandato As New OleDbCommand(Campos, MiMDBConexion)
MiMandato.ExecuteNonQuery()




Dim Registro As DataRow
‘Añadir las filas del DGV a la tabla del DataSet
For Each row As DataGridViewRow In MiXlsDGV.Rows
    If row.Index < MiXlsDGV.RowCount – 1 Then
        Registro = MiMdbDataSet.Tables(0).NewRow
        For Each col As DataGridViewColumn In MiXlsDGV.Columns
            ‘Añadir una entrada por celda
             Registro(col.Index) = row.Cells(col.Index).Value
        Next
        ‘Añadir una linea por fila
        MiMdbDataSet.Tables(0).Rows.Add(Registro)
    End If
Next
MiMdbAdaptador.Update(MiMdbDataSet)

 

Hecho!

Sin trampa ni carton, en la carpeta de la aplicacion veremos aparecer un misterisoso Bd1.Mdb

La Prueba

Los Mas desconfiados podeis hacer clic … e volila!

El Resultado

Saludos,
Pep Lluis,