Notice: This page requires JavaScript to function properly.
Please enable JavaScript in your browser settings or update your browser.
Aprenda Laços | Fundamentos de VBA
VBA do Excel para Automação Empresarial

Laços

Deslize para mostrar o menu

Até agora, cada técnica funcionou com um valor por vez. Os loops permitem aplicar a mesma lógica a vários valores em sequência — cinco produtos, quinhentos pedidos, ou quantas linhas uma tabela tiver — sem precisar copiar e colar o mesmo bloco de código repetidas vezes.

For...Next

Repete um bloco de código um número fixo e conhecido de vezes:

Dim i As Long
For i = 1 To 5
    Debug.Print "Row " & i
Next i
 
' Step lets you skip or count backward
For i = 10 To 1 Step -1
    Debug.Print i
Next i

No primeiro loop, i começa em 1, o código dentro executa uma vez com esse valor, depois i aumenta automaticamente em 1 e todo o bloco executa novamente — repetindo até que i ultrapasse 5, momento em que o loop simplesmente para e a execução continua após o Next. Step altera o incremento: Step -1 conta para baixo em vez do padrão de subir de um em um, e Step 2 contaria de dois em dois. A variável do loop i não é uma sintaxe especial — é apenas uma variável Long comum que o VBA atualiza a cada passagem.

For Each

Percorre diretamente cada item em uma coleção, sem precisar saber quantos itens existem ou gerenciar um contador manualmente:

Dim cell As Range
For Each cell In ThisWorkbook.Worksheets("Products").Range("B2:B6")
    Debug.Print cell.Value
Next cell

Aqui, cell assume cada célula individual no intervalo B2:B6 em sequência, e você lê o conteúdo dela com .Value. Compare com For...Next: com For...Next você conta números e usa esse número para buscar algo; com For Each você percorre diretamente os próprios itens, o que se torna mais natural ao trabalhar com intervalos de planilha.

Do While

Repete enquanto uma condição permanecer True — o loop não sabe de antemão quantas vezes irá rodar, o que é diferente do For...Next:

Dim stock As Integer
stock = 134
Do While stock > 0
    stock = stock - 30    ' simulate selling in batches of 30
Loop
Debug.Print stock   ' whatever's left after the loop stops

O VBA verifica stock > 0 antes de cada passagem pelo loop, inclusive na primeira. Acompanhe manualmente: 134 → 104 → 74 → 44 → 14, e então a condição é verificada novamente — 14 ainda é maior que 0, então o loop roda mais uma vez, chegando a -16. Só então stock > 0 retorna False, e o loop para com stock em -16, não exatamente em 0 ou 14. Vale a pena acompanhar cuidadosamente na primeira vez, pois é uma fonte comum de erros de um a mais ou a menos: um loop Do While continua rodando enquanto a condição for verdadeira no momento da verificação, mesmo que a ação dentro do loop ultrapasse o limite esperado.

Do Until

Existe também o Do Until, que é o oposto do Do While — repete enquanto uma condição for False e para assim que a condição se tornar True, ao invés do contrário. Qual deles soa mais natural depende de como você expressaria a regra de negócio: "continuar enquanto houver estoque" sugere Do While; "continuar até acabar o estoque" sugere Do Until — ambos podem produzir o mesmo comportamento, apenas expressos de formas opostas.

Exit Statements

Permitem sair de um loop antes do término natural da condição:

For i = 1 To 100
    If i = 10 Then Exit For   ' stop the loop immediately
    Debug.Print i
Next i

Este loop está configurado para contar até 100, mas no momento em que i chega a 10, Exit For interrompe imediatamente — nada após o Exit For é executado, e a execução salta direto para a linha após o Next i. Este é o padrão usado para buscar em uma lista e parar assim que encontrar o que procura, em vez de continuar verificando todos os itens restantes desnecessariamente.

Juntando Tudo

Todas as técnicas deste capítulo — variáveis, operadores, funções, lógica condicional e agora loops — se combinam no procedimento que este capítulo vem construindo:

Option Explicit
 
Sub CheckStockLevels()
 
    ' Sample data standing in for the Products table
    Dim products(1 To 5) As String
    Dim stockLevels(1 To 5) As Integer
    Dim reorderLevels(1 To 5) As Integer
    Dim i As Long
    Dim alertMessage As String
 
    products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20
    products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30
    products(3) = "USB-C Hub": stockLevels(3) = 44: reorderLevels(3) = 15
    products(4) = "Monitor Arm": stockLevels(4) = 18: reorderLevels(4) = 10
    products(5) = "Keyboard": stockLevels(5) = 61: reorderLevels(5) = 20
 
    alertMessage = ""
 
    For i = 1 To 5
        Select Case stockLevels(i)
            Case Is <= reorderLevels(i)
                alertMessage = alertMessage & products(i) & _
                    " — REORDER NOW" & vbNewLine
            Case Is <= reorderLevels(i) + 10
                alertMessage = alertMessage & products(i) & _
                    " — watch closely" & vbNewLine
        End Select
    Next i
 
    If alertMessage = "" Then
        MsgBox "All products are adequately stocked."
    Else
        MsgBox "Stock Alerts:" & vbNewLine & alertMessage
    End If
End Sub
Análise linha a linha
expand arrow
  • Dim products(1 To 5) As String e as duas linhas semelhantes abaixo declaram arrays — cada uma é uma linha numerada de cinco caixas em vez de uma única caixa, então products(1) é o nome do primeiro produto, products(2) o segundo, e assim por diante;
  • As cinco linhas usando dois-pontos (:) entre comandos agrupam várias atribuições em uma linha apenas para facilitar a leitura aqui — products(1) = "Laptop Stand": stockLevels(1) = 58: reorderLevels(1) = 20 é exatamente equivalente a escrever essas atribuições em três linhas separadas;
  • For i = 1 To 5 ... Next i percorre todos os cinco produtos um de cada vez, usando i tanto como contador do loop quanto como índice de cada array;
  • Select Case stockLevels(i) executa novamente a mesma decisão baseada em faixa da seção 2.4, mas agora com dados reais de array em vez de um único número fixo;
  • Case Is <= reorderLevels(i) captura qualquer produto cujo estoque caiu até ou abaixo do seu próprio nível de reposição — repare que reorderLevels(i) é uma variável, não um número fixo, então cada produto é avaliado pelo seu próprio limite em vez de um limite único para todos;
  • alertMessage = alertMessage & ... & vbNewLine constrói uma string crescente linha a linha — vbNewLine é uma constante interna que insere uma quebra de linha, então cada produto sinalizado aparece em uma linha separada na mensagem final;
  • O teste final If alertMessage = "" Then é o que decide qual das duas variantes do MsgBox o usuário verá — uma string vazia significa que o loop não encontrou nada que merecesse destaque.

Execute isto e você verá o Monitor Arm sinalizado como "observar de perto" (18 unidades contra um nível de reposição de 10) — acompanhe o loop manualmente para i = 4 se quiser confirmar exatamente por que é o único capturado pelo segundo Case e não pelo primeiro. Este procedimento utiliza arrays, um loop, um Select Case e construção de strings, todos trabalhando juntos. Isso já está genuinamente próximo de uma lógica de qualidade de produção, apenas rodando contra dados de exemplo digitados diretamente no código em vez de uma planilha real.

Tarefa

  1. Copie CheckStockLevels para sua pasta de trabalho e execute. Confirme se a mensagem corresponde à captura de tela.
  2. Altere o estoque do Wireless Mouse para 25 e execute novamente — agora ele também deve aparecer como "observar de perto".
  3. Adicione um loop Do While abaixo que simule a venda de 15 unidades de Laptop Stand por vez até que o estoque caia para 20 ou menos, imprimindo o total acumulado na Janela Imediata após cada venda.
  4. Desafio: reescreva o loop For i = 1 To 5 usando For Each sobre um array Variant — a lógica ainda funciona?
Dica
expand arrow

2. Alterando o estoque do Wireless Mouse

  • Localizar a linha que configura os dados do Wireless Mouse: products(2) = "Wireless Mouse": stockLevels(2) = 134: reorderLevels(2) = 30.
  • É necessário apenas alterar o número do meio (134) para 25 — mantenha o nome do produto e o nível de reposição inalterados.
  • Antes de executar, calcule manualmente qual Case irá capturá-lo: 25 ≤ 30 (o nível de reposição)? Compare especificamente com a linha Case Is <= reorderLevels(i), não com a segunda.

3. Simulando vendas em lote com Do While

  • É preciso uma variável para armazenar o estoque atual do Laptop Stand — inicie com o mesmo valor já presente em stockLevels(1) (58), assim não será necessário digitar um novo número que possa ficar fora de sincronia com o restante da macro.
  • A condição do loop deve verificar se o estoque ainda está acima de 20 — no momento em que verificar e encontrar o estoque em 20 ou menos, deve parar.
  • Subtraia 15 a cada passagem e imprima o novo valor logo após subtrair — não antes — para que cada número impresso reflita uma venda concluída.
  • Faça o rastreamento no papel primeiro: 58 → 43 → 28 → 13. Observe que o último valor fica abaixo de 20 em vez de chegar exatamente a 20 — esse é o mesmo comportamento de "ultrapassagem" do Do While mostrado anteriormente no diagrama de loops do capítulo, não é um erro.
Solução
expand arrow

Ponto 2 — dentro de CheckStockLevels, basta alterar um número:

products(2) = "Wireless Mouse": stockLevels(2) = 25: reorderLevels(2) = 30

Execute o Sub novamente.

Ponto 3 — adicione este trecho abaixo do código existente, ainda dentro de CheckStockLevels (antes do End Sub):

    ' --- Simulate selling Laptop Stand in batches of 15 ---
    Dim laptopStandStock As Integer
    laptopStandStock = stockLevels(1)

    Do While laptopStandStock > 20
        laptopStandStock = laptopStandStock - 15
        Debug.Print laptopStandStock
    Loop
Tudo estava claro?

Como podemos melhorá-lo?

Obrigado pelo seu feedback!

Seção 2. Capítulo 5

Pergunte à IA

expand

Pergunte à IA

ChatGPT

Pergunte o que quiser ou experimente uma das perguntas sugeridas para iniciar nosso bate-papo

Seção 2. Capítulo 5
some-alt