Escribir Macros VBA Desde Cero
El grabador de macros de Excel tiene mucho poder, pero tiene sus limitaciones. Como ya hemos comentado en otro artículo, la grabadora de macros suele registrar código innecesario y no puede registrar cosas como la lógica o las interacciones con otros programas. También puede ser difícil de usar para las macros más largas – puedes encontrarte haciendo un storyboard de tus acciones de antemano sólo para evitar cometer errores costosos.
Este artículo pretende ayudarle a empezar a codificar macros desde cero en VBA. Aprenderá dónde se almacenan las macros, escribirá una macro básica y aprenderá los fundamentos de la programación en VBA utilizando variables, lógica y bucles.
Cómo Empezar
VBA y el Editor de Visual Basic
VBA, o Visual Basic para Aplicaciones, es el lenguaje en el que se escriben las macros. Todas las macros se almacenan como código VBA, tanto si se codifican a mano como si se crean con el grabador de macros.
Puedes acceder a todo el código VBA de un libro de trabajo utilizando el Editor de Visual Basic. Se trata de un editor de texto especial y un depurador que está integrado en todas las aplicaciones de Office, incluido Excel. Normalmente, abrirás este editor con el atajo de teclado ALT+F11 en Excel, pero también puedes acceder a él desde la pestaña Programador de Excel si la tienes activada.
El Explorador de Proyectos
El Explorador de Proyectos es una ventana dentro del Editor VB que muestra todos los elementos que pueden tener código VBA en ellos. Si no ve esta ventana, pulse F5 para que aparezca o seleccione Explorador de Proyectos en el menú Ver.
Al hacer doble clic en un elemento del Explorador del Proyecto se mostrará el código de ese elemento. Hay varios tipos de elementos que pueden aparecer en el Explorador de Proyectos:
- Cuadernos de trabajo
- Hojas de trabajo
- Formularios de usuario
- Módulos de clase
- Módulos (las macros se almacenan en estos elementos)
Aunque todos estos tipos de elementos pueden incluir código VBA, la mejor práctica es codificar las macros en Módulos.
Cómo Hacer Su Primera Macro
Uso de la Lista de Macros
La lista de macros le muestra todas las macros de su libro de trabajo. Desde esta lista puede editar una macro existente o crear una nueva. Para crear una nueva macro utilizando la lista de macros:
- Seleccione la pestaña Desarrollador y haga clic en Macros (o pulse ALT+F8)
- Escriba un nuevo nombre para su macro y haga clic en «Crear»
Después de hacer clic en «Crear» aparecerá el Editor VB, mostrando la macro recién creada. Excel creará un nuevo módulo para la macro si es necesario.
Manualmente en el Editor VB
Puedes añadir una nueva macro manualmente sin la lista de Macros. Esta es la mejor opción si quieres especificar el módulo en el que se guarda la macro. Para añadir una macro manualmente:
- Abra el Editor VB(ALT+F11)
- O bien
- Añada un nuevo módulo haciendo clic en Insertar > Módulo en el menú (el módulo se abrirá automáticamente)
-
- O bien, haga doble clic en un módulo existente en el Explorador de Proyectos para abrirlo
- En el módulo, escriba el código de su nueva macro
Sub MiMacro()
End Sub
Estas dos líneas indican el comienzo y el final de una macro llamada «MiMacro» (nótese los paréntesis, que son necesarios). Esta aparecerá en el diálogo «Ver Macros» en Excel y puede ser asignada a un botón (aunque todavía no haga nada).
Añadir Algo de Código a la Macro
Ahora, vamos a añadir algo de código entre las líneas «Sub» y «End Sub» para hacer que esta macro realmente haga algo:
Sub MiMacro()
Range("A1").Value = "¡Hola Mundo!"
End Sub
Estructuras Básicas de Código
El Objeto Range
Excel VBA utiliza el objeto Range para representar las celdas de una hoja de cálculo. En el ejemplo anterior, se crea un objeto Range con el código Range(«A1») para acceder al valor de la celda A1.
Los objetos Range se utilizan principalmente para establecer los valores de las celdas:
Range("A1").Value = 1
Range("A1").Value = "Primera celda"
Observe que cuando se definen los valores de las celdas como números, sólo se introduce el número, pero cuando se introduce texto hay que rodear el texto con comillas.
Los rangos también pueden usarse para acceder a muchas propiedades de las celdas, como su fuente, bordes, fórmulas, etc.
Por ejemplo, puede establecer el tipo de letra de una celda en Negrita de esta manera:
Range("A1").Font.Bold = True
También puede establecer la fórmula de una celda:
Range(“A1”).Formula = "=Sum(A2:A10)"
En Excel, puedes seleccionar un bloque de celdas con el cursor (por ejemplo, de A1 a D10) y ponerlas todas en negrita. Los objetos de rango pueden acceder a bloques de celdas de esta manera:
Range("A1:D10").Font.Bold = True
También puedes referirte a varias celdas/bloques a la vez:
Range("A1:D10,A12:D12,G1").Font.Bold = True
El formato para esto es el mismo que el que utilizarías al seleccionar celdas para la fórmula SUM() en Excel. Cada bloque se separa con una coma, y los bloques se denotan con las celdas superior izquierda e inferior derecha separadas con dos puntos.
Por último, los objetos Range tienen métodos incorporados para realizar operaciones comunes en una hoja de cálculo. Por ejemplo, puedes querer copiar algunos datos de un lugar a otro. He aquí un ejemplo:
Range("A1:D10").Copy
Range("F1").PasteSpecial xlPasteValues
Range("F1").PasteSpecial xlPasteFormats
Esto copia las celdas A1:D10 al portapapeles, y luego hace un PasteSpecial() comenzando en la celda C1 – tal como lo harías manualmente en Excel. Ten en cuenta que este ejemplo muestra cómo usar PasteSpecial() para pegar sólo Valores y Formatos – hay parámetros para todas las opciones que verías en el diálogo de Pegar Especial.
Este es un ejemplo de cómo pegar «Todo» en otra hoja de cálculo:
Range("A1:D10").Copy
Sheets("Sheet2").Range(“A1”).PasteSpecial xlPasteAll
Sentencias If
Con una sentencia If, puede hacer que una sección de código se ejecute sólo «si» una determinada sentencia es verdadera.
Por ejemplo, puede querer poner una celda en negrita y colorearla en rojo, pero sólo «si» el valor de la celda es menor que 100.
If Range("A4").Value < 100 Then
Range("A4").Font.Bold = True
Range("A4").Interior.Color = vbRed
End If
La estructura adecuada de una sentencia If es la siguiente (los corchetes indican componentes opcionales):
If <condición> Then
[ElseIf <otra condición> Then]
[Else]
End If
Puede incluir tantos bloques ElseIf como desee para probar múltiples condiciones. También puede añadir un bloque Else que sólo se ejecute si no se cumple ninguna de las otras condiciones de la sentencia If.
Aquí hay otro ejemplo basado en el anterior, donde la celda se formatea de varias maneras diferentes dependiendo del valor:
If Range("A4").Value < 100 Then
Range("A4").Font.Bold = True
Range("A4").Interior.Color = vbRed
ElseIf Range("A4").Value < 200 Then
Range("A4").Font.Bold = False
Range("A4").Interior.Color = vbYellow
Else
Range("A4").Font.Bold = False
Range("A4").Interior.Color = vbGreen
End If
En el ejemplo anterior, la celda no está en negrita en los bloques ElseIf en los que el valor no es inferior a 100. Puede anidar las sentencias If para evitar la duplicación de código, así:
If Range("A4").Value < 100 Then
Range("A4").Font.Bold = True
Range("A4").Interior.Color = vbRed
Else
Range("A4").Font.Bold = False 'Quitar negrilla de la fuente una sola vez
If Range("A4").Value < 200 Then
Range("A4").Interior.Color = vbYellow
Else
Range("A4").Interior.Color = vbGreen
End If
End If
Variables
Una variable es una pieza de memoria utilizada para almacenar información temporal mientras se ejecuta una macro. A menudo se utilizan en los bucles como iteradores, o para mantener el resultado de una operación que desea utilizar varias veces a lo largo de una macro.
Aquí hay un ejemplo de una variable y cómo podrías usarla:
Sub ExtractSerialNumber()
Dim strSerial As String ' Está es la declaración de la variable
' "Como Cadena" significa que esta variable está pensada para almacenar texto
' establecer un número de serie ficticio:
Range("A4").Value = "serial# 804567-88"
' analizar el número de serie de la celda A4 y asignarlo a la variable
strSerial = Mid(Range("A4").Value, 9)
' ahora utiliza la variable dos veces, en lugar de tener que analizar el número de serie dos veces
Range("B4").Value = strSerial
MsgBox strSerial
End Sub
En este ejemplo básico, la variable ‘strSerial’ se utiliza para extraer el número de serie de la celda A4 utilizando la función Mid(), y luego se utiliza en otros dos lugares.
La forma estándar de declarar una variable es la siguiente: Dim CualquierNombre [As tipo]
- CualquierNombre es el nombre que decidas darle a tu variable
- tipo es el tipo de datos de la variable
La parte «[As tipo]» puede omitirse – si es así, la variable se declara como un tipo Variant, que puede contener cualquier tipo de datos. Aunque son perfectamente válidos, los tipos Variant deben evitarse, ya que pueden conducir a resultados inesperados si no se tiene cuidado.
Hay reglas para los nombres de las variables. ¡Tienen que empezar con una letra o un carácter de subrayado, no pueden tener espacios, puntos, comas, comillas o los caracteres «! @ & $ #».
Aquí hay algunos ejemplos de declaraciones de variables:
Dim strFilename As String ' buen estilo de nombre - descriptivo y usa prefijo
Dim i As Long ' mal estilo de nombre - aceptable sólo para algunos iteradores
Dim SalePrice As Double ' buen estilo de nombre - descriptivo, pero no usa prefijo
Dim iCounter ' nombre correcto - no demasiado descriptivo, usa prefijo, no tiene tipo de datos
Todos estos ejemplos utilizan esquemas de nomenclatura ligeramente diferentes, pero todos son válidos. No es mala idea anteponer al nombre de una variable una forma abreviada de su tipo de datos (como en algunos de estos ejemplos), ya que hace que tu código sea más legible a simple vista.
VBA incluye muchos tipos de datos básicos. Los más populares son:
- String (utilizado para almacenar los datos de texto)
- Long (utilizado para contener números enteros, es decir, sin decimales)
- Double (utilizado para contener números de punto flotante, es decir, decimales)
Una lista completa de los tipos de datos intrínsecos de VBA se puede encontrar aquí: https://docs.microsoft.com/en-us/office/vba/language/reference/user-interface-help/data-type-summary
Variables del Objeto Range
También es posible crear variables que hagan referencia a objetos de rango. Esto es útil si quieres referirte a un rango específico en tu código en varios lugares – de esa manera si necesitas cambiar el rango, sólo necesitas cambiarlo en un lugar.
Cuando crea una variable de objeto Range, tiene que «establecerla» a una instancia de un Range. Por ejemplo:
Dim rMyRange As Range
Set rMyRange = Range("A1:A10;D1:J10")
Si se omite la sentencia «Set» al asignar una variable Range, se producirá un error.
Bucles
Los bucles son bloques que repiten el código dentro de ellos un cierto número de veces. Son útiles para reducir la cantidad de código que tienes que escribir, y te permiten escribir una pieza de código que realiza las mismas acciones en muchos elementos diferentes relacionados.
For-Next
Un bloque For-Next es un bucle que se repite un cierto número de veces. Utiliza una variable como iterador para contar cuántas veces se ha ejecutado, y esta variable iteradora puede utilizarse dentro del bucle. Esto hace que los bucles For-Next sean muy útiles para iterar a través de celdas o matrices.
Aquí hay un ejemplo que hace un bucle a través de las celdas en las filas 1 a 100, columna 1, y establece sus valores al valor de la variable iteradora:
Dim i As Long
For i = 1 To 100
Cells(i, 1).Value = i
Next i
La línea «For i = 1 To 100» significa que el bucle comienza desde el 1 y termina después del 100. Puede establecer cualquier número de inicio y final que desee; también puede utilizar variables para estos números.
Por defecto, los bucles For-Next cuentan por 1. Si quiere contar por un número diferente, puede escribir el bucle con una cláusula Step explícita:
For i = 5 a 100 Step 5
Este bucle empezará en 5, y luego añadirá 5 a ‘i’ cada vez que el bucle se repita (así que ‘i’ será 10 en la segunda repetición, 15 en la tercera, y así sucesivamente).
Usando Step, puedes hacer que un bucle cuente hacia atrás también:
For i = 100 a 1 Step -1
También puede anidar bucles For-Next. Cada bloque requiere su propia variable para contar, pero puedes usar esas variables donde quieras. Aquí hay un ejemplo de la utilidad de esto en Excel VBA:
Dim i As Long, j As Long
For i = 1 To 100
For j = 1 To 100
Cells(i, j).Value = i * j
Next j
Next i
Esto le permite hacer un bucle a través de las filas y las columnas.
ADVERTENCIA: aunque está permitido, NUNCA debe MODIFICAR la variable del iterador dentro de un bloque For-Next, ya que utiliza ese iterador para seguir el bucle. Modificar el iterador puede causar un bucle infinito y colgar su macro. Por ejemplo:
For i = 1 To 100
i = 1
Next i
En este bucle, ‘i’ nunca llegará más allá de 2 antes de ser reiniciado a 1, y el bucle se repetirá para siempre.
For-Each
Los bloques For-Each son muy similares a los bloques For-Next, excepto que no utilizan un contador para especificar cuántas veces se repite el bucle. En cambio, un bloque For-Each toma una «colección» de objetos (como un rango de celdas) y se ejecuta tantas veces como objetos haya en esa colección.
He aquí un ejemplo:
Dim r As Range
For Each r In Range("A15:J54")
If r.Value > 0 Then
r.Font.Bold = True
End If
Next r
Observe el uso de la variable de objeto Range ‘r’. Esta es la variable iteradora utilizada en el bucle For-Each – cada vez que pasa por el bucle, ‘r’ obtiene una referencia a la siguiente celda del Range.
Una ventaja de utilizar los bucles For-Each en Excel VBA es que puede recorrer todas las celdas de un rango sin anidar bucles. Esto puede ser útil si necesita hacer un bucle a través de todas las celdas de un rango complejo como Range(«A1:D12,J13, M1:Y12»).
Una desventaja de los bucles For-Each es que no tienes control sobre el orden en que se procesan las celdas. Aunque en la práctica Excel recorrerá las celdas en orden, en teoría podría procesar las celdas en un orden completamente aleatorio. Si necesitas procesar las celdas en un orden particular, deberías utilizar los bucles For-Next en su lugar.
Do-Loop
Mientras que los bloques For-Next utilizan contadores para saber cuándo parar, los bloques Do-Loop se ejecutan hasta que se cumpla una condición. Para ello, se utiliza una cláusula Until al principio o al final del bloque, que comprueba la condición y hace que el bucle se detenga cuando se cumpla dicha condición.
Ejemplo:
Dim str As String
str = "Buffalo"
Do Until str = “Buffalo Buffalo Buffalo Buffalo Buffalo Buffalo Buffalo”
str = str & " " & "Buffalo"
Loop
Range("A1").Value = str
En este bucle, «Búfalo» se concatena con ‘str’ cada vez que pasa por el bucle hasta que coincide con la sentencia esperada. En este caso, la prueba se realiza al principio del bucle – si ‘str’ ya fuera la frase esperada (que no lo es porque no lo empezamos así, pero si) el bucle ni siquiera se ejecutaría.
Puedes hacer que el bucle se ejecute al menos una vez moviendo la cláusula Until al final, así:
Do
str = str & " " & "Buffalo"
Loop Until str = “Buffalo Buffalo Buffalo Buffalo Buffalo Buffalo Buffalo”
Puedes usar cualquier versión que tenga sentido en tu macro.
ADVERTENCIA: puede causar un bucle infinito con un bloque Do-Loop si la condición Until nunca se cumple. Escriba siempre su código de manera que la condición Until se cumpla definitivamente cuando utilice este tipo de bucle.
¿Qué es lo Siguiente?
Una vez que hayas comprendido lo básico, ¿por qué no intentas aprender algunas técnicas más avanzadas? Nuestro tutorial en https://www.automateexcel.com/excel/learn-vba-tutorial/ se basará en todo lo que ha aprendido aquí y ampliará sus habilidades con Eventos, UserForms, optimización de código y mucho más