Está en la página 1de 38

Curso de Programación en

VBA para Excel

Capítulo 1. Introducción y primeros pasos

Este curso va dirigido a aprender a programar en Visual Basic for Applications (VBA) para la
hoja de cálculo Microsoft Excel. El VBA es muy similar en el resto de herramientas de Microsoft
Office (Word, PowerPoint, etc), por lo que los conocimientos aquí adquiridos pueden aplicarse
en esos otros programas. Además el VBA es también muy similar al Visual Basic de verdad,
por lo que puede ser una puerta de acceso a la programación de aplicaciones (utilizando Visual
Basic) para personas sin conocimientos previos de programación.

Desde los primeros tiempos de las hojas de cálculo, con las míticas primeras versiones de
Lotus 1-2-3, existían macros (el nombre completo era macro-comandos), que servían para
automatizar tareas repetitivas. En aquellos tiempos las macros se limitaban básicamente a
simular pulsaciones del teclado el usuario, es decir, al ejecutar una macro era como si el
usuario estuviese pulsando las teclas que la macro "pulsaba", lo que a pesar de su sencillez
permitía hacer cosas interesantes. Con el tiempo las macros fueron evolucionando, pudiéndose
incluir en ellas sentencias que no se traducían en pulsaciones de teclas, aunque todo ello se
hacía introduciendo fórmulas en las celdas de la hoja de cálculo, lo que dejaba bastante que
desear.

Con la llegada de Excel 5.0, Microsoft introdujo las macros basadas en el popular Visual Basic,
creando lo que ha llamado Visual Basic for Applications, compartido por todas las aplicaciones
de Microsoft, y que añade a las mismas unas posibilidades enormes de personalización y
creación de soluciones a medida de las necesidades de cada usuario. De hecho, creo que el
nombre "macro" debería dejar de utilizarse en favor de otros conceptos más relacionados con
los lenguajes de programación (como rutinas, subrutinas y funciones), pero yo creo que se
mantiene por razones históricas.

Lo primero que tuve que decidir antes de escribir este curso sobre
programación en Excel fue hacia quién iba a ir dirigido: por un lado están todas
las personas que dominan uno o más lenguajes de programación, y con poco
esfuerzo pueden aprender los detalles específicos de Visual Basic for
Applications para Excel.

Por otro lado están todas aquellas personas que utilizan Excel simplemente
como una hoja de cálculo que hace operaciones aritméticas, que desaprovechan toda la
potencia de Excel. He decidido que este curso va a ir dirigido a estos últimos, porque creo que
es el perfil del usuario habitual de Excel, y aquellas personas que estén en el primer grupo
pueden también utilizar el curso, deteniéndose en las partes que expliquen cosas específicas
de Excel y saltándose otras como los conceptos generales de programación.

Una nota sobre versiones de Excel: la última versión de Excel es la de Office 97 (llamada Excel
97), aunque todavía existen muchos sitios en los que se utiliza la versión de Office 95 (Excel
95). Casi todo lo que vamos a hacer funciona en las dos versiones, y en los casos en los que
no sea así procuraré indicarlo.

El mejor método para aprender VBA es utilizar la opción de grabar macros de Excel: todo lo
que hagamos mientras Excel está grabando una macro se traduce en la instrucciones de VBA
necesarias para repetir nuestras acciones. Vamos a utilizar esa opción para crear nuestra
primera macro. Primero selecciona la opción "Herramientas, Grabar Macro", y escribe algo en
la celda A1. Luego selecciona la opción "Herramientas, Grabar macro..., Detener grabación"
para que Excel debe de grabar. Para ver la macro que acabamos de crear el método es distinto
en Excel 95 y Excel 97: en Excel 95, las macros se almacenan en módulos, que son como una
hoja más del libro, podemos ver una hoja llamada "Módulo1" en las pestañas que están en la
parte inferior. En Excel 97, para escribir macros se utiliza el Visual Basic Editor, y accedemos a
él mediante la opción Herramientas, Macros, Abrir Editor Visual Basic. En cualquiera de las dos
versiones veremos que Excel ha escrito algo parecido a esto:

Sub Macro1()
ActiveCell.Formula = "Mi primera macro"
Range("A2").Select
End Sub

Esta rutina escribe "Mi primera macro" en la celda activa y luego se desplaza a la celda inferior,
en este caso la celda A2 (esto ocurre porque Excel tiene por defecto la opción de que cuando
pulsas "Intro" el cursor se desplaza a la celda de abajo, y Excel también ha incluido eso en la
macro).

Vamos a ir poco a poco. La primera línea define una subrutina llamada Macro1 (es el nombre
que le ha puesto Excel, pero podemos cambiarlo a lo que nosotros queramos). Cada rutina que
escribamos debe empezar con Sub y terminar con una sentencia "End Sub".

Antes de explicar la segunda línea, una explicación sobre los "objetos": un objeto es una
variable de VBA que representa cualquier elemento de Excel. Por ejemplo, para representar un
rango de una hoja de cálculo se utiliza el objeto Range, o para representar una hoja de cálculo
se utiliza el objeto Worksheet. En nuestra macro estamos utilizando el objeto "ActiveCell", que
es un objeto de tipo Range que siempre apunta a la celda activa.

Los objetos tienen "propiedades" y "métodos". Una propiedad es un atributo del objeto que
define una característica del mismo. Por ejemplo, la propiedad "Row" del objeto "ActiveCell"
nos indica en qué fila de la hoja de cálculo está la celda activa. Para acceder a una propiedad
de un objeto se utiliza el nombre del objeto, un punto y el nombre de la propiedad (p.ej.
ActiveCell.Row). Unas propiedades muy utilizadas son las propiedades "Value" y "Formula" que
se aplican a todos los objetos Range. En nuestro ejemplo de macro, asignamos a la propiedad
"Formula" del objeto ActiveCell un texto, que es como si el usuario escribiera ese texto en esa
celda.

Los "métodos" son acciones que se pueden llevar a cabo sobre un objeto, son rutinas que se
aplican sobre el objeto. Para llamar a un método se utiliza el nombre del objeto, un punto y el
nombre del método. Por ejemplo, el método "ActiveCell.ClearContents" borra el contenido de la
celda activa (es decir, como si el usuario pulsa la tecla "Suprimir").

Volvamos a nuestra primera macro. La segunda línea asigna un valor a la propiedad " Formula"
del objeto ActiveCell. En realidad no es una formula sino una cadena, pero da lo mismo. Fíjate
en que en VBA siempre que escribamos una cadena de caracteres hay que encerrarla entre
comillas dobles ("), igual que en otros lenguajes. Si dentro de una cadena queremos poner
unas comillas dobles, sólo tenemos que escribirlas dos veces ("en esta cadena hay unas
comillas "" dobles")

La tercera línea llama al método Select del rango "A2" de la hoja activa. Fíjate en la forma de
obtener el objeto que representa a la celda "A2", utilizando Range("A2"). La última línea se
encarga de indicar dónde termina la rutina. Por cada Sub que escribamos obligatoriamente
tenemos que escribir un "End Sub".

Ejecutar una subrutina


Para ejecutar una rutina hay varios métodos.

 Con la opción "Herramientas, Macro..." Excel te lista todas las macros disponibles y
puedes seleccionar la que quieras y ejecutarla.
 Asignar una macro a una nueva opción del menú de Herramientas.
 Asignar una "tecla rápida" a la macro, que se ejecutará cada vez que pulsemos esa
tecla.
 Crear un botón y asignar a ese botón la rutina, de forma que ésta se ejecutará cada
vez que pulsemos el botón. Para crear un botón tenemos que mostrar la barra de
herramientas de "Diálogo" (pulsa con el botón derecho sobre cualquier barra de
herramientas, y en el menú que aparece selecciona "Diálogo" y verás que aparece la
nueva barra de herramientas).
 En esa barra de herramientas hay un botón que sirve para colocar botones (valga la
redundancia) en nuestra hoja. Pulsa ese botón y crea el tuyo en cualquier parte de una
hoja de cálculo, con el tamaño que quieras. Luego pulsa sobre ese botón con el botón
derecho y del menú contextual selecciona la opción "Asignar macro". Verás una lista de
macros disponibles, selecciona la que acabamos de crear (Macro1). Ahora cada vez
que pulsemos el botón se ejecutará la macro Macro1.
 Mientras estamos editando una hoja de módulos, un método muy práctico de ejecutar
las rutinas es situar el cursor dentro de una rutina y pulsar el botón de "Ejecutar
macro" de la barra de herramientas de Visual Basic. Hay que tener cuidado con este
método en Excel 95, porque en algunos casos puede dar errores: por ejemplo, con este
método nuestra primera macro no funciona porque "ActiveCell" no existe, ya que
estamos en una hoja de módulo, por lo que Excel nos dará un mensaje de error. En
Excel 97 este problema no ocurre porque no existen hojas de módulo, sino módulos
dentro del Visual Basic Editor.

Podemos utilizar cualquiera de estos métodos (y otros que ya veremos) para ejecutar nuestra
rutina, y comprobaremos que cada vez que la ejecutamos escribe un texto en la celda activa y
luego desplaza la selección a la celda de abajo.

Utilizar funciones de VBA

Además de los objetos con sus métodos y propiedades Excel también tiene funciones. Para
llamar a una función simplemente hay que escribir su nombre y luego los parámetros
necesarios. Por ejemplo, vamos a hacer una pequeña macro que utilice la función MsgBox.

Esta función sirve para presentar cuadros de diálogo con mensajes para el usuario, aunque no
tenemos muchas opciones para diseñar el diálogo, sólo se puede elegir el tipo de icono entre
varios predefinidos (interrogación, exclamación, etc.) y unas cuantas opciones sobre los
botones del cuadro de diálogo (Aceptar, Cancelar, Sí, No...). A pesar de todo es muy útil para
presentar información al usuario, por ejemplo cuando se ha terminado un proceso con éxito,
cuando ha ocurrido un error, o para pedir información del tipo de "¿Estás seguro de que
quieres hacer....?", lo que hace que se una función bastante utilizada.

Pues nada, aquí tenemos una pequeña rutina que utiliza la función MsgBox:

Sub MiMacro()
MsgBox "Hola mundo", vbOkOnly + vbInformation,
"Mi segunda macro"
End Sub

Recuerda que para escribir la macro tienes que situarte en una hoja de módulo en Excel 95, o ir
al editor de VB en Excel 97, y dentro de él seleccionar un módulo. Por ejemplo, podemos
escribir esta macro debajo de la que hemos creado antes utilizando la "grabadora" de Excel.
Si ejecutamos esta macro, veremos que sale un cuadro de diálogo
con el título "Mi segunda macro" y con el texto "Hola mundo", además
de un icono que indica que es un cuadro de información, y el botón
aceptar.

Hemos llamado a MsgBox, pasándole como primer parámetro el


texto del cuadro de mensaje, como segundo parámetro los
botones e icono que queremos que tenga y como tercer
parámetro el título del cuadro de diálogo.

Como habrás podido observar los argumentos van separados por comas. También se
pueden poner más parámetros para indicar qué fichero de ayuda queremos que se abra si el
usuario pulsa F1 mientras está viendo el cuadro de diálogo. Si quieres más información sobre
dichos parámetros, así como una lista de todas las opciones que puedes utilizar como segundo
parámetro (distintos botones e iconos) utiliza la ayuda de Excel, que es bastante completa. La
mejor forma de utilizar la ayuda es colocar el cursor sobre la instrucción sobre la que queremos
buscar la ayuda y pulsar F1. Si Excel encuentra esa palabra en el archivo de ayuda, nos
mostrará la página de ayuda sobre ella.

Otra pequeña macro que utiliza MsgBox:

Sub Macro3()
If MsgBox("Pulsa Aceptar o Cancelar",
vbOKCancel) = vbOK Then
MsgBox ("Has pulsado Aceptar")
Else
MsgBox ("Has pulsado Cancelar")
End If
End Sub

Bueno, varias cosas nuevas. En primer lugar el "If - Then - Else - End If". Como su nombre
indica, esta instrucción (la ayuda de Excel los llama enunciados) se utiliza para evaluar
condiciones. Su forma general es: If <condición> Then .... Else .... End If

Si el resultado de la condición es verdadero, se ejecutan las instrucciones que hay entre el If y


el Else. Si es falso, se ejecutan las instrucciones que hay entre el Else y el End If. El Else no
es obligatorio, o sea que si no nos interesa ejecutar nada en caso de que la condición no sea
verdadera, simplemente ponemos un End If y ya está.

Volvamos a nuestra función: lo que hacemos es llamar a la función MsgBox


con un texto y un parámetros (vbOkCancel) indicando los botones que
queremos que tenga. Hasta aquí todo claro. Lo único que cambia respecto al
ejemplo anterior es que como hemos puesto MsgBox detrás del If, Excel nos
obliga a poner los parámetros entre paréntesis. Lo que hacemos después es
comprobar el valor que nos devuelve la función MsgBox una vez que el
usuario ha cerrado el cuadro de diálogo.

El usuario va a tener dos botones (Aceptar y Cancelar), y dependiendo de cuál de ellos pulse
obtendremos un valor u otro, representados por Excel mediante unas constantes: vbOk si el
usuario pulsa Aceptar, vbCancel si el usuario pulsa Cancelar, vbYes si el usuario pulsa Sí (que
en este ejemplo no existe pero podemos ponerlo), etc. Como siempre, en la ayuda de Excel
están todas los valores posibles que puede devolver MsgBox.

Bueno, entendido esto supongo que el resto de la macro es fácil de entender: lo que hace es
mostrar un mensaje con dos botones (Aceptar y Cancelar), y dependiendo de lo que el usuario
seleccione muestra otro mensaje informando al usuario de lo que ha pulsado. No es que sea
demasiado útil pero nos ha servido para aprender algo más.

Vamos hacer otra macro un poco más complicada, que utilice la función MsgBox y las
propiedades de los objetos que hemos aprendido antes:

Sub Macro4()
If MsgBox("Información sobre la celda activa: " & Chr(13) & _
"Fórmula: " & ActiveCell.Formula
& Chr(13) & _ "Valor: " & ActiveCell.Value _
& Chr(13) & Chr(13) & _ "Pulsa Aceptar para borrar el contenido de la
celda activa " _ & "y Cancelar para dejarla como está", _ vbOKCancel +
vbInformation, "Mi cuarta macro") = vbOK Then
ActiveCell.Value = ""
End If
End Sub

Bueno, hay varias cosas que explicar: con el caracter "_" al final de una línea queremos decirle
a Excel que la línea continúa, pero lo vamos a escribir debajo (por razones de legibilidad). Es
decir, es como si desde el "If" de la segunda línea hasta el "Then" de la séptima línea estuviese
todo en la misma línea, pero si lo pusiésemos en la misma línea sería bastante difícil de leer.

El carácter "&" se utiliza para concatenar dos cadenas de caracteres. Por ejemplo, la cadena
"Macedonia Magazine" es igual que la cadena "Macedonia " & "Magazine".

La función Chr() se utiliza para obtener el carácter representado por un código ASCII. No es
demasiado utilizada, tan sólo nos interesa saber que código ASCII número 13 representa el
cambio de línea, y en este caso lo utilizamos para empezar una nueva línea en el texto que
vamos a presentar en el cuadro de diálogo.

Fíjate cómo obtenemos información sobre la celda activa utilizando las propiedades Formula y
Value del objeto ActiveCell. Podemos observar que las propiedades Formula y Value son
distintas cuando las leemos (una tiene la fórmula, y la otra tiene el valor) mientras que para dar
un valor a la celda nos da lo mismo utilizar una u otra: la línea que dice ActiveCell.Value = ""
puede sustituirse por ActiveCell.Formula = "", obteniendo el mismo resultado.

Para ejecutar esta rutina, vamos a probar el método de asignar a una tecla esta macro. Para
ello vamos a Herramientas, Macro. De la lista de macros, seleccionamos ésta y pulsamos el
botón "Opciones...", que nos llevará a una ventana donde aparecen varias opciones para
nuestra macro. En este diálogo podemos decir a Excel que ponga la macro como una opción
del menu de Herramientas, y también como tecla rápida. Podemos poner por ejemplo la tecla
Ctrl-M. Ahora vamos a una hoja de cálculo, e introducimos en cualquier celda la fórmula
"=5+2". Si pulsamos ahora las teclas Ctrl-M ejecutaremos nuestra macro y veremos lo
siguiente:

Bueno, espero que haya quedado relativamente claro. Hasta ahora hemos aprendido lo que es
una macro o rutina, cómo ejecutarla, unos conceptos básicos sobre objetos y la instrucción "If-
Then-Else", una de las más utilizadas.

Vamos a avanzar un poco más, aprendiendo a utilizar otra instrucción muy útil, el bucle "For", y
a profundizar un poco en el uso del objeto Range, que es seguramente el más utilizado.
Después de haber hecho el típico programa "Hola mundo" (el primero que hemos hecho todos
cuando hemos aprendido un lenguaje de programación) vamos a hacer ahora otro clásico:
vamos a pedirle al usuario que nos de un número y le vamos a dar la tabla de multiplicar de ese
número.
Aquí va la rutina completa, y luego la explicamos:

Sub TablaMultiplicar()
Dim n, i As Integer
Dim s As String
Dim r As Range

s = InputBox("Tabla de multiplicar del número: ", "Título")


If s <> "" Then
n = Val(s)
ActiveSheet.Range("C2").Value = "Tabla de multiplicar del " & n
Set r = ActiveSheet.Range("C4")
For i = 0 To 10
r.Offset(i, 0).Value = i
r.Offset(i, 1).Value = i * n
Next i
End If
End Sub

Pulsa aquí para bajarte un fichero de Excel que contiene este ejemplo. Lo primero es la
declaración de variables. Una variable es un espacio de memoria que reservamos para
almacenar datos.

Con la sentencia "Dim n,i as Integer" estamos diciendo que queremos reservar memoria para
dos variables (n, i) de tipo entero, para almacenar números enteros. Igualmente en las
siguientes líneas reservamos memoria para una variable de cadena (string), que almacenará
cadenas de caracteres, y para una variable de tipo Range. En VBA no es obligatorio declarar
las variables antes de utilizarlas, a no ser que en cada módulo escribamos al principio "Options
Explicit", con lo que estaremos indicando a VBA que debe comprobar que todas las variables
que utilicemos estén previamente declaradas. No voy a entrar en la eterna polémica de si es
mejor declarar las variables o no hacerlo, pero personalmente creo que es mejor hacerlo, para
que el tipo de datos que almacena cada variable esté claro y para evitar errores al escribir los
nombres de variables que luego pueden ser difíciles de localizar.

En la siguiente línea utilizamos la función "InputBox", que sirve para mostrar


un cuadro de diálogo simple en el que el usuario puede escribir un dato. El
primer parámetro es el texto descriptivo que se mostrará en el cuadro de
diálogo y el segundo parámetro es el título del cuadro de diálogo. El usuario
puede utilizar el cuadro de edición del diálogo para introducir el dato que le
pedimos y luego pulsar Aceptar o Cancelar. Si pulsa Aceptar, la función
InputBox devuelve una cadena de caracteres con el dato introducido por el
usuario. Si pulsa Cancelar, la función devuelve una cadena de caracteres
vacía (""). Utilizamos la función InputBox para que el usuario nos diga qué tabla de multiplicar
quiere, y almacenamos el valor devuelto por la función en la variable s, que previamente hemos
declarado como una variable de tipo cadena de carácteres (string).

Después de llamar a InputBox, comprobamos que variable "s" no está vacía, lo que significa
que el usuario ha escrito algo en el diálogo y luego ha pulsado Aceptar. Si "s" esta vacía, la
rutina termina sin hacer nada más.

Nuestro siguiente paso es obtener el número que ha introducido el usuario. Es importante


distinguir entre números y cadenas: en este momento tenemos la cadena de caracteres "s" que
contiene la cadena introducida por el usuario, y como queremos hacer operaciones aritméticas
necesitamos el número contenido en esa cadena. Por ejemplo, si el usuario ha escrito "3", la
variable "s" contendrá una cadena de caracteres de un solo carácter ("3"), y lo que nosotros
queremos obtener es el valor numérico 3. Para ello utilizamos la función Val(), que dada una
cadena de caracteres no da su valor numérico: p.ej: Val("3") nos devuelve 3. El resultado de la
función Val lo almacenamos en la variable n, que previamente hemos declarado como variable
de tipo entero.

Como siempre suele suceder, existe la posibilidad de que el usuario haya escrito un valor con
decimales o que haya escrito letras en lugar de números. En una macro más profesional
deberíamos comprobar esas posibilidades para asegurarnos de que nuestra macro no sufre
ningún error en caso de que el usuario introduzca algún dato inesperado, pero por ahora no
vamos a meternos en líos de esos.

La siguiente línea debería ser fácil de entender a estas alturas: damos un valor a la propiedad
"Value" del rango C2 de la hoja activa, al que accedemos utilizando "ActiveSheet.Range("C2")".
Una pequeña recomendación: siempre que hagas referencia a rangos de hojas de cálculo
desde VBA es recomendable utilizar nombres definidos de rango en lugar de referencias tipo
C2. Por ejemplo, podemos dar a la celda C2 el nombre "Título tabla" y acceder a ella utilizando
Range("Título tabla"). La ventaja de esto es que si luego queremos que en lugar de en la celda
C2 lo escriba en cualquier otra celda sólo tenemos que cambiar el nombre, sin tocar el código.

En la siguiente línea utilizamos el enunciado "Set" para que la variable r (de tipo Range) apunte
al rango C4 de la hoja activa.

Luego viene la sentencia "For - Next", que tiene varias formas, pero esta es la más sencilla: lo
que hacemos es que la variable "i" (como siempre, previamente declarada como de tipo entero)
tome los valores comprendidos entre el 0 y el 10 (ambos inclusive), y para cada uno de esos
valores se ejecute el código comprendido entre las líneas For y Next. Es decir, las dos líneas
que hay entre el For y el Next se van a ejecutar once veces: la primera vez que se ejecuten, la
variable i tendrá el valor 0; la segunda vez, i tendrá el valor 1; y la última vez i tendrá el valor
10. El bucle "For - Next" es muy utilizado, y en VBA funciona de forma muy parecida a
cualquier otro lenguaje de programación.

Las dos líneas que hay entre el For y el Next son prácticamente iguales. El método " Offset" es
un método que se aplica a los objetos de tipo Range (como nuestra variable "r") para desplazar
el rango al que apunta. El primer parámetro del método Offset es el número de filas que
queremos desplazar el rango (positivo hacia abajo, negativo hacia arriba), y el segundo
parámetro es el número de columnas que queremos desplazar el rango. Vamos a verlo con un
ejemplo: si nuestra variable "r" apunta al rango C4:

r.Value = 1 Pone el valor 1 en la celda C4


r.Offset(1,0).Value = 2 Pone el valor 2 en la celda C5
r.Offset(-1,0).Value = 3 Pone el valor 3 en la celda C3
r.Offset(0,1).Value = 4 Pone el valor 4 en la celda D4
r.Offset(-1,-1).Value = 5 Pone el valor 5 en la celda B3

Las dos líneas de nuestra rutina lo que hacen es crear una tabla de dos columnas, poniendo en
la primera columna los números del 0 al 10 (es decir, los valores que va tomando i cada vez
que se ejecutan estas dos líneas) y en la segunda columna el resultado de multiplicar el valor
de i por el número que nos ha indicado anteriormente el usuario (n).

Antes de terminar con este ejemplo hay que dejar claro que la tabla de multiplicar puede
hacerse de forma mucho más sencilla y rápida sin utilizar macros, utilizando tan sólo funciones
de hoja de cálculo, pero nos ha servido como ejemplo sencillo para aprender algunas cosas
más sobre VBA.

Bueno, hasta aquí ha llegado la primera entrega de este curso. Con lo que hemos aprendido
hasta aquí se pueden hacer ya algunas cosas. Que a nadie le de miedo hacer todos los
experimentos que quiera, que es la mejor forma de aprender. También es muy útil consultar a
menudo la ayuda de Excel, que es bastante completa. Espero que alguno de los que habéis
llegado hasta aquí me escribáis diciéndome qué os ha parecido.

Capítulo 2. Celdas, rangos, libros y hojas.

En este capítulo vamos a aprender un poco más sobre cómo hacer referencia a celdas, rangos,
hojas y libros. Supongo que todos estos conceptos están claros, que todo el mundo sabe lo que
es una celda o un rango, o la diferencia entre un libro y una hoja.

Excel2.xls
Todos los ejemplos de este capítulo están incluidos en este fichero:
(39kbs)

Bueno, para entrar en calor vamos a hacer una pequeña rutina que pida al usuario un valor y
luego sume ese valor a la celda activa.

Sub Sumar_A_Celda()
Dim i As Double

If MsgBox("Esta macro pide al usuario


un valor y lo suma a la celda activa.", _
vbOK, "Sumar a celda") = vbCancel Then Exit Sub
i = Val(InputBox("Importe a sumar: ", "Sumar a celda activa"))
ActiveCell.Value = ActiveCell.Value + i
End Sub

La primera línea es la declaración de la variable "i". Ya hemos comentado anteriormente lo que


es la declaración de variables, lo único nuevo es el tipo de variable (double). Cuando
declaramos una variable hay que indicar qué tipo de variable queremos que sea. Los tipos de
variables más importantes son:

Integer Un valor entero, entre -32.768 y 32.767


Long Un valor entero, entre -2.147.483.648 y 2.147.483.647
Boolean Verdadero y Falso
Single Un valor con decimales, con precisión simple
Double Un valor con decimales, con precisión doble
String Un cadena de caracteres
Date Una fecha
Object Referencia a cualquier tipo de objeto de Excel
Variant Un variable que puede cambiar de tipo

En este caso declaramos la variable como Double, por si acaso al usuario se le ocurre meter
un valor con decimales.

Siguiendo con nuestra rutina, primero presentamos al usuario un pequeño mensaje diciendo lo
que vamos a hacer. Esto está explicado en la entrega anterior, no creo que necesite nada más.
Si el usuario pulsa "Cancelar", salimos de la rutina y no hacemos nada.

En la siguiente línea obtenemos del usuario el valor que quiere sumar a la celda activa. La
función InputBox ya la hemos visto antes, obtiene del usuario una entrada, pero en formato de
cadena de caracteres. Como nosotros lo que queremos es un valor numérico, utilizamos la
función Val() para convertir la cadena de caracteres proveniente de InputBox en un número. Lo
ponemos todo en la misma línea, pero también se podía haber escrito en dos líneas:
Dim s as String
s = InputBox("Importe a sumar: ", "Sumar a celda activa")
i = Val(s)

Bueno, seguramente queda más claro que de la otra forma, pero normalmente se escribe de la
primera forma. Cada uno que lo escriba como quiera, tampoco tiene demasiada trascendencia.

La última línea es la que hace realmente la suma, dando valor a la propiedad


Value de ActiveCell. Ya hemos visto en la entrega anterior lo que es
ActiveCell. Una aclaración sobre ActiveCell y ActiveSheet (que también
vimos en la entrega anterior): en realidad, ActiveCell no es un objeto, sino
que es una "propiedad" de un objeto especial llamado Application, pero
cuando escribimos "ActiveCell" Excel entiende que estamos escribiendo
"Application.ActiveCell". Application es un objeto que representa la
aplicación Excel completa. A través de Application se puede acceder a
todas las opciones de la aplicación (las que podemos cambiar a través de Herramientas,
Opciones), acceder a las funciones de hoja de cálculo (SUMA, PROMEDIO, etc) y también
podemos obtener objetos que referencian a la celda activa (ActiveCell), la hoja activa
(ActiveSheet), el libro activo (ActiveWorkbook), etc.

Un pequeño ejemplo del uso del objeto Application: para mostrar y ocultar la barra de estado (la
que aparece en la parte de abajo, debajo de las etiquetas de las hojas), podemos usar el
siguiente código:

Para ocultar la barra de estado:


Application.DisplayStatusBar = False
Para volver a mostrar la barra de estado:
Application.DisplayStatusBar = True

El objeto Application tiene un montón de propiedades y métodos, que están muy bien
explicados en la ayuda de Excel, y su uso es bastante sencillo.

Siguiendo con la última línea de la rutina, podrás comprobar que utilizamos la propiedad Value
de ActiveCell. Si hubiésemos utilizado la propiedad Formula en lugar de Value, la rutina tendría
que ser un poco distinta. Utilizando Value, estamos dando a la celda activa un valor
directamente, es decir, si miras el contenido de la celda verás que no hay ninguna fórmula; la
suma la ha hecho nuestra rutina, y ha puesto en la celda el resultado de dicha suma.

Sin embargo, si queremos que la fórmula de la suma quede en la celda debemos usar la
propiedad Formula. La propiedad Formula es una "cadena de carácteres", que incluye todo lo
que se escribiría normalmente en una celda de una hoja de cálculo para introducir una fórmula
(incluyendo el signo "=" al principio). Por ejemplo, si queremos que poner en la celda A2 una
fórmula que nos de el doble del valor de la celda A1, haremos:

Range("A2").Formula = "=A1*2"

Como es una cadena de caracteres, hay que rodearla con comillas dobles, y entre éstas
ponemos la fórmula tal como lo haríamos en la hoja de cálculo. Tras esta explicación, si
queremos cambiar nuestra rutina para introducir la fómula de suma en la celda, nuestro primer
intento sería escribir:

ActiveCell.Formula = ActiveCell.Formula + i

Si ejecutamos este código veremos que el resultado puede variar dependiendo de lo que
contenga la celda activa:
 Si la celda activa contiene un número (no una fórmula), el resultado es el mismo que
antes. La razón es que como no hay ninguna fórmula ActiveCell.Formula devuelve un
número, igual que ActiveCell.Value. Luego le sumamos nuestro valor y asignamos el
valor resultante como fórmula de la celda.
 Si la celda activa contiene una fórmula, el resultado es que la macro se para con un
error. Esto es debido a que ActiveCell.Fórmula nos devuelve una cadena de caracteres
(por ejemplo, la cadena "=A1*2"), y luego estamos intentando sumar un número (i) a
una cadena de caracteres, cosa que evidentemente no se puede hacer y Excel nos da
un error de tipos de datos incompatibles.

Para conseguir lo que realmente queremos (introducir una fórmula en la celda), debemos
asignar a ActiveCell.Formula una cadena de caracteres con una fórmula escrita correctamente.
Vamos a intentarlo:

ActiveCell.Formula = ActiveCell.Formula & "+" & i

El operador & ya lo vimos en la primera entrega, se utiliza para concatenar cadenas de


caracteres. Partimos de la fórmula que actualmente tiene la celda activa (por ejemplo, "=A1*2")
y luego le añadimos un signo "+" y luego nuestro valor (i), con lo que la fórmula pasará a ser
"=A1*2+3" (si i tiene el valor 3).

El problema que se nos presenta ahora es que si en la celda activa no hay una celda, sino un
valor (por ejemplo, 2), nosotros asignaremos a ActiveCell.Formula la cadena "2+3" (si i tiene el
valor 3). ¿Veis el error? Evidentemente el error es que falta el signo "=" al principio de la
fórmula para decirle a Excel que es una fórmula. O sea que deberíamos añadir delante de la
fórmula un "=", lo que podemos hacer de la siguiente forma:

ActiveCell.Formula = "=" & ActiveCell.Formula & "+" & i

¿Cuál es el problema ahora? Pues que si la celda activa tiene una fórmula nos encontramos
con que nuestra fórmula definitiva tiene dos signos "=" al principio, uno el que ya tenía y otro el
que le hemos puesto nosotros. El resultado es que introducimos una fórmula incorrecta y Excel
nos vuelve a dar un error.

Bueno, creo que he montado un pequeño lío, pero en realidad no tiene ninguna dificultad. Lo
que hay que hacer es comprobar si en la celda activa hay una fórmula (esto se puede hacer
mirando si el primer carácter es el signo "=", utilizando por ejemplo la función Left). Si hay una
fórmula, sólo añadimos la parte del final, y si no hay una fórmula añadimos primero un signo "="
y luego la parte del final. Esto queda como ejercicio, y si no te sale me escribes y lo
comentamos.

Pues aparte de todo este lío ya lo hemos visto todo. Si ejecutas la rutina Sumar_A_Celda()
comprobarás que primero te pide un valor y luego suma ese valor a la celda activa. Por cierto,
que nadie piense que esta macro es ninguna maravilla, porque lo mismo que hace se puede
hacer más rápido utilizando "Pegado especial..", que además es capaz de restar, multiplicar y
dividir. Ya llegaremos a eso también, pero para ir aprendiendo un poco no nos viene mal.

Ahora vamos a avanzar otro paso: la rutina anterior sumaba un valor a la celda activa, y ahora
vamos a sumar ese valor a todo el rango que seleccione el usuario. Como siempre, aquí va la
rutina completa, luego la explicamos:

Sub Sumar_A_Rango()
Dim i As Double
Dim h As Object

If MsgBox("Esta macro pide al usuario un valor y lo


suma a todas las celdas " & _
Chr(13) & "del rango seleccionado.", vbOK, "Copiar
celda izquierda") _
= vbCancel Then Exit Sub
i = Val(InputBox("Importe a sumar: ", "Sumar a rango seleccionado"))
For Each h In Selection.Cells
h.Value = h.Value + i
Next h
End Sub

Lo primero que hacemos es declarar las variables. La primera variable (i), es de tipo Double, al
igual que en la rutina anterior. La segunda variable (h) la declaramos como una variable de tipo
Object, para que apunte a cualquier tipo de objeto de Excel (una hoja, un rango, una celda,
etc.)

Las dos siguientes líneas son iguales que antes: primero presentamos un pequeño mensaje al
usuario, y luego obtenemos el valor y convertimos la cadena a un valor numérico.

En las tres siguientes líneas está todo lo nuevo. Vamos por pasos: Selection es una propiedad
del objeto Application, o sea que al escribir Selection Excel supone que estamos escribiendo
Application.Selection. Pues bien, la propiedad Selection nos devuelve el rango que está
seleccionado en la hoja activa, es decir, un objeto de tipo Range.

Con Selection obtenemos un objeto de tipo Range que apunta al rango seleccionado de la
hoja activa. Si accedemos a la propiedad Cells de ese objeto Range, obtendremos un
"conjunto" de todas las celdas de ese rango.

¿Que es un conjunto? Un conjunto es un objeto que contiene otros objetos, generalmente del
mismo tipo (la definición la he copiado de la ayuda de Windows). La propiedad Cells de un
objeto Range nos devuelve un conjunto que contiene todas las celdas de ese rango.

Luego viene una instrucción "For". En la entrega anterior vimos una instrucción For, pero un
poco distinta a esta. En ese caso lo que hacíamos era dar a una variable distintos valores,
desde el 1 hasta el 10, y para cada valor de la variable ejecutábamos unas instrucciones.
Análogamente, en esta ocasión vamos a dar a la variable "h" (de tipo Object) unos valores, y
para cada valor de "h" vamos a ejecutar una instrucción.

Para dar los distintos valores a "h" vamos a utilizar la instrucción "For Each", que "repite un
grupo de enunciados para cada elemento de una matriz o de un conjunto". El conjunto que
vamos a utilizar es Selection.Cells, que como sabemos son todas las celdas del rango
seleccionado. Es decir, que con

For Each h In Selection.Cells


h.Value = h.Value + 1
Next h

lo que hacemos es ejecutar una instrucción para cada una de las celdas del conjunto
Selection.Cells. La primera vez que se ejecute la instrucción de dentro del buble, h
representará la primera celda del conjunto de celdas, la segunda vez representará la segunda
celda del conjunto, etc. En este caso lo que hemos hecho ha sido sumar el valor uno a todas
las celdas del rango seleccionado.

La instrucción que va dentro del bucle es la misma que en el ejemplo anterior; tan sólo fíjate
que utilizamos "h" en lugar de ActiveCell.

Vamos a hacer otro pequeño ejemplo del uso de "For Each" y de conjuntos. En esta ocasión
vamos a cambiar el nombre de todas las hojas del libro activo. Para obtener una referencia al
libro activo utilizaremos la propiedad ActiveWorkbook del objeto Application. Para acceder a
todas las hojas de cálculo del libro activo, utilizaremos la propiedad Worksheets de dicho
objeto, ActiveWorkbook. He utilizado la propiedad Worksheets porque esta nos devuelve sólo
las hojas de cálculo (no las hojas de gráficos, módulos, etc.). Si queremos acceder a todas las
hojas (de cualquier tipo) del libro, utilizaremos la propiedad Sheets, que funciona igual que
Worksheets.

Aquí va la rutina de ejemplo:


Sub NombresHojas()
Dim h As Object
Dim i As Integer

i = 15
For Each h In ActiveWorkbook.Worksheets
h.Name = "Hoja " & i
i=i+1
Next h
End Sub

Lo que hace esta rutina es cambiar los nombres de las hojas de cálculo del libro activo,
poniéndoles los nombres "Hoja15", "Hoja16", etc. No es que sea una rutina demasiado útil,
pero como siempre sirve para aprender un poco.

Como siempre, empezamos con la declaración de variables. Luego le damos a la variable "i" el
valor 15, porque nos da la gana, podíamos haberle dado cualquier otro. Luego viene lo que nos
interesa, el "For Each". Para cada hoja de cálculo (Worksheets) del libro activo
(ActiveWorkbook) vamos a ejecutar las dos instrucciones que están dentro del bucle.

Para cambiar el nombre de una hoja utilizamos la propiedad Name. Luego incrementamos el
valor de "i" para dar el nombre a la hoja siguiente. (Si intentamos dar a dos hojas el mismo
nombre Excel nos dará un mensaje de error)

Bueno, otra rutina para jugar un poco con hojas y celdas:

Sub ListaHojas()
Dim h As Object
Dim r As Range

If MsgBox("Esta macro crea en la celda


activa una lista con los nombres de todas" & _
Chr(13) & "las hojas del libro activo.", vbOK,
"Lista Hojas") = vbCancel _
Then Exit Sub
Set r = ActiveCell
For Each h In ActiveWorkbook.Sheets
r.Value = h.Name
r.Offset(0, 1).Value = TypeName(h)
Set r = r.Offset(1, 0)
Next h
End Sub

Lo que hace esta rutina es crear en la hoja de cálculo activa una tabla con los nombres de
todas las hojas del libro. Primero, con "Set r = ActiveCell", hacemos que la variable "r" apunte a
la celda activa.

Luego viene el bucle "For Each / Next", que al igual que en el ejemplo anterior hace que el
código entre estas dos líneas se ejecute una vez para cada hoja del libro. La única diferencia
es que en el ejemplo anterior utilizábamos "ActiveWorkbook.Worksheets" (que pasa por
todas las hojas de "cálculo" del libro) y aquí "ActiveWorkbook.Sheets" (que pasa por todas
las hojas del libro, de todo tipo).
Primero damos a la celda "r" el nombre de la primera hoja del libro. En la siguiente línea,
ponemos en a celda de la derecha de "r" (con el Offset(0,1)) el tipo de hoja de que se trata,
utilizando la función "TypeName(h)": esta función devuelve una cadena de carácteres que
proporciona información sobre la variable "h".

En la siguiente línea, utilizando otra vez Offset, "movemos" la variable "r" para que apunte a la
celda inferior. Y así, vuelta a empezar.

Y para terminar, vamos a aprender a utilizar el método Copy, que se aplica a objetos de Excel
que puedan ser copiados, como por ejemplo un objeto de tipo Range, aunque también a otros
objetos como hojas enteras o gráficos.

Lo que vamos a hacer es copiar en la celda activa el contenido de la celda de su izquierda:

Sub Copiar_CeldaIzquierda()
If MsgBox("Esta macro copia en la celda
activa el contenido de la celda situada" & _
Chr(13) & "a su izquierda.", vbOK, "Copiar celda
izquierda") = vbCancel Then Exit Sub
ActiveCell.Offset(0, -1).Copy ActiveCell
End Sub

La sintaxis de Copy es muy sencilla: se ejecuta el método Copy sobre el rango de "origen", es
decir, el que queremos copiar. En el ejemplo, hacemos "ActiveCell.Offset(0,-1).Copy", ya que
queremos copiar la celda que está a la izquierda de la celda activa.

El parámetro del método Copy indica el rango de "destino" para la copia. En nuestro ejemplo
ponemos "ActiveCell", ya que queremos que lo que hemos copiado se copie en la celda activa.
Si omitimos el parámetro del método Copy la copia se hará en el "Portapapeles", y luego
deberemos utilizar otros métodos como "Paste" o "PasteSpecial" para pegar el contenido del
portapapeles en otra celda.

Hasta aquí llega esta segunda entrega del curso. En este capítulo hemos aprendido a trabajar
con celdas, rangos, libros y hojas, que es una de las partes más útiles de la programación en
Excel, permitiéndonos hacer cualquier operación (mover, copiar, borrar, hacer operaciones
aritméticas, etc) con los datos de una hoja de cálculo.

Excel2.xls
Recuerda que los ejemplos de este capítulo están incluídos en este fichero:
(39kbs)

Capítulo 3. Cuadros de diálogo (Userforms).

Este capítulo va a tratar sobre los cuadros de diálogo, que se utilizan para obtener información
del usuario. Una aclaración respecto a versiones: uno de los cambios más importantes de
Excel 95 a Excel 97 en el apartado de programación es la parte de cuadros de diálogo. La
verdad es que hay muchas diferencias entre ambos y eso hace imposible hablar de las dos
versiones a la vez, por lo que este capítulo está dirigido sólo a Excel 97.

Excel3.xls
Todos los ejemplos de este capítulo están incluídos en este fichero:
(117kbs)

Los cuadros de diálogo en Office 97 son mucho más potentes que en la versión anterior. Se
han añadido muchas opciones, como la posibilidad de definir eventos, utilizar controles ActiveX
además de los incluidos en Excel (si no sabes qué es un control ActiveX no tiene demasiada
importancia, es un tema avanzado que quizá algún día tratemos), etc.

Nuestro primer cuadro de diálogo va a ser muy sencillo: vamos a presentar un cuadro de
diálogo en el que el usuario puede introducir un número, y si pulsa "Aceptar" copiaremos el
número introducido en la celda activa. Si el usuario pulsa "Cancelar" no haremos nada.

Lo primero es ir al editor de Visual Basic, utilizando la opción "Herramientas, Macro, Editor de


Visual Basic", o simplemente pulsando Alt-F11.

En la parte izquierda de la pantalla tendremos el "Explorador de Proyectos" y la ventana de


"Propiedades". Igual que antes, si no puedes ver estas ventanas utiliza el menú "Ver" para
hacer que aparezcan. En el "Explorador de Proyectos" aparecen todos los "proyectos" de VBA:
cada libro que tengamos abierto es un proyecto. Dentro de cada libro aparecen todas las hojas
del libro y también los módulos y cuadros de diálogo que crearemos más adelante.

En la ventana de "Propiedades" aparecen las propiedades del objeto que tengamos


seleccionado en ese momento. Supongo que a estas alturas ya debe estar claro el concepto de
"propiedad" de un objeto. Por ejemplo, vamos a ir a un proyecto de VBA en el "Explorador de
Proyectos". Dentro de él veremos las hojas de cálculo del libro, y vamos a seleccionar una de
ellas. En la ventana de "Propiedades" van a aparecer las propiedades de la hoja seleccionada.
Por ejemplo, la primera propiedad que vemos es la propiedad Name, que ya conocemos.
Podemos utilizar la ventana de "Propiedades" para cambiar las propiedades del objeto
seleccionado.

Ahora para crear nuestro cuadro de diálogo vamos a utilizar la opción "Insertar, Userform"
(Userform es el nombre que da Excel 97 a los cuadros de diálogo).

En este momento vemos en la parte derecha un cuadro de


diálogo vacío, y por otro lado veremos el "Cuadro de
herramientas", en el que están todos los controles que
podemos poner en el cuadro de diálogo. Si no aparece el
Cuadro de Herramientas utiliza la opción "Ver, Cuadro de
herramientas" para que aparezca.

Los controles del "Cuadro de herramientas" son los típicos de


cualquier cuadro de diálogo que podemos ver en cualquier
aplicación de Windows:

 Etiqueta
: para mostrar un texto en el
cuadro de diálogo. El usuario
no puede editarlo.
 C u a d r o d e t
introduzca un texto.
 C u a d r
para que el usuario seleccione
una opción entre varias.
 C u a d r o d e l i
seleccione una opción de entre
las que le presentamos.
 C a s i l l a d
 B o t ó n d e o p
seleccione una opción entre
varias.
 B o t ó n d e c
como los típicos de "Aceptar" y
"Cancelar"
 Marco: para agrupar varios controles. Su uso es básicamente por razones estéticas.
Como puedes ver en el diálogo de ejemplo un marco puede tener distintas apariencias.

Primero vamos a ver las propiedades del objeto UserForm. Para ello seleccionamos el
Userform de la parte derecha simplemente pulsándolo con el ratón. En la parte inferior
izquierda, en la ventana de Propiedades, tenemos la lista de propiedades del objeto UserForm.
Utilizando esta ventana podemos cambiar el valor de cualquier propiedad del Userform.
Algunas de las propiedades más importantes son:

 Name: el nombre con el que vamos a identificar el UserForm. Tiene que ser único y no
puede tener espacios ni otros caracteres raros. Yo suelo ponerles un nombre que
empiece por "uf" (por ejemplo, ufDatosPersonales), porque así cuando en el código VB
haga una referencia a este objeto sé que se trata de un objeto UserForm.
 Caption: es el título que el usuario verá en el cuadro de diálogo. Se puede poner
cualquier texto, incluyendo espacios.
 BackColor: el color de fondo del cuadro de diálogo. Por defecto es el color gris que
suelen tener todos los cuadros de diálogo en Windows.
 ForeColor: el color de primer plano, es decir, del texto que aparezca en el cuadro de
diálogo.
 Font: el tipo de letra por defecto para el cuadro de diálogo. Este es el tipo de letra que
tendrán todos los controles que insertemos en el cuadro de diálogo, pero si luego
queremos cambiarlo para cualquier control puede hacerse.
 StartupPosition: la posición en la que aparecerá el cuadro de diálogo. Si le damos el
valor "CenterScreen" el diálogo saldrá en el centro de la pantalla.
 SpecialEffect: para cambiar un poco los bordes del cuadro de diálogo.
 Picture, PictureAlignment, PictureSizeMode, PictureTiling: se utilizan para poner un
dibujo como fondo del cuadro de diálogo.

Hay más propiedades, pero su uso es bastante sencillo, y consultando la ayuda encontrarás la
descripción de todas las propiedades.

Vamos con nuestro diálogo: lo primero es cambiarle el nombre; vamos a la ventana de


Propiedades y en la propiedad Name, escribimos por ejemplo "ufPrimero". Luego en la
propiedad "Caption" escribiremos "Mi primer UserForm". Las demás propiedades las dejamos
como están, aunque si quieres cambiar alguna que afecte a la presentación del diálogo (color
de fondo, efectos especiales, etc) puedes hacerlo tranquilamente.

En cualquier momento puedes probar tu cuadro de diálogo seleccionándolo con el ratón y


utilizando la opción "Ejecutar, Ejecutar Sub/Userform" (o más rápido pulsando F5 o el botón de
ejecutar ). Para cerrar el diálogo tendrás que utilizar la "X" que aparece en la parte superior
derecha, porque todavía no hemos añadido ningún botón para cerrar el diálogo.

Como hemos dicho antes, en nuestro cuadro de diálogo queremos que el usuario escriba un
número. Para que pueda hacerlo, tendremos que poner un cuadro de texto en el diálogo. Para
ello pulsamos en el UserForm para que aparezca el "Cuadro de Herramientas" y en éste
pulsamos sobre el control "Cuadro de Texto" . Una vez seleccionado el "Cuadro de Texto"
pulsamos en cualquier parte del UserForm y veremos que aparece un cuadro de edición.
Podemos utilizar el ratón para moverlo y cambiarle el tamaño.

Pulsando con el ratón, seleccionaremos el cuadro de edición, y como de costumbre veremos


que en la ventana de "Propiedades" aparecen todas las propiedades del objeto " Cuadro de
Texto" (TextBox en inglés), entre las que se encuentran:

 Name: el nombre del objeto. Como antes, no puede incluir espacios ni caracteres
especiales. Yo suelo utilizar nombres que empiecen por "tb", para identificar estos
objetos como un TextBox, pero se puede utilizar cualquier nombre.
 Text: es el texto que va dentro del cuadro de edición, es decir, el que ha escrito el
usuario.
 TextAlign: alineación del texto dentro del cuadro de diálogo. Normalmente si lo que
queremos es que el usuario introduzca una cadena de texto se suele alinear a la
izquierda, y si queremos que introduzca números se suele alinear a la derecha.
 MultiLine: los valores posibles son verdadero y falso, indicando si queremos que el
control permita al usuario escribir más de una línea o no.

Las propiedas sobre la apariencia del control son parecidas a las que hemos visto antes
(BackColor, ForeColor, SpecialEffects). El resto de propiedades se pueden consultar en la
ayuda. Aunque parezca que nos estamos dejando muchas cosas, una vez que empezamos a
tener claras las cosas el utilizar propiedades que no hemos usado nunca es muy sencillo. O
sea, que por ahora nos centramos en lo básico.

Bueno, ahora vamos a nuestro cuadro de diálogo. Seleccionamos nuestro cuadro de edición, lo
colocamos en una posición que nos guste, y vamos a las propiedades. Primero la propiedad
Name, que en este caso vamos a dejar tal como está, TextBox1. No suele ser aconsejable
dejar estos nombres, porque si tienes varios cuadros de edición en un diálogo al final no sabes
a cuál te estás refiriendo, pero como en este caso sólo vamos a tener un cuadro de edición no
nos importa demasiado. Ahora vamos a la propiedad "TextAlign" y vamos a seleccionar la
opción "fmTextAlignRight" para alinear el texto a la derecha, ya que lo que queremos es que le
usuario introduzca un número. Por ahora no vamos a hacer nada más con este control.

Si ejecutamos el cuadro de diálogo veremos que podemos introducir un valor en el cuadro de


edición que hemos creado, pero aparte de eso no podemos hacer mucho más.

Lo siguiente que vamos a hacer es poner un texto descriptivo para el cuadro de edición. Para
ello seleccionamos del "Cuadro de herramientas" el control "Etiqueta" , y pulsamos en el
UserForm para crear un control del tipo etiqueta. Utilizando el ratón le podemos cambiar el
tamaño y moverlo, para ponerlo a la izquierda del control de edición que hemos creado antes.

En la ventana de propiedades de nuestro nuevo control (recuerda que tienes que seleccionarlo
para poder ver sus propiedades en la ventana de propiedades) veremos como siempre la lista
de propiedades. La propiedad Name la vamos a dejar como está, ya que no vamos a referirnos
a este control en el código, y no nos interesa su nombre: normalmente los controles de etiqueta
se utilizan sólo para poner un texto en el diálogo, y no se suelen referenciar desde el código
VB. La propiedad que nos interesa es "Caption", en la que escribiremos el texto que queremos
que aparezca en el cuadro de diálogo, por ejemplo "Escribe un número:".

Si colocamos bien los dos controles (utilizando por ejemplo la opción "Formato, Alinear, Medio),
ya tenemos un diálogo algo más completo.

Lo típico en estos cuadros de diálogo es que en la parte inferior haya dos botones, uno para
"Aceptar" y el otro para "Cancelar". Vamos a colocar estos dos botones, empezando por el de
"Cancelar" que es un poco más fácil.

Como antes, vamos al "Cuadro de Herramientas" y seleccionamos el control "Botón de


comando" . Pulsamos sobre el UserForm y hemos creado nuestro primer botón, que
podemos mover y cambiar de tamaño utilizando el ratón. Una vez seleccionado nuestro nuevo
control podremos ver sus propiedades en la ventana de "Propiedades":

 Name: el nombre del control. Vamos a darle el nombre "cbCancel" (cb viene de
CommandButton).
 Caption: el texto del botón. Lógicamente, vamos a poner "Cancelar".
 Cancel: puede ser verdadero o falso. Sólo puede haber un control en el cuadro de
diálogo con la propiedad Cancel establecida como verdadero. Si le damos a Cancel el
valor verdadero, cuando se esté ejecutando el cuadro de diálogo si el usuario pulsa
"Escape" será como si hubiese pulsado con el ratón sobre este botón. En este caso
nos interesa que ocurra, o sea que vamos a darle el valor verdadero.
 Default: verdadero o falso, indica si el botón es el botón por defecto del cuadro de
diálogo. Si el usuario pulsa "Enter" cuando está viendo el diálogo será como si pulsa
con el ratón sobre el botón que tenga la propiedad Default (sólo puede haber uno). En
este caso vamos a dejar la propiedad en False porque queremos que el botón por
defecto sea el de "Aceptar", que crearemos más adelante.

Por ahora dejamos el resto de propiedades de los botones. Bueno, hasta ahora le hemos dado
a nuestro botón el nombre "cbCancel", le hemos puesto el texto "Cancelar" y hemos dado el
valor "Verdadero" a la propiedad "Cancel".

Si ejecutamos el cuadro de diálogo veremos que tenemos un botón muy bonito, pero que no
hace absolutamente nada. Para que haga algo tenemos que meternos con un concepto muy
importante de la programación orientada a objetos, los Eventos.

A estas alturas ya deberían estar claros los conceptos de Objeto, Propiedad y Método. En
Excel, un objeto es una variable que representa cualquier elemento de Excel, como un rango,
un libro, una celda, o un UserForm. Todos los objetos tienen propiedades (como Cell.Value,
Workbook.Name o UserForm.BackColor), y métodos (como Range.ClearContents o
UserForm.Show).

Además de propiedades y métodos los objetos tienen también "eventos". He mirado en la


ayuda y no he encontrado una definición de evento, y tampoco me atrevo a dar una, pero voy a
ver si puedo explicar el concepto. Imaginemos que tenemos un control, como por ejemplo el
control de edición que hemos colocado en nuestro diálogo. Cuando sucede un "evento" de los
que este control "entiende", Excel llamará a una función con un nombre especial, siempre que
hayamos definido esa función (si no la hemos definido, no pasa nada, el "evento" se ignora).
Un ejemplo de evento es que el usuario mueva el ratón por encima de nuestro control. Cada
vez que el ratón se mueve se produce un evento "MouseMove", y entonces Excel llamará a la
rutina TextBox1_MouseMove( ... ), en caso de que hayamos definido esa rutina, lo que
haremos en caso de que nos interese hacer algo cada vez que el ratón pase por encima de
nuestro control. El nombre de la rutina es especial: primero va el nombre del control (recuerda
que lo habíamos dejado tal como nos lo había puesto Excel, TextBox1), luego un carácter de
subrayado ("_"), y luego el nombre del evento.

Otro ejemplo de evento: queremos que el usuario introduzca un número en el cuadro de


edición, pero si lo probamos veremos que se puede escribir cualquier carácter que no sea un
número. Cada vez que el usuario pulsa una tecla se produce el evento "KeyPress", que
podemos utilizar para ignorar la tecla pulsada por el usuario si éste pulsa una tecla que no es
un número. Más adelante veremos cómo se hace.

Bueno, no sé si ha quedado muy claro, pero creo que con un poco de práctica espero que sí.
Dominar los conceptos de objeto, propiedad, método y evento es muy importante, pero no
sólo para programación en Visual Basic for Applications, sino que estos conceptos son básicos
en todos los lenguajes de programación orientada a objetos (Visual Basic, Borland Delphi,
Java, etc.). De hecho, si dominas esos conceptos con cuatro cosas más podrás programar en
cualquiera de esos otros lenguajes.

Bueno, sigamos con los eventos. Vamos a centrarnos ahora en nuestro botón de " Cancelar". El
evento más normal para un botón es que el usuario lo pulse con el ratón (o con el teclado).
Cuando esto ocurra, se generará un evento Click, y llamará a la rutina cbCancelar_Click().
(cbCancelar es el nombre que habíamos dado al control, y Click es el nombre del evento). Lo
más fácil para crear un evento es seleccionar un control y luego pulsar el botón derecho y
seleccionar la opción "Ver Código". Veremos una página de código VB en la que Excel habrá
escrito la cabecera de un evento para dicho control (la verdad es que no sé cuál de los eventos
coge, supongo que cogerá el más utilizado). En nuestro caso, si pulsamos sobre el botón
"Cancelar" con el botón derecho y luego "Ver código" en la página de código veremos lo
siguiente:
Private Sub cbCancelar_Click()

End Sub

Excel nos ha creado la cabecera para la función que queremos crear. En este caso la función
no tiene ningún parámetro, pero en otros eventos la función tiene una lista de parámetros, y
Excel también nos los pone en la cabecera.

Otra cosa, la página de código que estamos viendo es como un módulo normal en el que
escribimos nuestro código, con la particularidad de que no sale en la lista de módulos en el
"Explorador de Proyectos", ya que es un módulo asociado al Userform.

Para crear una función para cualquier otro evento tenemos en la parte superior de la ventana
de código dos "persianas". En la persiana de la izquierda tenemos el objeto sobre el que
queremos definir una función para un evento. En la persiana de la derecha tenemos todos los
eventos que pueden ocurrir para el control seleccionado en la persiana de la izquierda. Si
queremos definir la función para otro evento lo único que tenemos que hacer es seleccionar
otro evento en esta persiana, y Excel insertará en el código la cabecera para la función que se
va a ejecutar cuando se de ese evento.

Bueno, lo que queremos hacer cuando el usuario pulsa el botón de Cancelar es simplemente
cerrar el cuadro de diálogo. Tendremos que cerrar el cuadro de diálogo cuando Excel nos avise
de que ha ocurrido un evento Click, es decir, dentro de la función cbCancelar_Click().

La instrucción que se utiliza para cerrar el UserForm es "Unload", que sirve para quitar un
objeto de la memoria. La instrucción Unload requiere un parámetro, que utilizaremos para
indicarle cuál es el objeto. En nuestro caso utilizaremos la palabra clave "Me", que apunta al
objeto en el que se está ejecutando el código, es decir, nuestro UserForm.

Nuestro "manejador de eventos" para el evento Click del botón cbCancel quedaría así:

Private Sub cbCancelar_Click()


Unload Me
End Sub

Cuando el usuario pulse el botón de


Cancelar se generará un evento Click, y
Excel llamará a nuestra función, que
utilizará la instrucción Unload para cerrar
el diálogo. Fíjate en que si pulsas la tecla
"Escape" el diálogo se cierra igual que si
hubieses pulsado con el ratón sobre el
botón: esto es debido a que hemos dado
el valor verdadero a la propiedad
"Cancel" del botón Cancelar.

Después de probar el cuadro de diálogo


y comprobar que nuestro botón de
Cancelar funciona perfectamente nos
queda añadir el botón de Aceptar. Para
crear el botón seleccionamos en el "Cuadro de Herramientas" el "Botón de comando" y lo
colocamos en el UserForm. Luego le ponemos su nombre (cbAceptar por ejemplo), cambiamos
su texto (ponemos Aceptar) y le damos el valor "Verdadero" a la propiedad Default para que si
el usuario pulsa Enter sea como si hubiese pulsado con el ratón sobre el botón.

Ahora nos queda todo el tema de los eventos. El procedimiento es el mismo que con el botón
de Cancelar, con la única diferencia de que antes de cerrar el cuadro de diálogo (con la
instrucción Unload) deberemos hacer lo que queremos que nuestro diálogo haga, es decir,
copiar el contenido del cuadro de edición TextBox1. La función sería la siguiente:

Private Sub cbAceptar_Click()


ActiveCell.Value = TextBox1.Value
Unload Me
End Sub

Esta función es prácticamente igual que la que hemos escrito para el botón Cancelar, con la
excepción de que antes de cerrar el cuadro de diálogo escribimos otra línea, que se encarga de
copiar en la celda activa (ActiveCell) el contenido del cuadro de edición. Fíjate como
accedemos al contenido del cuadro de edición, a través del nombre del control (TextBox1) y su
propiedad Value, que nos devuelve el valor numérico de lo que se ha introducido en el control
(si hay caracteres no numéricos la propiedad Value nos devolverá el valor 0).

Si probamos ahora el cuadro de diálogo veremos que ya funciona perfectamente, ya hemos


conseguido que nuestro primer UserForm funcione. El único problema que tiene es que en el
cuadro de edición el usuario puede escribir cualquier caracter además de números. Para evitar
esto ya he adelantado antes que hay que utilizar el evento KeyPress del cuadro de edición,
pero eso lo veremos más adelante.

- El segundo cuadro de diálogo.

Vamos a hacer otro cuadro de


diálogo: tenemos en una hoja de
cálculo una celda con el nombre de
una persona y otra celda con el
apellido. Queremos crear un
Userform que permita al usuario
editar ese nombre y apellido, y si
pulsa Aceptar en el cuadro de
diálogo los valores de esas celdas
deben actualizarse con lo introducido
por el usuario.

Si te fijas en el fichero de ejemplo


verás las dos celdas que incluyen el
nombre y el apellido. A estas celdas les he dado el nombre "rngNombre" y "rngApellido",
respectivamente. Cuando hagamos referencias a celdas de hojas de cálculo en nuestro código
es muy conveniente utilizar nombres de rangos en lugar de referencias absolutas (como por
ejemplo C12), ya que si utilizamos nombres de rangos y movemos esas celdas no tenemos que
hacer ningún cambio en el código, lo que deberemos hacer si utilizamos referencias absolutas.

Repetimos los pasos anteriores:

 Crear el UserForm, utilizando "Insertar, Userform" en el editor de Visual Basic. Vamos


a dar al UserForm el nombre "ufDatosPersonales"
 Insertamos dos cuadros de texto, uno para el nombre y otro para el apellido, a los que
daremos los nombres tbNombre y tbApellido.
 Insertamos dos etiquetas que colocaremos a la izquierda de cada uno de los dos
cuadros de texto.
 Insertamos un botón para Cancelar el cuadro de diálogo, al que cambiaremos el
nombre a "cbCancelar", el texto a "Cancelar" (utilizando la propiedad Caption") y
daremos a la propiedad Cancel el valor Verdadero.
 Insertamos un botón para Aceptar, cambiándole el nombre a "cbAceptar", el texto a
"Aceptar" y damos a la propiedad Default el valor Verdadero.
Vamos con los eventos: para el botón Cancelar la función que debemos escribir es
exactamente igual que en el caso anterior:

Private Sub cbCancelar_Click()


Unload Me
End Sub

Lo único que hace es cerrar el cuadro de diálogo al producirse el evento "Click" del botón
Cancelar.

La función para el botón Aceptar también es muy similar a la anterior:

Private Sub cbAceptar_Click()


Range("rngNombre").Value = tbNombre.Text
Range("RngApellido").Value = tbApellido.Text
Unload Me
End Sub

Esta función se ejecuta también cuando se produce el evento Click del botón llamado
cbAceptar. Antes de cerrar el cuadro de diálogo debemos guardar en las celdas de la hoja de
cálculo los valores de los cuadros de texto. Para ello utilizamos un objeto Range (a estas
alturas somos unos autenticos expertos en el objeto Range), y le asignamos a su propiedad
Value el valor de la propiedad Text del objeto TextBox. Esta es la única novedad, la utilización
de una propiedad de los objetos TextBox (tbNombre y tbApellido).

Si ejecutamos ahora el cuadro de diálogo veremos que funciona perfectamente: si cambiamos


los nombres en el UserForm y pulsamos Aceptar veremos que las celdas de la hoja de cálculo
han cambiado y ahora contienen los nuevos nombres.

Pero hay una pequeña opción que se nos ha escapado: si vamos directamente a la hoja de
cálculo, cambiamos los nombres en sus celdas, y ejecutamos el Userform, veremos que los
controles de edición no tienen ahora los nombres actualizados, ya que no recogen los cambios
que hemos hecho nosotros directamente en la hoja de cálculo.

Para eso vamos a utilizar también los eventos. En esta ocasión vamos a utilizar un evento del
Userform (sí, los UserForms también tienen eventos). Se trata del evento Initialize, que se
produce justo antes del que el UserForm aparezca en la pantalla. Ese es el momento para
hacer cualquier cambio en el Userform, como poner un texto en un control, que es lo que
queremos hacer.

Por lo tanto, seleccionamos el UserForm, pulsamos con el botón derecho y luego la opción "Ver
código" (también se puede hacer doble-click sobre el Userform) y en la persiana de la derecha
seleccionaremos el evento Initialize. Excel creará en ese momento la cabecera de nuestra
función:

Private Sub UserForm_Initialize()

End Sub

Ahora tenemos que escribir el código que queremos que se ejecute antes de que se muestre el
Userform. Lo que queremos hacer es poner en los dos cuadros de texto (el de nombre y el de
apellido) el contenido de las celdas que tienen esos datos. Para ello utilizaremos el siguiente
código:

Private Sub UserForm_Initialize()


tbNombre.Text = Range("rngNombre").Value
tbApellido.Text = Range("rngApellido").Value
End Sub

No creo que tenga demasiada dificultad. Es lo mismo que hemos escrito para el botón Aceptar
pero al revés, es decir, damos a los cuadros de texto del Userform el valor que tienen las
celdas de la hoja de cálculo.

Pues ya está, ahora sí que el cuadro de diálogo funciona perfectamente, tanto si hacemos los
cambios en el UserForm (se actualizará la hoja de cálculo si pulsamos Aceptar) como si
hacemos los cambios en la hoja de cálculo (se actualizará el UserForm antes de aparecer en
pantalla, porque se habrá ocurrido un evento Initialize).

Bueno, hasta aquí llega esta tercera entrega. Todavía nos queda mucho por ver sobre los
cuadros de diálogo (o UserForms, o formularios, como prefieras), pero eso lo dejamos para la
próxima entrega. Hasta entonces te toca practicar, y sobre todo recuerda que lo más
importante es tener claros los conceptos importantes: objetos, propiedades, métodos y
eventos.

Excel3.xls
Recuerda que los ejemplos de este capítulo están incluídos en este fichero:
(117kbs)

Capítulo 4. Cuadros de diálogo (Userforms). Segunda parte.

Seguimos con los UserForms y los controles. En esta entrega vamos a ampliar el diálogo sobre
datos personales, añadiéndole más opciones, y vamos a crear dos nuevos userforms: uno para
convertir de pesetas a euros y viceversa, y otro para hacer operaciones (sumar, restar...) sobre
un rango seleccionado (algo parecido a lo que hicimos antes, pero más completo).

Excel4.xls
Todos los ejemplos de este capítulo están incluídos en este fichero:
(116kbs)

Primero vamos a volver a hacer un diálogo de "Datos Personales" como el de la entrega


anterior, pero añadiendo algunas cosas. Partimos del userform de la entrega anterior, que tenía
un cuadro de edición para el nombre y otro para el apellido, y los dos botones clásicos (Aceptar
y Cancelar).

Habíamos escrito el código necesario para que al abrirse el diálogo (evento Initialize del
Userform) los cuadros de edición se llenen con el texto de las celdas de la hoja de cálculo, y
también para que cuando el usuario pulse Aceptar (evento Click del botón) se copie el texto de
los cuadros de edición a la hoja de cálculo. Para hacer estos traspasos entre la hoja de cálculo
y el Userform habíamos escrito un par de líneas de código en los eventos indicados, pero
vamos a ver que hay otro método para hacerlo:

Todos los controles tienen la propiedad "ControlSource", que se utiliza para decirle al control
cuál es la "fuente" de su información, que será una celda o un rango de una hoja de cálculo.
Por ejemplo, en el cuadro de edición del Nombre podemos poner como ControlSource la celda
de la hoja de cálculo en la que está ese dato. Como siempre, no vamos a utilizar referencias
absolutas a celdas y rangos (p.ej. Hoja1!A5), sino que vamos a utilizar nombres de rango. Por
ejemplo, vamos a la hoja de cálculo y damos a la celda "fuente" el nombre "rngNombre" (rng
porque es un rango de una hoja de cálculo). Luego vamos al editor VBE, seleccionamos el
control de edición Nombre y en su propiedad ControlSource escribimos el nombre del rango
que queremos que sea su "fuente", en este caso "rngNombre".

Ahora hacemos lo mismpo para el apellido: primero damos el nombre "rngApellido" a la celda
de la hoja de cálculo y luego escribimos rngApellido en la propiedad ControlSource del control
de edición de Apellido.

Ahora tenemos que borrar el código que habíamos escrito para pasar la
información de hoja de cálculo al Userform y viceversa. Mejor que
borrarlo, lo que haremos será "comentarlo", utilizando una comilla simple
', que indica a Excel que todo lo que escribamos en esa línea detrás de la
comilla son cosas nuestras y que las ignore (el texto "comentado"
aparecerá en otro color, normalmente en verde). Aprovechando que
explico lo de los comentarios, nunca está de más recordar la importancia
que tiene añadir al código todos los comentarios que sean necesarios.
Cuando estás escribiendo una rutina sabes perfectamente cómo funciona
y qué es lo que hace, y todos pensamos que los comentarios son innecesarios, pero cuando
tras algunas semanas tienes que volver a ver la rutina te encuentras con un montón de líneas
que no sabes para qué sirven ni cómo lo hacen, y si no las has comentado tienes que "bucear"
en ellas para averiguarlo.

A lo que íbamos, estábamos borrando el código de los eventos Initialize del Userform y Click
del botón Aceptar. Vamos al editor VBE, hacemos doble-click sobre el Userform y nos aparece
la rutina Userform_Initialize(). Ponemos una comilla delante de las dos líneas que se
encargan de copiar los datos de la hoja de cálculo al userform, y veremos que dichas líneas
cambian de color, indicándonos que para Excel son comentarios y los va a ignorar. Ahora
volvemos al Userform y hacemos doble-click en el botón Aceptar, y nos aparece la rutina
btnAceptar_Click(). Volvemos a poner las comillas en las dos líneas de código que queremos
quitar y ya está.

Si probamos ahora el diálogo, veremos que la propieda ControlSource funciona, y que antes de
mostrar el diálogo "lee" el contenido de la hoja de cálculo y lo pone en el Userform, y cuando
pulsamos Aceptar copia el contenido de los controles del Userform en la hoja de cálculo.

Sin embargo he detectado un problema con el uso de ControlSource. Si hacemos algún cambio
en el Userform y luego pulsamos el botón de "Cancelar", los cambios que hemos hecho en los
datos se actualizan en la hoja de cálculo, cuando no deberían actualizarse porque hemos
pulsado Cancelar. En cambio, si hacemos algún cambio y pulsamos la tecla Escape los
cambios no se actualizan en la hoja de cálculo. Es un poco raro. Creo que "se me escapa"
algo, si alguien descubre por qué ocurre esto que me avise.

Bueno, ahora vamos a añadir un control nuevo, que Excel llama "cuadro combinado" (el
nombre en inglés es ComboBox), que es la típica persiana que estamos hartos de ver en
cualquier diálogo, y permite al usuario escoger una opción entre varias que le presentamos. En
este caso vamos a mostrar una persiana para el "Estado Civil", y las opciones que vamos a
presentar son "soltero, casado, viudo y divorciado".

Las propiedades más importantes de un ComboBox son:

 List: un conjunto de cadenas de caracteres (strings) que representan a todos los


elementos de la lista. Para acceder a un elemento en concreto utilizamos
MiComboBox.List( 3 ), que nos devolvería el cuarto elemento de la lista, ya que el
primero tiene el número 0.

 ListCount: el número de elementos que hay en la lista. Si utilizamos MiComboBox.List(


MiComboBox.ListCount-1 ) obtendremos el último elemento de la lista.
 ListIndex: el número del elemento seleccionado actualmente por el usuario. Para
obtener el texto del elemento seleccionado utilizaríamos
MiComboBox.List( MiComboBox.ListIndex ). Si hemos definido el control como
"multiselección" (es decir, que el usuario pueda escoger más de un elemento), esta
propiedad no se puede usar, pero por ahora no nos vamos a meter en esto.

 Rowsource: es el rango del que queremos que el ComboBox lea los elementos.
Podemos utilizar esta propiedad, o bien introducir nosotros mismos mediante código
los elementos (utilizando el método AddItem).

 ControlSource: la celda en la que el ComboBox lee y escribe el elemento


seleccionado. Igual que con RowSource, podemos utilizar esta propiedad para que el
ComboBox nos escriba en una celda el elemento seleccionado o podemos utilizar
código para obtener el elemento seleccionado (utilizando ListIndex).

 Style: identifica el tipo de ComboBox que queremos. Tiene dos valores posibles:
o fmStyleDropDownCombo: el usuario puede escoger uno de los valores de la
lista o escribir otro distinto.
o fmStyleDropDownList: el usuario sólo puede escoger uno de los valores de la
lista.

 ControlTipText: esta propiedad se aplica a todos los controles, pero como todavía no
la he explicado, la pongo aquí. Esta propiedad sirve para mostrar al usuario un
pequeño texto de ayuda sobre el control cuando ponga el ratón sobre el mismo, el ya
clásico cuadrito amarillo.

Una vez vistas las propiedades, vamos con los métodos del objeto ComboBox:

 AddItem: sirve para añadir un elemento a la lista. Su sintaxis es


MiComboBox.AddItem( 'Mi texto', 3 ). El primer parámetro es el texto del elemento, y el
segundo parámetro (que es opcional), es la posición dentro de la lista que queremos
para el nuevo elemento. Si no utilizamos el segundo parámetro, nuestro nuevo
elemento se añadirá al final de la lista.

 RemoveItem: para borrar un elemento. Su sintaxis es MiComboBox.RemoveItem( 3 ),


para borrar el elemento número 3.

 Clear: borra todos los elementos de la lista.

Como siempre, hay muchos más métodos y propiedades, que están bastante bien explicados
en la ayuda de Excel.

Vamos a colocar nuestro ComboBox en el Userform, y una vez colocado vamos a las
propiedades. Primero vamos a establecer la propiedad Style como fmStyleDropDownList, para
que el usuario sólo pueda escoger uno de los valores que le presentamos (es decir, que no le
dejamos que se invente un nuevo estado civil). Ahora vamos a la hoja de cálculo y escribimos
en una celda cualquiera "Soltero", debajo "Casado", debajo "Divorciado" y debajo "Viudo".
Ahora vamos a dar un nombre a este rango, seleccionando las cuatro celdas y escribiendo en
el "Cuadro de Nombres" (en la parte superior izquierda) el nombre "rngEstadoCivil". Ya que
estamos vamos a seleccionar cualquier otra celda para que el ComboBox almacene el
elemento seleccionado por el usuario, y le damos a esta celda el nombre "rngValorEstadoCivil".

Ahora vamos otra vez al editor de Visual Basic (VBE), seleccionamos nuestro ComboBox, y en
la propiedad RowSource escribimos "rngEstadoCivil". En la propiedad ControlSource
escribimos "rngValorEstadoCivil".
Como propina, vamos a poner en la propiedad ControlTipText el texto "Selecciona tu estado
civil", que es lo que el usuario verá en un cuadrito amarillo cuando ponga el ratón sobre el
ComboBox. Recuerda que esta propiedad la tienen todos los controles.

Ya tenemos nuestro ComboBox, y si lo probamos veremos que funciona perfectamente.


Recuerda que el ComboBox coge los valores del rango establecido en RowSource, y almacena
el valor seleccionado por el usuario en la celda establecida en ControlSource.

Como ejercicio podemos hacer lo siguiente: borramos las propiedades


ControlSource y RowSource, y hacemos que el control funcione igual
pero encargándonos nosotros mismos de poner los valores en la lista y
luego identificar la selección del usuario y poner su valor en la celda que
queremos. Para ello tendremos que utilizar las propiedades List y
ListIndex, y los métodos Clear y AddItem, poniendo el código en los
eventos Userform_Initialize() y btnAceptar_Click().

Ahora que ya dominamos el ComboBox, una buena noticia: el control


ListBox ("Cuadro de Lista" según la traducción de Excel) funciona prácticamente igual. El
ComboBox es el control en el que sólo se ve una línea y pulsando un botón sale una "persiana"
con las distintas opciones, y en cambio en el control ListBox se ve siempre la lista de opciones,
no hay persiana. Aparte de esta diferencia "visual", los dos tipos de controles son
prácticamente iguales.

Vamos a por otro control, el SpinButton (Botón de número). Este botón se utiliza normalmente
combinado con un Cuadro de edición: si pulsamos el SpinButton hacia arriba aumentamos el
valor del cuadro de edición, y viceversa.

Las propiedades más importantes del SpinButton son:

 Value: el valor del SpinButton, un número.


 Min: el valor mínimo que puede tener el SpinButton.
 Max: el máximo.
 SmallChange: el incremento/decremento que sufrirá la variable Value cada vez que el
usuario pulse el SpinButton. Normalmente es 1, pero lo podemos cambiar.

Vamos a utilizar el control SpinButton combinado con un cuadro de edición que vamos a
utilizar para almacenar la edad. Primero ponemos un cuadro de edición, que llamaremos
"editEdad" (ya sabes, cambiando la propiedad Name). En una hoja de cálculo daremos el
nombre "rngEdad" a una celda, y utilizaremos esta celda para la propiedad ControlSource de
nuestro control "editEdad".

Ahora colocamos un control SpinButton. Normalmente se suelen colocar a la derecha del


cuadro de edición al que van asociados. En el cuadro de propiedades vamos a poner a Min el
valor 0 (edad mínima) y a Max el valor 150 (edad máxima). El nombre del control lo dejamos
como está (SpinButton1).

Ahora tenemos que jugar un poco con los eventos: cada vez que el usuario pulsa el SpinButton
se produce el evento Change. Cada vez que se produzca este evento queremos cambiar el
valor del cuadro de edición "editEdad". Hacemos doble-click en el SpinButton y aparece la
ventana de código, en la que escribiremos:

Private Sub SpinButton1_Change()


editEdad.Text = SpinButton1.Value
End Sub

Bastante sencillo, ¿no? Simplemente damos a la propiedad Text del objeto "editEdad" el valor
del SpinButton.
Ahora tenemos que hacer lo mismo pero "al revés". Si el usuario va directamente al cuadro de
edición y escribe una edad, queremos que el valor del SpinButton se actualice, ya que tanto el
cuadro de edición como el SpinButton tienen que tener el mismo valor. Para ello usamos el
evento Change del objeto editEdad. Hacemos doble-click sobre él y en la ventana de código
escribimos:

Private Sub editEdad_Change()


SpinButton1.Value = editEdad.Value
End Sub

Prácticamente igual que antes. El único cambio es que utilizamos la propiedad Value de
editEdad en lugar de la propiedad Text, porque queremos el valor numérico, y no la cadena de
caracteres. Si en el control de edición escribes alguna letra en lugar de un número verás que el
Userform se detiene mostrándote un mensaje de error porque no puede calcular la propiedad
Value de editEdad. En una aplicación "de verdad" deberíamos escribir algo de código para
evitar estos errores, pero todavía no hemos visto el control de errores (ya llegaremos).

Todavía nos queda un pequeño detalle respecto al SpinButton. Cuando el Userform se carga
por primera vez, el control editEdad lee de la hoja de cálculo la edad (porque se lo hemos dicho
en la propiedad ControlSource), pero el control SpinButton no está actualizado, tenemos que
darle el mismo valor que tiene el control editEdad. Para ello usaremos el evento Initialize el
Userform, que ya conocemos de sobra:

Private Sub UserForm_Initialize()


SpinButton1.Value = editEdad.Value
End Sub

El código es el mismo que el utilizado en el evento editEdad_Change(). Si probamos ahora el


diálogo veremos que la combinación editEdad + SpinButton1 funciona perfectamente (aparte
de la detección de errores, que veremos más adelante).

Ahora vamos con otros tipos de controles: las casillas de verificación (CheckBoxes en inglés),
y los botones de opción (OptionButtons). Para utilizarlos vamos a suponer que queremos que
el usuario nos indique si utiliza o no una hoja de cálculo, y en caso de que sí la utilice nos diga
cuál es su preferida.

Lo primero es preguntar si utiliza una hoja de cálculo, y para ello vamos a utilizar una casilla de
verificación, que puede tener el valor verdadero o falso. Como siempre colocamos el control
sobre el userform y le damos el nombre "cboxUtilizaHoja". En la propiedad ControlSource
vamos a escribir "rngUtilizarHoja", que es el nombre que hemos dado a un rango de una hoja
de cálculo (en el fichero de ejemplo es la celda C18 de la Hoja1). Y en la propiedad Caption
escribimos el texto del control, algo así como "Utiliza hoja de cálculo". También podemos
escribir algo en la propiedad ControlTipText.

Además de todas esas propiedades que ya conocemos las propiedades importantes de un


control de verificación o CheckBox son:

 Value: el valor del control. Puede ser verdadero o falso.

 TripleState: puede ser verdadero o falso (esto último por defecto). Si le damos el valor
verdadero el control tiene tres estados: verdadero, falso y nada (cuando se pone gris).
En algunas ocasiones puede ser útil pero normalmente lo dejaremos como falso.

Ahora vamos a ver cuál es la hoja de cálculo preferida del usuario. Para ello vamos a utilizar
unos botones de opción, para darle la opción de elegir entre Excel, Lotus 1-2-3 u otra hoja de
cálculo.
Lo primero que tenemos que hacer es colocar un control marco (Frame en inglés). Estos
controles sólo sirven para agrupar controles y para mejorar la presentación del userform.
También tienen sus propiedades y eventos, pero casi nunca se utilizan.

Bueno, colocamos un control Frame en el userform, y ahora vamos a poner dentro de él los
tres botones de opción. Para poner un control dentro del marco lo que hay que hacer es
seleccionar el marco y sin quitar la selección añadir el nuevo control. Vamos a hacer esto tres
veces, y añadiremos tres botones de opción dentro del marco.

Para guardar los valores de los botones de opción vamos a dar nombres a tres celdas de la
hoja de cálculo (en el ejemplo E16, E17 y E18), a las que nombraremos "rngExcel", "rngLotus"
y "rngOtros". Ahora vamos a los tres botones de opción que hemos puesto en el userform y en
la propiedad ControlSource de cada uno de ellos escribimos una de los nombres que
acabamos de crear. También convendría cambiar la propiedad Caption de cada uno de los
botones para mostrar el texto adecuado.

Las propiedades Value y TripleState de un botón de opción funcionan igual que en el control
de verificación, y el resto de propiedades no son demasiado importantes.

Si probamos ahora el userform debería funcionar perfectamente, excepto un pequeño detalle.


Si el usuario nos dice que no utiliza ninguna hoja de cálculo, los botones de opción siguen
preguntándole cuál es su hoja de cálculo preferida, lo que evidentemente no tiene ningún
sentido. Lo que tenemos que hacer es desactivar los botones de opción: para desactivar
cualquier control (no sólo los botones de opción) se utiliza la propiedad Enabled; si esta
propiedad es verdadera, el control está activado, y si es falso el control estará desactivado
(aparece en color gris), y el usuario no puede interactuar con él.

Lo que nos queda ahora es saber cuándo ha cambiado de estado (verdadero, falso) la casilla
de verificación cboxUtilizaHoja. Como siempre, lo hacemos con un evento, el evento Change
del control de verificación, que se ejecuta cada vez que cambia el estado del control. Por lo
tanto, en el evento Change tendremos que cambiar el estado (activado, desactivado) de los
botones de opción. El código es:

Private Sub cboxUtilizaHoja_Change()


Frame2.Enabled = cboxUtilizaHoja.Value
OptionButton1.Enabled = cboxUtilizaHoja.Value
OptionButton2.Enabled = cboxUtilizaHoja.Value
OptionButton3.Enabled = cboxUtilizaHoja.Value
End Sub

Fíjate que damos a la propiedad Enabled de los botones de opción y el marco el valor de la
propiedad Value del control de verificación. También podríamos haber escrito:

If cboxUtilizaHoja.Value = True Then


OptionButton1.Enabled = True
.....
Else
OptionButton1.Enabled = False
.....
End If

El resultado es el mismo, pero la primera opción es bastante más elegante.

Un pequeño detalle. Cuando el userform se inicia también deberíamos activar/desactivar los


botones según el valor de la casilla de verificación. Una solución rápida sería escribir dentro del
evento Userform_Initialize (que ya conocemos) el mismo código que en
cboxUtilizaHoja_Change, pero no es lo más adecuado porque estaríamos escribiendo el
mismo código en dos sitios distintos, cosa que hay que evitar porque si luego tenemos que
hacer algún cambio en el código tendremos que hacerlo en dos sitios.

Lo mejor es llamar a cboxUtilizaHoja_Change() desde el evento Userform_Initialize(). La


rutina cboxUtilizaHoja_Change es llamada cada vez que se produce el evento Change, pero
nada nos impide llamarla por nuestra cuenta en cualquier otro momento, como por ejemplo
cuando se inicia el userform. El evento Userform_Initialize quedará así:

Private Sub UserForm_Initialize()


cboxUtilizaHoja_Change
SpinButton1.Value = editEdad.Value
End Sub

Pues ya tenemos el userform de datos personales completo, y ya hemos aprendido a usar


prácticamente todos los controles. La apariencia final del userform de datos personales es la
siguiente.

Como ejercicio, vamos a hacer otro userform, en el que no vamos a utilizar ningún control
nuevo pero sí vamos a ver un evento nuevo (KeyUp). Lo que vamos a hacer es un diálogo en
el que el usuario pueda escribir una cifra en pesetas y automáticamente le diremos cuántos
euros son. Y al revés, si escribe los euros calcularemos cuántas pesetas son.

Pues vamos al VBE, creamos un userform, y ponemos en él dos controles de edición, que
llamaremos editPesetas y editEuros, dos etiquetas al lado de cada control de edición, y un
botón para cerrar el diálogo.

Primero lo más fácil. En el botón de cerrar (al que cambiaremos el Caption para que ponga
"Cerrar", y que llamaremos btnCerrar) tenemos que poner el código para cerrar el userform:

Private Sub btnCerrar_Click()


Unload Me
End Sub

Ahora vamos a los cuadros de edición. Lo que queremos hacer es que cada vez que el usuario
pulse una tecla se actualice el otro cuadro de edición. Por ejemplo, si el usuario va a escribir
2500 pts, nosotros actualizaremos el cuadro de edición de euros cada vez que el usuario pulse
una tecla, sin esperar a que termine. Para eso vamos a utilizar el evento KeyUp, que se
produce cada vez que el usuario pulsa una tecla.

Para escribir el código de este evento vamos a la ventana de código de nuestro userform, y en
las persianas de la parte superior seleccionamos el control editPesetas y en la parte derecha
el evento KeyUp. Excel nos habrá puesto la declaración de la rutina (con los parámetros
adecuados, que en este caso no nos interesan y vamos a ignorar) y el " End Sub"
correspondiente. Ahora sólo tenemos que poner lo del medio:

Private Sub editPesetas_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As


Integer)
If editPesetas.Text <> "" Then
editEuros.Text = Format(editPesetas.Value / 168, "0.00")
Else
editEuros.Text = ""
End If
End Sub

El "If" lo utilizo como una pequeña forma de detección de errores, por si el cuadro de edición
está vacío (de todas formas, se pueden producir muchos errores, como por ejemplo si el
usuario introduce una letra en lugar de un número, pero no vamos a ponernos ahora a escribir
código para detectar todos esos errores). El resto es bastante sencillo, se trata de poner en el
cuadro editEuros el importe de editPesetas dividido por 168 (el valor en pesetas de un euro),
y utilizando la función Format para que sólo presente dos decimales. (la función Format es
muy sencilla de utilizar, si quieres más información consulta la ayuda).

Podemos probar a ejecutar ahora el diálogo y veremos que cada vez que introduzcamos un
carácter en el cuadro editPesetas se actualiza el cuadro editEuros.

Ahora tenemos que hacer que cuando escribamos algo en editEuros se actualice editPesetas.
El procedimiento es exactamente el mismo:

Private Sub editEuros_KeyUp(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As


Integer)
If editEuros.Text <> "" Then
editPesetas.Text = Format(editEuros.Value * 168, "0.00")
Else
editPesetas.Text = ""
End If
End Sub

Igual que antes, pero multiplicando por 168 en lugar de dividir.

Hasta ahora, todos los botones que hemos utilizado en los userforms servían para cerrar el
userform, con la diferencia de que solemos poner uno para Aceptar y otro para Cancelar. Pero
también podemos poner en un userform un botón que realice cualquier otra acción pero no
cierre el userform. Lo más típico es que este botón haga algún cambio sobre los controles del
userform.

En este caso, aprovechando nuestro conversor de euros, vamos a crear dos botones, uno al
lado de cada cuadro de edición, que van a pegar en la celda activa de la hoja de cálculo el
contenido del cuadro de edición asociado.
Colocamos los dos botones, uno al lado de cada cuadro de edición, y les damos los nombres
btnPegarPts y btnPegarEuros, y les ponemos como Caption algo como "Pegar". Ahora
vamos al código:

Private Sub btnPegarPts_Click()


ActiveCell.Value = editPesetas.Value
End Sub

Private Sub btnPegarEuros_Click()


ActiveCell.Value = editEuros.Value
End Sub

El evento que utilizamos es el evento Click, que ya conocemos de sobra. Y el código tampoco
tiene ninguna dificultad, simplemente es poner en ActiveCell el valor del control de edición,
editPesetas o editEuros.

Como verás, al pulsar estos botones se pega el contenido en la hoja de cálculo, pero no se
cierra el userform. Si quisiéramos que después de hacer el pegado se cerrara el userform
tendríamos que añadir el clásico "Unload Me" a las dos rutinas anteriores.

Así nos ha quedado el userform del conversor de euros:

Y para terminar esta entrega, vamos a hacer un diálogo para hacer operaciones sobre un
rango, como los que ya hemos hecho, pero más completo. El diálogo va a permitirnos cambiar
el rango seleccionado, y luego nos permitirá seleccionar la operación aritmética que queremos
hacer sobre el rango (sumar, restar, multiplicar, dividir) utilizando para ello unos botones de
opción.

En este diálogo vamos a utilizar un control nuevo, el RefEdit, que sirve para que el usuario
pueda introducir una referencia (un rango). Puede hacerlo escribiendo la referencia absoluta o
el nombre del rango (como si fuese un cuadro de edición), o pulsando en el botoncito que
aparece a la derecha, que hace que desaparezca el userform y el usuario puede seleccionar el
rango con el ratón o el teclado.

Los controles que vamos a poner en este userform son:

Tipo de control Name Caption


RefEdit RefEdit1 N/A
TextBox tbValor N/A
Frame Frame1 Operación
OptionButton obSumar Sumar
OptionButton obRestar Restar
OptionButton obMultiplicar Multiplicar
OptionButton obDividir Dividir
CommandButton btnAceptar Aceptar
CommandButton btnCancelar Cancelar

El resultado final será algo así:

Lo único nuevo que tenemos que aprender es que el rango que el usuario ha introducido en el
RefEdit se guarda en la propiedad Text. Pero Text es una cadena de caracteres, por lo que si
queremos hacer referencia al rango deberemos usar Range(RefEdit1.Text).

Vamos con el código:

Private Sub UserForm_Initialize()


obSumar.Value = True
RefEdit1.Text = Selection.Address
End Sub

Primero hacemos que la operación seleccionada por defecto sea sumar (alguna tiene que ser)
y que en el RefEdit aparezca como rango la selección que tenía hecha el usuario antes de
llamar al diálogo.

Ahora los botones:

Private Sub btnAceptar_Click()


HacerOperacion
Unload Me
End Sub

Private Sub btnCancelar_Click()


Unload Me
End Sub
La única diferencia entre los dos botones es que uno de ellos llama a la rutina HacerOperacion
antes de cerrar el userform. La rutina HacerOperacion es la siguiente:

Sub HacerOperacion()
Dim r As Range
Dim c As Object
Dim i As Double

Set r = Range(RefEdit1.Text)
i = tbValor.Value
For Each c In r.Cells
If obSumar.Value = True Then
c.Value = c.Value + i
ElseIf obRestar.Value = True Then
c.Value = c.Value - i
ElseIf obMultiplicar.Value = True Then
c.Value = c.Value * i
ElseIf obDividir.Value = True Then
c.Value = c.Value / i
End If
Next c
End Sub

Primero obtenemos el rango seleccionado y lo almacenamos en "r". Luego obtenemos el valor


que hay que utilizar, que el usuario ha escrito en tbValor, y lo almacenamos en "i". Luego
hacemos un bucle "For Each - Next", que ya conocemos, para repetir el mismo código para
todas las celdas del rango. El "If" tan largo que utilizamos es bastante más sencillo de lo que
parece: lo único que hace es comprobar cuál es el botón de opción activado (Value = True) y
efectúa la operación asociada a ese botón.

Y aquí termina la cuarta entrega del curso. Si tienes cualquier duda o comentario que hacer, no
dudes en contactar conmigo. En la próxima entrega hablaremos de la creación de menús y
barras de herramientas personalizadas.

Excel4.xls
Recuerda que los ejemplos de este capítulo están incluídos en este fichero:
(116kbs)

Capítulo 5. Menús y barras de herramientas.

En esta entrega vamos a tratar sobre la creación de menús y barras de herramientas


personalizadas para nuestras hojas. En Visual Basic for Applications, las barras de menú y las
barras de herramientas están representadas por el mismo objeto (CommandBar), y su
funcionamiento es exactamente igual.

Excel5.xls
Todos los ejemplos de este capítulo están incluídos en este fichero:
(90kbs)

Antes de nada, vamos a intentar aclarar la nomenclatura que se utiliza en VBA para hacer
referencia a cada una de las partes de un menu.
El nombre del menu en
sí mismo es
CommandBar. Un
CommandBar (barra de
menú) representa a todo
el menú, como por
ejemplo el que aparece
cuando estás en una
hoja de cálculo. Si
cambias a una hoja de
gráfico verás que el
menú cambia: se ha
cambiado de barra de
menú (CommandBar).

Cada una de las


opciones de la barra de
menú se llama
CommandBarPopUp
(menú desplegable
según la traducción de
Microsoft). Por ejemplo,
en el menú de una hoja
de cálculo la opción
"Archivo" es un menú
desplegable o CommandBarPopUp.

Dentro del menú desplegable, cada una de las opciones se llama ControlButton (opción de
menú). Por ejemplo, "nuevo" y "Guardar" son opciones del menú desplegable "archivo" de la
barra de menú de "Hoja de cálculo" de Excel.

Para tener acceso a las barras de comandos (que pueden ser menús o barras de herramientas)
utilizaremos la propiedad CommandBars, que devuelve el conjunto de barras de comandos de
la aplicación. Cada una de las barras de comando será por tanto un objeto CommandBar.

Por ejemplo, para ver los nombres de todas las barras de comando que existen escribiremos la
siguiente rutina:

Sub ListaBarrasComando()
Dim h as Object
Dim dst as Range

Set dst = Sheets("Hoja1").Range("A1")


For Each h in CommandBars
dst.Value = h.Name
Set dst = dst.Offset(1, 0)
Next h
End Sub

De esta forma obtendremos el nombre de todas las barras de comando. Recuerda que puede
haber barras de comando que existan pero no estén activas, que no aparezcan en la pantalla.

Como habrás podido deducir, la propiedad Name de un objeto CommandBar nos devuelve el
nombre de la barra de comando.

1. Crear una opción de menú.


Lo primero que vamos a hacer es crear una opcion dentro de un menú desplegable. Por
ejemplo, vamos a crear una opción llamada "Macedonia" dentro del menú "Edición".

Antes que nada, declaramos las variables que vamos a utilizar:

Dim cBar As Object


Dim cBarPopUp As Object
Dim cButton As Object

La primera variable (cBar) la utilizaremos para almacenar el menú de hoja de cálculo entero, la
segunda (cBarPopUp) para obtener el menú de "Edición" dentro de cBar, y la tercera para crear
nuestra opción (Macedonia) dentro del menú de Edición.

Vamos a obtener el menú de hoja de cálculo. Si te fijas en el resultado de la rutina


ListaBarrasComando que hemos creado antes, verás que una de las barras de comando se
llama "Worksheet Menu Bar". Esta es la barra de comandos que está presente cuando estás en
una hoja de cálculo. Hay otras barras, como por ejemplo "Chart Menu Bar", que es la que
aparece cuando estás en una hoja de gráficos.

Para utilizar la barra de comandos "Worksheet Menu Bar" haremos lo siguiente:

Set cBar = CommandBars("Worksheet Menu Bar")

Con esto hemos conseguido que nuestra variable, cBar, contenga la barra de comandos que
nos interesa. Ahora queremos seleccionar una parte de ese barra de comandos: queremos el
menú de Edición. Para ello utilizamos el siguiente código:

Set cBarPopUp = cBar.Controls("Edición")

Hemos utilizado la propiedad "Controls" del objeto CommandBar. Esta propiedad nos permite
acceder a todos los submenús de una barra de comandos. El objeto devuelto es del tipo
"CommandBarPopup". Reconozco que la terminología es un poco confusa, pero así lo ha
hecho Microsoft.

Ahora ya tenemos el menú de "Edición" en nuestra variable. Y lo que


queremos hacer es añadir una opción dentro de ese menú. Para hacerlo
utilizaremos deberemos acceder a la propiedad "Controls" de nuestro
menú de Edición. Fíjate que antes hemos accedido a la propiedad
Controls del objeto cBar, y ahora vamos a acceder a la propiedad
Controls del objeto cBarPopUp. Pues bien, una vez que accedemos a
la propiedad "Controls" del menú Edición (cBarPopUp), utilizamos el
método Add para añadir una nueva opción del menú:

Set cButton = cBarPopUp.Controls.Add(msoControlButton)

Almacenamos en nuestra variable cButton el resultado, porque luego queremos hacerle unos
cambios.

El tipo de control que queremos añadir puede variar ( msoControlButton, msoControlEdit,


msoControlDropdown, msoControlComboBox o msoControlPopup ), pero en nuestro caso
queremos una opción de menú, y utilizamos msoControlButton.

Nos queda hacer que nuestra opción de menú (o ControlButton), tenga el texto que nosotros
queremos y haga lo que nosotros queremos. Para ello utilizaremos las propiedades del
ControlButton:
 Caption: es el texto que queremos que aparezca en la opción de menú. En nuestro
caso, "&Macedonia". El carácter "&" se utiliza para indicar que la letra que le sigue (la
"M" en este caso) queremos que apareza subrayada y funcione como tecla rápida una
vez que esté abierto el menú.
 OnAction: es el nombre de la rutina que queremos que se ejecute cuando el usuario
seleccione esa opción. En este caso vamos a darle el valor "MiMacro", que será una
pequeña rutina que simplemente avisará de que hemos seleccionado esa opción.
 ShortcutText: el texto que aparece en la opción del menú, a la derecha. Normalmente
se suele poner la tecla rápida para esa opción de menú. Cuidado, porque esta opción
sólo sirve para escribir el texto, pero no hace que la tecla rápida funcione, eso tendrás
que hacerlo tú por otro lado.
 FaceID: es el número de la imagen que queremos que se asigne a nuestra opción de
menú. La imagen aparece en la parte izquierda de la opción. Excel tiene un montón de
imágenes para nuestras opciones, y se pueden seleccionar cambiando el ID. Para ver
todas las imágenes disponibles y saber qué ID corresponde a cada imagen, lo mejor es
hacer una pequeña rutina que muestre todas las imágenes. (eso te queda como
ejercicio; si tienes alguna duda escríbeme).
 BeginGroup: true o false, indica si queremos que antes de nuestra opción se ponga un
"separador", una línea que separe un poco nuestra opción de la anterior.

Como siempre, hay muchas más propiedades, pero creo que hemos visto las más importantes.
Vamos a ver nuestra rutina completa:

Sub CrearOpcionMenu()
Dim cBar As Object
Dim cBarPopUp As Object
Dim cButton As Object

BorrarOpcionMenu
Set cBar = CommandBars("Worksheet Menu Bar")
Set cBarPopUp = cBar.Controls("Edición")
Set cButton = cBarPopUp.Controls.Add(msoControlButton)
With cButton
.Caption = "&Macedonia"
.OnAction = "MiMacro"
.FaceId = 7
.ShortcutText = "Ctrl+Shift+M"
.BeginGroup = True
End With
Call MsgBox("Se ha creado la opción 'Macedonia' en el menú 'Edición'", vbOKOnly,
"Macedonia")
End Sub

Para verla en acción abre el fichero de ejemplo, y utiliza el botón "Crear opción de menú".

Si te fijas en la rutina CrearOpcionMenu, hemos incluido una llamada a la rutina


BorrarOpcionMenu. Esta última se encarga de borrar la opción "Macedonia" del menú Edición
en caso de que ya exista, y llamándola evitamos que aparezcan dos opciones "Macedonia". La
rutina BorrarOpcionMenu es la siguiente:

Sub BorrarOpcionMenu()
Dim cBar As Object
Dim cBarPopUp As Object
Dim cc As Object

Set cBar = CommandBars("Worksheet Menu Bar")


Set cBarPopUp = cBar.Controls("Edición")
For Each cc In cBarPopUp.Controls
If cc.Caption = "&Macedonia" Then cc.Delete
Next cc
End Sub

Al igual que en la rutina CrearOpcionMenu, primero obtenemos la barra de comandos


"Worksheet Menu Bar", despues la barra "Edición", y luego, utilizando la instrucción "For Each",
pasamos por todos las opciones de menú, y borramos aquellas cuyo "Caption" sea
"&Macedonia" (incluyendo el &). Para borrar la opción de menú utilizamos el método Delete.

2. Crear un menú desplegable.

Ahora vamos a crear un menú desplegable (como el menú Archivo, o Edición, de la hoja de
cálculo de Excel). Como siempre, primero declaramos las variables que vamos a utilizar.

Dim cBar As Object


Dim cBarPopUp As Object
Dim cButton As Object

Luego vamos a obtener la barra de comandos de la hoja de cálculo:

Set cBar = CommandBars("Worksheet Menu Bar")

Para añadir un menú desplegable a dicha barra de comandos vamos a utilizar el método "Add"
de la colección "Controls" de la barra de comandos:

Set cBarPopUp = cBar.Controls.Add(Type:=msoControlPopup, Before:=10)

El tipo de control que queremos añadir es un "msoControlPopup", para indicar que queremos
un menú desplegable.

cBarPopUp.Caption = "&Macedonia"

Ahora tenemos en cBarPopUp un menú desplegable, igual que en el punto anterior teníamos el
menú desplegable "Edición". Ahora tenemos que añadir opciones en dicho menú desplagable,
igual que hemos hecho antes:

Set cButton = cBarPopUp.Controls.Add(msoControlButton)


With cButton
.Caption = "&Macedonia 1"
.OnAction = "MiMacro"
End With

También podemos añadir un submenú dentro de alguna opción de nuestro menú, de una forma
muy parecida. La rutina completa para crear un menú desplegable es la siguiente:

Sub CrearMenuDesplegable()
Dim cBar As Object
Dim cBarPopUp As Object
Dim cButton As Object
Dim i, j As Integer

BorrarMenuDesplegable
Set cBar = CommandBars("Worksheet Menu Bar")
Set cBarPopUp = cBar.Controls.Add(Type:=msoControlPopup, _
Before:=10)
cBarPopUp.Caption = "&Macedonia"

For i = 1 To 10
If i <> 5 Then
Set cButton = cBarPopUp.Controls.Add(msoControlButton)
With cButton
.Caption = "&Macedonia " & i
.OnAction = "MiMacro"
If i Mod 3 = 0 Then .BeginGroup = True
End With
Else
Set cButton = cBarPopUp.Controls.Add(msoControlPopup)
cButton.Caption = "&Macedonia " & i
For j = 1 To 5
With cButton.Controls.Add(msoControlButton)
.Caption = "Submenú Macedonia " & j
.OnAction = "MiMacro"
If j Mod 3 = 0 Then .BeginGroup = True
End With
Next j
End If
Next i
Call MsgBox("Se ha añadido la opción 'Macedonia' en el menú principal", _
vbOKOnly, "Macedonia")
End Sub

Para ver esta rutina en acción utiliza el botón "Crear menú desplegable" del fichero de ejemplo.

3. Crear una barra de menú.

Ahora vamos a crear una barra de menú completa, como la barra de menú "Worksheet Menu
Bar". Lo primero, como siempre, es declarar las variables:

Dim cBar As Object


Dim cBarPopUp As Object
Dim cButton As Object

En lugar de obtener la barra de menú "Worksheet Menu Bar" y luego trabajar con ella, ahora lo
que vamos a hacer es crear nosotros mismos una barra de menú, utilizando el método "Add"
de la colección "CommandBars".

Set cBar = CommandBars.Add("Barra Macedonia", msoBarTop, True)

El primer argumento es el nombre de la barra de comandos que vamos


a crear. El segundo argumento es la posición de la nueva barra de
comandos, y puede ser uno de los siguientes valores:

 msoBarLeft, msoBarRight, msoBarTop, msoBarBottom:


izquierda, derecha, arriba o abajo.
 msoBarFloating: queremos que la nueva barra de menú sea
flotante.
 msoBarPopUp: la nueva barra de menús será contextual, como las que salen cuando
pulsamos el botón derecho.

El tercer argumento (verdadero o falso) indica si queremos que la nueva barra de menú
reemplace a la barra de menús activa o no.

Una vez que tenemos nuestra barra de menú utilizamos el código que hemos aprendido antes
para crear los menús desplegables y sus opciones. La siguiente rutina crea una barra de menú
y varios menús desplegables y opciones:
Private Const NOMBREMENU = "Menú Macedonia"

Sub CrearBarraMenu()
Dim cBar As Object
Dim cBarPopUp As Object
Dim cButton As Object
Dim i, j As Integer

BorrarBarraMenu
Set cBar = CommandBars.Add(NOMBREMENU, msoBarTop, True)

For j = 1 To 5
Set cBarPopUp = cBar.Controls.Add(Type:=msoControlPopup)
cBarPopUp.Caption = "&Macedonia " & j
For i = 1 To j + 2
Set cButton = cBarPopUp.Controls.Add(msoControlButton)
With cButton
.Caption = "&Macedonia " & i
.OnAction = "MiMacro"
If i Mod 3 = 0 Then .BeginGroup = True
End With
Next i
Next j
Call MsgBox("Se ha creado la barra de menú 'Macedonia'.", vbOKOnly, "Macedonia")
End Sub

Hemos utilizado la variable "NOMBREMENU" para dar el nombre a la barra de menú. Cuando
se usa una cadena en más de un sitio del código es aconsejable sustituir la cadena por una
variable, para evitar errores al escribir la cadena en varios sitios.

Con la rutina anterior hemos creado la barra de menú, pero todavía no la podemos ver, porque
hay que activarla, usando:

CommandBars(NOMBREMENU).Visible = True

Como al crear la barra hemos indicado (con el tercer argumento) que esta barra tiene que
sustituir a la que esta activa, la barra activa desaparece y la nuestra aparece. Para volver a
desactivar nuestra barra, utilizaremos:

CommandBars(NOMBREMENU).Visible = False

Si queremos borrar la barra de menu que hemos creado utilizaremos el metodo Delete:

CommandBars(NOMBREMENU).Delete

En el fichero excel5.xls tienes unos botones que sirven para crear, activar, desactivar y borrar
una barra de menú.

4. Crear una barra de herramientas:

Como hemos visto al principio, en VBA las barras de menú y las barras de herramientas están
representadas por el mismo objeto (CommandBar), y su funcionamiento es prácticamente igual.

Crear una barra de herramientas es exactamente igual que crear una barra de menú:

Set cBar = CommandBars.Add(NOMBREBARRA, msoBarFloating, False)


En este caso hemos creado una barra "flotante", pero podíamos haber utilizado cualquiera de
los otros parámetros que hemos visto antes.

Ahora vamos a crear un botón de la barra de herramientas. La única diferencia entre crear un
botón y crear un menú desplegable es el tipo de control, el parámetro del método Add. En este
caso utilizaremos "msoControlButton":

Set cButton = cBar.Controls.Add(msoControlButton)


With cButton
.Caption = "&Macedonia " & i
.OnAction = "MiMacro"
.FaceId = Int(Rnd * 1000)
End With

El código utilizado para crear, activar, desactivar y borrar una barra de herramientas es el
mismo que para una barra de menús. De hecho no hay ninguna diferencia entre ellas, en Excel
las dos son una barra de comandos (CommandBar). Además, también podemos mezclar
botones y menús dentro de una barra de comandos: sólo hay que crear la barra y luego añadir
controles tipo "msoControlPopup" para los menús y controles "msoControlButton" para los
botones.

Bueno, aquí termina la quinta entrega del curso de VBA para Excel. Si tienes cualquier duda o
comentario no dudes en escribirme.

Excel5.xls
Recuerda que los ejemplos de este capítulo están incluídos en este fichero:
(90kbs)

También podría gustarte