25 marzo 2007

ADO 3, consultando datos 1

Sé que el título parece marcador final de un partido de fútbol, pero no es así. Todo se trata del famoso ADO combinado con VB 6.0 y SQL.

Hace algunos mensajes, escribí acerca de la manera de trabajar con ADO. Hablé (bueno, escribí) acerca de la manera de añadir referencias a un proyecto VB 6.0, declarar los objetos como globales en un módulo (cosa que nos va a ahorrar muchas líneas de código más adelante), inicializar los objetos al arrancar el programa y hasta insertamos un registro con un comando SQL. Aquí voy a seguir con el mismo proyecto, ahora le agrego una consulta. Probablemente para poder entender este mensaje, tienes que leer el anterior. Ese lo puedes leer aquí y si no te quedó claro, el primer artículo de esta serie de ADO lo puedes leer aquí.

Pues bien, siguiendo con el proyecto del sistema para la taquería de doña Amalia, proyecto que puedes bajar, en la fase actual que no está terminada del todo, pero que tiene lo que voy a explicar aquí, lo puedes bajar en este sitio.

Lo que voy a hacer en esta parte del proyecto es agregar una ventana que me permita buscar a un proveedor (consulta) ya sea por número de proveedor (mi llave primaria de la tabla Proveedor) o bien que pueda escribir el nombre del cliente. Pero como eso de escribir el nombre del cliente puede ser confuso, voy a poner un ComboBox con los nombres de todos los proveedores, ordenados alfabéticamente, para que seleccione el que desea consultar. Todavía no busca proveedores, solo abre una ventanita que inicializa la lista de proveedores. Sin embargo, de la misma manera en que se inicializa el control con los proveedores se pueden también generar consultas para hacer casi lo que quieras (menos conquistar el mundo, pero tal vez algún día...).

Para empezar, se necesita el código para abrir la nueva ventana que acabo de crear. Sé que esto no tiene ningún chiste. Solo llamo al método Show de frmBuscaProveed (así nombré la ventana, o Form, que tiene la lista de proveedores). Si quieres más datos acerca del método Show, dale click aquí. Este el el código, puesto en el botón que llamé btnBuscar:


Este código hace que aparezca esta ventana (aquí está en el modo de diseño):


Ahora sí, voy a escribir el código que va a llenar el ComboBox (que nombré cboNombres). Aquí pongo el código y abajito explico todo a detalle (bueno, espero que con el detalle suficiente).


Como hicimos al insertar un registro, a la propiedad CommandText de mi objeto Command (en mi caso, se llama cmdCommand) le asigno la instrucción SQL que va a llevar a cabo, en este caso: SELECT Nombre FROM Proveedor ORDER BY Nombre. Esto me devuelve todos los valores del campo Nombre de la tabla Proveedor ordenados por el campo Nombre. ¿Fácil? Ya lo creo.

A diferencia de insertar registros, cuya instrucción, INSERT INTO, no devuelve valores, tengo que abrir los resultados en un objeto RecordSet (o sea, la tabla) que en este proyecto se llama tblTable. Si una instrucción SQL no devuelve registros, uso el método Execute del objeto Command, pero si el una instrucción SELECT, tiene que abrirse en una tabla. Para eso uso el método Open de un RecordSet. Así como lo escribí lo vamos a escribir de forma idéntica siempre (bueno, si le cambiaste le nombre a las variables, serí lo único que cambiaría). Pero por aquello del no te entumas, voy a explicar la sintaxis completa.

cmdCommand se refiere a mi objeto Command que tiene la instrucción SELECT que deseo ejecutar. Si no quisiera usar el objeto Command, podría escribir la cadena con la instrucción SQL directamente allí (encerrado entre comillas, obviamente). Luego dejo el siguiente parámetro en blanco (por eso ves repetidas dos comas) porque tendría que especificar la conexión deseada (ActiveConnection). Esto lo usaría en el caso que escribiera el comando SQL como el primer parámetro, pero como estoy usando el objeto Command, la cual ya tiene una ActiveConnection asignada.

adOpenStatic le dice al DBMS que solo voy a hacer una consulta, es decirt, quiero una copia estática de los datos requeridos. En lugar de este parámetro, hay otros que permiten modificar los datos de la tabla desde esta consulta, pero no es nuestro caso. El penúltimo parámetro (que es el último que estoy usando), adLockBatchOptimistic, especifica la manera en que se van a bloquear los registros. Con esta constante, le estoy diciendo al DBMS que lo resuelva de la mejor manera en que crea conveniente. Pero, ¿qué es esto de bloquear registros? Imagínate que tu sistema, cuya base de datos está en un servidor accesible por varios clientes, tiene un registro de una tabla que quieren modificar dos personas al mismo tiempo. Vas a tener un pequeño problema porque si uno quiere modificar el campo RFC, por ejemplo, y otro quiere modificar el campo Tel al mismo tiempo, el DBMS tiene que decidir quién puede cambiar, o si ambos pueden hacerlo, o que forma resolver la bronca. Algunas DBMSs viejitos bloquean toda la tabla, o sea que cuando yo altero un registro, nadie puede actualizar nada de la tabla aunque no estén trabajando en el mismo registro que yo. Otros bloquean el registro (nadie puede modificar el mismo registro que yo, aunque puede modificar otros de la misma tabla). Otros más bloquean solo el campo que está siendo alterado (varios pueden modificar datos del mismo registros con tal que no sean el mismo campo).

El último parámetro, el que omití, es para poner constantes que permiten opciones avanzadas, Nosotros, pese a lo avanzados que estamos, no lo vamos a usar.

Eso fue lo más difícil. Después de esto, comienzo a deambular por un ciclo While que me permite ir de registro en registro hasta el final de la tabla (cuando se cumpla la propiedad EOF o End Of File, fin de archivo). Dentro del ciclo, uso el método AddItem del ComboBox, en mi caso llamado cboNombres, para agregar el nombre al ComboBox. Después de esto, le indico que avance al siguiente registro de la tabla con el método MoveNext del RecordSet.

Al terminar de agregar todos los nombres (cuando se la propiedad EOF es verdadero), cierro el RecordSet (¡que nunca se te olvide cerrarlo!) y le digo a cboNombres que despliegue el elemento de la lista de nombres (o sea, el primero) usando la propiedad ListIndex del ComboBox.

Una nota adicional. Cuando estás trabajando con ComboBoxes con registros, no quiere que el usuario pueda teclear lo que se le pegue la gana, así que puedes cambiar la propiedad Style sea igual a 2 (o sea, Dropdown list), el cual no le permite al usuario teclear nada que no esté en la lista. Y luego, al cambiar la propiedad ListIndex como hice arribe, te evitas la flojera de tener que validar en otro lado si la lista tiene un elemento seleccionado o no.

Ok, ya pasó lo peor (o lo mejor, dependiendo de tu punto de vista). Ahora voy a jugar con mis OptionButton, los cuales me permiten elegir una u otra búsqueda (o sea, por número o nombre). Es buena idea usar OptionButtons para esto porque al asignar la propiedad Value a verdadero en uno de ellos ya garantizas que hay uno elegido, cosa que se te simplifica a la hora de validar. Pero para no confundir al usuario, o sea a doña Amalia, vamos a bloquear cboNombres desde el principio y dejar habilitado txtNo (caja de texto donde van a escribir el número de proveedor). Si seleccionan la opción de búsqueda por nombre, optNombre, habilita cboNombres y deshabilita txtNo. Este es el código:


Dejé al final el código que puede ser el más complicado, pero estoy seguro que tu, querido lector, no tendrás problemas en resolver. Se trata del código del botón Cancelar (btnCancelar), la cual cierra la ventana frmBuscaProveed sin hacer ninguna consulta. Para esto, lo descargo, lo elimino de la memoria. Para esto sirve la función Unload y lo escribiría así:


¿Por qué decidí quitarlo de la memoria y no simplemente esconderlo (con el método Hide)? Es que quiero que cada vez que se cargue esta forma a la memoria se actualice cboNombres (o sea que ejecute la función Form_Load donde inicializo cboNombres).

¡Listo! Creo que expliqué todo, pero si tienes dudas, no dudes (valga la redundancia) en mandarme un i-meil o dejarme un comentario aquí. Más adelante terminaremos esta ventana de búsqueda para que muestre los datos del proveedor, así que no te lo pierdas y mantente al tanto de mi blog.

¡Hasta la próxima!
Publicar un comentario
Related Posts Plugin for WordPress, Blogger...