VBA - Artigo 008 - Array e Collection


Array e Collection

Há momentos em que precisamos trabalhar com algumas variáveis similares para armazenar valores diferentes. Por exemplo, precisamos de variáveis para armazenar posição inicial e comprimento dos campos em um arquivo. Você pode definir PosInicial1, Comprimento1, PosInicial2, Comprimento2 etc, mas não é muito prático, principalmente se houver a possibilidade de aumentar os campos no futuro. Seria melhor ter uma estrutura como uma matriz para armazenar os dados, certo? E tem, é o tipo de dado Array. Ele pode ser usado de forma unidimensional ou multidimensional:

Dim UmaDimensao(9)  ' Vai de [0] a [9], são 10 itens
Dim DuasDimensoes(5, 2)  ' Vai de [0, 0] a [5, 2], mas o tamanho é [6, 3]
Dim TresDimensoes(2, 2, 2)  ' Vai de [0, 0, 0] a [2, 2, 2], tamanho [3, 3, 3]

É possível mudar a posição inicial do Array, definindo os valores iniciais e finais da matriz. Vamos criar uma que vai de 1 a 10:

Dim Matriz(1 To 10) ' Vai de 1 a 10

Você pode achar essa forma pode ser mais fácil de trabalhar, é mais intuitivo contar de 1 a 10 do que de 0 a 9, a não ser que seja um programador experiente e habituado a essa forma. Mas é possível começar com qualquer valor:

Dim Matriz2(4 To 6, 8 To 10) ' Vai de [4, 8] a [6, 10]

Essa matriz não parece muito prática, mas pode haver ocasiões em que seja preciso trabalhar dessa forma.  É preciso ter bastante cuidado para não tentar acessar valores que estão fora da faixa definida. Se for definido que os valores vão de 1 a 10, não pode usar 0 ou 11, pois vai dar erro.

As matrizes acima foram dimensionadas como sendo do tipo Variant, pois não foi especificado o tipo nas declarações. É uma boa prática sempre declarar o tipo de dado, porque objetos do tipo Array alocam uma grande área de memória e se for do tipo Variant aumenta ainda mais o espaço usado. Portanto:

Dim NotaBimestral(1 To 4, 1 To 50) as Single

Esse exemplo armazena as 4 notas bimestrais para 50 alunos em formato Single, que é suficiente para a maioria das classes.  Entretanto, nem todas as classes têm 50 alunos e seria preciso se atentar não processar os dados onde não há alunos. Seria necessário codificar um Array dinâmico, que pode ser alterado em tempo de execução. Isso é possível, criando uma matriz dinâmica (sem tamanho especificado) e dimensionando quando for utilizar:

Dim NotaBimestral() as Single
Dim NumAlunos as Byte  ' Formato byte vai de 0 a 255

NumAlunos = 38
Redim NotaBimestral(1 To 4, 1 To NumAlunos)

Podemos alterar o valor do número de alunos em tempo de execução e redimensionar a matriz de notas dos alunos. Como vimos acima, Arrays alocam muito espaço de memória, portanto é uma boa prática liberar quando não houver mais necessidade, desta forma:

Erase NotaBimestral

Há ainda as instruções LBound e UBound, que indicam o limite inicial e final do Array. Podemos utilizá-los em estruturas de repetição For...Next:

For Iteracao = LBound(Matriz) To UBound(Matriz)
    ' Instruções
Next

Para Arrays com uma dimensão é bem prático, mas como fazemos quando há mais de uma dimensão?  LBound e UBound aceitam dois parâmetros: o tipo de dado Array em si e a posição da dimensão, que é parâmetro opcional. O exemplo das notas dos alunos ficaria desta forma:

For Aluno = LBound(Matriz, 2) To UBound(Matriz, 2)    ' 2 de segunda posição
    For Nota = LBound(Matriz, 1) To UBound(Matriz, 1) ' 1 de primeira posição
        ' Instruções
    Next Nota
Next Aluno

Faça uns testes com matrizes de uma e mais dimensões e execute passo a passo (tecla F8) para praticar. Logo você verá algum lugar em que poderia ter usado um tipo de dado Array ou mesmo verá uma possibilidade em um projeto em andamento.

O objeto Collection é um pouco mais simples. Ele permite adicionar valores de qualquer tipo a uma coleção de dados. Seu formato é exclusivamente Variant, não é possível definir como um tipo definido. É possível colecionar números, textos e até mesmo objetos na mesma coleção, portanto muita atenção com o que estiver colecionando. Veja um exemplo:

Dim Colecao As Collection
Set Colecao = New Collection

Colecao.Add 10
Colecao.Add "ABC"
Colecao.Add ActiveSheet

Perceba que juntar tipos diferentes não é algo prático, porque quando será trabalhoso pesquisar os dados que estão na coleção. A não ser em casos muito específicos, você irá colecionar sempre o mesmo tipo de dados.
Vejamos um exemplo mais usual:

Sub Frutas()

    Dim Frutas As Collection
    Set Frutas = New Collection
   
    Frutas.Add "Maçã"
    Frutas.Add "Banana"
    Frutas.Add "Laranja"
    Frutas.Add "Maçã"
   
    For Iteracao = 1 To Frutas.Count
        Debug.Print Iteracao & ": "; Frutas.Item(Iteracao)
    Next

    Frutas.Remove(1)

End Sub

Perceba que maçã foi adicionada duas vezes e que não aparece nenhum alerta de duplicidade. É preciso ficar atento para não adicionar várias vezes o mesmo item.  Nesse exemplo vemos todas os métodos da coleção: Add, Count, Item e Remove, cujas funções são bem simples e autoexplicativas. O método Item nem precisa ser escrito, é possível usar a forma Frutas(Iteracao). Não há nenhum método que permite verificar se um item já existe ou não, a melhor saída é codificar uma função para isso.

Function VerificarFruta(Fruta as string) as Boolean

    VerificarFruta = False

    For Each Item In Frutas
        If Item = Fruta Then
            VerificarFruta = True
            Exit For
        End If
    Next

End Function

Neste exemplo usei o For Each... Next ao invés do velho conhecido For... Next. Se não conhece essa estrutura ainda, analise o código para entender o funcionamento, que é bem simples. Ele varre todo o conteúdo da coleção e, se encontrar algum item que seja a fruta verificada, a função irá retornar Verdadeiro. Se não encontrar a fruta na lista, retornará Falso.

Há a opção de utilizar uma chave para indexar a coleção. Esse é um argumento opcional e não precisa ser colocado em todos os itens. Entretanto, o formato a ser usado é string, não é possível associar chaves numéricas. Vejamos o exemplo abaixo:

Sub Frutas()

    Dim Frutas As Collection
    Set Frutas = New Collection
   
    Frutas.Add "Maçã", "1"
    Frutas.Add "Banana", "9"
    Frutas.Add "Laranja", "5"

    Debug.Print Frutas("3")

End Sub

As chaves, sendo strings, precisam ser colocadas entre aspas. Elas podem ser qualquer texto, neste exemplo optei por colocar números não sequenciais. Se executar o código dará um erro, pois a chave "3" não existe. Se usar Frutas(3) (sem aspas), retornará "Laranja", que é o terceiro item da coleção.

A coleção tem ainda mais dois argumentos opcionais: Before e After. Use quando for preciso adicionar um item à coleção em uma posição específica. Exemplos:

    Frutas.Add "Cereja", Before:=1
    Frutas.Add "Amora", After:=1

Cereja e amora serão acrescentadas no início da coleção. Cereja será colocada antes do primeiro item, enquanto amora será colocada após o primeiro item, que é a cereja. Se invertermos a ordem dessas linhas, amora será colocada na primeiramente na segunda posição, mas ao acrescentar cereja na primeira ela será empurrada para a terceira posição. Teste essas linhas no exemplo que exibe os itens e confira.

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