El Administrador de Datos 1. Introducción Visual Basic puede acceder a distintos tipos de bases de datos. El acceso más sencillo es a una base de datos creada con el MotorJet que incorpora Visual Basic y que es compartido por Access, es decir, si quieres crear una base de datos con Access o en el Administrado de datos de Visual Basic el acceso a la misma será inmediato. Otro tipo de bases de datos con las que se puede acceder con Visual Basic son las llamadas bases de datos ISAM (Método Secuencial Indexado), entre las que se incluyen Btrive, dBASE, Foxpro y Paradox. El otro tipo de acceso es a una base de datos compatible con ODCB (Conectividad abierta de bases de datos), en las que es necesario un controlador ODCB para el tipo específico de base de datos. Si tienes dicho controlador el acceso también será inmediato. 2. Diseñar la base da datos El MotorJet de Visual Basic es un completo sistema gestor de bases de datos con el que se puede crear y manipular una base de datos. La creación de una base de datos es un proceso en el cual podemos diferenciar dos partes: El análisis y el diseño Se realiza el análisis de la base de datos cuando se piensa en qué se necesita alamacenar para tenerlo disponible en cualquier momento. El diseño es el proceso dependiente del tipo de base de datos que vayamos a utilizar, que casi con toda seguridad será relacional. Al crear una base de datos relacional tienes que trabajar con tablas, registros, campos, índices, etc. 3. Conocer el Administrador Visual Basic incorpora el Administrador de datos con el que puedes crear y establecer las propiedades de las tablas que conformen la base de datos. Sin embargo, si tienes Microsofr Access es recomendable utilizarlo en lugar del Administrador de Datos, ya que genera el mismo tipo de base de datos pero con una facilidad y flexibilidad mucho mayor. Para acceder al Administrador de Datos lo haremos mediante la opción de mismo nombre en el menú Complementos. 1 El administrador de datos nos permite modificar una base de datos ya creada o crear una nueva. Una base de datos creada con el MotorJet está compuesta por un único archivo con extensión *.MDB. Una base de datos MDB se compone de un conjunto de tablas y de QueryDef. Las tablas son la estructura fundamental de las bases de datos, formadas por distintos campos y sus valores en los registros introducidos. Las QueryDef son instrucciones SQL, que han sido guardadas con un nombre al tener interés en utilizarlas en futuras ocasiones. SQL es un lenguaje que nos permite entre otras cosas extraer resultados de una base de datos. 4. Crear una base de datos Lo primero que tienes que hacer para crear una base de datos es indicar dónde se guardará el archivo y darle un nombre válido. Una vez hayas creado el archivo de la base de datos, es el momento de ir construyendo las tablas que formarán las misma. Tienes que introducir el nombre de la nueva tabla, los campos que quieres que aparezcan en la aplicación. Puedes utilazar más de una tabla para los nombres de los campos. Deberás seleccionar el o los campos que quieras incluir y pasarlos a campos seleccionados. Acceso a bases de datos 1. El control DATA Con el control Data, podemos acceder a una base de datos, mostrar su información, introducir nuevos registros, etc, y todo sin programar ni una sóla línea de código. Los pasos a seguir para utilizar una base de datos en Visual Basic son: a.- Dibujar el control data y establecer la conexión a la base de datos apropiada. b.- Utilizar otros controles para manejar la información. Estos controles son conocidos como controles enlazados, al depender del control data como origen de los datos que muestran. El control data posee varios controles al estilo de un reproductor de vídeo para acceder a los registros anterior, posterior, primero y último. Las propiedades del control data que tienes que establecer para realizar la conexión con la base de datos son: Connect: Indica el tipo de base de datos a la que vamos a acceder. Por omisión es Access. DatabaseName: Indica el archivo de base de datos a la que se quiere acceder indicando la ubicación exacta del archivo. RecordSource: Permite indicar el conjunto de datos específico de la base de datos 2 indicada en la anterior propiedad. Normalmente será el nombre de una tabla de la base de datos o una instrucción SQL. Estableciendo adecuadamente el valor de estas tres propiedades tendremos la conexión con la base de datos que queramos. Si conoces la base de datos y el conjunto de datos a los que quieres tener acceso en tiempo de diseño puedes utilizar la ventana de propiedades para establecer estas propiedades, en caso contrario lo puedes hacer con código escrito. 2. Controles Enlazados Una vez establecida la conexión a la base de datos e indicando el conjunto de datos a los que vamos a tener acceso mediante el control data, es necesario utilizar otros controles para mostrar o introducir dicha información. Estos controles son conocidos como controles enlazados, ya que el origen de la información que muestran est&a ligado a un determinado control data. Normalmente se utilizan cuadro de texto, cuadros de lista e incluso controles imagen para mostrar el contenido de la base de datos a la que quieres acceder. Todos estos controles pueden actuar como controles enlazados. Exiten dos propiedades que tienes que modificar para enlazar los controles con el control data: DataSource: Indicaremos el control data que actuará como origen de los datos. DataField: Campo específico al que se enlaza el control. Por ejemplo: txtNombre.DataSource = datEmpleados txtNombre.DataField = "Nombre" Aquí se indica que se ligue el control txtNombre al campo Nombre de la tabla Empleados que se accede mediante el control data (datEmpleados). Este control deberá tener correctamente establecidas las tres propiedades anteriormente citadas. 3. RecordSets Al utilizar un control data y establecer la conexión con la base de datos, estás indicando el conjunto de datos sobre los que quieres tener acceso. En Visual Basic a dicho conjunto de datos se les denomina RecordSet, siendo una propiedad del control data. Existen tres tipos de Recordset: Table, Dynaset y Snapsoht. Dicho tipo se establece mediante la propiedad RecordsetType del control data, que predeterminadamente tiene el valor Dynaset. Un Recordset tipo Dynaset es un conjunto dinámico de registros que representan una determinada tabla o el resultado de una consulta, según se haya establecido la propiedad RecordSource del control data. Puedes agregar nuevos registros, modificar los campos existentes e incluso eliminar registros y todos estos cambios se reflejan en la base de datos afectada. Un Recordset de tipo Table representa una determinada tabla de base de datos. Al crear un Recordset de este tipo estarás representando dicha tabla, cargándose en memoria un solo registro que se corresponde con el registro actual. Toda modificación que se realice 3 se verá reflejada en la tabla. Finalmente el tipo Snapshot crea una copia estática del conjunto de datos al que se accede mediante el control data. En este caso no puedes actualizar la base de datos, sólo puedes visualizar los datos obtenidos. 4. Modificar la base de datos Si crear un Recordset de tipo Table o Dynaset, podrás modificar la base de datos subyacente sin tener que programar ni una sóla línea de código. Al ejecutar la aplicación, puedes desplazarte a través de los registros utilizando el control data, cualquier modificación que realices se verá reflejada en la base de datos al acceder al nuevo registro. Mediante la propiedad DataChanged de un control enlazado, si el valor mostrado por dicho control ha sufrido modificaciones respecto al valor original. En caso afirmativo dicha propiedad entrará en valor True. 5. Añadir registros Se pueden agregar nuevos registros a la base de datos sin tener que programar para ello. En este caso tienes que situarte en el último registro y moverte al siguiente. Si estableces correctamente la propiedad EOFAction al realizar dicha acción se creará un nuevo registro al que se le puede introducir nueva información. La propiedad EOFAction puede tener tres valores y nos indica lo que debe ocurrir cuando se llega al final de un Recordset del control data: Si EOFAction tiene un valor MoveLast, mantiene el último registro como registro actual sin desplazarse al siguiente registro, que no existe, aunque pulsemos el botón del control data para desplazarnos al próximo registro. Si el valor EOFAction deja el registro actual invalidado (ya que dicho registro todavía no existe), y desactivas el botón que nos permite desplazarnos al siguiente tienes que controlar esta situación mediante código ya que cualquier intento de acceder a la información del registro actual producirá un error al no ser un registro válido. Si EOFAction posee el valor AddNew, esntonces cuando te desplaces más allá del último registro, Visual Basic creará un registro nuevo en la base de datos, donde puedes introducir la nueva información. El valor AddNew es el que nos permite añadir nuevos registros a la base de datos sin tener que programar para ello. Para crear un nuevo registro tienes que sobrepasar el último registro que tengas en esos momentos, entonces Visual Basic limpiará el valor de los controles enlazados permitiéndote introducir la información del nuevo registro. Cuando te muevas a otro registro se añadirá a la base de datos. Al igual que se puede indicar que debe ocurrir cuando se llegue al final de un recordset, también podrás hacerlo cuando se llega al principo mediante la propieda BOFAction del control data de la misma forma que EOFAction. 4 Programar con la base de datos 1. Moverse por un RecordSet El control data nos permite movernos por un recordset de una forma rápida y sencilla a través de sus botones. Sin embargo en muchas ocasiones tendrás que escribir código en el que es necesario moverse a un determinado registro rápidamente. Para ello es necesario entender que aunque un recordset es una propiedad de control data, también tiene carácter de objeto, por lo que serán aplicables otras propiedades y métodos. La forma de hacerlo será con la síntaxis estándar: NombreControlData.Recordset.NombrePropiedad NombreControlData.Recordset.NombreMétodo Donde tanto el NombrePropiedad como el NombreMétodo son del recordset u no del control data. Los métodos que puedes utilizar para desplazarte por un recordset son: MoveFirst: Nos desplazamos al primer registro del recordset. MovePrevious: Nos desplazamos al registro anterior del recordset. MoveNext: Nos desplazamos al siguiente registro del recordset. MoveLast: Nos desplazamos al último registro del recordser. Move fila [,inicio]: Permite desplazarnos un número específico de registro hacia delante o hacia atrás respecto al marcador de inicio. El marcador BOF nos indica que estamos al principio del recordset y el marcador EOF nos indica que estamos al final. Si situas el registro actual en dichos marcadores, no se producirá un error pero no podrás acceder a la información del registro actual ya que no es un registro válido. Si se sobrepasa dichos marcadores se producirá un error en tiempo de ejecución. Hay que utilizar las propiedades BOF y EOF para prevenir este tipo de errores. La acción indicada por el valor de las propiedades BOFAction y EOFAction del control data se ejecutan cuando el registro actual se sitúa en los marcadores BOF y EOF respectivamente. Recuerda que BOFAction y EOFAction son propiedades del control data mientras que BOF y EOF son del recordset. 2. Buscar Registros Para buscar registros puedes utilizar los métodos Find cuando trabajes con recordset de tipo Dynaset o Snapshot, o utilizar el método Seek para un recordset de un tipo Table. El método Find presenta cuatro variantes: FindFirst: Busca el primer registro que cumple determinado criterio. FindLast: Busca el último registro que cumpla un determinado criterio. FindNext: Realiza la búsqueda hacia delante. FindPrevious: Realiza la búsqueda hacia atrás. 5 Vamos a ver el siguiente ejemplo: With.datEmpleados .Recordset.FindFirst "Nombre = ' " & txt.Nombre.Text & "'" If Recordset.NoMatch Then MsgBox "Lo siento no es un nombre de empleado válido" Exit Sub End If End With Mediante el uso de la estructura With nos evitamos tener que repetir código. Así no será necesario escribir la estructura datEmpleados hasta que lleguemos a End With. En la línea .Recordset.FindFirst "Nombre = ' " & txt.Nombre.Text & "'" es donde se produce la búsqueda de un determinado registro del recordset. Al utilizar el método FindFirst se está indicando que se efectúe la búsqueda del primer registro cuyo valor en el campo Nombre coincide con el valor que se ha introducido en el txtNombre. Con el uso del operador & concatenamos para crear el criterio de búsqueda, si por ejemplo se hubiera introducido el valor Coral en el cuadro de texto, esta línea quedaría de la siguiente forma: datEmpleados.Recordset.FindFirst "Nombre='Coral'" Luego utilizamos el método Nomatch del recordset para comprobar, una vez realizada la búsqueda, si se ha encontrado un registro o no. Si no se ha encontrado el registro, el método nomatch devolverá True por lo que se mostrará un menseja mediante el MsgBox y se saldrá del procedimiento utilizando el método Exit Sub. 3. Añadir registros El valor AddNew en la propiedad EOFAction del control data nos permitía agregar registros, pero esta forma sólo es adecuada cuando estamos accediendo a una única tabla en el recordset. El objeto recordset contiene el método AddNew que permite la creación de un registro nuevo en blanco donde puedes asignar los valores a sus campos. Una vez introducida dicha información, tendrás que hacer uso del método Update del recordset, con el objetivo de que el nuevo registro se actualice en la tabla. Si no utilizas Update el nuevo registro no se agregará finalmente. El código será: datEmpleados.Recordset.Update Tienes que tener en cuenta que el hecho de agregar un nuevo registro no implica que éste se convierta en el registro actual del recordset. Si quieres que el nuevo registro sea el registro actual puedes utilizar la propiedad del recordset LastModified. El código será: datEmpleados.Recordset.Bookmark = datEmpleados.Recordset.LastModified 6 La propiedad Bookmark se usa para saltar rápidamente al nuevo registro indicado por el marcador LasrModified. Boolmark te permite guardar el puntero del registro actual y colocarse rápidamente en un registro específico. El código será: Dim registoActual registroActual = datEmpleados.Recordset.Bookmark Aquí se guarda el registro actual datEmpleados.Recordset.MoveFirst Desplazamos al registro actual datEmpleados.Recordset.Bookmark = registroActual Vuelve al marcador guardado 4. Eliminar Registros Mediante el método Delete, puedes borrar un registro entero de un recordset. En este caso te tienes que situar en el registro y hacer uso de éste método. Tienes que tener cuidado a la hora de eliminar un registro, ya que el registro actual sigue siendo el registro eliminado, por lo que cualquier intento de acceder a la información del registro actual provocará un error de ejecución. Para evitar éste problema es conveniente desplazarno a un registro válido una vez hayas utilizado el método. No es necesario el uso de Update para hacer efectiva la eliminación. Un código de ejemplo sería: If datEmpleados.Recordset.EOF = False datEmpleados.Recordset.Delete If datEmpleados.Recordset.EOF = True Then cmdEliminar.Enabled = True End If datEmpleados.Recordset.MoveLast End If En la primera línea se comprueba si el recordset está vacío, es decir, si la propieda EOF tiene su valor a True. En el caso de que el recordset no esté vacío, se realiza la eliminación del registro actual, más tarde se vuelve a comprobar si el recordset está vacío ya que se podía haber borrado el único registro que contenía. Finalmente no movemos al último registro con MoveLast, ya que el registro actual no es válido al haber sido eliminado. En el caso de no existir ningún registro válido MoveLast nos situará en el marcador EOF. Opciones avanzadas base de datos 1. Cuadrícula enlazada a datos En algunas ocasiones desearás mostrar más de un registro a la vez, con sus correspondientes campos. Para ello Visual Basic incorpora un nuevo control llamado 7 Cuadrícula, que se presenta en dos versiones: enlazada y no enlazada Las dos permiten mostrar información de forma tabular, es decir, con un conjunto de filas y columnas. La versión enlazada (DBGrid), es más apropiada cuando deseamos mostrar información proveniente de una determinada base de datos. Al utilizar dicho control puedes mostrar en cada una de sus columnas un campo y en cada una de las filas un registro del recordset del que haya sido enlazado. El control Cuadrícula enlazada a datos no aparece en la caja de herramientas estándar ya que es un control personalizado con el siguiente aspecto: Deberás agregarlo manualmente a la caja de herramientas, su nombre es Data Bound Grid. El control cuadrícula enlazada a datos aparece inicialmente con dos filas y dos columnas. Se puede modificar en tiempo de diseño esperar que en tiempo de ejecución, cuando se enlace con un determinado recordset se ajuste al mismo. El primer conjunto de propiedades interesantes de este control es el que establece su comportamiento en tiempo de ejecución. Las propiedades AllowAddNes, AllowDelete y AllowUpdate nos indican si en tiempo de ejecución se va a permitir añadir, eliminar o actualizar respectivamente el registro de la cuadrícula. La propiedad que establece el enlace con el correspondiente control data es, al igual que en el resto de controles enlazados DataSource. Sin embargo, no presenta la propiedad DataField ya que cuando utilices una cuadrícula es para mostrar un conjunto de registros, que seguramente tendrán más de un campo. 2. Consultas en SQL Cuando quieras mostrar información que provenga de más de una tabla, no tienes más remedio que utilizar el lenguaje SQL para establecer la correspondiente consulta en la propiedad RecordSource de un control data. SQL es un lenguaje que pretende ser estándar en el acceso a bases de datos relacionales, de forma que independientemente del origen de la información, puedas acceder a ella a través de instrucciones SQL. Puedes establecer la propiedad RecordSource del control data en tiempo de ejecución y darle el valor de una determinada instrucción SQL, de esta forma el usuario puede especificar lo que quiere extraer de la base de datos. Una vez establecida la propiedad RecordSource, tienes que utilizar el método Refresh del control data para crear el objeto recordset, al haber cambiado la propiedad del recordsource. La instrucción que se utiliza para crear consultas de selección SQL es SELECT. La síntaxis de esta instrucción es la siguiente: SELECT -columnasFORM -tablas[WHERE -condiciones-] [ORDER BY -columnas-] 8 La instrucción SELECT comienza con dicha palabra y un conjunto de columnas, es decir, el conjunto de campos que queremos que muestre la consulta como resultado de la misma. Seguidamente aparecere la cláusula FORM, que identifica las tablas sobre las que se realiza la consulta. Los campos especificados en la cláusula SELECT deben pertenecer a las tablas especificadas en FORM. Seguidamente nos encontramos con dos cláusulas opcionales como nos indican la presencia de cochetes. La cláusula WHERE especifica el criterio que debe cumplir para que un determinado registro aparezca en el resultado de la consulta. Normalmente serán expresiones de comparación del tipo NombreCampo = Valor o usando ciertas funciones de SQL. La cláusula ORDER BY especifica en qué orden aparecerán los resultados de una consulta. Tienes que especificar el campo o conjunto de campos por los que se ordenan los registros de la consulta. También puedes indicar si el orden es ascendente o descendente. Vamos a ver un ejemplo: SELECT Nombre FORM Empleados Se especifica que se muestre el campo Nombre de los registros que pertenecen a la tabla Empleados. Si quieres que se muestra más de un campo, hay que separarlos por comas, y si quieres que se muestren todos los campos de una tabla se puede utilzar el caráter *. Así, la consulta devolverá todos los campos de la tabla Empleados. SELECT Empleados.Nombre, Empleados.[fecha alta] FORM Empleados,TiempoAlta WHERE Empleados.Puesto = TiempoAlta.Puesto En esta caso se está pidiendo que se muestren los campos Nombre y TiempoAlta de los registros situados en la tabla Empleados y cuyo Puesto exista en algún registro de la tabla Puesto. Si se utilizan más de una tabla de consultas es conveniente indicar el nombre de la tabla en la cláusula SELECT junto al nombre del campo que quieres mostrar, por que las dos tablas podrían tener el mismo nombre para uno o más campos. Si el nombre de un campo está compuesto por más de una palabra, tienes que utilizar corchetes para delimitarlo. Todas las tablas implicadas aparecen en la cláusula FORM separadas por comas. La cláusula WHERE presenta el criterio de comparación. 3. Validar el control Data Cuando se intereactua con el control data en un formulario podemos utilizar alguno de sus eventos para establecer niveles de validación de los datos que se han introducido o modificado. El evento más utilizado es validate. Sucede siempre antes de que el registro actual cambie. 9 Veamos un ejemplo: Private Sub datEmpleados_Validate(Action As Integer, Save As Integer) Dim respuesta As Integer If Save = True Then respuesta = MsgBox("Quieres guardar los cambios", vbYesNo) If respuesta = vbNo Then Save = False End If End If End Sub El procedimiento de evento Validate contiene dos parámetros: Action que indica por qué se ha producido el evento y Save que indica se se debe o no modificar la base de datos. Así el código utiliza el parámetro Save y permite confirmar, por parte del usuario, que se lleve a cabo la modificación que se ha realizado. Se se responde No, los cambios no tienen efecto al establecer el valor False del parámetro Save. También se pueden crear reglas de validación al crear una tabla. Así puedes introducir reglas de validación junto al menseja que debe aparecer si se infringen, reglas de integridad referencial, etc... 10