• No se han encontrado resultados

INSTITUTO SUPERIOR TECNOLÓGICO NORBERT WIENER

N/A
N/A
Protected

Academic year: 2021

Share "INSTITUTO SUPERIOR TECNOLÓGICO NORBERT WIENER"

Copied!
82
0
0

Texto completo

(1)

INSTITUTO SUPERIOR TECNOLÓGICO NORBERT WIENER

Manual del Alumno

ASIGNATURA : Lenguaje de Programación II (Visual Basic II)

PROGRAMA: S3C

LIMA-PERU

(2)

Índice General

Pag N°

1. Introducción y base de datos... 2

2. Control Ado ... 4

3. El Control Ado Data Control 6.0 (OLEDB)... ... 8

4. El Control Ado Data Control 6.0 (OLEDB)(continuación)... 44

5. El Control Ado Data Control 6.0 (OLEDB)(continuación)... 50

6. Controles Enlazados ... 56

7. Uso de Múltiples Tablas ... 57

8. Uso de Múltiples Tablas (continuación)... 58

9. El Data Environment ...63

10. Visual Basic – SQL ... 69

11. Controles no Enlazados ...70

12. Controles no Enlazados y Módulo de Clase...78

13. Controles Active X...86

14. Funciones Api‟s...91

(3)

INTRODUCCION Y BASE DE DATOS

Acceso a Datos:

Los datos se consideran uno de los activos más valiosos de la empresa moderna. Por tal razon, es importante que la misma cuente con una estrategia apropiada para administrarlos adecuadamente; esto es, almacenarlos, recuperarlos y procesarlos de tal forma que sean importantes para la toma de decisiones.

Visual Basic provee soporte a datos de muchas maneras. Se puede utilizar DAO (Data Access Objects) para manipular datos provenientes de Microsoft Jet o Access o Excel, ODBC (Open Database Conectivity), ISAM y tecnologís RDO (Remote Data Object) y ADO (Actives Data Object).

Los Objetos de acceso a datos (DAO) y el control Data utilizan el motor de base de datos Microsoft Jet para tener acceso a las bases de datos. El motor de base de datos Jet puede obtener acceso a tres tipos de bases de datos:

® Bases de datos Microsoft Jet:

Es un motor utilizado por Microsoft Access y Visual Basic. Este motor permite crear y manipular datos directamente.

® Bases de datos del Método de acceso secuencial indizado (ISAM, Indexed Sequential Access Method):

Dada la existencia de formatos conocidos y extendidos mundialmente, como por ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre otros, DAO permite la manipulación de datos de éstos formatos.

® Bases de datos compatibles con Open Database Connectivity (ODBC, Conectividad abierta de bases de datos):

No solo las bases de datos de escritorio o denominadas “desktop” tienen soporte por parte de DAO. Las bases de datos del estilo cliente/servidor que se ajustan al estándar ODBC, tal como SQL Server, Oracle u otros a los cuales se diseñó su apropiado

“provider” se le da soporte.

Visual Basic también provee otros métodos de acceso a datos, tal y como:

® Control de origen de datos remotos

En la edición empresarial de Visual Basic se dispone de un control de origen de datos

remotos, que soportan ODBC, tal como Microsoft SQL Server y Oracle.

(4)

® Bibliotecas ODBC

Le permiten llamar directamente a la interfaz de programación de aplicaciones (API) de ODBC. Está disponible como un producto independiente.

® Bibliotecas SQL para Visual Basic (VBSQL)

Proporcionan un vínculo directo a Microsoft SQL Server. Están disponibles como productos independientes.

Descripción de una Base de Datos:

Hoy día la mayoría de sistemas informáticos que administran la información de una empresa utilizan un esquema relacional. Esto es, relacionan logicamente la información utilizando tablas y entidades que conforman llaves de enlace.

Un esquema relacional presenta los datos como un grupo de tablas que se relaciona logicamente entre si. Por ejemplo, Visual Basic provee la base de datos Biblio.Mdb y en ella radican varias tablas de datos (tales como author y titles) que se relacionan entre si gracias a la duplicacion que existe en ellas del ID u otros campos.

Se puede observar el diagrama de base de datos denominada Students And Classes elaborada mediante asistente en Visual Foxpro, versión 6.0. Observense los campos, índices y relaciones contenidos:

Elementos de una tabla:

La base de datos Students and classes contiene varias tablas que agrupan información, como studentes, assigments, results, entre otras.

En una base de datos, las filas de tablas se denominan registros o tuplas y las

columnas campos. Los registros pertenecen a la descripción de una entidad, por ejemplo,

un cliente, un proveedor, un empleado, un producto, entre otros. Por otro lado, el campo

(5)

es parte del registro como puede ser la cedula, el nombre, la existencia, la direccion, el telefono, entre otros. Asimismo, existen índices (que pueden ser de diferentes tipos) y reglas (reglas de validación y de integridad referencial).

Clave principal:

Cada tabla contenida en una base de datos posee una clave principal. Esta es un campo, o la combinación de varios campos, que es exclusiva en cada fila de la tabla. Esto permite identificar de forma uniequivocamente un registro particular, permitiendo que no existan registros duplicados o accesar más rapidamente a un registro o a una colección de ellos. En el caso de la base de la base de datos Students and classes, se tiene una tabla denominada students, donde la clave primaria es studentid, dado que la identificación de todos y cada uno de los estudiantes es única en la colección de registros. Asimismo, en la tabla results se tiene una clave por el mismo campo, siendo una llave que se puede repetir tantas veces como sea necesaria, dado que un estudiante puede registrar todos los resultados obtenidas por materia. En este caso se determina una clave externa, dado que la misma no es propia de la tabla sino de otra que es students.

Registros:

Un registro contiene información referente a una entrada a una tabla. Es preferible que una tabla no contenga duplicados. En este caso es una tabla maestra. En el caso de la tabla Students, es necesario que cada estudiante tenga su propio Id y no exista otro similar en la tabla. Sin embargo, en registros históricos se repetirá tantas veces una llave como sea necesario.

Campos:

Un campo de una tabla identifica una parte de un registro. Por ejemplo, la tabla students contiene los campos studentid, lastname y firstname, entre otros.

Indices:

Los indices de una tabla son listas ordenadas en las que se puede localizar más rápidamente un determinado registro o conjunto de ellos. Se crean en base a un campo de la tabla, tomando como requerimiento cuál de ellos representa una entidad fuerte dentro de la colección o cuál es el adecuado para ordenar un conjunto de registros.

Conectividad a datos en Visual Basic:

Existen dos métodos para abrir una base de datos en Visual Basic: utilizando el Data Control (el cual es un objeto provisto por Visual Basic) o mediante el método OpenDatabase.

El control data es un objeto provisto por Visual Basic para la manipulación de datos en una o varias tablas.

El control data implementa este acceso mediante la utilización de un motor de bases de

datos tal como Microsoft Jet. Existen métodos apropiados para la manipulación de datos y

se provee de una herramienta de generación automática de formularios que se encarguen de

dicha manipulacion, sin necesidad de escribir mucho código.

(6)

Para construir una aplicación de bases de datos, utilizando el control data, se recomienda seguir los siguientes pasos:

1. Agregar un control data al formulario y configurar las propiedades Databasename, connect y recordsource, principalmente. Lo anterior para establecer la base de datos a la que se va a conectar el formulario, el tipo de conexión (por defecto es Microsoft Access) y el origen de datos (la tabla de la base de datos abierta).

2. Agregar controles tales como text box o label para que contengan los datos del recordsource. Aqui hay que configurar datasource y datafield como las propiedades que se conectarán a los datos del data control.

Usar controles enlazados a datos:

Cuando se utiliza un data control en un formulario generalmente es necesario diseñar controles que permitan contener los datos cargados en dicho data control. Estos controles pueden ser CheckBox, Image, Label, PictureBox, TextBox, ListBox, ComboBox y los contenedores OLE.

Propiedades y Métodos del Control Data:

Además de las propiedades Databasename y RecordSource el data control posee otras propiedades y métodos, tales como:

® Propiedad Connect

® Propiedad Exclusive

® Propiedad ReadOnly

® Propiedad Recordset

® Propiedades BOFAction y EOFAction

® Método Refresh

La Propiedad connect especifica el tipo de base de datos que se abrirá. Puede incluir argumentos tales como Id de usuario y la contraseña.

La propiedad Exclusive determina si la base de datos será abierta en forma exclusiva o no. Si el valor de esta propiedad es True la base de datos se abrirá exclusivamente y ninguna aplicación podrá utilizarla hasta que se cierre.

La propiedad ReadOnly determina si la base de datos se abrirá para solo lectura o no.

Si la propiedad es True no se podrán modificar los datos obtenidos.

El objeto Recordset contiene los registros devueltos para el data control, basado en una apertura de una tabla o producto de la ejecución de una instruccion SQL. Un recordset tiene propieades y metodos que se pueden utilizar para trabajar con los registros obtenidos.

Las propiedaes BOFAction y EOFAction determinan que acción realizar cuando las

propiedades BOF o EOF del Recordset son True. Por ejemplo, si la propiead EOFAction

del control data es vbAddNew y utiliza el control data para situarse trás el último registro del

recordset, el control data ejecutará automáticamente el metodo AddNew para incluir un

nuevo registro.

(7)

El método Refresh actualiza un objeto recordset. Si se cambia la propiedad RecordSource del data control, se deberá llamar a este método para actual el conjunto de registros en el data. Lo siguiente es un ejemplo de lo anterior:

Data1.RecordSource = "SELECT * FROM Empleados " & _

"WHERE [IdEmpleado] = " & txtEmpID.text Data1.Refresh

Recordset:

Es el conjunto de registros contenidos en el control data. Un Recordset se almacena en la memoria, transfiriendo los datos contenidos al disco, si fuera necesario.

Para manipular un Recordset debe utilizarse la propiedad del mismo nombre del data control.

Para determinar los límites de un Recordset se utilizan las propiedades EOF y BOF.

Cuando se desplace al último registro (EOF) o al inicio del archivo (BOF), se ejecutará la acción indicada por el valor de la propiedad BOFAction o EOFAction. Seguidamente se muestra como Microsoft grafica estas propiedades:

Asimismo, se muestra como utilizar un objeto Recordset de un determinado control Data:

Data1.Recordset.MoveNext 'Va al registro siguiente.

If Data1.Recordset.EOF Then Data1.Recordset.MoveLast End If

El ejemplo anterior muestra como desplazarse al registro siguiente en el Recordset y posteriormente validar si se ha llegado al final del mismo.

Se pueden utilizar otros métodos y propiedades del objeto Recordset para recuperar, agregar, modificar o eliminar registros de este objeto.

Las propiedades BOF y EOF del objeto Recordset indican si el registro actual está

al inicio o al final del Recordset, respectivamente. Si lo anterior es verdadero, se asignará

True a la propiedad respectiva. Si ambas son verdaderas es que no existen datos en el

Recordset.

(8)

Método AddNew:

El metodo AddNew de un objeto Recordset se utiliza para agregar un nuevo registro.

Cuando se ejecuta este metodo, Visual Basic elimina los controles enlazados y asigna a la propiedad EditMode del control data el valor dbEditAdd.

Para actualizar un registro en el Recordset luego de utilizar AddNew debe utilizarse el método UpdateRecord o Update. Lo siguiente muestra este aspecto:

Sub cmdAdd_Click ()

Data1.Recordset.AddNew End Sub

Metodo UpdateRecord:

El método UpdateRecord se utiliza para guardar el registro actual en una base de datos. Es decir, posterior al metodo AddNew, tal y como se muestra a continuación:

Sub cmdUpdate_Click () Data1.UpdateRecord End Sub

Metodo CancelUpdate:

Se utiliza para cancelar un método AddNew o Edit y actualizar los controles enlazados al control data. Es decir, restaura los datos originales del Recordset. A continuación se muestra el uso de este método:

Sub cmdCancel_Click () Data1.CancelUpdate End Sub

Metodo CancelUpdate:

Este método se utiliza para eliminar un registro de una tabla. El registro eliminado continuará siendo el actual hasta tanto el usuario no realice ninguna otra acción, tal y como se muestra en el codigo siguiente:

Sub cmdDelete_Click () Data1.Recordset.Delete Data1.Recordset.MoveNext If Data1.Recordset.EOF Then Data1.Recordset.MoveLast End If

End Sub

(9)

Usando Objetos Recordset

Un recordset es un objeto que presenta los registros de una tabla o el resultado de una consulta. Se pueden usar objetos para manipular los datos de una base de datos a un nivel de registro.

Se puede usar objetos “Field” para manipular los datos de un archivo a un nivel de registro.

Los cuatro tipos de recordset son:

Table, Dynaset, Snapshot y Forward-Only

Table: Este Recordset puede ser creado para una tabla Microsoft Access, pero no soporta ODBC (Open Database Connectivity) o tablas ligadas. Es decir, funciona para una sola tabla de Microsoft Access. Cuando se crea una tabla, el motor de bases de datos JET abre dicha tabla y subsecuentemente se produce la manipulacion de los datos, operando directamente sobre la misma.

Una ventaja importante de este tipo de recordset es que se puede utilizar un indice. Esto hace más eficiente la ordenacion de registros mediante un índice, mejorando significativamente las opciones de búsqueda. Para localizar un determinado registro se puede utilizar el metodo SEEK y no FIND, dado que este ultimo es mucho más lento.

Dynaset:Este recordset puede crearse sobre una o varias tablas, mediante consultas.

Esto es mediante un conjunto de referencias a registros en una o más tablas.

Con un dynaset, se pueden extraer y actualizar datos desde una o varias tablas, incluyendo las ligas que puedan existir con otras bases de datos. La actualizacion heterogenea es una caracteristica importante de los dynaset.

Uno de los más importantes beneficios es que los cambios realizados sobre una tabla se realizan tambien en otra que se encuentra ligada a ésta.

Asimismo, los cambios hechos por otros usuarios se reflejan en el dynaset.

El dynaset es el más flexible y poderoso de los demás tipos de recordset, sin embargo es mucho más lento que, por ejemplo, el tipo table.

Snapshot:Este recordset es una copia estática de un conjunto de registros, capturados en el momento de crearse el recordset. Este puede contener campos de una o más tablas de una base de datos. Este recordset es actualizable.

La principal ventaja de un snapshot es que éste crea menos “overhead” en el procesamiento que los demás recordset. Además se pueden ejecutar consultas y retornar los valores más rápidamente, especialmente cuando se trabaja con ODBC.

Se debe considerar que para archivos MDB, OLE y archivos memo son

direccionados por punteros en la consulta.

(10)

Forward-Only: Este tipo de recordset (muchas veces denominado forward-scrolling snapshot o forward-only snapshot) provee un subconjunto de capacidades de un snapshot. Con este objeto se puede mover solo en dirección adelante a traves de registros. Solo se soporta los metodos Move o Move Next. La ventaja de este tipo de recordset es que usualmente provee la mayor velocidad entre los demas recordset. Sin embargo, ofrece la menor funcionalidad que los demas.

Un Snapshot almacena una copia de todos los registros (excepto objetos OLE y campos memo).

Un Dynaset almacena justamente la llave primaria para cada registro, copiando la totalidad de registros solo cuando es necesario para edicion o propositos de despliegue. Desde un snapshot almacena una copia completa de todos los registros en una tabla, éste puede rendir más lentamente que un dynaset si el numero de registros es muy cuantioso. Para determinar cuando usar un dynaset o un snapshot se pueden abrir ámbos, ejecutar la misma consulta y comparar los tiempos de respuesta.

El tipo de recordset que se use depende de lo que el usuario debe hacer con los datos. Puede que solo desee realizar una vista o que además deba actualizarlos. Por ejemplo, si el usuario desea ordenar los datos o trabajar con indices, usese un tipo table, dado que estos estan indexados y son más rapidos de localizar. Otro caso es que si el usuario desea actualizar un conjunto de registros seleccionados por una consulta, debe usarse el dynaset.

Finalmente, si la tabla que se desea consultar pocas veces está disponible y se desea realizar una busqueda en un conjunto de registros determinados puede usarse un tipo forward-only.

Creando una variable objeto:

Para crear una variable objeto, debe usarse el método OpenRecordset. Primero debe declararse el tipo de variable y el grupo de variables para el objeto, retornado por el metodo OpenRecordset. Puede usarse el método OpenRecordset con Database, TableDef, QueryDef, y objetos existentes.

La sintaxis del método OpenRecordset es:

La sintaxis del método OpenRecordset para todos los tipos de objetos es:

Set variable = database.OpenRecordset (source [, type [, options [, lockedits ]]])

Set variable = object.OpenRecordset ([type [, options [, lockedits ]]])

(11)

La argumento variable es el nombre del nuevo objeto. El argumento database es el nombre del objeto de base de datos abierto. El argumento Object es el TableDef, QueryDef, o el objeto existente.

El argumento source especifica el origen de los registros para el nuevo objeto. El valor del origen es el valor del objeto DAO. Cuando se crea un nuevo objeto desde un objeto Database el argumento source es un TableDef o QueryDef en la base de datos o un retorno válido de una consulta SQL o sentencia. Cuando se crea un objeto de este tipo el mismo provee el origen de datos para el nuevo objeto.

El argumento type es una constante intrinseca que especifica la clase de objeto que se desea crear. Se pueden utilizar las siguientes constantes:

dbOpenTable dbOpenDynaset dbOpenSnapshot dbOpenForwardOnly

El tipo de constante dbOpenForwardOnly reemplaza al tipo de constante dbForwardOnly que estaba contenida en versión posterior de DAO. Es decir, esta constante se mantiene por compatibilidad con la version anterior de DAO.

La siguiente sección muestra los tipos, opciones y argumentos de “lockedits” en detalle:

Tipos por defecto:

Porque DAO automaticamente escoge el tipo por defecto, dependienteo del origen de datos y como se realiza la apertura, no se necesita especificar el tipo. Sin embargo, se puede especificar un tipo diferente usando el argumento type en el metodo OpenRecordset.

La lista siguiente describe los tipos disponibles y los tipos por defecto, dependiendo de cómo se abra el objeto:

Usando el método OpenRecordset con un objeto Database Set rstNew = dbs.OpenRecordset("Data Source")

Si el recurso de datos es una tabla local en la base de datos, los cuatro tipos estan disponibles y el tipo table está por defecto. Si el origen de datos es diferente, solo Dynaset y Snapshot estan disponibles. Dynaset es el default.

Usando el método OpenRecordset con un objeto TableDef:

(12)

Set rstNew = tdfTableData.OpenRecordset

Si tdfTableData se refiere a una tabla de Microsoft Access (*.mdb) o ISAM abierta directamente, entonces los cuatro tipos estan disponibles. Si tdfTableData es un base de datos abierta mediante ODBC o es una tabla ligada en una tabla externa, solo los tipos dynaset y snapshot estan disponibles.

Usando el método OpenRecordset con un objeto QueryDef:

Set rstNew = qdfQueryData.OpenRecordset

Solo los objetos dynaset y snapshot estan disponibles.

Usando el método OpenRecordset con un objeto existente:

Set rstNew = rstExisting.OpenRecordset

Solo los objetos dynaset y snapshot estan disponibles.

Opciones OpenRecordset:

Con el argumento Options del metodo OpenRecordset se puede especificar un numero de otras caracteristicas para un objeto. Se pueden utilizar las siguientes constantes:

DbAppendOnly: Los usuarios pueden agregar nuevos registros, pero no se puede editar o eliminar. Esto es util en aplicaciones que capturan y archivan muchos datos (solo dynaset).

DbReadOnly: No se pueden hacer cambios. Este argumento es proveido solo por compatibilidad de versiones anteriores. Se debe utilizar la constante dbReadOnly en el argumento lockedits para ello.

DbSeeChanges: Si otro usuario realiza cambios en los datos en los registros (con edit y update) se produce un error en tiempo de ejecucion. Esto es util en aplicaciones donde multiples usuarios realizan, simultaneamente, operaciones de lectura/escritura sobre los mismos datos (solo dynaset y table).

DbDenyWrite: Cuando se usa con dynaset o snapshot, esta opcion previene a otros usuarios de inserciones o modificaciones de registros. Cuando una tabla está en uso otros usuarios no pueden abrir ningun otro tipo de recordset.

DbDenyRead: Otros usuarios no pueden leer datos en la tabla (solo tabla)

DbForwardOnly: Esta opcion crea un recordset forward-only o snapshot. Este es proveido solo por compatibilidad con versiones anteriores. Use la constante dbOpenForwardOnly en el argumento type.

DbSQLPassThrough: Cuando el argumento source es una sentencia SQL, use esta constante para pasar las sentencias SQL a una base conectada via ODBC, para procesamiento. Si la usa con un dynaset, los datos no son actualizables (dynaset y snapshot solamente).

dbConsistent (Default): Solo consiste en actualizaciones (solo dynaset). Se puede

usar esta constante con la constante dbInconsistent.

(13)

DbInconsistent: Son permitidas actualizaciones inconsistentes. Esta es la contraria de dbConsistent (solo dynaset). No se puede usar esta constante con la constante dbConsistent.

Con el argumento lockedits del metodo OpenRecordset se puede controlar como bloquear un objeto. Se pueden utilizar las siguientes constantes:

DbReadOnly: No se pueden realizar cambios. Esta constante reemplaza a la constante dbReadOnly que fue usada en el argumento options en versiones anteriores de DAO.

dbPessimistic (Default): Microsoft Jet usa bloqueo pesimista para determinar como los cambios pueden ser hechos en un ambiente multiusuario.

DbOptimistic: Microsoft Jet usa bloqueo optimista para determinar como los cambios pueden ser hechos en un ambiente multiusuario.

El valor por defecto es dbPessimistic. El solo efecto de usar dbPessimistic o

dbOptimistic es para configurar el valor de los objetos con la propiedad LockEdits.

(14)

Creando un Objeto desde un Formulario:

Usted puede crear un objeto Recordset basado en un formulario de Microsoft Access.

Para hacer esto, use la propiedad RecordsetClone del formulario. Este crea un Recordset tipo dynaset que se refiere a la misma consulta o “data” del fomulario. Si el formulario está basado en una consulta, hay que referirse a la propiedad RecordsetClone. Esto es el equivalente a crear un dynaset con la misma consulta. Se puede utilizar la propiedad RecordsetClone cuando necesite aplicar un metodo provisto de acceso a todos los metodos y propiedades que se pueden utilizar con un dynaset. La sintaxis para la propiedad RecordsetClone es:

Set variable = form.RecordsetClone

El argumento variable es el nombre de un objeto Recordset existente. El argumento form es el nombre de un formulario Microsoft Access. El siguiente ejemplo muestra como asignar a un objeto Recordset los registros en el formulario “Orders”:

Dim rstOrders As Recordset

Set rstOrders = Forms!Orders.RecordsetClone

Este codigo siempre crea el tipo de Recordset siendeo cloneado (el tipo de Recordset basado en el formulario); otros tipos no están disponibles.

Creando un Objeto desde una Tabla:

El metodo que se use para crear un objeto Recordset desde una tabla depende de si la tabla es local a la base de datos actual o si está ligada a otra tabla en otra base de datos. La siguiente discusion explica las diferencias y provee de ejemplos para cada tipo de tabla:

Creando un Recordset desde una tabla en una base de datos local Microsoft Access:

El siguiente ejemplo usa el metodo OpenRecordset para crear una tabla tipo Recordset:

Objeto para una tabla en la base de datos actual:

Dim dbs As Database, rstCustomers As Recordset Set dbs = CurrentDb

Set rstCustomers = dbs.OpenRecordset("Customers")

Notese que no es necesario usar la constante dbOpenTable para crear una tabla de tipo Recordset. Si se omite la constante type DAO selecciona el tipo de Recordset de mayor funcionalidad, dependiendo del objeto, en cuanto el Recordset creado y el origen de datos.

Para cuando el tipo de tabla está disponible y se abre un Recordset, DAO usa

automáticamente este tipo.

(15)

Creando un Recordset desde una tabla ligada a una tabla de un formato diferente:

El siguiente ejemplo crea un Recordset de tipo dynaset, para una tabla Paradox® 3.X.

Pero el tipo tabla no está disponible cuando se abre un Recordset desde una tabla ligada a una base de datos que no sea Microsoft Access. DAO selecciona el tipo próximo de Recordset que sea más eficiente:

Dim dbs As Database Dim tdf As TableDef

Dim rstTableData As Recordset ' Obtiene la base de datos activa.

Set dbs = CurrentDb

Set tdf = dbs.CreateTableDef("PDXAuthor")

' Conecta a la base de datos la tabla Paradox Author.

' C:\PDX\Publish.tdf.Connect = "Paradox 3.X;DATABASE=C:\PDX\Publish"

tdf.SourceTableName = "Author"

' Liga la tabla.

dbs.TableDefs.Append tdf

' Crea un Recordset tipo dynaset-type para la tabla.

Set rstTableData = tdf.OpenRecordset()

Se puede abrir directamente una tabla Paradox, abriendo inicialmente la base de datos Paradox.

Usando un Indice en un Recordset de tipo tabla:

Se pueden ordenar registros en un Recordset de tipo “table” configurando la propiedad Index. Cualquier objeto Index en la colección Indexes para los objetos tipo Recordset pueden ser especificados en la propiedad Index.

El ejemplo siguiente crea un Recordset de tipo “table” basado en la tabla Customer y utilizando un indice existente llamado City:

Dim dbs As Database, rstTableData As Recordset Set dbs = CurrentDb

Set rstTableData = dbs.OpenRecordset("Customers", dbOpenTable) ' Mueve el puntero al primer registro de la tabla

rstTableData.MoveFirst ' El primer registro sin indice

MsgBox rstTableData!CompanyName

rstTableData.Index = "City" ' Selecciona el indice City.

rstTableData.MoveFirst „ Mueve el puntero al primer registro.

MsgBox rstTableData!CompanyName rstTableData.Close

Si se utiliza la propiedad Index para un indice que no existe, un error de ejecucion

capturable ocurre. Si se desea ordenar registros de acuerdo a un índice que no existe, se

(16)

puede crear el indice primero o crear un Recordset de tipo dynaset o snapshot, usando una consulta que retorne registros en un orden establecido.

Es importante utilizar la propiedad Index antes de usar el metodo Seek.

Creando un objeto Recordset desde una consulta:

Se puede crear un objeto Recordset basado en una consulta almacenada o no. En el siguiente ejemplo se muestra la lista de productos en una consulta almacenada en la base de datos activa:

Dim dbs As Database, rstProducts As Recordset Set dbs = CurrentDb

Set rstProducts = dbs.OpenRecordset("Current Product List")

Si la consulta almacenada no existe, el metodo OpenRecordset tambien acepta una cadena SQL. El ejemplo anterior puede ser reescrito tal como sigue:

Dim dbs As Database, rstProducts As Recordset Dim strQuerySQL As String

Set dbs = CurrentDb

strQuerySQL = "SELECT * FROM Products WHERE Discontinued = No " _

& "ORDER BY ProductName;"

Set rstProducts = dbs.OpenRecordset(strQuerySQL)

La desventaja de esta última es que la consulta basada en una cadena debe ser compilada cada vez que se ejecuta, mientras que una almacenada solo lo hace la primera vez. Esto mejora el rendimiento.

Cuando se crea un objeto Recordset, usando una cadena SQL o una consulta almacenada, el codigo de la misma no necesita seguir ejecutandose hasta que la consulta retorna la primera fila en el Recordset.

Ordenando y Filtrando Registros:

Si se utiliza un Recordset de tipo “Table” y se utiliza la propiedad Index se puede estar seguro que los registros apareceran en un orden especifico. Sin embargo, usualmente se necesita extraer registros en un especifico orden en otro tipo de Recordset. Por ejemplo, se puede necesitar visualizar las facturas ordenadas por número, o clientes en orden alfabetico.

Para ordenar los registros en un objeto Recordset que no es una tabla, utilice la claúsula Order By en la consulta. Tambien se puede filtrar los datos mediante la utilización de la claúsula Where

El siguiente ejemplo muestra el uso de ámbos:

Dim dbs As Database, rstManagers As Recordset

Set dbs = CurrentDb

(17)

Set rstManagers = dbs.OpenRecordset("SELECT FirstName, LastName FROM " _

& "Employees WHERE Title = 'Sales Manager' ORDER BY LastName")

Una desventaja de ejecutar una consulta SQL en un metodo OpenRecordset es que éste deventaja de ser precompilado cada vez que se ejecuta. Por ende, si la consulta es usada frecuentemente, se obtiene mayor rendimiento creando un procedimiento almacenado usando la misma consulta y abriendo un objeto Recordset cada vez que se requiera la consulta, tal y como se muestra a continuacion:

Dim dbs As Database

Dim rstSalesReps As Recordset Dim qdf As QueryDef

Set dbs = CurrentDb

Set qdf = dbs.CreateQueryDef("SalesRepQuery")

qdf.SQL = "SELECT * FROM Employees WHERE Title = 'Sales Representative';"

Set rstSalesReps = dbs.OpenRecordset("SalesRepQuery")

Para una mayor flexibilidad y control en tiempo de ejecucion se pueden usar parametros para determinar criterio de orden y filtro.

Recreando a consulta desde un objeto Recordset:

Se puede utilizar un objeto Recordset abierto desde un QueryDef creando un objeto de este tipo. Para hacer esto, se debe utilizar el metodo CopyQueryDef. Este es usualmente utilizado en situaciones donde un la variable de un objeto Recordset creado desde un objeto QueryDef es pasado a una funcion y ésta debe recrear el SQL equivalente a la consulta y posiblemente modificarla.

Modificando una Consulta desde un objeto Recordset:

Se puede utilizar el metodo Requery en un Recordset de tipo dynaset o snapshot cuando se requiere ejecutar una consulta cada vez que se cambian los parametros. Esto es más conveniente que abrir un nuevo Recordset y se ejecuta más velozmente.

El siguiente ejemplo crea un objeto Recordset y llama a una funcion que usa el metodo CopyQueryDef para extraer la cadena correspondiente a la consulta SQL. Este entonces dispone al usuario para que pueda utilizar los parametros de la consulta. El codigo usa el metodo Requery para ejecutar la consulta modificada por el usuario:

Sub AddQuery()

Dim dbs As Database Dim qdf As QueryDef

Dim rstSalesReps As Recordset Set dbs = CurrentDb

Set qdf = dbs.CreateQueryDef("SalesRepQuery")

qdf.SQL = "SELECT * FROM Employees WHERE Title = 'Sales Representative'"

set rstSalesReps = qdf.OpenRecordset()

(18)

'Llama a la funcion para agrear el constraint.

AddQueryFilter rstSalesReps

' Retorna a la base de datos original.

dbs.QueryDefs.Delete "SalesRepQuery"

rstSalesReps.Close End Sub

Function AddQueryFilter(rst As Recordset) Dim qdf As QueryDef

Dim strNewFilter As String, strRightSQL As String Set qdf = rst.CopyQueryDef

'"LastName LIKE 'D*'".

strNewFilter = InputBox("Digite nuevo criterio : ") strRightSQL = Right(qdf.SQL, 1)

' Quita caracteres desde el final de la consulta, como sea necesario.

Do While strRightSQL = " " Or strRightSQL = ";" Or strRightSQL = vbCR Or _ strRightSQL = vbLF

qdf.SQL = Left(qdf.SQL, Len(qdf.SQL) - 1) trRightSQL = Right(qdf.SQL, 1)

Loop

qdf.SQL = qdf.SQL & " AND " & strNewFilter & ";"

rst.Requery qdf ' Reconsulta el Recordset.

rst.MoveLast ' llena el Recordset.

' "Lastname LIKE 'D*'" podría retornar 2 registros.

MsgBox "Número de Registros encontrados = " & rst.RecordCount End Function

Para usar el metodo Requery, la propiedad Restartable del objeto Recordset debe estar en True. La propiedad Restartable es simpre True cuando el Recordset es creado desde una consulta. No se puede reiniciar consultas pass-through. Se puede o no tener disponibilidad para reiniciar consultas con tablas ligadas en otro formato de base de datos, sino es la nativa Microsoft Access. Para determinar cuando un objeto puede reejecutar una consulta chequee la propiedad Restartable.

Ordenamiento DAO y propiedades de filtro.

Otra manera de ordenar y filtrar objetos Recordset está para configurar las

propiedades de ordenamiento y filtrado del objeto DAO. Sin embargo, este es usualmente

más lento que incluir un criterio de ordenamiento o filtrado en la consulta original o

cambiando los parametros y ejecutando este de nuevo con el metodo Requery. Las

propiedades de ordenamiento y filtrado de DAO son usualmente utilizadas cuando se

necesitar utilizar un conjunto de resultados para un usuario, pero el origen de los datos no

está disponible para una nueva consulta. Por ejemplo, cuando un objeto Recordset tiene mas

de 100 registros. Usar el metodo CopyQueryDef es preferible para cuando esa cantidad es

inferior.

(19)

Moviendose a traves de objetos Recordset:

Un objeto Recordset usualmente tiene una posición actual, a menudo es un registro.

Cuando se refiere a un campo en el RecordSet, se obtienen valores desde el registro en la posicion actual. Sin embargo la posicion actual puede tambien ser la siguiente o la anterior.

En ciertos casos, la posicion actual es indefinida.

Se puede utilizar los siguientes métodos Move para movilizarse a traves de los registros de un Recordset:

MoveFirst mueve al primer registro.

MoveLast mueve al último registro.

MoveNext mueve al registro próximo.

MovePrevious mueve al registro anterior.

Move [n] mueve n registros hacia delante.

Se pueden usar cualquiera de estos métodos en un Recordset de tipo Table, Dynaset o Snapshot. En el tipo Forward-Only solo se puede usar el MoveNext y se pueden especificar la cantidad de registros que se desea desplazar.

El siguiente ejemplo abre un objeto Recordset utilizando la tabla “Employees”, la cual contiene todos los registros que tienen un valor Null en el campo ReportsToField. La función entonces actualiza los registros para indicar que éstos son empleados temporales.

Para cada registro en el Recordset, el ejemplo cambia los campos Title y Notes y salva los cambios con el método Update. Este usa el método MoveNext para moverse al registro próximo:

Function UpdateEmployees()

Dim dbs As Database, rstEmployees As Recordset, strQuery As String Dim intI As Integer

On Error GoTo ErrorHandler

Set dbs = CurrentDb

' Abre un Recordset con todos los registros desde la tabla Employees ' que tienen un valor Null en el camop ReportsTo.

strQuery = "SELECT * FROM Employees WHERE ReportsTo IS NULL;"

Set rstEmployees = dbs.OpenRecordset(strQuery, dbOpenDynaset)

' Si el Recordset está vacio, sale.

If rstEmployees.EOF Then Exit Function intI = 1

With rstEmployees Do Until .EOF

.Edit

![ReportsTo] = 5

![Title] = "Temporary"

![Notes] = rstEmployees![Notes] & "Temp #" & intI

(20)

.Update .MoveNext intI = intI + 1 Loop

.Close End With ErrorHandler:

Select Case Err Case 0

Exit Function Case Else

MsgBox "Error " & Err & ": " & Error, vbOKOnly, "ERROR"

Exit Function End Select

End Function

Cabe aclarar que este ejemplo es meramente ilustrativo, dado que el método Update funcionaría mejor utilizando una sentencia SQL.

Detectando los límites de un objeto Recordset:

En un objeto Recordset si se intenta mover a una posición que no es la correcta, se produce un error de ejecución. Por ejemplo, si se intenta mover al próximo registro estando en el último o al anterior estando en el primero.

La propiedad EOF indica el fin del archivo y BOF el inicio del mismo. Se puede acceder a estas propiedades para determinar el inicio o final del archivo y asi controlar el movimiento del puntero. En ambos casos se pretende obtener si la propiedad es False o True.

El siguiente ejemplo muestra como utilizar las propiedades BOF y EOF para detectar el inicio y final de un Recordset. Este fragmento de codigo crea un Recordset de tipo table basada en la tabla Orders. Se realizan movimientos a traves de los registros, primero desde el inicio del Recordset hasta el final de la tabla y luego hacia el final.

Dim dbs As Database, rstOrders As Recordset Set dbs = CurrentDb

Set rstOrders = dbs.OpenRecordset("Orders", dbOpenTable)

Do Until rstOrders.EOF .

. ' Manipulación de los datos.

.

rstOrders.MoveNext ' Mueve el puntero al próximo registro.

Loop

rstOrders.MoveLast ' Mueve el puntero al último registro.

' Mientras sea inicio del archivo

(21)

Do Until rstOrders.BOF .

. ' Manipulación de los datos.

' Mueve el puntero al registro anterior.

rstOrders.MovePrevious Loop

rstOrders.Close ' Cierra el Recordset.

Las propiedades BOF y EOF tienen las siguientes características:

Si el Recordset no contiene registros cuando se abre éste, tanto BOF como EOF son True.

Cuando BOF o EOF son True, la propiedad True se mantienen hasta que exista un movimiento hasta un registro existente, asignando False a BOF o EOF.

Cuando BOF o EOF es False, y solo el registro en el Recordset es eliminado, la propiedad devuelve False hasta que se desplaze el puntero hasta otro registro.

En el momento en que se crea o abre un Recordset que contiene más de un registro, el primero de ellos es el registro actual y tanto BOF y EOF son False.

Si el primer registro en el registro actual cuando use el método MovePrevious, BOF es puesto en True. Si se utiliza MovePrevious mientras BOF es True, un error en tiempo de ejecución ocurre.

Similarmente, moviéndose al último registro en el Recordset se cambia el valor de la propiedad EOF a True. Si se utiliza el método MoveNext mientras EOF es True, un error en tiempo de ejecución se presenta.

Contando el número de registros en un objeto Recordset:

Si puede conocer el número de registros en un objeto Recordset. Por ejemplo, si se necesita crear un formulario que muestre cuantos registros existen en cada tabla de la base de datos o los cambios presentados cuando se realizan inclusiones.

La propiedad RecordCount contiene el número de registros en un Recordset tipo tabla o el total de registros accesados en un dynaset o snapshot. Un objeto Recordset sin registros posee la propiedad RecordCount en 0.

El siguiente ejemplo crea un Recordset tipo snapshot y determina el número de registros en el mismo:

Function RecCount(strSQL As String) As Long

Dim rstCount As Recordset, dbs As Database On Error GoTo ErrorHandler

Set dbs = CurrentDb

Set rstCount = dbs.OpenRecordset(strSQL)

If rstCount.EOF Then

(22)

rstCount.Close RecCount = 0 Exit Function Else

rstCount.MoveLast

RecCount = rstCount.RecordCount rstCount.Close

Exit Function End If

ErrorHandler:

Select Case Err Case 0

Exit Function Case Else

MsgBox "Error:" & Err & ":" & Error, vbOKOnly, "ERROR"

Exit Function End Select

End Function

Cuando se eliminan registros en un Recordset tipo dynaset, el valor de RecordCount decrece. Sin embargo, en un ambiente multiusuario, los registros eliminados por otros usuarios no son reflejados en el valor del RecordCount hasta que el registro acutal es posicionado sobre un registro eliminado. Al mismo tiempo la configuración de la propiedad RecordCount es actualizada. Utilizando el método Requery sobre un Recordset, seguido por un metodo MoveLast, configuran la propiedad RecordCount al número total de registros en el Recordset.

Un Recordset tipo snapshot es estático y el valor RecordCount de este no se cambia cuando se agregan o eliminan registros.

Buscando la posición actual en un objeto Recordset:

Dos propiedades están disponibles para indicar la posición actual de un registro:

AbsolutePosition y PercentPosition.

El valor de la propiedad AbsolutePosition es la posición del registro actual relativo a 0. Sin embargo, no se piense como un número de registro; si el registro actual está indefinido, la propiedad AbsolutePosition retorna –1. En consecuencia, esto no significa que el registro tendrá la misma posicion absoluta si el objeto Recordset es recreado, porque el orden de los registros individuales en un Recordset utilizando SQL que incluyan la claúsula Order By cambia dichas posiciones.

La propiedad PercentPosition muestra la posicion actual expresada como un

porcentaje del total de registros indicados en la propiedad RecordCount. Para asegurarse la

correcta asignación del porcentaje referido utilicese los metodos MoveLast y MoveFirst

antes de abrir el Recordset.

(23)

La propiedad PercentPosition es solamente una aproximacion y no debería ser utilizada como un parametro critico. Esta propiedad es mejor para manejar un indicador que marque el progreso en una operación de registros procesados.

El siguiente ejemplo abre un objeto Recordset en una tabla llamada Employees. El procedimiento entonces permite moverse a traves de la tabla y usa la funcion SysCmd para desplegar una barra de progreso, mostrando el porcentaje que ha sido procesada en la tabla.

Si la fecha de nacimiento del empleado es posterior al 1 Enero de 1993, el texto “Senior Staff” es agregado al campo Notes.

Function PercentPos()

Dim dbs As Database, strMsg As String, rstEmployees As Recordset, intRet%

Dim intCount As Integer, strQuery As String, sngPercent As Single Dim varReturn As Variant

Dim lngEmpID() As Long

On Error GoTo ErrorHandler

strQuery = "SELECT * FROM Employees;"

Set dbs = CurrentDb

Set rstEmployees = dbs.OpenRecordset(strQuery, dbOpenDynaset)

With rstEmployees

If .EOF Then ' Si no hay registros, sale.

Exit Function Else

strMsg = "Procesando tabla Employees ..."

intRet = SysCmd(acSysCmdInitMeter, strMsg, 100) End If

Do Until .EOF

If !HireDate < #1/1/93# Then .Edit

!Notes = !Notes & ";" & "Senior Staff"

.Update End If

If .PercentPosition <> 0 Then

intRet = SysCmd(acSysCmdUpdateMeter, .PercentPosition) End If

.MoveNext Loop

.Close End With

intRet = SysCmd(acSysCmdRemoveMeter)

ErrorHandler:

Select Case Err

Case 0

(24)

Exit Function Case Else

MsgBox "Error " & Err & ": " & Error, vbOKOnly, "ERROR"

' limpia la métrica de progreso.

varReturn = SysCmd(acSysCmdSetStatus, " ") Exit Function

End Select End Function

Buscando un registro específico:

Muchas veces se desea encontrar un registro particular de un empleado, por ejemplo, basados en el código del mismo, o todos los detalles que se especifican para una determinada orden. En estos casos, se puede realizar una búsqueda utilizando los métodos Find y Seek.

Se puede utilizar el metodo Seek con tipos de Recordset Tables y el método Find con dynaset y snapshot. Forward-Only no soporta el uso de Seek o cualquiera de los Find.

Buscando un registro en un Recordset tipo Table:

Se puede utilizar el metodo Seek para localizar registros en un Recordset tipo Table.

Cuando se usa el método Seek para localizar un registro, el motor de base de datos Microsoft Jet usa los indices de la tabla, definidas por la propiedad Index.

Si se utiliza el método Seek en un Recordset tipo table, sin haber habilitado el indice primero, ocurre un error en tiempo de ejecucion.

La sintaxis para el método Seek es el siguiente:

table.Seek comparison, key1, key2 ...

El argumento table es el Recordset tipo table utilizado.

El argumento comparación es una cadena que determina la clase de comparacion que esta siendo aplicada. La siguiente tabla lista las cadenas de comparacion que se pueden utilizar con el método Seek.

Cadena de comparación Description

"=" Igual al valor especificado

">=" Mayor o igual al valor especificado

">" Mayor al valor especificado

"<=" Menor o igual al valor especificado

"<" Menor al valor especificado

(25)

El argumento Keyn son una serie de uno o más valores que corresponden al campo o campos que inicializan el indice actual del Recordset. Microsoft Jet compara estos valores con los valores en los campos correspondientes del Recordset.

El ejemplo siguiente abre un Recordset tipo table llamada Employees y utiliza el metodo Seek para localizar el record conteniendo el valor de IngEmpID en el campo EmployeeID. Este returna la fecha de nacimiento del empleado referido:

Function intGetHireDate(lngEmpID As Long, varHireDate As Variant) As Integer Dim rstEmployees As Recordset, dbs As Database

Const conFilePath$ = "C:\Program Files\Microsoft _ Office\Office\Samples\"

On Error GoTo ErrorHandler

Set dbs = OpenDatabase(conFilePath & "Northwind")

Set rstEmployees = dbs.OpenRecordset("Employees", dbOpenTable)

rstEmployees.Index = "PrimaryKey" 'Nombre del indice para Employee ID.

rstEmployees.Seek "=", lngEmpID

If rstEmployees.NoMatch Then varHireDate = Null

'La constante conErrNoMatch, conSuccess, y conFailed están definidos 'en el nivel de módulo como una constante publica con valores enteros 'entre -32,761, 0, y -32,737 respectivamente.

intGetHireDate = conErrNoMatch Exit Function

Else

varHireDate = rstEmployees!HireDate intGetHireDate = conSuccess

Exit Function End If

ErrorHandler:

Select Case Err Case 0

Exit Function Case Else

varHireDate = Null

intGetHireDate = conFailed

MsgBox "Error " & Err & ": " & Error, vbOKOnly, "ERROR"

Exit Function End Select

End Function

El metodo Seek siempre inicia buscando registros desde el principio del Recordset.

Se puede utilizar la propiedad NoMatch en el Recordset para comprobar si el registro buscado no fue encontrado, mediante examinación del valor True o False.

El siguiente ejemplo ilustra como se puede crear una función que utilice el método Seek para localizar un registro utilizando un indice de multiples campos:

Function GetFirstPrice(lngOrderID As Long, lngProductID As Long) As Variant

Dim dbs As Database, rstOrderDetail As Recordset

(26)

On Error GoTo ErrorHandler Set dbs = CurrentDb

Set rstOrderDetail = dbs.OpenRecordset("Order Details", dbOpenTable) rstOrderDetail.Index = "PrimaryKey"

rstOrderDetail.Seek "=", lngOrderID, lngProductID If rstOrderDetail.NoMatch Then

GetFirstPrice = Null

MsgBox "No se encontró el registro..."

Else

GetFirstPrice = rstOrderDetail!UnitPrice End If

rstOrderDetail.Close

ErrorHandler:

Select Case Err Case 0

Exit Function Case Else

MsgBox "Error " & Err & ": " & Error, vbOKOnly, "ERROR"

Exit Function End Select

End Function

En este ejemplo, la llave primaria de la tabla consiste en dos campos: OrderID y ProductID. Cuando llama a la función GetFirstPrice con una combinación válida de campos para OrderID y ProductID, la función retorna el precio unitario desde el registro encontrado.

Si no se encuentra la combinación de valores de campo la función retorna un valor Null.

Buscando un registro en tipos de Recordset Dynaset- o Snapshot:

Se puede utilizar el método Find para localizar un registro en un Recordset tipo Dynaset o Snapshot. DAO provee cuatro metodos para lo anterior:

FindFirst : busca el primer registro que satisface el criterio de búsqueda.

FindLast : busca el último registro que satisface el criterio de búsqueda.

FindNext: busca el próximo que satisface el criterio de búsqueda.

FindPrevious : busca el registro que satisface el criterio de búsqueda.

Nota: Para localizar un registro en un Recordset tipo table, debe utilizarse el método Seek, descrito anteriormente.

Cuando se utilice el metodo Find desde especificarse el criterio de busqueda;

tipicamente es una expresion con un nombre de campo con un valor especifico.

Se pueden localizar los registros buscados en orden último, anterior o siguiente,

utilizando los métodos FindLast, FindPrevious y FindNext.

(27)

DAO almacena True en la propiedad NoMatch cuando un metodo Find falla y el registro actual yace indefinido. Para retornar al registro actual debe utilizarse el metodo bookmark.

El ejemplo siguiente muestra como se puede utilizar el método FindNext para encontrar todas las ordenes en la tabla Orders que tiene los registros que no corresponden en la tabla Order Details y agrega los valores en el campo OrderID al arreglo IngOrderID():

Function FindEx(lngOrderID() As Long)

Dim dbs As Database, rstOrders As Recordset

Dim strQuery As String, rstOrderDetails As Recordset Dim intIndex As Integer

On Error GoTo ErrorHandler Set dbs = CurrentDb

'Abre un recordset con los registros de las tablas 'orders y Order Details.

'Si éstas no contienen registros sale.

strQuery = "SELECT * FROM Orders ORDER BY OrderID;"

Set rstOrders = dbs.OpenRecordset(strQuery, dbOpenSnapshot) If rstOrders.EOF Then Exit Function

strQuery = "SELECT * FROM [Order Details] ORDER BY OrderID;"

Set rstOrderDetails = dbs.OpenRecordset(strQuery, dbOpenSnapshot)

' Para el primer registro en Orders, encuentra el primer registro.

' en OrderDetails. Si no no encuentra, redimensiona el arreglo de order IDs ' y agrega el order ID al arreglo.

rstOrderDetails.FindFirst "OrderID = " & rstOrders![OrderID]

If rstOrderDetails.NoMatch Then

ReDim Preserve lngOrderID(1 To intIndex) lngOrderID(intIndex) = rstOrders![OrderID]

End If

' La primera búsqueda ha sido exitosa, entonces usa FindNext para encontrar ' próximo registro que satisfaga el criterio de búsqueda.

intIndex = 0

Do Until rstOrders.EOF

rstOrderDetails.FindNext "OrderID = " & rstOrders![OrderID]

If rstOrderDetails.NoMatch Then intIndex = intIndex + 1

ReDim Preserve lngOrderID(1 To intIndex) lngOrderID(intIndex) = rstOrders![OrderID]

End If

rstOrders.MoveNext Loop

ErrorHandler:

Select Case Err Case 0

Exit Function

(28)

Case Else

MsgBox "Error " & Err & ": " & Error, vbOKOnly, "ERROR"

Exit Function End Select

End Function

Si la búsqueda de registros es frecuente en un Recordset tipo dynaset, se pueden encontrar éstos facilmente creando una tabla indexada temporal y usar el método Seek.

Marcando la posición de un registro con Bookmarks:

Un bookmark es un sistema generado que identifica univocamente a cada registro. La propiedad bookmark de DAO en un Recordset cambia cada vez que se mueve a un nuevo registro. Para identificar un registro, se marca el registro actual con Bookmark en una variable tipo Variant. Para retornar a éste registro, asignele al bookmark el valor de esta variable.

El siguiente ejemplo ilustra como se puede usar bookmark para salvar la posicion actual del registro. Se pueden realizar otras operaciones sobre el recordset y posteriormente regresar al registro marcado.

Function BookMarkEx() As Integer

Dim dbs As Database, rstProducts As Recordset Dim vBookMark As Variant, sngRevenue As Single

Dim strQuery As String, rstCategories As Recordset, strCriteria As String On Error GoTo ErrHandler

BookMarkEx = 0

strQuery = "SELECT * FROM Products WHERE UnitsOnOrder >= 40 _ ORDER BY " _

& "CategoryID, UnitsOnOrder DESC;"

Set dbs = CurrentDb

Set rstProducts = dbs.OpenRecordset(strQuery, dbOpenSnapshot)

Set rstCategories = dbs.OpenRecordset("SELECT CategoryID FROM " _ & "Categories ORDER BY CategoryID;", dbOpenSnapshot) If rstProducts.NoMatch Then Exit Function

' Por cada categoría encontrada el producto genera el ingreso mínimo ' y el producto de mayor precio.

Do Until rstCategories.EOF

strCriteria = "CategoryID = " & rstCategories![CategoryID]

rstProducts.FindFirst strCriteria

sngRevenue = rstProducts![UnitPrice] * rstProducts![UnitsOnOrder]

If Not rstProducts.NoMatch Then

'Inicializa el bookmark en el primer registro conteniendo la

(29)

'CategoryID.

vBookMark = rstProducts.Bookmark 'Buscar el producto generando el de mayor precio

Do While rstProducts![CategoryID] = rstCategories![CategoryID]

If rstProducts![UnitPrice] * rstProducts![UnitsOnOrder] > sngRevenue Then sngRevenue = rstProducts![UnitPrice] * _

rstProducts![UnitsOnOrder]

End If

rstProducts.MoveNext

Loop

' Se mueve al primer registro que contiene el campo CategoryID.

rstProducts.Bookmark = vBookMark

sngRevenue = rstProducts![UnitPrice] * _ rstProducts![UnitsOnOrder]

' Encuentra el producto, generando el de menor precio/ingreso.

Do While rstProducts![CategoryID] = rstCategories![CategoryID]

If rstProducts![UnitPrice] * rstProducts![UnitsOnOrder] < sngRevenue Then sngRevenue = rstProducts![UnitPrice] * rstProducts![UnitsOnOrder]

End If

rstProducts.MoveNext Loop

End If

rstCategories.MoveNext Loop

' Error Handler.

ErrHandler:

Select Case Err Case 0

Exit Function Case Else

MsgBox "Error " & Err & ": " & Error, vbOKOnly, "ERROR"

Exit Function End Select

End Function

Un “bookmark” es particularmente útil si un método falla, por que la posición actual del registro se pierde.

La propiedad LastModified del objeto Recordset clarifica el como usar el bookmark.

Esta propiedad retorna el bookmark del ultimo registro en el Recordset a ser añadido o modificado. Para usar este, se debe configurar la propiedad Bookmark de DAO para que sea igual a la propiedad LastModified, tal y como se muestra a continuación:

RstClientes.BookMark = rstClientes.LastModified

(30)

Lo anterior mueve el registro actual hasta el último que fue agregado o modificado.

Esto es particularmente útil cuando se agregan nuevos registros, por que después de hacerlo el registro actual es el que se añadió. Con la propiedad LastModified, se puede mover al registro recién agregado.

Cuando usted cierra un objeto Recordset, cualquier bookmarks que haya salvado se invalida. No se puede usar un bookmark de un Recordset en otro. Sin embargo, puede usarse como en el siguiente ejemplo:

Dim dbs As Database

Dim rstOriginal As Recordset, rstDuplicate As Recordset Dim strPlaceholder As String

Set dbs = CurrentDb ' Crea el primer Recordset.

Set rstOriginal = dbs.OpenRecordset("Orders", dbOpenDynaset)

' Guarda la posición del registro actual strPlaceholder = rstOriginal.Bookmark

' Crea un Recordset duplicado.

Set rstDuplicate = rstOriginal.Clone()

' Se desplaza al mismo registro.

rstDuplicate.Bookmark = strPlaceholder

rstOriginal.Close

Que objetos Recordset no soportan Bookmarks?

Los Recordset de tipo Dynaset basados en ciertas tablas ligadas, como tablas Paradox que no tienen llaves primarias no soportan bookmarks. Se puede determinar si un objeto Recordset soporta o no bookmarks chequeando el valor de la propiedad bookmarkable, tal y como se muestra en el ejemplo siguiente:

If rstLinkedTable.Bookmarkable Then

MsgBox "Esta tabla soporta bookmarks."

Else

MsgBox "Esta tabla no soporta bookmarks."

End If

Cambiando datos:

Despues que se crea un Recordset tipo table o dynaset, se pueden modificar, eliminar o agregar nuevos registros. Lo anterior no se puede realizar si el Recordset es snapshot, o forward-only.

Usando consultas parametrizadas:

(31)

Una consulta parametrizada es aquella que cuando se ejecuta despliega una caja de diálogo que le indica al usuario que debe digitar información, como por ejemplo un criterio para la búsqueda de registros o valores para insertar en un campo. Se pueden utilizar procedimientos almacenados para brindar procesos de mantenimiento de bases de datos o para recuperar consultas de uso intensivo.

Para crear un procedimiento o consulta almacenada deben realizarse los siguientes pasos:

 Cree una consulta almacenada, especificando los parámetros que el usuario necesita proveer.

 Cuando se abre un Recordset utilizando esta consulta, la aplicación abre una caja de diálogo que solicita al usuario los valores para los parámetros establecidos en la consulta.

El siguiente ejemplo toma dos cadenas que representan fechas y crea una consulta parametrizada que retorna todos aquellos registros en la tabla Orders cuyo campo Order Date esté entre las dos fechas. Este añade todos los valores del campo OrderId retraido en la consulta y los almacena en un arreglo:

Function OrdersFromTo(strDateFrom As Variant, strDateTo As Variant, _ lngOrderIDs() As Long)

Dim dbs As Database, rstOrders As Recordset

Dim qdf As QueryDef, strSQL As String, intI As Integer

On Error GoTo ErrorHandler

Set dbs = CurrentDb

strSQL = "PARAMETERS [DateFrom] DateTime, [DateTo] DateTime; "

strSQL = strSQL & "SELECT * FROM Orders WHERE OrderDate BETWEEN

"

strSQL = strSQL & "[DateFrom] AND [DateTo];"

' Crea una consulta almacenada parametrizada.

Set qdf = dbs.CreateQueryDef("", strSQL)

' configura los parámetros de la consulta.

qdf.Parameters("DateFrom") = strDateFrom qdf.Parameters("DateTo") = strDateTo

'Abre un Recordset forward-only snapshot.

Set rstOrders = qdf.OpenRecordset(dbOpenSnapshot, dbForwardOnly)

' Carga en un arreglo todos los registros del campo OrderIDs ' obtenidos en la consulta

intI = 1

While rstOrders.EOF = False

ReDim lngOrderIDs(1 To intI)

Referencias

Documento similar

• Ello permite plantear una primera etapa de normalización de los sistemas de clasificación, al proveer al Ayuntamiento de un marco general que abarque toda su

Primeros ecos de la Revolución griega en España: Alberto Lista y el filohelenismo liberal conservador español 369 Dimitris Miguel Morfakidis Motos.. Palabras de clausura

[r]

[r]

SECUNDARIA COMPRENDE LOS

En una perspectiva más sosegada, el problema central para la ética del mundo tecnológico consiste en preservar, por un lado, la fuerza civilizatoria de emanci- pación social y

1. LAS GARANTÍAS CONSTITUCIONALES.—2. C) La reforma constitucional de 1994. D) Las tres etapas del amparo argentino. F) Las vías previas al amparo. H) La acción es judicial en