Capítulo 19: VBA II - Laços de Repetição, Coleções e Otimização de Performance

🎯 Objetivo da Aula

O que verdadeiramente diferencia um ser humano de um computador é a capacidade da máquina de executar a mesmíssima sequência de passos milhares de vezes sem se cansar, sem errar e em frações de segundo. Na ciência da computação, chamamos essa estrutura fundamental de Laço de Repetição (Loop ou Iteração).

Nesta aula, você dominará:

  1. Os três principais tipos de loops em VBA: For...Next, For Each...Next e Do While / Do Until.
  2. A navegação matricial bidimensional utilizando a propriedade Cells(linha, coluna).
  3. O cálculo dinâmico da última linha preenchida com Cells(Rows.Count, 1).End(xlUp).Row.
  4. O problema algorítmico da exclusão de linhas e o uso mandatória do passo regressivo Step -1.
  5. Técnicas profissionais de Otimização de Performance (ScreenUpdating e Calculation) para processar grandes bases de dados instantaneamente.

🏢 O Cenário Prático (Seu Desafio)

Situação: O setor financeiro e de faturamento da FastLog recebe no final do mês uma planilha com 5.000 faturas de frete. O analista precisa inspecionar cada fatura:

  1. Se a fatura estiver “Vencida”, pintar a linha de vermelho e enviar para cobrança jurídica.
  2. Se a linha estiver totalmente em branco (erro comum de exportação do ERP), deletar a linha inteira para não corromper os totais contábeis.

Missão: Construir dois robôs de processamento em lote em VBA que percorram dinamicamente toda a base de faturas em milissegundos, eliminando dias inteiros de conferência manual.


🧠 Fundamentos: A Teoria dos Laços de Repetição em VBA

1. O que é uma Iteração?

Uma Iteração é o ato de repetir um bloco de código alterando apenas a variável de controle (o índice i). Se você precisa verificar 1.000 linhas, em vez de escrever 1.000 linhas de código If, você escreve um único If dentro de um Loop que roda 1.000 vezes.

graph TD
    Start([Início do Loop: i = 2]) --> Cond{i <= Última Linha?}
    Cond -- "Sim (True)" --> Action[Processar Célula Cells(i, 2)]
    Action --> Inc[Próximo i: i = i + 1]
    Inc --> Cond
    Cond -- "Não (False)" --> ExitLoop([Fim do Loop: Segue o Script])
    
    style Cond fill:#8e44ad,stroke:#fff,stroke-width:2px,color:#fff
    style Action fill:#217346,stroke:#fff,stroke-width:2px,color:#fff

2. Os Quatro Tipos de Loops em VBA

A. O Loop Contador: For ... Next

Usado quando você sabe exatamente (ou calcula previamente) onde a repetição começa e onde ela termina.

1
2
3
4
Dim i As Long
For i = 2 To 100
    ' Executa para a linha 2, 3, 4 ... até 100
Next i

B. O Loop Regressivo ou com Passo Personalizado: Step

Por padrão, o For incrementa +1 a cada volta. A palavra-chave Step permite alterar esse incremento:

  • For i = 1 To 10 Step 2 (Pula de 2 em 2: 1, 3, 5, 7, 9)
  • For i = 10 To 1 Step -1 (Conta regressivamente: 10, 9, 8… 1)

C. O Loop de Coleções de Objetos: For Each ... Next

Itera diretamente sobre cada objeto dentro de um conjunto (uma coleção de abas, ou um conjunto de células selecionadas), sem precisar de um contador numérico:

1
2
3
4
5
6
Dim celula As Range
For Each celula In Range("A1:A10")
    If celula.Value < 0 Then
        celula.Interior.Color = vbRed
    End If
Next celula

D. O Loop Condicional: Do While e Do Until

Usado quando não sabemos quantas linhas existem e precisamos continuar rodando enquanto uma condição for verdadeira ou até que ela se torne verdadeira:

1
2
3
4
5
6
7
Dim linha As Long
linha = 2
' Roda enquanto a célula não estiver vazia
Do While Cells(linha, 1).Value <> ""
    ' Processa a linha
    linha = linha + 1
Loop

3. A Matriz Cartesiana: Cells(Linha, Coluna) vs Range("A" & i)

No VBA, para trabalhar dentro de laços, a propriedade Cells é muito superior ao Range:

  • Range("B5") usa coordenadas de texto (Letra e Número).
  • Cells(5, 2) usa números inteiros para a Linha (5) e Coluna (2 = B).

Por que usar Cells(i, j) em Loops?
Porque você pode variar tanto o número da linha (i) quanto o número da coluna (j) usando simples variáveis numéricas, permitindo varrer tabelas inteiras em duas dimensões (linhas e colunas).


4. Como Descobrir a Última Linha Dinamicamente (Dynamic End Row)

Nunca “engesse” o limite do seu código em um número fixo como For i = 2 To 500. Se a planilha tiver 501 linhas, a última será ignorada; se tiver 50, o código perderá tempo processando 450 linhas vazias.

Na indústria, utilizamos o comando que simula o atalho de teclado Ctrl + Seta para Cima:

1
2
Dim ultimaLinha As Long
ultimaLinha = Cells(Rows.Count, 1).End(xlUp).Row
  • Rows.Count: Retorna a última linha física do Excel (1.048.576).
  • Cells(Rows.Count, 1): Posiciona o cursor na célula A1048576.
  • .End(xlUp).Row: Sobe até colidir com o último dado preenchido e devolve o número exato daquela linha.

5. O Algoritmo de Exclusão de Linhas: Por que usar Step -1?

Excluir linhas em um laço de repetição esconde uma das armadilhas mais clássicas da programação: O deslocamento de índices.

Se você deletar a linha 3 contando de cima para baixo:

  1. A linha 4 antiga sobe instantaneamente e passa a ser a nova linha 3.
  2. O contador i avança para 4 no próximo ciclo.
  3. Resultado: O dado que subiu para a posição 3 nunca foi inspecionado e escapou da auditoria!
1
2
3
4
5
6
7
8
Contando de Cima para Baixo (ERRADO):
Passo 1: Avalia Linha 3 (Vazia) -> DELETA!
Passo 2: Linha 4 (Também Vazia) sobe para a posição 3.
Passo 3: Contador pula para i=4 -> A nova linha 3 foi IGNORADA!

Contando de Baixo para Cima (CORRETO com Step -1):
Passo 1: Avalia Linha 10 -> DELETA! (Nada acima foi afetado).
Passo 2: Contador desce para i=9 -> Todos os dados são inspecionados com 100% de integridade.

6. Turbinando a Performance do VBA (High Performance Mode)

Quando o VBA altera milhares de células, o Excel tenta redesenhar a tela e recalcular todas as fórmulas a cada linha modificada. Para acelerar seu código em até 100 vezes, utilizamos o padrão de blindagem:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
Sub ExecutarComAltaPerformance()
    ' 1. Desativa a atualização visual e cálculo automático
    Application.ScreenUpdating = False
    Application.Calculation = xlCalculationManual
    
    ' === SEUS LOOPS RODAM AQUI NA VELOCIDADE DA MEMÓRIA RAM ===
    
    ' 2. Restaura o funcionamento padrão do Excel
    Application.Calculation = xlCalculationAutomatic
    Application.ScreenUpdating = True
End Sub

📖 Exemplo Guiado: Varrimento Dinâmico de Linhas

Vamos criar um procedimento que percorre uma coluna e escreve a numeração do lote em todas as linhas preenchidas automaticamente.

Passo a Passo

  1. Abra o VBE (Alt + F11) e insira um novo Módulo.
  2. Digite o código estruturado abaixo:
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
Option Explicit

Sub NumerarLotesAutomatico()
    Dim i As Long
    Dim ultimaLinha As Long
    
    ' Descobre a última linha com dados na coluna B (Produtos)
    ultimaLinha = Cells(Rows.Count, 2).End(xlUp).Row
    
    If ultimaLinha < 2 Then
        MsgBox "Nenhum dado encontrado para processar!", vbExclamation
        Exit Sub
    End If
    
    ' Percorre da linha 2 até a última linha existente
    For i = 2 To ultimaLinha
        Cells(i, 1).Value = "LOTE-2026-" & Format(i - 1, "000")
    Next i
    
    MsgBox "Total de " & (ultimaLinha - 1) & " lotes numerados com sucesso!", vbInformation
End Sub

✅ Resultado Esperado (Exemplo)

Preencha produtos na coluna B (B2:B6). Ao rodar a macro, a coluna A receberá instantaneamente: LOTE-2026-001, LOTE-2026-002, LOTE-2026-003, etc.


🛠️ Prática Obrigatória 1: Auditor de Faturas Vencidas

Passo 1: Construindo a Base de Faturas

Na Planilha 1, monte a matriz de faturamento nas células A1 até D7:

ABCD
1ID_FaturaClienteValor_FreteStatus_Pagamento
2FAT-901Distribuidora Alpha3400,00Pago
3FAT-902MegaVarejo Sul8900,00Atrasado
4FAT-903Supermercados Unidos1250,00Pago
5FAT-904Indústria Metal14200,00Atrasado
6FAT-905Atacado Central4500,00Pendente
7FAT-906Logística Express6700,00Atrasado

Passo 2: Codificando o Loop de Auditoria

No seu Módulo VBA, digite a rotina com verificação e coloração de linhas:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
Option Explicit

Sub AuditarFaturasVencidas()
    Dim i As Long
    Dim ultimaLinha As Long
    Dim contadorAtrasados As Long
    Dim totalInadimplente As Double
    
    ' Otimização de Performance
    Application.ScreenUpdating = False
    
    ultimaLinha = Cells(Rows.Count, 1).End(xlUp).Row
    contadorAtrasados = 0
    totalInadimplente = 0#
    
    For i = 2 To ultimaLinha
        ' Limpa formatações anteriores da linha
        Cells(i, 4).Interior.ColorIndex = xlNone
        Cells(i, 4).Font.Color = vbBlack
        
        ' Verifica se o status na coluna 4 (D) é "Atrasado"
        If Trim(UCase(Cells(i, 4).Value)) = "ATRASADO" Then
            ' Destaca com fundo vermelho e texto branco em negrito
            Cells(i, 4).Interior.Color = RGB(192, 0, 0)
            Cells(i, 4).Font.Color = vbWhite
            Cells(i, 4).Font.Bold = True
            
            ' Acumula métricas financeiras
            contadorAtrasados = contadorAtrasados + 1
            totalInadimplente = totalInadimplente + CDbl(Cells(i, 3).Value)
        End If
    Next i
    
    ' Restaura atualização de tela
    Application.ScreenUpdating = True
    
    ' Relatório consolidado final
    MsgBox "Auditoria Concluída!" & vbCrLf & _
           "• Faturas Vencidas: " & contadorAtrasados & vbCrLf & _
           "• Montante em Atraso: " & FormatCurrency(totalInadimplente), _
           vbInformation, "FastLog Cobrança"
End Sub

Passo 3: Atribuição do Botão

Desenhe um botão 🔍 EXECUTAR AUDITORIA DE CRÉDITO na célula F2 e vincule à macro.

✅ Resultado Esperado (Prática 1)

As linhas 3, 5 e 7 terão suas células de status coloridas em vermelho escuro com fonte branca instantaneamente, e uma caixa de diálogo informará: 3 faturas vencidas e Montante em Atraso: R$ 29.800,00.


🛠️ Prática Obrigatória 2: Limpador de Registros Corrompidos (Step -1)

Passo 1: Criando a Base com Linhas Vazias

Na Planilha 2 (renomeie para Limpeza), crie dados na coluna A (A1 até A10), mas deixe as linhas A3, A5 e A8 completamente vazias.

Passo 2: O Código de Faxina Regressiva

No Módulo VBA, escreva a rotina de exclusão segura:

 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
Sub DeletarLinhasEmBranco()
    Dim i As Long
    Dim ultimaLinha As Long
    Dim linhasApagadas As Long
    
    Application.ScreenUpdating = False
    
    ' Começa da linha 10 (ou da última encontrada)
    ultimaLinha = 10
    linhasApagadas = 0
    
    ' Loop Regressivo Mandatório
    For i = ultimaLinha To 2 Step -1
        ' Se a célula na coluna A for vazia
        If Trim(Cells(i, 1).Value) = "" Then
            Rows(i).Delete
            linhasApagadas = linhasApagadas + 1
        End If
    Next i
    
    Application.ScreenUpdating = True
    
    MsgBox "Faxina concluída! " & linhasApagadas & " linhas corrompidas foram eliminadas.", vbInformation
End Sub

Passo 3: Teste e Validação

Desenhe o botão 🧹 ELIMINAR LINHAS VAZIAS e execute o script.


📤 Instruções de Entrega (Microsoft Teams)

Após finalizar as duas práticas obrigatórias:

  1. Salve o arquivo como .XLSM (Habilitado para Macro).
  2. Nome: Atividade_19_SeuNome_SeuSobrenome.xlsm
  3. No Microsoft Teams, envie o arquivo na tarefa “Capítulo 19 - Lógica com VBA II”.
  4. Clique em Entregar.

💡 Checkpoint de Lógica: Complexidade e Laços de Repetição

Você acaba de aplicar um algoritmo com Complexidade Linear $O(N)$. Isso significa que o tempo de execução cresce de forma diretamente proporcional ao número de linhas ($N$) da base.

Em bancos de dados SQL, esse laço equivale a uma instrução em lote do tipo:

1
2
3
UPDATE Faturas 
SET Status_Visual = 'Vermelho' 
WHERE Status_Pagamento = 'Atrasado';

No Excel com VBA, você construiu esse motor de processamento no nível do código de máquina!


🔥 Desafio de Fixação: Loop For Each com Múltiplas Abas

Crie uma macro chamada ProtegerTodasAsAbas() que utilize a estrutura For Each para percorrer todas as abas (Worksheets) da sua pasta de trabalho e aplicar uma senha de proteção contra edição:

1
2
3
4
5
6
7
8
9
Sub ProtegerTodasAsAbas()
    Dim aba As Worksheet
    
    For Each aba In ThisWorkbook.Worksheets
        aba.Protect Password:="fastlog2026"
    Next aba
    
    MsgBox "Todas as abas foram blindadas com sucesso!", vbInformation
End Sub

📝 Atividade Extra: Questionário de Fixação (Caderno)

Instruções: Responda no caderno, de próprio punho, as 10 perguntas abaixo com base no que foi estudado neste capítulo. Ao concluir, leve o caderno até o professor para correção e visto.

  1. O que é uma Iteração (Loop) e por que ela é útil na programação?
  2. Qual a diferença entre For…Next, For Each…Next e Do While?
  3. Como descobrir dinamicamente a última linha preenchida em uma planilha via VBA?
  4. Por que devemos usar Step -1 ao excluir linhas dentro de um loop?
  5. O que aconteceria se excluíssemos linhas de cima para baixo em vez de baixo para cima?
  6. Qual a diferença entre usar Cells(i, j) e Range(“A1”) dentro de um laço de repetição?
  7. Quais duas propriedades do Application são desativadas para otimizar a performance de um script VBA com muitos dados?
  8. Escreva a estrutura básica de um loop For…Next que percorre da linha 2 até a última linha com dados.
  9. O que é Complexidade Linear O(N) e como ela se relaciona com os laços de repetição?
  10. Dê um exemplo de tarefa repetitiva do cotidiano logístico que poderia ser automatizada com um loop.