Escolar Documentos
Profissional Documentos
Cultura Documentos
Texto Introdutório
versão 3
António Silva
DEI-Isep
2009-12-30
EP
IS
1
.
IS
EP
Conteúdo
1 Introdução 9
2 Conceitos Básicos 9
2.1 O que é um Macro? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 9
2.2 Técnicas de construção dum Macro . . . . . . . . . . . . . . . . . . . . . 10
2.3 Gravação de um Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . 10
2.4 A escrita de um Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.5 O editor de VBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
2.6 Criação de um Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
3
5.2.1 Estruturas de Controlo Do...Loop . . . . . . . . . . . . . . . . . . 44
5.2.2 Ciclos controlados por contador . . . . . . . . . . . . . . . . . . . 45
5.2.3 Exemplo integrador . . . . . . . . . . . . . . . . . . . . . . . . . . 47
5.2.4 Ciclos controlados por sentinela . . . . . . . . . . . . . . . . . . . 49
5.2.5 Estrutura de Controlo For..To..Next . . . . . . . . . . . . . . . . . 50
5.2.6 Estruturas de controlo repetitivo imbricadas . . . . . . . . . . . . 52
7 Funções e Procedimentos 62
7.1 Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 62
7.2 Exemplos de funções criadas pelo programador . . . . . . . . . . . . . . . 63
7.3 Passagem de parâmetros ByVal . . . . . . . . . . . . . . . . . . . . . . . 66
7.4 Procedimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 67
7.5 Passagem de parâmetros ByRef . . . . . . . . . . . . . . . . . . . . . . . 68
7.6 Como aceder às funções standard do Excel . . . . . . . . . . . . . . . . . 69
10 Manipulação de texto 83
10.1 Funções de manipulação de strings . . . . . . . . . . . . . . . . . . . . . 83
10.1.1 Trim, LTrim e RTrim . . . . . . . . . . . . . . . . . . . . . . . . . 83
10.1.2 Len . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
10.1.3 Left, Right . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 83
10.1.4 Mid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
10.1.5 InStr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 84
10.1.6 UCase, LCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
10.2 Algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85
4
10.2.1 Separação duma string em caracteres . . . . . . . . . . . . . . . . 85
10.2.2 Divisão de uma frase em palavras . . . . . . . . . . . . . . . . . . 86
11 Notas finais 88
EP
IS
5
Lista de Figuras
1 Janela de invocação do ambiente de Gravação de Macros . . . . . . . . . 10
2 Janela de Gestão de Macros . . . . . . . . . . . . . . . . . . . . . . . . . 11
3 Barra de Ferramentas de VBA . . . . . . . . . . . . . . . . . . . . . . . . 11
4 Editor integrado do VBA . . . . . . . . . . . . . . . . . . . . . . . . . . . 12
5 Criação de novo Módulo . . . . . . . . . . . . . . . . . . . . . . . . . . . 13
6 Diferentes tipos de dados e o seu armazenamento em memória . . . . . . 17
7 Como forçar a declaração explícita automaticamente . . . . . . . . . . . 18
8 Uma Form e vários Controlos . . . . . . . . . . . . . . . . . . . . . . . . 22
9 Janela de Propriedades . . . . . . . . . . . . . . . . . . . . . . . . . . . . 24
10 Lista de eventos disponíveis . . . . . . . . . . . . . . . . . . . . . . . . . 25
11 Objectos e Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 26
12 Exemplo de MsgBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 29
13 Exemplo de InputBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . 31
14 Vários optionButton agrupados numa frame . . . . . . . . . . . . . . . . 34
15 Vários checkBox agrupadas numa frame . . . . . . . . . . . . . . . . . . 35
16 Uma Frame agrupando três botões de comando . . . . . . . . . . . . . . 35
17 Exemplo de listBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 36
18 Interface construída directamente na folha de cálculo . . . . . . . . . . . 38
19 Estrutura de controlo condicional If...Then...Else . . . . . . . . . . . . . 39
20 Estrutura de controlo condicional If...Then . . . . . . . . . . . . . . . . 40
21 Estruturas de controlo condicional imbricadas . . . . . . . . . . . . . . . 43
22 Estrutura de controlo repetitivo Do...While . . . . . . . . . . . . . . . . 44
EP
6
Lista de Tabelas
1 Tipos de dados suportados pelo VBA . . . . . . . . . . . . . . . . . . . . 20
2 Propriedades mais comuns dos objectos gráficos VBA . . . . . . . . . . . 23
3 Valores de configuração das características de uma Caixa de Mensagem . 30
4 Valores devolvidos por uma Caixa de Mensagem . . . . . . . . . . . . . . 30
EP
IS
7
Listings
1 VerificaValor - exemplo de macro . . . . . . . . . . . . . . . . . . . . . . 14
2 verificaGama - exemplo de macro . . . . . . . . . . . . . . . . . . . . . . 14
3 Exemplo de aplicação de If..Then..Else imbricados . . . . . . . . . . . . 43
4 FormataBordo - exemplo de sub-rotina usando For..Next . . . . . . . . . 51
5 Exemplo usando Ciclos Imbricados . . . . . . . . . . . . . . . . . . . . . 53
6 Exemplo de Sub-rotina usando Ciclos Imbricados . . . . . . . . . . . . . 53
7 Exemplo de processamento de um vector . . . . . . . . . . . . . . . . . . 57
8 Outro exemplo de processamento de um vector . . . . . . . . . . . . . . . 58
9 Soma de matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 60
10 Função mLucro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 63
11 Função factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 64
12 Programa de cálculo de Combinações . . . . . . . . . . . . . . . . . . . . 65
13 Diferentes resultados na passagem por valor e por referência . . . . . . . 68
14 Sub-rotina InsereLinhas . . . . . . . . . . . . . . . . . . . . . . . . . . . 74
15 Handler do objecto cmdFechar para o evento click . . . . . . . . . . . . 78
16 Exemplo de sub-rotina de invocação de uma UserForm . . . . . . . . . . 79
17 Exemplo de sub-rotina de inicialização de uma UserForm . . . . . . . . . 79
18 Handler do objecto cmdFechar para o evento Click . . . . . . . . . . . . 80
19 Sub-rotina de inicialização da UserForm . . . . . . . . . . . . . . . . . . 81
20 Handler associado ao objecto Tabstrip1 para o evento Change . . . . . . 82
21 Separação de string em caracteres - 1o Método . . . . . . . . . . . . . . . 85
22 Separação de string em caracteres - 2o Método . . . . . . . . . . . . . . . 86
EP
8
1 Introdução
Este texto tem como objectivo apoiar o ensino das técnicas de programação de com-
putadores, utilizando, como ambiente de aplicação, programas como o gestor de folhas
de cálculo Excel. Destina-se, assim, aos alunos que já possuem alguns conhecimentos
da utilização e funcionamento desta aplicação. Concretamente, presume-se que estão já
familiarizados com os conceitos de folha de cálculo, de livro de trabalho, de fórmulas e
de funções standard.
A linguagem de programação que vai ser utilizada será o VBA (Visual Basic for
Applications). É uma linguagem que permite acrescentar capacidades adicionais a certo
tipo de aplicações informáticas, concretamente as pertencentes ao Microsoft Office, entre
as quais o Excel e o Word. Permite ainda automatizar a realização de muitas tarefas
rotineiras nessas aplicações.
Como o próprio nome indica, trata-se duma adaptação da linguagem genérica de
programação Visual Basic de modo a poder ser utilizada no ambiente específico das
aplicações Office.
2 Conceitos Básicos
O VBA constitui uma ferramenta poderosa nas mãos de programadores experimentados
mas pode, ao mesmo tempo, ser muito útil a um utilizador normal, mesmo inexperiente.
De facto, no dia a dia da utilização destas aplicações, defrontamo-nos com a neces-
sidade de repetir a mesma tarefa várias vezes ao dia ou, de em certas ocasiões, ter que
EP
repetir uma determinada tarefa uma série de vezes de seguida. Seja escrever ou formatar
um certo texto, seja executar uma série de comandos ou escolher opções de menus, seja
ainda realizar a formatação complexa de um documento, são inúmeras as ocasiões em
IS
9
2.2 Técnicas de construção dum Macro
Se bem que um macro seja um programa em VBA, nem sempre é necessário escrevê-lo de
forma explícita, ou seja, detalhando especificamente as instruções VBA que o compõem.
Sobretudo quando os macros são simples, é muitas vezes mais prático criá-los de forma
automática, gravando a sequência de passos que ele deverá executar na aplicação.
Esta forma de criar um macro corresponde a mostrar ao computador o que fazer
para conseguir obter o resultado pretendido. O utilizador indica ao programa que se
vai entrar num modo de gravação do macro e inicia a execução da sequência de acções
que normalmente teria que executar. Quando chega ao fim dessa sequência, indica ao
programa que a gravação terminou. Após ter atribuído a essa sequência uma combinação
de teclas especial, esse macro estará pronto a ser executado, substituindo assim o conjunto
de acções que anteriormente seriam necessárias. Tudo se passa como se estivéssemos a
ensinar a aplicação pelo exemplo.
Se se investigar, no entanto, o conteúdo desse macro, verificar-se-á que ele é composto
precisamente por instruções escritas em VBA, sendo que a cada acção ou comando da
aplicação corresponderá uma instrução (ou conjunto de instruções) específica do macro.
A forma alternativa de construir um macro será assim introduzir essas instruções num
editor de texto apropriado. É essa, de facto, a forma de criar um macro quando o seu
âmbito é algo não trivial1 .
Para gravar um macro que seja capaz de efectuar essas acções, haverá que invocar o
modo de gravação de macros, mediante o Menu "Tools/Macros/Record a New Macro"
(em Excel), o que fará aparecer a janela descrita da Figura 1. Nela se pode especificar o
nome do macro, a localização em que será armazenado, uma descrição das suas funções
1
A tratar na Secção 2.6 na página 13.
10
e ainda a combinação de teclas (Shortcut key) que será utilizada para arrancar com o
macro, uma vez este construído.
Após se premir a tecla OK, aparecerá uma pequena janela que permitirá controlar
o processo de gravação e dever-se-á dar início à execução das acções que o macro vai
substituir. Quando se tiver executado a última acção a incluir no macro, basta dar, nessa
janela, a indicação de que a gravação terminou.
Uma vez tal realizado, esse macro passará a estar disponível mediante a invocação
da combinação de teclas especificada anteriormente (no caso da Figura 1 na página pre-
cedente, seria Ctrl+Shft+M) e realizará, de forma automática, exactamente a mesma
sequência de acções que tínhamos efectuado manualmente.
EP
11
2.4 A escrita de um Macro
Ensinar pelo exemplo ao Excel como fazer as coisas é um método expedito de construir
um macro, mas tem as suas limitações. Já que um macro não é mais que um programa
escrito em VBA, porque não tratá-lo como tal e aceder ao seu código, alterando-o de
forma a melhorar a sua eficiência ou a corrigir problemas. E já agora, porque não criá-los
de raiz, aproveitando todo o poder duma linguagem como o VBA?
Do lado esquerdo na Figura 4 podem-se ver duas janelas, a primeira das quais é
designada por Explorador de Projectos e que serve para mostrar o conteúdo do projecto
VBA actual. Um projecto em VBA inclui um ficheiro duma aplicação Office (como, por
12
Figura 5: Criação de novo Módulo
exemplo, uma folha de cálculo do Excel) e todos os ficheiros VBA associados, incluindo
os próprios macros e eventuais user forms (janelas de interface próprias utilizadas pelos
macros2 ).
Para poder começar a escrever macros usando o VBA é necessário criar um módulo
que o possa albergar, o que é conseguido usando a opção de menu "Insert/Module". Como
consequência, para além do novo módulo aparecer referido na janela do Explorador de
EP
Projectos, será criada uma janela nova onde será possível escrever o código que constitui o
novo macro. Se já existir algum módulo criado, bastará seleccionar o módulo pretendido
IS
13
nome (verificaValor). O corpo do macro é composto pela estrutura de controle condici-
onal (If...Then 4 ) que vai verificar se o conteúdo da célula B25 é ou não maior que o valor
200. Caso essa condição seja verdadeira, o macro apresentará uma mensagem no ecran
dizendo que o valor máximo foi excedido. Finalmente, o macro é terminado com uma
linha contendo "End Sub".
Listing 1: VerificaValor - exemplo de macro
1 Public Sub v e r i f i c a V a l o r ( )
2 I f C e l l s ( 2 , 2 ) > 100 Then
3 MsgBox " Valor ␣maximo␣ e x c e d i d o ! "
4 End I f
5 End Sub
O que este simples macro faz, portanto, é verificar o conteúdo de uma célula específica
da folha de cálculo e avisar o utilizador caso o valor nela contido ultrapassar um valor
pré-determinado. Sempre que for necessário fazer esta verificação, bastará invocar a
combinação de teclas que tenha sido associada a este macro.
É verdade que esta verificação poderia ter sido realizada colocando numa célula uma
fórmula contendo a função standard do Excel IF. Mas suponhamos agora que se pretende
algo mais complicado, por exemplo, fazer essa verificação num conjunto de células e
apenas desencadear o alarme caso mais do que duas dessas células ultrapassem o limite
estabelecido. A sub-rotina modificada poderia ser algo como:
Listing 2: verificaGama - exemplo de macro
EP
1 Public Sub v e r i f i c a G a m a ( )
Dim i As Integer , c As Integer
IS
3 c = 0
4 For i = 1 To 5
5 I f C e l l s ( i , 3 ) > 100 Then
6 c = c + 1
7 End I f
8 Next
9 I f c > 2 Then
10 MsgBox c & "␣ v a l o r e s ␣ s u p e r i o r e s ␣ ao ␣ l i m i t e ! "
11 End I f
12 End Sub
14
Estaremos já em posição de perceber a utilidade de construir os macros usando di-
rectamente o VBA. Não seria trivial resolver este problema usando apenas fórmulas e
certamente impossível executando comandos e seleccionando menus do Excel.
A um macro criado usando directamente o VBA pode também ser associada uma
combinação de teclas que facilite o seu acesso. Isso pode ser feito através do botão Options
na Janela de Gestão de Macros, invocada mediante a combinação de teclas ALT-F8.
EP
IS
15
3 Variáveis e Tipos de Dados
A informação processada por um macro pode ser de diferente natureza e existir em
diferentes formatos. Genericamente um programa pode utilizar, entre outras, informação
numérica e informação chamada alfa-numérica, ou seja texto. A linguagem VBA consegue
lidar com informação de diversos tipos, que detalharemos mais adiante na Secção 3.4 na
página 20.
O tipo da variável especifica qual o tipo de dados que pode conter. Uma variável de
um determinado tipo não está preparada para armazenar dados de um tipo diferente.
EP
A razão para este facto é que o espaço necessário para armazenar diferentes tipos de
dados não é o mesmo. Enquanto um inteiro simples pode ser guardado em 2 bytes de
IS
memória 8 , para guardar um número real podem ser necessários 8 bytes (ou mesmo mais,
dependendo da precisão requerida). A Figura 6 na página seguinte ilustra graficamente
esta realidade. Enquanto que uma idade (valor inteiro) pôde ser guardada numa variável
do tipo integer, dimensionada para armazenar valores inteiros, já um peso (valor real) teve
que ser guardado numa variável do tipo single, com a dimensão adequada a armazenar
valores reais de uma dada precisão9 .
16
Figura 6: Diferentes tipos de dados e o seu armazenamento em memória
EP
do nome pelo qual ela será conhecida assim como qual o tipo de dados que ela deverá
estar preparada para receber.
IS
Como é óbvio, nenhuma variável pode ser utilizada antes de ser criada. A declaração
deve, pois, preceder a sua utilização. Desde que se siga esta regra, é possível inserir
declarações em qualquer ponto do macro. No entanto, é boa prática agrupar todas as
declarações necessárias num bloco a colocar no início, para mais fácil manutenção do
programa.
Em VBA, existem duas formas de declaração de variáveis: explícita e implícita. A
declaração explícita exige a utilização da instrução
Dim ... As ... (Dimensionar ... Como ...)
Por exemplo, a instrução
Dim Preço As Integer
cria (declara) uma variável com o nome Preço e do tipo Integer, ou seja, dimensio-
nada para receber dados do tipo integer (inteiro simples10 ).
A declaração implícita resume-se a utilizar pela primeira vez uma variável sem qual-
quer declaração explícita prévia, dando-lhe um nome e atribuindo-lhe um valor. O VBA
encarregar-se-á de criar automaticamente a variável do tipo pretendido.
Esta segunda forma de declarar variáveis tem, a despeito da sua simplicidade, um
10
A discussão dos vários tipos de dados suportados pelo VBA será feita na Secção 3.4.
17
problema grave: é possível, por distracção, criar uma variável nova indesejada, quando o
que se pretendia era apenas escrever o nome de uma variável já existente. Suponha, por
exemplo, que havia criado uma variável "Distancia" mediante a instrução11 :
Distancia=1260
Como é a primeira vez que o VBA encontra esta palavra ("Distancia"), partirá do
princípio que se trata de uma variável ainda por declarar e tratará de a criar, substituindo-
se ao programador. Dar-lhe-á o nome "Distancia" e dimensiona-la-á de forma a poder
guardar inteiros simples, já que é essa a utilização sugerida na instrução.
Agora suponha que adiante no programa, por engano, escrevia "Distncia" ao referir-se
à variável em causa. O VBA não emitirá nenhum alerta, já que aceitou tranquilamente
"Distncia" como uma nova variável. A forma mais prudente de lidar com declarações de
variáveis é, pois, utilizar apenas declarações explícitas, e instruir o VBA para não aceitar
declarações implícitas, gerando uma mensagem de erro apropriada. Para tal, deverá ser
acrescentada a instrução Option Explicit no início do módulo contendo o macro.
EP
IS
18
variáveis podem ser declaradas fora de qualquer módulo, então teremos que adicionar
uma característica adicional à definição de uma variável: o seu âmbito.
Por âmbito entende-se a zona do programa em que a variável é conhecida, ou seja,
em que pode ser utilizada. Esta zona está directamente relacionada com o local em que a
variável foi declarada. Para esclarecer melhor este ponto, atente-se na Listagem 3.3, em
que podemos ver duas sub-rotinas, sub1 e sub2, em que são criadas e utilizadas diversas
variáveis, e ainda uma variável n que foi declarada fora de qualquer sub-rotina.
1 Dim n As integer
2 ...
3
7 i = 10
8 n = 100
9 ...
10 End Sub
11
15 c = n ∗ 10 + i
...
EP
16
17 End Sub
IS
Na sub-rotina sub1 é usada quer a variável i (até aqui, nada de mais já que essa
variável foi criada na própria sub-rotina) quer a variável n. Ora, esta segunda variável
não lhe pertence, não foi declarada dentro de si. Tal é possível, porque, sendo exterior à
sub-rotina, foi declarada como variável dita global, fora de qualquer sub-rotina e, como
tal, acessível por qualquer módulo que a ela queira aceder. Por seu lado, a variável i
diz-se local já que o seu âmbito se restringe à sub-rotina em que foi declarada.
Na instrução da linha 15 da listagem, contida na sub-rotina sub2, são acediadas
três variáveis: c pertencendo à própria sub-rotina, a variável global n e a variável i. A
utilização da variável global já foi discutida. Vale a pena, porém, discutir a utilização da
variável i. Esta variável, se bem que tenha o mesmo nome de outra pertencendo a sub1,
é uma entidade diferente. A partilha do nome é mera coincidência. Assim sendo, e não
tendo sido guardado previamente qualquer valor na variável i dentro de sub2, o seu valor
por defeito será zero, pelo que o resultado da expressão armazenado em c será ( 10 x 100
+ 0 = 1000 ).
Impõe-se uma alerta relativamente à utilização de variáveis globais. O facto de po-
derem ser acedidas indistintamente por qualquer módulo torna a sua utilização muito
flexível e, em certos caso, insubstituível. No entanto, especial atenção deve ser prestada
a eventuais interacções indesejáveis entre módulos. Se muitas entidades acederem a uma
mesma variável global, modificando o seu conteúdo, pode tornar-se difícil detectar qual
o módulo responsável por valores anómalos que possam surgir nessa variável.
19
3.4 Tipos de Dados
Como já vimos, um macro deverá poder lidar com diferentes tipos de dados. A lingua-
gem VBA suporta, entre outros, o tratamento dos seguintes tipos de dados descritos na
Tabela 1.
Tipo Descrição
Integer Inteiro simples, usado para representar inteiros entre -32768 e 32767
Long Inteiro longo, ou seja, compreendido entre -2.147.483.648 e
2.147.483.647
Single Real representado com precisão simples, com valores negativos compre-
endidos entre cerca de -3,4E38 e -1,4E-45 e valores positivos entre cerca
de 1,4E-45 e 3,4E38
Double Real representado com precisão dupla, usado para representar números
reais muito maiores ou muito mais pequenos que com o tipo single
String Usado para representar texto (informação alfanumérica como letras,
algarismos e símbolos especiais); strings são apresentadas entre aspas
Boolean Usado para representar valores lógicos (True ou False)
Date Usado para representar datas ou valores de tempo; são representados
entre caracteres #
Object Serve para guardar referências a objectos
que ela irá suportar. No entanto, em VBA é possível omitir a especificação do tipo de
dados na declaração de variáveis. O VBA criará, nesse caso, uma variável do tipo Variant
IS
capaz de armazenar qualquer tipo de dados. O que, à partida, parece uma boa ideia acaba
por não o ser porque, entre outros motivos, implica um gasto excessivo de memória e torna
a execução dos macros mais lenta. Será, portanto, de evitar, na medida do possível.
20
total = peso1 + peso2
resultado = sqrt(2+peso)
No 1o exemplo, o VBA resolverá em primeiro lugar a expressão à direita do operador
de atribuição (=), somando os conteúdos das variáveis peso1 e peso2, após o que copiará
esse resultado para a variável total.
No 2o exemplo, a expressão à direita é composta pela função standard do VBA sqrt().
Esta função calcula a raiz quadrada do valor ou expressão que se encontrar dentro dos
seus parêntesis. Assim sendo, o VBA calculará em 1o lugar o resultado da expressão 2 +
peso, fornecerá esse valor à função sqrt(), após o que copiará o valor fornecido por essa
função para a variável resultado.
É importante que se perceba que a operação de atribuição é uma operação destrutiva.
Se a variável contiver já um valor, uma operação subsequente de atribuição sobre essa
variável, substituirá o valor nela contido pelo novo valor. Convem, assim, lembrar que
nesta operação o fluxo da informação se faz sempre da direita para a esquerda e não o
contrário.
Há ainda que ter em atenção o facto de que não é normalmente aconselhável atribuir
um valor de um dado tipo a uma variável de tipo diferente. Os resultados podem ser a
perda de informação ou o mau funcionamento do programa. O VBA poderá gerar uma
mensagem de erro mas tal nem sempre acontece, podendo produzir-se comportamentos
anómalos difíceis de detectar e corrigir.
Uma constante consiste num nome que é dado a um valor numérico ou a uma cadeia de
caracteres, e que pode ser usado dentro do programa na vez desses valores. Funciona
IS
21
4 Como trabalhar com Objectos
Para que uma macro possa manipular o ambiente da aplicação, seja modificando a forma-
tação de um documento, modificando opções da aplicação ou introduzindo dados numa
gama de células, vai ser preciso interagir com Objectos. Genericamente, pode dizer-se que
um objecto é algo que pode ser visto, tocado, sentido. Em VBA, considera-se um objecto
tudo aquilo que pode ser visto e que pode ser manipulado de alguma forma.
Quer o documento, quer uma célula ou gama de células, quer a própria aplicação
são considerados, para os efeitos de programação em VBA, como sendo objectos. Mas
podem ainda existir outros objectos, nomeadamente aqueles que permitem construir uma
interface gráfica específica do macro. A esses objectos gráficos chamamos controlos e são
colocados em janelas especiais chamadas forms.
Na Figura 8 podem ser observados vários objectos instalados numa form: uma caixa
de texto, dois botões de comando, vários rótulos ou etiquetas e uma caixa de verificação.
Através de elementos como estes é possível o macro interagir com o utilizador. Veremos
em detalhe mais à frente para que servem e como utilizar estes diferentes objectos.
EP
IS
22
• Os seus "métodos" especificam o que pode ser feito com ele: acelerar, travar, mudar
de direcção, etc;
• Os seus "eventos" são ocorrências que provocarão respostas automáticas por parte
do automóvel, como seja, um alarme que dispara (resposta) caso desliguemos o
carro com as luzes ligadas (evento).
4.1.1 Propriedades
As propriedades de um objecto traduzem as suas características físicas e formas de com-
portamento. Como na vida real, cada objecto possui características próprias ou propri-
edades, que podem ser quantificadas ou especificadas, como sejam as suas dimensões ou
o tipo de letra que usa. A cada objecto está associada uma lista de propriedades a que
é possível atribuir valores, determinando a sua aparência, localização e outros detalhes.
Pode-se então dizer que as propriedades de um objecto definem a forma como ele se
apresenta ou se comporta.
Diversas classes de objectos podem partilhar a mesma propriedade. Essa propriedade,
no entanto, pode afectar esses objectos de forma diferente.
Já vimos que quer os elementos do Excel como folhas de cálculo ou próprio docu-
mento, quer elementos constituintes de interfaces gráficas que os macros possam utilizar,
são considerados objectos. Na Tabela 2 são descritas algumas das propriedades mais
importantes e que são comuns à maior parte dos objectos gráficos.
No caso dos objectos gráficos, os valores que as propriedades de um dado objecto
tomam podem ser consultados ou modificados usando a janela de propriedades (Figura 9
na próxima página). Nessa janela aparece a lista de propriedades do objecto que estiver
nesse momento seleccionado . Nela pode observar, entre outras, algumas das propriedades
referidas na lista acima (Caption, Height e Font) e os respectivos valores no momento.
23
Figura 9: Janela de Propriedades
4.1.2 Métodos
Os métodos traduzem acções que um macro pode realizar sobre os objectos. Por exem-
plo, aplicar o método Save ao objecto ActiveDocument implica desencadear o processo
de salvaguarda do conteúdo do documento activo num determinado ficheiro. Aplicar o
método Clear a um objecto da classe ListBox (tratada na Secção 4.3.10 na página 36)
terá como consequência a eliminação de todas as linhas nele contidas. A cada classe de
objectos é possível aplicar um determinado conjunto de métodos.
Para vermos como um método é aplicado a um objecto, vamos considerar o objecto
Worksheet, que representa uma folha de cálculo do Excel. Se pretendermos que o nosso
macro mova essa folha para uma nova posição dentro do Livro de Trabalho (Workbook ),
ele deverá aplicar o método Move a esse objecto, usando a seguinte sintaxe:
Worksheet.Move([Before][, After])
Exemplificando, se quisermos que o macro desloque a folha de cálculo "Dados 2009"para
a posição imediatamente a seguir à folha "Dados 2008", o comando a inserir no macro
será:
Worksheets("Dados 2009").Move Before:=Worksheets("Dados 2008")
Como veremos mais à frente, o objecto Worksheet é definido como um elemento do
24
conjunto de folhas de cálculo contidas no Livro de Trabalho. Este conjunto de folhas é
representado por Worksheets(). Assim sendo, Worksheets("Dados 2009") refere-se à folha
de cálculo com o nome "Dados 2009".
Outro método útil é o que permite referenciar uma célula individual pertencendo a
um objecto do tipo "Range"(gama de células) ou Worksheet. Trata-se do método Cells,
com a seguinte sintaxe:
Objecto.Cells(Linha,Coluna)
Se a indicação de Objecto for omitida, partir-se-á do princípio que nos referimos à
folha de cálculo activa.
A instrução seguinte, por exemplo, copia o valor contido na célula C2 para a variável
temp:
temp = Cells(2,3)
Outra forma de referir uma célula individual é usar a notação utilizada pelo Excel
para referenciar células, envolvendo-a em parêntesis rectos. O exemplo anterior ficaria
assim:
temp = [C2]
4.1.3 Eventos
Os eventos resultam de acções que, uma vez exercidas sobre um objecto, implicam a
possibilidade de ocorrer uma resposta automática por parte dele. Basicamente, um evento
EP
é algo que acontece a um objecto. Por exemplo, a abertura de uma folha de um livro de
trabalho (workbook ) em Excel é um evento. A inserção de uma nova folha no livro de
IS
25
à direita, pode ser acedida a lista de eventos disponíveis para o objecto Worksheet 12 .
Seleccionando um dos eventos, será possível construir o procedimento event handler que
permita ao objecto Worksheet reagir a esse evento. O cabeçalho e o delimitador final são
criados automaticamente pelo editor do VBA, sendo da responsabilidade do programador
a inclusão das instruções necessárias. Na figura são referidos vários eventos que podem
ocorrer no objecto Worksheet, tais como o Activate que ocorre sempre que uma folha
de cálculo se torna activa, ou o Change que é desencadeado por qualquer alteração ao
seu conteúdo. Assim sendo, um mesmo objecto, por exemplo, a Worksheet pode estar
preparada para reagir a diferentes eventos, desde que possua event handlers específicos
para esses eventos.
EP
IS
26
detalhes do código que o event handler deverá conter para produzir o efeito desejado.
Preocupemo-nos, de momento, apenas com as interacções entre as várias entidades que
intervêm no processo.
Como é visível na Figura 11 na página precedente, existem na interface vários objectos
(chamados controlos). Entre eles, têm particular interesse para esta discussão a caixa de
texto txt1, o rótulo lbl2 e o botão de comando command1. Quando o utilizador pretende
utilizar o macro, uma vez este invocado, deverá introduzir o número a testar em txt1 e
pressionar ("clicar") o botão command1. Quando isso acontece, diz-se que ocorreu um
evento click no botão command1. Se esse botão não dispuser de nenhum event handler
para lidar com esse tipo de evento, nada se passará. No entanto, se se tiver previamente
associado a esse objecto (command1 ) um event handler adequado, o objecto será já capaz
de responder ao evento e produzir o resultado desejado. Neste caso, o resultado deverá
ser efectuar os cálculos necessários para concluir se o número introduzido é ou não primo
e apresentar essa conclusão no rótulo lbl2.
27
ActiveWindow e à Application. Podemos omitir esses detalhes e apenas escrever:
ActiveCell.Font.Name
Se quisermos utilizar esta propriedade para mudar o tipo de letra da célula activa,
utilizaremos então uma instrução como a seguinte13 :
ActiveCell.Font.Name = "Helvetica"
Note-se que estamos aqui a utilizar uma propriedade como uma variável cujo conteúdo
pode ser modificado. De facto, uma propriedade pode ser vista como uma variável especial
associada a um dado objecto.
Se, ao contrário, quisermos obter o valor de uma dada propriedade, a instrução a usar
será do tipo:
variavel = Objecto.Propriedade
Para obtermos, por exemplo, o conteúdo da célula activa da folha de cálculo, a ins-
trução correcta seria:
conteudo = ActiveCell.Value
Estaremos, assim, a usar a propriedade Value do objecto ActiveCell. Nessa proprie-
dade encontra-se armazenado o conteúdo da célula.
Vimos na Secção 4.1.2 na página 24, que os métodos de uma classe de objectos descrevem
as acções que podemos executar sobre eles ou, por outras palavras, aquilo que podemos
fazer com eles. Na sua forma mais simples, a sintaxe usada para aplicar um método a
IS
28
Muitas vezes, os argumentos que se podem fornecer a um método são opcionais. Por
exemplo, a instrução abaixo adiciona (insere) uma nova folha de cálculo imediatamente
antes da folha com o nome "Dados_Jan":
Worksheets.Add Before:=Worksheets("Dados_Jan")
No entanto, caso seja omitido o argumento Before, a nova folha será inserida antes da
folha de cálculo activa. É esse o comportamento por defeito do método Add.
4.3.1 MsgBox
A função MsgBox permite apresentar no ecran uma Caixa de Mensagem (Msg Box ).
Trata-se de uma pequena janela contendo uma mensagem, pelo menos um botão de
comando e eventualmente um pequeno desenho (ícone) ilustrativo do tipo de mensagem.
Na Figura 12 encontra-se um exemplo de uma destas janelas.
EP
IS
29
Mensagem Texto a apresentar (máximo de 1024 caracteres)
Características Valor numérico que especifica o número de botões, o tipo do
ícone e o botão de defeito (com o “focus”), obtido pela soma
de três valores parciais (opcional)
Título Conteúdo da barra de título da janela (opcional)
O 2o argumento será calculado usando os valores da Tabela 3. Assim, para obter o
valor do parâmetro características, será preciso somar três valores, um de cada coluna
da Tabela 3, cada um deles especificando uma das características (Botões de Comando,
Ícone e qual o botão com o "focus"14 ).
do que um botão, está-se a pedir ao utilizador que escolha uma de entre duas ou três
alternativas. Dependendo de qual o botão premido pelo utilizador, assim o valor numérico
devolvido pela função MsgBox será um de entre 7 valores possíveis, descritos na Tabela 4.
De notar que caso a tecla ESC (Escape) seja premida o valor devolvido será 2, a que
corresponde o botão Cancel (o que indica que as duas acções são equivalentes).
14
O botão com o "focus" ou botão de defeito é aquele que será accionado automáticamente caso o
utilizador prima a tecla Enter ou Return.
30
Quando se pretende aproveitar o valor devolvido pela função MsgBox será necessário
usá-la com a seguinte sintaxe:
Variável = MsgBox(Mensagem, Características, Título)
Desta maneira, o valor devolvido pela função será guardado (atribuído) em Variável,
podendo depois ser avaliado por instruções seguintes.
Quando, pelo contrário, não haja interesse em aproveitar o valor devolvido pela função
(tipicamente quando há apenas um botão), a sua invocação poderá fazer-se da seguinte
forma:
MsgBox Mensagem, Características, Título
4.3.2 InputBox
A função InputBox permite apresentar ao utilizador uma mensagem com uma questão,
recolhendo ao mesmo tempo uma string contendo a sua resposta. Assim, ao contrário
da função MsgBox (Secção 4.3.1 na página 29), esta função produz um resultado do tipo
string e não do tipo integer.
EP
IS
Como pode ser visto na Figura 13, esta função cria um objecto composto (uma Caixa
de Entrada) incluindo um caixa de texto, dois botões15 e um rótulo dentro de uma
pequena janela.
A sua sintaxe é
Variável = InputBox (mensagem, título, valor_de_defeito, xpos, ypos)
Em que os argumentos são:
Mensagem Texto da mensagem a afixar na Caixa de Entrada (máximo
de 1024 caracteres)
Título Conteúdo da barra de título da janela (opcional)
valor_de_defeito Texto a colocar à partida na caixa de texto da Caixa de En-
trada (opcional)
xpos e ypos Coordenadas da “Input Box” relativamente aos bordos es-
querdo e superior do ecrã (opcionais)
Ao contrário da MsgBox, neste caso os dois botões são fixos. Por outro lado, a tecla ESC tem o
15
mesmo comportamento.
31
4.3.3 Forms
Como vimos no início da Secção 4 na página 22, uma interface gráfica (em terminolo-
gia VBA, uma DialogBox ) é construída dispondo os objectos adequados (genericamente
designados por controlos) sobre uma janela especial, a form. Efectivamente uma form é
utilizada como um contentor para outros objectos gráficos. Um objecto da classe User-
Form pode ser criado no Editor do VBA através do Menu "Insert/User Form". Esse
processo será visto em detalhe na Secção 9 na página 76.
A seguir são apresentadas algumas das principais propriedades que podem ser confi-
guradas numa Form:
Name especifica o nome pelo qual a Form será identificada
Caption especifica o título que figura no topo da Form
BackColor permite seleccionar a cor do fundo
Enabled controla a utilização da Form pelo utilizador
ShowModal permite alterar o comportamento da Form de modo a controlar
o acesso à aplicação enquanto a Form estiver activa
Font controla o tipo e tamanho da letra utilizada
Height especifica a altura da Form
Width especifica a largura da Form
Nas próximas secções, referiremos com algum detalhe os controlos de uso mais comum
na construção de dialogBoxes em VBA. Estes são os objectos que mais frequentemente
são colocados numa form.
EP
lizado para permitir ao utilizador dar ordens (comandos) ao programa. Como se pode
verificar na Figura 11 na página 26, é a este tipo de controlos que normalmente se asso-
ciam as sub-rotinas que permitem responder a eventos como o clicar de um rato.
As propriedades normalmente referidas em relação a esta classe de objectos são as que
controlam as dimensões (Height e Width) e a propriedade Caption que permite especificar
o texto afixado.
A instrução seguinte serve de exemplo de como alterar programaticamente o estado
de um botão de comando:
cmdArranque.Enabled = True
O que fizemos com a instrução acima foi atribuir o valor booleano (lógico) True à
propriedade Enabled 16 do botão de comando cmdArranque.
4.3.5 Rótulos
Os rótulos, também designados por etiquetas (label ) são usados para apresentar texto
na interface. Mais uma vez, a propriedade mais utilizada é a propriedade Caption, que
permite especificar o texto a apresentar. Este controlo é usado não só para apresentar
16
Esta propriedade permite controlar o acesso do utilizador ao botão de comando.
32
informação estática, que é escolhida na fase de concepção da interface, como também
informação dinâmica, como seja a usada na apresentação de resultados:
lblResultado.Caption = "O valor total é 235 metros"
A instrução acima atribui à propriedade Caption do rótulo lblResultado a string "O
valor total é 235 metros", o que vai ter como consequência a sua afixação na interface.
A função str(), por seu lado, converte um valor numérico num texto contendo esse
valor. Uma utilização típica é a de permitir compor strings como a do exemplo
apresentado na Secção 4.3.5.
A string "O valor total é de 35 metros"pode ser composta usando o símbolo "+"como
operador de concatenação (colagem) de texto, numa instrução como a seguinte:
texto = "O valor total é de "+ str(res) + "metros"
O símbolo "+"tanto pode ser interpretado como operador de adição como de conca-
tenação. Essa ambiguidade é desfeita pelo VBA, analizando o tipo dos seus operan-
dos. Se forem ambos numéricos, será realizada uma adição. Se forem ambos texto,
será feita uma colagem. Se forem de tipo diferente, ocorrerá um erro. Para que na
instrução atrás, isso não ocorra, é preciso usar a função str() para converter para
string o conteúdo numérico da variável res.
Agora, já poderemos perceber qual o resultado da primeira instrução apresentada
(pesoTotal = txt1.Text + txt2.Text): ocorrerá a colagem do texto contido nas duas
TextBox, em vez da soma dos correspondentes valores numéricos.
33
numéricos e, no caso do Excel, referências a células e mesmo fórmulas.
Algumas das suas propriedades mais importantes são:
Text Permite obter ou alterar o texto contido no objecto.
MaxLenght Especifica o tamanho máximo do texto (em caracteres) que o
utilizador pode introduzir.
MultiLine Permite escolher entre permitir ou não a apresentação do texto
em várias linhas.
Enquanto que os rótulos (Label ) são utilizados pelo programa para apresentar infor-
mação ao utilizador, já as caixas de texto (Text Box ) são geralmente usadas para permitir
a leitura de informação pelo programa.
34
Figura 15: Vários checkBox agrupadas numa frame
0 não activada
1 activada
2 não disponível
O texto a inserir junto de cada caixa de verificação deve ser especificado mediante a
propriedade Caption.
35
4.3.10 Caixas de Listagem
Este objecto serve para apresentar listas e permite que o utilizador escolha uma ou mais
opções dentro de uma dada lista. Esta lista é apresentada numa caixa própria (com uma
barra de deslocamento vertical à direita, no caso de a lista ser mais extensa que o número
de linhas disponível na caixa).
em que
elemento é o novo elemento a acrescentar à lista
posição refere-se à posição na lista em o elemento vai ser inserido
Na primeira variante acima o elemento será inserido a seguir à última linha preen-
chida, desde que a lista não seja ordenada. Se a propriedade Sorted (ver tabela abaixo)
estiver activa (True), qualquer inserção de nova linha será feita na posição adequada para
manter a lista ordenada
A remoção de um elemento da lista pode ser feita mediante o método RemoveItem:
Listbox.RemoveItem posição
A remoção simultânea de todas as linhas da caixa de listagem pode ser conseguida
aplicando-lhe o método Clear (este método não necessita de qualquer argumento):
Listbox.Clear
As propriedades mais relevantes desta classe de objectos são:
36
ListCount permite conhecer em qualquer momento o número de elemen-
tos contidos na lista
Sorted permite especificar se a lista é ou não apresentada de maneira
ordenada
ColumnCount especifica qual o número de colunas em que a lista é apresen-
tada
ColumnHeads controla os cabeçalhos das colunas
MultiSelect permite controlar a forma de selecção de elementos na lista:
0 - só é possível seleccionar um elemento
1 - é possível seleccionar vários elementos simultaneamente,
pressionando cada elemento
2 - é possível seleccionar vários elementos simultaneamente,
usando a tecla Ctrl
ListIndex fornece ou especifica qual o índice do item actualmente selec-
cionado (ou –1 caso nenhum esteja). Sintaxe:
objecto.ListIndex [= indice]
List permite aceder aos elementos duma lista, quer para os ler,
quer para os modificar. Sintaxe:
objecto.List(indice) [= string]
Text permite obter o elemento actualmente seleccionado. Sintaxe:
variavel = objecto.Text
RowSource especifica qual a gama de células de uma folha de cálculo Excel
em que se encontra a informação a incluir na lista, ou seja, a
fonte dos dados a apresentar.
EP
usada do lado direito de uma operação de atribuição, enquanto que na versão completa
o que se pretende é atribuir um valor à propriedade.
Existe uma variante da ListBox, chamada ComboBox, que combina uma TextBox com
uma ListBox. O utilizador pode introduzir um item na TextBox ou seleccioná-lo na lista
que, estando normalmente escondida, só aparecerá quando se clica num ícone próprio. É
normalmente utilizada quando se pretende dar a possibilidade de escolher um elemento
de uma lista mas sem ocupar muito espaço na form.
37
Figura 18: Interface construída directamente na folha de cálculo
instalar seleccionando o ícone respectivo, após o que se desenhará com o rato na própria
folha de cálculo a área que esse controlo vai ocupar. A sua posição e dimensões definitivas
poderão ser afinadas quer com o rato quer manipulando as propriedades correspondentes
na janela de Propriedades.
EP
IS
38
5 Estruturas de controlo do programa
Um macro é um programa escrito na linguagem VBA. Vamos agora começar a analizar
mais em detalhe a estrutura de um programa. Um programa é composto por um conjunto
de instruções, cada uma delas executando uma tarefa específica. A sequência de instruções
levará à solução do problema que o programa se propõe resolver. Mas essa sequência não
tem que ser necessariamente linear, i.e., composta por uma lista de instruções que serão
realizadas uma após outra, de forma imutável. Isso tornaria o programa inflexível, incapaz
de se adaptar às circunstâncias ou aos diferentes desejos do utilizador.
Já foi introduzida na Secção 3.5 na página 20 a noção de operação de atribuição. Com
essa operação podemos criar instruções simples, mediante as quais é possível copiar valores
entre variáveis, ou armazenar resultados do cálculo de expressões. Mas um programa
flexível não poderá ser construído apenas com instruções desse tipo. É preciso dispor
de instruções que permitam alterar o fluxo do programa. Para tal, vamos introduzir
estruturas de controlo que possibilitam a alteração desse fluxo.
5.1.1 If...Then...Else
EP
IS
39
A Figura 19 na página anterior descreve a estrutura condicional If...Then...Else. Como
o seu nome sugere, esta estrutura está baseada no teste de uma condição. Se essa condição
fôr verdadeira, desencadeará a execução das instruções representadas na figura por Bloco
de Instruções1. Em caso contrário, será executado o Bloco de Instruções 2.
A sintaxe desta estrutura é:
1 I f c o n d i c a o Then
2 [ instrucoes ]
3 Else
4 [ instrucoes alternativas ]
5 End I f
Quando a condição é verdadeira serão executadas as instruções delimitadas por Then
e Else. Em caso contrário, será executado o bloco alternativo de instruções.
A condição pode consistir numa comparação ou outra operação lógica, ou ainda em
qualquer expressão de que resulte um valor numérico: um valor não nulo será interpretado
como Verdadeiro, enquanto um valor nulo será considerado como Falso.
A condição é, portanto, uma expressão booleana (lógica). Uma expressão booleana
representa um valor booleano, TRUE (verdadeiro) ou FALSE (falso) e pode ser cons-
tituída por uma variável, uma função ou uma combinação destas entidades através de
operadores.
5.1.2 If...Then
EP
IS
Quando numa estrutura condicional não existe qualquer acção a executar quando a
40
condição seja falsa, usa-se uma variante simplificada, a If...Then. O seu diagrama está
descrito na Figura 20 na página precedente. A sua sintaxe será então:
1 I f c o n d i c a o Then
2 [ instrucoes ]
3 End I f
Nesta 2a variante, quando a acção a realizar no caso a condição ser verdadeira puder
ser executada com apenas uma instrução, é possível ainda utilizar a seguinte sintaxe
simplificada, sem o delimitador End If e sem mudança de linha:
If condicao Then instrucao
Expressões lógicas
As expressões lógicas, utilizadas nas condições das estruturas de controlo, são cons-
truídas utilizando operadores lógicos específicos. A linguagem VBA prevê os seguin-
tes operadores lógicos, utilizáveis em expressões:
Operador Descrição
> Maior que
< Menor que
= Igualdade
<= Menor ou igual
>= Maior ou igual
<> Desigualdade
EP
And E
Or Ou
IS
Not Negação
Dos primeiros seis operadores não haverá muito a dizer. Já do And e do Or haverá
alguns detalhes a esclarecer:
AND
Sintaxe: Expr1 And Expr2
• Basta que quer Expr1 quer Expr2 seja falsa, para a expressão ser falsa
OR
Sintaxe: Expr1 Or Expr2
• Basta que quer Expr1 quer Expr2 seja verdadeira, para a expressão ser ver-
dadeira
41
5.1.3 Estruturas condicionais embutidas
É possível construir estruturas de controlo mais complexas, oferecendo ao programa a
capacidade de escolher uma de entre várias alternativas possíveis. Estas estruturas con-
dicionais embutidas ou encadeadas são construídas inserindo estruturas condicionais den-
tro de outras estruturas condicionais. Isso pode realizar-se de dois modos. O primeiro
método implica utilizar a palavra reservada ElseIf.
A sintaxe desta estrutura é:
1 I f c o n d i c a o 1 Then
2 Accao1
3 E l s e I f c o n d i c a o 2 Then
4 Accao2
5 E l s e I f c o n d i c a o 3 Then
6 ...
7 Else
8 AccaoN
9 EndIf
Esta estrutura condicional permite a selecção de uma entre várias alternativas mutua-
mente exclusivas. As instruções que se seguem à palavra reservada Else (aqui representa-
das por "AcçãoN") serão executadas apenas se nenhuma das condições se tiver verificado.
É possível imbricar um qualquer número de blocos ElseIf dentro de uma dada estrutura
condicional.
As estruturas condicionais produzidas usando o método alternativo não são tão com-
EP
pactas mas tornam-se talvez mais legíveis, sobretudo se se usar a indentação apropriada:
1 I f c o n d i c a o 1 Then
IS
2 Accao1
3 Else
4 I f c o n d i c a o 2 Then
5 Accao2
6 Else
7 If condicao 3
8 Accao 3
9 Else
10 Accao4
11 End I f
12 End I f
13 EndIf
Na Figura 21 na página seguinte pode-se ver o fluxograma de uma estrutura imbricada
com quatro vias alternativas. A Acção 1 é executada caso a 1a condição seja verdadeira.
A Acção 3 será executada caso a Condição 3 for verdadeira e as duas anteriores falsas.
A Acção 4 será executada caso todas as quatro condições se tiverem verificado falsas.
Chama-se a esta acção, a acção por defeito, ou seja, aquilo que se faz quando todo o resto
falha.
É muito importante que se compreenda que estamos aqui a tratar de verdadeiras alter-
nativas, i.e., mútuamente exclusivas. Cada vez que uma estrutura deste tipo é executada,
42
Figura 21: Estruturas de controlo condicional imbricadas
só uma das acções será efectuada. Pode dizer-se que, genericamente, para um programa
poder escolher uma de entre N alternativas, será necessário utilizar N - 1 estruturas
EP
condicionais encadeadas.
O exemplo da Listagem 3 traduz uma situação em que o programa, confrontado com
IS
a necessidade de classificar uma nota numérica, pode escolher uma de entre seis notas
qualitativas diferentes. Só várias estruturas condicionais encadeadas permitirão resolver
esse problema.
Listing 3: Exemplo de aplicação de If..Then..Else imbricados
1 I f ( nota < 0 ) Or ( nota > 2 0 ) Then
2 r e s u l t a d o = " Nota ␣ I n v a l i d a ! "
3 E l s e I f nota < 6 Then
4 r e s u l t a d o = "Mau"
5 E l s e I f nota < 10 Then
6 r e s u l t a d o = " Mediocre "
7 E l s e I f nota < 14 Then
8 resultado = " Suficiente "
9 E l s e I f nota < 17 Then
10 r e s u l t a d o = "Bom"
11 Else
12 r e s u l t a d o = " Muito ␣Bom"
13 End I f
43
5.2 Estruturas de controlo repetitivo
Como vimos, as estruturas de controlo condicional permitem alterar o fluxo do pro-
grama, ou seja, executar diferentes sequências de instruções conforme as circunstâncias
do momento. As estruturas de controlo repetitivo (também conhecidas por estruturas
de repetição ou ciclos) permitem repetir um dado conjunto de instruções o número de
vezes que fôr necessário.
Existem diversas variantes de ciclos, diferindo umas das outras pela forma como é
controlada a execução das instruções contidas no corpo do ciclo. Genericamente, pode-se
dizer que uma estrutura de controlo repetitiva assegura a execução repetida de um dado
conjunto de instruções dependendo do resultado do teste de uma determinada condição
de funcionamento. De facto, como veremos, também os ciclos dependem da verificação
de uma condição, normalmente de forma explícita, noutros casos definida implicitamente.
Analizando esse fluxograma, pode observar-se que tudo roda à volta do teste a uma
condição, descrita como condição de funcionamento. Se a condição for verdadeira
na altura em que o teste é realizado, as instruções que compõem o chamado corpo do
ciclo serão executadas, após o que novo teste à condição será efectuado. Enquanto a
condição se verificar ser verdadeira, o programa não sairá deste ciclo. Na 1a vez em que
a condição se mostrar falsa, o ciclo terminará e o programa poderá continuar com as
instruções seguintes.
Chama-se corpo do ciclo ao conjunto de instruções que serão executadas em cada
iteração (repetição) do ciclo. Esse conjunto pode incluir qualquer número de instruções
e de qualquer tipo, mesmo outras estruturas de repetição. Neste último caso, estaremos
44
perante o que se designa por ciclos imbricados ou embutidos, que serão tratados em
detalhe na Secção 5.2.6 na página 52.
A sintaxe em VBA desta estrutura de controle é a seguinte:
1 Do While c o n d i c a o
2 [ instrucoes ]
3 Loop
A segunda variante é muito semelhante à primeira. A grande diferença diz respeito à
condição de controle. Neste caso, temos a chamada condição de termo (ou de paragem)
o que faz com que o ciclo funcione enquanto a condição for falsa ou, por outras palavras,
até que a condição de termo seja verdadeira (Figura 23).
EP
45
Um ciclo controlado por contador baseado na estrutura Do..While pode assumir a
seguinte forma genérica:
1 contador = v a l o r _ i n i c i a l
2 Do While c o n t a d o r <= v a l o r _ f i n a l
3 ’ Corpo do C i c l o
4 contador = contador + 1
5 Loop
EP
IS
Decorrendo do que vimos na secção anterior, torna-se claro que é igualmente possível
construir este ciclo usando a estrutura Do..Until.
Há que ter em conta as seguintes questões na construção de um ciclo controlado por
contador usando as estruturas de controlo Do...While ou Do...Until :
46
Quando se usam estas estruturas, ao contrário do que se passa com a estrutura de
repetição For...To...Next, a analizar na Secção 5.2.5 na página 50, é da responsabilidade
do programador assegurar-se de que tais acções são correctamente executadas conforme
está espelhado no diagrama de fluxo representado na Figura 24 na página anterior.
Um último aspecto a observar é o seguinte: só é viável construir um ciclo controlado
por contador quando se pode conhecer à partida o número de vezes que ele vai funcionar
ou, por outras palavras, o número de repetições necessárias. Isso nem sempre é possível.
Nesses casos, a alternativa será usar ciclos controlados por sentinela.
47
• Quando se "clica" no botão de comando "cmdTotal", a resposta desse objecto
deverá ser o cálculo do somatório do conteúdo de cada linha da listBox e a sua
apresentação na label "Label2".
botão de comando encontra-se na Figura 26. Analizando esse código, são pertinentes as
seguintes observações:
48
o conteúdo da variável c for maior que o número de linhas da ListBox menos 117 .
O número de linhas da ListBox é fornecido pela propriedade ListCount.
Exemplo
Se o utilizador estiver a introduzir os dados referentes a um conjunto de alunos
identificados pelos seus números de matrícula, a introdução de um número com
menos de 6 dígitos (no caso do ISEP) como, por exemplo, o valor 1, permitirá
indicar ao programa que a presente sequência de introdução de dados deve
terminar. Seria esse, neste caso, o valor sentinela escolhido.
49
EP
50
estrutura de controlo. O programador precisa, apenas, de especificar qual o valor de início
e de fim (ou, de forma indirecta, o número de vezes que o ciclo vai funcionar) e quais as
instruções que o ciclo vai repetir (o corpo do ciclo).
O conteúdo da variável de controlo do ciclo pode ser utilizado por instruções contidas
no corpo do ciclo, mas não deve, sob pretexto algum, ser modificado por estas instruções,
sob pena de se perder o controlo do funcionamento do ciclo.
A estrutura de controlo verifica no início de cada iteração (repetição) do ciclo se a
condição de funcionamento do ciclo é ainda verdadeira. Caso seja falsa, o ciclo terminará,
e o programa passará a executar as instruções que se lhe seguem.
Pode ainda ser utilizada a seguinte sintaxe alternativa:
1 For c o n t a d o r = v a l o r _ i n i c i a l To v a l o r _ f i n a l Step p a s s o
2 [ instrucoes ]
3 Next
A diferença está na utilização da palavra Step após a especificação do valor final. A
sua inclusão é opcional: caso se pretenda que o conteúdo da variável de controlo seja
incrementada uma unidade de cada vez, é desnecessário especificar o passo. Em caso
contrário, Step passo permitirá incrementar o valor de variável de um valor diferente da
unidade (positivo ou negativo).
Caso o valor de passo seja positivo a variável contadora será incrementada. Se pre-
tendermos, no entanto, efectuar um decremento, deverá ser utilizado um valor negativo.
Obviamente, nesse caso, a condição implícita de funcionamento do ciclo passará a ser
contador >= fim.
Repare-se que nesta estrutura de controlo, ao contrário das estudadas anteriormente,
EP
verificada mas não é especificada de forma explícita pelo programador, apenas de forma
indirecta ao fixarem-se os valores inicial e final da variável de contagem.
Listing 4: FormataBordo - exemplo de sub-rotina usando For..Next
1 Public Sub FormataBordo ( )
2 Dim c e l l O b j e c t As Range
3 For Each c e l l O b j e c t In S e l e c t i o n
4 c e l l O b j e c t . BorderAround C o l o r I n d e x :=3 , Weight := x l T h i c k
5 Next
6 End Sub
Existe ainda em VBA uma estrutura de controlo que é uma variante da For..To..Next
e que opera numa colecção de objectos. Uma colecção é um conjunto de objectos idênticos,
pertencentes à mesma classe, e que são referenciáveis mediante um índice. Por exemplo,
um Workbook é constituído por um conjunto de objectos da classe Worksheet 18 .
A sintaxe desta estrutura é a seguinte:
1 For Each e lemento In C o l e c c a o
18
Por sua vez, um workbook é também um objecto. Um objecto pode assim ser ele próprio uma
colecção de objectos.
51
2 [ instrucoes ]
3 Next
O bloco de instruções será aplicada a cada elemento da colecção de objectos em causa.
Na Listagem 4 na página anterior é apresentado um exemplo de sub-rotina, utilizando
esta estrutura de controlo. Nela é utilizada a variável cellObject para guardar um objecto
do tipo Range (que representa uma gama de células - assunto tratado na Secção 8.3).
O ciclo For Each...Next aplica o método BorderAround a cada uma das células contidas
na gama representada por cellObject. Com os argumentos fornecidos no exemplo, este
método formata o bordo dessas células a vermelho e usando uma linha grossa.
52
cálculo de um factorial é realizado efectuando uma sucessão de multiplicações. Será
necessário usar um ciclo para o efeito. Por sua vez, se pretendermos repetir esse cálculo
um certo número de vezes, teremos também que usar um ciclo. Teremos assim um
ciclo, chamemos-lhe exterior, que se encarrega de produzir uma sequência de factoriais
e cujo corpo inclui por sua vez um ciclo, dito interior, que é responsável pelo cálculo de
cada factorial. O diagrama de fluxo da Figura 28 na página precedente representa esta
realidade. O código necessário para traduzir esse diagrama é o contido na Listagem 5.
Listing 5: Exemplo usando Ciclos Imbricados
1 num = InputBox ( " I n t r o d u z a ␣um␣ i n t e i r o ␣ p o s i t i v o " )
2 Do U n t i l num < 0
3 factorial = 1
4 contador = 1
5 Do U n t i l c o n t a d o r > num
6 f a c t o r i a l = f a c t o r i a l ∗ contador
7 c o n t a d o r = c o n t a d o r +1
8 Loop
9 num = InputBox ( " I n t r o d u z a ␣um␣ i n t e i r o ␣ p o s i t i v o " )
10 Loop
O ciclo exterior é controlado por uma sentinela, no caso qualquer valor inteiro não
positivo. É um exemplo de sentinela constituído não por um valor específico mas por
uma gama de valores possíveis. O ciclo interior é claramente controlado por contador,
funcionando tantas vezes quantas o valor do inteiro cujo factorial se pretende calcular.
EP
1 Sub F i l l R a n g e ( )
2 Num = 1
3 For Row = 1 To 10
4 For Col = 1 To 10
5 C e l l s (Row, Col ) . Value = Num
6 Num = Num + 1
7 Next Col
8 Next Row
9 End Sub
53
6 Variáveis indexadas - vectores e matrizes
Até agora, temos trabalhado com variáveis que podemos classificar como individuais.
Como essas variáveis não podem conter simultaneamente mais que um dado, a atribuição
de um novo valor a essa variável implica o desaparecimento do valor anteriormente nela
contido.
Mediante a utilização de um novo tipo de variáveis, as variáveis do tipo Array (Vector),
passa a ser possível armazenar na mesma variável múltiplos valores desde que sejam do
mesmo tipo. Estamos, portanto, a utilizar agora variáveis que se podem classificar como
variáveis múltiplas. Na Figura 29 podemos observar representações de uma variável
simples do tipo integer e de uma variável múltipla (um vector uni-dimensional) contendo
valores inteiros. Cada elemento do vector é identificado por um valor numérico específico.
EP
Um vector é uma lista ordenada de variáveis simples do mesmo tipo. Pode também
ser visto como um conjunto de variáveis simples agrupadas. Todos os elementos desse
vector partilham o mesmo nome (o nome do vector) e são identificados individualmente
mediante o valor dum índice, que determina qual a sua posição dentro do vector. É por
isso que estas variáveis são conhecidas por variáveis indexadas.
Os valores do índice devem obrigatoriamente ser inteiros. O primeiro valor do índice
é zero19 .
Um elemento de um vector é identificado utilizando o nome do vector seguido do valor
do índice dentro de parêntesis:
nome_vector(indice)
Exemplos:
var_Multipla(3) 4o elemento do vector ‘var_Multipla’
var_Multipla(7) 8o e último elemento do vector ‘var_Multipla’
notas(14) 15o elemento do vector ‘notas’
nomes(0) 1o elemento do vector ‘nomes’
19
É possível forçar que os índices dos vectores comecem do valor 1 usando a directiva Option Base 1.
54
Figura 30: Um exemplo de vector de strings
Os elementos de um vector não têm que ser inteiros, nem sequer valores numéricos.
Na Figura 30 é representado um vector contendo strings (texto). Considerando o vector
como armazenado os nomes dos membros de uma equipa de futebol, os sucessivos valores
do índice podem ser vistos como os correspondentes números das suas camisolas. Note-se
que estamos, neste caso, a forçar os valores do índice a iniciar em 1.
20
. Uma das formas de utilizar a instrução Dim para declarar vectores é a seguinte:
Dim nome_vector(num_elementos) As Tipo
IS
Exemplos:
Dim var_Multipla(8) As Integer
Dim notas(30) As Single
Dim nomes(100) As String
Note- se que num_elementos não se refere ao valor máximo que a variável índice
pode assumir (7, no caso do vector var_Multipla) mas sim ao número de elementos do
vector (8, neste caso). Por este processo, a declaração do limite inferior faz-se de forma
implícita: por defeito assume-se como limite inferior do índice o valor zero (ou 1 se tal
for especificado mediante a instrução Option Base 1 ).
Uma forma alternativa de utilizar a instrução Dim para declarar vectores implica a
utilização da palavra reservada To, permitindo especificar o menor e o maior valor que o
índice pode assumir:
Dim nome_vector(menorIndice To maiorIndice) As Tipo
Exemplos:
20
Adicionalmente, a instrução Dim atribui valores iniciais a todos os elementos do vector (zeros no
caso de vectores numéricos e strings nulas no caso de vectores alfa-numéricos).
55
Dim numeros(100 To 200) As Double
Dim valores(-100 to 100) As Single
verifique que a dimensão inicialmente atribuída não foi adequada. Nessa situação, caso
se pretenda manter os valores já existentes no vector, dever-se-á usar a opção Preserve.
IS
Exemplo:
ReDim Preserve vector(200)
56
Figura 31: Porquê usar ciclos para processar vectores?
Do atrás exposto facilmente se verificará que esta solução não tem qualquer exequi-
bilidade prática. Analizemos então a solução alternativa usando uma variável indexada:
EP
em vez de 100 variáveis individuais teremos apenas um vector de 100 elementos, cada um
deles capaz de armazenar o preço de um produto. Consequentemente, teremos apenas
uma instrução Dim, no caso, algo como Dim preços As single. E quando for necessário
IS
actualizar os preços, como o vector é uma variável múltipla indexada, haverá apenas que
construir um ciclo que percorra automáticamente o vector, actualizando cada um dos
seus elementos.
57
limite superior a especificar pelo utilizador na TextBox txtMaior (a largura do intervalo
não deve exceder 100, visto ser esta a dimensão do vector). Os valores calculados são
armazenados num vector para eventual futura utilização.
58
6.4 Matrizes
As variáveis indexadas descritas anteriormente representam vectores uni-dimensionais.
Não há nada, no entanto, que nos impeça de trabalhar com estruturas de dados multi-
dimensionais. A declaração de vectores multi-dimensionais far-se-á acrescentando di-
mensões adicionais entre os parêntesis das instruções Dim. Um vector bidimensional
(vulgarmente designado por matriz) será criado mediante uma instrução do tipo:
Dim matriz(Numero_de_linhas, Numero_de_colunas) As Tipo
Exemplo:
Dim matriz(50,50) As Integer
O exemplo anterior cria uma matriz quadrada capaz de armazenar 2500 valores intei-
ros. Para referenciar um elemento de matriz será necessário usar dois índices, um para
identificar a linha e outro para a coluna.
No que diz respeito ao processamento de uma matriz, se, para processar um vec-
tor uni-dimensional, é necessário utilizar um ciclo, para processar uma matriz (vector
bidimensional) serão precisos dois ciclos encadeados.
EP
IS
Na Figura 32 pode ser visto um fragmento de código em VBA que permite calcular
a soma de duas matrizes (m1 e m2), colocando o resultado noutra matriz (ms). No
diagrama pode ser observada a existência de um ciclo interior que processa uma linha
da matriz (correspondendo, no fundo, a um vector uni-dimensional), coluna a coluna, e
que se encontra integrado no corpo de um ciclo exterior que repete esse processamento
para todas as linhas da matriz.
Analizando mais em detalhe o código apresentado na Figura 32, pode verificar-se a
existência de dois índices, concretizados nas variáveis i e j (a 1a para controlar as linhas e a
2a para as colunas). Estas variáveis foram também utilizadas como variáveis de controle
59
dos ciclos For. Dessa maneira, vão ser percorridos automaticamente os intervalos de
valores dos índices de 1 até nl (variável contendo o no de linhas) e de 1 até nc (variável
contendo o no de colunas).
Listing 9: Soma de matrizes
1 Option Base 1
2 Const Linhas = 10
3 Const Colunas = 10
4
19
21
22 lstM1 . AddItem l i n h a
23 Next
24 For i = 1 To n l ’ l e i t u r a da m a t r i z 2
25 l i n h a = ""
26 For j = 1 To nc
27 m2( i , j ) = Val ( InputBox ( "M2[ " & i & " , " & j & "]=" ) )
28 l i n h a = l i n h a & "␣␣␣␣" & m2( i , j )
29 Next
30 lstM2 . AddItem l i n h a
31 Next
32 For i = 1 To n l ’ c a l c u l o da soma de m1 com m2
33 l i n h a = ""
34 For j = 1 To nc
35 ms( i , j ) = m2( i , j ) + m1( i , j )
36 l i n h a = l i n h a & "␣␣␣␣" & ms( i , j )
37 Next
38 lstMS . AddItem l i n h a
39 Next
40 End I f
41 End Sub
60
Na Listagem 9 na página precedente pode ser encontrado o código completo de um
programa que preenche as duas matrizes m1 e m2 com valores fornecidos pelo utilizador,
após o que calcula a matriz soma ms. O programa faz ainda a apresentação do conteúdo
das três matrizes noutras tantas caixas de listagem.
No código pode ser observada a utilização de constantes para facilitar a escrita e
eventual alteração do programa. Foram inicialmente definidas as duas constantes Linhas
e Colunas que vão ser em seguida utilizadas por várias vezes ao longo do programa. Se
houver necessidade de alterar as dimensões das matrizes, bastará modificar a definição
inicial das constantes.
As instruções contidas nas linhas 20, 28 e 36 são usadas para acrescentar à string a
adicionar às ListBox o conteúdo (devidamente formatado) do elemento da matriz que se
encontra a ser processado no momento.
EP
IS
61
7 Funções e Procedimentos
Nesta secção vamos falar da organização interna de um programa. Em vez de incluir todas
as instruções numa única entidade, é possível e aconselhável organizar um programa em
vários módulos, divididos de acordo com a sua especialização.
A melhor maneira de encontrar a solução para um problema complexo é dividi-lo em
subproblemas e estes por sua vez em problemas de ainda menor dimensão até atingir
um nível de complexidade suficientemente baixo para ser resolvido sem dificuldade. Uma
vez resolvidos os subproblemas de nível mais baixo, começa um processo inverso, de
integração de módulos individuais num todo coerente.
A construção de um programa baseia-se num processo idêntico. Deve ser seguido o
método de subdividir o problema nas suas partes constituintes e encontrar solução para
cada uma delas, integrando no fim as partes no todo. Cada uma dessas partes pode
constituir um módulo independente que será utilizado pelo programa principal, usando
um mecanismo que se pode descrever como de "subcontratação".
Usando este mecanismo, o programa principal vai utilizar os serviços dos módulos
especializados na realização de certas tarefas. É possível, assim, re-aproveitar as capaci-
dades desses módulos, em vez de ser o próprio programa a assegurar essas tarefas.
Por outro lado, organizando o programa dessa forma, é possível melhorar a sua legi-
bilidade e facilitar a sua manutenção, já que quaisquer alterações a cada módulo ficarão
circunscritas a esse módulo, evitando efeitos secundários indesejáveis.
7.1 Funções
EP
Os programas descritos nos exemplos que têm sido apresentados destinam-se a executar
tarefas. Por exemplo, as rotinas descritas na Secção 2.6 na página 13 têm como objectivo
IS
62
Figura 33: Funções como caixas pretas
Para calcular a fórmula, ir-se-á multiplicar por 10 o resultado fornecido pela função
standard sin. Esta, por sua vez, para poder fornecer o resultado deverá ter recebido a
IS
informação de qual o ângulo (neste caso em radianos) de que se quer calcular o seno.
Quando a função termina o seu trabalho, deixará o resultado do seu cálculo no lugar que
ocupava na fórmula.
Para o utilizador da função, não interessa conhecer o seu funcionamento interno, mas
apenas qual a informação que lhe tem que fornecer e qual o tipo de resultado esperado.
Assim sendo, pode dizer-se que do ponto de vista do programa que utiliza a função, ela
se comporta como uma caixa preta, à qual é fornecida informação e que, com base nela,
produz um resultado (Figura 33).
63
Observe-se que função mlucro possui dois parâmetros de entrada, v e c, através dos
quais receberá os dados das vendas e dos custos respectivamente. Estes dois parâmetros
estão preparados para receber dados do tipo single. Note-se ainda que o resultado da
expressão que calcula a margem de lucro é atribuído directamente ao próprio nome da
função. É esse o processo pelo qual uma função consegue fornecer o resultado do seu
trabalho à entidade que a invocou. O tipo de resultado fornecido pela função é especificado
na parte direita do cabeçalho, também do tipo single, neste caso21 .
Esta função poderá ser utilizada em qualquer fórmula contida numa célula da folha de
cálculo, da mesma maneira que qualquer das funções pré-existentes o seria. Um exemplo
de uma fórmula utilizando esta função seria a apresentada na Figura 34.
A fórmula, que pode ser visualizada na barra de fórmulas da imagem apresentada na
Figura 34, contem referências às células D3 e D2, em que estão contidos, respectivamente,
o preço de venda e o custo do produto. Quando a função é invocada, cópias do conteúdo
EP
destas duas células são passadas à função. Esta recebe-os através dos parâmetros de
entrada respectivos, v e c. O resultado do seu cálculo será deixado na fórmula, quando a
IS
Vamos agora apresentar outro exemplo de função criada pelo programador e de como
esta pode ser utilizada num programa. Trata-se de uma função que calcula o factorial de
um número inteiro. Já que o factorial de um número é obtido à custa da multiplicação
21
Quer no que respeita ao tipo de resultado devolvido, quer ao tipo de dados recebido pela função
através dos parâmetros de entrada, é possível omitir a sua especificação no cabeçalho da função. Isso
terá como consequência que o VBA parta do princípio que se trata de dados do tipo Variant. Os
inconvenientes de usar este tipo de dados já foram referidos na Secção 3.4 na página 20.
64
de todos os valores inteiros entre 1 e esse número, estamos perante um caso típico de uti-
lização de uma estrutura de repetição. O código da função apresentado na Listagem 11
na página precedente usa um ciclo For para repetir a instrução f = f * i, responsável
pela actualização da variável f. No final do ciclo, essa variável conterá o resultado das
sucessivas multiplicações, ou seja, o próprio factorial. Atente-se a que essa variável deve
ser inicializada com o valor 1, já que é este o elemento neutro na multiplicação. Final-
mente, o resultado contido em f é copiado para o nome da função de modo a permitir
que ela possa devolver esse resultado ao programa que a invoca.
Na Listagem 12 pode ser consultado o código de um programa que calcula combi-
nações, usando a função factorial que acabámos de estudar22 . Este programa codifica a
resposta do botão de comando cmdCombina ao evento click.
22
Programa adaptado de um exemplo dos textos de apoio do prof. Ângelo Martins.
A fórmula de cálculo de combinações é np = (n−p)!p! .
23
n!
65
Em 1o lugar, são copiados os valores das variáveis do programa principal para os
parâmetros de entrada da função24 . Assim n e p são substituídos pelos valores presentes
nesse momento nessas variáveis (Passo 1). Como na 2a invocação da função o que lhe está
a ser passado é o resultado da expressão n - p, essa expressão tem que ser calculada. Em
seguida, a função é sucessivamente invocada com os valores previamente obtidos. Com
esses valores, a função faz o cálculo do factorial e terminando o seu trabalho, deixa no seu
lugar o rsultado do cálculo (Passo 4). Só falta agora calcular o resultado da expressão e
armazenar o seu resultado na célula D7.
Para poder receber a informação que lhe foi passada como argumento, a função deverá
ter sido criada de forma a poder recebê-la adequadamente. Para tal, deverá possuir
IS
um parâmetro de entrada por onde essa informação possa entrar. No caso da função
factorial, n é esse parâmetro de entrada e está preparado para receber dados do tipo
integer.
24
Para ver em detalhe esse proceeso, consultar a Secção 7.3
66
Na Figura 36 na página precedente está assinalado o parâmetro n com o sendo a via
de entrada de informação na função bem como a forma pela qual o resultado é fornecido.
No código da função factorial pode observar-se a inclusão da palavra reservada ByVal
imediatamente antes do nome do argumento. Esta palavra indica que a função espera
que um argumento lhe seja passado "por valor", ou seja, que aquilo que venha a receber
através daquele parâmetro seja exactamente o dado com que vai trabalhar.
Por oposição a ByVal pode usar-se a palavra ByRef ("por referência"). Neste caso,
a informação passada à função ou procedimento será não um valor específico mas a
indicação de onde esse valor poderá ser encontrado ou, por outras palavras, o endereço
da variável em que o valor a utilizar se encontrará. O uso de ByRef tem ainda outras
consequências que serão estudadas na Secção 7.4.
7.4 Procedimentos
Até agora, temos estado a analisar o processo pelo qual as funções e os programas que as
invocam comunicam entre si. Uma função, como vimos, devolve um e um só resultado.
Há, no entanto, situações em que é conveniente que as rotinas possam devolver mais do
que um resultado. Nesses casos, uma função não pode ser utilizada. Teremos que usar
um procedimento (ou sub-rotina) 25 e usar a técnica de passagem de parâmetros por
referência (ByRef ).
Se bem que já tenhamos por várias vezes lidado com procedimentos, está na altura
de formalizar o processo da sua criação. A sintaxe utilizada é a seguinte:
Sub <nome>(Lista_de_argumentos )
EP
instrucoes
End Sub
IS
67
Uma forma alternativa de chamar um procedimento implica o uso da palavra Call.
Nesse caso, a eventual lista de argumentos é passada dentro de parêntesis. Teremos assim:
Call nome_do_procedimento(argumento1, argumento 2,...argumentoN)
3 Dim b As Integer
4
5 a = 100
6 b = 400
7
8 ’ v a l o r e s de a e b a n t e s da chamada de proc2
9 [ I3 ] = a
10 [ J3 ] = b
11
12 pro c 2 a , b
13
14 ’ v a l o r e s de a e b d e p o i s da chamada de proc2
15 [ I4 ] = a
16 [ J4 ] = b
17 End Sub
18
68
Analizemos o código da Listagem 13 na página anterior. O procedimento proc1 tra-
balha com as variáveis a e b. Copia os seus valores para as células I3 e J3 respectivamente.
Em seguida chama o procedimento proc2 passando-lhe dois argumentos: o primeiro é
passado por referência ()ByRef ), ou seja, o que é efectivamente enviado é endereço (re-
ferência) da variável a ; o segundo é passado por valor (ByVal ), i.e, é efectuada uma
cópia do conteúdo da variável b. Dentro de proc2 são modificados os valores dos seus
parâmetros de entrada v1 e v2 em que, na altura da sua invocação, foram colocados uma
referência à variável a e uma cópia do conteúdo de b, respectivamente.
Observe-se agora qual o conteúdo de a e b após a invocação de proc2, conforme
apresentados na Figura 37.
autorização para alterar a variável a, já no caso do segundo parâmetro o que foi enviado
foi meramente uma cópia do conteúdo de b. Esse valor foi alterado dentro de proc2 mas
IS
69
Esta instrução permite aceder à função standard Average do Excel, à qual é passado
um objecto do tipo Range, representando a gama de células descritas sob o nome "Dados".
O resultado fornecido pela função será a média dos valores contidos nas células que
compõem essa gama.
EP
IS
70
8 Programação do Excel usando VBA
Nesta secção vamos aprender a trabalhar com os objectos do Excel mais comuns: o Work-
book (Livro de trabalho), a Worksheet (Folha de cálculo) e o Range (gama de células). São
objectos que pertencem, por sua vez, ao objecto principal que é a Application (Aplicação,
neste caso, o próprio Excel).
• Usando o objecto Workbooks que representa o conjunto dos ficheiros Excel abertos
naquele momento (Workbooks(Nome));
Workbooks.Open Nome_do_ficheiro
IS
Exemplo:
Workbooks.Open "C : \Documentos\Excel\Dados.xls"
Os métodos Save e Close são utilizados de forma similar para salvaguardar o conteúdo
dum ficheiro e para o fechar, respectivamente.
71
• Worksheet.Name - permite mudar ou obter o nome da folha de cálculo. O exemplo
abaixo muda o nome de "Folha 1" para "Medidas":
Workbook("Dados 2007").Worksheets("Custos").Activate
Sintaxe:
Worksheet.Copy [Position]
Exemplo:
Worksheets(2).Copy After:=Worksheets(3)
Sintaxe:
Worksheet.Add [Position]
28
A folha de cálculo activa é aquela que está visível no momento.
72
8.3 Trabalhar com objectos Range
Um objecto do tipo Range pode representar uma simples célula, um conjunto de células,
uma linha ou uma coluna. Não existe em VBA um objecto específico para representar
uma célula individual.
Para nos referirmos a uma célula ou gama de células podemos aplicar o método Range
ao objecto Worksheet usando uma de duas sintaxes possíveis:
Sintaxe 1:
Worksheet.Range(Nome)
Sintaxe 2:
Worksheet.Range(Celula1, Celula2)
A 1a sintaxe usa nomes de gamas pré-definidos29 , enquanto que a 2a utiliza as re-
ferências das células que definem os dois vértices opostos da área rectangular contendo
as células que se quer especificar. Caso se omita a referência a Worksheet em qualquer
das sintaxes anteriores, o VBA pressupõe que se trata da folha de cálculo activa naquele
momento.
Exemplos:
Range("C5").Value = 100
Range("D1","D10").Value = 0
Worksheets(3).Range("Dados").ClearContents
O 1o exemplo guarda o valor 100 na célula C5 da folha de cálculo activa. O 2o exemplo
EP
atribui o valor zero a todas as células da gama D1 a D10. Nestes dois exemplos é utilizada
a propriedade Value dos objectos Range que permite conhecer ou modificar o seu valor.
IS
73
Caso se pretenda identificar uma linha ou coluna completa, podem ser utilizados os
métodos Rows e Columns.
Sintaxe:
Objecto.Rows(Indice)
Objecto.Columns(Indice)
Para ilustrar a utilização do método Rows atente-se no seguinte exemplo de sub-
rotina31 :
Listing 14: Sub-rotina InsereLinhas
1 Sub I n s e r e L i n h a s ( gama As Range , num As Integer )
2 Dim num_linhas As Integer , u l t i m a _ l i n h a As Integer
3 Dim i As Integer
4 With gama
5 num_linhas = . Rows . Count
6 u l t i m a _ l i n h a = . Rows ( num_linhas ) . Row
7 For i = 1 To num
8 . Rows ( u l t i m a _ l i n h a + i ) . I n s e r t
9 Next
10 End With
11 End Sub
Esta sub-rotina recebe como argumentos uma gama de células (um objecto do tipo
EP
74
Sintaxe:
Range.Offset(linha,coluna)
Na Figura 38 podem observar-se dois exemplos de aplicação desta propriedade. Mantendo-
se a célula activa B3, no caso A foi armazenado o valor 2 na célula B5 (duas linhas abaixo
de B3 e na mesma coluna) usando a seguinte instrução:
ActiveCell.Offset(2,0) = 2
No caso B, foi colocado o valor 2 em A3 (na mesma linha e uma coluna antes de b3),
usando a instrução:
ActiveCell.Offset(0,-1) = 2
Note-se que nos dois casos a célula activa se manteve inalterada. Apenas se especificou
a posição de uma célula em relação a um referencial fixo (B3).
EP
IS
Usando esta propriedade podemos escolher uma célula especificando a sua coluna ou
a sua linha (ou as duas) de forma relativa, ou seja, em relação ao objecto Range a que
se aplica. Isto pode não parecer à primeira vista especialmente útil. No entanto, se
pensarmos que linha ou coluna podem ser constituídos por variáveis, cujo valor pode
ser controlado por uma estrutura de repetição, podemos ver que temos aqui uma forma
expedita de executarmos uma mesma acção sobre um conjunto de células definido de
forma relativa em relação a uma dada célula, que podemos considerar como uma espécie
de âncora.
75
9 Adicionando uma interface gráfica
O acesso aos macros faz-se, conforme referido na Secção 2.3, mediante a combinação de
teclas ALT-F8. Pode ainda associar-se a um macro uma combinação de teclas especial
que permite accioná-lo directamente. No entanto, em muitos casos, é mais conveniente
poder interagir com o macro através de uma interface própria, concebida especialmente
para ele. Usam-se para o efeito objectos gráficos como Dialog Boxes (Caixas de Diálogo)
desenhadas à medida, que são versões mais desenvolvidas das já conhecidas Input Boxes
e Message Boxes.
Vamos nesta secção ver como construir as nossas próprias Dialog Boxes usando ob-
jectos da classe UserForm e como as integrar numa aplicação em VBA.
Na Figura 39 pode-se ver uma Form vazia e uma caixa de ferramentas (Toolbox )
contendo os vários controlos (objectos gráficos) disponíveis para a construção da interface.
Pode ainda ver-se no canto inferior esquerdo a Janela de Propriedades, através da qual é
76
possível manipular várias características da Form (como, aliás, de qualquer controlo que
esteja seleccionado).
1. Visualização da Form
EP
77
Unload Me
No entanto, desactivar uma Form através da instrução Unload não implica que esta
deixe de estar em memória. Para garantir a sua efectiva remoção, que se traduzirá na
geração do evento Terminate, haverá que se usar a seguinte técnica:
1 Exemplo :
2 Set MinhaForm = Nothing
6 End I f
End Sub
IS
78
Classe Conteúdo
CheckBox True ou False conforme esteja ou não activada
OptionButton True ou False conforme esteja ou não activada
ListBox A posição da linha seleccionada
TextBox O conteúdo da TextBox (pode-se também usar a propriedade Text)
TabStrip Um inteiro indicando qual a Tab que está activa
Recorde-se que nas List Boxes em VBA à 1a linha corresponde a posição 1.
memória quando ela termine o seu trabalho. Para facilitar a sua invocação, é conveniente
associar ao macro uma combinação de teclas específica, usando uma das técnicas já
aprendidas (ver parte final da Secção 2.6).
79
Figura 40: A UserForm para Entrada Múltipla de Dados
8 End Sub
IS
80
Figura 41: Objecto da classe Tabstrip
Conforme já referido anteriormente (Secção 4.1 na página 23), para que um controlo
possa reagir a acções provocadas pelo utilizador, como o "clicar" do rato, é preciso que
o programador crie sub-programas especiais, chamados Event Handlers (tratadores de
eventos) e que esses sub-programas sejam associados aos controlos respectivos. Esses
Handlers contêm as instruções que controlam a reacção do objecto ao evento ocorrido.
Vamos apresentar dois exemplos de Event Handlers, sub-programas que permitem
especificar o comportamento de controlos em face de certos eventos. Em primeiro lugar,
apresentar-se-á o Event Handler da form "UserForm" para o evento Initialize (Lista-
EP
gem 19). Este evento ocorre automaticamente quando, após o arranque do programa, a
form é criada.
IS
Este procedimento vai inicializar os dois separadores do controlo Tabstrip1 com que
ele é criado por defeito, mudando-lhe os nomes para "Civil" e "Informática". De seguida,
acrescenta um terceiro separador e dá-lhe o nome "Electrotecnia". Por fim, são atribuídos
a cada uma das TextBox contidas na Tabstrip1 os conteúdos das três células da folha de
81
cálculo referentes ao curso referente ao 1o separador.
Mais uma vez, repare-se na utilização da estrutura With..End que permite simplificar
a escrita das instruções 3,4 e 5. Sem ela, cada uma dessas instruções deveria vir precedida
do nome do objecto a que se aplicam (TabStrip1 ). Da mesma forma, nas instruções 8,9 e
10, as referências às células D5, D6 e D7 teriam que ser precedidas da indicação de qual
a folha de cálculo a que pertenciam (Worksheets(4)).
O próximo procedimento (Listagem 20) é o Event Handler do controlo Tabstrip1
para o evento Change que ocorre sempre que alguma alteração ocorre nesse controlo,
concretamente, uma mudança de separador activo.
A propriedade Value dos objectos Tabstrip contem um valor numérico inteiro que
traduz qual o separador que está activo. Em função do valor recolhido na variável v, a
estrutura condicional imbricada If...Then...Else irá escolher o conjunto de valores corres-
pondente e armazená-los nas caixas de texto respectivas.
8 txtMedia = . [ D7 ]
9 E l s e I f v = 1 Then
txtNumAlunos = . [ E5 ]
IS
10
11 txtPercAprov = . [ E6 ] ∗ 100
12 txtMedia = . [ E7 ]
13 Else
14 txtNumAlunos = . [ F5 ]
15 txtPercAprov = . [ F6 ] ∗ 100
16 txtMedia = . [ F7 ]
17 End I f
18 End With
19 End Sub
82
10 Manipulação de texto
O VBA representa texto através de strings (cadeias de caracteres). Não existe um tipo
de dados específico para representar caracteres individuais, pelo que se utiliza o mesmo
tipo usado para cadeias de caracteres.
10.1.2 Len
Retorna o número de caracteres de uma string ou, por outras palavras, o seu compri-
mento..
Exemplos:
Dim s1 As String , n As Integer
s1 = "␣␣ISEP␣ C i v i l ␣␣"
n = Len( s1 ) ’ R e s u l t a d o : n = 14
n = Len(Trim( s1 ) ) ’ R e s u l t a d o : n = 10
83
Dim s1 As String , s2 As String , n As Integer
s1 = "ISEP␣ C i v i l "
n = 2
s2 = Left ( s t 1 , n ) ’ R e s u l t a d o : s2 = " IS "
s2 = Right ( s t 1 , n ) ’ R e s u l t a d o : s2 = " i l "
’ E l i m i n a r o p r i m e i r o c a r a c t e r de uma s t r i n g .
s1 = Right ( s1 , Len( s1 ) −1) ’ R e s u l t a d o : s1 = "SEP C i v i l "
Esta última instrução usa a função Right para seleccionar os primeiros Len(s1)-1
caracteres contados a partir da direita. Se Len(s1) nos dá o número de caracteres da
string então os caracteres seleccionados serão todos menos o primeiro. Como esta nova
string é de novo guardada em s1, estamos efectivamente a eliminar o 1o caracter da string
s1.
10.1.4 Mid
Sintaxe:
Mid(s As String, i As Integer [, n As Integer]) As String
Copia n caracteres da string s a partir da posição inicial i. Se n não for indicado (o
3 argumento é opcional), será copiado tudo desde i até ao fim da string.
o
Exemplos:
Dim s1 As String , s2 a s String
EP
s1 = "ISEP␣ C i v i l "
s2 = Mid( s1 , 2 , 2 ) ’ R e s u l t a d o : s2 = "EP"
IS
10.1.5 InStr
Sintaxe:
Instr([i as Integer, ] s1 As String, s2 As String) As Integer
Procura um padrão s2 dentro de uma string (s1) a partir da posição i. Se essa posição
i não for definida (o 1o argumento é opcional), a pesquisa começará no princípio da string.
Se a pesquisa tiver sucesso, a função devolverá um valor numérico indicando a posição
na string s1 em que o padrão s2 começa. Caso não tenha sucesso, será devolvido o valor
zero.
Exemplos:
Dim s As String , n As Integer
s = "ISEP␣ C i v i l "
n = Instr ( s , "␣" ) ’ Resultado : n = 5
n = Instr ( 5 , s , "␣" ) ’ Resultado : 0
n = InStr ( s , " C i v i l " ) ’ Resultado : 6
84
10.1.6 UCase, LCase
Sintaxe:
UCase(s As String) As String
LCase(s As String) As String
Retorna uma cópia da string original s, mas com letras convertidas para maiúsculas
(UCase) ou minúsculas (LCase). Obviamente os valores numéricos e os caracteres de
pontuação mantem-se inalterados.
Exemplos:
Dim s1 As String , s2 As String
s1 = " i109123X "
s2 = UCase( s1 ) ’ R e s u l t a d o : s2 = "I100Y"
s2 = LCase( s1 ) ’ R e s u l t a d o : s2 = " i 1 0 0 y "
10.2 Algoritmos
Nesta secção são discutidos métodos que permitem dividir uma string nos caracteres que
a constituem e dividir uma frase em palavras 32 .
O método baseia-se na repetição das instruções nas linhas 3 e 5 para cada elemento
da string. A 1a instrução usa a função Left para isolar o 1o caracter da string, copiando-o
para a variável c. Conforme analizado na Secção 10.1.3 na página 83 a 2a instrução vai
armazenar a string s uma vez expurgada do 1o caracter. Será essa string amputada que
vai ser processada na próxima iteração do ciclo. Este terminará quando s contiver a string
vazia. O conteúdo da string original ficará assim perdido.
32
Os exemplos desta Secção são adaptações dos incluídos nos textos de apoio do prof. Ângelo Martins.
85
Listing 22: Separação de string em caracteres - 2o Método
1 Dim s t As String , c As String , v As Integer
2 For v = 1 To Len( s )
3 c = Mid( s , v , 1 )
4 ’ Processamento do c a r a c t e r que acabou de s e r i s o l a d o
5 Next
Este 2o método baseia-se na instrução da linha 3, que usa a função Mid. Como
descrito na Secção 10.1.4 na página 84, esta função vai copiar um caracter (3o argumento)
da string s a partir da posição especificada pelo conteúdo da variável v. Esta variável,
que é ao mesmo tempo a variável de controle do ciclo For, vai conter, ao longo do seu
funcionamento, todos os valores desde 1 até Len(s), ou seja, a posição do último caracter
da string. Não há qualquer alteração do conteúdo da string original.
3 s = Trim( s )
4 Do While s <> ""
IS
5 p = InStr ( s , "␣" )
6 I f p > 0 Then
7 p a l = Left ( s , p − 1 )
8 s = LTrim( Right ( s , Len( s ) − p ) )
9 Else
10 pal = s
11 s = ""
12 End I f
13 ’ Processamento da p a l a v r a c o n t i d a em p a l
14 Loop
2. Right(s, Len(s) - p) copia a parte da string s que vai do seu fim até à posição p,
ou seja, tudo menos a palavra que foi já copiada para pal.
86
3. A função LTrim limita-se a descartar o espaço existente entre a 1a palavra e o resto
da string.
EP
IS
87
11 Notas finais
Alguns dos exemplos apresentados foram inspirados no livro de Paul McFreddies[1]. Fo-
ram ainda reutilizados e adaptados materiais contidos na Sebenta de Introdução à Com-
putação da minha autoria[2].
Referências
[1] Paul McFredies. VBA for the Microsoft Office System, QUE.
EP
IS
88