el Guille, la web del Visual Basic y más... Bases de Datos usando DAO ========================= Actualizado el 29-Sep-2001 Para ver los temas relacionados con ADO (ActiveX Data Objects) Contenido: Copiar la estructura de una tabla con Access Ordenes SQL para cambiar los datos de una tabla. Caracteres no "standards" en los nombres de los campos Procesar una consulta SQL (Execute) Procesar una consulta SQL creando un Recordset Evitar el error al asignar un Null Comprobar si un registro se está editando Asignar a un Recordset los registros deseados Compactar una base de datos, usando código VB (27/Feb) Crear una base de datos, usando código VB (18/Abr) Como crear un Formulario de Datos con un Grupo de Registros Subyacente (18/Abr) Cambiar los caracteres extraños por ? (para usar en las consultas a bases de datos con LIKE) (20/Abr) Procesar el resultado de una consulta con varias tablas para evitar registros duplicados (13/Jul) Programación sobre la seguridad de Access (31/Ago) Un método rápido para efectuar búsquedas (8/Sep) Enumerar las tablas de una base de datos (17/Sep) Capturar errores de ODBC (9/Abr/98) Acceso a bases de datos SQL Server... Cargar Imágenes de una base de datos sin usar el DataControl Acceder a bases de Access 2000 (usando el datacontrol de ADO) (31/Ago/99) Acceder a bases de datos usando ADO (sin el data control) (31/Ago/99) Acceder a bases de datos de Access 2000 con el VB5 (05/Oct/99) Un consejo si instalas VB6 SP4 para acceder a bases de datos de Access 2000 (10/Nov/00) Manipular imágenes usando ADO (con datacontrol) (11/Jul/2001) Acceder a una base de datos ADO con contraseña (05/Sep/2001) 1.- Copiar la estructura de una tabla con Access Para copiar/duplicar la estructura de una tabla en una base de datos Access, sigue estos pasos: Carga la base de datos en Access Selecciona la tabla a copiar En el menú de Edición, selecciona Copiar En el menú de Edición, selecciona Pegar Escribe el nuevo nombre de la tabla Selecciona "Estructura solamente" Ya está la tabla "duplicada" en la misma base de datos, por si haces cambios de los que después te arrepientas. Si la intención es copiarla en otra base de datos, antes de seguir con el paso 4, cargar o crear la nueva base de datos y ya está. En el paso 6 puedes seleccionar "Estructura y Datos" si quieres copiar también los datos. 2.- Ordenes SQL para cambiar los datos de una tabla. UPDATE tabla SET nombre_campo = 'nuevo_valor' WHERE opciones_a_tener_en_cuenta Ejemplo: Actualizar la tabla Clientes poniendo el campo Agente a LIBRE si la fecha de ÚltimaVisita es anterior al 1 de Enero de 1996 (este es un caso sobre una base de datos que uso en mi trabajo, pero como ejemplo puede valer): UPDATE Clientes SET Agente = 'LIBRE' WHERE [ÚltimaVisita] < DateValue('01/01/96') Normalmente el campo de fechas será según tengáis configurado el sistema. 3.- Caracteres no "standard" en los nombres de los campos Si al crear las tablas de la base de datos usas caracteres acentuados, eñes, espacios, etc. Cuando hagas una consulta o lo uses en un Recordset, etc, ponlos entre corchetes, fijates en cómo se usa ÚltimaVisita en el ejemplo anterior. 4.- Procesar una consulta SQL (Execute) Para ejecutar una orden SQL en una base de datos, usar la orden Execute en la variable de una base de datos (Database) 'SQLTmp= orden SQL 'Db será una base de datos: 'Dim Db As Database 'Variable para las Bases de Datos 'Set Db = OpenDatabase("Nombre_Base_Datos") On Error Resume Next Db.Execute SQLTmp, dbFailOnError If Err Then MsgBox "Se ha producido un error al ejecutar la orden:" & vbCrLf & SQLTmp End If 5.- Procesar una consulta SQL creando un Recordset Se creará un Recordset con el resultado de una consulta SQL realizada a uan base de datos, posteriormente se procesarán los datos que ha producido dicha consulta. Por ejemplo si tenemos una base de datos con nuestra colección discográfica, podríamos hacer una consulta con todos los CD's de Phil Collins Suponiendo que el formato de los discos (CD, LP, etc.) es Formato y el Nombre del Autor está en Cantante, la orden a ejecutar sería: SQLTmp = "SELECT * FROM mis_discos WHERE Formato Like '*CD*' AND Cantante Like '*Phil Collins*'" Por supuesto se puede usar = en lugar de Like, si estamos seguros de que no necesitamos los comodines, ya que la consulta es "bastante" más rápida. Es decir quedaría así: SQLTmp = "SELECT * FROM mis_discos WHERE Formato = 'CD' AND Cantante = 'Phil Collins'" 'Ejecutar orden SQL con los datos solicitados 'Db será una base de datos: 'Dim Db As Database 'Variable para las Bases de Datos 'Set Db = OpenDatabase("Nombre_Base_Datos") Dim SQLTmp As String Dim MySnap As Recordset SQLTmp = "select * from " & Nombre_Tabla & " " & " order by " & Clasificar Set MySnap = Db.OpenRecordset(SQLTmp, dbOpenSnapshot) Err = 0 MySnap.MoveFirst If Err Then Err = 0 'no hay datos, avisar MsgBox "No hay datos que coincidan con la búsqueda especificada," & vbCrLf & "(o no está bien realizada)", 64, "Listados" Exit Sub End If 'Añadir el resultado a un List List1.Clear MySnap.MoveFirst Do Until MySnap.EOF 'Procesar los datos... ' List1.AddItem MySnap("Cantante") & " " & MySnap("[Canción]") '...y demás datos MySnap.MoveNext Loop MySnap.Close 6.- Evitar el error al asignar un campo Null de una base de datos. Además de evitar el error, es más rápido que usar If...Then... para comprobar si el campo es nulo o está vacío. Para cadenas: Cadena = "" & rs!Campo Para números: Numero = 0 & rs!Campo 7.- Comprobar si un registro se está editando. Esto puede ser útil si el programa tiene que acceder a una base de datos en red o bien si accedes en el mismo equipo a una base de datos. Lo que hay que hacer es usar EditMode y comprobar si se está editando. Veamos un ejemplo: With Data1.Recordset 'Escribe el código para buscar el registro a editar, etc. '... Do While .EditMode = dbEditInProgress DoEvents Loop 'Cuando llegue aquí, es que ya está libre... .Edit '...hacer los cambios al registro... .Update End With Los valores que devuelve EditMode, pueden ser: dbEditNone Si no se está editando. dbEditInProgress Se está editando actualmente. dbEditAdd Se ha añadido un registro con AddNew y el registro actual todavía está en el buffer. 8.- Seleccionar los registros que queremos en un Recordset Para asignar a un Data (Recordset) los datos que quieras de una tabla, usa la propiedad Recordsource. Data1.RecordSource = "SELECT * FROM Tabla WHERE (condiciones de selección) ORDER BY campo, [campo2]" Data1.Refresh El Refresh que no se te olvide, si no quieres que produzca error. Condiciones de selección, serán las comparaciones (consulta) que quieres incluir para la selección. Por ejemplo, si quieres incluir todos los clientes de Málaga que tengan coche, clasificados por la población: Data1.RecordSource = "SELECT * FROM Clientes WHERE Provincia = 'Málaga' AND Coche = 'Si' ORDER BY [Población]" Fijate que Población está entre corchetes, esto es necesario, porque la ó (o acentuada) es un caracter "extraño" y se debe poner entre corchetes para que el Jet lo entienda. Lo mismo hay que hacer si el nombre del campo incluye espacios. Otra cosa a tener en cuenta es que si usas =, el contenido del campo "debe coincidir exactamente", si en Provincia tienes algo como: Málaga (Andalucía), no lo "encontrará". Para que lo incluya también, cambia el signo igual por LIKE: Data1.RecordSource = "SELECT * FROM Clientes WHERE Provincia LIKE '*Málaga*' AND Coche = 'Si' ORDER BY [Población]" Más cosas, en la parte ORDER BY, se pueden incluir más de un campo, separados por comas. El asterisco (*) que hay después de SELECT, es para que incluya todos los campos de la tabla. Si sólo quieres incluir algunos campos, especificalos en lugar del asterisco y separalos con comas: Data1.RecordSource = "SELECT Nombre,Apellidos, [Población], Provincia, Coche FROM Clientes WHERE Provincia LIKE 'Málaga' AND Coche = 'Si' ORDER BY [Población]" 9.- Compactar una base de datos, usando código VB (27/Feb) Este es el código que uso para compactar las bases de datos. Cosa que suelo hacer bastante a menudo, sobre todo en las que uso en la empresa, que cambian a diario. Por aquello de la seguridad, mantengo dos copias: la anterior y la última. Más vale prevenir. Nunca se sabe cuando se cortará la luz o se quedará colgado el equipo... así que, me curo en salud. 'Cerrar la base (esto sólo si la tienes abierta...) Db.Close 'Liberar memoria y "desligarla" Set Db = Nothing ' 'Tomar el nombre sin la extensión sTmp = "" i = InStr(NombreBase, ".") If i Then p = i - 1 Else p = Len(NombreBase) End If sTmp = Left$(NombreBase, p) 'Buscar \, para tomar el directorio (path) For i = p To 1 Step -1 If Mid$(NombreBase, i, 1) = "\" Then sTmp = Left$(NombreBase, i) Exit For End If Next If Right$(sTmp, 1) <> "\" Then sTmp = sTmp & "\" End If 'Todo este proceso es para estar seguro de que se quede una copia 'en caso de que falle la compactación... dBaseTmp = sTmp & "~dBase2.mdb" If Len(Dir$(dBaseTmp)) Then Kill dBaseTmp If Len(Dir$(sTmp & "~dBase1.mdb")) Then Kill sTmp & "~dBase1.mdb" 'Esta es la madre del cordero, se pueden usar otras "versiones", es cuestión de adecuarte. CompactDatabase NombreBase, dBaseTmp, dbLangSpanish, dbVersion20 'Guardar una copia de como estaba antes Name NombreBase As sTmp & "~dBase1.mdb" 'Esta es la base ya compactada, así que asignar el nombre Name dBaseTmp As NombreBase 'Borrar los ficheros LDB If Len(Dir$(sTmp & "*.ldb")) Then Kill sTmp & "*.ldb" 10.- Crear una base de datos, usando código VB (18/Abr) Aprovechando que he puesto la colaboración de Harvey Triana en esta página, pues te voy a poner cómo crear una base desde dentro del propio Visual Basic. Te recomiendo que veas el Proyecto Paso a Paso, en el que puedes tener el código completo y otras cosillas que aquí no se van a explicar. Este es el listado del procedimiento que se encargará de crear la base de datos. Por supuesto, deberás cambiar los nombres de los campos y tipos de datos a tu conveniencia, pero de esta forma, tienes algo por dónde empezar. Private Sub CrearBase(sBase As String) 'Crear la base de datos indicada ' Dim Db As Database Dim Fd As Field Dim Tb As New TableDef 'Definir una Tabla Dim Idx As New Index 'Para crear un índice Dim i As Integer 'Crear base de datos, idioma español y para la versión 2.0 del Jet de Access '================================================================================ 'Si vas a adaptar este programa para VB3, usa dbVersion11 en lugar de dbVersion20 '================================================================================ Set Db = CreateDatabase(sBase, dbLangSpanish, dbVersion20) ' 'La constante dbVersion20 no aparece en la ayuda, en su lugar lo hace la dbVersion25 'pero ésa no está creada!!! ' 'Primero la tabla de las tareas Set Tb = Db.CreateTableDef("Tareas") 'Vamos a crear cada uno de los campos Set Fd = Tb.CreateField("ID", dbLong) 'Ahora vamos a asignar las propiedades de contador, etc. Fd.Attributes = dbAutoIncrField Or dbUpdatableField Or dbFixedField Tb.Fields.Append Fd 'El resto de los campos Set Fd = Tb.CreateField("Fecha", dbDate) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Asunto", dbText, 255) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Descripcion", dbMemo) Tb.Fields.Append Fd Set Fd = Tb.CreateField("FechaInicio", dbDate) Tb.Fields.Append Fd Set Fd = Tb.CreateField("FechaTermino", dbDate) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Terminada", dbInteger) Tb.Fields.Append Fd 'Creamos un índice con el ID Idx.Name = "PrimaryKey" Idx.Unique = True Idx.Primary = True Idx.Fields = "ID" Tb.Indexes.Append Idx 'Añadimos la tabla a la base Db.TableDefs.Append Tb ' 'Creamos la otra tabla: Anotaciones Set Tb = Db.CreateTableDef("Anotaciones") 'El campo ID, es el contador, etc. Set Fd = Tb.CreateField("ID", dbLong) Fd.Attributes = dbAutoIncrField Or dbUpdatableField Or dbFixedField Tb.Fields.Append Fd 'El resto de los campos Set Fd = Tb.CreateField("Fecha", dbDate) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Tema", dbText, 50) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Asunto", dbText, 255) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Medio", dbText, 255) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Localizacion", dbText, 255) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Descripcion", dbMemo) Tb.Fields.Append Fd Set Fd = Tb.CreateField("Detalle", dbLongBinary) Tb.Fields.Append Fd 'Creamos un índice con el ID Set Idx = Nothing 'Quitar la referencia anterior Idx.Name = "PrimaryKey" Idx.Unique = True Idx.Primary = True Idx.Fields = "ID" Tb.Indexes.Append Idx 'Añadimos la segunda tabla a la base Db.TableDefs.Append Tb 'Cerramos la base Db.Close MsgBox "Nueva base de datos " & sBase & " creada.", vbInformation End Sub 15.- Un método rápido para efectuar una búsqueda (8/Sep) En este ejemplo, uso un recordset para hacer la búsqueda, el único requisito es que tenga un campo llamado ID, que será el que se devuelva con el dato encontrado. La rutina acepta búsquedas hacia delante y hacia atrás, para buscar hacia atrás la variable buscAtras será True. Se supone que además tienes una variable (Db) con la base de datos que estás usando. Aquí tienes el código... Private Function BuscarEnBase(Optional ByVal sBusqueda As String = "") As Long 'Devuelve el número de ID ( 5/Jul/97) Dim sSQL As String Dim lID As Long On Local Error Resume Next If Len(sBusqueda) Then sSQL = "SELECT * FROM " & sTabla & " WHERE " & sBusqueda Set RsBuscar = Db.OpenRecordset(sSQL, dbOpenSnapshot) If Not RsBuscar.EOF Then 'Primera búsqueda If buscAtras Then RsBuscar.MoveLast End If lID = CLng(RsBuscar("ID")) Else lID = 0& End If Else If buscAtras Then RsBuscar.MovePrevious Else RsBuscar.MoveNext End If lID = CLng(RsBuscar("ID")) End If If (lID = 0&) Or (Err <> 0) Then lID = 0& 'para que al seguir buscando se empiece por el primero If buscAtras Then RsBuscar.MoveLast RsBuscar.MoveNext Else RsBuscar.MoveFirst RsBuscar.MovePrevious End If End If Err = 0 BuscarEnBase = lID End Function Esto es un ejemplo de cómo se llamaría a esta función, usando el diálogo de buscar y reemplazar: iFFAtras = True If gsBuscar(sBuscar, cFFAc_Buscar + cFFAc_Atras, "Buscar datos") > cFFAc_IDLE Then sBuscar = Trim$(sBuscar) If Len(sBuscar) Then buscAtras = iFFAtras 'buscCompleta = iFFCompleta YaEstoyAqui = True LblStatus(1) = "Buscando " & sBuscar & "..." DoEvents 'Usar una rutina del tipo consulta (SQL) qID = BuscarEnBase(Text1(ControlActual).DataField & " LIKE '" & sBuscar & "*'") If qID Then Data1.Recordset.FindFirst "ID = " & CStr(qID) If Data1.Recordset.NoMatch Then qID = 0& End If End If If qID = 0& Then Beep MsgBox "No se ha hallado el dato buscado en el campo: " _ & Text1(ControlActual).DataField, vbOK + vbInformation, "Buscar" 16.- Enumerar las tablas de una base de datos (17/Sep) Aquí te muestro como saber las tablas que existen en una base de datos. De esta forma puedes buscar si la que necesitas está en la base especificada o bien puedes usarla para abrir "cualquier" tabla de una BD. Las rutinas sirven igual para VB3 (ejemplo aparte) y VB4 o superior. Para probar esta rutina, en un form, añade un ListBox (List1) y un botón que al pulsarlo llame a EnumerarTablas, deberás cambiar la localización de la base de datos por la que sea en tu equipo... 'Ejemplo para VB4 o superior Private Sub EnumerarTablas() Dim Db As Database Dim Td As TableDef List1.Clear Set Db = OpenDatabase("D:\VB\Biblio.MDB") For Each Td In Db.TableDefs 'Sólo las tablas con atributo igual a CERO, 'son tablas normales If Td.Attributes = 0 Then List1.AddItem Td.Name End If Next Db.Close Set Db = Nothing End Sub 'Para VB3: (en VB4 también se puede usar de esta forma) Private Sub EnumerarTablas() Dim INListTabl As Snapshot Dim Db As Database List1.Clear Set Db = OpenDatabase("D:\VB\Biblio.MDB") Set INListTabl = Db.ListTables() INListTabl.MoveFirst Do Until INListTabl.EOF If INListTabl("Attributes") = 0 Then List1.AddItem INListTabl("Name") End If Loop Db.Close Set Db = Nothing End Sub Si lo que quieres es sólo comprobar si existe, en lugar de añadirla a un list, haces una comparación: If Td.Name = miTabla Then ExisteTabla = True End If 17.- Un consejo si instalas VB6 SP4 para acceder a bases de datos de Access 2000 (10/Nov/00) Si has leido el artículo sobre el acceso a bases de datos de Access 2000 usando el DAO Datacontrol (Acceder a bases de datos de Access 2000 con el VB5), verías que había un comentario sobre que no se puede usar ese control para acceder al nuevo formato de las bases de datos de Access 2000... Eso es cierto para el VB5 y para el VB6 pre-SP4, ya que el DAO Datacontrol que se incluye con la nueva "revisión" del VB6 SI reconoce dicho formato, además de que carga de forma automática la Microsoft DAO 3.6 Object Library, sin la cual no se puede acceder a las bases del Access 2000. Pero puedes llevarte una sorpresa si, (a pesar de indicar en las referencias que se use el nuevo motor de bases de datos 3.6), el VB te avisa de que no hay datos que mostrar... Esto es cierto si lo que estás probando es un proyecto que ya tuvieras hecho anteriormente, ya que con los nuevos proyectos no hay problemas... la razón es que, (si miras con un editor de textos el contenido de un formulario de VB), lo que se asigna a la propiedad Connect, para un control existente, es diferente del que se asigna para uno nuevo... con lo cual, si quieres que tus proyectos pre-SP4 funcionen sin problemas y sin tener que quitar el control existente y añadirlo de nuevo, (que sería la forma lógica de hacerlo), simplemente tendrás que cambiar la asignación que se le hace a dicha propiedad: Nuevo: (vb6, SP4) ------ Begin VB.Data Data1 Caption = "Data1" Connect = "Access 2000;" Antiguo: (vb6 SP3... o anterior) -------- Begin VB.Data Data1 Caption = "Data1" Connect = "Access" Es decir, cambia el "Access" por "Access 2000;" Espero que este "truquillo" te alivie algún que otro quebradero de cabeza... Nos vemos Guillermo Acceder a una base de datos ADO con contraseña (05/Sep/2001) Para abrir una base de datos ADO con contraseña, podemos hacerlo al crear la conexión. He probado varias de las formas que se indican en la ayuda, pero la única que me ha funcionado es la que aquí te muestro... así que, si a ti te funciona de otra forma, pues... eso, que uses la que mejor te parezca... je, je. Este código es para bases de datos del tipo Access 97, en caso de que quieras usar una de Access 2000, hay que cambiar el provider por: Provider=Microsoft.Jet.OLEDB.4.0; Set Cnn = New ADODB.Connection Cnn.Open "Provider=Microsoft.Jet.OLEDB.3.51; " & _ "Data Source=" & sBase & ";" & _ "Jet OLEDB:Database Password=laclave" En este ejemplo, asumimos que tenemos una variable llamada Cnn del tipo ADODB.Connection y otra, (sBase), del tipo String, a la que se ha asignado el nombre de la base de datos a la que queremos acceder. ADO ALGUNAS COSAS ================= el Guille, la web del Visual Basic y más... Bases de datos ADO (ActiveX Data Objects) Actualizado el 25-Oct-2001 Sigue este link para ver cómo hacer las cosas con DAO Contenido: (los más recientes arriba) Más consejos para mejorar el acceso a datos, aportados por Norman A. Armas (25/Oct/2001) Compactar y cambiar el password de una base de datos (24/Oct/2001) Compactar una base de datos con password (24/Oct/2001) Consejos para mejorar el acceso a los datos (04/Oct/2001) Código de ejemplo de compactar, crear base y crear tablas con ADO (29/Sep/2001) Compactar una base de datos usando ADO y VB (29/Sep/2001) Crear una tabla en una base de datos, usando ADO y VB (29/Sep/2001) Leer nota del 04/Oct/2001 Crear una base de datos con ADO, usando código de VB (29/Sep/2001) Abrir una base de datos ADO con contraseña (05/Sep/2001) Manipular imágenes usando ADO (con datacontrol) (11/Jul/2001) Usar el ADO DataControl (Curso Básico Ent.36) (14/Feb/2001) Acceder a bases de datos usando ADO (sin el data control) (31/Ago/1999) Acceder a bases de Access 2000 (usando el datacontrol de ADO) (31/Ago/1999) Más consejos para mejorar el acceso a los datos, aportados por Norman A. Armas (25/Oct/2001) Algunos consejos para mejorar el acceso a datos: -Abrir el recordset o el Data sólo en el momento necesario, NUNCA abrir los recordsets o datas en el momento de cargar la forma (salvo en casos en que no queda mas remedio) Por ejemplo si tienes un formulario con varios combos no es necesario llenarlos en el momento de cargar la forma, una buena costumbre es cargarlos en el momento en que el usuario haga click en el combo. -No cargar mas de 100 records como máximo en un grid o lista, si es necesario mostrar más, jugar con el SELECT TOP y el WHERE para mostrar los datos en bloques de a 100 (o menos de 100) Compactar una base de datos con password y cambiarlo. (24/Oct/2001) Para compactar una base de datos con password (o contraseña), se hace prácticamente igual que en una base de datos sin password, lo único que hay que hacer es añadirle la cadena correspondiente al código mostrado anteriormente. Este sería el código para compactar una base de datos con password: je.CompactDatabase "Data Source=" & txtNombreBase.Text & ";" & _ "Jet OLEDB:Database Password=PasswordAnterior", _ "Data Source=" & sDBTmp & ";" Y este otro para cambiarle el password actual y ponerle otro: je.CompactDatabase "Data Source=" & txtNombreBase.Text & ";" & _ "Jet OLEDB:Database Password=PasswordAnterior", _ "Data Source=" & sDBTmp & ";" & _ "Jet OLEDB:Database Password=NuevoPassword" Consejos para mejorar el acceso a los datos (04/Oct/2001) Esta sección te mostrará algunos consejos con los cuales podrás mejorar el acceso a los datos, el primero de ellos, con el que inauguramos esta sección es de Norman A. Armas, si crees que tienes alguno que se pueda añadir, me lo mandas. Gracias. Consejo aportado por Norman A. Armas, publicado el 04/Oct/2001 Nunca usar SELECT * FROM TuTabla., especifica siempre que campos son los que se quieren seleccionar en ese momento y que record o records Código de ejemplo de compacta, crear base y crear tablas con ADO (29/Sep/2001) Este es el link al código completo de los tres casos indicados: Cómo crear una base de datos con ADO, Cómo crear tablas y Cómo compactar una base de datos. En la página se muestra el código completo, el cual puedes bajar mediante un fichero comprimido. ¡Que lo disfrutes! Guillermo Compactar una base de datos usando ADO y VB (29/Sep/2001) Para compactar bases de datos usando ADO, tienes que crear una referencia a Microsoft Jet and Replication Objects 2.6 Library (JRO). Nota: JRO sólo se puede usar con bases de datos Microsoft JET Aquí tienes el código necesario para compactar una base de datos: Private Sub cmdCompactar_Click() ' Compactar una base de datos con ADO Dim sDBTmp As String Dim je As JRO.JetEngine ' On Error GoTo ErrCompactar ' Set je = New JRO.JetEngine ' ' Crear un nombre "medio" aleatorio sDBTmp = "DBT_" & Format$(Minute(Now), "00") & Format$(Second(Now), "00") & ".mdb" ' Asegurarnos de que no existe una base con el nombre temporal If Len(Dir$(sDBTmp)) Then Kill sDBTmp End If ' lblInfo.Caption = " Compactando la base de datos..." lblInfo.Refresh ' ' Compactar la base de datos je.CompactDatabase "Data Source=" & txtNombreBase.Text & ";", _ "Data Source=" & sDBTmp & ";" ' ' Eliminar la base de datos original Kill txtNombreBase.Text ' ' Renombrar la base temporal con el original Name sDBTmp As txtNombreBase.Text ' lblInfo.Caption = " Base de datos compactada." lblInfo.Refresh ' Exit Sub ' ErrCompactar: ' Mostrar el mensaje de error MsgBox "Error al compactar la base de datos:" & vbCrLf & _ Err.Number & " " & Err.Description, _ vbExclamation, "Error al compactar la base de datos" Err.Clear lblInfo.Caption = " *** Error al compactar la base de datos ***" lblInfo.Refresh End Sub Para más información: Compacting a Database (MDAC Technical Articles) Crear una tabla en una base de datos usando ADO y VB (29/Sep/2001) Hay que crear una referencia a ADOX (ver Cómo crear una base de datos con ADO). El código, casi simplificado, sería algo como esto: Dim cat As ADOX.Catalog Dim tbl As ADOX.Table ' Set cat = New ADOX.Catalog Set tbl = New ADOX.Table ' ' Abrir el catálogo cat.ActiveConnection = _ "Provider=" & cboProvider.Text & ";" & _ "Data Source=" & txtNombreBase.Text & ";" ' ' Crear la nueva tabla With tbl .Name = txtNombreTabla.Text ' Crear los campos y añadirlos a la tabla. ' Esto hay que hacerlo antes de añadir la tabla a la colección de tablas .Columns.Append "ID", adInteger ' Dependiendo del tipo de proveedor, los datos de cadena serán de un tipo u otro If cboProvider.Text = "Microsoft.Jet.OLEDB.3.51" Then ' Para Access 97 .Columns.Append "Nombre", adVarChar, 50 ' Una cadena de 50 caracteres .Columns.Append "email", adVarChar, 100 .Columns.Append "Telefono", adVarChar .Columns.Append "Observaciones", adLongVarChar ' Una cadena larga, (Memo) Else ' Para Access 2000 .Columns.Append "Nombre", adVarWChar, 50 ' Una cadena de 50 caracteres .Columns.Append "email", adVarWChar, 100 .Columns.Append "Telefono", adVarWChar .Columns.Append "Observaciones", adLongVarWChar ' Una cadena larga, (Memo) End If .Columns("Nombre").Attributes = adColNullable ' Permite contener nulos .Columns("email").Attributes = adColNullable .Columns("Telefono").Attributes = adColNullable .Columns("Observaciones").Attributes = adColNullable End With ' ' Añadir la nueva tabla a la base de datos cat.Tables.Append tbl ' Set tbl = Nothing Set cat = Nothing En este ejemplo, tenemos que tener asignadas las variables sProvider (el proveedor), sNombreBase (el nombre y path de la base de datos) y sNombreTabla para el nombre de la tabla. Para una base de datos del tipo Access 97, sProvider = "Microsoft.Jet.OLEDB.3.51" Para una base de datos del tipo Access 2000, sProvider = "Microsoft.Jet.OLEDB.4.0" Nota: Los tipos de datos de cadena adVarChar y adLongVarChar son los que aceptan las tablas para Access 97, las tablas de Access 2000 se deben usar los del tipo adVarWChar y adLongWChar. Nota 2: Los campos se añaden a la tabla por orden alfabético, independientemente del orden en el que se han añadido. Si alguien sabe cómo hacer que no se clasifiquen, por favor que me lo diga, gracias Para más información: Defining and Retrieving a Database’s Schema (MDAC Technical Articles) Crear una base de datos con ADO, usando código de VB (29/Sep/2001) Para poder crear una base de datos, desde Visual Basic, usando ADO (ActiveX Data Objects), tenemos que crear en nuestro proyecto una referencia a: Microsoft ADO Ext. 2.6 for DDL and Security (msadox.dll), y crear un objeto del tipo Catalog. Nota: Esta referencia es para la versión 2.6 de ADO, por tanto puede ser que, si la versión que tienes instalada es otra, en lugar de 2.6 aparezca otra numeración. ADOX sólo está disponible a partir de la versión 2.1 de ADO. Veamos, de forma simple, cómo crear una base de datos: Dim cat As ADOX.Catalog Set cat = New ADOX.Catalog ' ' Crear la base de datos cat.Create "Provider=" & sProvider & ";" & _ "Data Source=" & sNombreBase & ";" En este ejemplo, tenemos que tener asignadas las variables sProvider (el proveedor) y sNombreBase (el nombre y path de la base de datos). Para una base de datos del tipo Access 97, sProvider = "Microsoft.Jet.OLEDB.3.51" Para una base de datos del tipo Access 2000, sProvider = "Microsoft.Jet.OLEDB.4.0" Nota: Si la base de datos ya existe, dará un error. Para más información: Defining and Retrieving a Database’s Schema (MDAC Technical Articles) Abrir una base de datos ADO con contraseña (05/Sep/2001) Para abrir una base de datos ADO con contraseña, podemos hacerlo al crear la conexión. He probado varias de las formas que se indican en la ayuda, pero la única que me ha funcionado es la que aquí te muestro... así que, si a ti te funciona de otra forma, pues... eso, que uses la que mejor te parezca... je, je. Este código es para bases de datos del tipo Access 97, en caso de que quieras usar una de Access 2000, hay que cambiar el provider por: Provider=Microsoft.Jet.OLEDB.4.0; Set Cnn = New ADODB.Connection Cnn.Open "Provider=Microsoft.Jet.OLEDB.3.51; " & _ "Data Source=" & sBase & ";" & _ "Jet OLEDB:Database Password=laclave" En este ejemplo, asumimos que tenemos una variable llamada Cnn del tipo ADODB.Connection y otra, sBase del tipo String, a la que se ha asignado el nombre de la base de datos a la que queremos acceder.