Bucles VBA de Excel – For Each, For Next, Do While, Bucles Anidados y Más
In this Article
- Ejemplos Rápidos de Bucles VBA
- Constructor de Bucles VBA
- Bucle For Next de VBA
- Bucle For Each de VBA
- Bucle For Each para recorrer cada celda del rango
- Bucle For Each para recorrer cada hoja en el libro de trabajo
- Bucle For Each para recorrer cada libro de trabajo abierto
- Bucle For Each para recorrer cada forma en la hoja de trabajo
- Bucle For Each para recorrer cada forma en cada hoja de trabajo en el libro de trabajo
- For Each – Bucle IF
- Bucle Do While de VBA
- Bucle Do Until de VBA
- Salir del Bucle Do
- Finalizar o romper el bucle
- Más Ejemplos de Bucles
- Bucles en Access VBA
Para trabajar efectivamente en VBA, debe entender los bucles. Los bucles le permiten repetir un bloque de código un número determinado de veces o repetir un bloque de código en cada objeto de un conjunto de objetos.
Primero le mostraremos algunos ejemplos para enseñarle de qué son capaces los bucles. Luego le enseñaremos todo sobre los bucles.
Ejemplos Rápidos de Bucles VBA
Bucles For Each
Los bucles For Each recorren cada objeto de una colección, como cada hoja de trabajo del libro o cada celda de un rango.
Recorrer todas las hojas de trabajo del libro de trabajo
Este código hará un bucle a través de todas las hojas de trabajo en el libro de trabajo, desocultando cada hoja:
Sub BucleAtravesdeHojas()
Dim hoja As Worksheet
For Each hoja In Worksheets
hoja.Visible = True
Next
End Sub
Recorrer todas las celdas del rango
Este código recorrerá un rango de celdas, probando si el valor de la celda es negativo, positivo o cero:
Sub BucleIf()
Dim Celda As Range
For Each Celda In Range("A2:A6")
If Celda.Value > 0 Then
Celda.Offset(0, 1).Value = "Positivo"
ElseIf Celda.Value < 0 Then
Celda.Offset(0, 1).Value = "Negativo"
Else
Celda.Offset(0, 1).Value = "Cero"
End If
Next Celda
End Sub
Bucles For Next
Otro tipo de bucle «For» es el bucle For Next. El bucle For Next le permite hacer un bucle a través de enteros. Este código hará un bucle a través de los enteros del 1 al 10, mostrando cada uno con un cuadro de mensaje:
Sub BucleForNext()
Dim i As Integer
For i = 1 To 10
MsgBox i
Next i
End Sub
Bucles Do While
Los bucles Do While hacen un bucle mientras se cumple una condición. Este código también hará un bucle a través de los enteros del 1 al 10, mostrando cada uno con un cuadro de mensaje.
Sub BucleDoWhile()
Dim n As Integer
n = 1
Do While n < 11
MsgBox n
n = n + 1
Loop
End Sub
Bucles Do Until
A la inversa, los bucles Do Until harán un bucle hasta que se cumpla una condición. Este código hace lo mismo que los dos ejemplos anteriores.
Sub BucleDoUntilLoop()
Dim n As Integer
n = 1
Do Until n >= 10
MsgBox n
n = n + 1
Loop
End Sub
Discutiremos esto más adelante, pero debe tener mucho cuidado cuando cree bucles Do While o Do Until para no crear un bucle interminable.
Constructor de Bucles VBA
Esta es una captura de pantalla del «Constructor de Bucles» de nuestro Complemento VBA Premium : AutoMacro. El Constructor de Bucles le permite construir rápida y fácilmente bucles para recorrer diferentes objetos o números. Puede realizar acciones en cada objeto y/o seleccionar sólo los objetos que cumplan ciertos criterios. El complemento también contiene muchos otros constructores de código, una extensa biblioteca de código VBA y una variedad de herramientas de codificación. Es una herramienta imprescindible para cualquier desarrollador de VBA. Ahora cubriremos los diferentes tipos de bucles en profundidad.
Bucle For Next de VBA
Sintaxis del Bucle For
El bucle For Next le permite repetir un bloque de código un número específico de veces. La sintaxis es:
[Dim contador As Long]
For contador = Inicio to Fin [Valor de Paso]
[Hacer Algo]
Next [contador]
Donde los elementos entre paréntesis son opcionales.
- [Dim Contador As Long] – Declara la variable contador. Se requiere si la opción explícita se declara en la parte superior de su módulo.
- Contador – Una variable entero largo utilizada para contar
- Inicio – El valor inicial (Ej. 1)
- Fin – El valor final (Ej. 10)
- [Valor de paso ] – Le permite contar cada n enteros en lugar de cada 1 entero. También puede ir a la inversa con un valor negativo (Ej. Paso -1)
- [Hacer algo ] – El código que se repetirá
- Next [contador] – Declaración de cierre del bucle For Next. Puede incluir el contador o no. Sin embargo, recomiendo incluir el contador ya que hace que su código sea más fácil de leer.
Si eso es confuso, no te preocupes. Revisaremos algunos ejemplos:
Contar hasta 10
Este código contará hasta 10 usando un bucle For-Next:
Sub BucleForEach_ContarHasta10()
Dim n As Integer
For n = 1 To 10
MsgBox n
Next n
End Sub
Paso del bucle For
Contar hasta 10 – Sólo números pares
Este código contará hasta 10 sólo contando los números pares:
Sub BucleForEach_ContarHasta10_Pares()
Dim n As Integer
For n = 2 To 10 Step 2
MsgBox n
Next n
End Sub
Observe que hemos añadido «Step 2». Esto le dice al bucle For que «pase» por el contador de 2 en 2. También podemos usar un valor de paso negativo para pasar al revés:
Paso del Bucle For – Inverso
Cuenta atrás desde 10
Este código hará la cuenta atrás desde 10:
Sub ForEach_Countdown_Inverse()
Dim n As Integer
For n = 10 To 1 Step -1
MsgBox n
Next n
MsgBox "Despegue"
End Sub
Borrar Filas si la Celda está en Blanco
La mayoría de las veces he utilizado un bucle For-Loop de paso negativo para hacer un bucle a través de rangos de celdas, eliminando las filas que cumplen ciertos criterios. Si haces un bucle desde las filas superiores a las inferiores, a medida que eliminas filas desordenarás tu contador. Este ejemplo borrará las filas con celdas en blanco (empezando por la fila inferior):
Sub BucleForEach_BorrarFilasEnBlanco()
Dim n As Integer
For n = 10 To 1 Step -1
If Range("A" & n).Value = "" Then
Range("A" & n).EntireRow.Delete
End If
Next n
End Sub
Bucle For anidado
Puede «anidar» un bucle For dentro de otro bucle For. Utilizaremos los bucles For anidados para crear una tabla de multiplicación:
Sub Nested_ForEach_MultiplicationTable()
Dim row As Integer, col As Integer
Para row = 1 a 9
Para col = 1 a 9
Cells(row + 1, col + 1).Value = row * col
Siguiente col
Siguiente fila
End Sub
Exit For
La sentencia Exit For permite salir inmediatamente de un bucle For Next. Normalmente se utiliza Exit For junto con una sentencia If, saliendo del bucle For Next si se cumple una determinada condición. Por ejemplo, puede utilizar un bucle For para encontrar una celda. Una vez que la celda es encontrada, puede salir del bucle para acelerar su código. Este código hará un bucle a través de las filas 1 a 1000, buscando el «error» en la columna A. Si lo encuentra, el código seleccionará la celda, le avisará del error encontrado y saldrá del bucle:
Sub SalidaDeFor_Loop()
Dim i As Integer
For i = 1 To 1000
If Range("A" & i).Value = "error" Then
Range("A" & i).Select
MsgBox "Error Encontrado"
Exit For
End If
Next i
End Sub
Importante: En el caso de los bucles For anidados, Exit For sólo sale del bucle For actual, no de todos los bucles activos.
Continue For
VBA no tiene el comando «Continue» que se encuentra en Visual Basic. En su lugar, necesitará usar «Exit».
Bucle For Each de VBA
El Bucle For Each de VBA recorrerá todos los objetos de una colección:
- Todas las celdas de un rango
- Todas las hojas de trabajo de un libro
- Todas las formas en una hoja de trabajo
- Todos los libros de trabajo abiertos
También puede utilizar bucles For Each anidados para:
- Todas las celdas de un rango en todas las hojas de trabajo
- Todas las formas de todas las hojas de trabajo
- Todas las hojas de todos los libros de trabajo abiertos
- y así sucesivamente…
La sintaxis es:
For Each Objeto in Collection
[Hacer algo]
Next [Objeto]
Donde:
- Objeto – Variable que representa un rango, hoja de trabajo, libro de trabajo, forma, etc. (ej. rng)
- Colección – Colección de objetos (ej. Rango(«a1:a10»)
- [Hacer algo ] – Bloque de código a ejecutar en cada objeto
- Next [ Objeto] – Declaración de cierre. [Objeto] es opcional, pero se recomienda encarecidamente.
Bucle For Each para recorrer cada celda del rango
Este código recorrerá cada celda de un rango:
Sub ForEachCelda_enRange()
Dim celda As Range
For Each celda In Range("a1:a10")
celda.Value = cell.Offset(0,1).Value
Next celda
End Sub
Bucle For Each para recorrer cada hoja en el libro de trabajo
Este código hará un bucle a través de todas las hojas de trabajo en un libro de trabajo, desprotegiendo cada hoja:
Sub ForEachHoja_enLibro()
Dim hoja As Worksheet
For Each hoja In Worksheets
hoja.Unprotect "password"
Next hoja
End Sub
Bucle For Each para recorrer cada libro de trabajo abierto
Este código guardará y cerrará todos los libros de trabajo abiertos:
Sub ForEachLibro_enLibros()
Dim libro As Workbook
For Each libro In Workbooks
libro.Close SaveChanges:=True
Next libro
End Sub
Bucle For Each para recorrer cada forma en la hoja de trabajo
Este código borrará todas las formas en la hoja activa.
Sub ForEachForma()
Dim forma As Shape
For Each forma In ActiveSheet.Shapes
forma.Delete
Next forma
End Sub
Bucle For Each para recorrer cada forma en cada hoja de trabajo en el libro de trabajo
También puede anidar los bucles For Each. Aquí haremos un bucle a través de todas las formas en todas las hojas de trabajo en el libro de trabajo activo:
Sub ForEachForma_enTodasLasHojas()
Dim forma As Shape, hoja As Worksheet
For Each hoja In Worksheets
For Each forma In hoja.Shapes
forma.Delete
Next forma
Next hoja
End Sub
For Each – Bucle IF
Como hemos mencionado antes, puede utilizar una sentencia If dentro de un bucle, realizando acciones sólo si se cumplen ciertos criterios. Este código ocultará todas las filas en blanco de un rango:
Sub ForEachCeldaEnRango()
Dim celda As Range
For Each celda In Range("a1:a10")
If celda.Value = "" Then _
celda.EntireRow.Hidden = True
Next celda
End Sub
Bucle Do While de VBA
Los bucles VBA Do While y Do Until (ver la siguiente sección) son muy similares. Repetirán un bucle mientras (o hasta que) se cumpla una condición. El bucle Do While repetirá un bucle mientras se cumpla una condición. Esta es la sintaxis del Do While:
Do While Condición
[Hacer algo]
Loop
Donde:
- Condición – La condición a probar
- [Hacer algo] – El bloque de código a repetir
También puede establecer un bucle Do While con la Condición al final del bucle:
Do
[Hacer algo]
Loop While Condición
Haremos una demostración de cada uno de ellos y mostraremos en qué se diferencian:
Do While
Aquí está el ejemplo del bucle Do While que demostramos anteriormente:
Sub BucleDoWhile()
Dim n As Integer
n = 1
Do While n < 11
MsgBox n
n = n + 1
Loop
End Sub
Bucle While
Ahora vamos a ejecutar el mismo procedimiento, excepto que moveremos la condición al final del bucle:
Sub BucleDoLoopWhile()
Dim n As Integer
n = 1
Do
MsgBox n
n = n + 1
Loop While n < 11
End Sub
Bucle Do Until de VBA
Los bucles Do Until repetirán un bucle hasta que se cumpla una determinada condición. La sintaxis es esencialmente la misma que la de los bucles Do While:
Do Until Condición
[Hacer algo]
Loop
y de forma similar la condición puede ir al principio o al final del bucle:
Do
[Hacer Algo]
Loop Until Condición
Do Until
Este bucle Do Until contará hasta 10, como nuestros ejemplos anteriores
Sub BucleDoUntil()
Dim n As Integer
n = 1
Do Until n > 10
MsgBox n
n = n + 1
Loop
End Sub
Bucle Loop Until
Este bucle Loop Until contará hasta 10:
Sub BucleDoLoopUntil()
Dim n As Integer
n = 1
Do
MsgBox n
n = n + 1
Loop Until n > 10
End Sub
Salir del Bucle Do
De forma similar al uso de Exit For para salir de un bucle For, se utiliza el comando Exit Do para salir de un bucle Do inmediatamente
Exit Do
Aquí hay un ejemplo de Exit Do:
Sub EjemploExitDo_Loop()
Dim i As Integer
i = 1
Do Until i > 1000
If Range("A" & i).Value = "error" Then
Range("A" & i).Select
MsgBox "Error Encontrado"
Exit Do
End If
i = i + 1
Loop
End Sub
Finalizar o romper el bucle
Como mencionamos anteriormente, puedes usar el Exit For o Exit Do para salir de los bucles:
Exit For
Exit Do
Sin embargo, estos comandos deben ser añadidos a su código antes de ejecutar su bucle. Si está tratando de «romper» un bucle que se está ejecutando actualmente, puede intentar presionar ESC o CTRL + Pause Break en el teclado. Sin embargo, esto puede no funcionar. Si no funciona, tendrás que esperar a que tu bucle termine o, en el caso de un bucle infinito, utilizar CTRL + ALT + Supr para forzar el cierre de Excel. Esta es la razón por la que trato de evitar los bucles Do, es más fácil crear accidentalmente un bucle sin fin que te obligue a reiniciar Excel, perdiendo potencialmente tu trabajo.
Más Ejemplos de Bucles
Bucle a través de las filas
Esto hará un bucle a través de todas las filas de una columna:
Sub BucleATravesdeFilas()
Dim celda As Range
For Each celda In Range("A:A")
If celda.Value <> "" Then MsgBox celda.Address & ": " & celda.Value
Next celda
End Sub
Bucle a través de las columnas
Esto hará un bucle a través de todas las columnas de una fila:
Sub BucleATravesdeColumnas()
Dim celda As Range
For Each celda In Range("1:1")
If celda.Value <> "" Then MsgBox celda.Address & ": " & celda.Value
Next celda
End Sub
Recorrer los archivos de una carpeta
Este código recorrerá todos los archivos de una carpeta, creando una lista:
Sub BucleATravesdeArchivos()
Dim oFSO As Object
Dim oFolder As Object
Dim oFile As Object
Dim i As Integer
Set oFSO = CreateObject("Scripting.FileSystemObject")
Set oFolder = oFSO.GetFolder("C:\Demo)
i = 2
For Each oFile In oFolder.Files
Range("A" & i).Value = oFile.Name
i = i + 1
Next oFile
End Sub
Bucle a través de la matriz
Este código recorrerá el array ‘arrList’:
Sub bucleATravesdeMatriz()
For i = LBound(matriz) To UBound(matriz)
MsgBox matriz(i)
Next i
End Sub
La función LBound obtiene el «límite inferior» de la matriz y UBound obtiene el «límite superior».
Bucles en Access VBA
La mayoría de los ejemplos anteriores también funcionan en Access VBA. Sin embargo, en Access, hacemos un bucle a través del objeto Recordset en lugar del objeto Range.
Sub BucleATravesdeRegistros()
On Error Resume Next
Dim dbs As Database
Dim rst As Recordset
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("tblClients", dbOpenDynaset)
With rst
.MoveLast
.MoveFirst
Do Until .EOF = True
MsgBox (rst.Fields("NombreDelCliente"))
.MoveNext
Loop
End With
rst.Close
Set rst = Nothing
Set dbs = Nothing
End Sub