Excel VBA Loops – For Each, For Next, Do While, Aninhados e Mais
In this Article
Para trabalhar com eficiência no VBA, você precisa entender os loops.
Os loops permitem repetir um bloco de código um número definido de vezes ou repetir um bloco de código em cada objeto de um conjunto de objetos.
Primeiro, apresentaremos alguns exemplos para mostrar do que os loops são capazes. Em seguida, ensinaremos tudo sobre loops.
Exemplos Rápidos de Loops do VBA
Loops For Each
Os loops For Each percorrem todos os objetos de uma coleção, como todas as planilhas da pasta de trabalho ou todas as células de um intervalo.
Loop em Todas as Planilhas da Pasta de Trabalho
Esse código percorrerá todas as planilhas da pasta de trabalho, exibindo cada uma delas:
Sub LoopPelasPlanilhas()
Dim ws As Worksheet
For Each ws In Worksheets
ws.Visible = True
Next
End Sub
Percorrer todas as células do intervalo
Esse código percorrerá um intervalo de células, testando se o valor da célula é negativo, positivo ou zero:
Sub LoopComCondicional()
Dim Cell as Range
For Each Cell In Range("A2:A6")
If Cell.Value > 0 Then
Cell.Offset(0, 1).Value = "Positivo"
ElseIf Cell.Value < 0 Then
Cell.Offset(0, 1).Value = "Negativo"
Else
Cell.Offset(0, 1).Value = "Zero"
End If
Next Cell
End Sub
Loops For Next
Outro tipo de loop “For” é o loop For Next. O loop For Next permite que você faça um loop entre números inteiros
Esse código percorrerá os números inteiros de 1 a 10, exibindo cada um deles em uma caixa de mensagem:
Sub LoopFor()
Dim i As Integer
For i = 1 To 10
MsgBox i
Next i
End Sub
Loops Do While
Os loops Do While farão um loop enquanto uma condição for atendida. Esse código também percorrerá os números inteiros de 1 a 10, exibindo cada um deles em uma caixa de mensagem.
Sub LoopDoWhile()
Dim n As Integer
n = 1
Do While n < 11
MsgBox n
n = n + 1
Loop
End Sub
Loops Do Until
Por outro lado, os loops Do Until fazem um loop até que uma condição seja atendida. Esse código faz a mesma coisa que os dois exemplos anteriores.
Sub LoopDoUntil()
Dim n As Integer
n = 1
Do Until n >= 10
MsgBox n
n = n + 1
Loop
End Sub
Discutiremos isso a seguir, mas você precisa ser extremamente cuidadoso ao criar loops Do While ou Do Until para não criar um loop interminável.
Criador de loops VBA
Esta é uma captura de tela do “Loop Builder” do nosso suplemento Premium VBA: AutoMacro. O Loop Builder permite que você crie loops de forma rápida e fácil para percorrer diferentes objetos ou números. Você pode executar ações em cada objeto e/ou selecionar apenas objetos que atendam a determinados critérios.
O suplemento também contém muitos outros construtores de código, uma extensa biblioteca de código VBA e uma variedade de ferramentas de codificação. É um item obrigatório para qualquer desenvolvedor de VBA.
Agora, abordaremos em profundidade os diferentes tipos de loops.
VBA For Next Loop
Sintaxe do For Loop
O For Next Loop permite que você repita um bloco de código um número especificado de vezes. A sintaxe é a seguinte:
[Dim Contador as Long]
For Contador = Inicio to Fim [Valor do Step]
[Faça algo]
Next [Contador]
Em que os itens entre colchetes são opcionais.
- [Dim Contador as Long] – Declara a variável contador. Necessário se a Option Explicit for declarada na parte superior do módulo.
- Contador – Uma variável inteira usada para contar
- Inicio – O valor inicial (ex.: 1)
- Fim – O valor final (Ex. 10)
- [Valor do Step] – Permite que você conte a cada n números inteiros em vez de cada 1 número inteiro. Você também pode fazer o inverso com um valor negativo (ex. Step -1)
- [Faça algo] – O código que será repetido
- Next [Contador] – Declaração de fechamento do loop For Next. Você pode incluir ou não o contador. No entanto, recomendo enfaticamente a inclusão do contador, pois isso facilita a leitura do código.
Se isso for confuso, não se preocupe. Vamos analisar alguns exemplos:
Contagem até 10
Esse código contará até 10 usando um loop For-Next:
Sub ForEach_ContarAte10()
Dim n As Integer
For n = 1 To 10
MsgBox n
Next n
End Sub
Etapa do Loop For
Contar até 10 – somente números pares
Esse código contará até 10 contando apenas números pares:
Sub ForEach_ContarAte10_Pares()
Dim n As Integer
For n = 2 To 10 Step 2
MsgBox n
Next n
End Sub
Observe que adicionamos “Step 2”. Isso diz ao For Loop para “avançar” no contador em 2. Também podemos usar um valor de passo negativo para avançar no sentido inverso:
Passo do Loop For – Inverso
Contagem Regressiva a Partir de 10
Esse código fará a contagem regressiva a partir de 10:
Sub ForEach_Contagem_Regressiva()
Dim n As Integer
For n = 10 To 1 Step -1
MsgBox n
Next n
MsgBox "Decolar"
End Sub
Excluir Linhas se a Célula Estiver em Branco
Na maioria das vezes, utilizo um For-Loop de etapa negativa para percorrer intervalos de células, excluindo as linhas que atendem a determinados critérios. Se você fizer um loop das linhas superiores para as inferiores, ao excluir as linhas, o contador ficará confuso.
Este exemplo excluirá as linhas com células em branco (começando pela linha inferior):
Sub ForEach_ApagarLinhas_CelulasEmBranco()
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
Loop For Aninhado
Você pode “aninhar” um For Loop dentro de outro For Loop. Usaremos os For Loops aninhados para criar uma tabela de multiplicação:
Sub ForEach_Aninhado_TabelaMultiplicacao()
Dim row As Integer, col As Integer
For row = 1 To 9
For col = 1 To 9
Cells(row + 1, col + 1).Value = row * col
Next col
Next row
End Sub
Exit For
A instrução Exit For permite que você saia imediatamente de um loop For Next.
Normalmente, você usaria Exit For junto com uma instrução If, saindo do loop For Next se uma determinada condição for atendida.
Por exemplo, você pode usar um For Loop para localizar uma célula. Quando essa célula for encontrada, você poderá sair do loop para acelerar o código.
Esse código percorrerá as linhas de 1 a 1000, procurando por “erro” na coluna A. Se for encontrado, o código selecionará a célula, alertará você sobre o erro encontrado e sairá do loop:
Sub Loop_ExitFor()
Dim i As Integer
For i = 1 To 1000
If Range("A" & i).Value = "erro" Then
Range("A" & i).Select
MsgBox "Erro Encontrado"
Exit For
End If
Next i
End Sub
Importante: no caso de loops For aninhados, Exit For sai apenas do loop For atual, não de todos os loops ativos.
Continue For
O VBA não tem o comando “Continue” encontrado no Visual Basic. Em vez disso, você precisará usar “Exit”.
VBA For Each Loop
O loop For Each do VBA percorrerá todos os objetos de uma coleção:
- Todas as células em um intervalo
- Todas as planilhas em uma pasta de trabalho
- Todas as formas em uma planilha
- Todas as pastas de trabalho abertas
Você também pode usar loops For Each aninhados para:
- Todas as células em um intervalo em todas as planilhas
- Todas as formas em todas as planilhas
- Todas as planilhas em todas as pastas de trabalho abertas
- e assim por diante…
A sintaxe é a seguinte:
For Each Object in Collection
[Faça Algo]
Next [Object]
Onde:
- Object – Variável que representa um intervalo, uma planilha, uma pasta de trabalho, uma forma etc. (ex.: rng)
- Collection – Coleção de objetos (por exemplo, Range(“a1:a10”)
- [Faça Algo] – Bloco de código a ser executado em cada objeto
- Next [Object] – Declaração de encerramento. [Object] é opcional, mas altamente recomendado.
Para Cada Célula no Intervalo
Esse código percorrerá cada célula em um intervalo:
Sub ParaCadaCelula_NoIntervalo()
Dim celula As Range
For Each celula In Range("a1:a10")
celula.Value = celula.Offset(0,1).Value
Next celula
End Sub
Para Cada Planilha na Pasta de Trabalho
Esse código percorrerá todas as planilhas em uma pasta de trabalho, desprotegendo cada planilha:
Sub ParaCadaPanilha_NaPasta()
Dim ws As Worksheet
For Each ws In Worksheets
ws.Unprotect "senha"
Next ws
End Sub
Para Cada Pasta de Trabalho Aberta
Esse código salvará e fechará todas as pastas de trabalho abertas:
Sub ParaCadaPasta_EmWorkbooks()
Dim wb As Workbook
For Each wb In Workbooks
wb.Close SaveChanges:=True
Next wb
End Sub
Para Cada Forma na Planilha
Esse código excluirá todas as formas na planilha ativa.
Sub ParaCadaForma()
Dim shp As Shape
For Each shp In ActiveSheet.Shapes
shp.Delete
Next shp
End Sub
Para Cada Forma em Cada Planilha da Pasta de Trabalho
Você também pode aninhar loops For Each. Aqui, percorreremos todas as formas em todas as planilhas da pasta de trabalho ativa:
Sub ParaCadaForma_EmTodasPlanilhas()
Dim shp As Shape, ws As Worksheet
For Each ws In Worksheets
For Each shp In ws.Shapes
shp.Delete
Next shp
Next ws
End Sub
For Each – Loop IF (Condicional)
Como mencionamos anteriormente, você pode usar uma instrução If em um loop, executando ações somente se determinados critérios forem atendidos.
Esse código ocultará todas as linhas em branco em um intervalo:
Sub ParaCadaCelula_NoIntervalo()
Dim cell As Range
For Each cell In Range("a1:a10")
If cell.Value = "" Then _
cell.EntireRow.Hidden = True
Next cell
End Sub
Loop Do While do VBA
O Do While e o Do Until do VBA (consulte a próxima seção) são muito semelhantes. Eles repetem um loop enquanto (ou até) uma condição for atendida.
O Do While Loop repetirá um loop enquanto uma condição for atendida.
Aqui está a sintaxe do Do While:
Do While Condição
[Faça algo]
Loop
Onde:
- Condição – A condição a ser testada
- [Faça algo] – O bloco de código a ser repetido
Você também pode configurar um loop Do While com a Condição no final do loop:
Do
[Faça algo]
Loop While Condição
Demonstraremos cada um deles e mostraremos como eles diferem:
Do While
Aqui está o exemplo do loop Do While que demonstramos anteriormente:
Sub LoopDoWhile()
Dim n As Integer
n = 1
Do While n < 11
MsgBox n
n = n + 1
Loop
End Sub
Loop While
Agora vamos executar o mesmo procedimento, mas moveremos a condição para o final do loop:
Sub DoLoopWhile()
Dim n As Integer
n = 1
Do
MsgBox n
n = n + 1
Loop While n < 11
End Sub
Loop Do Until do VBA
Os loops Do Until repetem um loop até que uma determinada condição seja atendida. A sintaxe é essencialmente a mesma dos loops Do While:
Do Until Condição
[Faça Algo]
Loop
e, da mesma forma, a condição pode estar no início ou no final do loop:
Do
[Faça algo]
Loop Until Condicao
Do Until
Esse loop Do Until contará até 10, como em nossos exemplos anteriores
Sub LoopDoUntil()
Dim n As Integer
n = 1
Do Until n > 10
MsgBox n
n = n + 1
Loop
End Sub
Loop Until
Este loop Loop Until contará até 10:
Sub DoLoopUntil()
Dim n As Integer
n = 1
Do
MsgBox n
n = n + 1
Loop Until n > 10
End Sub
Sair do Loop Do
Da mesma forma que usar Exit For para sair de um loop For, você usa o comando Exit Do para sair de um loop Do imediatamente
Exit Do
Aqui está um exemplo de Exit Do:
Sub Sair_LoopDo()
Dim i As Integer
i = 1
Do Until i > 1000
If Range("A" & i).Value = "erro" Then
Range("A" & i).Select
MsgBox "Erro Encontrado"
Exit Do
End If
i = i + 1
Loop
End Sub
Finalizar ou Interromper o Loop
Como mencionamos acima, você pode usar Exit For ou Exit Do para encerrar loops:
Exit For
Exit Do
Entretanto, esses comandos devem ser adicionados ao seu código antes de executar o loop.
Se estiver tentando “interromper” um loop que está em execução, tente pressionar ESC ou CTRL + Pause Break no teclado. Entretanto, isso pode não funcionar. Se não funcionar, você precisará aguardar o término do loop ou, no caso de um loop infinito, usar CTRL + ALT + Delete para forçar o fechamento do Excel.
É por isso que tento evitar loops Do, pois é mais fácil criar acidentalmente um loop infinito, forçando-o a reiniciar o Excel e, potencialmente, perder seu trabalho.
Mais Exemplos de Loop
Loop Através de Linhas
Isso fará um loop por todas as linhas em uma coluna:
Public Sub LoopAtravesLinhas()
Dim cell As Range
For Each cell In Range("A:A")
If cell.value <> "" Then MsgBox cell.address & ": " & cell.Value
Next cell
End Sub
Loop Através de Colunas
Isso fará um loop por todas as colunas em uma linha:
Public Sub LoopAtravesColunas()
Dim cell As Range
For Each cell In Range("1:1")
If cell.Value <> "" Then MsgBox cell.Address & ": " & cell.Value
Next cell
End Sub
Percorrer Arquivos em uma Pasta
Esse código percorrerá todos os arquivos em uma pasta, criando uma lista:
Sub PercorrerArquivos ()
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
Loop Através da Matriz
Este código percorrerá a matriz ‘arrList’:
For i = LBound(arrList) To UBound(arrList)
MsgBox arrList(i)
Next i
A função LBound obtém o “limite inferior” da matriz e a UBound obtém o “limite superior”.
Loops no Access VBA
A maioria dos exemplos acima também funcionará no Access VBA. Entretanto, no Access, fazemos um loop no objeto Recordset em vez de no objeto Range.
Sub LoopAtravesRegistros()
On Error Resume Next
Dim dbs As Database
Dim rst As Recordset
Set dbs = CurrentDb
Set rst = dbs.OpenRecordset("tblClientes", dbOpenDynaset)
With rst
.MoveLast
.MoveFirst
Do Until .EOF = True
MsgBox (rst.Fields("NomeCliente"))
.MoveNext
Loop
End With
rst.Close
Set rst = Nothing
Set dbs = Nothing
End Sub