Capítulo 07: Laços Condicionais (Do While / Do Until) e Encontrando a Última Linha

🎯 Objetivo da Aula

Nesta aula, você aprenderá a criar laços de repetição não determinísticos utilizando Do While...Loop e Do Until...Loop. Você entenderá a diferença lógica fundamental entre repetir “enquanto uma condição for verdadeira” versus repetir “até que uma condição se torne verdadeira”, aprenderá a se proteger contra laços infinitos (infinite loops) e consolidará o algoritmo corporativo para localização dinâmica da última linha ativa na planilha.

Ao final desta aula, você terá construído o robô de conciliação bancária diária da tesouraria da FastLog S.A.


🏢 Cenário Prático (FastLog S.A.)

Empresa: FastLog Transportes & Logística Integrada S.A.
Problema: Toda manhã, a tesouraria central baixa do banco um extrato eletrônico de pagamentos recebidos dos clientes corporativos. A quantidade de linhas nunca é fixa: em uma terça-feira comum podem ser 40 linhas, enquanto no quinto dia útil chegam a mais de 800 lançamentos. Além disso, o arquivo pode conter quebras acidentais de registros. O analista júnior usava um For i = 2 To 1000 estático; quando o arquivo tinha 50 linhas, o código ficava rodando no vazio por 2 minutos processando 950 linhas em branco, gerando lentidão e gravando zeros indesejados.
Sua Missão: Desenvolver o procedimento ConciliarExtratoBancario, utilizando Do While para percorrer os lançamentos exatamente enquanto houver dados preenchidos, somando créditos, subtraindo tarifas bancárias e gerando o saldo contábil líquido instantaneamente.


🧠 Fundamentos: A Teoria Traduzida

1. Do While vs. Do Until: Qual a Diferença?

flowchart TD
    subgraph DOWHILE["Laço Do While (Enquanto)"]
        DW_START["Início"] --> DW_COND{"Condição é VERDADEIRA?"}
        DW_COND -- SIM --> DW_EXEC["Executa bloco de código"] --> DW_COND
        DW_COND -- NÃO --> DW_END["Encerra o laço"]
    end

    subgraph DOUNTIL["Laço Do Until (Até Que)"]
        DU_START["Início"] --> DU_COND{"Condição é VERDADEIRA?"}
        DU_COND -- NÃO --> DU_EXEC["Executa bloco de código"] --> DU_COND
        DU_COND -- SIM --> DU_END["Encerra o laço"]
    end

    style DOWHILE fill:#1a365d,stroke:#fff,stroke-width:2px,color:#fff
    style DOUNTIL fill:#2c3e50,stroke:#fff,stroke-width:2px,color:#fff
    style DW_COND fill:#27ae60,stroke:#fff,stroke-width:2px,color:#fff
    style DU_COND fill:#e67e22,stroke:#fff,stroke-width:2px,color:#fff
  • Do While Condição: Continua executando enquanto a condição for True.
    • Exemplo: “Execute enquanto a célula NÃO estiver vazia (Do While Cells(lin, 1).Value <> "")”.
  • Do Until Condição: Continua executando até que a condição se torne True.
    • Exemplo: “Execute até que a célula FIQUE vazia (Do Until IsEmpty(Cells(lin, 1)))”.

2. O Perigo do Laço Infinito e o Atalho de Emergência

Se você esquecer de incrementar a linha dentro do laço (ex: esquecer a instrução lin = lin + 1), o teste condicional continuará eternamente verdadeiro. O Excel entrará em estado de “Não Respondendo” (looping infinito).

Atalho de Emergência para Interromper uma Macro Travada: Pressione as teclas Ctrl + Pause Break ou Esc repetidamente no teclado para forçar a parada do código pelo VBE.

3. O Algoritmo Universal da Última Linha

Para encontrar onde termina uma tabela, simulamos o atalho do teclado Ctrl + Seta para Cima partindo do final da planilha:

1
lngUltimaLinha = Cells(Rows.Count, "A").End(xlUp).Row
  • Rows.Count retorna 1048576 (a última linha física do Excel).
  • .End(xlUp) sobe verticalmente como um foguete até colidir com a última célula preenchida da coluna A.

📖 Exemplo Guiado: Passo a Passo no Laboratório

No computador do laboratório, acesse o VBE com Alt + F11.

Passo 1: Inserção do Módulo da Tesouraria

  1. No menu superior, clique em Inserir ➔ Módulo.
  2. Na janela de propriedades (F4), renomeie o módulo para: modTesouraria.
  3. Confirme a diretiva Option Explicit.

Passo 2: Estruturação dos Dados de Extrato na Planilha

No Excel, monte o cabeçalho na linha 1:

  • A1: ID_Transacao | B1: Descricao_Operacao | C1: Tipo (C/D) | D1: Valor_Lancamento | E1: Saldo_Acumulado
  • Digite a massa de lançamentos da manhã:
    • Linha 2: TRX-801 | Pgto Frete Ambev | C | 15400
    • Linha 3: TRX-802 | Tarifa Emissão Boleto | D | 45.50
    • Linha 4: TRX-803 | Pgto Frete Unilever | C | 28900
    • Linha 5: TRX-804 | Manutenção Rastreador | D | 320
    • Linha 6: TRX-805 | Pgto Frete Magazine Luiza | C | 41250

🛠️ Prática Obrigatória 1: Conciliação Dinâmica com Do While

Implementaremos o algoritmo que varre o extrato com Do While, apurando o saldo corrente a cada lançamento.

Passo a Passo no Computador:

  1. No módulo modTesouraria, digite a rotina de conciliação:
     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
    43
    44
    45
    46
    47
    48
    49
    50
    
    Option Explicit
    
    Sub ConciliarExtratoBancario()
        Dim ws As Worksheet
        Dim lngLinha As Long
        Dim strTipo As String
        Dim curValor As Currency
        Dim curSaldoAcumulado As Currency
        Dim lngTotalCreditos As Long
        Dim lngTotalDebitos As Long
    
        Set ws = ThisWorkbook.Worksheets(1)
    
        ' Ponto de partida: primeira linha de dados
        lngLinha = 2
        curSaldoAcumulado = 0
        lngTotalCreditos = 0
        lngTotalDebitos = 0
    
        ' Laço executa ENQUANTO houver ID de transação na coluna A
        Do While ws.Cells(lngLinha, 1).Value <> ""
            strTipo = UCase(Trim(ws.Cells(lngLinha, 3).Value))
            curValor = CCur(ws.Cells(lngLinha, 4).Value)
    
            ' Atualização do saldo conforme Crédito (C) ou Débito (D)
            If strTipo = "C" Then
                curSaldoAcumulado = curSaldoAcumulado + curValor
                lngTotalCreditos = lngTotalCreditos + 1
            ElseIf strTipo = "D" Then
                curSaldoAcumulado = curSaldoAcumulado - curValor
                lngTotalDebitos = lngTotalDebitos + 1
            End If
    
            ' Grava o saldo acumulado na coluna E (Coluna 5)
            ws.Cells(lngLinha, 5).Value = curSaldoAcumulado
            ws.Cells(lngLinha, 5).NumberFormat = "R$ #,##0.00"
    
            ' INCREMENTO OBRIGATÓRIO: Avança para a próxima linha!
            lngLinha = lngLinha + 1
        Loop
    
        ' Autoajuste de colunas
        ws.Columns("A:E").AutoFit
    
        MsgBox "Conciliação bancária concluída com sucesso!" & vbCrLf & vbCrLf & _
               "• Lançamentos de Crédito: " & lngTotalCreditos & vbCrLf & _
               "• Lançamentos de Débito: " & lngTotalDebitos & vbCrLf & _
               "• Saldo Líquido Final: " & FormatCurrency(curSaldoAcumulado), _
               vbInformation, "Tesouraria FastLog"
    End Sub
  2. Posicione o cursor no código e execute com F5.
  3. Veja o saldo ser calculado linha a linha na coluna E:
    • Linha 2: R$ 15.400,00
    • Linha 3: R$ 15.354,50 (subtraiu os 45,50)
    • Linha 4: R$ 44.254,50
    • Linha 5: R$ 43.934,50
    • Linha 6: R$ 85.184,50 (Saldo final correto).

✅ Resultado Esperado (Prática 1):

A coluna E exibe a evolução do saldo bancário e uma caixa de mensagem resume a quantidade de créditos, débitos e o saldo final da empresa.


🛠️ Prática Obrigatória 2: Verificação de Integridade com Do Until

Agora usaremos Do Until para percorrer a planilha validando se existem transações com valores nulos ou negativos na coluna de lançamentos, alertando o auditor antes do fechamento do caixa.

Passo a Passo no Computador:

  1. No mesmo módulo, insira o procedimento de auditoria preventiva:
     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
    
    Sub AuditarInconsistenciasExtrato()
        Dim ws As Worksheet
        Dim lngLinha As Long
        Dim blnEncontrouErro As Boolean
        Dim strMensagemErro As String
    
        Set ws = ThisWorkbook.Worksheets(1)
        lngLinha = 2
        blnEncontrouErro = False
        strMensagemErro = ""
    
        ' Laço executa ATÉ QUE a célula fique vazia (IsEmpty)
        Do Until IsEmpty(ws.Cells(lngLinha, 1))
            ' Teste de integridade: valor não pode ser menor ou igual a zero
            If ws.Cells(lngLinha, 4).Value <= 0 Then
                blnEncontrouErro = True
                strMensagemErro = strMensagemErro & "• Linha " & lngLinha & ": ID " & ws.Cells(lngLinha, 1).Value & " tem valor inválido!" & vbCrLf
                ws.Cells(lngLinha, 4).Interior.Color = RGB(255, 199, 206) ' Alerta vermelho
            End If
    
            lngLinha = lngLinha + 1
        Loop
    
        If blnEncontrouErro Then
            MsgBox "AUDITORIA: Foram encontradas inconsistências:" & vbCrLf & vbCrLf & strMensagemErro, _
                   vbExclamation, "Inconsistências Detectadas"
        Else
            MsgBox "Todos os lançamentos do extrato possuem valores válidos e positivos!", _
                   vbInformation, "Auditoria Homologada"
        End If
    End Sub
  2. Teste a macro com os dados atuais: ela confirmará a homologação.
  3. Altere o valor da linha 3 para 0 ou -10 e execute novamente: o sistema identificará o erro e pintará a célula faltosa!

✅ Resultado Esperado (Prática 2):

O robô identifica com precisão qualquer anomalia nos lançamentos bancários antes da consolidação na contabilidade.


📤 Instruções de Entrega (Microsoft Teams)

  1. Salve o arquivo como: Atividade_07_VBA_SeuNome_SeuSobrenome.xlsm.
  2. Acesse o Microsoft Teams na disciplina.
  3. Abra a tarefa: “VBA - Cap 07: Laços Do While e Do Until”.
  4. Anexe sua planilha e envie.

💡 Checkpoint de Gestão & TI

Em sistemas de automação de processos de escritório (Office RPA), os laços orientados a eventos (Do While / Do Until) são amplamente utilizados para ler arquivos sem cabeçalho fixo, como extratos CNAB 240, arquivos de log de balança e filas de mensagens. Saber quando usar um laço condicional em vez de um laço com limite fixo evita processamento inútil de milhares de linhas vazias, otimizando o consumo de CPU.


🔥 Desafio de Fixação: Linha de Totais Automatizada

Adicione ao procedimento de conciliação a gravação de uma linha de rodapé elegante ao final do extrato:

  1. Ao sair do laço Do While, a variável lngLinha conterá o número da primeira linha vazia.
  2. Na célula Cells(lngLinha, 2), grave o texto "SALDO LÍQUIDO CONCILIADO:".
  3. Na célula Cells(lngLinha, 5), grave o valor da variável curSaldoAcumulado.
  4. Aplique negrito e preenchimento verde suave (RGB(198, 239, 206)) na linha inteira de totais.

🔑 Revelar Gabarito Oficial de Laboratório (Clique para expandir)
💡 Incentivo Pedagógico: Tente resolver as práticas e o desafio de fixação por conta própria antes de abrir o gabarito. Seus erros e tentativas durante o laboratório são a chave para a consolidação real do aprendizado!

Código Consolidado (modTesouraria):

 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
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
Option Explicit

Sub ConciliacaoBancariaIntegral()
    Dim ws As Worksheet
    Dim lngLinha As Long
    Dim strTipo As String
    Dim curValor As Currency
    Dim curSaldoAcumulado As Currency
    Dim curTotalCreditos As Currency
    Dim curTotalDebitos As Currency
    
    Set ws = ThisWorkbook.Worksheets(1)
    
    Application.ScreenUpdating = False
    
    lngLinha = 2
    curSaldoAcumulado = 0
    curTotalCreditos = 0
    curTotalDebitos = 0
    
    ' Varredura com Do While
    Do While ws.Cells(lngLinha, 1).Value <> ""
        strTipo = UCase(Trim(ws.Cells(lngLinha, 3).Value))
        curValor = CCur(ws.Cells(lngLinha, 4).Value)
        
        If strTipo = "C" Then
            curSaldoAcumulado = curSaldoAcumulado + curValor
            curTotalCreditos = curTotalCreditos + curValor
        ElseIf strTipo = "D" Then
            curSaldoAcumulado = curSaldoAcumulado - curValor
            curTotalDebitos = curTotalDebitos + curValor
        End If
        
        ws.Cells(lngLinha, 5).Value = curSaldoAcumulado
        ws.Cells(lngLinha, 5).NumberFormat = "R$ #,##0.00"
        
        lngLinha = lngLinha + 1
    Loop
    
    ' Linha de Rodapé Executivo (Desafio de Fixação)
    With ws.Range(ws.Cells(lngLinha, 1), ws.Cells(lngLinha, 5))
        .Font.Bold = True
        .Interior.Color = RGB(220, 240, 220)
        .Borders(xlEdgeTop).LineStyle = xlDouble
        .Borders(xlEdgeBottom).LineStyle = xlContinuous
    End With
    
    ws.Cells(lngLinha, 2).Value = "SALDO LÍQUIDO CONCILIADO:"
    ws.Cells(lngLinha, 5).Value = curSaldoAcumulado
    ws.Cells(lngLinha, 5).NumberFormat = "R$ #,##0.00"
    
    ws.Columns("A:E").AutoFit
    Application.ScreenUpdating = True
    
    MsgBox "Conciliação FastLog Concluída!" & vbCrLf & vbCrLf & _
           "• Total Entradas (Créditos): " & FormatCurrency(curTotalCreditos) & vbCrLf & _
           "• Total Saídas (Débitos): " & FormatCurrency(curTotalDebitos) & vbCrLf & _
           "• Saldo Final em Conta: " & FormatCurrency(curSaldoAcumulado), _
           vbInformation, "Tesouraria & Finanças"
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 você estudou neste capítulo. Ao concluir, apresente o caderno ao professor para visto.

  1. Em que situação prática é preferível utilizar um laço Do While em vez de um laço For...Next?
  2. Explique a diferença semântica e lógica entre as instruções Do While e Do Until.
  3. O que acontece com o computador se a instrução de incremento do contador (ex: lngLinha = lngLinha + 1) for esquecida dentro de um laço Do While?
  4. Qual é a combinação de teclas de atalho de emergência utilizada para interromper a execução de um laço infinito no Excel?
  5. Explique como funciona o comando Cells(Rows.Count, "A").End(xlUp).Row e por que ele é tão rápido.
  6. Qual é a utilidade da função IsEmpty() no teste condicional do laço Do Until?
  7. No laboratório de conciliação bancária, como a variável curSaldoAcumulado foi manipulada para somar créditos e abater tarifas?
  8. Por que a propriedade Application.ScreenUpdating = False é indicada mesmo em rotinas que utilizam laços Do While?
  9. Como o código do Desafio de Fixação aproveitou o valor final da variável lngLinha após o término do laço para gravar o rodapé?
  10. O que significa a propriedade LineStyle = xlDouble aplicada às bordas da linha de fechamento contábil?