jueves, junio 11, 2009

Transferir datos de Excel a Access – segunda nota.

En la nota anterior vimos como transferir datos de Excel a Access manualmente usando los mecanismos nativos de Access.
Otra alternativa es exportar los datos de Excel a Access programáticamente, es decir usando Vba.

Para nuestro ejemplo usaremos nuevamente el archivo de la nota anterior.

En la nota anterior usamos los mecanismos de Access para importar los datos de Excel.
Al realizar la tarea con Vba haremos el camino a la inversa, decir crearemos una conexión a Access desde Excel. Esto lo haremos usando objetos de la ADO library (ADO = ActiveX Data Objects).

Antes de sumergirnos en los vericuetos del código, una observación importante: para poder usar las funciones de ADO en Excel debemos primero crear una referencia con el menú Tools-Reference del editor de Vb



Transferir datos de Excel a Access

Como en el ejemplo anterior, empezamos por crear una base de datos que contiene una tabla a la cual queremos exportar los datos de Excel. Nuestra base de datos (bd1.mdb) contiene la tabla Ventas que por ahora está vacía

Transferir datos de Excel a Access

Sin entrar demasiado en detalles técnicos, podemos describir la tarea de la siguiente manera:

# - creamos una conexión a la base de datos

#- definimos en qué tabla de la base de datos queremos poner los datos

# - definimos un objeto que contenga los datos a transferir (recordset)

# - definimos donde se encuentran los datos a transferir (en nuestro ejemplo el cuaderno tiene dos hojas con datos)

# - transferimos los datos

He agregado la hoja Parámetros en la cual podemos definir donde se encuentra la base de datos, cuál es la tabla a la cual queremos copiar los datos y en qué cuaderno se encuentran. De esta manera, podemos controlar los parámetros del código con facilidad.
Transferir datos de Excel a Access

Como ven he agregado también la línea a partir de la cual hay que transferir los datos de la hoja. En general los datos empiezan en la fila 2 (la 1 está ocupada por los encabezamientos). También podemos elegir de qué hoja pasar los datos, con una lista desplegable en la celda B3.
El código de la macro es el siguiente

Sub ExcelaAccess_ADO()

Dim Conn As ADODB.Connection, RecSet As ADODB.Recordset
Dim fila As Long, primerFila As Integer, ultimaFila As Long, iX As Long
Dim dataSource As String, Tabla As String
Dim wsName As String


'definimos los parametros que seran usados por el codigo

dataSource = Sheets("parametros").[B1]
Tabla = Sheets("parametros").[B2]
wsName = Sheets("parametros").[B3]
primerFila = Sheets("parametros").[B4]


' establecemos la conexion a la base de datos

Set Conn = New ADODB.Connection
Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " & _
dataSource & ";"

' definimos un recordset
Set RecSet = New ADODB.Recordset
RecSet.Open Tabla, Conn, adOpenKeyset, adLockOptimistic, adCmdTable

ultimaFila = WorksheetFunction.CountA(Sheets(wsName).Range("A:A"))

For iX = primerFila To ultimaFila 'mientras que la celda la columna A
'tenga un valor transferimos la fila
With RecSet
.AddNew
.Fields("Factura") = Sheets(wsName).Cells(iX, 1).Value
.Fields("Fecha") = Sheets(wsName).Cells(iX, 2).Value
.Fields("Producto") = Sheets(wsName).Cells(iX, 3).Value
.Fields("Descripcion") = Sheets(wsName).Cells(iX, 4).Value
.Fields("Cantidad") = Sheets(wsName).Cells(iX, 5).Value
.Fields("Precio") = Sheets(wsName).Cells(iX, 6).Value
.Fields("Total") = Sheets(wsName).Cells(iX, 7).Value
.Update
End With
Next iX


RecSet.Close
Set RecSet = Nothing
Conn.Close
Set Conn = Nothing
End Sub



Este código debe ponerse en un módulo común de Vba.

35 comentarios:

  1. Hola Buenas Tardes..Muy bueno tu codigo pero me gustaria saber como esta dispuesto en excel y en access lo que estas transfiriendo porque estoy tratando de ahcer lo mismo y no he podido...

    Agradeceria mucho tu ayuda

    ResponderBorrar
  2. Tal como está explicado en la nota. ¿Qué es lo que no te sale?

    ResponderBorrar
  3. tengo una duda el codigo cuando se exportan los datos a la hora de crear un nuevo registro este lo superpone al anterior o lo crea en el orden que se lleva

    ResponderBorrar
  4. Hola yo estoy tratando de hacer lo mismo, estuve buscando la forma y encontre lo que has publicado, yo estoy trabajando con access, el codigo que pusiste lo puse en un modulo asi como lo indicas, pero al momento de correrlo me muestra el siguiente error:

    Error de compilación
    Sub o función no definida
    Me podrías ayudar por favor

    ResponderBorrar
  5. ¿Has creado la referencia a la ActiveX Data Objects Library cono está indicado al principio de la nota?

    ResponderBorrar
  6. Hola soy Azul.

    Yo estoy buscando la froma de pasar un excel a access y vi lo que has publicado, estoy probando tu codigo, pero tengo unas dudas, lo que pones como sheets es el nombre de la hoja de excel en donde se encuetran los datos a pasar

    ResponderBorrar
  7. Azul,

    si te refieres a Sheets(wsName), la variable wsName contiene el nombre de la hoja con los datos que hemos definido con
    wsName = Sheets("parametros").[B3]

    donde la celda B3 de la hoja "parametros" contiene el nombre de la hoja ("abril" en nuestro ejemplo).

    ResponderBorrar
  8. Buenas tardes,
    Estoy intentando hacer este ejercicio y creo que no me encuentra donde tengo guardad la excel ventas_access_vba el compilador falla con el error de "error en el método sheets" cuando le doy a depurar me marca: dataSource = Sheets("parametros").[B1]

    ResponderBorrar
  9. ¿La hoja "parametros" existe en tu modelo?

    ResponderBorrar
  10. Muchas gracias Jorge, excelente ejemplo, justo lo que estaba buscando.

    Realicé tu ejercicio, y está bien estructurado.

    Para estos ejercicios es importante aclarar a los usuarios que requieren conocimientos basicos de base de datos asi como programación en VBA.

    Fuera de ello, todo esta super bien, muchas gracias por compartirnos tus conocimientos.

    ResponderBorrar
  11. Estimado,
    gracias por el codigo. Sabes, estoy usando Access 2007 y al pasar por el reconocimiento de la base de datos, me arroja un error, el que indica que no reconoce el formato de la base de datos.
    me podrias ayudar?

    agradecido

    ResponderBorrar
  12. Muchas gracias jorge, el ejemplo esta buenisimo.
    tengo una duda. pues estoy ocupando Access 2007 y me arroja un error que no reconoce el formato de la tabla de datos. en el ejemplo es mdb y las que uso son accdb. sabes por donde puedo corregir ese detalle?.
    agradecido

    ResponderBorrar
  13. Releyendo el comentario, reemplazar el código

    Conn.Open "Provider=Microsoft.Jet.OLEDB.4.0;Data Source= " & _
    dataSource & ";"

    por

    Conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " & _
    dataSource & ";"

    ResponderBorrar
  14. Funciono Perfecto.
    muchas gracias

    ResponderBorrar
  15. Buenas noches. Antes que nada me parece excelente tu blog.
    Ahi va mi pregunta, me sale el siguiente error:
    "error 3706: no se encontro el proveedor especificado".
    Los pasos arriba detallados los segui todos, tenes idea que puede estar pasando?
    Gracias.
    Matias

    ResponderBorrar
  16. Matías,
    ¿qué versión de Excel estás usando?
    El proveedor a que se refiere el mensaje es Microsoft.Jet.OLEDB.4.0 (fijate en el comentario del 9/12/2012 también). Parece ser que no tenés alguna de esas versiones.

    ResponderBorrar
  17. Jorge, que buen aporte, con unas adecuaciones a mi proyecto funciona de maravilla.

    Muchas Gracias.
    ATTE. David

    ResponderBorrar
  18. Jorge no me resulta con excel 2010, alguna ayuda

    ResponderBorrar
  19. Tenés que reemplazar la orden

    Provider=Microsoft.Jet.OLEDB.4.0

    con

    Provider=Microsoft.ACE.OLEDB.12.0

    ResponderBorrar
  20. Muy buen informacion pero me sale un error y dice esto "Error de sintaxis en la clausula From

    ResponderBorrar
  21. ERROR EN LA SNTAXIS DE LA CLAUSULA FROM.
    ME MANDA A ESTE RENGLON:
    Set RecSet = New ADODB.Recordset
    RecSet.Open Tabla, Conn, adOpenKeyset, adLockOptimistic, adCmdTable

    ResponderBorrar
  22. ¿Has creado la referencia a la ADO library, como se muestra en la primer parte de la nota? ¿Has modificado los parámetros para que apunten a la hoja y a las celdas adecuadas?

    ResponderBorrar
  23. hola que tal te consulto. como se puede hacer para que me actualize los datos desde access y me elimine los existentes dado que me los va agregando y solo quiero que actualice los mismos.
    Ej. Cliente 1000 compro 2300 el martes a las 9 de la mañana
    a la tarde este cliente 1000 compro 2300 mas,cuando actualizo no me deja dado que la base de acces no se deja poner datos por duplicado

    ResponderBorrar
  24. Disculpas por la demora. No me queda claro lo que querés hacer. En la base de datos hay un registro del cliente 1000 con 2300 en ventas. ¿Ahora hay que actualizarlo a 4600? Si es así, ¿no querías registrar las ventas por fecha/hora? Me parece extraño lo de los duplicados ya que si bien es el mismo cliente los datos son distintos (fecha/hora, contidad, importe).

    ResponderBorrar
  25. Jorge gracias por el código, pero quisiera saber lo siguiente:
    Tengo una tabla con un campo Primary Key, importo el excel a access mediante código VB6 y hasta ahí me funciona muy bien.
    Lo que quiero saber es como hago para importar datos de dos columnas de excel a dos columnas específicas de la misma tabla access sin borrar los registros existentes en las demás columnas de la misma tabla.

    Muchas gracias por tu respuesta
    Atte, Douglas

    ResponderBorrar
  26. Hola Douglas, ¿se trata de corregir registros existentes?

    ResponderBorrar
  27. Jorge gracias por tu pronta respuesta. Esa tabla maneja 2 campos o columnas que mes a mes debo actualizar pues deben contener unos pagos y la fecha de pago, digamos que si podría ser corregis registros existentes porque los campos pago y fechapago los debo modificar mes a mes
    Trabajo con Ado
    Lo he tratado de hacer de la siguiente manera:
    Set Cn = New ADODB.Connection 'Ajusta Cn como conexión ADO con BD
    Set Rs = New ADODB.Recordset 'Ajusta Rs como recordset ADO con BD
    Set ArchivoExcel = New Excel.Application

    Cn.Open "Provider=Microsoft.ACE.OLEDB.12.0;" & "Data Source=" & path + nombrebasedatos + ";"
    Rs.ActiveConnection = Cn
    Rs.CursorLocation = adUseClient
    Rs.LockType = adLockOptimistic
    Rs.Open "Select * From DatosPersonalesCartera"

    For x = 2 To 253
    With Rs
    .Requery
    .AddNew
    !apto = ArchivoExcel.Cells(x, 2) 'este es Primary Key
    !pago = ArchivoExcel.Cells(x, 16) 'estos son lo campos que debo importar a la tabla mes a mes
    !fechapago = ArchivoExcel.Cells(x, 17) 'y están ubicados en la columna 2, 16 y 17 de la tabla

    .Update
    End With

    La verdad es que tengo problemas porque cuando ejecuto la aplicación me sale error en la primary key porque se duplica el índice; y de otro lado no me importa los datos.

    Gracias por tu ayuda.

    ResponderBorrar
  28. Douglas, te sugiero que, si no lo has hecho, pongas tu consulta en alguno de los foros de Access. En estos días, lamentablemente, no dispongo de tiempo libre para ocuparme de consultas específicas.

    ResponderBorrar
  29. buen día:

    Presento un problema en la siguiente sentencia RecSet.Open Tabla, Conn, adOpenKeyset, adLockOptimistic, adCmdTable , el error que muestra es "Argumentos incorrectos, fuera del intervalo permitido o en conflicto con otros

    ResponderBorrar
  30. Tal como dice la información del error, tienes que revisar los argumentos, en particular la variable Tabla.

    ResponderBorrar
  31. Buenas tardes,

    Se para aquí:
    Conn.Open "Provider=Microsoft.ACE.OLEDB.12.0;Data Source= " & _
    dataSource & ";"

    ¿Hay alguna actualizacón posterior?

    ResponderBorrar
  32. Fijate en esta página

    https://www.connectionstrings.com/excel/

    ResponderBorrar
  33. Buenas tardes,

    observo que en ningún momento se establece la ruta del excel que se va a cargar a access, y sin embargo la hoja si.
    en mi caso voy a hacer que VBA abra todos los excel contenidos en una carpeta y repita el proceso para cada uno de ellos, siendo todos iguales, y cargándolos a una tabla de access.

    Mi primera duda es si al cargar un archivo tras otro no estará pisando las líneas de la tabla del access cargadas con el excel anterior.

    La segunda duda es cómo establezco en que carpeta debe buscar el excel para ya encargarme yo de que busque todos los archivos de esa carpeta.

    Un saludo
    Muchas gracias previamente.

    ResponderBorrar

Nota: sólo los miembros de este blog pueden publicar comentarios.