Curso Básico de Programación
en Visual Basic

 

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ño

Los 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: cmdSalir

En 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 Sub

Lo 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 Sub

Si 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 Sub

El 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 Sub

Y 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 Sub

Bien, 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 Sub

Private 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 With

Ahora 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 Sub

En 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)


 
entrega anterior ir al índice siguiente entrega

Ir al índice principal del Guille