INSTITUTO SUPERIOR TECNOLÓGICO NORBERT...

82
INSTITUTO SUPERIOR TECNOLÓGICO NORBERT WIENER Manual del Alumno ASIGNATURA: Lenguaje de Programación II (Visual Basic II) PROGRAMA: S3C LIMA-PERU

Transcript of INSTITUTO SUPERIOR TECNOLÓGICO NORBERT...

Page 1: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

INSTITUTO SUPERIOR TECNOLÓGICO

NORBERT WIENER

Manual del Alumno

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

PROGRAMA: S3C

LIMA-PERU

Page 2: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 3: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 4: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 5: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 6: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 7: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 8: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 9: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 10: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 11: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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:

Page 12: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 13: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 14: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 15: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 16: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 17: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 18: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 19: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 20: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 21: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 22: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 23: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 24: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 25: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 26: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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.

Page 27: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 28: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 29: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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

Page 30: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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:

Page 31: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

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)

Page 32: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

32

lngOrderIDs(intI) = rstOrders!OrderID

intI = intI + 1

rstOrders.MoveNext

Wend

ErrorHandler:

Select Case Err

Case 0

Exit Function

Case Else

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

Exit Function

End Select

End Function

Para más información veáse en la ayuda: “parameter queries.”

Marcando cambios Bulk:

Muchos de los cambios que se pueden realizar en una base de datos pueden

eficientizarse utilizando consultas definidas. El ejemplo siguiente crea un objeto QueryDef

para actualizar la tabla Employees:

Dim dbs As Database, qdfChangeTitles As QueryDef

Set dbs = CurrentDb

Set qdfChangeTitles = dbs.CreateQueryDef("")

qdfChangeTitles.SQL = "UPDATE Employees SET Title = 'Account Executive' " _

& "WHERE Title = 'Sales Representative';"

qdfChangeTitles.Execute dbFailOnError ' llama a la consulta.

Se puede reemplazar toda la cadena SQL en este ejmplo con una consulta almacenada

parametrizable. El siguiente ejemplo muestra como el código anterior puede ser reescrito

como una consulta almacenada y no como consulta definida:

Dim dbs As Database, qdfChangeTitles As QueryDef

Dim strSQLUpdate As String, strOld As String

Dim strNew As String

Set dbs = CurrentDb

strSQLUpdate = "PARAMETERS [Old Title] Text, [New Title] Text; " _

& "UPDATE Employees SET Title = [New Title] WHERE Title = [Old

Title];"

' Crea el objeto QueryDef.

Set qdfChangeTitles = dbs.CreateQueryDef("", strSQLUpdate)

Page 33: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

33

' Solicita al usuario el valor anterior.

strOld = InputBox("Digite el puesto anterior")

' Solicita al usuario el nuevo valor.

strNew = InputBox("Digite el nuevo puesto")

' Configura los parametros.

qdfChangeTitles.Parameters("Old Title") = strOld

qdfChangeTitles.Parameters("New Title") = strNew

' Invoca la consulta.

qdfChangeTitles.Execute

Nota: una consulta de eliminación en más eficiente que el código que busca ciclicamente a

través de un conjunto de registros, especialmente con bases de datos creadas con Access para

Windows 95 o superior.

Modificando un registro existente:

Se pueden modificar registros existentes en un Recordset tipo table o dynaset usando

los métodos Edit y Update.

Para modificar un registro existente en un Recordset table o dynaset:

1. Localizar el registro que se quiere modificar.

2. Use el método Edit para preparar el registro actual para edición.

3. Realice los cambios necesarios al registro.

4. Use el método Update para salvar los cambios hechos.

El siguiente ejemplo ilustra como cambiar el título del puesto para todos los

representantes de ventas contenidos en una tabla llamada Employees.

Dim dbs As Database, rstEmployees As Recordset

Set dbs = CurrentDb

Set rstEmployees = dbs.OpenRecordset("Employees")

rstEmployees.MoveFirst

Do Until rstEmployees.EOF

If rstEmployees!Title = "Sales Representative" Then

rstEmployees.Edit

rstEmployees!Title = "Account Executive"

rstEmployees.Update

End If

rstEmployees.MoveNext

Page 34: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

34

Loop

rstEmployees.Close

Es importante notar que si se utiliza el método Edit antes que se realicen los cambios

ocurre un error de ejecución. Si se edita el registro actual y entonces se mueve el puntero de

registros o se cierra el Recordset sin haber primeramente ejecutado un metodo Update, los

cambios realizados no surtirán efecto.

Se puede finalizar el método Edit y cualquier otra transacción pendiente sin salvar los

cambios utilizando el método CancelUpdate.

Actualizaciones inconsistentes:

Un Recordset tipo dynaset puede estar basados en una consulta de múltiples tablas con

una relación tipo uno a muchos. Por ejemp.lo, supongase que se desea crear una consulta de

múltiples tablas que combinan campos de las tablas Orders y Order Details. Generalmente

hablando no se pueden cambiar valores en la tabla Orders por que están subordinados a los

valores Order Details. Los cambios en estos casos tienen que realizarse en ámbas tablas para

que no se presenten inconsistencias. En tal caso puede utilizarse la constante dbInconsistent

del método OpenRecordset para crear un dynaset inconsistente.

Por ejemplo: Set rstTotalSales = dbs.OpenRecordset("Sales Totals" ,, _ dbInconsistent)

Cuando se actualiza un dynaset inconsiste, se puede facilmente destruir la integridad

referencial de los datos en el dynaset. Por ende, debe procurarse realizar los cambios en

todas aquellas tablas que mantengan esta integridad referencial.

La constante dbInconsisten está disponible solo para los objetos Recordset de tipo

dynaset. Este es ignorado para los de tipo table, snapshot y forward-only.

Elimimando un registro existente:

Se puede eliminar un registro existente en un Recordset de tipo table o dynaset

utilizando el método Delete. No se pueden eliminar registros de un snapshot.

El ejemplo siguiente muestra como eliminar todos los registros duplicados en la tabla

Shippers:

Function DeleteDuplicateShippers() As Integer

Dim rstShippers As Recordset, strQuery$, dbs As Database, strName$

On Error GoTo ErrorHandler

strQuery = "SELECT * FROM Shippers ORDER BY CompanyName;"

Set dbs = CurrentDb

Set rstShippers = dbs.OpenRecordset(strQuery, dbOpenDynaset)

' Si no hay registros en la tabla Shippers table, sale.

Page 35: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

35

If rstShippers.EOF Then Exit Function

strName = rstShippers![CompanyName]

rstShippers.MoveNext

Do Until rstShippers.EOF

If rstShippers![CompanyName] = strName Then

rstShippers.Delete

Else

strName = rstShippers![CompanyName]

End If

rstShippers.MoveNext

Loop

ErrorHandler:

Select Case Err

Case 0

' La constante conSuccess y conFailed son definidas en

' el nivel de módulo como constante pública con valor entero.

' con valores de 0 y -32,737 respectivamente.

DeleteDuplicateShippers = conSuccess

Exit Function

Case Else

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

DeleteDuplicateShippers = conFailed

Exit Function

End Select

End Function

Cuando se usa el metodo Delete, Microsoft Jet inmediatamente elimina el registro

actual (después de ejecutar la búsqueda, por supuesto), sin presentar ninguna advertencia al

respecto. Si se elimina el registro actual el motor no provee un desplazamiento automático al

siguiente o al registro anterior en el Recordset, por tanto debe utilizarse el método MoveNext

para realizarlo.

Si se intenta accesar un registro previamente eliminado en el Recordset tipo table se

puede presentar una condición de error: 3167 “Registro eliminado”. En un dynaset se puede

obtener el error 3021 “No registro actual”.

Agregando un nuevo registro:

Se puede agregar un nuevo registro a un Recordset tipo table o dynaset utilizando el

método AddNew.

Para agregar un nuevo registro a un Recordset table o dynaset:

1. Use el método AddNew para crear un nuevo registro.

2. Asigne valores para cada campo del registro.

3. Use el método Update para guardar los datos o CancelUpdate para cancelar.

Page 36: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

36

El siguiente ejemplo agrega un nuevo registro en el Recordset tipo tabla de nombre

rstShippers:

Dim dbs As Database, rstShippers As Recordset

Set dbs = CurrentDb

Set rstShippers = dbs.OpenRecordset("Shippers")

rstShippers.AddNew

rstShippers!CompanyName = "Global Parcel Service"

.

. ' Set remaining fields.

.

rstShippers.Update

rstShippers.Close

Cuando se utiliza el método AddNew, Microsoft Jet prepara un nuevo registro en

blanco y lo habilita como el registro actual. Si se añade un registro a un Recordset de tipo

dynaset este nuevo registro aparece al final del Recordset. Para forzarlo a que aparezca en la

posición adecuada de un ordenamiento se debe recrear el Recordset mediante el método

Requery. Si se agrega un registro a un Recordset tipo table, el registro aparece posicionado

de acuerdo al indice actual, o al final de la tabla si no hay un índice abierto.

Transacciones Microsoft Jet:

Una transacción es un conjunto de operaciones realizadas que son tratadas como una

sola unidad de trabajo. El trabajo en una transacción pueden ser completadas como un todo;

si una parte de la misma falla toda la transacción falla. Las transacciones ofrecen al

desarrollador de software la posibilidad para reforzar la integridad de la informacion.

Cuando múltiples tablas son involucradas en procesos de actualización, por ejemplo, pueden

surgir fallas que pueden crear inconsistencias peligrosas de información.

El ejemplo más común de transacciones son las que atañen a la automatización

bancaria de algunos procesos, Automated Teller Machine (ATM). El proceso de dispensar

dinero y el débito y crédito de cuentas son consideradas una unidad lógica de trabajo y que

son tratadas como una transacción: el dinero no puede ser dispensado sin que el sistema esté

disponible para realizar el débito de la cuenta.

Utilizando Transacciones en aplicaciones:

Microsoft Jet soporta transacciones a traves de DAO: BeginTrans, CommitTrans y

Rollback. La sintaxis básica de estos métodos se muestran en la siguiente tabla:

Método Operación

Workspace.BeginTrans Inicia la transacción

Workspace.CommitTrans Después de la transacción escribe y actualiza permanente a los

objetos relacionados en la base de datos.

Page 37: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

37

Workspace.Rollback Cancela las transacciones, por error o por decisión del usuario.

El siguiente ejemplo cambia los títulos de oficio de todos los representantes de ventas

en la tabla Employees de la base de datos Northwind. Después del método BeginTrans

inicia una transacción que realiza los cambios respectivos en la tabla Employees, el método

CommitTrans guarda los cambios realizados. Se puede utilizar el método Rollback para

cancelar los cambios realizados con el Update y restaurar la tabla a su estado original.

Sub ChangeTitle()

Dim dbsSales As Database

Dim rstEmp As Recordset

Dim wrkCurrent As Workspace

Set wrkCurrent = DBEngine.Workspaces(0)

Set dbsSales = OpenDatabase("Northwind.mdb")

Set rstEmp = dbsSales.OpenRecordset("Employees", dbOpenTable)

wrkCurrent.BeginTrans

Do Until rstEmp.EOF

If rstEmp!Title = "Sales Representative" Then

rstEmp.Edit

rstEmp!Title = "Sales Associate"

rstEmp.Update

End If

rstEmp.MoveNext

Loop

If MsgBox("Guarda todos los cambios?", vbQuestion + vbYesNo) = vbYes Then

wrkCurrent.CommitTrans

Else

wrkCurrent.Rollback

End If

rstEmp.Close

dbsSales.Close

End Sub

Cuando se utilizan transacciones, todas las bases de datos y los objetos Recordset en el

Workspace especificado son afectados. Esto es, las transacciones afectan al workspace

global no a una base de datos o recordset específico. Asimismo, los métodos asociados

tienen su incidencia a traves de todo el workspace: CommitTrans y Rollback.

Nota: Se pueden utilizar los métodos BeginTrans, CommitTrans y Rollback con el objeto

DBEngine. En este caso, la transacción es aplicada al workspace por defecto, como:

DBEngine.Workspaces(0).

Manejando Transacciones:

Microsoft Jet utiliza algoritmos sofisticados para proveer transacciones seguras y

confiables.

Page 38: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

38

Tamaño de transacciones:

El tamaño de las transacciones que se pueden realizar con Visual Basic, utilizando el

motor Jet, está limitada únicamente por la cantidad física de espacio en el disco duro en que

se realicen. Esto es, Microsoft Jet puede almacenar una cantidad de transacciones tan grande

como lo sea el medio de almacenamiento donde se realice. Si por ejemplo, en la ejecución

de una transacción se agota el espacio físico en disco se produce un error interceptable

(2004) y reacciona de acuerdo al código de la aplicación. El caso es que si la aplicación

realiza el commit después de ocurrido este error, es factible que Microsoft Jet no pueda

regenerar la base de datos por tanto no se puede determinar el número de registros afectados

(olvidemos el dbrecordaffected), poniendo a esta en un estado inconsistente. Si por el

contrario, se realiza un rollback de los cambios la base de datos queda en su estado original.

Niveles Transaccionales:

Se pueden tener hasta 5 niveles de transacciones activas al mismo tiempo. Esto es, se

pueden crear hasta 5 niveles transaccionales en una misma ejecución. Si se desea tener

transacciones con “overlapping”, “nonnested scopes” se pueden abrir objetos workspace

adicionales y manejar dichas transaccionales en dichos workspaces.

Cuando una transacción es “Rolled Back” por el motor de bases de datos Jet:

Si se cierra un objeto Workspace, cualquier transacción es automaticamente “Rolled

Back”. Microsoft Jet nunca realiza un Commit automáticamente sin haberla iniciado.

Asimismo, cuando se cierra una base de datos, variables atinentes o transacciones sin

committ sufren el mismo efecto.

Transacciones en origenes de datos externos:

Las transacciones no son soportadas en origenes de datos externas ( a excepción de

datos mediante ODBC). Por ejemplo, si la base de datos tiene ligas a tablas de FoxPro® o

dBASE®, las transacciones a estos objetos son ignorados. Para determinar o no si una base

de datos u objeto Recordset soporta transacciones se puede chequear el valor de la propiedad

Transactions. Un valor True indica que si lo soporta.

Transacciones y rendimiento:

En versiones anteriores de Microsoft Access era generalmente recomendado que se

usaran transacciones como un factor de mejoramiento en el rendimiento de aplicaciones.

Hoy día todas las transacciones para DAO (agregación, modificación y eliminación) son

mejoradas en su rendimiento internamente y automaticamente. En muchas situaciones, este

soporte automático provee a las aplicaciones el mejor rendimiento posible. Sin embargo,

muchas veces se debe recurrir a configurar algunas variables en el registro de Windows para

mejorar en este aspecto.

Page 39: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

39

Extrayendo Datos desde un registro:

Después de que se ha localizado un registro particular, se puede necesitar extraer datos

para usar en un aplicación, sea quiza para modificarlo.

Copiando un campo simple:

Se puede copiar un campo simple de un registro a una variable del tipo apropiado. El

ejemplo siguiente extrae tres campos del primer registro del objeto Recordset:

Dim dbs As Database, rstEmployees As Recordset

Dim strFirstName As String, strLastName As String

Dim strTitle As String

Set dbs = CurrentDb

Set rstEmployees = dbs.OpenRecordset("Employees")

rstEmployees.MoveFirst

strFirstName = rstEmployees!FirstName

strLastName = rstEmployees!LastName

strTitle = rstEmployees!Title

rstEmployees.Close

Copiando registros completos en un arreglo:

Para copiar uno o más registros completos, se puede crear un array bidimensional y

copiar los registros en él. Se incrementa el primer parámetro por cada campo y el segundo

por cada registro.

Una via rápida para hacer esto es con el método GetRows. El método GetRows retorna

un arreglo bidimensional. El primer parámetro identifica el campo y el segundo el número

de fila, tal y como se muestra en el ejemplo siguiente:

varRecords(intField, intRecord)

El siguiente ejemplo utiliza una sentencia SQL para extraer tres campos desde una tabla

llamada Employees y los coloca en un objeto Recordset. Este entonces utiliza el método

GetRows para extraer los primeros tres registros del Recordset y almacena los registros

seleccionados en un arreglo bidimensional. Imprime entonces cada registro, campo por

campo, usando los dos arreglos indexados para seleccionar campos especificos y registros.

Para aclarar este punto se ilustra como los arreglos indexados son utilizados. El

ejemplo utiliza una sentencia separada para identificar e imprimir cada campo de cada

registro. En la práctica, es mejor utilizar dos ciclos, uno en el otro, y proveer variables

enteras para los indices que navegan en ambas dimensiones del arreglo:

Page 40: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

40

Sub GetRowsTest()

Dim dbs As Database

Dim rstEmployees As Recordset

Dim varRecords As Variant

Dim intNumReturned As Integer

Dim intNumColumns As Integer

Dim intColumn As Integer, intRow As Integer

Set dbs = CurrentDb

Set rstEmployees = dbs.OpenRecordset("SELECT FirstName, LastName, Title" _

& " FROM Employees", dbOpenSnapshot)

varRecords = rstEmployees.GetRows(3)

intNumReturned = UBound(varRecords, 2) + 1

intNumColumns = UBound(varRecords, 1) + 1

For intRow = 0 To intNumReturned - 1

For intColumn = 0 To intNumColumns - 1

Debug.Print varRecords(intColumn, intRow)

Next intColumn

Next intRow

rstEmployees.Close

End Sub

Se puede utilizar subsecuentes llamadas al método GetRows si hay más registros

disponibles.

Usando Consultas sumarizadas:

Se puede sumarizar datos utilizando las claúsulas GROUP BY y HAVING. GROUP

BY organiza los datos dentro de grupos; HAVING configura condiciones de grupos para

incluir en el resultado. Estas claúsulas pueden estar juntas, HAVING usada sin GROUP BY

puede producir resultados confusos.

Usando Eventos del Control Data:

Tres eventos se pueden utilizar en aplicaciones de bases de datos, utilizando Visual

Basic: Validate, Error y Reposition.

Evento Validate:

Este evento se utiliza para comprobar los datos del RecordSet antes de guardar el

registro en la base de datos. Este evento se produce antes de que Visual Basic escriba los

datos en la base de datos. Es útil para solicitar al usuario confirme los cambios a realizar en

la base de datos.

La sintaxis de este evento es la siguiente:

Private Sub Data1_Validate (index As Integer, action As Integer, save As Integer)

El argumento action indica la operación que provocó el evento Validate. Este evento

es producto de realizar las siguientes operaciones: MoveFirst, MovePrevious, MoveNext,

Page 41: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

41

MoveLast, AddNew, Update, Delete, Find, establecer la propiedad BookMark, cerrar la

base de datos, descargar el formulario. Para cancelar cualquiera de estas acciones, se debe

asignarsele vbDataActionCancel al argumento action.

El argumento save indica si va a guardarse o no el registro. Si save es True, los datos

enlazados han cambiado. Para cancelar la acción de guardar puede asignarse False al

argumento save.

El código siguiente solicita al usuario que confirme los cambios realizados en la base

de datos. Si el usuario indica que no, los cambios se cancelarán automáticamente:

Private Sub Data1_Validate (Action As Integer, Save As Integer)

Dim Respuesta As Integer

If Save = True Then

Respuesta = MsgBox ("¿Guardar cambios?", vbYesNo)

If Respuesta = vbNo Then

Save = False

Data1.UpdateControls ' Actualiza campos.

End If

End If

End Sub

Evento Reposition:

El evento Reposition se utiliza para modificar la apariencia de un formulario o realizar

una acción necesaria cuando se desplace a un nuevo registro. Esto se realiza cuando Visual

Basic se desplaza a otro registro o cuando se abre la base de datos.

Se puede variar la apariencia de un formulario mostrando información sobre cuántos

registros se encuentran en el Recordset activo. Para ello, debe utilizarse la propiedad

AbsolutePosition. El código siguiente ilustra como demostrar lo anterior:

Private Sub Data1_Reposition()

Data1.Caption = "Número de registro " & _

Data1.Recordset.AbsolutePosition + 1

End Sub

Evento Error:

Este evento se ejecuta cuanto el usuario interactua con el control data y se produce un

error de acceso a datos. En este caso debe agregarse una rutina personalizada de tratamiento

de errores.

Los valores contenidos en objetos enlazados a datos no cambian cuando se produce un

error. Puede asignar el valor 0 al argumento Response para que no se muestre el mensaje de

error. El siguiente ejemplo muestra lo anterior:

Page 42: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

42

Private Sub Data1_Error(DataErr As Integer, Response As Integer)

If DataErr = 3022 Then 'Error de clave duplicada

MsgBox "Escriba un número de Id. de empleado único"

txtEmpID.SetFocus

Response = 0

Else

Response = 1 'muestra el mensaje de error estándar

End If

End Sub

Enlazando datos a Controles ActiveX:

Un control ActiveX es un objeto que permite interactuar a un usuario con una

aplicación. Estos objetos tienen eventos que se pueden utilizar. La extensión de estos

objetos ActiveX es .OCX.

Un ejemplo clásico, y muy utilizado, es el objeto Cuadrícula (DbGrid). Este objeto

permite mostrar datos de una base de datos en forma de cuadrícula, con lo que le permite al

usuario manipular varios registros a la vez. Este control posee la propiedad DataSource que

permite guardar el nombre del origen de datos desde el cual se cargarán sus celdas. El

DBGrid permite ver y modificar registros simultáneamente.

Se puede utilizar la colección columns para recuperar el texto de la celda seleccionada

actualmente en tiempo de ejecución mediante el siguiente código:

MsgBox DBGrid1.Columns(DBGrid1.Col).Text

Para modificar la información cargada en el DBGrid del objeto Recordset asociado

puede utilizarse el siguiente código:

Data1.Recordset.Edit

Data1.Recordset.Fields("Campeon") = "L.D.A."

Data1.Recordset.Update

El evento BeforeUpdate se ejecuta antes de que se muevan los datos desde un DBGrid

al control data. En este caso puede validarse la información respectiva y cancelarse si es

necesario.

Un objeto que tiene similares particularidades al DBGrid es el MSFlexGrid. Sin

embargo, este control solo permite datos de captura. Puede almacenar en el datos

provenientes de un data control o de una consulta mediante SQL. Muchas veces es necesario

combinar celdas, tal y como se realiza en Excel. MSFlexGrid permite realizar esto

asignando a la propiedad MergeCells un valor distinto de cero y posteriormente asignar las

propiedades de matrices MergeRow() y MergeCol() el valor True para las filas que se

deseen combinar. El siguiente ejemplo muestra como combinar las celdas de la tabla

Facturas:

Page 43: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

43

Private Sub Form_Load()

MSFlexGrid1.MergeCells = flexMergeFree

MSFlexGrid1.MergeCol(1) = True

End Sub

Un control de cuadro de lista enlazado a datos (DBList) o el cuador combinado

enlazado a datos (DBCombo) se utilizan para presentar un listado de datos de un Recordset.

Esto es útil cuando se desea validar datos por parte del usuario. Por ejemplo, si se desea

enviar una notificación a un cliente, se puede utilizar un control DBList para presentar la

lista de todos los nombres de clientes válidos y obtener asi su ID.

En un DBCombo para asignar datos debe configurarse la propiedad RowSource con el

nombre de un control data existente y en la propiedad ListField el nombre de un campo.

Si se debe actualizar un campo de la base de datos debe establecerse las propiedades

DataSource y DataField con lo requerido. Para establecer la relación entre la tabla que

contiene los valores de búsqueda y la tabla que se está modificando realmente, debe

establecerse la propiedad BoundColumn.

DBEngine y WorkSpace:

DAO es una metodología de acceso a datos que permite la manipulación de estos

mediante la utilización de objetos que pertenecen a su jerarquía. Sin embargo, para poder

accesar datos de una base, debe utilizarse primero el objeto DBEngine para abrir un

espacio de trabajo, o sesión, denominado Workspace.

El objeto DBEngine es el objeto de nivel superior dentro del modelo DAO. En este

contexto se pueden utilizar los métodos RepairDatabase y CompactDataBase de este

objeto para darle mantenimiento a una base de datos, tal y como se muestra en el código

siguiente:

MsgBox "El número de versión de DAO es " & _

DBEngine.Version

DBEngine.RepairDatabase "C:\MIBD.MDB"

El objeto WorkSpace define una sesión de usuario, determinando cuanto interactua su

aplicación con los datos de la base de datos. Si se abre una base de datos sin definir el

Workspace se utiliza DBEngine.Workspaces(0) como valor predeterminado para la sesión.

En el ejemplo siguiente se crea una sesión de usuario que utiliza el motor de bases de datos

de Microsoft Jet:

Dim wspNew as Workspace

Set wspNew = DBEngine.CreateWorkspace _

("NewJetWorkspace", "Admin", "", dbUseJet)

Usando el método OpenDatabase:

Page 44: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

44

Con este método se puede crear un objeto tipo Database. Este método se caracteriza

por manejar las siguientes tareas: el nombre de la base de datos origen, el metodo de acceso

a datos, indicación del ambiente de uso (monousuario, multiusuario), indicacion de

lectura/escritura en la base de datos o alguno de ellos, conexión ISAM, DAO u ODBC.

La sintaxis de esta función es la siguiente:

Set basededatos = espaciodetrabajo.OpenDatabase (nombrebasededatos,

opciones, sólolectura, conexión)

La sintaxis del método OpenDatabase consta de las siguientes partes:

Argumento Descripción

basededatos Una variable de objeto que representa el objeto

Database que va a abrir.

espaciodetrabajo Opcional. Una variable de objeto que representa el

objeto Workspace existente que contendrá la base de

datos. Si no incluye un valor para espaciodetrabajo,

OpenDatabase utiliza el espacio de trabajo

predeterminado.

nombrebasededatos Un tipo de datos String que es el nombre de un archivo

de base de datos Microsoft Jet existente o el nombre del

origen de datos (DSN) de un origen de datos ODBC

existente. Consulte la propiedad Name para obtener más

información acerca de este valor.

Argumento Descripción

opciones Opcional. Un tipo de datos Variant que establece varias

opciones para la base de datos, como se especifica en

Valores.

sólolectura Opcional. Un valor de tipo de datos Variant (subtipo

Boolean) que es True si desea abrir la base de datos con

acceso de sólo lectura o False (predeterminado) si desea

abrir la base de datos con acceso de lectura/escritura.

conexión Opcional. Un tipo de datos Variant (subtipo String) que

especifica información variada sobre la conexión,

incluyendo las contraseñas.

Valores:

Para los espacios de trabajo Microsoft Jet, puede utilizar los siguientes valores para el

argumento opciones:

Valor Descripción

True Abre la base de datos en modo exclusivo.

False (Predeterminado) Abre la base de datos en modo compartido.

Para los espacios de trabajo ODBCDirect, el argumento opciones determina si y

cuando informar al usuario acerca de establecer la conexión. Puede utilizar una de

las siguientes constantes:

Page 45: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

45

Constante Descripción

dbDriverNoPrompt El Administrador del controlador de ODBC utiliza la

cadena de conexión suministrada en nombrebasededatos

y conexión. Si no proporciona información suficiente,

se produce un error en tiempo de ejecución.

DbDriverPrompt El Administrador del controlador de ODBC muestra

el cuadro de diálogo ODBC Data Sources, que

muestra cualquier información interesante

suministrada en nombrebasededatos o conexión. La

cadena de conexión se realiza con el DSN que el

usuario selecciona en los cuadros de diálogo o, si el

usuario no especifica un DSN, se utiliza el valor

predeterminado de DSN. DbDriverComplete (Predeterminado) Si los argumentos conexión y

nombrebasededatos incluyen toda la información

necesaria para completar la conexión, el Administrador

del controlador de ODBC utiliza la cadena en conexión.

De otro modo funciona como cuando especifica

dbDriverPrompt.

Constante Descripción

DbDriverCompleteRequired Esta opción funciona como dbDriverComplete

excepto que el controlador ODBC desactiva el

envío de información que no necesita para

completar la conexión.

Abriendo tablas ISAM:

Muchas veces se necesita abrir tablas o archivos que son tipo DBF, por ejemplo. En

este caso se puede utilizar la siguiente sintaxis:

Set dbMydb = OpenDatabase("\\PlaniVB", False, False, "Dbase III;")

Set rs = dbMydb.OpenRecordset("Planilla", dbOpenTable)

rs.Index = "Cedula"

Se puede observar que PlaniVB es el directorio donde está contenida la tabla que se

desea abrir. Puede observarse que el comando OpenDatabase no abre ninguna base de datos

sino que solo referencia el directorio en donde yace la tabla DBF. Seguidamente, se crea un

Recordset, de tipo Table, para abrir la tabla DBF respectiva. En la tercera línea puede

observarse como habilitar un índice “Cedula” que utiliza la tabla y que podemos utilizar en el

Recordset para realizar una búsqueda indizada en la misma, tal y como se muestra en el

código siguiente:

rs.Seek "=", Busc

Busc en este caso, es una variable que contiene el valor obtenido, por ejemplo, de un

TextBox o de cualquier objeto.

El índice puede crearse utilizando Visual Data de Visual Basic. Se abre la tabla y se

modifica mediante la apertura en modo diseño y se crea el índice que se necesita. Visual

Basic mantiene posteriormente el índice actualizado automaticamente. También puede

Page 46: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

46

crearse inicialmente un archivo tipo texto, con cualquier editor y salvarlo con extensión INF.

El archivo debe ser tal y como se muestra:

Archivo INDCED.INF:

NDX = CEDULA.NDX

Comentarios:

Cuando abre una base de datos, automáticamente se agrega a la colección Databases.

Además, en un espacio de trabajo ODBCDirect, el objeto Connection correspondiente al

objeto Database nuevo también se crea y anexa a la colección Connections del mismo objeto

Workspace.

Estas son algunas consideraciones que se debe aplicar cuando utilice

nombrebasededatos:

Si se hace referencia a una base de datos que ya está abierta para acceso en

modo exclusivo por otro usuario, se produce un error.

Si no se hace referencia a una base de datos existente o a un nombre de un origen de

datos ODBC válido, se produce un error.

Si es una cadena de longitud cero ("") y conexión es "ODBC;", se muestra un cuadro

de diálogo que enumera todos los nombres de orígenes de datos ODBC registrados

para que el usuario pueda seleccionar una base de datos.

Si se está abriendo una base de datos mediante un espacio de trabajo ODBCDirect y

proporciona el DSN en conexión, puede establecer nombrebasededatos a una

cadena de su elección que puede utilizar para hacer referencia a esta base de datos

en el código más adelante.

El argumento conexión se expresa en dos partes: el tipo de base de datos, seguido por

punto y coma (;) y los argumentos opcionales. Primero debe proporcionar el tipo de base de

datos, como "ODBC;" o "FoxPro 2.5;". A continuación, os argumentos opcionales sin un

orden concreto, separados por punto y coma. Uno de los parámetros puede ser la contraseña

(si hay alguna asignada). Por ejemplo:

"FoxPro 2.5; pwd=micontraseña"

Utilizar el método NewPassword en un objeto Database distinto de una base de datos

de ODBCDirect cambia el parámetro de contraseña que aparece en la parte ";pwd=..." de este

argumento. Debe aplicar los argumentos opciones y sólolectura

para proporcionar una cadena de origen. Consulte la propiedad Connect para su

sintaxis.

Para cerrar una base de datos y, de este modo, quitar el objeto Database de la colección

Databases, utilice el método Close en el objeto .

Page 47: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

47

Nota Cuando tiene acceso a un origen de datos ODBC conectado a Microsoft Jet,

puede mejorar el rendimiento de sus aplicaciones abriendo un objeto Database conectado al

origen de datos ODBC, en vez de vincular objetos TableDef individuales a tablas específicas

en el origen de datos ODBC.

El cuadro siguiente muestra el soporta que brinda Visual Basic a varios formatos de

bases de datos:

Database Format DataBaseName Connect

Microsoft Access drive:\path\file.mdb (none)

Betrieve drive:\path\file.ddf “Betrieve”

DBase III drive:\path “dBASE III”

Dbase IV drive:\path “DBASE IV”

FoxPro Versión 2.5 drive:\path “FoxPro 2.5”

ODBC (SQL Server,Oracle) Registered data source “Odbc;Dsn=Server;

Name(usualmente el Uid=User; Pd = Password”

Nombre del servidor)

Desarrollo Avanzado de Bases de Datos:

Exigencia de la Integridad de los datos:

Este apartado no se refiere al manejo de datos con sistemas administradores de bases

de datos de alto nivel como Oracle, Sybase o Microsoft SQL Server, dado que sobrepasan el

alcance de este manual. Se refiere, por el contrario, a la manipulación de datos con

Microsoft Access o Microsoft Jet como motor de administración de datos para aplicaciones

de mediana complejidad y de uso de escritorio y no cliente servidor.

Cuando se crea una aplicación de base de datos, debe asegurarse de que sólo se

escriban datos válidos en la misma.

Microsoft Access permite crear reglas y establecer restricciones de integridad

referencial en una base de datos para ayudar a garantizar la integridad de los datos.

Se recibirá un error de tiempo de ejecución si se trata de infringir estas restricciones.

En este caso debe proporcionarse el código que intercepta estos errores y que permite al

usuario corregir los datos y continuar.

Cuando se utiliza una base de datos de Microsoft Jet, pueden definirse reglas que

especifiquen los datos que son válidos en un campo o en una tabla. Estas reglas se almacenan

con la base de datos y se exigirán independientemente de cómo modifique los datos. Por

ejemplo puede establecerse que en una tabla determinada de una base de datos no permita

valores nulos o ceros.

Propiedades de las reglas:

Con Visual Basic se pueden crear o ver las reglas de una base de datos. Los objetos

Field y Recordset cuentan con dos propiedades relacionadas con las reglas.

Estas propiedades sólo se admiten en las bases de datos de Microsoft Jet:

Page 48: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

48

ValidationRule: Define los criterios de la regla.

ValidationText : Proporciona un mensaje de error que puede mostrarse si se infringe

la regla.

Por ejemplo, si una tabla denominada Pedidos posee un campo Cantidad, puede

escribirse código que permita mostrar las propiedades Validadtion Rule y Validation Text,

tal como sigue:

Sub DisplayRule()

Set rstOrders = dbMydb.OpenRecordset("Detalles de pedidos")

' Imprime ">0"

Debug.Print rstOrders("Cantidad").ValidationRule

' Imprime "La cantidad debe ser mayor que 0"

Debug.Print rstOrders("Cantidad").ValidationText

End Sub

Nota Se puede establecer la propiedad ValidationRule de un objeto Field para definir

una regla de forma programada. Sin embargo, aquí no se explica cómo definir una regla por

programa. Para obtener más información acerca de la creación de reglas, vea la propiedad

ValidationRule en la Ayuda de Visual Basic.

Errores de infracción de las reglas:

Si cuando se actualiza un registro se infringe una regla, se producirá un error de tiempo

de ejecución. La propiedad ValidateOnSet determina cuándo se produce el error de

infracción de la regla.

Si ValidateOnSet es True, el error de tiempo de ejecución se produce cuando se

establece el campo, como se muestra en el ejemplo siguiente:

recOrders.Edit

recOrders("Cantidad").ValidateOnSet = True

recOrders("Cantidad").Value = 0 'SE GENERA UN ERROR

recOrders.Update

Si ValidateOnSet es False, el error de tiempo de ejecución se producirá cuando se

ejecute el método Update, como en el siguiente ejemplo:

recOrders.Edit

recOrders("Cantidad").ValidateOnSet = False

recOrders("Cantidad").Value = 0

recOrders.Update 'Se genera un error.

Tratamiento de las infracciones de las reglas:

Normalmente, si se produce una infracción de las reglas se deseará permitir al usuario

corregir los datos y tratar de volver a actualizarlos.

Page 49: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

49

Si se utiliza el control Data e infringe una regla, se producirá el evento Error. El

control Data muestra la propiedad ValidationText y cancela la actualización. El usuario

puede modificar los datos y hacer clic en el control Data para tratar de volver a realizar la

actualización.

Se puede agregar código al evento Error para realizar una acción distinta cuando se

produzca el error. Por ejemplo, puede mostrarse texto en un título en lugar de un cuadro de

mensajes o bien cambiar la propiedad ForeColor de los campos para indicar que se ha

producido un error.

Si se utilizan Objetos de acceso a datos (DAO) e infringe una regla, se recibirá un error

de tiempo de ejecución. Debe interceptarse este error e informar al usuario.

El siguiente fragmento de código muestra como desplegar un mensaje cuando se

produzca una infracción a la regla (cantidad igual a cero, por ejemplo):

Private Sub cmdUpdate_Click()

On Error GoTo update_err

rs.Edit

rs("Cantidad") = txtQuantity.Text

rs.Update

Exit Sub

update_err:

If Err.Number = 3316 Then 'determina la infracción

lblError.Caption= Err.Description

rs.CancelUpdate

Exit Sub

End If

End Sub

La propiedad Description del objeto Err contiene el valor de la propiedad

ValidationText.

Puede utilizarse el método CancelUpdate para cancelar el método Edit o AddNew

actual y para actualizar el registro actual. Pueden dejarse los datos del usuario en el

formulario o bien actualizar el formulario con los datos actuales de la base de datos.

Reglas de Integridad Referencial:

La integridad referencial hace referencia a las restricciones que se deben poner en una

base de datos para mantener las relaciones definidas entre dos tablas cuando se agregan,

cambian o eliminan registros.

Definir las restricciones de integridad referencial:

El motor de base de datos Microsoft Jet puede exigir automáticamente la integridad

referencial en las bases de datos de Microsoft Jet.

Page 50: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

50

Por ejemplo, puede existir una tabla denominada Clientes y otra Pedidos. No se

pueden incluir pedidos si no existe un cliente; eso es mantener la integridad referencial de los

datos.

Nota Pueden definirse las relaciones entre tablas mediante programación con Visual

Basic o bien manualmente, mediante Microsoft Access. Para obtener información acerca de

la creación de relaciones mediante programación, vea el método CreateRelation en la

Ayuda de Visual Basic.

Actualizaciones y eliminaciones en cascada:

Una vez establecida la integridad referencial, pueden especificarse las opciones

Actualizar en cascada los campos relacionados o Eliminar en cascada los registros

relacionados. Si establece estas opciones, el motor de base de datos Microsoft Jet permitirá

al usuario cambiar y eliminar registros, y cambiará o eliminará automáticamente los registros

relacionados de las tablas relacionadas.

Por ejemplo, suponga que se ha creado una relación entre las tablas Clientes y Pedidos.

Si se selecciona la opción Eliminar en cascada los registros relacionados para la tabla

Clientes, cada vez que el usuario elimine el registro de un cliente, el motor de base de datos

Microsoft Jet eliminará automáticamente todos los registros relacionados con ese cliente de

la tabla Pedidos.

Nota El motor de base de datos Microsoft Jet no muestra ninguna advertencia cuando

elimina los registros relacionados. Es muy importante que se entienda cómo están definidas

las relaciones en la base de datos para evitar pérdidas de datos al eliminar registros.

Tratamiento de las infracciones de integridad referencial:

Si se trata de infringir las restricciones de integridad referencial, se recibirá un error de

tiempo de ejecución. Debe interceptarse este error e informar al usuario.

El siguiente fragmento de código muestra un mensaje de error si el usuario intenta

eliminar el registro de un cliente que tiene un pedido:

Private Sub cmdDelete_Click()

On Error GoTo del_err

rs.Delete

rs.MoveNext

FillFields 'procedimiento escrito por el usuario

Exit Sub

del_err:

'Referencia a la violación de integridad

If Err.Number = 3200 Then

lblError.Caption = "No se puede borrar un cliente con órdenes."

Exit Sub

Else

'controlar otros errores...

Page 51: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

51

End If

End Sub

El registro no se elimina y no se vuelve a posicionar en el registro actual. Los cuadros

de texto del formulario siguen conteniendo los datos actuales.

Prevenir infracciones de integridad referencial:

Para evitar infracciones de integridad referencial puede proporcionarse un cuadro de

lista con entradas válidas. Si las entradas válidas son demasiado largas y no caben en un

cuadro de lista, permitase que el usuario especifique criterios de búsqueda y muestrese

después una lista de entradas válidas.

Por ejemplo, cuando agrega un nuevo producto, se puede permitir al usuario escribir un

valor para un nombre de producto y a continuación mostrar una cuadrícula con todos los

productos que coincidan con ese nombre. Seguidamente, el usuario puede seleccionar un

producto válido de la cuadrícula.

Transacciones:

Una transacción es una serie de cambios realizados en una base de datos. Pueden

agruparse varios cambios de bases de datos en una transacción.

Si todas las operaciones se realizan correctamente, confirmará la transacción. Si alguna

de las operaciones falla, deshará la transacción.

Métodos de transacciones:

Los métodos de transacciones se aplican al objeto Workspace. Se Utiliza el método

BeginTrans antes de actualizar el primer registro. Si alguna de las siguientes actualizaciones

falla, se utiliza el método Rollback para deshacerlas todas. Se usa el método CommitTrans

tras haber actualizado correctamente el último registro.

El siguiente fragmento de código muestra la utilización de transacciones con el fin de

agregar un entrada a la tabla Pedidos y a la tabla Detalles de pedidos:

Sub cmdAddOrder_Click ()

On Error GoTo AddOrder_Err

DBEngine.WorkSpaces(0).BeginTrans

db.Execute "Insert Into Pedidos...", dbFailOnError

db.Execute "Insert Into [Detalles de pedidos]..." , dbFailOnError

DBEngine.WorkSpaces(0).CommitTrans

lblStatus.Caption = "Actualizaciones terminadas"

Exit Sub

AddOrder_Err:

lblStatus.Caption = Err.Description

Msgbox "No se han efectuado todas las actualizaciones con éxito"

DBEngine.Workspaces(0).Rollback

Page 52: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

52

Exit Sub

End Sub

Utilizar transacciones para mejorar el rendimiento:

Además de utilizar las transacciones para mantener la integridad de los datos, puede

mejorarse el rendimiento si se incluye una instrucción Update de SQL en una transacción.

Las operaciones de la transacción se almacenan en búfer y no se escriben a disco hasta que

se confirma la transacción.

El siguiente ejemplo incluye una instrucción Update de SQL en una transacción:

DBEngine.Workspaces(0).BeginTrans

stSQL = "UPDATE Productos SET [PrecioUnidad] = [PrecioUnidad] * 0.1"

db.Execute strSQL, dbFailOnError

DBEngine.Workspaces(0).CommitTrans

Nota Es posible anidar transacciones en un objeto Workspace. Se deberá confirmar o

deshacer la transacción actual antes de poder confirmar o deshacer una transacción de un

nivel superior.

Si se desea disponer de transacciones que se solapen pero que sean independientes

entre sí, puede crearse un segundo objeto Workspace.

Para obtener más información acerca de la creación de objetos Workspace, veáse el

método CreateWorkspace en la Ayuda de Visual Basic.

Consideraciones multiusuario:

Las aplicaciones de bases de datos se vuelven más complejas si se desea permitir que

varios usuarios tengan acceso a una base de datos simultáneamente. Deberán tratar diversos

errores que pueden producirse cuando varios usuarios tengan acceso a los mismos datos. Por

ejemplo:

Dos usuarios tratan de modificar los mismos datos: El motor de base de datos

Microsoft Jet bloquea automáticamente los datos para evitar que dos usuarios

modifiquen un registro simultáneamente. Si los usuarios tratan de actualizar un

registro bloqueado, recibirán un error de tiempo de ejecución.

Alguien cambia un registro que otro usuario está viendo: Si un usuario intenta

actualizar un registro y los datos se han modificado desde que se ejecutó el método

Edit, el motor de base de datos Microsoft Jet devolverá un error.

Alguien elimina un registro que otro usuario está viendo: Si un usuario intenta

tener acceso a un registro que se ha eliminado, el motor de base de datos Microsoft

Jet devolverá un error.

Abrir una tabla para acceso exclusivo:

Page 53: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

53

Para evitar los problemas que ocurren cuando se permite que varios usuarios tengan

acceso a una base de datos, puede abrirse un tabla para uso exclusivo. Al abrirse una tabla de

este modo se evita que otro usuario la utilice. Aunque se trata de una solución bastante

restrictiva, puede resultar adecuada para tal situación.

El argumento opciones para el método OpenRecordset determina cómo se abre el

Recordset.

En el código siguiente se abre una tabla para uso exclusivo. Puede modificarse la tabla

Pedidos, pero ningún otro usuario podrá ver ni modificar los datos de dicha tabla:

Set recOrders = dbMydb.OpenRecordset _

("Pedidos", dbOpenTable, dbDenyRead + dbDenyWrite)

En el código siguiente se abre una tabla para escritura en modo exclusivo. Puede verse

y modificarse la tabla Pedidos; los otros usuarios pueden ver los datos de la tabla, pero no

pueden modificarlos:

Set recOrders = dbMydb.OpenRecordset _

("Pedidos", dbOpenTable, dbDenyWrite)

En el código siguiente se abre un Recordset en modo de sólo lectura. Pueden leerse los

datos de la tabla, pero no modificarlos. Esto no afecta a los demás usuarios:

Set recOrders = dbMydb.OpenRecordset _

("Pedidos", dbOpenTable, dbReadOnly)

En el código siguiente se abre un Recordset en modo anexar. Sólo pueden agregarse

registros; no pueden verse ni modificar los registros existentes. Esto no afecta a los demás

usuarios:

Set recOrders = dbMydb.OpenRecordset _

("Pedidos", dbOpenDynaset, dbAppendOnly)

Si sólo se desea agregar registros a una tabla, debe utilizarse la opción dbAppendOnly

para obtener mayor rendimiento. La opción dbDenyRead sólo está disponible en el

Recordset de tipo table.

Para obtener una lista de valores válidos para el argumento opciones, veáse el método

OpenRecordset en la Ayuda de Visual Basic.

El bloque de Microsoft Jet:

Todos los sistemas de administración de bases de datos proporcionan algún tipo de

mecanismo de bloqueo para evitar que dos usuarios actualicen datos simultáneamente.

El motor de base de datos Microsoft Jet proporciona un bloqueo de página. Las páginas

son bloques de registros de 2048 bytes (2 KB) de tamaño. Visual Basic almacena tantos

registros como quepan en cada página. Cuando Visual Basic bloquea la página que contiene

un registro que está modificando, todos los demás registros de esa página también quedarán

bloqueados.

Page 54: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

54

Nota La información aquí consignada es específica de las bases de datos que utilizan

el motor Microsoft Jet. Cuando se tiene acceso a bases de datos a través de ODBC, el

mecanismo de bloqueo está controlado por el sistema de administración de bases de datos.

Bloqueo pesimista frente a bloqueo optimista:

El valor de la propiedad LockEdits del objeto Recordset determina cuándo se activa

un bloqueo para los registros del Recordset.

Bloqueo pesimista:

Si la propiedad LockEdits tiene el valor True, el bloqueo pesimista está activo. La

página que contiene el registro actual se bloquea en el momento en que utiliza el método

Edit. La página se desbloquea cuando utiliza el método Update.

La estrategia de bloqueo predeterminada bloquea los registros durante un período de

tiempo mayor, pero garantiza que después de ejecutarse el método Edit ningún otro usuario

pueda modificar los datos.

Bloqueo optimista:

Si la propiedad LockEdits tiene el valor False, el bloqueo optimista está activo. La

página que contiene el registro sólo se bloquea mientras se actualiza el registro.

Los bloqueos permanecen activos durante un período de tiempo más corto y varios

usuarios pueden utilizar el método Edit sin bloquear la página. No obstante, en este caso

deberán tratarse los posibles errores cuando el usuario ejecute el método Update.

Si se piensa que los usuarios no intentarán modificar el mismo registro a menudo,

considerese la posibilidad de asignar a la propiedad LockEdits el valor False.

Desbloqueo:

El motor de base de datos Microsoft Jet marca una página para que se desbloquee en

cuanto se complete la actualización. Sin embargo, los bloqueos se quitan realmente cuando

no se produce ninguna otra acción.

Puede utilizarSE el método Idle del objeto DBEngine con la opción dbFreeLocks

para suspender el proceso y permitir al motor de base de datos Microsoft Jet liberar los

bloqueos y seguir con las otras tareas en segundo plano, como muestra el siguiente código:

DBEngine.Idle dbFreeLocks

Controlar los errores de bloqueo:

Cuando varios usuarios están actualizando una base de datos, deberá agregarse código

que intercepte los errores siguientes:

3260: No se pudo actualizar; actualmente está bloqueado: Se produce en el

método Edit cuando el registro está bloqueado. El código debe esperar unos

instantes y tratar de aplicar Edit otra vez o informar al usuario del error.

Page 55: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

55

3186: No se pudo guardar el registro; bloqueado actualmente: Se produce en el

método Update cuando el registro está bloqueado. El código debe esperar unos

instantes y volver a intentarlo o informar al usuario del error.

3197: Los datos han cambiado; la operación se ha detenido: Se produce en el

método Update o Edit si otro usuario cambió los datos desde la última vez que

tuvo acceso a ellos. El código debe actualizar el formulario con los datos más

recientes o informar al usuario del error. Para obtener una lista completa de los errores disponibles en Visual Basic, veáse

Errores interceptables en la Ayuda de Visual Basic.

Tratar errores en Edit

El siguiente código de ejemplo muestra como tratar los errores de bloqueo que pueden

ocurrir en el método Edit:

Private Sub cmdEdit_Click()

On Error GoTo HandleError

rs.Edit

ButtonEditAddMode

Exit Sub

HandleError:

Select Case Err.Number

Case 3260 'la página está bloqueada actualmente

MsgBox "El registro está bloqueado actualmente. Inténtelo más

tarde."

Case 3197 'los datos han cambiado

MsgBox "Los datos han cambiado y se van a actualizar."

rs.Bookmark = rs.Bookmark 'obtener datos actualizados

FillFields

rs.Edit

Case Else

MsgBox Err.Number & ": " & Err.Description

End Select

End Sub

Si el registro está bloqueado cuando el usuario ejecuta el método Edit, se mostrará un

mensaje; si los datos han cambiado, el código actualizará el formulario con los datos más

recientes.

La instrucción recOrders.Bookmark = recOrders.Bookmark actualiza el registro

actual del Recordset con los datos más recientes de la base de datos.

Tratar errores en Update:

Page 56: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

56

El siguiente código de ejemplo muestra como tratar los errores de bloqueo que pueden

ocurrir en el método Update:

Private Sub cmdSave_Click()

Dim answer As Integer

On Error GoTo HandleError

rs.Fields("NombreCategoría") = txtCategoryName.Text

rs.Fields("Descripción") = txtDescription.Text

rs.Update

rs.Bookmark = rs.LastModified

FillFields

ButtonNonEditAddMode

Exit Sub

HandleError:

Select Case Err.Number

Case 3260

MsgBox "El registro está bloqueado actualmente. " & _

"Intente guardarlo más tarde o cancele los cambios."

Case 3197

answer = MsgBox("Los datos han sido modificados por otro

usuario. " & _ "¿Sobrescribir cambios?", vbYesNo)

If answer = vbYes Then

Resume

Else

rs.Bookmark = rs.Bookmark 'actualizar con cambios de

'otros usuarios

cmdCancel_Click

End If

Case Else

MsgBox Err.Number & ": " & Err.Description

End Select

End Sub

Tratar errores de los registros eliminados por otros usuarios:

Cuando el Recordset de tipo dynaset se ha llenado por completo, si otro usuario

elimina un registro de la base de datos, el puntero a esa entrada no se eliminará del dynaset.

Sin embargo, dicho registro ya no aparecerá en la base de datos. No podrá verse y se

producirá un error si se intenta tener acceso a los datos de ese registro.

La forma más sencilla de tratar este error es eliminar la entrada que hace referencia al

registro eliminado del dynaset.

El siguiente fragmento de código muestra cómo tratar un error generado por un intento

de tener acceso a un registro eliminado:

Page 57: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

57

Private Sub cmdMoveNext_Click()

On Error GoTo err_movefirst:

retry_MoveNext:

rs.MoveNext

txtLName.Text = rs("Apellidos") 'Puede ocurrir un error

Exit Sub

err_Movefirst:

If Err.Number = 3167 Then

'se borra el registro,

'eliminar la entrada del dynaset

rs.Delete

Resume retry_MoveNext

Else

MsgBox Err.Description

Exit Sub

End If

End Sub

Anteriormente, se dedicó gran parte a explicar el objeto Recordset y se comentó acerca

de la creación y manipulación de estos. Seguidamente, se brinda un reforzamiento de

conceptos al respecto.

Acceso a bases de datos externas:

Desde Visual Basic puede tenerse acceso a diversas bases de datos ISAM (Método de

acceso secuencial indizado) como dBASE, Paradox, Btrieve y Microsoft Visual FoxPro.

Visual Basic proporciona controladores para diversas bases de datos ISAM. Estos

controladores se muestran en el registro.

También puede utilizar Visual Basic para tener acceso a archivos de datos estándar,

como archivos de texto delimitados por comas.

Nota Las bases de datos que utilizan el motor de base de datos Microsoft Jet se

consideran nativas de Visual Basic.

Opciones de acceso:

Hay dos formas de tener acceso a los datos de una base de datos externa: adjuntar la

base de datos externa y abrirla directamente.

Adjuntar una tabla a una base de datos de Microsoft Jet:

Cuando se adjunta una base de datos externa a una base de datos de Microsoft Jet, los

datos de la tabla permanecen en la base de datos externa. Sin embargo, la información de

conexión y la definición de la tabla se almacenan en la base de datos de Microsoft Jet. Puede

Page 58: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

58

utilizarse la tabla como cualquier otra tabla de bases de datos de Microsoft Jet, a excepción

de que no puede crear un Recordset de tipo table en una tabla adjunta.

Puede utilizarse Microsoft Access para adjuntar fácilmente una tabla a una base de

datos de Microsoft Jet. También puede adjuntarse una tabla por programa mediante Visual

Basic.

Para obtener información acerca de cómo adjuntar tablas por programa, veáse el

método CreateTableDef en la Ayuda de Visual Basic.

Nota Normalmente puede tenerse acceso más rápidamente a los datos de las tablas

ODBC que se adjuntan a una base de datos de Microsoft Jet que a los datos de una base de

datos ODBC que haya abierto directamente. Si es posible, considerese la posibilidad de

adjuntar tablas externas en lugar de abrirlas directamente.

Abrir una tabla directamente:

Cuando se abre directamente una tabla externa, debe especificarse la información de

conexión mediante los argumentos del método OpenDatabase o la propiedad Connect del

control Data.

El siguiente fragmento de código muestra como utilizar los métodos OpenDatabase y

OpenRecordset para abrir una tabla directamente:

Page 59: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

59

Sub OpenTable()

Dim wspCurrent As Workspace

Dim dbCurrent As Database

Dim rstProducts As Recordset

Set wspCurrent = CreateWorkspace("New Workspace", "Admin", "", _

dbUseJet)

Set dbCurrent = wspCurrent.OpenDatabase("C:\Archivos de _

programa\DevStudio\VB\Inventario.mdb")

Set rstProducts = dbCurrent.OpenRecordset("Productos", dbOpenTable)

rstProducts.MoveLast

MsgBox "Hay " & rstProducts.RecordCount & " registros."

rstProducts.Close

dbCurrent.Close

wspCurrent.Close

End Sub

Acceso a bases de datos ISAM:

Para abrir una base de datos ISAM directamente, debe asignarse al argumento

Database del método OpenDatabase (o a la propiedad DatabaseName del control Data) el

nombre de la carpeta que contiene las tablas ISAM. Si la red lo admite, puede utilizar una

ruta de acceso de red para el nombre de la base de datos, por ejemplo,

“\\mi_servidor\mi_recurso”.

Asignese a la propiedad Connect del objeto Database o del control Data el tipo de

base de datos que se va a abrir. Para obtener una lista de valores posibles, veáse la propiedad

Connect en la Ayuda de Visual Basic.

En el ejemplo siguiente se abre directamente una base de datos de Microsoft Visual

FoxPro:

Public Sub OpenFoxProTable()

Dim dbFox As Database

Dim recAccounts As Recordset

Set dbFox = OpenDatabase _

("\\FoxPro\Data\AP", False, False, “FoxPro 5.0;") „direccionado a la red.

Set recAccounts = dbFox.OpenRecordset("Cuentas")

End Sub

Para adjuntar una base de datos ISAM a una base de datos .mdb existente, debe crearse

un nuevo objeto TableDef y establecer las propiedades Connect y SourceTableName del

objeto TableDef.

En el ejemplo de código siguiente se adjunta una tabla de Microsoft FoxPro a una base

de datos de Microsoft Jet. Puede crearse una nueva base de datos de Microsoft Jet o bien

utilizar una existente:

Dim tbdAttach as TableDef

Set dbMydb=OpenDatabase ("Mibd.mdb")

Set tbdAttach = dbMydb.CreateTableDef ("Tabla FoxPro adjunta")

Page 60: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

60

tbdAttach.Connect = "FoxPro 5.0;DATABASE=\\FoxPro\AP"

tbdAttach.SourceTableName = "Cuentas"

dbMydb.TableDefs.Append tbdAttach

Cuando se haya adjuntado la tabla a una base de datos de Microsoft Jet, podrá abrirse

de la forma siguiente:

Set dbMydb = OpenDatabase ("Mibd.mdb")

Set recAttach = dbMydb.OpenRecordset ("Tabla FoxPro adjunta")

Distribuir el ejecutable:

Cuando se distribuya una aplicación que tenga acceso a una base de datos ISAM,

deberá proporcionarse al usuario los controladores ISAM adecuados.

Trabajando con archivos de datos:

Pueden crearse aplicaciones de Visual Basic que trabajen con información de archivos

de datos estándar en lugar de hacerlo con una base de datos.

Cuando se trabaje con información procedente de archivos de datos estándar, pueden

utilizarse alguna de las siguientes opciones:

Instrucciones de E/S de archivos: Puede utilizar las instrucciones estándar de

acceso a archivos de Visual Basic para leer y escribir archivos. Para obtener más

información acerca de la instrucción Open, vea Open en la Ayuda de Visual Basic.

Importación manual a una base de datos: Puede utilizar Microsoft Access para

importar manualmente un archivo de texto a una base de datos. Microsoft Access

admite diversos formatos de archivo, como de longitud fija, delimitados por comas,

etc.

Importación mediante programación a una base de datos: Puede crear un

programa que lea un archivo de texto y agregue los datos a una base de datos.

Page 61: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

61

El siguiente código de ejemplo muestra los pasos básicos para utilizar la E/S de

archivo con el fin de leer un archivo e insertar los datos en una base de datos:

Private Sub Command4_Click()

Dim fhandle As Integer

fhandle = FreeFile()

Open "newCust.txt" For Input As fhandle

Do

'Leer archivo utilizando alguna instrucción Input

'Crear cadena sql

'Ejecutar instrucción Insert de SQL

Loop Until EOF(fhandle)

End Sub

Acceso a datos mediante ODBC:

La versión 3.5 de DAO presenta una nueva tecnología de conexión cliente-servidor

llamada Open Database Connectivity Direct (ODBCDirect). Esta tecnología establece una

conexión directamente con un origen de datos ODBC, sin cargar el motor de base de datos

Microsoft Jet.

Definir un espacio de trabajo ODBC:

La tecnología de ODBCDirect permite tener acceso directamente a orígenes de datos

ODBC mediante Objetos de acceso a datos (DAO). Pueden utilizarse las características de

esta conexión cliente-servidor para tener acceso rápidamente a una base de datos, sin cargar

el motor de base de datos Microsoft Jet.

El primer paso para utilizar ODBCDirect consiste en definir el tipo de espacio de

trabajo que utilizará. Puede hacerse de dos formas: establecer el tipo de espacio de trabajo

predeterminado o definir un tipo de espacio de trabajo específico como ODBCDirect.

Establecer el espacio de trabajo predeterminado:

Para establecer el tipo de espacio de trabajo predeterminado como ODBCDirect, debe

utilizarse la propiedad DefaultType del objeto DBEngine. Este tipo se utilizará siempre que

se cree un objeto Workspace.

Para definir un tipo de espacio de trabajo específico como ODBCDirect, debe

asignarse a la propiedad DefaultType el valor dbUseODBC. Este valor impide que el motor

de base de datos Microsoft Jet se cargue en memoria, si no ha creado ya un espacio de

trabajo de base de datos de Microsoft Jet.

Page 62: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

62

El código siguiente establece el tipo de espacio de trabajo predeterminado como

ODBCDirect:

DBEngine.DefaultType = dbUseODBC

Crear un espacio de trabajo específico:

Puede invalidarse el valor de espacio de trabajo predeterminado para un determinado

espacio de trabajo si utiliza el argumento tipo del método CreateWorkspace.

Conectarse a un origen de datos remoto:

Conectarse con un origen de datos remoto es similar a abrir una base de datos de

Microsoft Jet. Primero debe crearse un espacio de trabajo (como un espacio de trabajo de

ODBCDirect) y después abrir el origen de datos.

Para abrir un origen de datos remoto, debe crease un objeto Connection de la misma

forma en que se crearía un objeto Database para abrir una base de datos de Microsoft Jet.

Una vez creada una conexión, pueden recuperarse datos del origen de datos remoto.

Declaración de la conexión:

La variable de objeto Connection se refiere a su conexión. Utilicese la instrucción Set

para abrir la conexión.

El código siguiente abre una conexión en el espacio de trabajo predeterminado:

Dim conNewConnection As Connection

Set conNewConnection = OpenConnection _

("New", dbDriverPrompt, False, _

"ODBC;DATABASE=pubs;UID=sa;PWD;DSN=SQLServer")

Método OpenConnection:

En la tabla siguiente se enumeran los argumentos del método OpenConnection y se

describe su uso.

Page 63: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

63

Argumento Descripción

Nombre Cualquier cadena, si especifica un nombre de origen de datos (DSN) ODBC

registrado. Si en la declaración de OpenConnection no se incluye un DSN

válido, el nombre deberá hacer referencia a un DSN válido de ODBC, que

también será la propiedad Name.

Opciones Establece diversas opciones para la conexión.

Solo_lectura True o False. Si es True, no se permiten modificaciones. El valor

predeterminado es False.

Conexión Una cadena de conexión ODBC.

El argumento opciones determina si y cuándo se pedirá al usuario que establezca la

conexión y si la conexión se abrirá o no de manera asíncrona.

En la tabla siguiente se muestran los valores del argumento opciones y se describe su

uso.

Constante Resultado

dbDriverNoPrompt El Administrador de controladores ODBC utiliza la cadena de conexión

proporcionada en el argumento conexión

dbDriverPrompt El Administrador de controladores ODBC muestra el cuadro de diálogo

Seleccionar origen de datos, que presenta toda la información relevante

proporcionada en el argumento conexión. La cadena de conexión está

formada por el DSN seleccionado por el usuario mediante los cuadros de

diálogo o bien, si el usuario no especifica ningún DSN, se usará el DSN

predeterminado.

dbDriverComplete Si el argumento conexión incluye toda la información necesaria para

completar una conexión, el Administrador de controladores ODBC usará

la cadena del argumento conexión. De lo contrario, se comportará como

cuando especifica la constante predeterminada dbDriverPrompt. Es el

valor predeterminado.

dbDriverCompleteR

equired

Esta opción se comporta como la constante dbDriverComplete, excepto

en que el controlador ODBC desactiva las peticiones de información

innecesarias para completar la conexión

dbRunAsync Ejecuta el método de forma asíncrona. Esta constante se puede utilizar

con cualquiera de las demás constantes de opciones

Page 64: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

64

Recuperar datos remotos:

La recuperación de datos remotos mediante ODBCDirect es muy similar a la

recuperación de datos desde una base de datos de Microsoft Jet. Después de establecer una

conexión con una base de datos compatible con ODBC mediante ODBCDirect, cree un

objeto Recordset; para ello, utilicese el método OpenRecordset de la misma forma que si se

recuperaran registros de una base de datos de Microsoft Jet.

Declaración del Recordset:

El siguiente ejemplo de código crea un espacio de trabajo de ODBCDirect con una

conexión al espacio de trabajo y después recupera un Recordset:

Sub OpenODBCDirectRecordset()

Dim wspODBC As Workspace

Dim conODBC As Connection

Dim rstODBC As Recordset

Set wspODBC = CreateWorkspace _

("", "sa", "", dbUseODBC)

Set conODBC = wspODBC.OpenConnection _

("NewConnection", dbDriverNoPrompt, False, _

"ODBC;DATABASE=pubs;UID=sa;PWD=;DSN=SQLServer")

Set rstODBC = conODBC.OpenRecordset _

("SELECT * FROM Autores WHERE au_lname = 'Enrique Gómez'",

_

dbOpenSnapshot, 0, dbReadOnly)

rstODBC.MoveLast

MsgBox "Este conjunto de datos remoto contiene " & _

rstODBC.RecordCount & " registros."

rstODBC.Close

conODBC.Close

wspODBC.Close

End Sub

El Recordset recuperado de un origen de datos remoto se puede controlar de la misma

forma que un Recordset recuperado mediante DAO con el motor de base de datos Microsoft

Jet.

Método OpenRecordset con ODBCDirect:

Además de las opciones disponibles en el método OpenRecordset de un objeto

Database, el método OpenRecordset de un objeto Connection permite recuperar registros

de una base de datos.

Cuando se utiliza un espacio de trabajo de ODBCDirect están disponibles los

siguientes argumentos del método OpenRecordset:

Tipo:

— dbOpenDynamic

Page 65: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

65

Abre un Recordset de tipo dynamic que puede utilizar para agregar, cambiar o eliminar

registros de una o varias tablas de una base de datos subyacente. Un cursor dinámico puede

contener campos de una o más tablas de una base de datos.

Opciones:

— dbRunAsync

Ejecuta una consulta asíncrona. Una consulta asíncrona es aquella en que las

consultas SQL devuelven el control inmediatamente, incluso aunque los resultados no estén

preparados. Esto permite que una aplicación efectúe otros procesos mientras la consulta se

termina.

— dbExecDirect

Ejecuta una consulta; para ello elude SQLPrepare y llama directamente a

SQLExecDirect. Utilice esta opción sólo cuando no vaya a abrir un Recordset basado en

una consulta de parámetros.

® ediciones_bloqueo

— dbOptimisticValue

Utiliza la concurrencia optimista basada en valores de fila.

— dbOptimisticBatch

Activa la actualización optimista por lotes.

Nota El espacio de trabajo predeterminado de ODBCDirect es de sólo lectura. Para

que los usuarios puedan leer y escribir registros en un espacio de trabajo de ODBCDirect,

debe especificarse el tipo de bloqueo dbOptimistic. Para obtener información acerca de los

tipos de bloqueo, veáse el método OpenRecordset en la Ayuda de Visual Basic.

Page 66: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

66

Problemas de rendimiento:

El diseño de una aplicación afecta en gran medida a su rendimiento. Cuando se

desarrollen aplicaciones de base de datos, tengase en cuenta las siguientes sugerencias:

Analícese lo que se requiere: Algunas consultas SQL son más eficientes que otras.

Por ejemplo, ordenar por un campo que contiene un índice es más rápido que

ordenar por un campo que no contiene un índice.

Para obtener más información acerca de la optimización de consultas, busque

Sugerencias de rendimiento y solución de problemas en los Libros en pantalla de

Visual Basic y haga clic en Sugerencias de rendimiento y solución de problemas.

Solicitar únicamente los datos que necesite: No crear Recordsets de tipo dynaset y

snapshot en toda una tabla. El diseño de una aplicación debe permitir al usuario

especificar criterios y devolver un Recordset limitado.

En lugar de seleccionar todas las columnas de un registro, deben seleccionarse

únicamente las columnas necesarias.

El código siguiente crea un Recordset basándose en un valor especificado por el

usuario. Por ejemplo, si el usuario escribe “A”, el código creará un Recordset de

todos los empleados cuyo apellido empiece por “A”:

strSQL = "Select [Apellidos], [Nombre] From Empleados " & _

"Where [Apellidos] Like " & _

"'" & txtName.Text & "'" & "*"

Set recEmployees = dbMydb.OpenRecordset (strSQL,dbOpenDynaset)

Utilizar únicamente la funcionalidad necesaria: Si no se necesita actualizar la base

de datos, ábrase de sólo lectura. Esto mejora el rendimiento, ya que el motor de

base de datos Microsoft Jet no necesita hacer un seguimiento de los bloqueos.

Si no se necesita actualizar un Recordset, ábrase como de sólo lectura.

Si sólo se va a agregar a un Recordset, ábrase con la opción dbAppendOnly.

Utilizar transacciones: Utilizar una transacción reduce el acceso a disco a una vez

por transacción, no una vez por registro, lo cual puede mejorar considerablemente

el rendimiento de una aplicación. Puede que se desee agrupar transacciones. Si una

transacción es demasiado grande, utilizará memoria que pueden necesitar otras

operaciones.

Utilizar consultas almacenadas: En general, es mejor crear consultas almacenadas

que utilizar SQL en el texto. Una consulta almacenada está precompilada, por lo

que ahorrará tiempo de compilación durante la ejecución. Además, normalmente es

más sencillo mantener consultas que están almacenadas en un archivo .mdb que las

creadas mediante aplicación.

Si es posible, utilice consultas almacenadas o SQL para las operaciones por lotes,

como la actualización de un grupo de registros, en lugar de actualizar los registros

de uno en uno con el método Update.

Page 67: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

67

Adjuntar tablas SQL: Adjuntar tablas de bases de datos ODBC a una base de datos

.mdb local. La información de conexión y de definición de datos se mantiene con el

archivo .mdb y, por tanto, mejora el rendimiento.

Escribir sus propias pruebas de rendimiento: Hay muchos factores que afectan al

rendimiento de una aplicación. La mejor manera de averiguar si una característica

mejorará el rendimiento es probarla con los datos de su entorno.

Práctica No. 17

Diseñe el siguiente formulario:

Escriba el siguiente codigo en las declaraciones generales del formulario:

Public CodDML As Integer

Public Mensaje, TituloBarra As String

Function Ver_Forma2()

Form2.Show

End Function

Function Habilita_Textos()

If CodDML = 0 Then

Page 68: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

68

Text1.Enabled = True

End If

Text2.Enabled = True

Text3.Enabled = True

Text4.Enabled = True

End Function

Function DesHabilita_Textos()

If CodDML = 0 Then

Text1.Enabled = False

End If

Text2.Enabled = False

Text3.Enabled = False

Text4.Enabled = False

End Function

Function Descubre_Botones()

Incluir.Visible = True

Anterior.Visible = True

Siguiente.Visible = True

Final.Visible = True

Inicio.Visible = True

Modificar.Visible = True

Excluir.Visible = True

Cerrar.Visible = True

Aceptar.Visible = False

Cancelar.Visible = False

End Function

Function Esconde_Botones()

Incluir.Visible = False

Modificar.Visible = False

Excluir.Visible = False

Anterior.Visible = False

Siguiente.Visible = False

Final.Visible = False

Inicio.Visible = False

Cerrar.Visible = False

Aceptar.Visible = True

Cancelar.Visible = True

End Function

Private Sub Aceptar_Click()

Select Case CodDML

Case CodDML = 0

Data1.Recordset.Update

Case CodDML = 1

Data1.Recordset.Update

Case CodDML = 2

Data1.Recordset.Delete

End Select

Page 69: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

69

MsgBox Mensaje, 0 + 16 + 56, TituloBarra

Call Descubre_Botones

Call DesHabilita_Textos

End Sub

Private Sub Anterior_Click()

If Not Data1.Recordset.BOF Then

Data1.Recordset.MovePrevious

Siguiente.Enabled = True

Final.Enabled = True

If Data1.Recordset.BOF Then

Anterior.Enabled = False

Inicio.Enabled = False

Data1.Recordset.MoveFirst

MsgBox "Inicio de la tabla"

End If

End If

End Sub

Private Sub Buscar_Click()

Call Ver_Forma2

Data1.Recordset.FindFirst "[CEDULA] = 'ABuscar'"

If Data1.Recordset.NoMatch Then

MsgBox "NO se encuentra"

End If

End Sub

Private Sub Cancelar_Click()

Data1.Refresh

Call DesHabilita_Textos

Call Descubre_Botones

End Sub

Private Sub Cerrar_Click()

End

End Sub

Private Sub Excluir_Click()

CodDML = 2

Call Esconde_Botones

Call Habilita_Textos

Mensaje = "El Registro fue Exitosamente Eliminado"

TituloBarra = "Eliminado.."

End Sub

Private Sub Final_Click()

Data1.Recordset.MoveLast

Siguiente.Enabled = False

Final.Enabled = False

Page 70: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

70

Anterior.Enabled = True

Inicio.Enabled = True

End Sub

Private Sub Incluir_Click()

CodDML = 0

Call Esconde_Botones

Call Habilita_Textos

Mensaje = "El Registro fue Exitosamente almacenado"

TituloBarra = "Inclusión de Registros.."

Data1.Recordset.AddNew

End Sub

Private Sub Inicio_Click()

Data1.Recordset.MoveFirst

Anterior.Enabled = False

Inicio.Enabled = False

Siguiente.Enabled = True

Final.Enabled = True

End Sub

Private Sub Modificar_Click()

CodDML = 1

Call Esconde_Botones

Call Habilita_Textos

Data1.Recordset.Edit

Mensaje = "El Registro fue Exitosamente Modificado"

TituloBarra = "Modificación de Registros.."

Text2.SetFocus

End Sub

Private Sub Siguiente_Click()

If Not Data1.Recordset.EOF Then

Data1.Recordset.MoveNext

Anterior.Enabled = True

Inicio.Enabled = True

If Data1.Recordset.EOF Then

Data1.Recordset.MoveLast

Siguiente.Enabled = False

Final.Enabled = False

MsgBox "Final de la tabla"

End If

End If

End Sub

Private Sub Text1_KeyPress(Tecla As Integer)

Page 71: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

71

If Tecla = 13 Then

Text2.SetFocus

End If

End Sub

Private Sub Text2_GotFocus()

Text2.SelStart = 0

Text2.SelLength = Len(Text2.Text)

End Sub

Private Sub Text2_KeyPress(Tecla As Integer)

If Tecla = 13 Then

Text3.SetFocus

End If

End Sub

Private Sub Text3_GotFocus()

Text3.SelStart = 0

Text3.SelLength = Len(Text3.Text)

End Sub

Private Sub Text3_KeyPress(Tecla As Integer)

If Tecla = 13 Then

Text4.SetFocus

End If

End Sub

Private Sub Text4_GotFocus()

Text4.SelStart = 0

Text4.SelLength = Len(Text4.Text)

End Sub

Nota: La codificación anterior contiene algunos errores de forma y de fondo.

Corresponderá al estudiante corregirlas y culminar este ejemplo con o sin ayuda del profesor.

Asimismo, el profesor le explicará, paso a paso, la codificación del mismo.

Práctica No. 18

1. Cree una tabla en Microsoft Access o utilizando el VisData de Visual Basic, denominada

Nomina.Mdb y en ella una tabla del mismo nombre con los campos Id_depart(Text 15) y

dep_desc(text 30).

2. Diseñe el siguiente formulario y establezca en el Data Control la base de datos Nomina y

la tabla del mismo nombre.

Page 72: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

72

3. Escriba en cualquiera de los botones (los cuales son una matríz de controles) el siguiente

código:

Private Sub Barra_Click(Index As Integer)

Select Case Index

Case 0

If Barra(0).Caption = "Nuevo" Then

Data1.Recordset.AddNew

Barra(0).Caption = "Incluir"

Barra(1).Caption = "Cancelar"

CODIGO.Enabled = True

DESCRIPCION.Enabled = True

For a = 2 To 4

Barra(a).Visible = False

Barra(a).Enabled = False

Next

CODIGO.SetFocus

Else

Data1.Recordset!id_depart = CODIGO.Text

Data1.Recordset!dep_desc = DESCRIPCION.Text

On Error GoTo RUTINA_ERROR

Data1.Recordset.Update

On Error GoTo 0

Barra(0).Caption = "Nuevo"

Barra(1).Caption = "Editar"

CODIGO.Enabled = False

DESCRIPCION.Enabled = False

For a = 2 To 4

Barra(a).Visible = True

Barra(a).Enabled = True

Next

End If

Barra(0).Refresh

Page 73: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

73

Barra(1).Refresh

Case 1

If Barra(1).Caption = "Cancelar" Then

CODIGO.Text = ""

DESCRIPCION.Text = ""

Barra(0).Caption = "Nuevo"

Barra(1).Caption = "Editar"

For a = 2 To 4

Barra(a).Visible = True

Barra(a).Enabled = True

Next

Else

Data1.Recordset.Edit

Barra(0).Caption = "Modificar"

Barra(1).Caption = "Cancelar"

DESCRIPCION.Enabled = True

For a = 2 To 4

Barra(a).Visible = False

Barra(a).Enabled = False

Next

DESCRIPCION.SetFocus

End If

Barra(0).Refresh

Barra(1).Refresh

Case 2

Case 3

Case 4

End

End Select

RUTINA_ERROR:

Select Case Err.Number

Case 3022

Msg = "Registro Ya Existe en la Tabla"

MsgBox Msg, , "!!! PANTALLA DE ERRORES !!!"

Err.Clear ' Clear Err object fields

CODIGO.SetFocus

End Select

End Sub

Page 74: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

74

SSQQLL

SQL es un lenguaje de programación de base de datos cuyas iniciales vienen de las

palabras inglesas Structured Query Language, que se puede traducir como Lenguaje

Estructurado de Búsqueda o Consulta. Este lenguaje está estrechamente relacionado con la

invención de la base de datos relacional hecha por E.F. Cood a principio de 1970.

El moderno SQL ha evolucionado ampliamente como un estandard en el manejo de

bases de datos relacionales, y está definido por los estandares ANSI. La mayoría de las

implementaciones de SQL tienen pequeñas diferencias de los estandares definidos

incluyendo la version soportada por el motor de bases de datos Microsoft Jet.

SQL Vrs. Navegación:

El motor de base de datos Microsoft Jet provee dos metodos separados para llevar a

cabo la mayoría de tareas relacionadas con las bases de datos:

El modelo navegacional que consiste en ir accesando los registros de la base de datos.

El modelo relacional que está basado en el lenguaje estructurado de búsqueda.

Para los programadores que están familiarizados con sistemas de bases de datos

basados/orientados a archivos como Dbase, Foxpro o Paradox podrían sentirse más comodos

utilizando el metodo navegacional. Sin embargo, en la mayoria de los casos el equivalente

utilizadndo el metodo SQL es mas eficiente y po lo tanto deberian ser tuilizados donde el

rendimiento o tiempo de respuesta es importante. Adicionalmente, SQL tiene la ventaja de

ser la interfase estandar de base de datos de diferentes porveedores, por lo tanto, el

conocimiento de comandos SQL permiten accesar y manipular una gran variedad de

productos de bases de datos.

Codificando consultas con SQL:

El SQL es usado para crear objetos QueryDef utilizandolo como parametro en el

metodo Recordset o en la propiedad de un Data Control. Tambien puede ser utilizado con el

metodo Execute para crear o manipular directamente bases de datos JET y para crear

consultas por Selección o por Acción.

Operaciones DML:

El SQL Data Manipulation Language (Lenguaje de manipulación de datos) son

utilizados para consultar, actualizar, crear o eliminar registros en las tablas de una base de

datos. Esto se realiza mediante el uso de varias instrucciones, pero la mayoría de ellas se

usan con la estructura general del query Select.

COMANDO DESCRIPCIÓN

CREATE Se usa para crear nuevas tablas, campos e

Page 75: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

75

índices.

DROP Se usa para borrar tablas e índices.

ALTER Se usa para modificar tablas, añadiendo campos

o cambiando las definiciones.

SELECT Se usa para crear consultas a la base de datos,

según un criterio especificado.

INSERT Se usa para cargar datos en la base de datos.

UPDATE Se usa para actualizar registros de tablas.

DELETE Se usa para borrar registros de tablas.

Operadores lógicos:

AND

OR

NOT

Los operadores lógicos se utilizan para conectar expresiones, usualmente en la claúsula

WHERE. Ejemplo:

SELECT *FROM MyTable WHERE condition1 AND condition2

Operadores de comparación:

< Menor que

<= Menor o igual que

> Mayor que

>= Mayor o igual que

<> Diferente de

BETWEEN Entre

LIKE Parecido a

IN En

Ejemplo:

SELECT *FROM MyTable WHERE PubId = 5

Sintaxis:

SELECT SELECT [ALL] | DISTINCT | DISTINCTROW | [TOP n [PERCENT]]]

{*| Table.*}| [Table.]field1 [AS alias1] [,[table.]field2[AS alias2][,...]]}

FROM tableexpresion [, ...] [IN externaldatabase]

[WHERE ...]

Page 76: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

76

[GROUP BY ...]

[HAVING ...]

[ORDER BY ...]

[WITH OWNERACCESS OPTION]

SELECT field1[, field2[, ...]] INTO newtable [IN externaldatabase] FROM source

INSERT INTO target [IN externaldatabase] [(field1[,field2[, ...]])]

SELECT [source.]field1 [,field2[, ...]

FROM tableexpresion

Single record append query:

INSERT INTO target [(field1[,field2[, ...]]) VALUES (value1[,value2[, ...]])

DELETE [table.*] FROM table WHERE criteria

UPDATE table SET newvalue WHERE criteria;

Ejemplos SQL:

1. SELECT *FROM empleados;

2. SELECT empleados.depto, supervisores.supnombre FROM empleados;

INNER JOIN supervisores ;

WHERE empleados.dpto = supervisores.depto;

3. SELECT BirthDate AS Birth FROM empleados;

4. SELECT COUNT(empleadosID) As HeadCount FROM empleados;

5. SELECT LastName, FirstName, Title, Salary FROM empleados;

AS T1 WHERE Salary >= (SELECT Avg(Salary) FROM empleados;

WHERE T1.Title = empleados.titles) ORDER BY Title;

6. SELECT LastName, Salary FROM empleados WHERE Salary > 100000;

7. SELECT * FROM Orders WHERE ShippedDate = DateValue(„01/02/1999‟);

8. INSERT INTO Customers SELECT * FROM [New Customers];

9. INSERT INTO empleados (FirstName,LastName, Title);

VALUES („Gómez‟,‟Enrique‟Enrique‟,‟Profesor‟);

10. SELECT Title, Count(Title) AS Total FROM empleados;

WHERE Region = „Heredia‟;

GROUP BY Title;

HAVING Count(Title) > 1;

11. SELECT Count(*) AS TotalOrders FROM orders;

12. SELECT IIF(PostalCode BETWEEN 98101 AND 99100, „Local‟, „NonLocal‟);

FROM publishers;

13. SELECT sum(UnitPrice*Quantity) AS [Total UK Sales];

Page 77: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

77

FROM orders;

INNER JOIN [Orders Details];

ON orders.OrderId = [Orders Details]. OrderId;

WHERE (ShipCountry = „UK‟);

14. SELECT LastName, FirstName FROM empleados;

WHERE LastName LIKE „[A-D]*‟;

15. SELECT Avg(Freight) AS [Average Freight] FROM orders WHERE Freight > 100;

16. SELECT Count (ShipCountry) AS [UK Orders];

FROM orders WHERE ShipCountry = „UK‟;

17. SELECT DISTINCTROW CompanyName FROM customers;

INNER JOIN orders;

ON customer.customerID = orders.customerID;

ORDER BY CompanyName;

18. UPDATE orders;

SET orderAmount = orderAmount * 1.5;

Freight = Freight + (Freight * .10);

WHERE shipcountry = „UK‟;

Page 78: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

78

ACCESOS EXTERNOS:

Page 79: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

79

Page 80: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

80

Page 81: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

81

Page 82: INSTITUTO SUPERIOR TECNOLÓGICO NORBERT …wiener.edu.pe/manuales/CicloII/LENGUAJE-DE-PROGRAMACION-II-VIS… · ejemplo, Btrieve, dBase, Microsoft Visual FoxPro, Paradox, entre ...

Manual del Alumno

82