APLICANDO VBA A UNA BASE DE DATOS
EN ACCESS
Moviéndonos por el Recordset
Teniendo claro el uso de los cursores y los cerrojos, podemos comenzar a ver los métodos y
propiedades que utilizaremos para recorrer un Recordset. A través de la utilización de los
métodos podremos definir el movimiento a realizar, el que será complementado con la
utilización de las propiedades que nos permitirán controlar la situación del puntero, evitando
que nos salgamos de los límites del Recordset.
Método Descripción
Move Permite movernos hacia arriba si le indicamos un
número positivo, o hacia abajo si le indicamos uno
negativo. Ej.: [Link] 2
MoveFirst Nos lleva al primer registro del Recorset.
MoveNext Nos permite recorrer secuencialmente el Recordset,
avanzando un registro hacia adelante.
MoveLast Nos lleva al último registro del Recordset.
MovePrevious Nos permite recorrer en forma inversa el Recordset,
avanzando un registro hacia atrás. Nos lleva al
registro anterior.
Las propiedades relacionadas con el movimiento a través del Recordset son las siguientes:
Propiedad Descripción
AbsolutePosition Nos indica el número del registro en el que nos
encontramos. También lo podemos utilizar para
movernos a una determinada posición.
Ej.: [Link] = 5
BOF Es True cuando nos encontramos al principio del
Recordset, antes del primer registro.
EOF Es True cuando nos encontramos al final del
Recordset, después del último registro.
RecordCount Nos señala el número de registros que contiene el
objeto Recordset.
Métodos, propiedades y colecciones del Recordset
Ahora que hemos visto los aspectos básicos de un Recordset entregaremos al lector una guía
con los principales métodos asociados a este objeto, de forma que se pueda profundizar en
el estudio y utilización del objeto Recordset.
Método Descripción
AddNew Crea un nuevo registro en el Recordset. Sólo será
insertado en la tabla cuando se aplique el método
Update. Ejemplo:
[Link]
rs("Nombre") = "Rodrigo"
rs("Apellido") = "Rohland"
[Link]
CancelUpdate Cancela un proceso de actualización, ya sea de
creación o de modificación de registros.
Clone Crea una copia del objeto Recordset. Ejemplo: Set
rs2 = [Link]
Close Cierra el objeto Recordset utilizado.
Delete Elimina del Recordset el registro que estemos
utilizando en ese momento.
GetRows Crea un arreglo con el contenido del Recordset. Si
quieres aprender más sobre este método visita este
artículo.
Move Permite movernos hacia arriba si le indicamos un
número positivo, o hacia abajo si le indicamos uno
negativo. Ejemplo: [Link] 2
MoveFirst Nos lleva al primer registro del Recorset.
MoveNext Nos permite recorrer secuencialmente el Recordset,
avanzando un registro hacia adelante.
MoveLast Nos lleva al último registro del Recordset.
MovePrevious Nos permite recorrer en forma inversa el Recordset,
avanzando un registro hacia atrás. Nos lleva al
registro anterior.
NextRecordSet En algunos casos una consulta SQL puede devolver
más de un Recordset. Con este método borraremos el
Recordset actual y avanzaremos al siguiente.
Open Abre el objeto Recordset, cargando en él los
resultados de la consulta efectuada a una o varias
tablas. Ejemplo: [Link] SQL, oConn, cursor,
cerrojo
Requery Con este método se puede actualizar el objeto
Recordset, observándose los cambios ocurridos en los
datos.
Supports Mediante este método podremos validar si el objeto
Recordset abierto, soporta algún método o función en
particular. Este método nos presente las siguientes
posibilidades:
adAddNew. El Recordset soporta el método
AddNew.
adApproxPosition. Soporta las propiedades
AbsolutePosition y AbsolutePage.
adDelete. Soporta el método Delete.
adMovePrevious. Soporta los métodos Move y
MovePrevious.
adUpdate. Soporta el método Update.
Update Actualiza la tabla a la que hace referencia el objeto
Recordset, haciendo efectivos los cambios realizados.
Vistos los métodos, pasaremos a analizar las propiedades del objeto Recordset, con las cuales
podremos conocer el estado de este objeto durante la ejecución de nuestra aplicación.
Propiedad Descripción
AbsolutePage Cuando hayamos paginado nuestro Recordset,
podremos utilizar esta propiedad para ubicarnos en
una página determinada del objeto paginado. Para
aprender más sobre la paginación de Recordset lee el
este artículo.
AbsolutePosition Nos indica el número del registro en el que nos
encontramos. También lo podemos utilizar para
movernos a una determinada posición.
Ej.: [Link] = 5
ActiveConnection Sirve para leer el DSN o la ruta correspondiente a la
conexión relacionada con nuestro objeto Recordset.
BOF Es True cuando nos encontramos al principio del
Recordset, antes del primer registro.
Bookmark Devuelve o fija un identificador para el registro
actual.
CacheSize Define el número de registros o filas que el Recordset
va a pre-almacenar en la memoria caché.
CursorType Se relaciona con el tipo de cursor que utilizaremos en
el objeto Recordset. Las opciones se analizaron en el
apartado "Tipos de Cursor del Recordset"
EditMode Señala el estado de edición de un registro. Existen
tres posibilidades:
adEditNone. El registro no se encuentra
editado.
adEditInProgress. El registro se encuentra
editado, pero no se ha grabado.
adEditAdd. Se ha llamado al método AddNew.
EOF Es True cuando nos encontramos al final del
Recordset, después del último registro.
Filter Permite filtrar un Recordset, manteniendo sólo los
registros que superen ese filtro. Ejemplo:
Filtro = "Fecha='" & Date "'"
[Link] = Filtro
LockType Se relaciona con el tipo de cerrojo que utilizaremos
en el objeto Recordset. Las opciones se analizaron en
el apartado "Tipos de Cerrojo del Recordset"
MaxRecords Nos permite fijar el número máximo de registros que
aceptará el objeto Recordset. El valor por defecto es
0 e indica que no existirá límite.
PageCount Nos dice cuántas páginas tenemos en función del
tamaño de cada página que hemos con PageSize.
PageSize Define el número de registros o filas que forman una
página. Por defecto son 10.
RecordCount Nos señala el número de registros que contiene el
objeto Recordset.
State Señala el estado del objeto Recodset. Existen las
siguientes posibilidades:
adStateClosed. El Recordset está cerrado.
adStateOpen. El Recordset está abierto.
Por último, debemos referirnos a las dos colecciones que forman parte del objeto Recordset.
Estas colecciones son las siguientes:
Colección Descripción
Fields La colección Fields representa los campos o columnas
del objeto Recordset. Los objetos Field de un objeto
Recordset se utilizan para leer y establecer valores
para los campos del registro activo del objeto
Recordset. Para hacer referencia a un objeto Field en
una colección por su número de orden o por su valor
de propiedad Name, podemos utilizar los siguientes
formatos de sintaxis :
Fields(0)
Fields("nombre")
Properties Corresponde al conjunto de propiedades del objeto
Recordset, ya sean por defecto o modificadas por
nosotros. Accederemos a ellas de la siguiente forma:
[Link](propiedad)
APLICANDO ASP INTEGRADO CON RECORDSET
OBJETIVO
Utilizar el objeto recordset para manipular
resultados
MARCO TEORICO
Para recuperar datos, examinar resultados y modificar su base de datos, ADO proporciona el
objeto Recordset . El objeto Recordset tiene las funciones necesarias para, dependiendo de las
restricciones de las consultas, recuperar y presentar un conjunto de filas, o registros , de una
base de datos. El objeto Recordset mantiene la posición de cada registro devuelto por la
consulta, lo que permite recorrer los resultados de uno en uno.
Recuperar un conjunto de registros
Las buenas aplicaciones de datos Web emplean el objeto Connection para establecer un
vínculo, y el objeto Recordset para manipular los datos devueltos. Al combinar las funciones
especializadas de ambos objetos puede desarrollar aplicaciones de bases de datos que realicen
casi cualquier tarea de tratamiento de datos. Por ejemplo, la siguiente secuencia de comandos
del servidor utiliza el objeto Recordset para ejecutar un comando SELECT de SQL. El comando
SELECT recupera un conjunto específico de información basándose en las restricciones de la
consulta. La consulta también contiene una cláusula WHERE de SQL, que se utiliza para
establecer el criterio de selección de la consulta. En este ejemplo, la cláusula WHERE limita la
consulta a todos los registros que contengan el apellido Soto en la tabla Customers de la base
de datos.
<% 'Establece una conexión con un origen de datos.
strConnectionString = "Provider=[Link].4.0;" & _
& "Data Source=C:\Datos\[Link]"
Set cn = [Link]("[Link]")
[Link] strConnectionString
'Crea una instancia de un objeto Recordset.
Set rsCustomers = [Link]("[Link]")
'Abre un objeto Recordset con el método Open
'y utiliza la conexión establecida por el objeto Connection.
strSQL = "SELECT FirstName, LastName FROM Customers" & _
& " WHERE LastName = 'Soto' "
[Link] strSQL, cnn
'Recorre el conjunto de los registros y presenta los resultados
'e incrementa la posición del registro con el método MoveNext.
Set objFirstName = rstCustomers("Nombre")
Set objLastName = rstCustomers("Apellido")
Do Until [Link]
[Link] objFirstName & " " & objLastName & "<BR>"
[Link]
Loop %> Observe que en el ejemplo anterior, el objeto Connection estableció la conexión con
la base de datos y que el objeto Recordset utilizó la misma conexión para recuperar resultados
de la base de datos. Este método es útil cuando tenga que configurar con precisión la forma en
que se establece el vínculo con la base de datos. Por ejemplo, si necesitara especificar el
tiempo de espera antes de anular un intento de conexión, tendría que utilizar el objeto
Connection para establecer dicha propiedad . Sin embargo, si sólo desea establecer una
conexión con las propiedades de conexión predeterminadas de ADO, podría utilizar el método
Open del objeto Recordset para establecer el vínculo:
<%
strConnectionString = _
"Provider=[Link].4.0;" & _
& "Data Source=C:\Datos\[Link]"
strSQL = "SELECT FirstName, LastName FROM " & _
& "Customers WHERE LastName = 'Soto' "
Set rsCustomers = [Link]("[Link]")
'Abre una conexión con el método Open
'y utiliza la conexión establecida por el objeto Connection.
[Link] strSQL, strConnectionString
'Recorre el conjunto de registros, presenta los resultados
'e incrementa la posición del registro con el método MoveNext.
Set objFirstName = rstCustomers("Nombre")
Set objLastName = rstCustomers("Apellido")
Do Until [Link]
[Link] objFirstName & " " & objLastName & "<BR>"
[Link]
Loop %> Cuando establece una conexión con el método Open del objeto Recordset , está
utilizando implícitamente el objeto Connection para proteger el vínculo. Para obtener más
información, consulte la documentación acerca de Microsoft ActiveX Data Objects (ADO),
disponible en el sitio Web de Microsoft Universal Data Access en la dirección
[Link]
Nota: Para mejorar de forma significativa el rendimiento de las aplicaciones ASP de base de
datos, piense en la posibilidad de cambiar el estado del conjunto de registros a Application.
Para obtener más información, consulte Guardar datos en la memoria caché.
A menudo resulta útil contar el número de registros que se devuelven en un conjunto de
registros. El método Open del objeto Recordset permite especificar un parámetro opcional,
cursor , que determina cómo recupera y recorre el conjunto de registros el proveedor
subyacente. Al agregar el parámetro de cursor adOpenKeyset a la instrucción que se utiliza
para ejecutar la consulta, permite que la aplicación cliente recorra todo el conjunto de
registros. Como resultado, la aplicación puede utilizar la propiedad RecordCount para calcular
con precisión el número de registros del conjunto. Vea el siguiente ejemplo:
<% Set rsCustomers = [Link]("[Link]")
[Link] "SELECT * FROM NewOrders", _
"Provider=[Link].3.51;Data" & _
& "Source='C:\Pedidos\Clientes\[Link]'", _
adOpenKeyset, adLockOptimistic, adCmdText
'Utiliza la propiedad RecordCount del objeto Recordset
'para realizar la cuenta.
If [Link] >= 5
then [Link] "Recibimos estos " & [Link] & _
& " nuevos pedidos<BR>"
Do Until [Link]
[Link] rs("NombreCliente") & " " & _
rs("ApellidoCliente") & "<BR>"
[Link] rs("NumeroCuenta") & "<BR>" & _
[Link] rs("Cantidad") & "<BR>"
[Link] rs("FechaEntrega") & "<BR><BR>"
[Link]
Loop
Else [Link] "Hay menos de " & [Link] & _
& " nuevos pedidos."
End If
[Link]
%>
VB: Recordsets
« Anterior | Inicio
Bueno, pues ya has visto como funcionan y podemos utilizar los DataControls.
Ahora vamos a dar un paso adelante, y vamos a aprender a manejar los Recordsets:
Habiamos visto que nosotros utilizabamos un DataControl para poder acceder a los datos que
teniamos almacenados en memoria en un recordset que se creaba automaticamente cuando
nosotros poniamos el nombre de la tabla del DataControl, y le deciamos de que tabla o
consulta SQL queriamos que se cogiesen los datos para ese DataControl.
Lo que vamos a hacer ahora es crear dos variables especiales que existen a partir de Visual 4,
y que puede contener Bases de Datos y Registros de una tabla de base de datos.
Es decir, que hay un tipo especial de variables que en vez de ser Integer, Boolean o String,
son de tipo "DataBase", y pueden "contener" una base de datos, o mas bien el nombre y path
de una base de datos, y luego hay otro tipo de variables que son de tipo "Recordset", y en
ellas podremos almacenar tablas de datos, con lo que el esquema anterior se quedaria de la
siguiente manera:
Basicamente no hay ninguna diferencia encuanto al manejo de los datos respecto a como se
hacen con el DataControl, salvo que ahora estamos trabajando directamente sobre la tabla
cargada en memoria sin necesidad de un intermediario como era el DataControl.
Pero bueno, es un poquito mas complicado.
En el DataControl, para que funcionase, debiamos rellenar dos propiedades fundamentales
del mismo, que eran DataBaseName, y DataRecordSource, en una se le daba el nombre de la
base de datos que ibamos a manejar, y en la otra se le decia de que tabla o consulta SQL se
iban a coger esos datos.
Bueno, eso ahora se desglosa en cuatro lineas de codigo:
Dim dbBaseDatos as DataBase
Dim rsIngredientes as Recordset
Set dbBaseDatos = OpenDataBase ("C:\Recetas\[Link]")
Set rsIngredientes = [Link] ("SELECT * FROM Ingredientes")
En las dos primeras, lo unico que hacemos, es definir dos variables, una de tipo DataBase,
que es la que va a contener el path de la base de datos que vamos a utilizar, pero que no
puede ser String, porque necesitamos decirle que va a ser una base de datos.
Y la segunda variable es de tipo Recordset , es decir que es como si fuese una tabla en
blanco que nosotros creamos contra la base de datos que hayamos especificado en la primera
variable.
Ya tenemos definidas las dos variables, ahora nos queda darle los valores, que es lo que
hacemos en las lineas 3 y 4.
En la linea 3, inicializamos la variable BaseDatos, con la base de datos que vamos a utilizar, y
en la segunda inicializamos la variable rsIngredientes para que coja todos los valores de la
tabla ingredientes.
Dos puntualizaciones:
Yo le he dado los nombres a las variables como : dbBaseDatos, y rsIngredientes.
Las dos letras que preceden al nombre, no son necesarias, simplemente se las he puesto por
la politica de prefijos, para saber que una es de tipo BaseDatos (db), y la otra es de tipo
Recordset (rs).
Y en segundo lugar, he utilizado una sentencia SQL para decirle de donde queria yo que me
cogiese los datos, pero podria haber hecho lo siguiente y hubiese funcionado igualmente:
Set rsIngredientes = [Link] ("Ingredientes")
Es decir, dandole directamente el nombre de la tabla en vez de una sentencia SQL.
Te habras dado cuenta de que las lineas 1 y 3, equivalen a la propiedad DataBaseName del
DataControl:
Dim dbBaseDatos as DataBase
Set dbBaseDatos = OpenDataBase ("C:\Recetas\[Link]")
Y las filas 2 y 4, equivalen a la propiedad RecordSource del DataControl:
Dim rsIngredientes as Recordset
Set rsIngredientes = [Link] ("SELECT * FROM Ingredientes")
A partir de aqui, nosotros podriamos utilzar esa variable recordset, como si de un DataControl
se tratase, pero ahora tendriamos que escribir lo siguiente:
Intstrucciones de movimiento:
[Link]
Nos movemos al primer registro del recordset Ingredientes
[Link]
Nos movemos al último registro del recordset Ingredientes
[Link]
Nos movemos al registro anterior del recordset Ingredientes
[Link]
Nos movemos al registro siguiente del recordset Ingredientes
Instrucciones de busqueda:
[Link] Condicion
Busca el primer registro que cumpla una condicion
[Link] Condicion
Busca el siguiente registro que cumpla una condicion
Acceso a los datos del recordset:
Nombre1 = [Link] ("Nombre")
Metemos el contenido del campo
Nombre2 = rsIngredientes!Nombre
Nombre en la variable Nombre1
Como ves, la unica diferencia es que cambiamos "[Link]", por el nombre del
recordset que hemos creado.
Para que te quede mas claro, vamos a hacer un ejemplo:
Vamos a hacer una pantalla como la siguiente en la que se nos presenten los datos de los
distintos ingredientes que tenemos, pero sin utilizar un DataControl, sino que crearemos y
utilizaremos un recordset propio.
La pantalla es la siguiente:
Bueno, en primer lugar añadiremos los controles a la pantalla, y yo les he llamado:
TxNombre, TxTipo, TxPrecio, TxEmbalaje, BtAnterior, BtSiguiente
Paso 1
Empezaremos seleccionando la base de datos que vamos a utilzar, y diciendo que registros
vamos a utilzar. Si tuviesemos un DataControl, utilizariamos las dos propiedades que ya
conocemos "DataBaseName", y "RecordSource". Pero hemos dicho que vamos a utilzar
variables, por lo que deberemos definirlas.
Nos encontramos con el problema de localidad de las variables, es decir, que si yo las
variables las defino por ejemplo en el Form_Load, solo van a valer en el momento en el que
se cargue el formulario, y luego no voy a poder utilizarlas una vez que el formulario ya haya
sido cargado. Es una definicion que se nos queda corta para lo que necesitamos.
Podriamos pensar en hacer un modulo *.BAS y de esta forma ya nos valdria para todo el
proyecto, pero este caso quiza sea una definicion demasiado amplia, pues solo vamos a
utilizar este recordset en este Form, y no en ningun otro.
Asi que la solucion idonea en este momento parece realizar la definicion de las dos variables
en el lugar de definicion de variables a nivel de formulario:
Bueno, ya tenemos definidas las dos variables, una para abrir la base de datos, y otra para
abrir una tabla.
Pero nos queda abrir esas tablas, y eso deberiamos hacerlo en este caso en el momento en
que se cargue el formulario:
Primero abrimos la base de datos diciendole donde esta situada en el disco duro, y luego
abrimos una variable Recordset rsIngredientes, en la que le decimos los registros que
queremos que se recojan en esa variable, que en este caso son todos los de la tabla
ingredientes.
Y luego hacemos una llamada a una funcion que se llama PresentaDatos, y que lo que va a
hacer es coger los datos del registro actual del recordset rsIngredientes, y presentarlos cada
uno en la caja de texto que le corresponde si es que los campos no estan vacios, y si estan
vacios entonces los rellena con "nada".
Debemos controlar si los campos estan rellenos o vacios, porque no podemos asignar a una
caja de texto el valor NULL, que es el que tiene el campo si es que no tiene datos metidos.
La funcion seia la siguiente:
Private Function PresentaDatos()
If Not [Link] And Not [Link] Then
[Link] = rsIngredientes!Nombre
[Link] = rsIngredientes!Tipo
If Not IsNull(rsIngredientes!Precio) Then
[Link] = rsIngredientes!Precio
Else
[Link] =
</P>
<P>End If</P>
<P>If Not IsNull(rsIngredientes!embalaje) Then</P>
<P>[Link] = rsIngredientes!embalaje</P>
<P>Else</P>
<P>[Link] =
End If
End If
End Function
Esta linea de la funcion anterior
If Not [Link] And Not [Link] Then
significa que "Si no es el primer registro del recordset rsIngredientes (BOF), y no es tampoco
el ultimo (EOF) entonces puede hacer el resto de la funcion, que es rellenar cada Caja de
Texto con su valor correspondiente.
Bueno, ahora solo queda definir el codigo que se va a ejecutar cuando se pulse cualquiera de
los dos botones, que seria el siguiente:
Private Sub BtAnterior_Click()
If Not [Link] Then
[Link]
PresentaDatos
End If
End Sub
Private Sub BtSiguiente_Click()
If Not [Link] Then
[Link]
PresentaDatos
End If
End Sub
Controlando siempre que no se me vaya mas alla del principio o de los datos almacenados en
el recordset.
Bueno, solo nos queda por comentar una ultima cosa, y es que este tipo de variables, ya sean
de Bases de Datos (Database), o Recordsets, una vez que no van a ser utilzados mas, deben de
ser cerrados, porque sino vamos a tener un monton de tablas y bases de datos cargadas en
memoria que no necesitaremos para nada.
Para hacer esto, en este caso, podriamos añadir un boton mas al formulario que fuese BtSalir,
en el cual haremos que se cierre la base de datos y el recordset, y que luego se termine la
aplicacion.
El codigo seria el siguiente:
Private Sub BtSalir_Click()
[Link]
[Link]
End
End Sub
Bueno, este ejemplo nos sirve para aprender a generar una variable de tipo Recordset, pero
realmente estas variables, muy rara vez se definen a nivel de formulario, sino que se crean y
se cierran a nivel de funciones concretas.
Por ejemplo, en el caso de la pantalla en la que presentabas datos de dos tablas distintas,
una de Recetas, y otra de Ingredientes, se podria haber resuelto de una forma muy sencilla
por medio de una variable de tipo recordset que nos simplificaria mucho la instruccion SQL.
Seria algo asi:
Al hacer click sobre una receta, cogemos el contenido del campo CodigoPlato y Receta, que
son los que me la relacionan con la tabla de Ingredientes por Receta, y con esos datos
recogidos, metemos en un recordset, el CodigoPlato, Nreceta de la tabla IngxReceta, y todos
los datos de la tabla Ingredientes, relacionados por un INNER JOIN.
Puedes intentar hacerlo asi para practicar.
Solo un detalle, no se puede asociar un DBGrid a una variable Recordset, asi que tendrias que
crear una tabla con SQL en la base de datos con todos los registros del Recordset , y asociar el
DBGrid de Ingredientes a esa tabla recien creada.
Pero eso es otra historia, y debe ser contada en otro momento.... (en el siguiente capitulo:
Ampliacion de SQL)
CODIGO FUENTE PARA DEFINIR UN
RECORDSET EN UN FORM
Dim rs As [Link]
Dim rs3 As [Link]
Set db = CurrentDb
Set rs = [Link]("SELECT distinct [NOMBRE CLIENTE],CODIGO,ENTRADA From
Pedidos, dbOpenDynaset)
While Not [Link]
[Link]
[Link](0) = [Link]("NOMBRE CLIENTE")
[Link](1) = [Link]("CODIGO")
[Link]
[Link]
Wend