En este bloque veremos:
- 3.1 ¿Para qué sirve realmente el código?: La utilidad del sistema nervioso de nuestra herramienta y cómo permite la transferencia de datos.
- 3.2 Programando: entendiendo la lógica de objeto - acción: El uso de los selectores para navegar por el editor.
- 3.3 Entendiendo los programas o subrutinas: La importancia de la estructura rígida y la sangría visual.
- 3.4 Dando órdenes: Cómo usar métodos para acciones y propiedades para estados.
- 3.5 Creando un formulario inteligente: El uso de la lógica condicional “If... Then... Else”.
- 3.6 Rizando el rizo: el arte de prever lo inesperado: Cómo resetear valores para evitar resultados indeseados.
3.1 ¿Para qué sirve realmente el código?
Si el formulario que diseñamos en el Bloque II era el cuerpo de nuestra herramienta, el código es el sistema nervioso que le permite reaccionar y moverse. Para no perderte, imagina que tu trabajo en Word tiene ahora dos niveles que coexisten al mismo tiempo:
- El escenario (formulario): Es lo que hemos visto en el Bloque II. Es la parte en la que el usuario introducirá los datos.
- El camerino (código): Es donde escribimos las instrucciones para que, cuando alguien toque un botón en el formulario, se ejecute alguna acción.
En definitiva, el código hace que todo lo que dibujamos en el corcho tenga utilidad, especialmente en dos elementos:
- Interacción: Lograr que un objeto influya sobre otro. Que al seleccionar un botón se oculte otro objeto, o se haga visible un cuadro de texto que estaba oculto.
- Transferencia: El código es el que nos permitirá recabar los datos que el usuario ha escrito en el formulario e inyectarlos hacia nuestra plantilla de Word para generar el documento final.
Llegamos a lo que es, sin duda, el punto más crítico de todo el proyecto y donde es más probable que nos cueste procesar la información. Es normal sentir cierto vértigo al ver líneas de texto que parecen jeroglíficos, pero mantén la calma. Si yo, que soy un ladrillo, he aprendido a programar, tú también puedes.
3.2 Programando: entendiendo la lógica de objeto - acción
Para entrar en las “tripas” de nuestro proyecto y empezar a dar órdenes a los widgets, basta con dar doble clic sobre cualquier objeto de tu formulario.
Al entrar aquí, fíjate bien en la parte superior de la pantalla, porque verás dos selectores desplegables que son tu mapa de navegación, en nuestro caso, UserForm y Click:
- Selector izquierdo (objeto): Contiene un listado con todos y cada uno de los objetos que has dibujado en tu formulario (UserForm, cmbDecision, tglAproximación, tglComunicación, etc.).
- Selector derecho (acciones): Una vez que has elegido un objeto a la izquierda, este segundo desplegable te muestra todas las acciones posibles que ese objeto puede realizar.
Verás una lista enorme, vamos a explicar los más relevantes:
- Initialize: Solo está disponible para el objeto UserForm. Es el que permite programar lo que queremos suceda en el mismo instante en que lanzamos el formulario.
- Click: Permite programar qué sucede cuando hacemos click sobre el objeto en cuestión.
- Change: Permite programar qué sucede cuando un objeto cambia de valor.
- DblClick: Permite programar una orden que solo se dispara al hacer doble click, evitando ejecuciones accidentales.
- Enter / Exit: Permiten programar qué ocurre cuando el cursor entra o sale de un cuadro de texto.
3.3 Entendiendo los programas o subrutinas
Si echamos la vista atrás, recordaremos que uno de los objetos que hemos insertado ha sido un ComboBox (cmbDecision), el cual queremos que contenga las opciones “Prorrogar” o “Denegar”.
Sin embargo, si lanzaras el formulario ahora mismo y clicaras en la flecha del desplegable, verías que no aparece nada: es una lista vacía.
Objetos como el cuadro combinado (ComboBox) o las listas (ListBox) nacen totalmente vacíos por defecto. Funcionan como contenedores que no muestran ninguna opción hasta que nosotros, mediante instrucciones específicas de código, introducimos los elementos uno a uno.
En nuestro caso, nos interesa que dichos objetos aparezcan completos desde el momento en que iniciemos el formulario, si bien podría haber situaciones específicas en las que quisiéramos vincularlos a otros eventos dependiendo de la complejidad de nuestra herramienta.
El evento Initialize asociado al UserForm es la herramienta idónea para esta tarea, ya que permite programar instrucciones que se ejecutan de forma automática en el mismo instante en que la herramienta se activa. Al trabajar dentro de este bloque, logramos que la carga de datos ocurra "detrás del escenario", de modo que cuando el formulario se vuelve visible para el usuario, todas las listas ya están preparadas, configuradas y totalmente operativas.
Para ello, haz doble clic sobre el fondo del formulario (el corcho). Al hacerlo, verás que el editor de VBA crea automáticamente un bloque de texto llamado Private Sub UserForm_Click().
Ignora este bloque. El editor siempre ofrece la acción Click por defecto, pero nosotros no queremos que ocurra nada cuando el usuario haga clic en el fondo, sino cuando el formulario se genere. Por tanto, dirígete al selector de la derecha (el de acciones) y elige Initialize.
Por eso, en vez de usar la acción Click, buscamos en el selector de la derecha la acción Initialize. Al hacer clic, verás que automáticamente se crea lo siguiente:
Es fundamental que entiendas que lo que se ha escrito automáticamente es una subrutina o programa, es decir, un compartimento cerrado diseñado para ejecutar una tarea específica. Toda subrutina se compone de una estructura rígida con un inicio y un final que funcionan como “paréntesis” obligatorios:
- Private Sub: Es la cabecera donde se indica el nombre del objeto y la acción que lo activa.
- Cuerpo: Para que el código sea legible y profesional, las órdenes que escribas dentro de estos dos límites deben ir identadas (tabuladas, o con cuatro espacios). Esto significa que no escribimos pegado al margen izquierdo, sino que pulsamos la tecla Tab para desplazar el texto hacia la derecha. Esta sangría visual es lo que permite distinguir de un vistazo dónde empieza y dónde acaba el contenido de cada programa.
- End Sub: Es el cierre absoluto. Indica al ordenador que las instrucciones de esa tarea concreta han terminado.
*NOTA: La identación NO es un capricho. El código no funcionará si no respetas la correspondiente tabulación.
En nuestro caso, hemos creado la subrutina Initialize, bajo la cual configuraremos TODAS las acciones que tengan que ejecutarse de forma automática nada más lanzar el formulario.
3.5 Dando órdenes
Una vez creada la subrutina, abordemos nuestro problema concreto: nuestro cmbDecision actualmente carece de contenido, con lo que queremos que el ordenador, al inicializar el formulario, le añada dos elementos: “Prorrogar” y “Denegar”.
Para ello, dentro de la subrutina, hay que darle órdenes al ordenador, y la lógica para ello es muy sencilla y siempre sigue el mismo esquema: primero escribimos el nombre del objeto al que nos referimos, luego ponemos un punto y, justo después, decidimos si queremos darle una instrucción o modificar sus propiedades:
- Acciones (métodos): Son órdenes directas para que el objeto “haga algo” activo. Por ejemplo.
- .AddItem: Añade este elemento al objeto.
- Clear: Borra todo el contenido previo asociado al objeto.
- Como estás dando una orden directa, simplemente dejas un espacio y pones el contenido.
- Ejemplo: cboDecision.AddItem “Prorrogar”
- Estados o contenido (propiedades): Son instrucciones que afectan las propiedades del objeto.
- .Visible: Cámbiame la visibilidad.
- .Value: Cambia el contenido del objeto.
- .Caption: Cambia la etiqueta que ve el usuario.
- * Como estás definiendo una característica, usas el signo “=”para asignar ese valor.
- Ejemplo: tglAproximación.Visible = False
Una vez escritas estas líneas, llega el momento comprobar si nuestro código funciona. Para ello, fíjate en la barra de herramientas superior del editor de VBA y busca el icono de un triángulo verde de Play al que nos referíamos con anterioridad. Al pulsar este botón, Word lanzará el formulario en modo de prueba, tal y como lo vería el usuario final en su día a día.
Si pinchas ahora en la flecha de tu cmbDecision, verás que el desplegable contiene ahora los dos elementos que hemos programado, Prorrogar y Denegar, listos para ser seleccionados.
Con tal de salir de la prueba, basta con pulsar el botón Restablecer en forma de cuadrado, al lado del botón Play.
3.6 Creando un formulario inteligente
Una vez que ya tenemos un desplegable con vida, vamos a por el objetivo final: que el formulario sea inteligente y reaccione a lo que el usuario decida. No queremos que la pantalla esté llena de botones que no se van a usar, queremos que el formulario se transforme según la lógica intrínseca a nuestro proyecto. Concretamente, no tiene sentido mostrar los botones de medidas si se va a denegar la prórroga.
Para ello, vuelve al editor y haz doble clic sobre el ComboBox (cmbDecision). Verás que se abre un nuevo cajón llamado Private Sub cmbDecision_Change(). En este caso, Change sí que es la acción que queremos, porque se activa cada vez que cambiamos la elección en la lista.
Si bien antes con la instrucción cboDecision.AddItem "Prorrogar" queríamos que dicha acción sucediera siempre que inicializáramos el formulario, ahora lo que pretendemos es que tenga lugar un evento pero condicionado a que se cumpla alguna condición previa.
Concretamente, nuestro objetivo es que se visibilicen o se oculten los botones del formulario según si el usuario selecciona la opción "Prorrogar" o la opción "Denegar" en el menú desplegable.
Esto es lo que se conoce como una estructura de control de flujo o código condicional, y su función primordial es crear una bifurcación en el flujo del programa, funcionando de manera idéntica a un sistema de puertas lógicas.
Esta estructura se denomina If... Then... Else (inglés para Si.... Entonces... En otro caso...), y su anatomía algorítmica es muy sencilla:
- SI el valor de cmbDecision es “Prorrogar”:
- Lo que queremos que haga es que los botones de Aproximación y Comunicación se vuelvan visibles.
- EN OTRO CASO (es decir, si eliges Denegar o dejas el cuadro vacío):
- Lo que queremos es que esos mismos botones se oculten o permanezcan invisibles.
El código para ejecutar este pensamiento es el siguiente:
Private Sub cmbDecision_Change()
If cmbDecision.Value = "Prorrogar" Then
tglAproximación.Visible = True
tglComunicación.Visible = True
Else
tglAproximación.Visible = False
tglComunicación.Visible = False
End If
End Sub
Lo mejor de este código es que, si lo lees en voz alta traduciendo las palabras del inglés, verás que es una frase que tiene todo el sentido del mundo. No es lenguaje binario ni con caracteres extraños, es lenguaje ordinario:
- If...: “Si la decisión es prorrogar...”
- Then: “...entonces, hazme el favor de mostrar los botones de las medidas.”
- Else ...en otro caso “... oculta los botones.”
- End If: “Y con esto, ya he terminado”
Junto con la anterior estructura, también es posible usar otro elemento llamado ElseIf:
Private Sub cmbDecision_Change()
If cmbDecision.Value = "Prorrogar" Then
tglAproximación.Visible = True
tglComunicación.Visible = True
ElseIf cmbDecision.Value = "Denegar"
Then tglAproximación.Visible = False
tglComunicación.Visible = False
Else tglAproximación.Visible = False
tglComunicación.Visible = False
End If
End Sub
Mientras que el Else es un cajón de sastre para todo lo que no hayamos previsto, el ElseIf nos permite introducir una segunda o tercera condición específica antes de llegar a ese final.
Sea como fuere, e independientemente de si aquí usamos Else o ElseIf, para que la magia de nuestro formulario sea perfecta nos falta un detalle técnico fundamental: los botones tglAproximación y tglComunicación deberían aparecer, de origen, invisibles. Por el contrario, si abrieras ahora el formulario, verías que, por defecto, aparecerían ambos botones visibles, desapareciendo solo al hacer clic en Denegar.
Tenemos dos caminos para conseguir que estos botones no se vean al principio:
- Opción A (a través de la ventana de Propiedades): Es la forma más visual. Solo tienes que volver al Escenario, pinchar una vez sobre el botón (por ejemplo, el de tglAproximación) y mirar la ventana de Propiedades que tienes a la izquierda, y en la propiedad llamada Visible, cambiar su valor por False.
- Opción B: A través del código (Initialize). Si prefieres tenerlo todo controlado por escrito, podemos aprovechar el cajón de Initialize que creamos antes. Recuerda que este apartado es el que prepara todo al cargar el formulario. Para ello, solo tenemos que añadir dos líneas más a nuestra subrutina:
Private Sub UserForm_Initialize()
cmbDecision.AddItem "Prorrogar"
cmbDecision.AddItem "Denegar"
tglAproximación.Visible = False
tglComunicación.Visible = False
End Sub
Ahora, cuando pulses el botón Play, el formulario aparecerá limpio, solo con el desplegable. Y en cuanto el usuario elija “Prorrogar”, el código que escribimos en el apartado anterior hará que los botones aparezcan en pantalla.
3.7 Rizando el rizo: el arte de prever lo inesperado
Llegados a este punto, conviene señalar que programar es también un ejercicio intelectual de previsión: debemos ser capaces de anticipar los efectos no deseados o lo que en el mundillo se conoce como monkey testing, es decir, imaginar qué pasaría si un usuario empieza a tocar botones de forma errática o cambia de opinión a mitad del proceso.
En nuestro ejemplo de la prórroga, es fácil advertir un problema de lógica si nos quedamos solo en la visibilidad: imagina que el usuario selecciona “Prorrogar” y marca los dos botones de medidas. De repente, cambia de opinión y selecciona “Denegar”. Los botones desaparecen (nuestro código funciona), pero siguen marcados internamente con el valor de activado. Si finalmente vuelve a marcar “Prorrogar”, los botones aparecerán de nuevo, pero aparecerán ya seleccionados de antes, lo cual es peligroso y puede dar lugar a resultados indeseados.
Para solucionar esto, no basta con modificar la visibilidad (.Visible); tenemos que resetear también el valor del botón (.Value). Queremos que, cuando se elija “Denegar”, el formulario no solo esconda los botones, sino que los desmarque automáticamente para que, si se vuelve atrás, todo esté como nuevo.
Private Sub cboDecision_Change()
If cboDecision.Value = "Prorrogar" Then
tglAproximación.Visible = True
tglComunicación.Visible = True
Else
tglAproximación.Visible = False
tglAproximación.Value = False
tglComunicación.Visible = False
tglComunicación.Value = False
End if
End Sub
Por ello, basta que en nuestra subrutina cboDecision_Change () introduzcamos dentro de la opción Else que tanto la visibilidad (.Visible) como el valor (.Value) de los botones se cambie a False.
< BLOQUE II. Creando el formulario
0 Comentarios