VBA - Artigo 020 - Melhorando seu código com objetos Type

Progredindo em VBA no Microsoft Excel

Melhorando seu código com objetos Type

Dei uma breve explicação sobre objetos type no meu sexto artigo, com um exemplo muito simples e superficial. Neste vou explicar melhor as aplicações para este objeto tão subestimado no VBA.

Observe este exemplo real de declaração de variáveis, que usei em uma ocasião que fiz o código sem fazer um projeto antes de começar:

Private Arquivos        As Variant
Private Resposta        As Integer
Private ContadorArquivo As Integer
Private TotalArquivos   As Integer
Private Quantidade      As Integer
Private Contador        As Integer
Private Inicio          As Long
Private Proximo         As Long
Private Tamanho         As Long
Private Linha           As Long
Private UltimaLinha     As Long
Private ValorEncontrado As Long
Private NomeArquivo     As String
Private Registro        As String
Private TipoRegistro    As String
Private Texto           As String
Private Intervalo       As Range
Private Tabela          As Range
Private Adicionado      As Boolean
Private Encontrado      As Boolean

Para deixar mais claro, deixei as variáveis separadas por tipo. Perceba que mesmo com os nomes de variáveis com a maior clareza possível, a finalidade de cada uma começa a ficar confusa quando há várias com nomes similares e tipos distintos. Em alguns casos, acabei reutilizando as variáveis em mais de uma sub-rotina, pois eram variáveis definidas para o módulo. No final, a manutenção acabava prejudicada, pois até descobrir a finalidade exata de cada uma levava algum tempo.

Algo que é muito recorrente nos códigos são as estruturas de repetição. Em laços do tipo For... Next costumamos declarar duas variáveis: a iteração (que irá incrementar ou decrementar conforme o laço é executado) e o limite (o valor que encerra o laço). No exemplo acima temos ContadorArquivo, Contador e Linha como iterações e TotalArquivos, Quantidade e UltimaLinha como limites. Linha e UltimaLinha foram duas das variáveis que foram utilizadas em várias sub-rotinas para controlar o processamento em tabelas distintas. E se eu precisasse de procurar algum valor em outra tabela? Não daria para usar as mesmas variáveis, pois estavam em uso. Mais um par de variáveis sendo criado...

Existe alguma maneira de simplificar? Um objeto type pode ajudar. Observe o código abaixo:

Type tpIteracao
    Atual   As Integer
    Limite  As Integer
End Type

Sub Teste()

    Dim Contador As tpIteracao
    Contador.Limite = 10
   
    For Contador.Atual = 1 To Contador.Limite
        Debug.Print "Contador = " & Contador.Atual
    Next

End Sub

O objeto tpIteracao está declarado fora das rotinas, sendo assim público. Pode ser utilizada em qualquer sub-rotina do módulo atual ou mesmo em outros módulos. O objeto foi criado com duas propriedades Atual e Limite (poderia usar outros nomes, mas preferi estes).

No exemplo acima foi declarado Contador como sendo do tipo tpIteracao e assim tendo a mesma estrutura do objeto criado. Na estrutura de repetição, Contador.Atual se refere à iteração atual e Contador.Limite se refere à última iteração.

Uma grande vantagem é que o objeto pode ser declarado dentro da sub-rotina, existindo somente enquanto esta estiver em execução. Se houver necessidade de um laço dentro do outro, cria-se dois objetos tpIteracao. Outra vantagem é que os nomes das propriedades ficam padronizadas em todas as vezes que o objeto for criado, facilitando assim o entendimento e a manutenção do código.

Você pode criar objetos diferentes para cada finalidade. Por exemplo, pode criar um objeto tpLinha como contador de linhas da tabela e usar propriedades do tipo long, para suportar todas as linhas da planilha e um objeto tpContador, com propriedades do tipo integer, para quantidades menores, podendo usar até nomes de propriedades diferentes, de acordo com as necessidades do momento:

Type tpLinha
    Atual   As Long
    Ultima  As Long
End Type
Type tpContador
    Item    As Integer
    Total   As Integer
End Type

O melhor uso para objetos type é agrupar dados referentes a um objeto específico. Por exemplo, em vez de criar variáveis individuais para um cliente, podemos criar uma estrutura type com todas as propriedades que queremos para o cliente, de preferência na mesma ordem que colocaremos na planilha:

Type tpCliente
    Codigo          As Long
    Nome            As String
    DataNascimento  As Date
    CPF             As Long
End Type

Suponha que seu código tenha uma função para pesquisar cliente que retorna um valor Verdadeiro ou Falso caso encontre ou não. A pesquisa poderia ser por código, pelo nome do cliente junto com a data de nascimento (para prevenir problemas com homônimos) ou pelo CPF. Ao invés de enviar cada propriedade individualmente como parâmetro da rotina, podemos colocar o objeto type como único parâmetro. Veja o exemplo da declaração da sub-rotina com parâmetros individuais e com o type como parâmetro:

Function PesquisarCliente(Codigo As Long, Nome As String, DataNascimento As Date, _
    CPF As Long) As Boolean

Function PesquisarCliente(Cliente As tpCliente) As Boolean

A segunda forma é muito mais clara e simples. A primeira pode até assustar pela quantidade de parâmetros.

Da mesma forma, uma sub-rotina para adicionar o cliente fica mais simples com um parâmetro apenas:

Sub AdicionarCliente(Cliente As tpCliente)

Veja como a manutenção fica mais fácil: caso você precise acrescentar campos na planilha de cliente, basta acrescentá-los na declaração do objeto tpCliente e depois editar as sub-rotinas que farão uso desses campos, sem necessidade de editar os parâmetros de cada sub-rotina e função para acrescentar os campos novos.

Outra grande vantagem de usar objeto type é poder contar com o InteliSense do editor de VBA. Assim que teclar o ponto para digitar uma propriedade, o menu aparece:

Desta forma fica mais fácil garantir que não haverá erros de digitação nos nomes das propriedades e também ajuda a lembrar os nomes das propriedades, pois aparecerão na lista.

Lembra das enumerações? As propriedades podem ser combinadas com enumerações, facilitando ainda mais a digitação e a clareza do código. Veja um exemplo com uma enumeração para o tipo de telefone:

Enum enumTipoTelefone
    Celular = 1
    Residencial = 2
    Comercial = 3
    Recado = 4
End Enum
Type tpTelefone
    CodigoCliente   As Long
    Tipo            As enumTipoTelefone
    DDI             As Byte
    DDD             As Byte
    Numero          As Long
End Type

Veja como fica na hora de digitar:
São pequenos detalhes que fazem toda a diferença na hora de fazer manutenção no código. Fica tudo mais organizado, simples e autodocumentado. A bagunça de variáveis declaradas da forma como está no começo do artigo passa a não existir, pois em seu lugar ficarão somente as declarações dos objetos type.

O que achou de conhecer melhor o objeto type? Vai passar a usar? Vai pegar algum projeto existente e fazer alterações para ver se realmente fica mais simples? Prefere usar classes? Comente, dê sua opinião.

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.





Catálogo de aulas (NOVIDADE)

Criei um catálogo de aulas para ajudar você em seus estudos. Acesse clicando na imagem abaixo ou clique aqui.


Postagem Anterior Próxima Postagem