Select Menu



por Alessandro Trovato

» » » » » » VBA - Artigo 010 - Estruturas de repetição
«
Proxima
Postagem mais recente
»
Anterior
Postagem mais antiga


Estruturas de repetição

O VBA fornece seis formas de estrutura de repetição. Quatro delas são variantes das duas básicas (Do... Loop e For... Next), mas ainda assim são formas distintas de estrutura de repetição.

A primeira estrutura que costuma-se ensinar é o Do While... Loop, talvez por ser a mais simples de entender. A tradução de Do While é Faça Enquanto, ou seja, irá executar enquanto uma condição for verdadeira. Vejamos um exemplo simples de código:

Sub NumeroLinha()

    Dim Linha As Integer
    Linha = 1

    Do While Linha <= 10
        Cells(Linha, 1).Value = Linha
        Linha = Linha + 1
    Loop

End Sub

O código acima colocará o número da linha na primeira coluna da linha 1 até a 10. Na estrutura de repetição temos uma condição que define até quando a estrutura será executada (Linha <= 10). O laço será executado enquanto "Linha for menor ou igual a 10". Assim que a variável Linha assumir um valor superior, o laço deixará de ser executado.

Perceba que a variável foi inicializada com o valor 1 antes da estrutura de repetição. Se ela fosse inicializada com um valor superior a 10 a execução sequer entraria no laço Do While... Loop. Faça uma alteração no código, inicialize com 11 e teste, utilizando a depuração (tecla F8).

Há casos em que precisamos executar o laço pelo menos uma vez antes verificar a condição. Neste caso podemos usar a variante Do... Loop While. A diferença no código é a posição do While e a condição. Alterando o código anterior teremos:

Sub NumeroLinha()

    Dim Linha As Integer
    Linha = 1

    Do
        Cells(Linha, 1).Value = Linha
        Linha = Linha + 1
    Loop While Linha <= 10

End Sub

Executando o código veremos que o resultado é exatamente o mesmo da primeira versão do código. Qual a diferença então? A diferença é que a condição está sendo testada no final do laço, não no começo. Para entendermos melhor o que isso significa, vamos inicializar a variável Linha com o valor 11 e testar o código. Desta vez o laço foi executado uma vez e o valor 11 apareceu na décima primeira linha.

Como pode-se perceber, há diferença entre testar a condição no começo ou no final do laço. Testando ao final do laço garante pelo menos uma execução do processo. Há casos em que isso é necessário, assim como há casos em que só deve executar quando a condição for verdadeira. Cabe ao desenvolvedor perceber qual é a necessidade e codificar de acordo. Na maioria dos casos a condição é testada antes, o teste ao final costuma ser em casos bem específicos.

Temos também a estrutura Do Until... Loop, cuja tradução é Faça Até. Enquanto o Do While executa enquanto a condição seja verdadeira, o Do Until executa até que a condição seja verdadeira. Compreendeu a diferença? Veja o mesmo código anterior adaptado e perceba a diferença na forma de escrever a condição:

Sub NumeroLinha()

    Dim Linha As Integer
    Linha = 1
    
    Do Until Linha > 10
        Cells(Linha, 1).Value = Linha
        Linha = Linha + 1
    Loop

End Sub

A condição passou a ser Linha > 10. Traduzindo o código teremos a frase: "faça até que Linha tenha um valor maior que 10". Em termos lógicos, é exatamente o oposto da condição Linha <=10. Da mesma forma que temos o Do... Loop While, também temos o Do... Until Loop:

Sub NumeroLinha()

    Dim Linha As Integer
    Linha = 1
    
    Do
        Cells(Linha, 1).Value = Linha
        Linha = Linha + 1
    Loop Until Linha > 10

End Sub

Faça o mesmo teste de inicializar Linha com 11 e veja que o resultado é o mesmo obtido com Do... Loop While.

Quando usar Do While ou Do Until? Isso vai depender da necessidade do momento e da forma que você compreender melhor o código. Você pode optar por usar somente um deles, mas é importante conhecer os dois para o caso de precisar dar manutenção em código de outras pessoas. Se você utiliza outras linguagens de programação deve saber que algumas têm somente While ou Until.

Outra estrutura de repetição é o For... Next. É uma estrutura mais apropriada quando há variável de controle, como nos exemplos anteriores. Vejamos como fica o mesmo código anterior usando o For... Next:

Sub NumeroLinha()

    Dim Linha As Integer

    For Linha = 1 To 10
        Cells(Linha, 1).Value = Linha
    Next Linha

End Sub

Ao contrário das estruturas de repetição Do... Loop, em For... Next a variável de controle é inicializada na própria estrutura, bem como o incremento. Não é necessário adicionar 1 à variável Linha porque o laço já faz isso automaticamente. Linha receberá valores de 1 a 10 e a estrutura será encerrada ao final da décima execução.

Nas estruturas Do... Loop podemos alterar o incremento alterando o valor para 2, por exemplo. A linha do incremento ficaria assim:

        Linha = Linha + 2

Na estrutura For... Next, adicionamos um parâmetro chamado Step (passo em inglês):

    For Linha = 1 To 10 Step 2

Podemos editar o loop de incremento para decremento. Na estrutura For... Next isso é feito em apenas uma linha:

    For Linha = 10 To 1 Step -1

Desta maneira a execução irá de 10 para 1, decrementando 1 a cada execução. Nas estruturas Do... Loop precisamos alterar a linha com a inicialização da variável, bem como a do incremento, passando para decremento. Por fim, precisamos mexer na condição também, para que reflita a alteração para decremento.

As estruturas Do... Loop demandam mais atenção, pois caso o código dentro da estrutura não permitir a saída do laço, o código será executado indefinidamente até que o Excel trave e interrompa a execução. Por essa razão é melhor que quem esteja iniciando na programação use a estrutura For... Next, que é menos propensa a erros.

Por fim, temos a estrutura For Each... Next, que é específica para trabalhar com coleções de objetos e arrays. For Each significa Para Cada, ou seja, executa o processamento para cada objeto que houver em uma coleção ou para cada item em um array. O código abaixo gera o mesmo resultado dos anteriores:

Sub NumeroLinha()

    Dim Celula As Range
    Dim Intervalo As Range
    Set Intervalo = Range("A1:A10")
    
    For Each Celula In Intervalo
        Celula.Value = Celula.Row
    Next

End Sub

A variável Intervalo foi inicializada para conter as células entre A1 e A10. Por ser um objeto (do tipo Range), essa variável deve ser inicializada usando o comando Set. A estrutura For Each... Next percorre cada célula individual da coleção (um intervalo é uma coleção de células) e preenche o conteúdo da célula com o número da linha.


Vimos as seis estruturas de repetição disponíveis no VBA. Tirando o For Each... Next que é específico para coleções de objetos e arrays, as outras podem ser escolhidas de acordo com a necessidade ou mesmo pela sua compreensão do funcionamento. Eu recomendo que faça testes e exercícios com cada uma delas para praticar e conhecer melhor cada uma. Use a depuração (tecla F8) para executar passo a passo que ajuda a entender o funcionamento.

Pedro Martins


Formado em Tecnologia em Eletrônica Digital, já trabalhou como artefinalista, eletrotécnico, programador de CLP (para máquinas industriais) e analista de sistemas em sistema bancário, programando em COBOL.
Mexe com computadores e programação desde a segunda metade dos anos 1980, quando teve um MSX e aprendeu a programar em BASIC. É a favor da disseminação do conhecimento.

Autor Pedro Martins

Esta é uma breve descrição no bloco de autor sobre o autor. Você edita-lo, no html
«
Proxima
Postagem mais recente
»
Anterior
Postagem mais antiga

9 comentários

  1. Gostaria de saber se é possível e como faço para o excel listar todas as combinações possíveis (sem repetições) compostas por 4 números de um conjunto de 62 números.
    Isto é: eu tenho um conjunto de números que vai do 23 ao 80, mais o 87, o 88, o 90 e o 96.
    Pretendo que o excel liste todas as combinações possíveis compostas por 4 números. Ex: 23-24-25-26, 23-24-26-25, 23-25-24-26, etc...
    O objectivo é, posteriormente, aplicar a formula (a/b)x(c/d) à listagem obtida.
    Obrigada

    ResponderExcluir
  2. Bom dia, Eliana. É possível sim fazer o que você precisa. Primeiramente precisa entender um pouco do processo que será feito.

    Cada número precisará acontecer uma única vez, sem repetição. Para termos todos os números em todas as quatro posições possíveis, precisaremos que todos os laços sejam do primeiro até o último número. Para evitar repetição, precisaremos conferir se o valor do número obtido é igual a um dos obtidos nos laços externos.

    Cada número será obtido no começo do laço e então será conferido se é igual a um dos outros laços (exceto no primeiro, por não haver necessidade). Somente no laço mais interno, após termos os quatro números, é que preencheremos os dados.

    O código segue abaixo, não é complexo. Apenas leve em conta que levará um bom tempo até gerar as milhões de combinações possíveis. Exatamente pela demora é que coloquei o valor da linha que está sendo preenchida na barra de status, porque senão pode-se pensar que o Excel travou, quando na verdade ele está processando todas as possibilidades.

    Coloque seus números nas células A1 a A62 e depois execute o código:

    Option Explicit
    Sub FazerCombinacoes()

    Dim Quantidade As Integer
    Dim Linha As Long
    Dim Laco1 As Integer
    Dim Laco2 As Integer
    Dim Laco3 As Integer
    Dim Laco4 As Integer
    Dim Valor1 As Integer
    Dim Valor2 As Integer
    Dim Valor3 As Integer
    Dim Valor4 As Integer

    Debug.Print Now

    Quantidade = 62
    Linha = 1

    For Laco1 = 1 To Quantidade
    Valor1 = Cells(Laco1, 1).Value
    For Laco2 = 1 To Quantidade
    Valor2 = Cells(Laco2, 1).Value
    If Valor2 = Valor1 Then
    GoTo SaiLaco2
    End If
    For Laco3 = 1 To Quantidade
    Valor3 = Cells(Laco3, 1).Value
    If Valor3 = Valor1 Or Valor3 = Valor2 Then
    GoTo SaiLaco3
    End If
    For Laco4 = 1 To Quantidade
    Valor4 = Cells(Laco4, 1).Value
    If Valor4 = Valor1 Or Valor4 = Valor2 Or Valor4 = Valor3 Then
    GoTo SaiLaco4
    End If
    Cells(Linha, 3).Value = Valor1
    Cells(Linha, 4).Value = Valor2
    Cells(Linha, 5).Value = Valor3
    Cells(Linha, 6).Value = Valor4
    Cells(Linha, 7).Formula = "=(" + _
    Cells(Linha, 3).Address + "/" + Cells(Linha, 4).Address + ")*(" + _
    Cells(Linha, 5).Address + "/" + Cells(Linha, 6).Address + ")"
    Linha = Linha + 1
    Application.StatusBar = "Linha atual: " & Linha
    DoEvents
    SaiLaco4:
    Next Laco4
    SaiLaco3:
    Next Laco3
    SaiLaco2:
    Next Laco2
    Next Laco1

    Application.StatusBar = False
    Debug.Print Now

    End Sub

    Esse código está "engessado" para os 62 números e para uma combinação de 4 deles. Você pode adaptar o código para as suas necessidades. Note que no meu código há um "Debug.Print Now" no começo e no fim do código. Esse comando irá mostrar na área "Verificação imediata" do editor VBA a hora de início e a hora de fim do processamento, para que você possa ter uma noção do tempo de demora para processar tudo. No meu notebook (um pouco velhinho) demorou cerca de 10 minutos para processar as primeiras 50 mil possibilidades. Lembre-se que serão milhões de possibilidades, por isso deixe a máquina processando quando tiver muito tempo à disposição.

    Avise se era isso mesmo que queria e se resolveu seu problema. Informe também quanto tempo levou para processar e quantas possibilidades foram geradas. Pelas minhas contas devem ser geradas 61^4 = 13.845.841 possibilidades.

    ResponderExcluir
    Respostas
    1. Olá Pedro!
      Que espetáculo meu amigo... Só essa resposta já merece um novo Post...
      Não deixe de publicá-lo pois ao compartilhar com nossa comunidade haverá um grande alcance...

      Excluir
    2. A solução colocada aqui tem um problema, pois a quantidade de combinações passa das 1.048.576 linhas existentes na planilha do Excel. Fiz as adaptações no código e logo mais teremos uma postagem com a solução, bem como as devidas explicações para chegar na solução final.

      Excluir
    3. Pois é! Eu já tinha pensado nesse pormenor, no entanto estava a aguardar os resultados chegarem a essa linha.
      Obrigada, Sr Pedro Martins.

      Excluir
  3. Olá Pedro.
    Gostaria de saber se é possível fazer um loop para somar as células de uma coluna a cada 64 células. Por exemplo: em uma coluna com 1400 células as somas receberiam os valores de 64 em 64 células.
    Desde já agradeço.
    Sds
    Rodrigo Franco

    ResponderExcluir
    Respostas
    1. Boa tarde Rodrigo! Tomo a liberdade de participar da sua pergunta.
      Tenho uma aula que explica como fazer o que você precisa no Youtube.
      Segue o link.
      https://www.youtube.com/watch?v=X6lJa5oW3CY

      Bons estudos!

      Excluir
  4. Ola pedro
    Primeiro quero parabeniza lo pelo site goste muito e ja esta nos meu favoritos

    e tbm gostaria de tirar uma duvida

    tenho uma planilha com algumas datas e gostaria de q tivesse um alerte sempre q ultrapassa essa data
    por exemplo
    digamos q a celula A1 esteja com a data 05/12/2016 ai quando for 06/12/2016 aparecer um alerta q passou a data

    não sei se fui claro mas espero que tenha entendido

    ResponderExcluir
  5. Olá boa noite
    Gostaria de saber se tem como eu enumrar uma coluna de forma crescente entre valores determinados
    Por exemplo:
    Enumrar a coluna "A" com números sequênciais de 1 a 10
    Ficando assim
    A1 = 1
    A2 = 2
    A3 = 3
    E assim por diante até chegar o número 10
    Sendo que esses valores eu possa alterar quando for preciso
    Poderia me ajudar
    Desde já agradecido

    ResponderExcluir