Até agora todos os tipos de dados vistos (Integer, Double, String, Boolean, ) foram tipos de dados atômicos. O tipo de Dados Vetor é um tipo de dados composto por outros tipos de dados.
Basicamente, um vetor é uma seqûência de dados do mesmo tipo. Desta forma, podemos ter um vetor de inteiros, um vetor de strings, etc. O que caracteriza um vetor é o fato de possuir um tamanho, que é o conjunto de posições contidas no vetor, e o fato de estas posições de dados poderem ser acessadas através de um índice.
Uma declaração de um vetor de 20 posições de inteiros é feita da seguinte maneira:
Dim vet(20) as Integer
Em geral, costuma-se deixar o valor de um vetor representado na forma de uma constante:
Const TAM_VET = 20
Dim vet(TAM_VET) as Integer
A primeira posição do vetor é a posição 1. A última é a posição TAM_VET. As posições do vetor podem ser acessadas através de um índice inteiro. Eis aqui alguns exemplos de manipulação do vetor vet:
vet(1) = 22
i=2
vet(i) = 20
vet(i+1) = vet(i) - vet(i-1)
Acessos ao vetor com valores de índice fora do intervalo padrão 1..TAM_VET são considerados ilegais e causam erros de execução no programa. Podemos alterar os valores deste intervalo padrão na declaração, por exemplo:
Dim lucroAnual(1985 To 2010) as Double
faz com que os valores legais de índice para o vetor estejam no intervalo 1985..2010. Note que o tamanho do vetor lucroAnual é 26 = 2010 - 1985 + 1 (a mesma fórmula é usada no cálculo dos vetores no caso padrão: o tamanho de vet é 20 = 20 - 1 + 1; em geral tamanho = PosiçaoFinal - PosiçãoInicial + 1.)
Podemos ter vetores multidimensionais. Um vetor bidimensional é,
em geral, chamado de matriz. A declaração dos vetores
multidimensionais segue o mesmo padrão da declaração dos vetores
unidimensionais:
Dim matriz(50, 10) as String 'Matriz de 50 linhas por 10 colunas
Dim multiDimensional(5, 10, 2) as Double
O acesso a uma matriz se dá através de dois índices; similarmente, um vetor de n dimensões é acessado através de níndices. Em geral, quando mencionamos vetores, temos em mente o caso unidimensional, e é a ele que vamos nos restringir nesta seção.
Com relação ao uso de vetores como parâmetros de funções e procedimentos:
Como conseqüência deste último fato, a alteração de vetores dentro de uma função ou procedimento se dá por efeito colateral. Com isso queremos dizer que, se um vetor é passado para uma função e, no interior desta função este vetor é alterado, esta alteração será percebida na função ou procedimento que chamou a função.
Isto é o que ocorre na função ColVet() abaixo, que lê uma coluna e copia seus valores um um vetor. Esta função recebe um vetor como parâmetro e, ao retornar, além de retornar o número de posições lidas, o valor do vetor está alterado, contendo uma cópia dos valores contidos na coluna.
Vamos considerar um exemplo. Considere uma planilha que contém, em uma coluna, valores positivos e negativos. Queremos eliminar os valores negativos (pois supostamente representam valores ilegais) eliminar as células ocupadas por estes valores. Por exemplo, queremos transformar:
12,50
12,50
-4,00
5,20
5,20
em
7,00
-9,50
7,00
Para resolver este problema, vamos dividi-lo em uma série de funções e macros auxiliares, de acordo com a seguinte descrição geral da solução:
Antes de iniciar o detalhamento, vamos mostrar as constantes usadas no módulo.
Const TamVet = 20
Const LinhaInicial = 2
Const ColunaFoco = 1
Começamos mostrando a macro principal, que invoca todas as outras funções e procedimentos , além de realizar a compactação do vetor no item 3.
Sub EliminaNeg()
Dim i As Integer
Dim tam1 As Integer 'Tamanho inicial do vetor
Dim tam2 As Integer 'Tamanho do vetor compactado
Dim iniVet(TAM_VET) As Double 'Vetor inicial
Dim CompactVet(TAM_VET) As Double 'Vetor compactado
'Lê coluna sob Foco, no máximo TAM_VET posições
tam1 = ColVet(ColunaFoco, iniVet(), LinhaInicial, TamVet)
tam2 = 0
'Zera posições negativas
Call ApagaNeg(iniVet(), tam1)
i = 1
'Principal
Do While i <= tam1
If iniVet(i) > 0 Then
'Copia de iniVet para CompactVet
tam2 = tam2 + 1
CompactVet(tam2) = iniVet(i)
End If
i = i + 1
Loop
'Copia CompactVet para a coluna
Call VetCol(ColunaFoco, compactVet(), LinhaInicial, tam2)
'Esvazia demais posições
Call Esvazia(ColunaFoco, tam2 + LinhaInicial, tam1 + LinhaInicial - 1)
End Sub
Em seguida mostramos o item 2, que é uma subrotina que altera um vetor, mudando todos os valores negativos para 0. Como parâmetro, recebe o vetor e o seu tamanho:
Sub ApagaNeg(vet() As Double, tam As Integer)
Dim i As Integer
i = 1 'Inicialização
Do While i <= tam
If vet(i) < 0 Then
vet(i) = 0
End If
i = i + 1 'Proxima linha
Loop
End Sub
Em seguida, o item 1 é feito pela função ColVet(), que recebe como parâmetros a coluna a ser copiada, o vetor a ser alterado, o valor da primeira linha a ser copiada e o número máximo de posições que o vetor suporta. A função retorna o número de posições realmente lidas, que pode ser menor que o tamanho máximo.
Function ColVet(col As Integer, vet() As Double, iniLin As Integer, tamMax As Integer)
Dim i As Integer
Dim lin As Integer
i = 1
lin = LinhaInicial
Do While i <= tamMax And Not IsEmpty(Cells(lin, col))
'Lê célula atual
vet(i) = Cells(lin, col)
'Próxima linha
i = i + 1
lin = lin + 1
Loop
'Retorno
ColVet = i - 1
End Function
O item 4 é feito pelo procedimento VetCol(), o oposto de ColVet(), que copia um vetor para uma coluna da planilha. Os parâmetros são os mesmos e não há necessidade de retornar nenhum valor, uma vez que o tamanho do vetor já é conhecido.
Sub VetCol(col As Integer, vet() As Double, iniLin As Integer, tam As Integer)
Dim i As Integer
i = 1
Do While i <= tam
Cells(i + iniLin - 1, col) = vet(i)
i = i + 1
Loop
End Sub
Por fim, o procedimento que apaga as linhas restantes.
Sub Esvazia(col As Integer, iniLin As Integer, fimLin As Integer)
Dim lin As Integer
lin = iniLin
Do While lin <= fimLin
Cells(lin, col) = Empty
lin = lin + 1
Loop
End Sub
Exercícios
Nota: Algumas versões do Excel podem vir com o padrão de indexação diferente daquele apresentado nesse cap'itulo. Para garantir que todos os vetores possuem a primeira posição indexada por 1 (e não por 0), basta adicionar no início do seu módulo (antes das declarações de Const) a seguinte instrução:
Option Base 1
Você deve usar uma função auxiliar que recebe um vetor e retorna o índice da posição que contém o menor valor. Não se esqueça que este valor do índice não é o mesmo que o valor da linha que contém o menor valor, pois a linha inicial na coluna considerada não é necessariamente a primeira.