31 agosto 2007

Una aplicación sencillita usando Visual Basic 6

Solo para arrancar, aquí hay un ejemplo de como crear un programita muy sencilla usando Visual Basic 6.

Se trata de un programa que calcula el cuadrado y el cubo de un numero. Creo que está muy fácil, pero si tienes dudas, déjame un mensaje.

Aquí está el video (por si no aparece abajo) y aquí puedes bajar los archivos del proyecto. ¡Hasta la próxima!


26 agosto 2007

¿Qué es un GUI? ¿No es una grosería?

Aunque suene medio feo, GUI es un acrónimo jalado para decir interfaz gráfico (Graphical User Interface, por aquellos que les guste el lenguaje de Shakespeare) y ningún programa hoy en día puede ser concebido sin una interfaz gráfica y sin un mouse que mover por el escritorio. Antes, en mis tiempos mozos, todos los programas eran de puro texto y uno tecleaba comandos crípticos y extraños a una computadora con un monitor que solo mostraba letras verdes... pero ¡ya no más! Ahora somo de la nueva era de dibujitos en la pantalla.

Ciertamente las interfaces gráficas nos hacen la vida mucho más sencilla (bueno, casi a todos. Los ciegos son los que más batallan, pero se están desarrollando cosas chidas para ellos, como dice aquí) y es por eso que desde que se comenzaron a usar, muchas más personas han entrado a la carrera cybertecnológica y han estado divirtiéndose con su compu, cosa que difícilmente podrían hacer si estuvieran preocupados por memorizar cien mil y pico de instrucciones textuales. Este tipo de interfaces son más intuitivos y sencillos de usar. Podemos resumir diciendo que las interfaces gráficas es la parte visual del programa con la que interactúa el usuario y contiene formas y controles.

Una interfaz gráfica se compone de controles. Pero, ¿qué es un control? Los controles nos rodean por doquier, por ejemplo, hay controles de la TV, la videocasetera, el DVD, la onda del satélite (si tienes tele con SKY o DirectTV), el estéreo de la casa y el del carro, la de la videocámara... Pese a que todos estos controles nos simplifican la vida (o nos vuelve más huevones, según tu punto de vista), no son usados en interfaces gráficas. Para nosotros (por lo menos en lo que se refiere a la programación visual) un control es un objeto visual en la pantalla que le ayuda al programa comunicarse con el usuario ya sea aceptando datos de entrada o desplegando información. Como podrás imaginar, sin controles, los programas no serían muy útiles.

Multitarea y multiprocessing
Cuando hay un programa, como podría ser un servidor de base de datos, se ejecuta en el fondo, o background, es multitarea (multitasking). Esto deja que otros programas se ejecuten en primer plano (foreground). Un programa background carece de interface de usuario, mientras que un programa de primer plano si lo tiene.

Para entender bien como está la movida, es importante entender lo que son los programas front-end y back-end (los voy a dejar en inglés para mayor claridad... a los programadores les encanta hablar en su pseudoinglés mal pronunciado, así que mejor vayan agarrando la onda desde ahorita). Los clientes (entendiéndose el software de un programa de la compu) generalmente corren en el foreground, y por eso se llaman programas front-end. O sea que dan la cara por un desconocido, un software que se ejecuta en el background y por ello se le denomina back-end. En pocas palabras, el front-end es un programa como la secre de un cuate muy ocupado. Los clientes nunca conocen al tipo, pero interactúan con la secre. O sea que accesan al trabajo del cuate (el back-end) pero solo ven la sonrisa y piernas de la secre (el front-end).

Muchas veces se confunde la multitarea (multitasking) con el multiprocesamiento (multiprocessing). Multitarea se refiere a que una computadora hace más de una cosa a la vez, sin embargo el multiprocesamiento es usar más de un CPU para realizar un trabajo (por ejemplo, hoy es bastante común encontrar tarjetas madres para computadoras que aceptan 2 o más CPUs).

Ahora lo que se tiene que hacer, es jugar con las formas (ventanas) y los controles. Y de eso nos ocuparemos en todos mis mensajes acerca de la programación en Visual Basic 6, .net y 2005, aunque también aplica para un montón de otros lenguajes y ambientes de desarrollo (como RealBasic, Delphi, Visual C++, y muchísimos más). Y eso, como diría la viejita, es otra historia.

¡Hasta la próxima!

23 agosto 2007

Un programita sencillo... para ir calentando

Aquí presento un pequeño video que muestra como crear una simple aplicación con Visual Basic 2005. Es muy sencillo, solo genera un número aleatorio entre 0 y 10 cuando arranca la ventana y lo compara con lo que le escriba el usuario. Si no puedes ver el video, fíjate en esta liga. Los archivos del proyecto los puedes bajar aquí. ¡Hasta la próxima!


22 agosto 2007

Elementos de la Comunicación

¿Qué es la comunicación?
La comunicación es algo interesantísimo, algo vital que necesitamos todos los días. Para ponerlo sencillo y sin tanto rollo, la comunicación es la creación y transmisión de un mensaje de una fuente a uno o más receptores. Creo que esto queda muy claro, sin embargo quiero hacer hincapié en que comienza con el creación del mensaje, algo que hay que pensar claramente antes de intentar comunicarse. Descartés (que se pronuncia algo como "descart") alguna vez dijo: "Pienso, luego existo" (bueno, la verdad dijo Cogito ergo sum, pero 'pal caso es lo mismo). No olviden pensar las cosas antes de abrir la boca, o producir un video o crear una página web o cualquier otro acto comunicativo.

La palabra comunicación viene de la palabra latina communis que quiere decir común o compartido. La comunicación es la que nos permite compartir con quienes tengo a mi algrededor, con quienes tengo cosas en común.

¿Qué tipos de comunicación hay?
Realmente se podría clasificar la comunicación de muchas diferentes maneras. Para lo que vamos a estar usando, elegí esta para comenzar (luego iremos afinando el concepto más adelante):
  • Comunicación unilateral - El emisor manda un mensaje y el receptor es pasivo.
  • Comunicación bilateral - El emisor y receptor intercambian sus funciones, o sea que uno manda el mensaje, el otro lo recibe y le contesta.

Elementos del proceso de comunicación
Diferentes autores eligen los elementos que se les pega la gana. Por ejemplo, aquí mi amigo Gil puso una imagen con los 3 elementos principales que conforman la comunicación. Otros son más sofisticados, como los de Wikipedia que proponen estos elementos. Para nuestros propósitos, voy a describir algunos elementos que considero importantes:
  • Emisor: el que produce la información
  • Referente: situaciones que van más allá del lenguaje ("extralingüísticos" para que se oiga elegante) para interpretar los mensajes enviados.
  • Mensaje: lo que se codifica, o sea la idea ya puesta en español, codificado para enviarse por internet, el video terminado, etc.
  • Código: los signos usados para codificar el mensaje, por ejemplo las reglas del español (acentos, pronunciación, etc.) o el lenguaje para sordomudos, etc.
  • Receptor: es quien recibe el mensaje, lo descodifica y lo interpreta.
  • Canal: es el medio por el cual circula el mensaje. Por ejemplo, puede ser el aire que permite que viajen las ondas sonoras de mi boca, la señal del teléfono celular, el cable telefónico que conecta el fax, etc.
  • Contexto: Son el conjunto de factores y circunstancias en los que se produce el mensaje.
  • Ruido: Elementos que estorban el el proceso comunicativo. Por ejemplo, puede ser la música que está a todo volumen en el antro, la estática que se ve en la tele cuando no se ve bien la señal, el corto circuito que tiene un micrófono, la diferencia del vocabulario (por ejemplo, el otros países latinoamericanos algunas palabras tienen connotaciones muy diferentes), etc.
  • Redundancia: elementos innecesarios.
Luego seguiremos platicando de más elementos comunicativos. ¡Hasta la próxima!

16 agosto 2007

¿Qué $%·$!¡ es una red?

Introducción
Hollywood le da mala propaganda a las redes de computadora. Ya en el 83 nos presentan una película (War Games) donde un chavo pseudohacker de a peso entra a un mainframe militar y está apunto de desatar la 3a. Guerra Mundial. En las películas Terminator (1984, 1991 y 2003), una red de computación del futuro (llamado Skynet) toma el control del planeta, crea robots exterminadores extra perrísimos mata-todo-lo-que-se-le-ponga-enfrente y los manda de regreso en el tiempo para eliminar a todas las que se llamen Sarah Connor. En la película The Net (1995), Sandra Bullock encuentra un ícono en la esquina inferior izquierda de la pantalla (aunque cualquier chico de 4 años que use una computadora lo hubiera encontrado) que la lleva a descubrir un "compló" (en palabras del Peje) en un mundo de espionaje computarizado y los "malos" le cancelan cuentas bancarias, eliminan todo tipo de identificación. Y, una de mis favoritas, en The Matrix del 99 y sus secuelas Reloaded y Revolutions (ambas del 2003), una red inmensa de computadoras usan a los humanos como esclavos y los mantiene atrapados en una simulación del mundo real.

Pese a que las redes hacen películas taquilleras, no les hacen justicia. Estas aplicaciones y amenazas malas, crueles y ruines solo han servido para sembrar miedo y terror entre los que usan el internet. Sin embargo las redes son más tranquilas y predecibles. No piensan por si solas, no pueden evolucionar el algo que mate a la humanidad, ni nada por el estilo.

Después de tanto rollo mareador, vamos hablando de lo que es una red. Ésta no es más que dos o más computadoras conectadas, por cables o sin ellas y mil otros cybercachivaches, que les permitan intercambiar información y recursos. Reconozco que esta no es una definición super-profesional, sin embargo es suficiente para nuestros fines.

Cualquier equipo de cómputo, para poder ser funcional, requiere un sistema operativo. Algunas computadoras conectadas a la red tienen instalados sistemas operativos de red que controlan el funcionamiento de la misma (algunos nerdos los llaman NOS, acrónimo de Network Operating System o sistema operativo de red). Hoy en día todos los sistemas operativos cuentan con soporte de redes porque ya no se puede concebir un ambiente de trabajo cyberchiroliro desconectado de una red. Es casi una herejía pensarlo.

Alcances de las redes
Hay redes de diferentes tamaños (pensando en tamaños físicos o geográficos), que algunos llaman "alcance" de las redes. Y como todo en el mundo mágico musical de las redes tiene que tener algún acrónimo jalado, estas son los diferentes redes como son conocidos entre quienes saben de conexiones cibernéticas. Para operar una red no importa cómo se llame, sin embargo les doy la definición por si quieren apantallar a sus cuates:
  • LAN (Local Area Network) - Una red local pequeño que a barca uno o varios edificios que se encuentran cercanos entre sí.
  • CAN (Campus Area Network) - Una red local escolar grandecito que cubre un campus universitario (generalmente las universidades chidas ocupan mucho espacio y tiene muchos edificios)
  • SAN (Storage Area Network) - Una red hecha para almacenar información.
  • MAN (Metropolitan Area Network) - Una red grandotota que conecta máquinas localizadas en diferentes lugares de una ciudad o metrópoli.
  • WAN (Wide Area Network) - Una red todavía más grandototota que una MAN. Puede abarcar desde 100 hasta 1000 Km.
Algunos cybercachivaches que conforman una red
Una red, como dije antes, está conformado por diferentes elementos (llamados cybercachivaches por mí, un término jalado que es equivalente a hardware). Voy a describir algunos de ellos:
  • Nodo: en palabras técnicas, es un "punto de intersección o unión de varios elementos que confluyen en el mismo lugar". En términos prácticos, cualquier hardware conectado a la red, como pueden ser las computadoras, terminales, impresoras de red (impresoras especiales que tienen forma de enchufarle un cable de red y no necesitan estar conectados a una computadora, como este), discos duros de red (discos que tienen enchufe para conectarse a la red sin necesidad de computadora, como este), etc.
  • Terminal: es una computadora, pero sin la computadora, jeje. Explico mejor: es un cybercachivache que solo tiene teclado y monitor. Todo lo que necesite hacer lo hace un servidor al cual se encuentra conectado. Dale click aquí para mayores informes.
  • Modem: pese a que parece una palabra formal, es un acrónimo de MODulator-DEModulator. Nos sirve para mandar datos por medio de la red telefónica. Es que la computadora usa señales digitales (o sea, puros unos y ceros) y la línea telefónica solo usa señales analógicas (o sea, sonidos). Por lo tanto, el MODEM convierte las señales digitales en ruiditos para que puedan mandarse por teléfono y del otro lado al recibir estos ruiditos los vuelve a convertir en unos y ceros. ¿Has escuchado los ruiditos que hace un fax? Esos son los ruiditos que genera.
  • Tarjeta de red (o NIC, acrónimo de Network Interface Card): es un cybercachivache que necesita cualquier nodo para poder enviar y recibir datos por la red.
Todavía hace falta aprender mucho de redes, pero eso lo iremos viendo más adelante. ¡Hasta la próxima!

31 mayo 2007

¡Se dan clases de verano!

Debido a la necesidad que impera con respecto a la capacitación en el uso de la computadora, no puedo quedarme viendo que México necesita de personas capacitadas, así que estoy ofreciendo este verano cursos de computación.

Si quieres, te puedo enseñar a usar los programas que enlisto o bien podemos trabajar en un proyecto (o sea, las clases ayudan a aprender y a resolver un trabajo). Los programas en las que te puedo ayudar son estos:
  • Adobe Premiere (edición de video)
  • Adobe Photoshop (edición o creación de imágenes de mapas de bits)
  • Adobe ImageReady (prepara imágenes de mapas de bits para su uso en el internet)
  • Adobe Ilustrador (dibujo vectorizado)
  • Adobe Acrobat (manejo de archivos portátiles, PDF)
  • Adobe Flash (animaciones y páginas web)
  • Adobe Dreamweaver (páginas web)
  • Adobe GoLive (páginas web)
  • Adobe InDesign (diseño editorial)
  • Microsoft Office (software de productividad): Word, Excel, Powerpoint, Access.
  • Programación en C, C++, SQL, Visual Basic 6.0, Visual Basic .net, Visual Basic 2005, Pascal, etc.
Si te interesa ponerte al corriente en clases de computación, necesitas aprender diseño gráfico o programación, o simplemente saber usar el Office, avísame. Déjame un comentario en este blog o mándame un correo.

23 mayo 2007

¿Y qué objeto tiene imprimir?

En esa era postmoderna llena de circuitos electrónicos y bits de información que hostigan información por las vías digitales de la comunicación moderna, ¿todavía es importante tener documentos impresos? ¿Qué no se había acabado eso cuando se petatearon los dinosaurios y esa onda? ¿Acaso me mintieron cuando me dijeron que el internet y las bases de datos movían información sin necesidad de papel?

Ciertamente los documentos han perdido importancia con el advenimiento de las maravillas digitales, sin embargo los documentos impresos son todavía imprescindibles. Se usa para los documentos realmente importantes (como el pasaporte, acta de nacimiento, etc.), de las que se tiene que asegurar que le llegue a las personas (se sorprenderían las veces que a la gente nunca le llegan los correos los documentos que mando por i-meil... échenle la culpa al i-meil...) o autorizar cosas (cheques, permisos, etc.) o que necesiten acuse de recibido (como la boleta de calificaciones de la primaria).

Para dejar a un lado tanto choro mareador, los documentos impresos son importantes y son fundamentales para los sistemas que usan bases de datos. Siempre se necesitan usar reportes impresos. Siempre.

Hay muchas estrategias para imprimir desde Visual Basic 6.0. Han desarrollado programas externos que se "pegan" a VB (como el Crystal Reports), crear formas con arreglos de controles (como labels) y usar la función PrintForm, y otras mil maneras diferentes (bueno, pue' que exageré un poco con las mil maneras, pero seguramente llegan a 999, jeje). Hoy voy a explicar la manera de usar el objeto Printer para crear documentos impresos.

El objeto Printer tiene todos los métodos y propiedades necesarias para imprimir (la explicación "oficial" del objeto Printer, sus propiedades, métodos, eventos y demás monerías, lo puedes encontrar aquí). Haz de cuenta que dibujas sobre una hoja (le pones círculos, logos, líneas, texto, etc.) y cuando ya está listo, le dices que imprima la hoja. El objeto se refiere a la impresora instalada por defáult. Si quieres acceder a otra impresora que haya instalado en el sistema, se hace uso de la colección Printers. Haz de cuenta que una colección es un arreglo de objetos, en este caso, un arreglo de objetos Printer.

Para que veas como funciona esto, preparé un programa explicatorio que da las explicaciones necesarias para explicar cómo se puede usar el objeto Printer en una aplicación de manera explicada. ¿Me explico?

Este programa consta de tres ventanas: la principal desde donde se imprime, otra que te permite configurar la impresora y la última nunca se ve, pero contiene la foto de Wally que vamos a usar más adelante. Al ejecutar el programa se ve esta pantalla:


Aquí apareden varas cajas de texto donde le usuario puede escribir lo que se le pega la gana (siempre y cuando no sean pelangochadas ni vituperios espantosos). A un lado hay una cajita donde el usuario puede "tachar" la caja a un lado de la línea que quiere ver en negritas. Hasta a bajo hay otras tres "cajitas". Una te imprime un círculo en la hoja, otra dibuja un rectángulo y el tercero dibuja la imagen de mi buen amigo (y casi casi mi doble) Wally (conocido también como Waldo en otros lugares). Como es solo un ejemplo, dibujé el círculo donde se me pegó la gana, al igual que el rectángulo y el lugar donde pongo la foto de Wally. En un caso real, usa el mismo código, pero acomoda las cosas donde se vean estéticamente placenteras. Este es el ejemplo de una ventana con datos:


En este caso, escirbe un renglón en negritas y otros dos en texto normal. También le especifiqué que dibujara el círculo, el recftángulo y que pusiera la foto de mi buen amigo Wally. Al darle click al botón que tiene la impresora volando con una carpeta atrás, genera una hoja como ésta:


Yo sé que no es nada del otro mundo, pero es suficiente para demostrar como funciona esta onda. Esto se imprime a la impresora que el usuario tiene especificada como predeterminada. Pero, ¿qué sucede si quiere cambiar de impresora? Una solución sería decirle al usuario que se decida y ponga como predeterminada la impresora que quiere usar y si lo quiere imprimir en otra, que vaya al Panel de Control - Impresoras o directamente a la opción Impresoras y faxes del menú de Windows y establezca la impresora defáult y le mueva a las opciones. Sería una solución, pero te verías demasiado chafa y probablemente te manden por un tubo debido a tu poca pericia informática (digo, es un enfado entrar a configurar las impresoras cada vez que quieras moverle algo a la impresora... que hueva).

Una mejor solución, de hecho la que usan todos los programas que te permiten imprimir, sería darle una ventana donde pueda configurar la impresora (o cambiar de impresora). Para esto es la segunda ventana, misma que aparece cuando el usuario le pica al botón que tiene una impresora sobre una mano extendida. Esta es la segunda ventana:


En el primer combo box, lo inicializo con los nombres de todas las impresoras instaladas en el sistema, abajito muestro el número de copias que va a imprimir, luego puede elegir el tamaño del papel (yo le dejé las opciones de carta y oficio, pero se pueden programar otros tamaños), la calidad de impresión y te muestra la orientación del papel. Abajo están dos botones y, como eres un empollón (bueno, tal vez no tanto), podrás deducir que el botón que tiene la palomita verde cierra la ventana guardando los cambios y el que tiene la espantosa X roja, sirve para cerrar la ventana sin guardar los cambios hechos.

Ahora que ya vista como funciona, vámonos al código. Vamos empezando con la primera ventana. Solamente voy a poner aquí el código que sea interesante para lo relacionado a la impresión (o sea, no esperes que explique el código para cerrar la ventanita o terminar el programa).

Al presionar el botón que imprime el documento, se ejecuta el siguiente código:


Comienzo con la instrucción On Error que le dice a VB 6.0 que si se traba con alguna bronca, se vaya a la etiqueta llamada "fin" que puse al final. O sea que en cuantro encuentre un problemita o problemón (cosa que esperamos nunca suceda), va a interrumpir el proceso de impresión, imprimiendo solo aquello que alcanzó a hacer antes del error. Se quedará en la memoria de la impresora lo que intentó hacer hasta el error.

Después de asegurarnos que no hay problema en caso que algo falle, me fijo si el usuario quiere dibujar un círculo sobre la hoja. En mi caso, el Checkbox que me indica si quiere el círculo se llama chkCircle. Si es así, uso la función Circle del objeto Printer para dibujarlo. Lo único que le tengo que dar son las coordenadas del centro del círculo y el radio del mismo. Tiene otros parámetros que se pueden especificar para hacer semicírculos, llenarlos de color, etc. , pero por lo pronto con estos bastan. Recuerda que es solo un ejemplo, ya te toca a ti experimentar un poco más. Después uso las propiedades CurrentX y CurrentY para posicionarme en esas coordenadas sobre la hoja y en esa posición escribo el texto Círculo mediante la función Print que sirve para escribir texto sobre la hoja. Puedes ver estas ligas para infomación acerca del uso de la función Circle y de las propiedades CurrentX y CurrentY (esta documentación está en inglés, pero no creo que tengas problemas en agarrar la onda).

Después hago algo muy similar con el rectángulo, solo que aquí el CheckBox se llama chkRect, y se usa la función Line, aunque está hecho para dibujar líneas al especificar las coordenadas donde comienza y donde termina, al final le escribí el parámetro B que indica que es una caja (box). Dejé dos paréntesis porque el parámetro que sigue de las coordenadas es la del color de la línea, que en mi caso no quería modificar. Para más informes acerca del uso de la función Line, haz click aquí.

Para dibujar una imagen, que es la condición que sigue, puedo usar el contenido de un PictureBox que ponga sobre una ventana. En mi caso tengo una tercera ventana en mi proyecto que nunca es vista por el usuario que sirve para este fin. La forma se llama frmImagen que tiene un PictureBox con la foto de Wally (llamado picWally). Entonces cargo la forma a la memoria (Load frmImagen), dibujo la foto en la hoja (Printer.PaintPicture frmImagen.picWally 600,900) y quito la ventana de la memoria (Unload frmImagen). La función PaintPicture recibe como parámetros las coordenadas donde se va a dibujar la imagen. Tiene mil otros parámetros para hacer chuchulucos y monerías diversas y si quieres verlo más a fondo, haz click aquí. La ventana frmImagen en la vista diseño, es esta:

Después de todo este alboroto, toca escribir las líneas de texto. Para esto mis cajas de texto son un arreglo de Textboxes, llamados txtTextLine, que consta de 10 elementos. También tengo los Checkboxes que me indican si la línea va en negritas en otro arreglo llamado chkNegritas, también de 10 elementos. Entonces compiezo un ciclo, controlado por la variable i, que va de 0 a 10 para recorrer las cajas de texto y cajas de opción. Inicializo la posición de Y (para los posicionarse en los renglones) en 1300 para que comience desde allí. Mientras i sea menor a 10 y haya algún texto en la caja de texto (valga la redundancia), establece la posición en X en 500 (todos los renglones comienzan donde mismo, en mi ejemplo) y se fija si va en negritas o no. Si lo quiere más negrote, establece la propiedad FontBold en verdadero. Luego escribe el texto, como ya se explicó antes, con la función Print, incremento i y pongo en falso la propiedad FontBold para que no siga escribiendo en negritas. Y el ciclo se repite, y repite, y repite, y repite...

Al terminar de imprimir las líneas de texto, uso la función EndDoc que sirve para decir que ya terminó el trabajo y que escupa la hoja que ya dibujé. Si se tienen que imprimir muchas hojas, puedes usar la función NewPage que escupe una hoja y te deja otra "en blanco" para que sigas dibujando.

Hasta allí todo parece felicidad y alegría. Lo que nos falta ver ahora es la manera de que aparezca la ventana que permite elegir y configurar las impresoras. Al cargar la ventana a la memoria, lleno un ComboBox con las impresoras instalados en la compu del usuario y lleno los otros controles. Es muy sencillo, así que ni lo explico (bueno, lo explicaré abajo del código). Este es el código:


Comienzo con un ciclo desde 0 hasta el número de impresoras instaladas menos uno. ¿Por qué le resto uno? Porque consideramos la primera impresora instalada como la número cero. La propiedad DeviceName es una cadena con el nombre de la impresora (por ejemplo, "HP LaserJet 1200"). El siguiente ciclo me sirve para establecer la impresora default como la impresora seleccionada en el ComboBox (cboPrinters). Para lograr esto, hago un ciclo recorriendo la lista de impresoras (de la colección Printers) hasta encontrar el que tiene el mismo nombre (DeviceName) que el de la impresora predeterminada (el objeto Printer es la impresora predeterminada).

Después de esto, inicializo mis ComboBoxes de tamaño y calidad en 0 (para asegurar que hay algún elemento seleccionado y no me de broncas después), muestro el número de copias que tiene especificada (usando la propiedad Copies) y la orientación del papel. Para la orientación del papel, usa la constante vbPRORPortrait la cual es simplemente un número que guarda la propiedad Orientation. ¡Listo! Ya está.

Ahora vamos a guardar la configuración. Este es el código del botón que acepta los valores y cierra la ventana (es lo que sucede cuando presionan el botón cmdPrint_Click):


Esta está sencillo. Establezo que Printer sea igual a la impresora seleccionada (Set Printer = Printers(cboPrinters.ListIndex)), cambio el tamaño de papel al que eligieron (Printer.PaperSize = Right(cboTmno.List(cboTmno.ListIndex), 1)). Para especificar la calidad, uso un Case y según el elemento elegido, le establezco la calidad (con el vbPRPQDraft, vbPRPQLow, vbPRPQMedium y vbPRPQHigh). Al final cierro la ventana (Unload Me). ¡Listo!

Creo que es todo. Les dejé ligas a páginas que tienen las referencias a todo lo habido y por haber. Si hay dudas, mándame un emilio y deja un mensaje aquí. ¡Hasta la próxima!

07 mayo 2007

Primer concurso multimediático: Convocatoria definitiva y final

Extendimos el plazo de entrega, hemos conseguido muchos premios más (iPods, curso de edición de video o diseño digital de $2350, bocinas home theater para compu, 2 celulares Nokia 5300 y estamos en espera de otras sorpresas...).



Sólo falta que te inscribas. ¡Te espero el 24/Mayo con tu proyecto!

02 mayo 2007

Textos, textos y más textos...

Algo que es útil y que te puede sacar de apuros muchas veces son los archivos de texto. Tal vez creas que son cosa del pasado, hoy en pleno siglo XXI con mil DBMSes chiroliros en el mercado, ¿y usar archivos de texto? Así es. Son muy usados todavía, por ejemplo, los archivos ini, inf y bat de Windows son archivos de texto, así como archivos de código fuente en lenguaje C (.c), C++ (.cpp), Visual Basic.net, Visual Basic 6.0 (.frm, .bas, etc.), etc.

Claro que no sirven para resolver todo tipo de problemas, para eso están los DBMS como Oracle o MySQL. Pero para generar reportes, guardar configuración o mandar datos a Excel, es eficiente. Como es útil, vamos a ver cómo manipular archivos de texto con Visual Basic 6.0.

Hice un pequeño proyecto que ejemplifica el uso de archivos de texto que puedes bajar aquí (todavía no sirve la liga, pero pronto lo podrás descargar). El programa tiene varias funciones: deja que el usuario escriba lo que sea en 24 cajas de texto, los almacena como archivos de texto "normales" o en formato CSV para abrirlos en Excel, abre archivos de texto y los elimina.

Para comenzar con el código, yo, en mi caso particular, decidí hacer un módulo que contiene una variable global (FileName) que almacena el nombre de archivo que se está manipulando (o sea, el que se quiere abrir, guardar o eliminar) y también almacena una función, FileWindow, que se encarga de abrir la ventana que deja que veas las unidades, carpetas y archivos para que selecciones el archivo a manipular y llena la variable global FileName con el resultado (así otras ventanas saben el nombre del archivo y la carpeta en donde se encuentra). Esto me ahorra código porque casi todas las funciones necesitan usar una ventana similar para almacenar, guardar o eliminar. No es absolutamente necesario hacerlo de esta manera, pero funciona. Aquí les muestro el código de el módulo.


Como puedes ver, solo carga la ventana frmFile, le cambia el Caption y lo muestra. Esta es la ventana frmFile primero en la vista diseño y luego al ejecutarlo y pedirle que abra un archivo):




Ok. Aquí escribo todo el código que contiene esta ventana. Básicamente son eventos que controlan los controles (valga la rebuznancia) del drive (Drive1), de la lista de carpetas (Dir1) y la lista de archivos (File1). El otro código usa la caja de texto que tiene el nombre del archivo (txtFile) y lo asigna a mi variable global (FileName, que ya expliqué anteriormente). Este es:


Ok. Hasta allí nos hemos ocupado de detallitos vanos y ruines que solamente nos sirven para ahorrarnos código más adelante. Ahora vamos a hablar del código que trabaja con los archivos de texto. Para esto, vamos a ver el código de la ventana principal que se encarga de guardar archivos de texto "normalazos" (es que hay otro botón que los guarda en formato CSV para su uso en Excel), lo que sucede cuando presionan un botón llamado cmdSave. Aquí pongo el código y abajo lo explico.

Comienzo declarando dos variables: i que controla un ciclo que graba las líneas de texto al archivo e Imprimir, una cadena que almacena lo que se va a escribir en el archivo, un renglón a la vez.
Después de las declaraciones, usa la función FileWindow, explicado anteriormente, para desplegar la ventana que permite buscar en unidades de disco, carpetas, etc. para especificar la carpeta y nombre del archivo a guardar. Si el usuario no presionó el boton Cancelar de esa ventana que pide los detalles del archivo (frmFile), o sea que el nombre del archivo (FileName) no es igual a una cadena vacía (porque el código del botón cancelar de frmFile le asigna una cadena vacía, "", a FileName), comienzo toda la onda.

Para manipular un archivo se tiene que abrir. Para eso me sirve la instrucción Open. Cuando abres un archivo tienes que decirle que archivo y que quieres hacer con él. Es igual que invitar a una chava a salir: tienes que decidir a qué chava (escribir el nombre del archivo) y decirle que quieres hacer con ella (por ejemplo, llevarla al cine, a cenar, a barrer y trapear tu cuarto, etc.), si no, las cosas no funcionan. Es por esto que escribo Open seguido del nombre completo del archivo (o sea con todo y la ruta de carpetas) y al final le escribo el uso que quiero hacer con el archivo. Como aquí quiero escribir datos al archivo, o sea darle salida a mis datos, le digo For Output.

Visual Basic tiene mucha confianza al trabajar con archivos, algo similar a lo que sucede en tu casa o con tus amigos. Tienes tanta confianza que no te llaman por tu nombre sino por un apodo. Visual Basic hace lo mismo: para referirse a un archivo a la que quiere escribir, o desde donde quiere leer datos, no lo hace por el nombre del archivo sino por un número del 1 al 9. Es por eso que al final de la instrucción Open le agregue el As #1. De esta manera, al usar instrucciones que manipulan al archivo (Close, Print, etc.) indico que todo va a funcionar con el archivo número 1. Para resumir, la sintáxis completa de la instrucción Open queda así:

Open nombre_del_archivo For uso As número

Después de abrir el archivo, uso un ciclo For para controlar el número de renglones que voy a escribir al archivo. Para hacerlo fácil y rápido uso una característica que tiene Visual Basic 6.0 y pierde en la versión .NET. Esto es el uso de arreglos de controles. Hice 3 arreglos de textboxes (txtTexto1, txtTexto2 y txtTexto3) cada uno con 8 elementos.

Con el contenido de las cajas de texto, armo la cadena que voy a escribir al archivo (Imprimir). Si no es una cadena vacía, o sea que escribieron algo en cualquier caja de texto de ese renglón, uso la función Print para escribir la cadena Imprimir al archivo.

En primer lugar, le tengo que decir el archivo al que quiero escribir la cadena (por medio del número, en nuestro caso 1) y la cadena que quiero escribir (en este caso, la cadena Imprimir). Por eso la instrucción queda como Print #1, Imprimir.

Después de escribir un renglón al archivo, vuelve a arrancar el ciclo y vuelve a hacer lo mismo. Al final de toda la escribidera, tengo que cerrar el archivo, con Close #1, o sea, cierra el archivo al que hace referencia el número 1.

El código que almacena un archivo CSV para su uso en Excel usa un código casi idéntico. Al principio se asegura de que la extensión sea CSV y todo lo demás es casi lo mismo, excepto que inserta comas entre las cadenas.

Los archivos CSV (Comma Separated Values) son archivos de texto que puede importarse directamente a Excel. Lo único que los hace diferentes es que cada renglón del archivo de tesxto corresponde a una fila de excel y los valores de las celdas se escriben seaprados por una coma, o sea que la coma separa los valores que van en las diferentes celdas de la fila. Para mayor información acerca de archivos CSV, dale click aquí.

Este es, por fin y después de tanto rollo, el código que genera los archivos CSV (esto se ejecuta cuando le das click al botón cmdExcel):


Solo hace un pequeño cambio para poder leer datos del archivo. Este es el código que abre un archivo de texto y vacía su contenido en otra ventana (frmRead) en una caja de texto (txtFileCont). Este es el código:


Lo que hago aquí es sencillo. Declaro una cadena que va a almacenar las líneas que voy leyendo del archivo (Cadena), luego uso mi función FileWindow para pedir el archivo que se va a abrir. Si el usuario da un nombre de archivo, abro el archivo para lectura. Esto se hace sustituyendo el For Output que usábamos para escribir al archivo, por For Input que indica que voy a leer datos del archivo. Y, en lugar de usar el Print para escribir al archivo, uso el Input. En mi caso leo un caracter a la vez para no errarle. La sintáxis es Input(no_de_caracteres_a_leer, no_de_archivo). Fácil, ¿no?

Como estoy leyendo caracter por caracter, lo hago dentro de un ciclo. Voy adjuntando los caracteres que voy leyendo a la caja de texto de la ventana donde voy a desplegar el contenido del archivo (frmRead.txtFileCont). Esto se repite hasta que llegue al final del archivo, cosa que pruebo usando la función EOF(no_de_archivo).

Otra operación que se realiza con frecuencia es eliminar gente, perdón, registros (bueno también se mata a mucha gente, pero ese es otra historia que no tiene que ver con archivos de texto). Para esto existe la instrucción linda y tierna Kill seguida por el nombre del archivo a eliminar. Esto se puede observar en este código que se ejecuta cuando se presiona el botón eliminar (cmdKill):


Creo que eso es todo. Lo único que no expliqué fue la ventana de "Acerca de..." (lo puse por pura vanidad). ¡Hasta la próxima!

26 abril 2007

Arrejuntando datos

Hace tiempo que escribí acerca de muchas opciones que tiene la instrucción SELECT de SQL para hacer consultas. Sin embargo, solo eran consultas simples, sin mayor chiste ya que esas consultas solo consultan (valga la redundancia) una tabla. Pero, ¿qué pasa cuando tengo datos en diferentes tablas y quiero un solo reporte que contenga datos de ellos? Para eso existe la instrucción INNER JOIN que se escribe en un SELECT.

Vamos a ver como funciona esta onda. Estas es la sintaxis para unir dos tablas (luego lo extendemos para usar datos de más tablas, pero vámonos despacio porque llevamos prisa, diría Napoleón):

SELECT lista_de_campos_de_las_tablas FROM tabla1 INNER JOIN tabla2 ON campo_tabla1=campo_tabla 2

Al final puedo poner un WHERE, ORDER BY o lo que sea (bueno, lo que sea que sea válido, valga la repetidera de "que seas").

¿Qué hace esta instrucción? En primer lugar, enlista los campos que quieres obtener en la consulta, sin importar de qué tabla son. Si hay campos que se llaman igual en ambas tablas, hay que escribir el nombre de la tabla seguido de un punto y luego el nombre del campo. Más a delante lo vemos en un ejemplo. Después del FROM viene el INNER JOIN seguido de la tabla que se quiere adjuntar, mezclar, pegar, añadir, o como le quieras decir. Hasta aquí todo es felicidad y alegría, con la excepción de que el SELECT no va a saber cómo relacionar los registros de las dos tablas. Para esto, entra en acción el tremendo ON que iguala los campos que tienen el mismo valor de ambas tablas.

Sé que los choros mareadores les aburren, así que les voy a explicar con un ejemplo sencillito. Supongamos que una librería tiene un sistema que controla los libros. Esta sería la esctructura y datos de las tablas Libros, Editoriales y Autores (ahorita uso Libros y Editoriales, luego usamos los Autores):


Supongamos que quiero saber todos los títulos cuyo título comience con la letra W. Quiero ver el título, el precio y la editorial. La consulta SELECT Titulo,EditorialID,Precio FROM Libros WHERE Titulo LIKE "W*" me arrojaría este conjunto de registros:


Muy padre pero, ¿qué editorial es la 5? ¿y la 7? Quien sabe. No es información útil para el simple mortal. Ahora intentemos con un INNER JOIN a ver que pasa. Esta sería la instrucción SQL:

SELECT Titulo,Nombre,Precio FROM Libros INNER JOIN Editorial ON Libros.EditorialID=Editorial.EditorialID WHERE Titulo LIKE "W*"

y me devolvería estos datos:


Mucho mejor, ¿no? Solo le estoy diciendo que los campos requeridos (Titulo, Nombre y Precio) están en las tablas Libros y Editorial y lo que tienen en común es el campo EditorialID. Nótese que no tengo que decir de que tabla es cada dato siempre y cuando no hayan campos con el mismo nombre en las tablas que se unen en la consulta.

Ahora vámonos complicando la existencia un poco para facilitársela al usuario y como el usuario es quien paga, hay que hacerle caso. Un reporte que se me hace muy útil para una tienda que vende libros es el de los libros y las cantidades de libros que se tienen. Por lo tanto, necesitamos crear la instrucción SQL que devuelva el titulo, autor, editorial y cantidad de libros buscados, ordenados por un campo. Suponiendo que hago pedidos a editoriales diversos, seguramente me conviene ordenar los registros por editorial. Por lo tanto, podría usar esta instrucción SQL, la cual une a las 3 tablas:

SELECT Titulo,Autores.Nombre As Autor, Editorial.Nombre As Editor,Cant FROM (Libros INNER JOIN Autores ON Libros.AutorID=Autores.AutorID) INNER JOIN Editorial ON Libros.EditorialID=Editorial.EditorialID ORDER BY Editorial.Nombre


Primero uno las tablas Libros y Autores y cuando ya están unidos en una sola consulta (la computadora hace esta consulta primero) le "arrejunta" la tabla Editorial. La tabla que generaría como resultado sería esta:


Espero que esta explicación no deje tantas dudas. Si no entendiste algo, avísame. Déjame un comentario y/o escríbeme por i-meil. ¡Hasta la próxima!

18 abril 2007

¡Se acerca el primer concurso multimediático!



Si te gusta hacer archivos de animaciones, sitios web o carteles y además te quieres ganar premios y reconocimiento (por parte mía por lo menos) y gozar de fama y fortuna, no te puedes perder nuestro primer concurso multimediático.

La idea es crear un sitio web, animación y/o cartel acerca del tema (El Adolescente y las enfermedades venéreas). El único requisito es que seas alumno de alguna preparatoria. El evento tendrá lugar el jueves 24/Mayo y las inscripciones terminan el 7/May, así que ¡a jugar con la compu! Aquí están las bases. Para cualquier duda acerca del concurso, no dejen de contactarme y con gusto les podré aclarar (u obscurecer más) sus dudas. Lo único que falta es que arreglen la página de la prepa Univa (prepa.univa.mx) para el registro, pero todo lo demás está listo. Ya estamos consiguiendo premios interesantes, así que anímate y diviértete con nosotros.

27 marzo 2007

Deslizando imágenes en Flash

Para aprovechar el área de tu animación Flash al máximo (recuerda que la resolución mínima de un usuario vil y mortal es de 800x600 por lo que deberías hacer tus animaciones para esta resolución para que todo el mundo lo pueda ver), existen componentes diferentes que te pueden servir de ayuda.

En este ejemplo voy a usar el componente ScrollPane para mostrar una imágen bastante grande. Estos son los pasos que seguí para hacerlo (acompañado de algunas imágenes chiroliras):
  1. Hice un nuevo documento Flash. Lo "bauticé" scrollpane.fla.
  2. Importé a la biblioteca (library) 3 archivos JPG: foto1.jpg, foto2.jpg y foto3.jpg.
  3. En el primer fotorama de la capa Layer1 le inserté un símbolo Clip de película (movie clip) llamado fotos la cual contiene las tres imágenes todas alineadas en fila. Nótese que el punto de registro (registration mark) está en la esquina superior izquierda. Para alinearlas, usé las herramientas del ventana de alineación (Window-Align). Chécate la figura 1 que está hasta abajo de este post (en esta ocasión se me ocurrió poner todas las imágenes hasta abajo, espero que no te sea inconveniente).
  4. Agrupo las 3 imágenes (Modify-Group o CTRL+G).
  5. Abro la ventana de componentes y abro los componentes de interfaz (Window-Components). Esto lo puedes ver abajo en la figura 2.
  6. Arrastré una copia del componente ScrollPane al escenario de mi animación. Ve la figura 3. Le cambié el ancho a 448 y el alto a 296 (para adecuarse al tamaño del símbolo fotos) y lo centré en la escena pa' que se vea chuvidubis.
  7. Di click con el botón derecho del mouse sobre el icono del símbolo fotos en la ventana de la biblioteca (library) y selecciona la opción Linkage (no sé como se tradujo a la versión en español, será ¿vinculación?). Esto viene en la figura 4.
  8. Aparece la ventana que puedes ver en la figura 5. Aquí selecciono la opción Export for ActionScript (lo cual me permite accesarlo desde otras partes de mi animación como son los controles). Ahora le puedo poner un nombrecito con el que lo puedo vincular al ScrollPane. Yo le puse fotos0, pero, como te has de imaginar, puede ser el nombre que sea.
  9. Ahora selecciono mi ScrollPane y altero sus propiedades, en la parte de parámetros. Hago los siguientes cambios: al parámetro contentPath le escribo fotos0 (el nombre de la "liga" de mi clip de película fotos) para asignar el contenido de fotos al ScrollPane y al parámetro scrollDrag le pongo valor verdadero lo cual me permite arrastrar las imágenes dentro del fotos con mi mouse. Esto se ve en la figura 6.
  10. Ahora todo lo que resta hacer es presionar Ctrl+Enter y ser feliz. El resultado lo muestro en la figura 7.
Espero que esto te haya servido para iluminar tu vasto entendimiento. Seguimos en contacto...

Figura 1. El símbolo fotos

Figura 2. La ventana de componentes

Figura 3. Scene1 con el ScrollPane.

Figura 4. Menú contextual del símbolo fotos

Figura 5. Ventana "linkage" (¿será vinculación?)

Figura 6. Parámetros del ScrollPane

Figura 7. La animación terminada

26 marzo 2007

Animando desde una animación...

Como la idea es hacer que los archivos de Flash que ven los internautas sean lo más pequeños posible, es posible (valga la redundancia) crear una animación con el "esqueleto" de la página y desde esa animación cargar otras animaciones (por ejemplo, las diferentes partes del sitio). Esto lo usan casi todas las páginas hechas en flash. Ayuda a que el usuario no se desespere mientras baja una paginotototota que descarga partes de la página que a lo mejor ni le interesan.

El video explicativo lo puedes bajar aquí (baja los 3 archivos y descomprímelos con el WinRAR en tu computadora) o ver en YouTube aquí (también puse el video al final de este mensaje, por si te da flojera ir al sitio de YouTube). Los archivos con el proyecto están aquí.

Si quedan dudas, avísenme por i-meil o déjame un comentario al final. ¡Hasta la próxima!

25 marzo 2007

ADO 4 - El regreso de las consultas (2)

Ya me puse a chambear para hacer otra consulta leve. Con el mensaje anterior echamos relajo con una consulta que se llama para llenar un ComboBox con un campo de los registros de una tabla. Ahora, siguiendo con el programa para doña Amalia, voy a hacer una consulta y llenaré una ventana con los datos de un proveedor.

Bien, el proyecto, todavía en fase muy lejos de ser la final, que incluye lo que voy a explicar hasta ahorita lo puedes bajar aquí. Voy a ir explicando los pequeños cambios que hice poco a poco, con código y toda la cosa, para que entiendas mejor el código.

Bueno, como estamos continuando con el proyecto de doña Amalia, voy a explicar ahora los pequeños cambios que realicé. Como recordarás del mensaje anterior, ya teníamos una ventana que nos permite consultar por número de proveedor o por nombre del proveedor. Ahora voy a programar el botón Mostrar, que yo lo llamé btnMostrar, para que abra una ventana nueva, frmDatosProveed, con puras etiquetas para mostrar los datos del proveedor. Podría haber usado la misma ventana de los proveedores para la consulta pero, sería mucho relajo porque debería deshabilitar el botón de Altas (ni modo que le piquen, por error o maldad, el botón de Altas para insertar un registro que ya existe).

También decidí cambiar el botón Eliminar a la ventana con los datos del proveedor. Así, primero aseguro que el usuario vea los datos del proveedor antes de matarlo, perdón, quise decir eliminarlo.

Bueno, por lo pronto aquí va el código que llena la ventana frmDatosProveed con la información del proveedor elegido, ya sea por nombre o número. Sin más preámbulos (porque abajo describo y explico el código), ahi va...


Tal vez parezca mucho rollo complicado, pero no es así. En realidad es muy sencillo. Comienzo revisando las opciones: si seleccionó la primera opción, la de buscar por número de proveedor (optNoProveed) y el número que tecleó es correcto (para esto uso la función Val que me convierte una cadena a un número). En caso que esto sea cierto, llena la propiedad CommandText con la instrucción SQL que busca todos los registros que sean igual al número escrito por el usuario: SELECT * FROM Proveedor WHERE NoProveed=" & txtNo.

Si esto no se cumple, o sea, que seleccionó optNoProveed y no escribió un valor válido para el número de proveedor, le mando un mensaje de error, pongo el cursor en txtNo para que escriba un valor válido y me excito de la función (se oye feo, pero digo que me excito porque estoy usando el Exit).

Si ninguno de los anteriores se cumple, quiere decir que seleccionó optNombre y no tengo que revisar el valor porque es un Dropdown List (o sea que no deja que el usuario escriba algo que no venga en la lista) y lo inicialicé seleccionando el primer proveedor de la lista (si tienes dudas de cómo hacerlo, lee mi mensaje anterior). Entonces lo que hago es igualar a cmdCommand.CommandText a la instrucción SQL que regresa todos los campos del registro cuyo nombre es igual a lo que está en cboNombres (eso lo saco con el cboNombres.List(cboNombres.ListIndex)).

Una vez que ya asigné el comando SQL correcto, paso a abrir el RecordSet (tblTable) que tendrá el registro que ando buscando. Esto lo hago con el tblTable.Open que ya expliqué previamente.

Si la tabla no llegó al final del archivo, lo que debería suceder siempre, cargo a la memoria una nueva forma que hice para mostrar datos, llamado frmDatosProveed. Esto lo hago con la instrucción Load frmDatosProveed. Una vea hecho esto, frmDatosProveed ya existe en la memoria, pero el usuario todavía no lo ve. Entonces lleno las etiquetas (lblNo, lblNombre, lblWeb, lblFax, lblTel y lblIMeil) con los valores de los campos del registro encontrado (tblTable!NoProveed, tblTable!Nombre, etc.). Al terminar de llenar las etiquetas, dejo que el usuario vea la ventana (usando el método Show) y todo es felicidad.

Si de pura casualidad al abrir la tabla llega luego luego al final (tblTable.EOF), (por ejemplo, si el número de proveedor no existe) quiere decir que no pudo encontrar al registro y le mando un mensaje de error.

Para terminar, cierro la tabla para poder usarla de nuevo en cualquier otro lado del programa.

Pero, ¿cómo se ve esta ventanita chuvidubis llamada vulgarmente como frmDatosProveed? Así se ve en la vista diseño:


Y así se ve a la hora de ejecutar el programa:


Ese fue la función más trabajosa, bueno la que hace todo el trabajo. Solo nos resta cerrar la ventana. Esto lo hago en la función btnAceptar con este código que se ejecuta cuando hacen click sobre el botón:


Tal vez ese sea el código más complicado de esta etapa. Ahora, ¿qué sigue? Probablemente programaré el botón de Eliminar (btnEliminar), pero ya veremos luego. ¡Hasta la próxima!

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!

El Tony y sus ondas...

Related Posts Plugin for WordPress, Blogger...