|
Curso básico
de programación en Visual Basic
Lección
41
Acceder
a bases de datos ADO sin el data control
|
Realizamos
programas para la gestión de empresas. Empresas medianas y
pequeñas. Programas de contabilidad, cartera de pedidos
clientes proveedores, facturación control de albaranes,
tesorería cartera de cobros y pagos y estadísticas.
Nuestro
agradecimiento a todos los que por unas causas o por otras
visitan nuestra web. Gestión de empresas PYMES. Curso de
programación de Visual Basic.
|
Aquí tienes la
entrega prometida para acceder a bases de datos ADO sin el data
control.
El ejemplo o código que te muestro, como verás, es prácticamente
idéntico al mostrado en el último ejemplo de la
entrega anterior, salvo en lo que a las referencias a las
librerías que hay que usar para poder acceder a las bases de datos
ADO, pero esto lo veremos a continuación, así que prepara el
cuerpo y el alma y te enterarás...
Cómo
acceder a bases de datos ADO, 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.
(Toc, toc, toc, Guille... ¿esto no es lo
mismo que lo que dijiste en la entrega anterior? Sí,
pero como para esta también es válido y ya lo tengo escrito,
¿para que inventarme otra cosa? Pues
sí... la cosa es buscar alguna excusa para ¡no trabajar! Buenooo,
quitaré algo para que no sea exactamente "copiado", que
es lo que suelen hacer la mayoría de la gente cuando escriben
libros y otras cosas sobre las nuevas versiones...)
El formulario de prueba:
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 el mismo del último
ejemplo de la entrega anterior):

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, cmdBuscar
Un Listview1 para mostrar los resultados de la búsqueda
Una etiqueta (LblData) para mostrar algunos mensajes y el botón de
salir es: cmdSalir
Las referencias
necesarias:
En el menú Proyecto/Referencias... selecciona Microsoft ActiveX
Data Objects 2.6 Library -aunque también puedes seleccionar
cualquiera de las otras que te muestra, (si es que te muestra alguna
más); a mi me aparecen las versiones 2.0, 2.1, 2.5 y 2.6, la única
que no deberías seleccionar es la 2.0 que ya está obsoleta-
Una vez añadida la
referencia a los objetos ADO, puedes usar los objetos expuestos por
esta librería.
En este ejemplo usaremos dos de esos objetos, que serán los que en
la mayoría de los casos usemos:
El objeto Connection y el objeto Recordset.
El primero es el que permite acceder a la base de datos y el segundo
será el que acceda a los datos propiamente dicho, cuando veas el
código seguramente lo entenderás y si no lo entiendes... es que
deberías leerte TODAS las entregas, ¡empezando por la primera! (tendrá
que excusarse el Guille de alguna forma si no entiendes lo que
explica)
Los objetos ADO más
comunes:
Normalmente, el objeto Connection
suele declararse de forma que sea visible en todo el formulario,
salvo en el caso de que añadieses algún módulo BAS y necesitaras
usarlo desde ese módulo BAS, en cuyo caso, deberías declararlo
Público o Global, pero como por ahora no es necesario... dejemos
las cosas estar...
El objeto Recordset
de ADO produce eventos, por tanto, si necesitamos acceder a esos
eventos, declararemos la variable con WithEvents, de esa
forma podemos interceptar los eventos que produzca de la misma
manera que lo hacemos con el resto de controles (de esto veremos
más en las entregas de las clases)
En el procedimiento Buscar, veremos cómo usar otro recordset, pero
de la forma tradicional: sin eventos.
Escribe este
código en las declaraciones generales del formulario:
Option Explicit
' En ADO, se usa el objeto Connection para abrir las bases de datos
Private cnn As ADODB.Connection
' Necesitamos los eventos si queremos controlar algunas cosillas
Private WithEvents rst As ADODB.Recordset
Al cargar el
formulario, creamos los objetos y asignamos la información
correspondiente para abrir la base de datos y crear o llenar el
Recordset.
Como te dije, la base de datos se abre usando el objeto Connection,
del cual usaremos el método Open al cual hay que indicarle el
"proveedor" y el nombre de la base de datos:
Private Sub Form_Load()
'
Text2 = ""
'
' Indicar el path correcto de la base de datos
' ¡ACUERDATE DE PONER EL PATH CORRECTO!
Const sPathBase As String = "C:\Program Files\Microsoft Visual _
Studio\VB98\BIBLIO.MDB"
'
' Crear los objetos
Set cnn = New ADODB.Connection
Set rst = New ADODB.Recordset
'
' Crear la conexión manualmente
' Usar "Provider=Microsoft.Jet.OLEDB.3.51;" para bases de Access 97
' Usar "Provider=Microsoft.Jet.OLEDB.4.0;" para bases de Access 2000
With cnn
.ConnectionString = _
"Provider=Microsoft.Jet.OLEDB.3.51;" & _
"Data Source=" & sPathBase & ";"
.Open
End With
' Indicarle de que tabla vamos a leer los datos
rst.Open "SELECT * FROM Authors", cnn, adOpenDynamic, adLockOptimistic
'
' Asignar los nombres de los campos a las etiquetas
Label1(0).Caption = "Au_ID:"
Label1(1).Caption = "Author:"
Label1(2).Caption = "Year Born:"
'
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
'
' Si hay datos, posicionarlo en el primer registro:
cmdMover_Click 0
End Sub
En el ejemplo de la
entrega anterior, teníamos un procedimiento al que llamábamos cada
vez que teníamos que actualizar la información del registro que
estaba activo. Pero como el Recordset de ADO produce eventos,
vamos a usar uno de esos eventos: MoveComplete, el cual se
produce cada vez que se cambia el registro activo.
Como te comenté antes, las variables declaradas con WithEvents
siguen la misma "nomenclatura" que los eventos de los
controles, por tanto, ese evento estará en: rst_MoveComplete
(selecciona el objeto rst de la lista desplegable derecha y el
evento MoveComplete de la lista de la izquierda), éste es el
código para mostrar los datos cada vez que se cambia el registro
activo, aunque realmente no sería necesario si hubiésemos
"ligado" los controles con el recordset... pero de esa
forma no tendríamos el control total sobre los datos, así que
vamos a seguir con esto de usar los eventos:
Private Sub rst_MoveComplete(ByVal adReason As ADODB.EventReasonEnum, _
ByVal pError As ADODB.Error, adStatus As ADODB.EventStatusEnum, _
ByVal pRecordset As ADODB.Recordset)
' Cada vez que el registro actual cambie,
' se producirá este evento (igual que con el DataControl)
With rst
If .EOF And .BOF Then
lblData.Caption = "No hay ningún registro activo"
.MoveFirst
Else
Text1(0) = .Fields("Au_ID")
' Por si el dato es nulo, añadirle una cadena vacia
Text1(1) = .Fields("Author") & ""
Text1(2) = .Fields("Year Born") & ""
End If
End With
End Sub
En este evento
podemos usar tanto el objeto rst como el que está en el
parámetro: pRecordset, los dos se refieren al mismo objeto.
Hacemos una pequeña comprobación de que no nos encontremos con un
recordset vacío o que esté fuera de los límites permitidos, (cosa
que ocurre cuando queremos pasar al siguiente registro cuando
estamos al final (se produce EOF) o cuando pasamos al registro
anterior y estamos al principio, (se produce BOF).
Si todo va bien, asignamos a las cajas de textos el contenido de los
campos correspondientes.
Fíjate que en algunos de los campos añado una cadena vacía al
contenido del campo, esto es para los casos en que esos campos
contengan un valor nulo. Si se lo quitas al Year Born, verás cómo
se produce un error, ya que en la base de datos Biblio, que es la
que usaremos para este ejemplo, ese campo no suele estar asignado.
Ahora te muestro el
resto del código para los botones de Mover, Nuevo, Actualizar y
Eliminar, que es prácticamente igual al de la versión para DAO,
con la salvedad de Actualizar, ya que en ADO no es necesario poner
un registro (o columna que es como se debería decir), en modo
edición para poder modificarlo, ya que al usar Update, se
actualiza el registro.
Private Sub cmdMover_Click(Index As Integer)
' Mover según el botón pulsado
'On Error Resume Next
'
With rst
If Index = 0 Then ' Primero
.MoveFirst
ElseIf Index = 1 Then ' Anterior
.MovePrevious
ElseIf Index = 2 Then ' Siguiente
.MoveNext
ElseIf Index = 3 Then ' Último
.MoveLast
End If
'
If .BOF Or .EOF Then
.MoveFirst
lblData.Caption = " No hay datos..."
Else
lblData.Caption = " Registro actual: " & rst("Au_ID")
End If
End With
'
Err = 0
End Sub
Private Sub cmdAdd_Click()
' Añadir un nuevo registro
rst.AddNew
' Añadimos algún texto, para que no se pierda este registro
Text1(1) = "Nuevo"
' Actualizamos los datos
rst.Update
' Movemos al último registro para que los cambios se hagan permanentes
' y se muestre el nuevo registro
rst.MoveLast
End Sub
Private Sub cmdActualizar_Click()
' Guardar el contenido de las cajas de texto
With rst
' Este campo es auto numé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
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 (rst.EOF Or rst.BOF) Then
' Avisar de que no hay registros
lblData.Caption = "Ningún registro activo"
Else
' Eliminar el registro actual
rst.Delete
'
' Movemos al primer registro para que los cambios se hagan permanentes
' (también podríamos haberlo movido al último registro)
rst.MoveFirst
End If
End Sub
Creo que no
necesita información adicional, en los comentarios está todo
explicado.
Para terminar,
vamos a ver el código para Buscar datos:
Private Sub cmdBuscar_Click()
' Mostrar los datos en el listview
Dim sBuscar As String
Dim tRs As Recordset
Dim tLi As ListItem
'
' Comprobar si tiene caracteres "no válidos" para ADO:
' NOTA: Replace es una función de VB6
sBuscar = Text2
sBuscar = Replace(sBuscar, "*", "%")
sBuscar = Replace(sBuscar, "?", "_")
'
Text2 = sBuscar
' 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 '" & sBuscar & "' _
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 = cnn.Execute(sBuscar)
' 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
Caracteres comodines:
Como podrás comprobar el procedimiento de buscar es muy parecido,
por no decir casi idéntico al usado en DAO, con la salvedad de que
hacemos una comprobación para cambiar los caracteres comodines que
hubiese en el texto indicado para la búsqueda, ya que en ADO no son
los mismos que en DAO.
Según la ayuda de ADO, se usará el carácter % (tanto por ciento)
en lugar del * (asterisco), cuando queramos indicar cualquier cosa
que haya en el sitio en que se encuentra dicho carácter, por
ejemplo: %jan% encontrará todos los registros que contenga
"jan", esté en el sitio que esté: Janet,
Alejandro, etc. Si pusiéramos jan%, sólo mostraría
los que empezaran con jan, etc.
Por otro lado, el
carácter _ (subrayado bajo) sustituye a la ? (interrogación), en
este caso este comodín significa "cualquier carácter que
esté en esa posición", por ejemplo: %r_us% encontrará
cualquier palabra que contenga: una r seguida de cualquier cosa,
seguida de us. Tal es el caso de Rouse,
Marcus, etc.
La función Replace
usada para cambiar esos caracteres es propia de la versión 6 de
Visual Basic, en VB5 no existe, así que tendrás que crearte tu
propia función Replace.
Bueno,
vale... aquí la tienes:
Private Function Replace(ByVal Expresion As String, _
ByVal Encontrar As String, _
ByVal ReemplazarCon As String) As String
'---------------------------------------------------------------
' Función Replace para usar con VB5 o anteriores
'---------------------------------------------------------------
Dim i As Long, j As Long
'
j = 1
Do
' Buscar la cadena indicada en la expresión
i = InStr(j, Expresion, Encontrar)
' Si la hemos hallado, quitamos dicha cadena y ponemos la nueva
If i Then
Expresion = Left$(Expresion, i - 1) & ReemplazarCon & _
Mid$(Expresion, i + Len(Encontrar))
j = i + 1
End If
Loop While i
' Devolver la cadena
Replace = Expresion
End Function
¡Esto esto amigos!
(¿y para las amigas nada?, es
que cuando se habla de forma genérica, se usa el género
masculino... como si fuese neutro... sí,
ya, es que algunos que dicen ser muy masculinos, realmente son
neutros... ¿a quién te refieres?
no, a nadie en concreto... es por
aclarar las cosas... ¡Ah! creía...)
Dejemos a los
Guilles con su discusión y te espero en la próxima
entrega, que aún no sé de que tratará... ¿será de clases?
¿será de acceso a datos? ¿será sobre algún tema nuevo? ya
veremos...
Nos vemos

|