Entrega Cuarenta: 04/Sep/2001
por Guillermo "guille" Som
Si quieres linkar con las otras entregas, desde el índice lo puedes hacer
Confío en que no acabes tarumba con tantas vueltas que estoy dando... la entrega anterior fue sobre las clases en Visual Basic y esta que te ofrezco ahora sigue los pasos de la entrega 36 sobre el acceso a bases de datos, aunque en esta ocasión sin usar el data control y con DAO. En otra entrega, veremos lo mismo, pero usando ADO... hasta que finalmente nos quedemos con ese tipo de acceso a datos, ya que Microsoft no "quiere" que sigamos usando DAO y lo trata como obsoleto, aunque no lo es tanto... pero como hay que está a la última en esto de programación, habrá que hacerles caso... así que también ve preparando el cuerpo, ya que a partir del 2002 la "nueva ola" será .NET y habrá que ir "concienciándose" de la nueva tecnología... pero no te preocupes que también podrás aprenderla... para que no te quedes atrás, aunque eso será en un futuro... talvez no muy lejano...
Cómo acceder a bases de datos DAO, sin el datacontrol.
Empecemos desde el principio... para que te vayas acostumbrando... aunque ya deberías saber crear tus propios formularios y añadir los controles que te indique... aunque prácticamente no te lo haya explicado en el curso, es algo que te enseñan en prácticamente cualquier libro e incluso en los "tutoriales" que incluye el Visual Basic.
Sólo decirte que usando la versión 5CCE de Visual Basic no se pueden acceder a datos, así que tendrás que usar la versión Profesional o la Empresarial... pero si de verdad te quieres dedicar a esto de la programación... esa serán las versiones de las que deberías disponer... y no me preguntes dónde conseguirlas... ya que las venden en cualquier "tienda" de informática o en los distribuidores que puedes encontrar en Internet.Vayamos al tema que nos interesa, ya que no es plan de hacer "marketing" gratuito a los distribuidores que "no sponsorizan" este curso básico... ¡hum!
Crea un nuevo proyecto, se creará un proyecto con un formulario.
Añade los siguientes controles para que el formulario quede con el aspecto que te muestro a continuación, (que es parecido al usado en las entregas anteriores de acceso a datos):
Aspecto del formulario en tiempo de diseñoLos controles usados son:
En la parte superior:
cmdMover, un array de 0 a 3
Label1, un array de 0 a 2, Text1, un array de 0 a 2
cmdAdd, cmdActualizar, cmdBorrar
El segundo grupo:
Label2, Text2, Option1, Option2, cmdBuscar, cmdBuscarSig
Elbotón de salir es: cmdSalirEn el menú Proyecto/Referencias... selecciona Microsoft DAO 3.51 Object Library -aunque también puedes seleccionar cualquier otra que empiece por Microsoft DAO... cualquiera de ellas vale... puede que también tengas la 3.6 e incluso la 2.5/3.51 Compatibility Library, todo dependerá de la versión de DAO que tengas instalada-
A diferencia de cuando seleccionas un componente, después de cerrar el cuadro de diálogo no verás nada nuevo en la ventana de herramientas, ya que las referencias no añaden nuevos controles, pero si que añaden nuevas librerías que exponen objetos que podemos usar en nuestra aplicación...Uno de esos objetos es el objeto Database, el cual se usará para "mantener" una referencia a la base de datos, con la cual podremos abrir recordsets que nos permitirán, entre otras cosas, introducir y modificar los datos de cualquier tabla incluida en la base de datos a la que queramos acceder...
¿Qué es un Recordset?
Según la ayuda de Visual Basic, "Un objeto Recordset representa los registros de una tabla o los registros del resultado de ejecutar una consulta". Una consulta es... eso... una consulta... una especie de búsqueda avanzada, en la que podemos indicar varios criterios de búsqueda... aunque también, como verás pronto, es algo más sencillo que todo eso. No te preocupes que veremos algunos ejemplos de "consultas".Para poder manejar los objetos Database y Recordset, hay que crear unas variables para dichos objetos, por tanto en la sección de declaraciones del formulario (General/Declaraciones), añade estas líneas:
Option Explicit
Private db As Database
Private rs As Recordset
De esta forma tendremos una variable llamada db que apuntará al objeto Database y otra, llamada rs, que apuntará a un objeto del tipo Recordset.
En el evento Form_Load asignaremos los "objetos reales" a esas dos variables.
Para poder abrir la base de datos, necesitamos saber el path en el que se encuentra dicha base de datos, para ello vamos a crea una constante, en la cual tendrás que indicar el path correcto, es decir, el sitio exacto en el que se encuentra la base de datos, en nuestro caso será BIBLIO.MDB, la base de ejemplo que se incluye con Visual Basic.Const sPathBase As String = "C:\Program Files\Microsoft Visual Studio\VB98\BIBLIO.MDB"
A continuación abrimos la base de datos usando la función OpenDatabase, la cual devuelve un objeto de la base de datos recién abierta, uno de los parámetros que espera recibir dicha función es el path de la base de datos que queremos abrir, en nuestro ejemplo usaremos el contenido de la constante anterior: sPathBase.
' Crear el objeto de base de datos
Set db = OpenDatabase(sPathBase)A continuación creamos el objeto recordset a partir de una "consulta" realizada a la base de datos, en este caso lo que queremos "consultar" son TODOS los campos de la tabla Authors:
' Crear el recordset con la tabla que queremos manipular
Set rs = db.OpenRecordset("SELECT * FROM Authors", dbOpenDynaset)La constante dbOpenDynaset le indica al método OpenRecordset que lo que queremos asignar a la variable rs, (de tipo Recordset), es del tipo Dynaset, este tipo de recordset permite mostrar y modificar los datos asignados a dicho recordset; además de este tipo de recordset, existen otros los cuales sólo se pueden usar para "recorrer" los datos o mostrarlos, si así lo prefieres, pero no permiten modificarlos, ese tipo de recordset también lo veremos en esta misma entrega.
Una vez que tenemos la variable rs, podemos acceder al contenido de la tabla Authors tal y como lo haciamos antes con el control Data. Para que te hagas una idea, rs tendrá el mismo funcionamiento que el que tenía Data1.Recordset en los ejemplos de las entregas anteriores sobre acceso a datos, en particular las entregas 34 y 35.
Como no tenemos un control data, el cual nos permitía movernos por los diferentes registros de la tabla, en el formulario hay cuatro botones, que se usarán para esa tarea: movernos tanto al primero, anterior, siguiente o último registro, el código para hacerlo es el que te muestro a continuación:
Private Sub cmdMover_Click(Index As Integer) On Error Resume Next ' ' Cuando las propiedades BOF y EOF dan como resultado TRUE, ' es que no hay datos, por tanto, salir del procedimiento If rs.BOF = True And rs.EOF = True Then Exit Sub End If ' ' Mover al registro indicado según el botón pulsado If Index = 0 Then ' Al primero rs.MoveFirst ElseIf Index = 1 Then ' Al anterior rs.MovePrevious ElseIf Index = 2 Then ' Al siguiente rs.MoveNext ElseIf Index = 3 Then ' Al último rs.MoveLast End If ' ' Si estamos antes del primero. mover al primero If rs.BOF Then rs.MoveFirst ' Si estamos después del último, mover al último ElseIf rs.EOF Then rs.MoveLast End If ' Si no se ha producido error, mostrar los datos If Err = 0 Then MostrarRegistro End If ' Err = 0 End SubLo primero que hacemos es comprobar si hay datos en el recordset, para ello comprobamos que ni BOF ni EOF den como resultado un valor verdadero. Cuando BOF es True, significa que el recordset está "antes" del primer registro, por otro lado EOF será True cuando estemos después del final de los registros. Cuando estas dos propiedades devuelven un valor verdadero, es que no hay datos en el recordset.
A continuación movemos el "puntero" del recordset al registro indicado, según el valor de Index sabremos que botón se ha pulsado y por tanto que "acción" tenemos que elegir. En los comentarios puedes ver qué valor corresponde con cada movimiento.
Como es posible que el usuario pulse en el botón anterior o siguiente después de estar al principio o al final respectivamente, tenemos que "controlar" si ya estamos al principio o al final del recordset para posicionarnos en el registro adecuado.
Por último, si todo ha ido bien, (no se ha producido un error), llamamos al procedimiento que muestra el contenido del registro activo en las cajas de texto.
Esto último lo hace el procedimiento MostrarRegistro, cuyo código es el siguiente:Private Sub MostrarRegistro() ' Mostrar los datos del registro actual ' A este procedimiento hay que llamarlo cada vez que ' queramos mostrar los datos del registro actual. With rs Text1(0) = .Fields("Au_ID") Text1(1) = .Fields("Author") Text1(2) = .Fields("Year Born") End With End SubSi le echas un vistazo al código de las pruebas con el control Data, notarás que no era necesario llamar expresamente a un procedimiento para que los datos se mostraran, esto era así porque el propio datacontrol se encargaba de actualizar la información en los controles que tenía "enlazados", pero ahora no tenemos un control que "automatice" esta tarea, así que, tenemos que hacerlo por nuestros medios... por suerte no es tan difícil.
Ahora vamos a ver los procedimientos de Añadir un nuevo registro, actualizar uno ya existente y eliminar el registro actual. En el propio código encontrarás la explicación de que es lo que hace cada línea usada.
El código de Añadir un nuevo registro:
Private Sub cmdAdd_Click() ' Añadir un nuevo registro With rs .AddNew ' Añadimos algún texto, para saber que es un nuevo dato .Fields("Author") = "Nuevo Autor" ' Actualizamos los datos, para que se graben en el recordset .Update End With End SubEl código de Actualizar el contenido de las cajas de texto en el recordset:
Private Sub cmdActualizar_Click() ' Guardar el contenido de las cajas de texto With rs ' Antes de actualizar los datos del recordset, ' hay que ponerlo en modo edición .Edit ' Este campo es autonumérico, así que no asignarlo '.Fields("Au_ID") = Text1(0) + 0 ' Añadimos una cadena vacía al final ' ya que si Text1(1) está vacío, se asignará un valor NULL y dará error .Fields("Author") = Text1(1) & "" ' Idem con el año de nacimiento, pero como es numérico, se sumará 0 .Fields("Year Born") = Text1(2) + 0 ' Actualizar los datos en el recordset .Update End With End SubY por último el código para eliminar un registro... como siempre, borrar es muy fácil...
Private Sub cmdBorrar_Click() ' Borrar el registro actual ' Se comprueba que haya algún registro activo, ' para ello se comprueba que no hayamos pasado del principio o el final del Recordset ' ' Comprobar que hay registros, porque si no hay, dará error If Not (rs.EOF Or rs.BOF) Then ' Eliminar el registro actual rs.Delete ' ' Movemos al primer registro cmdMover_Click 0 End If End SubBien, básicamente estas tareas son prácticamente iguales a las usadas con el datacontrol, con la salvedad de que hay que mostrar los datos cuando se cambia el registro activo.
Ahora veremos el código usado para buscar los datos, el cual es también prácticamente lo mismo que cuando se tenía el datacontrol. Fíjate que la única diferencia es que en lugar de usar la propiedad Recordset del datacontrol, se usa el recordset "cargado" con los datos y que está contenido en la variable rs.Este es el código de buscar y buscar siguiente, para lo cual usamos los métodos FindFirst y FindNext respectivamente.
Private Sub cmdBuscar_Click() ' Buscar el primer registro que coincida con el dato buscado Buscar End Sub Private Sub cmdBuscarSig_Click() ' Buscar el siguiente 'Buscar Siguiente:=True Buscar True End SubPrivate Sub Buscar(Optional ByVal Siguiente As Boolean = False) ' Procedimiento para buscar el dato indicado (18/Ene/01) ' Si Siguiente = True, se busca a partir del registro activo Dim nReg As Long Dim sBookmark As String Dim sBuscar As String ' ' Iniciamos la detección de errores On Error Resume Next ' ' Buscar la primera coincidencia en el recordset del Data1 If Option1.Value Then ' Convertir el contenido de TextBox en un número nReg = Val(Text2) ' en el campo Au_ID sBuscar = "Au_ID = " & nReg End If If Option2.Value Then ' en el campo Author sBuscar = "Author Like '" & Text2.Text & "'" End If ' With rs ' Guardar la posición anterior, por si no se halla lo buscado... sBookmark = .Bookmark ' If Siguiente = False Then ' Buscar desde el principio .MoveFirst .FindFirst sBuscar Else ' Busca a partir del registro actual .FindNext sBuscar End If ' Devolverá un error si no se halla lo buscado ' aunque no siempre es así... If .NoMatch Then Err.Clear MsgBox "No existe el dato buscado o ya no hay más datos que mostrar." ' Posicionar el recordset en la posición guardada .Bookmark = sBookmark End If ' Mostrar los datos del registro actual MostrarRegistro End With End Sub¿Cómo realizar consultas con DAO?
Ya hemos visto cómo introducir y modificar registros, también hemos visto cómo buscar un dato y seguir mostrando el resto de las coincidencias que se vayan produciendo. Pero hay ocasiones en las que a veces es necesario poder ver TODO el resultado de la búsqueda, incluso a veces nos interesa buscar más de un dato a la vez. Eso mismo se puede hacer con FindFirst y FindNext, es decir, podemos buscar en más de un campo del mismo registro el dato o datos que nos interesa a un mismo tiempo. Pero además de usar recordsets de sólo lectura, podemos acelerar esa tarea de "obtener" la información que queramos realizando consultas en lugar de ir buscando uno por uno los datos. Independientemente de cómo hagamos la consulta, siempre nos quedará el recurso de poder usar los métodos FindXXX para buscar a su vez datos dentro del resultado de la consulta, ya que al fin y al cabo el resultado de dicha consulta se almacena en un objeto recordset... ¡que lio! ahora veremos con ejemplos cómo funciona todo esto.Para mostrar el resultado de la "búsqueda" o consulta, vamos a usar un control ListView.
Para añadir un control ListView a nuestro proyecto, primero hay que "añadir" el control a la barra de herramientas de Visual Basic, para ello, selecciona la opción Componentes del menú Proyecto y del cuadro de diálogo que te muestra, selecciona Microsoft Windows Common Controls, (pude que a continuación de este nombre te muestre la versión de Visual Basic, en mi caso, me muestra 6.0, pero también la 5.0 (SP2), ya que tengo instalado esas dos versiones de VB.
Una vez que has pulsado en Aceptar, verás que se han añadido nuevos controles a la barra de herramientas (ToolBox), selecciona el que representa al Listview y añadelo al formulario, mediante código configuraremos la apariencia.
Si quieres puedes crearte un nuevo proyecto para esta "segunda" prueba, ya que, además de añadir el ListView, también vamos a quitar los botones de búsqueda, porque no tiene sentido tenerlos... al menos para el propósito de este ejemplo.
El aspecto del formulario sería el siguiente:
El aspecto, en tiempo de diseño, del segundo formulario
El código para configurar el ListView en tiempo de ejecución para mostrar la información de la tabla Authors de la base de datos Biblio.mdb lo pondremos en el evento Form_Load y es el siguiente:With ListView1 ' El tipo de Listview que queremos es del tipo "reporte" .View = lvwReport ' Que muestre las líneas de separación entre datos .GridLines = True ' Que no se puedan modificar los datos del listview .LabelEdit = lvwManual ' Añadimos las cabeceras .ColumnHeaders.Add , , "Au_ID", 900 .ColumnHeaders.Add , , "Autor", 2700 .ColumnHeaders.Add , , "Año nacimiento", 1500, lvwColumnRight End WithAhora la búsqueda sólo se hará por el nombre del autor y se mostrarán en la lista todos los autores que coincidan con los datos que queremos buscar. El código del botón Buscar sería el siguiente:
Private Sub cmdBuscar_Click() ' Mostrar los datos en el listview Dim sBuscar As String Dim tRs As Recordset Dim tLi As ListItem ' ' Formar la cadena de la consulta: ' Se busca por el nombre del autor y se muestran clasificados por el nombre sBuscar = "SELECT * FROM Authors WHERE Author LIKE '" & Text2 & "' ORDER BY Author" ' Creamos un recordset del tipo "estático", el cual no es modificable ' para poder modificarlo, tendría que ser del tipo dbOpenDynamic Set tRs = db.OpenRecordset(sBuscar, dbOpenSnapshot) ' Comprobar que hay datos en el recordset With tRs ' Si no hay datos... If (.BOF And .EOF) Then MsgBox "No se han encontrado los datos buscados" Else ' Mostrar los datos hallados ListView1.ListItems.Clear .MoveFirst Do While Not .EOF Set tLi = ListView1.ListItems.Add(, , .Fields("Au_ID") & "") tLi.SubItems(1) = .Fields("Author") & "" tLi.SubItems(2) = .Fields("Year Born") & "" .MoveNext Loop End If End With End SubEn otra ocasión veremos cómo "diseñar" un formulario para consultas con distintas opciones de búsqueda, así como para búsqueda en múltiples campos.
En la próxima entrega veremos el código que habría que usar para hacer esto mismo pero usando ADO.
Así que, paciencia y a ser buenos.
Nos vemos
Guillermo
P.S.
Este link te permite bajar el código de los dos ejemplos. (basico40_cod.zip 7.98 KB)