VBA Guía de Referencia - Roddy Rivas
VBA Guía de Referencia - Roddy Rivas
VBA Guía de Referencia - Roddy Rivas
Roddy Rivas-Llosa M.
PRESENTACIÓN
1. PRIMERA PARTE
Aspectos generales del entorno y del lenguaje
Con fines didácticos, distinguiremos tres aproximaciones o soluciones prácticas al problema de cómo crear
un programa en la computadora. Estos tres “estilos” se podrían denominar respectivamente grabación de
macros, programación de código fuente y programación mixta. El cuadro siguiente muestra una breve
reseña de los dos primeros y un esquema intuitivo de la relación existente entre todos ellos.
CUADRO 1
LOS TRES ESTILOS DE PROGRAMACIÓN
Cuando el usuario registra un conjunto de operaciones manuales mediante el menú Herramientas / Macro /
Grabar nueva macro..., la computadora crea una secuencia de comandos automáticamente y le asigna un
nombre a esta secuencia. El programa generado de esta forma se conoce como “macro” y puede ser
posteriormente ejecutado mediante el menú Herramientas / Macro / Macros..., o asignándolo a un objeto
(tal como un botón de comando), a una combinación de teclas o invocándolo mediante su nombre desde otra
macro o subrutina.
Las instrucciones que conforman una macro son accesibles para su revisión y edición a través del entorno de
programación de Visual Basic, al que puede ingresarse mediante el menú Herramientas / Macro / Editor de
Visual Basic o mediante la combinación de teclas ALT-F11. Una vez dentro de este entorno, el archivo de
Excel pasa a llamarse “proyecto”.
Roddy Rivas-Llosa M. 2
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
GRÁFICO 1
ENTORNO DE PROGRAMACIÓN VISUAL BASIC PARA EXCEL
Dentro de un proyecto es posible insertar los llamados “Módulos”, que funcionan como contenedores de
instrucciones. Cada módulo puede contener una gran cantidad de pequeños programas independientes o
interdependientes, que son llamados subrutinas o funciones1.
Si el usuario ingresa al entorno Visual Basic y allí elabora el programa enteramente, entonces se puede decir
que ha llevado a cabo la programación en código fuente. En contraste, la técnica de programación mixta
consiste en grabar una macro base (una macro “de ejemplo”), que en sí misma no será ejecutada. A partir de
ella, el usuario adapta la secuencia de comandos autogenerada por la computadora en código fuente a sus
necesidades específicas.
¿Cuál es la diferencia esencial entre la grabación de macros y la edición de código fuente? La diferencia
clave reside en que, ya que el código fuente de la macro grabada es autogenerado por la computadora a
medida que el usuario realiza una tarea, este tipo de programas no puede contener estructuras lógicas. Así, a
diferencia de un programa elaborado a nivel de código fuente, una macro grabada carece del potencial para
tomar decisiones, llevar a cabo repeticiones automáticamente o interactuar con el usuario.
Diseñaremos un programa para automatizar la tarea de llenar un cierto rango de la hoja de cálculo con el
valor 0 (por ejemplo, un rango de celdas de stocks). El propósito será asociar este proceso a un pequeño
botón en la hoja, que realice automáticamente la tarea en lugar de tener que copiar manualmente los valores
en las celdas de destino.
1
Una subrutina es un programa diseñado para funcionar activamente y es capaz de cambiar los contenidos de la hoja de cálculo. Por
su parte, una función es un programa diseñado para realizar cálculos y devolver un valor, normalmente dependiente de ciertos
parámetros.
Roddy Rivas-Llosa M. 3
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
Comenzaremos por entrar en el entorno de programación, localizar el proyecto actual e insertar un módulo
nuevo con el menú Insertar / Módulo.
GRÁFICO 2
ENTORNO DE PROGRAMACIÓN VISUAL BASIC PARA EXCEL
A continuación comprobaremos que en la parte derecha de la pantalla se haya abierto una ventana vacía que
corresponde al contenido del módulo recién insertado. Si no fuera así, bastará con hacer doble click sobre el
nombre del módulo para activar la ventana de contenido.
Dentro de la ventana de contenido escribiremos el código de la subrutina o programa que deseamos crear:
Sub LlenaCeros()
Range(“A1:E20”) = 0
End Sub
La sintaxis usada corresponde a uno de los comandos más simples de Visual Basic: una referencia pura a un
rango de la hoja de cálculo y la asignación de un valor constante.
Para poder ejecutar la rutina fácilmente desde la hoja de cálculo, regresaremos a Excel (usando ALT-TAB,
por ejemplo) y mostraremos la barra de herramientas formularios (Ver / Barras de Herramientas /
Formularios).
Roddy Rivas-Llosa M. 4
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
GRÁFICO 3
LA BARRA DE HERRAMIENTAS FORMULARIOS
Luego, usando la herramienta para insertar botones de comando en la hoja, dibujaremos un pequeño botón
sobre la superficie de la hoja de cálculo. Excel nos preguntará inmediatamente qué macro deseamos ejecutar
al pulsar el botón recién insertado (a este proceso se le denomina asignar una macro al botón). En la ventana
correspondiente elegiremos la macro LenaCeros de la lista y aceptaremos esta configuración. Como paso
final, cambiaremos el texto de la carilla del botón.
GRÁFICO 4
LA VENTANA DE ASIGNACIÓN DE MACRO
Tras llevar a cabo los pasos anteriores, la ventana de Excel lucirá similar a la siguiente:
Roddy Rivas-Llosa M. 5
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
GRÁFICO 5
EXCEL CON EL BOTÓN INCRUSTADO
Al hacer click en el botón de comando “Reiniciar rango”, comprobaremos que la macro se activa y llena el
rango de datos con el valor 0.
GRÁFICO 6
LA HOJA UNA VEZ EJECUTADA LA MACRO
Cabe notar que, una vez ejecutada una macro, no se encuentra disponible la opción “Deshacer”.
Roddy Rivas-Llosa M. 6
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
2. SEGUNDA PARTE
Estructuras funcionales y comandos básicos del lenguaje
[Dirección]
Se refiere al valor de una celda específica en la hoja activa 2. Permite el uso de nombres de rangos y rangos
rectangulares. Admite procedimientos o propiedades vinculados al rango.
Ejemplos:
[a1] = 10
[b9] = “Probando...”
[TasaActiva] = 0.12
[A1:B20] = 0.10
[C20:E30].Clear ‘Borra contenido y formatos
[A1] = [B14]
[A1].Formula = “=B14”
El primero asigna el valor de B14 en A1 de manera estática, es decir, únicamente en el momento de ejecutar
el comando. El segundo, en cambio, asigna B14 como una fórmula, de modo que al cambiar el contenido de
esta celda, los cambios se propagarán hacia la celda A1. Este comportamiento hace posible escribir
comandos tales como [A1] = [A1] + 1 sin generar una referencia circular, ya que se trabaja únicamente con
el valor actual de la celda (específicamente, este comando incrementaría en una unidad el valor de A1).
Range(“Dirección”) o Range(“NombreDeRango”)
Se refiere a un rango específico (puede ser una celda o grupo de celdas).
Ejemplos:
Range(“A1”) = 2
Range(“A1”).Value = 2 ‘Funciona igual que la anterior
Range(“A11:C22”) = “X”
Range(“B9:C15”).Formula = “=Rand()”
Range(“D11”).ClearContents ‘Sólo borra el contenido
Range(“FlujoDeCaja”).Copy ‘Copia el rango indicado
Range(“Reporte”).PasteSpecial ‘Pega en el rango indicado
Conviene notar (en el cuarto ejemplo) que el uso de la propiedad “Formula” requiere la redacción de las
funciones en inglés (Rand() es el equivalente a la función Aleatorio()).
Si se desea direccionar un rango de una hoja distinta a la hoja activa, puede usarse la sintaxis siguiente:
Sheets(“Presupuesto”).Range(“G20”) = 10
Offset(numFilas, numColumnas)
Es una propiedad del objeto Range. Se refiere a un rango que se encuentra tantas filas y columnas hacia
abajo y a la derecha a partir del rango original como lo indiquen los parámetros de la propiedad.
Ejemplos:
2
Nótese que al omitir el nombre de la propiedad de un rango se interpreta por defecto como la propiedad Value.
Roddy Rivas-Llosa M. 7
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
[A9] = Sheets(“Datos”).Range(“C14”).Offset(3,2)
ActiveCell.Offset(-1,-2)=[A8].Offset(3,9)
Cabe resaltar que el segundo ejemplo fijará la celda que, respecto a la celda actualmente activa, se encuentra
una columna hacia la izquierda y dos filas hacia arriba, con el contenido de la celda J11.
Range(“Rango”)
Se refiere a un rango de celdas.
Ejemplos:
Sheets(“Hoja”)
Se refiere a una hoja de cálculo del libro activo.
Ejemplos:
Sheets(“Hoja1”).Select ‘Selecciona la hoja
Sheets(“Hoja1”).Range(“B9”).Clear ‘Borra el rango
Sheets(“Presupuesto”).Range(“10:100”).Delete ‘Elimina filas
Workbooks(“Libro”)
Se refiere a un libro de cálculo abierto.
Uso típico:
Workbooks(“Libro1”).Activate
Application
Se refiere al programa Excel en sí mismo
Ejemplos:
2.2. Subrutinas
Las subrutinas se declaran mediante la palabra reservada SUB, seguida del nombre de la subrutina y,
opcionalmente (entre paréntesis) la lista de argumentos. Las subrutinas no devuelven ningún valor como
respuesta, sino que se utilizan para ejecutar comandos que normalmente alteran la visualización, el contenido
o el formato de la hoja de cálculo3.
3
Para ejecutar una subrutina desde otra subrutina o función basta colocar su nombre como si fuera un comando incorporado. En caso
de tener argumentos, éstos se separan del nombre con un espacio y entre sí con comas (P.Ej. CreaOtroInforme 2,”Enero”,3 )
Roddy Rivas-Llosa M. 8
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
Ejemplos:
SUB CreaInforme()
...
END SUB
Préstese especial atención al emparejamiento de las cláusulas de apertura y cierre. Si existiese un SUB o un
END SUB no apareado, la computadora se negaría a ejecutar cualquier porción del programa.
Nota importante: en caso de encontrarse un error en el código fuente, el programa resaltará con color
amarillo la línea de código identificable más cercana al error y la computadora entrará en un estado llamado
“modo de interrupción”. Antes de realizar cualquier corrección o ejecutar nuevamente el programa, debe
detenerse la ejecución y salir del modo de interrupción, presionando el botón de “Restablecer” (el cuadrado
azul en la barra superior de herramientas) en el entorno de Visual Basic.
2.3. Funciones
Las funciones se declaran mediante la palabra reservada FUNCTION, seguida del nombre de la función y,
entre paréntesis, la lista de argumentos. Dentro del cuerpo de la función se debe incluir una línea de
asignación de resultado, que asigne valor a una variable implícita que lleva el mismo nombre de la función.
Ejemplos:
FUNCTION SinParametros()
...
SinParametros = 1 ‘Aquí se asigna la respuesta
END FUNCTION
FUNCTION ConParametros( x, y, S)
...
ConParametros = “El resultado es ” & (x+y)
END FUNCTION
Los Bucles o repeticiones funcionan como estructuras de automatización. Cuando el lenguaje encuentre estas
estructuras, repetirá un fragmento de código tantas veces como lo indique el usuario o mientras se cumpla
una condición lógica. Los bucles propiamente dichos se expresan mediante las palabras reservadas
FOR...TO...STEP...NEXT, mientras que las repeticiones (abiertas) se ingresan mediante la palabra reservada
DO WHILE...LOOP. Un tipo especial de bucle, referido a colecciones, se programa mediante las cláusulas
FOR EACH … IN … NEXT
Ejemplos 4:
‘Los cuadrados de los primeros números impares
FOR i = 1 TO 100 STEP 2
Range(“A1”).Offset(i,0) = i ^ 2
NEXT i
4
Nótese que si en el segundo ejemplo no se incrementara el valor de la variable i la repetición nunca concluiría. De hecho, no es
posible saber a priori si esta repetición concluirá o no (si la celda B1 contuviera un –1 la repetición continuaría indefinidamente). En
estos casos, cuando se hace necesario detener la ejecución de un programa, basta presionar la combinación de teclas CTRL-Pausa.
Roddy Rivas-Llosa M. 9
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
2.5. Condicionales
Las estructuras condicionales se utilizan para permitir la toma de decisiones en medio de un programa. Las
formas básicas del condicional son dos: la forma corta y la forma larga. En ambos casos, las palabras
reservadas son IF...THEN...ELSE. En la forma larga, aparece la palabra ENDIF como cierre de la cláusula.
Ejemplos 5:
‘Formas cortas, no llevan ENDIF, pero son de una sola línea
IF x>0 THEN i = i + 1 ELSE q = r / 2
IF [A20]<0.1 THEN [A20]=2*[A20]
‘Forma larga
IF x>0 THEN
i = i + 1
k = k * 7
ELSE
i = i – 1
k = k \ 7
ENDIF
Esta estructura se utiliza para indicar a la computadora que tome una decisión en función del valor de una
variable o expresión. Las palabras reservadas son SELECT CASE... CASE... END SELECT. Puede
considerarse el SELECT CASE como una aplicación especializada de los condicionales.
Ejemplo:
SELECT CASE x
CASE 1
S = “X tomó el valor 1”
j = j + 1
Range(“A1”).Offset(1,j) = [B20]
CASE 2
S = “X tomó el valor 2”
CASE 3
S = “X tomó el valor 3”
CASE ELSE
5
Véase en el segundo ejemplo el uso del operador \ (backslash). Cuando se utiliza este operador en lugar del operador / de división, la
división se realiza considerando sólo resultados enteros. Así, mientras que 8 / 3 = 2.6667, 8 \ 3 = 2.
Roddy Rivas-Llosa M. 10
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
En el ejemplo, la variable S toma distintos valores según el contenido de la variable x. Además, en caso de
que x sea igual a la unidad, se llevan a cabo dos procesos adicionales (esto ilustra cómo pueden incluirse
varias líneas de código fuente dentro de cada una de las instrucciones CASE, tal como sucede en la versión
larga de una cláusula condicional).
LEN(Texto)
Devuelve el número de caracteres de un texto. Es equivalente a la función LARGO(Texto) en Excel.
VAL(Texto)
Convierte un texto a su valor numérico.
STR$(Número)
Convierte un número a su equivalente en texto.
ASC(Carácter)
Devuelve el código ASCII del carácter especificado (ASC(“A”) devuelve el número 65). Esta función se
utiliza en conjunto con la siguiente (ver a continuación el ejemplo).
CHR$(Código de carácter)
Devuelve el carácter que corresponde al código ASCII indicado (CHR$(65) corresponde a la letra “A”)
INT(Número)
Redondea un número al menor entero relativo más próximo.
Ejemplo:
INT(8.99) devuelve 8
INT(-8.01) devuelve –9
RND
Devuelve un número pseudo-aleatorio Z tal que 0 <= Z < 1
Ejemplo:
INT(RND*100+1)
LOG(Número positivo)
Devuelve el logaritmo natural de un número positivo.
EXP(Número)
Devuelve el antilogaritmo natural de un número. (Debe tenerse precaución pare evitar los errores de
desbordamiento si se intenta antilogaritmar un número de magnitud muy grande).
Roddy Rivas-Llosa M. 11
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
3. TERCERA PARTE
Algunos ejemplos de aplicación
3.1. Cómo contar cuántos valores contiguos hay por debajo de una celda
Queremos construir una función que, al aplicarse a la celda C1, devuelva el valor 5, indicando que hay cinco
celdas contiguas por debajo e incluyendo a C1.
A B C D E F G H I
1 10
2 14
3 8
4 -7
5 5
6
7 4
8 21
9
La función podría redactarse del siguiente modo, usando un bucle abierto para ir bajando por la columna
hasta encontrar una celda vacía:
FUNCTION CuentaContiguasPorDebajoDe(Celda)
Application.Volatile
Num = 0
DO WHILE Celda.Offset(Num,0) <> “”
Num = Num + 1
LOOP
CuentaContiguasPorDebajoDe = Num
END FUNCTION
La primera línea de la función (Application.Volatile) se utiliza para que Excel recalcule la fórmula incluso si
cambia el valor de una celda que no es el argumento (en el ejemplo, C1).
3.2. Cómo extraer en un rango separado las celdas que cumplen con una condición
Se necesita copiar a la columna H, uno debajo de otro, los valores del rango C1:F8 que son mayores que A1.
A B C D E F G H I
1 5 10 7 -1 4
2 14 11 1 10
3 8 1 9 -3
4 -7 1 9 9
5 5 2 7 11
6 11 4 -7 6
7 4 2 8 7
8 21 12 1 -1
9
Roddy Rivas-Llosa M. 12
Seminario Banco Central de Reserva Lenguaje Visual Basic para Excel – Guía de referencia
Para ello utilizaremos un bucle de barrido sobre toda el rango de valores y una variable que indique cuántos
elementos han sido copiados hasta el momento.
SUB CopiaValoresMayoresQueA1()
NumCopiados = 0
FOR Columna = 1 TO 4
FOR Fila = 1 TO 8
Valor = Range(“C1”).Offset(Fila-1,Columna-1)
IF Valor > [A1] THEN
Range(“E1”).Offset(NumCopiados,0) = Valor
NumCopiados = NumCopiados + 1
ENDIF
NEXT Fila
NEXT Columna
END SUB
SUB CopiaValoresMayoresQueA1B()
NumCopiados = 0
FOR EACH Valor IN Range(“C1:F8”)
IF Valor > [A1] THEN
Range(“E1”).Offset(NumCopiados,0) = Valor
NumCopiados = NumCopiados + 1
ENDIF
NEXT Valor
END SUB
Febrero de 2004
Roddy Rivas-Llosa M. 13