Tecnicas de UserForm Avanzadas PDF
Tecnicas de UserForm Avanzadas PDF
Tecnicas de UserForm Avanzadas PDF
UserForm
avanzadas
Anexo del Manual de Programacin
VBA Excel
http://www.ayudaexcel.com
Contenido
Este manual complementa el captulo 11 del Manual de Macros y programacin VBA. Aqu
encontraremos ms ejemplos de UserForms.
La mayora de los cuadros de dilogo que nos encontramos con cuadros de dilogo modales,
que debemos hacer desaparecer de la pantalla antes de poder realizar cualquier accin con la
aplicacin subyacente. Sin embargo, algunos dilogos son no modales, lo que significa que el
usuario puede seguir trabajando en la aplicacin mientras se muestra el cuadro de dilogo.
UserForm1.Show vbModeless
La palabra vbModeless es una constante integrada que tiene un valor de 0. Por lo tanto la
siguiente instruccin funciona de forma idntica:
UserForm1.Show 0
El siguiente ejemplo muestra un cuadro de dilogo no modal que contiene informacin sobre
la celda activa. Cuando se muestra el cuadro de dilogo, el usuario puede mover el cursor de la
celda, activar otras hojas y realizar otras acciones con Excel.
La clave est en determinar cundo actualizar la informacin del cuadro de dilogo. Para ello,
el ejemplo supervisa dos eventos del libro: SheetSelectionChange y SheetActivate. Estos
procedimientos de control de eventos se encentran en el mdulo de cdigo para el objeto
ThisWorkbook.
Sub UpdateBox()
With UserForm1
' Nos aseguramos de que hay una hoja activa
If TypeName(ActiveSheet) <> "Worksheet" Then
.lblFormula.Caption = "N/A"
.lblNumFormat.Caption = "N/A"
.lblLocked.Caption = "N/A"
Exit Sub
End If
El procedimiento UpdateBox cambia el ttulo del UserForm para que muestre la direccin de
la celda activa; despus actualiza los tres controles de etiqueta (lblFormula,
lblNumFormat y lblLocked).
El siguiente dibujo muestra una versin mucho ms sofisticada de este ejemplo. Esta versin
contiene un poco ms de informacin adicional acerca de la celda seleccionada. Los usuarios
veteranos de Excel notarn las similitudes con la ventana Info (una funcin que fue eliminada
de Excel hace varios aos).
Una de las necesidades ms comunes de los programadores de Excel tiene que ver con los
indicadores de progreso. Un indicador de progreso es un grfico parecido a un termmetro
que muestra el progreso de una tarea, como una macro, que tarde mucho en ejecutarse.
Para utilizar un indicador de progreso tenemos que poder (de alguna manera) calcular cunto
tardar la macro en completar su trabajo. Esto se puede hacer de varias formas, dependiendo
de la macro. Por ejemplo, si la macro escribe datos en celdas (y sabemos el nmero de celdas
que se van a escribir), basta con escribir cdigo que calcule el porcentaje completado. Incluso
si no podemos calcular de forma precesa el proceso de una macro, es una buena idea indicar al
usuario que la macro todava est en ejecucin.
Un indicador de progreso ralentizar un poco la macro debido al esfuerzo extra de tener que
actualizarla. Si la rapidez es absolutamente crucial en nuestro libro, quizs sea mejor renunciar
al indicador de progreso.
Mostrar el progreso en la barra de estado
Un modo simple de mostrer el progreso de una macro es utilizar la barra de estado de Excel.
La ventaja es que es muy fcil de programar. Sin embargo, el inconveniente es que la mayora
de los usuarios no estn acostumbrados a mirar la barra de estado y preferiran algo ms
visual.
Para escribir texto en la barra de estado, utilizamos una instruccin como sta:
Por supuesto, se puede actualizar la barra de estado mientras progresa la macro. Por ejemplo,
si tenemos una variable llamada Pct que prepresenta el porcentaje completado, podemos
escribir cdigo que peridicamente ejecute una instruccin como esta:
Cuando la macro finaliza, se devuelve la barra de estado a su estado normal con la siguiente
declaracin:
Application.StatusBar = False
Sub GenerateRandomNumbers()
' Inserta nmeros al azar en la hoja activa
Dim Counter As Integer
Const RowMax As Integer = 500
Const ColMax As Integer = 40
Dim r As Integer, c As Integer
Dim PctDone As Single
Por supuesto, podemos aplicar cualquier otro tipo de formato a los controles. Por ejemplo, se
puede cambiar la propiedad SpecialEffect del control de marco que aparece en el dibujo
anterior.
Sub GenerateRandomNumbers()
' Inserta nmeros al azar en la hoja activa
Dim Counter As Integer
Const RowMax As Integer = 500
Const ColMax As Integer = 40
Dim r As Integer, c As Integer
Dim PctDone As Single
Sub UpdateProgress(Pct)
With UserForm1
.FrameProgress.Caption = Format(Pct, "0%")
.LabelProgress.Width = Pct * (.FrameProgress. _
Width - 10)
.Repaint
End With
End Sub
Crear un procedimiento de inicio para un indicador de progreso independiente
Todo lo que falta es un procedimiento que muestre el UserForm. Introducimos el siguiente
procedimiento en un mdulo VBA:
Sub ShowUserForm()
With UserForm1
.LabelProgress.BackColor = ActiveWorkbook.Theme. _
ThemeColorScheme.Colors(msoThemeAccent1)
.LabelProgress.Width = 0
.Show
End With
End Sub
Para personalizar esta tcnica, tendremos que averiguar cmo determinar el porcentaje
completado y asignrselo a la variable PctDone. Esto variar dependiendo de la aplicacin. Si
el cdigo se ejecuta en un bucle (como en este ejemplo), determinar el porcentaje completado
es sencillo. Si el cdigo no est en un bucle, quizs tengamos que calcular el progreso
completado en varios puntos del cdigo.
Como en el ejemplo previo, ste introduce nmeros aleatorios en una hoja. La diferencia es
que esta aplicacin contiene un UserForm donde el usuario puede especificar la cantidad de
filas y columnas en las que insertar los nmeros aleatorios.
Modificar un UserForm para un indicador de progreso con un control de pgina
mltiple
Este paso presupone que existe un UserForm completamente configurado. Aadiremos un
control de pgina mltiple. La primera pgina del control de pgina mltiple contendr todos
los controles originales. La segunda contendr los controles que muestran el indicador de
progreso. Cuando la macro comience a ejecutarse, el cdigo VBA cambiar la propiedad
Value del control de pgina mltiple. Esto ocultar efectivamente los controles originales y
mostrar el indicador de progreso.
El siguiente paso es activar la pgina 2 y configurarla como la que se puede ver en el siguiente
dibujo. Es bsicamente la misma combinacin de controles utilizados en el ejemplo de la
seccin anterior.
Sub UpdateProgress(Pct)
With UserForm1
.FrameProgress.Caption = Format(Pct, "0%")
.LabelProgress.Width = Pct * (.FrameProgress. _
Width - 10)
End With
DoEvents
End Sub
Este procedimiento se invoca desde la macro que se ejecuta cuando el usuario hace clic en el
botn Aceptar, y realiza la actualizacin del indicador de progreso.
MultiPage1.Value = 1
Esta instruccin activa la pgina 2 del control de pgina mltiple (la pgina que muestra el
indicador de progreso).
En el siguiente paso, todo depender mucho ms del programador. Quizs haya que escribir
cdigo que calcule el porcentaje completado y asigne este valor a una variable llamada
PctDone. Este clculo se realizar dentro de un bucle. Despus se insertar la siguiente
instruccin, actualizando el indicador de progreso:
Call UpdateProgress(PctDone)
Me.Height = 172
Crear asistentes
Muchas aplicaciones incorporan asistentes para ayudar a los usuarios en alguna operacin. El
asistente para importar texto de Excel es un buen ejemplo. Un asistente es bsicamente una
serie de cuadros de dilogo que solicitan informacin del usuario. A menudo, las elecciones del
usuario en los primeros cuadros de dilogo influyen en los contenidos de los siguientes
cuadros de dilogo. En la mayora de los asistentes, el usuario puede avanzar o retroceder en
la secuencia de cuadros de dilogo o hacer clic en el botn Finalizar para aceptar todos los
valores predeterminados.
Por supuesto, podemos crear asistentes utilizando VBA y series de UserForms. Sin embargo, el
modo ms eficiente de crear un asistente es utilizar un nico UserForm y un control de pgina
mltiple con las fichas ocultas. El siguiente dibujo muestra un ejemplo de un simple asistente
de cuatro pasos que consta de un nico UserForm que contiene un control de pgina mltiple.
Cada paso del asistente muestra una pgina diferente del control de pgina mltiple.
A continuacin, aadimos los controles deseados para cada pgina del control de pgina
mltiple. Por supuesto, esto variar dependiendo de la aplicacin. Puede que tengamos que
cambiar el tamao del control de pgina mltiple mientras trabajamos para tener espacio para
los controles.
Aadir los botones al UserForm del asistente
A continuacin aadiremos los botones que controlen el progreso del asistente. Estos botones
se colocan fuera del control de pgina mltiple porque se usan mientas se muestra cualquiera
de las pginas. La mayora de los asistentes tienen cuatro botones:
En algunos casos, el usuario puede hacer clic en el botn Finalizar en cualquier momento y
aceptar los valores predeterminados para aquellos elementos que el usuario no ha definido.
En otros casos, el asistente necesita una respuesta del usuario para algunos elementos. En ese
caso, el botn Finalizar se deshabilita hasta que se realicen todas las entradas necesarias.
Los procedimientos de control de eventos para los botones Atrs y Siguiente son los
siguientes:
Sub UpdateControls()
Select Case MultiPage1.Value
Case 0
BackButton.Enabled = False
NextButton.Enabled = True
Case MultiPage1.Pages.Count - 1
BackButton.Enabled = True
NextButton.Enabled = False
Case Else
BackButton.Enabled = True
NextButton.Enabled = True
End Select
En este ejemplo, el cdigo utiliza dos matrices de controles, uno para los controles de casilla
de verificacin (paso 3) y otro para los controles de marco (paso 4). El cdigo utiliza un bucle
For-Next para ocultar los controles de los productos que no se utilizan y ajusta su posicin
vertical. Si ninguna de las casillas de verificacin del paso 3 est marcada, se ocultan todos los
elementos del paso 4 excepto un cuadro de texto que muestra Haz clic en Finalizar para salir (si
no se introdujo un nombre en el paso1) o Se requiere un nombre para el paso 1 (si no se
introdujo un nombre en el paso 1). El procedimiento MultiPage1_Change aparece a
continuacin:
TopPos = 22
FSpace = 8
AtLeastOne = False
r = Application.WorksheetFunction. _
CountA(Range("A:A")) + 1
Unload Me
End Sub
Tras probar el asistente y comprobar que todo parece funcionar correctamente, podemos
establecer el valor para la propiedad Style del control de pgina mltiple a 2
fmTabStyleNone.
Este ejemplo estudia una funcin personalizada que emula la funcin MsgBox de VBA. Al
principio, crear tal funcin puede parecer bastante fcil, pero no es del todo cierto. La funcin
MsgBox es extraordinariamente verstil gracias a los argumentos que acepta. Por tanto, crear
una funcin que emule MsgBox no es una tarea fcil.
La clave de este ejercicio no es crear una funcin alternativa que muestre mensajes. La clave
es mostrar cmo desarrollar una funcin relativamente compleja que tambin incorpora un
UserForm. Sin embargo, a algunas personas les puede gustar la idea de ser capaces de
personalizar sus mensajes. En ese caso, descubrirn que esta funcin es muy fcil de
personalizar. Por ejemplo, pueden cambiar las fuentes, los colores, el botn de texto y
elementos similares.
Esta sintaxis es exactamente igual que la sintaxis de MsgBox, excepto que no utiliza los dos
ltimos argumentos opcionales (Helpfile y Context). MsgBox tambin utiliza las mismas
constantes predefinidas que MsgBox: vbOkOnly, vbQuestion, vbDefaultButton1 y similares.
El UserForm que aparece a continuacin contiene cuatro controles de imagen (uno para cada
uno de los posibles iconos), tres controles de botn de comando y un control de cuadro de
texto.
Se incluyen otros tres procedimientos de control de eventos (uno para cada botn de
comando). Estas rutinas determinan en qu botn se hizo clic y devuelven un valor para la
funcin asignando un valor a la variable UserClick.
Este argumento crea un MsgBox con tres botones (S, No y Cancelar), muestra el icono de
pregunta y hace que el tercer botn sea el botn predeterminado. El argumento real es 547 (3
+ 32 + 512).
A pesar de las reducidas aplicaciones prcticas de esta tcnica, el ejemplo de esta seccin nos
ayudar a comprender los eventos relacionados con el ratn. El UserForm que se muestra a
continuacin contiene tres controles de imagen. El usuario puede utilizar el ratn para
arrastrar las imgenes por el cuadro de dilogo.
Cada uno de los tres controles de imagen tiene dos procedimientos de eventos asociados:
MouseDown y MouseMove. El procedimiento de evento para el control Image1 se muestra
a continuacin (los dems controles de imagen son idnticos a este, excepto por el nombre de
cada control):
Cuando se hace clic con el botn del ratn, tiene lugar el evento MouseDown, y se guardan las
posiciones X e Y del cursor. Se utilizan dos variables pblicas para hacer un seguimiento de la
posicin original de los controles: OldX y OldY. Este procedimiento tambin modifica la
propiedad ZOrder, que coloca la imagen sobre las otras.
Cuando se mueve el ratn, el evento MouseMove ocurre repetidamente. El procedimiento del
evento comprueba el botn del ratn. Si el argumento Button es 1, significa que el botn
izquierdo del ratn est presionado. En este caso, el control de imagen se mueve en relacin a
su antigua posicin.
Tambin, observamos que el cursor cambia cuando est sobre la imagen. Esto se debe a que la
propiedad MousePointer es 15 fmMousePointSizeAll. Este estilo de cursor se
utiliza comnmente para indicar que algo se puede mover.
Excel no ofrece ninguna manera de mostrar directamente un UserForm sin barra de ttulo.
Pero este reto es posible con la llamada de algunas nuevas funciones API. El siguiente dibujo
muestra un UserForm sin barra de ttulo.
Otro ejemplo de UserForm sin barra de ttulo se ofrece en el dibujo siguiente. Este cuadro de
dilogo contiene un control de imagen y un control de botn de comando.
Para mostrar un UserForm sin barra de ttulo necesitamos cuadro funciones API:
GetWindowLong, SetWindowLong, DrawMenuBar, y FindWindowA. El procedimiento
UserForm_Initialize invoca estas funciones:
Esta seccin describe cmo crear una barra de herramientas alternativa: un UserForm no
modal que simula una barra de herramientas flotante. El siguiente dibujo muestra un
UserForm que puede sustituir a una barra de herramientas.
El UserForm contiene ocho controles de imagen, y cada uno de ellos ejecuta una macro.
Al ver, en el editor de Visual Basic, el UserForm en modo Diseo, podremos observar que:
El cdigo VBA se encarga de la apariencia. Alinea los controles y ajusta la imagen del UserForm
para que no se malgaste ningn espacio, adems, el cdigo emplea funciones API de Windows
para reducir el tamao de la barra de ttulo, justo como una barra de herramientas de verdad.
Para hacer que el UserForm se parezca todava ms a una barra de herramientas,
estableceremos la propiedad ControlTipText de cada control de imagen. Esto har que se
muestre informacin sobre la herramienta similar a la de una barra de herramientas cada vez
que pasemos el cursor sobre ese control.
El efecto final es que el usuario consigue cierta informacin visual cuando el cursor pasa sobre
el control, como sucedera con una barra de herramientas de verdad. Sin embargo, esto es
todo lo que da de s la simulacin de la barra de herramientas. No es posible cambiar el
tamao del UserForm (por ejemplo, hacer que las imgenes se muestren verticalmente en
lugar de horizontalmente). Y, por supuesto, tampoco es posible acoplar nuestra barra de
herramientas a uno de los bordes de la ventana de Excel.
Un UserForm de tamao ajustable
Excel utiliza varios cuadros de dilogo de tamao ajustable. Por ejemplo, puede cambiarse el
tamao del cuadro de dilogo Administrador de nombres si hacemos clic en la esquina inferior
derecha y arrastramos.
Si queremos crear un UserForm de tamao ajustable, pronto descubriremos que no hay una
forma de hacerlo directamente. Una solucin es recurrir a las llamadas de la API de Windows.
El mtodo funciona, pero es complicado de configurar. En esta seccin veremos una tcnica
ms sencilla para crear un UserForm de tamao ajustable.
El truco est aqu en el control de etiqueta, que se agrega al UserForm en tiempo de ejecucin.
El control de tamao en la esquina inferior derecha es en realidad un control de etiqueta que
muestra la letra O (carcter 111) de la fuente Marlett (grupo de caracteres 2). Este control,
llamado objResizer, se agrega al UserForm en el procedimiento
UserForm_initialize:
Si estudiamos estos hechos de manera creativa, eremos que es posible traducir los
movimientos del usuario de un control de etiqueta en informacin que se puede utilizar para
ajustar el tamao de un UserForm.
Este procedimiento se ejecuta nicamente si el botn izquierdo del ratn est presionado (es
decir, el argumento Button es 1) y el cursor est en la etiqueta objResizer. Las
coordenadas X e Y del ratn se almacenan en las variables de mdulo LeftResizePos y
TopResizePos.
Si estudiamos el cdigo, veremos que las propiedades Width y Height se ajustan basndose
en el movimiento del control de etiqueta objResizer.
El problema del dibujo anterior, desde luego, es que el otro control del UserForm no responde
al nuevo tamao del UserForm. Debera expandirse el cuadro de lista, y debera cambiar la
posicin del botn de comando para que permanezca en la esquina inferior derecha.
Es necesario ms cdigo VBA para ajustar los controles del UserForm cuando se modifica su
tamao. Escribiremos este cdigo nuevo en el procedimiento controlador de eventos
objResizerMouseMove. La siguiente declaracin se encarga de ello:
Estos dos controles se ajustan en relacin al tamao del UserForm (es decir, Me). Despus de
insertar este cdigo nuevo, el cuadro de dilogo funciona sin problemas. El usuario lo puede
aumentar como necesite, y los controles se ajustan al tamao.
La parte que presenta un mayor desafo al crear un cuadro de dilogo de tamao ajustable es
lograr que los controles se ajusten. Cuando tenemos ms de uno o dos controles las cosas se
pueden complicar bastante.
Cada botn de comando de un UserForm debe tener su propio procedimiento para controlar
sus eventos. Por ejemplo, si tenemos dos botones de comando, necesitaremos al menos dos
procedimientos de control de eventos.
En otras palabras, no se puede asignar una macro para que se ejecute cuando se haga clic en
cualquier botn de comando. Cada controlador de eventos Click est conectado a su botn
de comando. Sin embargo, podemos hacer que cada controlador de eventos llame a otra
macro que los incluya a todos en los procedimientos de control de eventos, pero tendremos
que pasar el argumento que indique en qu botn se hizo clic. En los siguientes ejemplos, al
hacer clic en CommandButton1 o CommandButton2 se ejecuta el procedimiento
ButtonClick y el nico argumento indica al procedimiento ButtonClick en qu botn
se hizo clic.
Esta seccin describe una forma de eliminar esta limitacin utilizando un mdulo de clase para
definir una nueva clase.
Los siguientes pasos describen cmo crear el ejemplo de UserForm que se muestra a
continuacin:
Sub ShowDialog()
UserForm1.Show
End Sub
4. En el mdulo de cdigo para el UserForm, introducimos el siguiente procedimiento
UserForm_Initialize. Este procedimiento lo inicia el evento Initialize del
UserForm. Observamos que el cdigo excluye un botn llamado OKButton del grupo
de botones. Por lo tanto, hacer clic en el botn Aceptar no har que se ejecute el
procedimiento ButtonGroup_Click.
El ejemplo de esta seccin es una funcin que muestra un cuadro de dilogo (la idea es similar
a la funcin MsgBox, pero un poco ms complejo). La funcin, llamada GetAColor, devuelve un
valor de color:
UserColor = GetAColor ()
Ejecutar esta instruccin muestra el UserForm. El usuario selecciona un color y hace clic en
Seleccionar color. A continuacin, la funcin asigna el valor del color que ha seleccionado el
usuario a la variable UserColor.
El UserForm GetAColor tiene otro detalle: recuerda el ltimo color seleccionado. Cuando la
funcin finaliza, los tres valores de la barra de desplazamiento se almacenan en el registro de
Windows, con el siguiente cdigo (APPNAME es una cadena definida en Module1):
Las funciones SaveSetting y GetSetting siempre utilizan esta clave del registro:
Curiosamente, no hay una forma directa de mostrar un grfico en un UserForm. Por supuesto,
podemos copiar el grfico y pegarlo en la propiedad Picture de un control de imagen, pero
esto crea una imagen esttica del grfico y no mostrar ningn cambio que realicemos en l.
Esta seccin describe cmo mostrar un grfico en un UserForm. El siguiente dibujo muestra un
UserForm con un grfico que se muestra como un objeto de imagen. El grfico en realidad se
encuentra en una hoja y el UserForm siempre muestra el grfico actual. Esta tcnica funciona
copiando el grfico a un archivo de grficos temporal y despus, con la funcin
LoadPicture, especificamos el archivo temporal de la propiedad Picture del control de
imagen.
Pasos generales para mostrar un grfico en un UserForm
Para mostrar un grfico en un UserForm, seguimos estos pasos generales:
Image1.Picture = LoadPicture(Fname)
Si desea obtener ms ejemplos de UserForms o aprender otras tcnicas con VBA le invitamos a
visitar nuestra web, http://www.ayudaexcel.com, donde encontrar la coleccin ms completa
de ejemplos con VBA, plantillas, manuales, trucos y academias donde se imparten cursos de
Excel.