89
Programação em VBA Texto Introdutório versão 2 António Silva DEI-Isep 2009-12-30 1

Programming in VBA v2a

Embed Size (px)

Citation preview

Page 1: Programming in VBA v2a

Programação em VBATexto Introdutório

versão 2

António SilvaDEI-Isep

2009-12-30

1

Page 2: Programming in VBA v2a

.

Page 3: Programming in VBA v2a

Conteúdo1 Introdução 9

2 Conceitos Básicos 92.1 O que é um Macro? . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 92.2 Técnicas de construção dum Macro . . . . . . . . . . . . . . . . . . . . . 102.3 Gravação de um Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . 102.4 A escrita de um Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.5 O editor de VBA . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 122.6 Criação de um Macro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 13

3 Variáveis e Tipos de Dados 163.1 Conceito de variável . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.2 Criação das variáveis . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 163.3 Âmbito de uma variável . . . . . . . . . . . . . . . . . . . . . . . . . . . 183.4 Tipos de Dados . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 203.5 A operação de Atribuição . . . . . . . . . . . . . . . . . . . . . . . . . . 203.6 O uso de constantes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 21

4 Como trabalhar com Objectos 224.1 Propriedades, Métodos e Eventos . . . . . . . . . . . . . . . . . . . . . . 23

4.1.1 Propriedades . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 234.1.2 Métodos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 244.1.3 Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25

4.2 Os objectos do Excel mais comuns . . . . . . . . . . . . . . . . . . . . . . 274.2.1 Como trabalhar com as propriedades dos objectos Excel . . . . . 274.2.2 Como aplicar métodos aos objectos . . . . . . . . . . . . . . . . . 28

4.3 Objectos gráficos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294.3.1 MsgBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 294.3.2 InputBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 314.3.3 Forms . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324.3.4 Botões de Comando . . . . . . . . . . . . . . . . . . . . . . . . . 324.3.5 Rótulos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 324.3.6 Caixas de Texto . . . . . . . . . . . . . . . . . . . . . . . . . . . . 334.3.7 Botões de Opção . . . . . . . . . . . . . . . . . . . . . . . . . . . 344.3.8 Caixas de Verificação . . . . . . . . . . . . . . . . . . . . . . . . . 344.3.9 Quadros (Frames) . . . . . . . . . . . . . . . . . . . . . . . . . . 354.3.10 Caixas de Listagem . . . . . . . . . . . . . . . . . . . . . . . . . . 36

4.4 Interface gráfica sem uma Form . . . . . . . . . . . . . . . . . . . . . . . 37

5 Estruturas de controlo do programa 395.1 Estruturas de controlo condicional . . . . . . . . . . . . . . . . . . . . . . 39

5.1.1 If...Then...Else . . . . . . . . . . . . . . . . . . . . . . . . . . . . 395.1.2 If...Then . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 405.1.3 Estruturas condicionais embutidas . . . . . . . . . . . . . . . . . . 42

5.2 Estruturas de controlo repetitivo . . . . . . . . . . . . . . . . . . . . . . 44

3

Page 4: Programming in VBA v2a

5.2.1 Estruturas de Controlo Do...Loop . . . . . . . . . . . . . . . . . . 445.2.2 Ciclos controlados por contador . . . . . . . . . . . . . . . . . . . 455.2.3 Exemplo integrador . . . . . . . . . . . . . . . . . . . . . . . . . . 475.2.4 Ciclos controlados por sentinela . . . . . . . . . . . . . . . . . . . 495.2.5 Estrutura de Controlo For..To..Next . . . . . . . . . . . . . . . . . 505.2.6 Estruturas de controlo repetitivo imbricadas . . . . . . . . . . . . 52

6 Variáveis indexadas - vectores e matrizes 546.1 Declaração estática de vectores . . . . . . . . . . . . . . . . . . . . . . . 556.2 Declaração dinâmica de vectores . . . . . . . . . . . . . . . . . . . . . . . 566.3 Processamento de vectores . . . . . . . . . . . . . . . . . . . . . . . . . . 566.4 Matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 59

7 Funções e Procedimentos 627.1 Funções . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 627.2 Exemplos de funções criadas pelo programador . . . . . . . . . . . . . . . 637.3 Passagem de parâmetros ByVal . . . . . . . . . . . . . . . . . . . . . . . 667.4 Procedimentos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 677.5 Passagem de parâmetros ByRef . . . . . . . . . . . . . . . . . . . . . . . 687.6 Como aceder às funções standard do Excel . . . . . . . . . . . . . . . . . 69

8 Programação do Excel usando VBA 718.1 Trabalhar com objectos Workbook . . . . . . . . . . . . . . . . . . . . . . 718.2 Trabalhar com objectos Worksheet . . . . . . . . . . . . . . . . . . . . . 71

8.2.1 Propriedades de Worksheet . . . . . . . . . . . . . . . . . . . . . . 718.2.2 Métodos de Worksheet . . . . . . . . . . . . . . . . . . . . . . . . 72

8.3 Trabalhar com objectos Range . . . . . . . . . . . . . . . . . . . . . . . . 73

9 Adicionando uma interface gráfica 769.1 Instalação da Form . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 769.2 Instalação dos Controlos . . . . . . . . . . . . . . . . . . . . . . . . . . . 779.3 Associação da Form ao procedimento . . . . . . . . . . . . . . . . . . . . 77

9.3.1 Como visualizar e terminar uma Form . . . . . . . . . . . . . . . 779.3.2 Tratamento de eventos através de Event Handlers . . . . . . . . . 789.3.3 Como recolher os resultados de uma Form . . . . . . . . . . . . . 789.3.4 Exemplo de aplicação . . . . . . . . . . . . . . . . . . . . . . . . . 79

9.4 Exemplo de aplicação mais elaborado . . . . . . . . . . . . . . . . . . . . 80

10 Manipulação de texto 8310.1 Funções de manipulação de strings . . . . . . . . . . . . . . . . . . . . . 83

10.1.1 Trim, LTrim e RTrim . . . . . . . . . . . . . . . . . . . . . . . . . 8310.1.2 Len . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8310.1.3 Left, Right . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8310.1.4 Mid . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8410.1.5 InStr . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 8410.1.6 UCase, LCase . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

10.2 Algoritmos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 85

4

Page 5: Programming in VBA v2a

10.2.1 Separação duma string em caracteres . . . . . . . . . . . . . . . . 8510.2.2 Divisão de uma frase em palavras . . . . . . . . . . . . . . . . . . 86

11 Notas finais 88

5

Page 6: Programming in VBA v2a

Lista de Figuras1 Janela de invocação do ambiente de Gravação de Macros . . . . . . . . . 102 Janela de Gestão de Macros . . . . . . . . . . . . . . . . . . . . . . . . . 113 Barra de Ferramentas de VBA . . . . . . . . . . . . . . . . . . . . . . . . 114 Editor integrado do VBA . . . . . . . . . . . . . . . . . . . . . . . . . . . 125 Criação de novo Módulo . . . . . . . . . . . . . . . . . . . . . . . . . . . 136 Diferentes tipos de dados e o seu armazenamento em memória . . . . . . 177 Como forçar a declaração explícita automaticamente . . . . . . . . . . . 188 Uma Form e vários Controlos . . . . . . . . . . . . . . . . . . . . . . . . 229 Janela de Propriedades . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2410 Lista de eventos disponíveis . . . . . . . . . . . . . . . . . . . . . . . . . 2511 Objectos e Eventos . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2612 Exemplo de MsgBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 2913 Exemplo de InputBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3114 Vários optionButton agrupados numa frame . . . . . . . . . . . . . . . . 3415 Vários checkBox agrupadas numa frame . . . . . . . . . . . . . . . . . . 3516 Uma Frame agrupando três botões de comando . . . . . . . . . . . . . . 3517 Exemplo de listBox . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 3618 Interface construída directamente na folha de cálculo . . . . . . . . . . . 3819 Estrutura de controlo condicional If...Then...Else . . . . . . . . . . . . . 3920 Estrutura de controlo condicional If...Then . . . . . . . . . . . . . . . . 4021 Estruturas de controlo condicional imbricadas . . . . . . . . . . . . . . . 4322 Estrutura de controlo repetitivo Do...While . . . . . . . . . . . . . . . . 4423 Estrutura de controlo repetitivo Do...Until . . . . . . . . . . . . . . . . 4524 Ciclos controlados por contador . . . . . . . . . . . . . . . . . . . . . . . 4625 Exemplo integrador - Interface . . . . . . . . . . . . . . . . . . . . . . . . 4726 Exemplo integrador - Código . . . . . . . . . . . . . . . . . . . . . . . . . 4827 Ciclos controlados por sentinela . . . . . . . . . . . . . . . . . . . . . . . 5028 Exemplo de Ciclos Imbricados . . . . . . . . . . . . . . . . . . . . . . . . 5229 Um vector é uma variável múltipla . . . . . . . . . . . . . . . . . . . . . 5430 Um exemplo de vector de strings . . . . . . . . . . . . . . . . . . . . . . 5531 Porquê usar ciclos para processar vectores? . . . . . . . . . . . . . . . . . 5732 Ciclos encadeados para processar um vector bidimensional . . . . . . . . 5933 Funções como caixas pretas . . . . . . . . . . . . . . . . . . . . . . . . . 6334 Utilização da função margemLucro numa fórmula . . . . . . . . . . . . . 6435 Análise passo a passo da expressão de cálculo das combinações . . . . . . 6536 Comunicação da função com o programa que a invoca . . . . . . . . . . . 6637 Resultados do código da Listagem 13 na página 68 . . . . . . . . . . . . 6938 Exemplos de utilização da propriedade Offset . . . . . . . . . . . . . . . 7539 Criação de uma Form no VBA . . . . . . . . . . . . . . . . . . . . . . . 7640 A UserForm para Entrada Múltipla de Dados . . . . . . . . . . . . . . . 8041 Objecto da classe Tabstrip . . . . . . . . . . . . . . . . . . . . . . . . . . 81

6

Page 7: Programming in VBA v2a

Lista de Tabelas1 Tipos de dados suportados pelo VBA . . . . . . . . . . . . . . . . . . . . 202 Propriedades mais comuns dos objectos gráficos VBA . . . . . . . . . . . 233 Valores de configuração das características de uma Caixa de Mensagem . 304 Valores devolvidos por uma Caixa de Mensagem . . . . . . . . . . . . . . 30

7

Page 8: Programming in VBA v2a

Listings1 VerificaValor - exemplo de macro . . . . . . . . . . . . . . . . . . . . . . 142 verificaGama - exemplo de macro . . . . . . . . . . . . . . . . . . . . . . 143 Exemplo de aplicação de If..Then..Else imbricados . . . . . . . . . . . . 434 FormataBordo - exemplo de sub-rotina usando For..Next . . . . . . . . . 515 Exemplo usando Ciclos Imbricados . . . . . . . . . . . . . . . . . . . . . 536 Exemplo de Sub-rotina usando Ciclos Imbricados . . . . . . . . . . . . . 537 Exemplo de processamento de um vector . . . . . . . . . . . . . . . . . . 578 Outro exemplo de processamento de um vector . . . . . . . . . . . . . . . 589 Soma de matrizes . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6010 Função mLucro . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6311 Função factorial . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6412 Programa de cálculo de Combinações . . . . . . . . . . . . . . . . . . . . 6513 Diferentes resultados na passagem por valor e por referência . . . . . . . 6814 Sub-rotina InsereLinhas . . . . . . . . . . . . . . . . . . . . . . . . . . . 7415 Handler do objecto cmdFechar para o evento click . . . . . . . . . . . . 7816 Exemplo de sub-rotina de invocação de uma UserForm . . . . . . . . . . 7917 Exemplo de sub-rotina de inicialização de uma UserForm . . . . . . . . . 7918 Handler do objecto cmdFechar para o evento Click . . . . . . . . . . . . 8019 Sub-rotina de inicialização da UserForm . . . . . . . . . . . . . . . . . . 8120 Handler associado ao objecto Tabstrip1 para o evento Change . . . . . . 8221 Separação de string em caracteres - 1o Método . . . . . . . . . . . . . . . 8522 Separação de string em caracteres - 2o Método . . . . . . . . . . . . . . . 8623 Separação de frase em palavras . . . . . . . . . . . . . . . . . . . . . . . 86

8

Page 9: Programming in VBA v2a

1 IntroduçãoEste 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 folhasde cálculo Excel. Destina-se, assim, aos alunos que já possuem alguns conhecimentosda 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 ede funções standard.

A linguagem de programação que vai ser utilizada será o VBA (Visual Basic forApplications). É uma linguagem que permite acrescentar capacidades adicionais a certotipo de aplicações informáticas, concretamente as pertencentes ao Microsoft Office, entreas quais o Excel e o Word. Permite ainda automatizar a realização de muitas tarefasrotineiras nessas aplicações.

Como o próprio nome indica, trata-se duma adaptação da linguagem genérica deprogramação Visual Basic de modo a poder ser utilizada no ambiente específico dasaplicações Office.

2 Conceitos BásicosO VBA constitui uma ferramenta poderosa nas mãos de programadores experimentadosmas 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 querepetir uma determinada tarefa uma série de vezes de seguida. Seja escrever ou formatarum certo texto, seja executar uma série de comandos ou escolher opções de menus, sejaainda realizar a formatação complexa de um documento, são inúmeras as ocasiões emque dava jeito poder automatizar essas tarefas repetitivas.

É aqui que entra o VBA, permitindo a construção daquilo que se designa vulgarmentepor macros.

2.1 O que é um Macro?

Um macro contem uma lista das instruções a realizar para executar uma determinadatarefa. No fundo, é um programa escrito em VBA, que indica a uma aplicação como oExcel quais os passos a dar para atingir um objectivo específico. Pode-se dizer que ummacro não é mais que uma descrição formalizada das tarefas que se pretende automatizar.

Os macros incluem instruções que interagem com elementos da aplicação. Por exem-plo, quando, numa aplicação Office se pretende fechar uma janela, pode-se seleccionar aopção de menu Close. Um macro escrito em VBA, usará a seguinte instrução para obtero mesmo efeito:

ActiveWindow.Close

Existem duas formas alternativas de criar um macro mas a forma como ele é criadonão muda o seu conteúdo, continuando a ser um contentor de uma lista de instruções arealizar pela aplicação em que está instalado.

9

Page 10: Programming in VBA v2a

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 deforma 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 formaautomá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 fazerpara conseguir obter o resultado pretendido. O utilizador indica ao programa que sevai entrar num modo de gravação do macro e inicia a execução da sequência de acçõesque normalmente teria que executar. Quando chega ao fim dessa sequência, indica aoprograma que a gravação terminou. Após ter atribuído a essa sequência uma combinaçãode teclas especial, esse macro estará pronto a ser executado, substituindo assim o conjuntode acções que anteriormente seriam necessárias. Tudo se passa como se estivéssemos aensinar a aplicação pelo exemplo.

Se se investigar, no entanto, o conteúdo desse macro, verificar-se-á que ele é compostoprecisamente por instruções escritas em VBA, sendo que a cada acção ou comando daaplicaçã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 numeditor de texto apropriado. É essa, de facto, a forma de criar um macro quando o seuâmbito é algo não trivial1.

2.3 Gravação de um Macro

Quando uma dada operação envolvendo uma série de acções deve ser utilizada frequen-temente, faz sentido tentar automatizar a sua execução.

Figura 1: Janela de invocação do ambiente de Gravação de Macros

Para gravar um macro que seja capaz de efectuar essas acções, haverá que invocar omodo 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 onome do macro, a localização em que será armazenado, uma descrição das suas funções

1A tratar na Secção 2.6 na página 13.

10

Page 11: Programming in VBA v2a

e ainda a combinação de teclas (Shortcut key) que será utilizada para arrancar com omacro, uma vez este construído.

Após se premir a tecla OK, aparecerá uma pequena janela que permitirá controlaro processo de gravação e dever-se-á dar início à execução das acções que o macro vaisubstituir. Quando se tiver executado a última acção a incluir no macro, basta dar, nessajanela, a indicação de que a gravação terminou.

Uma vez tal realizado, esse macro passará a estar disponível mediante a invocaçãoda 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 mesmasequência de acções que tínhamos efectuado manualmente.

Figura 2: Janela de Gestão de Macros

Em alternativa, mediante a combinação de teclas ALT-F8, pode ser accionada a janelade Gestão de Macros (Figura 2), onde, entre outras acções, pode ser escolhido o macro aser executado.

Para facilitar o acesso às facilidades de gravação e edição de macros, será convenientetornar visível de forma permanente a barra de ferramentas de Visual Basic (Figura 3).No Excel, isto poderá fazer-se mediante a opção de Menu "View/Toolbars/Visual Basic".

Figura 3: Barra de Ferramentas de VBA

11

Page 12: Programming in VBA v2a

2.4 A escrita de um Macro

Ensinar pelo exemplo ao Excel como fazer as coisas é um método expedito de construirum macro, mas tem as suas limitações. Já que um macro não é mais que um programaescrito em VBA, porque não tratá-lo como tal e aceder ao seu código, alterando-o deforma a melhorar a sua eficiência ou a corrigir problemas. E já agora, porque não criá-losde raiz, aproveitando todo o poder duma linguagem como o VBA?

2.5 O editor de VBA

Para aceder ao editor especializado de Visual Basic (Figura 4), que se encontra integradono próprio Excel, basta utilizar o icone adequado na barra de ferramentas ou usar direc-tamente a combinação de teclas ALT-F11 (tornando a premir esta combinação de teclas,voltaremos à nossa folha de cálculo). A este editor especializado é também dado o nomede Integrated Development Environment (IDE) ou Ambiente de Desenvolvimento Inte-grado e é semelhante à aplicação autónoma usada para o desenvolvimento de programasem Visual Basic.

Figura 4: Editor integrado do 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 projectoVBA actual. Um projecto em VBA inclui um ficheiro duma aplicação Office (como, por

12

Page 13: Programming in VBA v2a

Figura 5: Criação de novo Módulo

exemplo, uma folha de cálculo do Excel) e todos os ficheiros VBA associados, incluindoos próprios macros e eventuais user forms (janelas de interface próprias utilizadas pelosmacros2).

Para poder começar a escrever macros usando o VBA é necessário criar um móduloque o possa albergar, o que é conseguido usando a opção de menu "Insert/Module". Comoconsequência, para além do novo módulo aparecer referido na janela do Explorador deProjectos, será criada uma janela nova onde será possível escrever o código que constitui onovo macro. Se já existir algum módulo criado, bastará seleccionar o módulo pretendidono explorador de projectos, posicionar o cursor na janela do editor correspondente aesse módulo, numa área fora de qualquer macro já existente, e seleccionar a opção demenu "Insert/Procedure". Aparecerá uma janela própria (Figura 5) onde será possíveldar o nome ao novo procedimento (o conjunto de instruções que constituirá o macro),especificar o tipo de macro que vai ser construído (função ou procedimento3) e qual oâmbito da sua utilização (privada ou pública, ou seja, limitada ou não ao ficheiro actual).Após premir o botão aparecerá na janela do editor o esqueleto do novo macro, apenascom o cabeçalho e o delimitador final.

2.6 Criação de um Macro

Está na hora de construir o primeiro macro em VBA. Suponhamos que se pretende criarum macro que verifique se o valor presente numa determinada célula é superior a umdado limite e que, caso seja, disso notifique o utilizador. A sub-rotina em que esse macrodeverá assentar poderá ter o conteúdo apresentado na Listagem 1 na próxima página.

Não nos vamos de momento preocupar com os detalhes do código que constitui omacro. Basta verificar, em 1o lugar, que é constituído por uma linha de cabeçalho queespecifica o tipo de macro (neste caso, uma sub-rotina (Sub) ou procedimento) e o seu

2Sobre o assunto, ver Secção 9.3A distinção entre funções e procedimentos (ou sub-rotinas) será abordada na Secção 7 na página 62.

13

Page 14: Programming in VBA v2a

nome (verificaValor). O corpo do macro é composto pela estrutura de controle condici-onal (If...Then4) que vai verificar se o conteúdo da célula B25 é ou não maior que o valor200. Caso essa condição seja verdadeira, o macro apresentará uma mensagem no ecrandizendo que o valor máximo foi excedido. Finalmente, o macro é terminado com umalinha contendo "End Sub".

Listing 1: VerificaValor - exemplo de macro

1 Public Sub v e r i f i c aVa l o r ( )2 I f Ce l l s (2 , 2) > 100 Then3 MsgBox "Valor ␣maximo␣ excedido ! "4 End I f5 End Sub

O que este simples macro faz, portanto, é verificar o conteúdo de uma célula específicada folha de cálculo e avisar o utilizador caso o valor nela contido ultrapassar um valorpré-determinado. Sempre que for necessário fazer esta verificação, bastará invocar acombinação de teclas que tenha sido associada a este macro.

É verdade que esta verificação poderia ter sido realizada colocando numa célula umafórmula contendo a função standard do Excel IF. Mas suponhamos agora que se pretendealgo mais complicado, por exemplo, fazer essa verificação num conjunto de células eapenas desencadear o alarme caso mais do que duas dessas células ultrapassem o limiteestabelecido. A sub-rotina modificada poderia ser algo como:

Listing 2: verificaGama - exemplo de macro

1 Public Sub ver i f icaGama ( )2 Dim i As Integer , c As Integer3 c = 04 For i = 1 To 55 I f Ce l l s ( i , 3) > 100 Then6 c = c + 17 End I f8 Next9 I f c > 2 Then

10 MsgBox c & "␣ va l o r e s ␣ s up e r i o r e s ␣ao␣ l im i t e ! "11 End I f12 End Sub

A verificação é agora repetida em todas as células de C1 a C5 graças aos serviçosda estrutura de controlo repetitivo For...To...Next6 que executará 5 vezes as instruçõescontidas nas linhas 5 a 7. Para além de verificar o conteúdo da célula em análise, é aindaactualizado um contador, baseado na variável c (ver linha 6), sempre que o valor contidonessa célula ultrapasse o limite. Só quando o valor desse contador for maior que 2 serágerada a mensagem de alarme.

4Ver Secção 5.1.2 na página 40.5Cells(2,2) refere-se à célula B2 (2a coluna, 2a linha)6Ver Secção 5.2.5 na página 50.

14

Page 15: Programming in VBA v2a

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 ecertamente impossível executando comandos e seleccionando menus do Excel.

A um macro criado usando directamente o VBA pode também ser associada umacombinação de teclas que facilite o seu acesso. Isso pode ser feito através do botão Optionsna Janela de Gestão de Macros, invocada mediante a combinação de teclas ALT-F8.

15

Page 16: Programming in VBA v2a

3 Variáveis e Tipos de DadosA informação processada por um macro pode ser de diferente natureza e existir emdiferentes formatos. Genericamente um programa pode utilizar, entre outras, informaçãonumérica e informação chamada alfa-numérica, ou seja texto. A linguagem VBA conseguelidar com informação de diversos tipos, que detalharemos mais adiante na Secção 3.4 napágina 20.

3.1 Conceito de variável

Uma variável é uma localização de memória em que a informação pode ser guardada demodo a ser usada por um macro. Cada variável é essencialmente caracterizada pelo seunome e pelo seu tipo, ou seja, o tipo de dados que pode armazenar7. Como é sugeridopelo próprio nome, o conteúdo de uma variável pode mudar durante a execução do macro.

Existem algumas regras governando a escolha do nome duma variável:

1. Deve obrigatoriamente começar por uma letra;

2. Não pode conter espaços nem caracteres como vírgulas ou pontos;

3. Não pode exceder 255 caracteres;

4. Não pode ser igual a uma palavra reservada para o VBA.

O tipo da variável especifica qual o tipo de dados que pode conter. Uma variável deum determinado tipo não está preparada para armazenar dados de um tipo diferente.A razão para este facto é que o espaço necessário para armazenar diferentes tipos dedados não é o mesmo. Enquanto um inteiro simples pode ser guardado em 2 bytes dememó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 graficamenteesta realidade. Enquanto que uma idade (valor inteiro) pôde ser guardada numa variáveldo tipo integer, dimensionada para armazenar valores inteiros, já um peso (valor real) teveque ser guardado numa variável do tipo single, com a dimensão adequada a armazenarvalores reais de uma dada precisão9.

3.2 Criação das variáveis

Ao acto de criação de variáveis chama-se declaração. Criar uma variável envolve dar-lheum nome e reservar em memória o espaço necessário para que ela possa guardar o tipo dedados para o qual está a ser criada. O acto de declarar a variável informa o VBA àcerca

7Na Secção 3.3 na página 18 é referida outra característica das variáveis, o seu âmbito, que, em certassituaçoes, faz sentido considerar.

8Para armazenar números que podem variar entre -32768 e 32767, ou seja 65536 valores diferentes, hánecessidade de dispor de 16 unidades básicas de informação (bits), ou seja dois bytes (1 byte = 8 bits).De facto, se cada bit apenas pode representar um valor binário (0 ou 1), 16 bits poderão representar até216 = 65536 valores diferentes.

9É possível armazenar um valor inteiro dentro de uma variável dimensionada para guardar valoresreais. O contrário é que já não é verdadeiro: ocorreria obrigatoriamente a truncagem do valor real,perdendo-se a parte fraccionária.

16

Page 17: Programming in VBA v2a

Figura 6: Diferentes tipos de dados e o seu armazenamento em memória

do nome pelo qual ela será conhecida assim como qual o tipo de dados que ela deveráestar preparada para receber.

Como é óbvio, nenhuma variável pode ser utilizada antes de ser criada. A declaraçãodeve, pois, preceder a sua utilização. Desde que se siga esta regra, é possível inserirdeclarações em qualquer ponto do macro. No entanto, é boa prática agrupar todas asdeclarações necessárias num bloco a colocar no início, para mais fácil manutenção doprograma.

Em VBA, existem duas formas de declaração de variáveis: explícita e implícita. Adeclaraçã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 VBAencarregar-se-á de criar automaticamente a variável do tipo pretendido.

Esta segunda forma de declarar variáveis tem, a despeito da sua simplicidade, um10A discussão dos vários tipos de dados suportados pelo VBA será feita na Secção 3.4.

17

Page 18: Programming in VBA v2a

problema grave: é possível, por distracção, criar uma variável nova indesejada, quando oque se pretendia era apenas escrever o nome de uma variável já existente. Suponha, porexemplo, 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á doprincí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 poderguardar 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 devariáveis é, pois, utilizar apenas declarações explícitas, e instruir o VBA para não aceitardeclarações implícitas, gerando uma mensagem de erro apropriada. Para tal, deverá seracrescentada a instrução Option Explicit no início do módulo contendo o macro.

Figura 7: Como forçar a declaração explícita automaticamente

Se se pretender que seja esse o comportamento automático do VBA em todos os mó-dulos, deverá seleccionar-se no Editor do VBA a opção "Require Variable Declaration"nosub-menu Options do menu Tools, conforme pode ser observado na Figura 7.

3.3 Âmbito de uma variável

Dissemos na Secção 3.1 na página 16 que uma variável se caracterizava pelo seu nomee pelo tipo de dados que estava preparada para guardar. Isso é rigorosamente verdadese considerarmos apenas variáveis contidas num único módulo. Mas se tivermos emconta que vários módulos podem existir, cada um com as suas variáveis, e ainda que as

11Como se verá na secção 3.5, esta instrução guarda na variável "Distancia"o valor 1260

18

Page 19: Programming in VBA v2a

variáveis podem ser declaradas fora de qualquer módulo, então teremos que adicionaruma 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 avariável foi declarada. Para esclarecer melhor este ponto, atente-se na Listagem 3.3, emque podemos ver duas sub-rotinas, sub1 e sub2, em que são criadas e utilizadas diversasvariáveis, e ainda uma variável n que foi declarada fora de qualquer sub-rotina.

1 Dim n As integer2 . . .3

4 Private Sub sub1 ( )5 Dim i As integer , x As s i n g l e6

7 i = 108 n = 1009 . . .

10 End Sub11

12 Private Sub sub2 ( )13 Dim i As integer , c As integer14

15 c = n ∗ 10 + i16 . . .17 End Sub

Na sub-rotina sub1 é usada quer a variável i (até aqui, nada de mais já que essavariável foi criada na própria sub-rotina) quer a variável n. Ora, esta segunda variávelnã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, comotal, acessível por qualquer módulo que a ela queira aceder. Por seu lado, a variável idiz-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 acediadastrês variáveis: c pertencendo à própria sub-rotina, a variável global n e a variável i. Autilização da variável global já foi discutida. Vale a pena, porém, discutir a utilização davariá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ãotendo sido guardado previamente qualquer valor na variável i dentro de sub2, o seu valorpor 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 muitoflexível e, em certos caso, insubstituível. No entanto, especial atenção deve ser prestadaa eventuais interacções indesejáveis entre módulos. Se muitas entidades acederem a umamesma variável global, modificando o seu conteúdo, pode tornar-se difícil detectar qualo módulo responsável por valores anómalos que possam surgir nessa variável.

19

Page 20: Programming in VBA v2a

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 naTabela 1.

Tipo DescriçãoInteger Inteiro simples, usado para representar inteiros entre -32768 e 32767Long Inteiro longo, ou seja, compreendido entre -2.147.483.648 e

2.147.483.647Single Real representado com precisão simples, com valores negativos compre-

endidos entre cerca de -3,4E38 e -1,4E-45 e valores positivos entre cercade 1,4E-45 e 3,4E38

Double Real representado com precisão dupla, usado para representar númerosreais 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

Tabela 1: Tipos de dados suportados pelo VBA

Quando declaramos variáveis dever-se-á, em princípio, especificar qual o tipo de dadosque ela irá suportar. No entanto, em VBA é possível omitir a especificação do tipo dedados na declaração de variáveis. O VBA criará, nesse caso, uma variável do tipo Variantcapaz de armazenar qualquer tipo de dados. O que, à partida, parece uma boa ideia acabapor não o ser porque, entre outros motivos, implica um gasto excessivo de memória e tornaa execução dos macros mais lenta. Será, portanto, de evitar, na medida do possível.

3.5 A operação de Atribuição

A operação de Atribuição permite guardar um dado numa variável, ou seja, atribuir-lheum valor. A sintaxe utilizada por esta operação é a seguinte:

Variável = Valor

O resultado da operação será, portanto, o de guardar Valor em Variável. Valorpode ser um valor constante ou o conteúdo de outra variável. Neste segundo caso, aatribuição consistirá na cópia do conteúdo de uma variável para outra do mesmo tipo. Ainstrução seguinte copia o valor contido na variável idade para a variável temp (partimosdo princípio que ambas são do tipo integer):

temp = idade

Pode ainda ser atribuído a um variável o resultado de uma expressão ou o valordevolvido por uma função. Atente-se nos seguintes exemplos:

20

Page 21: Programming in VBA v2a

total = peso1 + peso2resultado = sqrt(2+peso)

No 1o exemplo, o VBA resolverá em primeiro lugar a expressão à direita do operadorde 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 dosseus 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 essafunçã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 essavariável, substituirá o valor nela contido pelo novo valor. Convem, assim, lembrar quenesta operação o fluxo da informação se faz sempre da direita para a esquerda e não ocontrário.

Há ainda que ter em atenção o facto de que não é normalmente aconselhável atribuirum valor de um dado tipo a uma variável de tipo diferente. Os resultados podem ser aperda de informação ou o mau funcionamento do programa. O VBA poderá gerar umamensagem de erro mas tal nem sempre acontece, podendo produzir-se comportamentosanómalos difíceis de detectar e corrigir.

3.6 O uso de constantes

Uma constante consiste num nome que é dado a um valor numérico ou a uma cadeia decaracteres, e que pode ser usado dentro do programa na vez desses valores. Funcionacomo uma espécie de sinónimo. A utilização de uma constante, em substituição do valorque representa, justifica-se pelo seguinte facto: se um dado valor constante fôr utilizadomuitas vezes ao longo dum programa, caso ocorra a necessidade de o modificar, seremosforçados a corrigir manualmente todas as ocorrências desse valor, correndo, além disso, orisco de nos enganarmos. Se, ao invés, for definida uma constante com esse valor, bastarámodificar essa definição inicial para que tal mudança automaticamente se repercuta emtodas as ocorrências dessa constante no decurso do programa. A sintaxe da definição deconstantes é a seguinte:

Const Nome As tipo = expressão

Por expressão entende-se um valor numérico, uma cadeia de caracteres, ou uma ex-pressão cujo resultado seja um destes tipos de valores.

Caso, por exemplo, seja necessário usar ao longo de um macro um mesmo factor emvários cálculos, faz sentido definir esse factor como constante e usar o seu nome em vezdele:

Const Factor as Single = 1.347

Sempre que seja subsequentemente necessário utilizar este factor numa expressão,usar-se-á Factor em vez de 1.347.

21

Page 22: Programming in VBA v2a

4 Como trabalhar com ObjectosPara 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 numagama de células, vai ser preciso interagir com Objectos. Genericamente, pode dizer-se queum objecto é algo que pode ser visto, tocado, sentido. Em VBA, considera-se um objectotudo 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çãosão considerados, para os efeitos de programação em VBA, como sendo objectos. Maspodem ainda existir outros objectos, nomeadamente aqueles que permitem construir umainterface gráfica específica do macro. A esses objectos gráficos chamamos controlos e sãocolocados em janelas especiais chamadas forms.

Na Figura 8 podem ser observados vários objectos instalados numa form: uma caixade 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. Veremosem detalhe mais à frente para que servem e como utilizar estes diferentes objectos.

Figura 8: Uma Form e vários Controlos

Os objectos podem ser manipulados de várias formas:

• podemos mudar as suas propriedades, que traduzem características próprias dosobjectos;

• podemos aplicar um método a um objecto, ou seja, executar uma acção sobre ele;

• podemos especificar uma sub-rotina que será executada sempre que um determinadoevento ocorra nesse objecto.

Vamos agora utilizar a analogia para introduzir estes conceitos. Consideremos umautomóvel:

• As suas "propriedades" são características físicas como o modelo, o peso ou a cilin-drada;

22

Page 23: Programming in VBA v2a

• Os seus "métodos" especificam o que pode ser feito com ele: acelerar, travar, mudarde direcção, etc;

• Os seus "eventos" são ocorrências que provocarão respostas automáticas por partedo automóvel, como seja, um alarme que dispara (resposta) caso desliguemos ocarro com as luzes ligadas (evento).

4.1 Propriedades, Métodos e Eventos

Vamos, de seguida, aprofundar estes conceitos de propriedades, métodos e eventos.

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 ouo 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 seapresenta ou se comporta.

Diversas classes de objectos podem partilhar a mesma propriedade. Essa propriedade,no entanto, pode afectar esses objectos de forma diferente.

Caption Define o texto a afixar na barra de título das forms, da legenda(“caption”) dos botões de comando, ou nos rótulos (“label”)

Name Define o nome pelo qual o objecto é identificadoLeft Define o afastamento entre uma “form” e o limite esquerdo do ecrã

ou entre um controlo e o limite esquerdo da formTop Define o afastamento entre uma “form” e o topo do ecrã ou entre um

controlo e o topo da “form”Height Define a altura do objectoWidth Define a largura do objectoFont Especifica qual o tipo de letra a usar nos controlosVisible Permite controlar o aparecimento de um dado objecto

Tabela 2: Propriedades mais comuns dos objectos gráficos VBA

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 maisimportantes 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 objectotomam podem ser consultados ou modificados usando a janela de propriedades (Figura 9na próxima página). Nessa janela aparece a lista de propriedades do objecto que estivernesse momento seleccionado . Nela pode observar, entre outras, algumas das propriedadesreferidas na lista acima (Caption, Height e Font) e os respectivos valores no momento.

23

Page 24: Programming in VBA v2a

Figura 9: Janela de Propriedades

Quando num programa pretendemos referir-nos a uma propriedade de um objecto,utilizamos a seguinte sintaxe:

Objecto.Propriedade

Por exemplo, se nos quisermos referir à propriedade que controla o tipo de letra (font)da célula activa duma folha de cálculo, usaremos

ActiveCell.Font.Name

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 processode salvaguarda do conteúdo do documento activo num determinado ficheiro. Aplicar omé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 deobjectos é possível aplicar um determinado conjunto de métodos.

Para vermos como um método é aplicado a um objecto, vamos considerar o objectoWorksheet, que representa uma folha de cálculo do Excel. Se pretendermos que o nossomacro 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"paraa posição imediatamente a seguir à folha "Dados 2008", o comando a inserir no macroserá:

Worksheets("Dados 2009").Move Before:=Worksheets("Dados 2008")

Como veremos mais à frente, o objecto Worksheet é definido como um elemento do

24

Page 25: Programming in VBA v2a

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 à folhade cálculo com o nome "Dados 2009".

Outro método útil é o que permite referenciar uma célula individual pertencendo aum 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áveltemp:

temp = Cells(2,3)

Outra forma de referir uma célula individual é usar a notação utilizada pelo Excelpara referenciar células, envolvendo-a em parêntesis rectos. O exemplo anterior ficariaassim:

temp = [C2]

4.1.3 Eventos

Os eventos resultam de acções que, uma vez exercidas sobre um objecto, implicam apossibilidade de ocorrer uma resposta automática por parte dele. Basicamente, um eventoé algo que acontece a um objecto. Por exemplo, a abertura de uma folha de um livro detrabalho (workbook) em Excel é um evento. A inserção de uma nova folha no livro detrabalho é outro exemplo de evento.

Para que um objecto possa reagir a um dado evento deverá existir, previamente pro-gramado, um procedimento especial, chamado event handler (tratador de eventos), quevai especificar o que fazer caso esse evento ocorra. Sem isso, o objecto detectará esseacontecimento mas não saberá o que fazer. Nenhuma resposta será produzida.

Figura 10: Lista de eventos disponíveis

Na Figura 10 pode ver-se a janela de escrita de código de macros. Na parte de cima,

25

Page 26: Programming in VBA v2a

à direita, pode ser acedida a lista de eventos disponíveis para o objecto Worksheet12.Seleccionando um dos eventos, será possível construir o procedimento event handler quepermita ao objecto Worksheet reagir a esse evento. O cabeçalho e o delimitador final sãocriados automaticamente pelo editor do VBA, sendo da responsabilidade do programadora inclusão das instruções necessárias. Na figura são referidos vários eventos que podemocorrer no objecto Worksheet, tais como o Activate que ocorre sempre que uma folhade cálculo se torna activa, ou o Change que é desencadeado por qualquer alteração aoseu conteúdo. Assim sendo, um mesmo objecto, por exemplo, a Worksheet pode estarpreparada para reagir a diferentes eventos, desde que possua event handlers específicospara esses eventos.

Figura 11: Objectos e Eventos

Para tentar esclarecer melhor o conceito de evento e a questão de como organizara resposta do objecto a um evento, vamos apresentar um exemplo utilizando apenasobjectos gráficos dispostos numa form. Repare-se na Figura 11: o que se pretende aquié um macro capaz de verificar se um dado número inteiro, introduzido pelo utilizadorusando a interface descrita na figura, é ou não um número primo. Parte-se do princípioque todos sabem o que é um número primo e não nos vamos agora debruçar sobre os

12Isto porque as diferentes classes de objectos não são necessariamente sensíveis aos mesmos tipos deeventos.

26

Page 27: Programming in VBA v2a

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 queintervê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 detexto txt1, o rótulo lbl2 e o botão de comando command1. Quando o utilizador pretendeutilizar o macro, uma vez este invocado, deverá introduzir o número a testar em txt1 epressionar ("clicar") o botão command1. Quando isso acontece, diz-se que ocorreu umevento click no botão command1. Se esse botão não dispuser de nenhum event handlerpara lidar com esse tipo de evento, nada se passará. No entanto, se se tiver previamenteassociado a esse objecto (command1 ) um event handler adequado, o objecto será já capazde 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 primoe apresentar essa conclusão no rótulo lbl2.

4.2 Os objectos do Excel mais comuns

Já vimos que um documento Word ou Excel é, em si mesmo, um objecto. Se bem que nãolhe possamos tocar, podemos claramente vê-lo e interagir com ele de múltiplas formas, sejaalterando o conteúdo de células (no caso do Excel), seja mudando formatos ou inserindolinhas e colunas. Por sua vez, todos estes elementos são, eles também, objectos. Nasaplicações Office, os objectos estão organizados de forma hierárquica. O objecto maisgeral é o Application, e dentro dele existem múltiplos objectos de nível progressivamenteinferior.

4.2.1 Como trabalhar com as propriedades dos objectos Excel

Como já vimos, os objectos possuem características próprias, chamadas propriedades. Asintaxe genérica para nos referirmos a uma propriedade de um objecto é a seguinte:

Objecto.Propriedade

Se nos quisermos referir, por exemplo, à propriedade ActiveWindow do objecto Ap-plication, procederemos do seguinte modo:

Application.ActiveWindow

A propriedade ActiveWindow refere-se à janela da aplicação com que estamos, demomento, a trabalhar. No caso do Excel, podemos ainda referir-nos, por exemplo, àpropriedade ActiveSheet para designar a folha de cálculo em que se está a trabalhar ou aActiveCell para nos referirmos à célula actualmente seleccionada.

Se pretendermos, por exemplo, especificar o tipo de letra da célula activa, usaremosa seguinte descrição de objecto:

Application.ActiveWindow.ActiveCell.Font.Name

Esta descrição ilustra a relação hierárquica existente entre os objectos do Excel.Na prática, quando nos estamos a referir a uma propriedade da janela activa da

aplicação como seja a ActiveCell, não precisamos, no entanto, de referir que pertence à

27

Page 28: Programming in VBA v2a

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údopode ser modificado. De facto, uma propriedade pode ser vista como uma variável especialassociada a um dado objecto.

Se, ao contrário, quisermos obter o valor de uma dada propriedade, a instrução a usarserá 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.

4.2.2 Como aplicar métodos aos objectos

Vimos na Secção 4.1.2 na página 24, que os métodos de uma classe de objectos descrevemas acções que podemos executar sobre eles ou, por outras palavras, aquilo que podemosfazer com eles. Na sua forma mais simples, a sintaxe usada para aplicar um método aum objecto é similar à usada para trabalhar com as suas prorpiedades:

Objecto.Método

Um exemplo da aplicação de um método a um objecto, usando esta sintaxe, é oseguinte:

Worksheets("Leituras").Activate

Estamos aqui a aplicar o método Activate ao objecto Worksheets("Leituras"), oque tem como consequência que essa folha de cálculo se tornará activa.

No entanto, muitas vezes, os métodos exigem informação adicional para poderemexecutar o seu trabalho. Essa informação adicional será fornecida através de argumentos,inseridos a seguir ao nome do método aplicado:

Objecto.Método (argumento1, argumento2. ...)

O seguinte exemplo abre um Livro de Trabalho pré-existente com o nome "Dados.xls":

Workbooks.Open("Dados.xls")13Trata-se de uma operação de atribuição, descrita na Secção 3.5 na página 20

28

Page 29: Programming in VBA v2a

Muitas vezes, os argumentos que se podem fornecer a um método são opcionais. Porexemplo, a instrução abaixo adiciona (insere) uma nova folha de cálculo imediatamenteantes 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 dafolha de cálculo activa. É esse o comportamento por defeito do método Add.

4.3 Objectos gráficos

Vão agora ser apresentados de forma mais sistemática alguns dos objectos e facilidadesnecessários para realizar interfaces gráficas simples. Essas interfaces vão permitir queos macros tenham uma interacção directa com o utilizador, requerendo e fornecendoinformação.

A forma mais simples de o macro interagir com o utilizador é através de duas funções:MsgBox e InputBox.

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 decomando e eventualmente um pequeno desenho (ícone) ilustrativo do tipo de mensagem.Na Figura 12 encontra-se um exemplo de uma destas janelas.

Figura 12: Exemplo de MsgBox

Uma Caixa de Mensagem destina-se a apresentar ao utilizador uma mensagem cominformação relevante, sejam avisos, resultados, perguntas ou sugestões. Uma janela destetipo tem um comportamento peculiar: enquanto não for premido um dos seus botões,não será possível qualquer outra interacção com o computador, já que essa janela tomouo controlo. O utilizador é assim obrigado a atender à mensagem apresentada.

A sintaxe da função MsgBox é a seguinte:

MsgBox(Mensagem, Características, Título)

Em que os argumentos são:

29

Page 30: Programming in VBA v2a

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 somade 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 ovalor do parâmetro características, será preciso somar três valores, um de cada colunada Tabela 3, cada um deles especificando uma das características (Botões de Comando,Ícone e qual o botão com o "focus"14).

Botões de Comando Ícone Botão com o “focus”0 - OK 0 - Nenhum 0 - 1o Botão1 - OK, Cancel 16 - Mensagem Crítica 256 - 2o Botão2 - Abort, Retry, Ignore 32 - Mensagem de Aviso 1 512 - 3a Botão3 - Yes, No, Cancel 48 - Mensagem de Aviso 24 - Yes, No 64 - Mensagem de Informação5 - Retry, Cancel

Tabela 3: Valores de configuração das características de uma Caixa de Mensagem

No caso da Figura 12 na página precedente, os valores a somar seriam os seguintes:

1 + 16 + 0 = 17

A MsgBox serve então para apresentar uma mensagem ao utilizador. No entanto,permite também recolher informação. Quando a caixa de mensagem apresenta maisdo que um botão, está-se a pedir ao utilizador que escolha uma de entre duas ou trêsalternativas. Dependendo de qual o botão premido pelo utilizador, assim o valor numéricodevolvido pela função MsgBox será um de entre 7 valores possíveis, descritos na Tabela 4.

Constante Valor Botão seleccionadovbOK 1 OKvbCancel 2 CancelvbAbort 3 AbortvbRetry 4 RetryvbIgnore 5 IgnorevbYes 6 YesvbNo 7 No

Tabela 4: Valores devolvidos por uma Caixa de Mensagem

De notar que caso a tecla ESC (Escape) seja premida o valor devolvido será 2, a quecorresponde o botão Cancel (o que indica que as duas acções são equivalentes).

14O botão com o "focus" ou botão de defeito é aquele que será accionado automáticamente caso outilizador prima a tecla Enter ou Return.

30

Page 31: Programming in VBA v2a

Quando se pretende aproveitar o valor devolvido pela função MsgBox será necessáriousá-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 seguinteforma:

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árioda função MsgBox (Secção 4.3.1 na página 29), esta função produz um resultado do tipostring e não do tipo integer.

Figura 13: Exemplo de InputBox

Como pode ser visto na Figura 13, esta função cria um objecto composto (uma Caixade Entrada) incluindo um caixa de texto, dois botões15 e um rótulo dentro de umapequena 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áximode 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)

15Ao contrário da MsgBox, neste caso os dois botões são fixos. Por outro lado, a tecla ESC tem omesmo comportamento.

31

Page 32: Programming in VBA v2a

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 (genericamentedesignados 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". Esseprocesso 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á identificadaCaption especifica o título que figura no topo da Form

BackColor permite seleccionar a cor do fundoEnabled controla a utilização da Form pelo utilizador

ShowModal permite alterar o comportamento da Form de modo a controlaro acesso à aplicação enquanto a Form estiver activa

Font controla o tipo e tamanho da letra utilizadaHeight especifica a altura da FormWidth especifica a largura da Form

Nas próximas secções, referiremos com algum detalhe os controlos de uso mais comumna construção de dialogBoxes em VBA. Estes são os objectos que mais frequentementesão colocados numa form.

4.3.4 Botões de Comando

Um botão de comando (objecto commandButton), como o próprio nome sugere, é uti-lizado para permitir ao utilizador dar ordens (comandos) ao programa. Como se podeverificar 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 quecontrolam as dimensões (Height eWidth) e a propriedade Caption que permite especificaro texto afixado.

A instrução seguinte serve de exemplo de como alterar programaticamente o estadode 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 Enabled16 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 textona interface. Mais uma vez, a propriedade mais utilizada é a propriedade Caption, quepermite especificar o texto a apresentar. Este controlo é usado não só para apresentar

16Esta propriedade permite controlar o acesso do utilizador ao botão de comando.

32

Page 33: Programming in VBA v2a

informação estática, que é escolhida na fase de concepção da interface, como tambéminformaçã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 "Ovalor total é 235 metros", o que vai ter como consequência a sua afixação na interface.

Funções Val e StrA linguagem VBA dispõe de um grande número de funções pré-definidas. Duasdelas, relacionadas com "strings", são particularmente úteis para lidar com objectosda classeTextBox e Label :

Função DescriçãoVal() Retorna como valor numérico um número contido dentro duma stringStr() Retorna uma string representando um número

Vamos supor que um macro precisa de calcular o peso total à custa de dois valo-res introduzidos pelo utilizador através de duas TextBox. A tentação seria usar ainstrução:

pesoTotal = txt1.Text + txt2.Text

No entanto, o que a propriedade Text das TextBox contem é apenas texto, aindaque contendo algarismos. Para extrair a informação numérica de dentro do texto,haverá que utilizar a função Val():

pesoTotal = Val(txt1.Text) + Val(txt2.Text)

A função str(), por seu lado, converte um valor numérico num texto contendo essevalor. Uma utilização típica é a de permitir compor strings como a do exemploapresentado na Secção 4.3.5.A string "O valor total é de 35 metros"pode ser composta usando o símbolo "+"comooperador 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 nainstrução atrás, isso não ocorra, é preciso usar a função str() para converter parastring 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 duasTextBox, em vez da soma dos correspondentes valores numéricos.

4.3.6 Caixas de Texto

As caixas de texto (objecto TextBox ) são uma classe de controlos muito versáteis quepermitem a introdução pelo utilizador de diversos tipos de informação: texto, valores

33

Page 34: Programming in VBA v2a

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 permitira leitura de informação pelo programa.

4.3.7 Botões de Opção

Estes objectos permitem ao utilizador efectuar escolhas entre diversas alternativas. Sãocompostos pelo botão propriamente dito (de forma circular) e um pequeno texto que oacompanha, controlado pela propriedade Caption do objecto.

Figura 14: Vários optionButton agrupados numa frame

Os botões de opção são geralmente agrupados em conjuntos de dois ou mais, estandointerligados entre si, já que, ao mesmo tempo, só é possível que esteja um botão selecci-onado dentro do mesmo grupo de botões de opção. Encontram-se muitas vezes inseridosem frames (Secção 4.3.9 na página seguinte).

Para além de Caption, outra propriedade importante dos botões de opção é a propri-edade Value, que pode assumir o valor “True” ou “False” conforme o botão se encontre ounão seleccionado.

4.3.8 Caixas de Verificação

Estes objectos comportam-se de forma semelhante à dos botões de opção mas, neste caso,é possível encontrar vários controlos deste tipo activados simultaneamente na mesmaform, visto que tais objectos funcionam de forma independente (isto é, não se encontramrelacionados entre si).

Possuem também uma propriedade Value que, neste caso, pode apresentar os seguintesvalores:

34

Page 35: Programming in VBA v2a

Figura 15: Vários checkBox agrupadas numa frame

0 não activada1 activada2 não disponível

O texto a inserir junto de cada caixa de verificação deve ser especificado mediante apropriedade Caption.

4.3.9 Quadros (Frames)

Tais objectos destinam-se a agrupar outros objectos (controlos). São usados muitas vezespara organizar um dado conjunto de botões de opção (Secção 4.3.7 na página precedente),tornando-os independentes de outros botões de opção eventualmente existentes na mesmaform.

Figura 16: Uma Frame agrupando três botões de comando

É importante criar o quadro antes de aí inserir os controlos. Se o controlo fôr criadoantes do quadro, não será possível deslocá-lo para dentro do quadro após este ter sidocriado.

Uma vez inserido um objecto dentro do quadro, esse quadro passa a constituir o“contentor” desse objecto. Quer isto dizer que a sua localização passa a ser definida nãoem relação à form mas em relação ao quadro que o contem.

Outra utilidade dos quadros é servir de “moldura” a um dado conjunto de controlos, demodo a melhorar a aparência e a organização da form em que estão inseridos, agrupandoos diversos controlos de acordo com as suas funcionalidades.

35

Page 36: Programming in VBA v2a

4.3.10 Caixas de Listagem

Este objecto serve para apresentar listas e permite que o utilizador escolha uma ou maisopções dentro de uma dada lista. Esta lista é apresentada numa caixa própria (com umabarra de deslocamento vertical à direita, no caso de a lista ser mais extensa que o númerode linhas disponível na caixa).

Figura 17: Exemplo de listBox

Os elementos da lista podem ser especificados à partida usando a propriedade List,ou ser acrescentados durante a execução do programa usando o método AddItem:

listbox.AddItem elemento

ou

listbox.AddItem elemento, posição

em que

elemento é o novo elemento a acrescentar à listaposiçã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 paramanter 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 conseguidaaplicando-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

Page 37: Programming in VBA v2a

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 maneiraordenada

ColumnCount especifica qual o número de colunas em que a lista é apresen-tada

ColumnHeads controla os cabeçalhos das colunasMultiSelect permite controlar a forma de selecção de elementos na lista:

0 - só é possível seleccionar um elemento1 - é possível seleccionar vários elementos simultaneamente,pressionando cada elemento2 - é 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 Excelem que se encontra a informação a incluir na lista, ou seja, afonte dos dados a apresentar.

Na especificação de sintaxe, os parêntesis rectos indicam que o seu conteúdo é opcional.No caso das propriedades ListIndex e List descritas acima, a versão curta destina-se a serusada do lado direito de uma operação de atribuição, enquanto que na versão completao que se pretende é atribuir um valor à propriedade.

Existe uma variante da ListBox, chamada ComboBox, que combina uma TextBox comuma ListBox. O utilizador pode introduzir um item na TextBox ou seleccioná-lo na listaque, estando normalmente escondida, só aparecerá quando se clica num ícone próprio. Énormalmente utilizada quando se pretende dar a possibilidade de escolher um elementode uma lista mas sem ocupar muito espaço na form.

4.4 Interface gráfica sem uma Form

É possível criar uma interface gráfica para um macro sem ter que usar uma form onde seinstalem os diferentes controlos. Nesse caso, os controlos serão instalados directamentena própria folha de cálculo, numa área reservada para o efeito. Um exemplo pode serobservado na Figura 18 na página seguinte. A interface descrita utiliza um botão decomando e dois botões de opção.

Para a instalação desta interface, deve usar-se a Caixa de Ferramentas dos Con-trolos activada através da Barra de Ferramentas de VBA descrita na Figura 3 napágina 11. Esta Caixa de Ferramentas pode ser vista na parte inferior da Figura 18na página seguinte. Nesta Caixa é possível escolher-se qual o controlo que se pretende

37

Page 38: Programming in VBA v2a

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ópriafolha de cálculo a área que esse controlo vai ocupar. A sua posição e dimensões definitivaspoderão ser afinadas quer com o rato quer manipulando as propriedades correspondentesna janela de Propriedades.

38

Page 39: Programming in VBA v2a

5 Estruturas de controlo do programaUm macro é um programa escrito na linguagem VBA. Vamos agora começar a analizarmais em detalhe a estrutura de um programa. Um programa é composto por um conjuntode instruções, cada uma delas executando uma tarefa específica. A sequência de instruçõeslevará à solução do problema que o programa se propõe resolver. Mas essa sequência nãotem que ser necessariamente linear, i.e., composta por uma lista de instruções que serãorealizadas uma após outra, de forma imutável. Isso tornaria o programa inflexível, incapazde 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. Comessa operação podemos criar instruções simples, mediante as quais é possível copiar valoresentre variáveis, ou armazenar resultados do cálculo de expressões. Mas um programaflexível não poderá ser construído apenas com instruções desse tipo. É preciso disporde instruções que permitam alterar o fluxo do programa. Para tal, vamos introduzirestruturas de controlo que possibilitam a alteração desse fluxo.

5.1 Estruturas de controlo condicional

Uma estrutura de controlo fundamental é a estrutura condicional, ou de selecção. Usandoesta estrutura, as instruções podem ser executadas condicionalmente. Se uma dada con-dição fôr verdadeira, será executada uma dada sequência de instruções. Se fôr falsa, umasequência diferente será escolhida.

5.1.1 If...Then...Else

Figura 19: Estrutura de controlo condicional If...Then...Else

39

Page 40: Programming in VBA v2a

A Figura 19 na página anterior descreve a estrutura condicional If...Then...Else. Comoo seu nome sugere, esta estrutura está baseada no teste de uma condição. Se essa condiçãofôr verdadeira, desencadeará a execução das instruções representadas na figura por Blocode Instruções1. Em caso contrário, será executado o Bloco de Instruções 2.

A sintaxe desta estrutura é:

1 I f condicao Then2 [ i n s t r u c o e s ]3 Else4 [ i n s t r u c o e s a l t e r n a t i v a s ]5 End I f

Quando a condição é verdadeira serão executadas as instruções delimitadas por Thene 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 emqualquer expressão de que resulte um valor numérico: um valor não nulo será interpretadocomo Verdadeiro, enquanto um valor nulo será considerado como Falso.

A condição é, portanto, uma expressão booleana (lógica). Uma expressão booleanarepresenta 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 deoperadores.

5.1.2 If...Then

Figura 20: Estrutura de controlo condicional If...Then

Quando numa estrutura condicional não existe qualquer acção a executar quando a

40

Page 41: Programming in VBA v2a

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 condicao Then2 [ i n s t r u c o e s ]3 End I f

Nesta 2a variante, quando a acção a realizar no caso a condição ser verdadeira puderser executada com apenas uma instrução, é possível ainda utilizar a seguinte sintaxesimplificada, 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<> DesigualdadeAnd EOr OuNot 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

• Se Expr1 e Expr2 forem ambas verdadeiras, a expressão será verdadeira

• Basta que quer Expr1 quer Expr2 seja falsa, para a expressão ser falsa

OR

Sintaxe: Expr1 Or Expr2

• Se Expr1 e Expr2 forem ambas falsas, a expressão será falsa.

• Basta que quer Expr1 quer Expr2 seja verdadeira, para a expressão ser ver-dadeira

41

Page 42: Programming in VBA v2a

5.1.3 Estruturas condicionais embutidas

É possível construir estruturas de controlo mais complexas, oferecendo ao programa acapacidade 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 primeirométodo implica utilizar a palavra reservada ElseIf.

A sintaxe desta estrutura é:

1 I f condicao1 Then2 Accao13 ElseIf condicao2 Then4 Accao25 ElseIf condicao3 Then6 . . .7 Else8 AccaoN9 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 estruturacondicional.

As estruturas condicionais produzidas usando o método alternativo não são tão com-pactas mas tornam-se talvez mais legíveis, sobretudo se se usar a indentação apropriada:

1 I f condicao1 Then2 Accao13 Else4 I f condicao2 Then5 Accao26 Else7 I f condicao 38 Accao 39 Else

10 Accao411 End I f12 End I f13 EndIf

Na Figura 21 na página seguinte pode-se ver o fluxograma de uma estrutura imbricadacom 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 restofalha.

É 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

Page 43: Programming in VBA v2a

Figura 21: Estruturas de controlo condicional imbricadas

só uma das acções será efectuada. Pode dizer-se que, genericamente, para um programapoder escolher uma de entre N alternativas, será necessário utilizar N - 1 estruturascondicionais encadeadas.

O exemplo da Listagem 3 traduz uma situação em que o programa, confrontado coma necessidade de classificar uma nota numérica, pode escolher uma de entre seis notasqualitativas diferentes. Só várias estruturas condicionais encadeadas permitirão resolveresse problema.

Listing 3: Exemplo de aplicação de If..Then..Else imbricados

1 I f ( nota < 0) Or ( nota > 20) Then2 r e su l t ado = "Nota␣ Inva l i da ! "3 ElseIf nota < 6 Then4 r e su l t ado = "Mau"5 ElseIf nota < 10 Then6 r e su l t ado = "Mediocre "7 ElseIf nota < 14 Then8 r e su l t ado = " Su f i c i e n t e "9 ElseIf nota < 17 Then

10 r e su l t ado = "Bom"11 Else12 r e su l t ado = "Muito␣Bom"13 End I f

43

Page 44: Programming in VBA v2a

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ânciasdo momento. As estruturas de controlo repetitivo (também conhecidas por estruturasde repetição ou ciclos) permitem repetir um dado conjunto de instruções o número devezes 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-sedizer que uma estrutura de controlo repetitiva assegura a execução repetida de um dadoconjunto de instruções dependendo do resultado do teste de uma determinada condiçãode funcionamento. De facto, como veremos, também os ciclos dependem da verificaçãode uma condição, normalmente de forma explícita, noutros casos definida implicitamente.

5.2.1 Estruturas de Controlo Do...Loop

Estão disponíveis quatro variantes deste ciclo: Do...While e Do...Until, com teste dacondição no princípio ou no fim. Vejamos em detalhe as diversas variantes. O fluxogramada primeira encontra-se na Figura 22:

Figura 22: Estrutura de controlo repetitivo Do...While

Analizando esse fluxograma, pode observar-se que tudo roda à volta do teste a umacondição, descrita como condição de funcionamento. Se a condição for verdadeirana altura em que o teste é realizado, as instruções que compõem o chamado corpo dociclo serão executadas, após o que novo teste à condição será efectuado. Enquanto acondição se verificar ser verdadeira, o programa não sairá deste ciclo. Na 1a vez em quea condição se mostrar falsa, o ciclo terminará e o programa poderá continuar com asinstruções seguintes.

Chama-se corpo do ciclo ao conjunto de instruções que serão executadas em cadaiteração (repetição) do ciclo. Esse conjunto pode incluir qualquer número de instruçõese de qualquer tipo, mesmo outras estruturas de repetição. Neste último caso, estaremos

44

Page 45: Programming in VBA v2a

perante o que se designa por ciclos imbricados ou embutidos, que serão tratados emdetalhe na Secção 5.2.6 na página 52.

A sintaxe em VBA desta estrutura de controle é a seguinte:

1 Do While condicao2 [ i n s t r u c o e s ]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).

Figura 23: Estrutura de controlo repetitivo Do...Until

A sintaxe da variante Do...Until será então:

1 Do2 [ i n s t r u c o e s ]3 Loop Unt i l condicao

Como nesta variante o teste da condição é feito no fim, as instruções constantes docorpo do ciclo serão garantidamente executadas pelo menos uma vez. Tal pode ou nãoverificar-se conveniente.

É possível transformar uma estrutura Do...While numa Do...Until desde que se subs-titua a palavra While pela Until e se negue a condição de controlo. Escolher uma ououtra estrutura de controlo depende, no fundo, do jeito do programador e, sobretudoquando se usam condições múltiplas, da forma como a expressão lógica traduz com maiorou menor facilidade a condição expressa em linguagem corrente.

5.2.2 Ciclos controlados por contador

Usando como base estas duas estruturas de controlo repetitivo é possível construir doistipos de ciclos: ciclos controlados por um contador e ciclos controlados por aquilo quese designa como sentinela. Comecemos pelos primeiros.

45

Page 46: Programming in VBA v2a

Um ciclo controlado por contador baseado na estrutura Do..While pode assumir aseguinte forma genérica:

1 contador = va l o r_ i n i c i a l2 Do While contador <= va l o r_ f i na l3 ’ Corpo do Cic lo4 contador = contador + 15 Loop

Figura 24: Ciclos controlados por contador

Decorrendo do que vimos na secção anterior, torna-se claro que é igualmente possívelconstruir este ciclo usando a estrutura Do..Until.

Há que ter em conta as seguintes questões na construção de um ciclo controlado porcontador usando as estruturas de controlo Do...While ou Do...Until :

• Inicializar a variável contadora

• Especificar a condição de funcionamento do ciclo

• Incluir no corpo do ciclo uma instrução que incremente ou decremente a variávelcontadora.

46

Page 47: Programming in VBA v2a

Quando se usam estas estruturas, ao contrário do que se passa com a estrutura derepetição For...To...Next, a analizar na Secção 5.2.5 na página 50, é da responsabilidadedo programador assegurar-se de que tais acções são correctamente executadas conformeestá 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 controladopor contador quando se pode conhecer à partida o número de vezes que ele vai funcionarou, 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.

5.2.3 Exemplo integrador

Vamos agora considerar o seguinte exemplo que permite integrar a utilização de algumaspropriedades importantes do controlo "listBox" com a aplicação de um ciclo controladopor contador para obter a soma dos valores numéricos contidos na "listBox". Aproveita-se ainda para ilustrar a forma de tratar certos eventos ocorridos em objectos presentesna interface. A ocorrência desses eventos bem como a resposta que lhes é dada é descritana Figura 25.

Figura 25: Exemplo integrador - Interface

O que se pretende do programa é que demonstre o seguinte comportamento:

• Quando se "clica" directamente na própria listBox a resposta do objecto deveráconsistir na apresentação na label "Label1" do conteúdo da linha seleccionada. Se,em vez de um click, ocorrer um duplo click, já a resposta respectiva deverá consistirna apresentação na mesma label do número da linha actualmente seleccionada.Estaremos, assim, perante uma resposta diferenciada do mesmo objecto a doiseventos de tipo diferente.

47

Page 48: Programming in VBA v2a

• Quando se "clica" no botão de comando "cmdTotal", a resposta desse objectodeverá ser o cálculo do somatório do conteúdo de cada linha da listBox e a suaapresentação na label "Label2".

Figura 26: Exemplo integrador - Código

O código das sub-rotinas tratadoras de eventos associadas à caixa de listagem e aobotão de comando encontra-se na Figura 26. Analizando esse código, são pertinentes asseguintes observações:

• Na sub-rotina lstValores_Click() é codificada a resposta do objecto lstValores aoevento Click. Nela, apenas se atribui ao label "Label1" um texto resultante da con-catenação (colagem) da string "Conteúdo: " com o conteúdo da linha seleccionadana ListBox, fornecido pela propriedade Text desse objecto.

• Na sub-rotina lstValores_DblClick() é codificada a resposta do objecto "lstValo-res"ao evento Duplo Click. É realizada uma operação análoga à anterior, usando,desta vez, a propriedade ListIndex da ListBox.

• A sub-rotina cmdTotal_Click() instrui o botão de comando "cmdTotal" sobre o quefazer caso nele ocorra um evento Click. O código utilizado usa uma estrutura decontrolo repetitivo, neste caso um ciclo Do..While que, para cada linha da ListBox,actualiza a variável soma com o conteúdo da linha especificada pelo valor contidona variável c.

• Esta variável é usada para construir um contador que monitorize o número delinhas cujo conteúdo se está a somar. O seu valor inicial é 0 e, para cada iteração(repetição) do ciclo, será incrementada de uma unidade. O ciclo terminará quando

48

Page 49: Programming in VBA v2a

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.

5.2.4 Ciclos controlados por sentinela

Quando não é possível conhecer antecipadamente o número de vezes que o ciclo deveráser executado é necessário usar uma técnica diferente: ciclos controlados por sentinela.Por sentinela deve entender-se um valor limite que assinala o fim de uma dada sequênciade valores, mas que não esteja incluído nessa sequência.

Exemplo

Se o utilizador estiver a introduzir os dados referentes a um conjunto de alunosidentificados pelos seus números de matrícula, a introdução de um número commenos 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 deveterminar. Seria esse, neste caso, o valor sentinela escolhido.

A selecção do valor sentinela é da responsabilidade do programador, devendo serescolhido fora do intervalo possível de valores a introduzir, podendo ainda, ter-se ematenção a eventual ocorrência de valores fora desse intervalo que possam resultar dealgum eventual erro de digitação. O valor sentinela escolhido não deve pois ser passívelde facilmente ocorrer por mero acidente.

Conforme pode ser observado na Figura 27 na próxima página um ciclo controladopor sentinela deverá ser precedido da leitura de um elemento da sequência de valores aintroduzir. As leituras dos restantes valores dessa sequência serão efectuadas dentro docorpo do ciclo, um em cada iteração. Essa leitura deverá, no entanto, ser feita no fim docorpo do ciclo, após o processamento do valor anteriormente lido. Neste tipo de ciclos, aleitura e o processamento de cada valor lido andam, assim, desfasados de uma iteraçãodo ciclo. No caso de se usar a estrutura Do..While, o ciclo funcionará enquanto o valorlido for diferente do valor sentinela escolhido.

O exemplo apresentado acima, poderia ser codificado pelo segmento de programaseguinte:

1 num = InputBox( " D ig i t e ␣o␣numero" , "ISEP␣−␣Matr i cu las " )2 Do While numero <> 13 I f numero <> 1 Then l s tbox1 .AddItem num4 num = InputBox( " D ig i t e ␣o␣numero" , "ISEP␣−␣Matr i cu las " )5 Loop

Geralmente o valor sentinela é um valor preciso. Existem casos, porém, em que asentinela pode ser qualquer valor dentro de uma determinada gama, por exemplo, todosos números negativos. Um exemplo de um ciclo controlado por uma sentinela com estascaracterísticas é apresentado na Secção 5.2.6 na página 52.

17Note que a variável contadora foi inicializada com o valor 0.

49

Page 50: Programming in VBA v2a

Figura 27: Ciclos controlados por sentinela

5.2.5 Estrutura de Controlo For..To..Next

Esta estrutura permite repetir um dado conjunto de instruções um número pré-determinadode vezes. Como vimos na secção anterior, nem sempre é possível saber de antemão quan-tas vezes as instruções contidas no corpo do ciclo devem ser repetidas. Nesse caso, deverãoser utilizadas as estruturas de controlo repetitivo estudadas na Secção 5.2.1 na página 44.

Esta estrutura permite construir ciclos controlados por contador de forma compactae eficiente. A sua sintaxe é:

1 For contador = va l o r_ i n i c i a l To va l o r_ f i na l2 [ i n s t r u c o e s ]3 Next

Esta estrutura baseia-se na existência dum contador que incrementa automaticamenteo conteúdo da variável contador, chamada variável de controlo do ciclo, cada vezque o ciclo funciona, isto é, cada vez que as instruções contidas no corpo do ciclo sãoexecutadas. No início, contador vai conter o valor inicial e após valorfinal - valorinicial iterações atingirá o valor final. Será essa a última iteração do ciclo.

A inicialização da variável contadora, o seu incremento/decremento e a verificação dacondição de funcionamento do ciclo (contador <= fim) é da responsabilidade da própria

50

Page 51: Programming in VBA v2a

estrutura de controlo. O programador precisa, apenas, de especificar qual o valor de inícioe de fim (ou, de forma indirecta, o número de vezes que o ciclo vai funcionar) e quais asinstruçõ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 contidasno 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 acondiçã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 contador = va l o r_ i n i c i a l To va l o r_ f i na l Step passo2 [ i n s t r u c o e s ]3 Next

A diferença está na utilização da palavra Step após a especificação do valor final. Asua inclusão é opcional: caso se pretenda que o conteúdo da variável de controlo sejaincrementada uma unidade de cada vez, é desnecessário especificar o passo. Em casocontrário, Step passo permitirá incrementar o valor de variável de um valor diferente daunidade (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 sercontador >= fim.

Repare-se que nesta estrutura de controlo, ao contrário das estudadas anteriormente,o incremento ou decremento da variável de controle do ciclo é automático. Outro aspectointeressante é que a condição de funcionamento do ciclo é implícita. Ela existe e éverificada mas não é especificada de forma explícita pelo programador, apenas de formaindirecta 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 lOb j e c t As Range3 For Each c e l lOb j e c t In S e l e c t i o n4 c e l lOb j e c t . BorderAround ColorIndex :=3 ,Weight:=xlThick5 Next6 End Sub

Existe ainda em VBA uma estrutura de controlo que é uma variante da For..To..Nexte 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 Worksheet18.

A sintaxe desta estrutura é a seguinte:

1 For Each elemento In Coleccao

18Por sua vez, um workbook é também um objecto. Um objecto pode assim ser ele próprio umacolecção de objectos.

51

Page 52: Programming in VBA v2a

2 [ i n s t r u c o e s ]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, utilizandoesta estrutura de controlo. Nela é utilizada a variável cellObject para guardar um objectodo 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 contidasna gama representada por cellObject. Com os argumentos fornecidos no exemplo, estemétodo formata o bordo dessas células a vermelho e usando uma linha grossa.

5.2.6 Estruturas de controlo repetitivo imbricadas

Foi dito anteriormente que o corpo de um ciclo era constituído pelo conjunto de instruçõesque o ciclo irá executar repetidamente. Foi também dito que nesse conjunto de instruçõesse poderia incluir qualquer tipo de instruções, mesmo constituindo outras estruturas decontrolo repetitivo. Destes ciclos se diz que se encontram imbricados ou embutidosum dentro do outro. Diz-se também que esses ciclos estão encadeados.

Figura 28: Exemplo de Ciclos Imbricados

Considere-se o problema de calcular uma série de factoriais de números inteiros. O

52

Page 53: Programming in VBA v2a

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álculoum certo número de vezes, teremos também que usar um ciclo. Teremos assim umciclo, chamemos-lhe exterior, que se encarrega de produzir uma sequência de factoriaise cujo corpo inclui por sua vez um ciclo, dito interior, que é responsável pelo cálculo decada factorial. O diagrama de fluxo da Figura 28 na página precedente representa estarealidade. O código necessário para traduzir esse diagrama é o contido na Listagem 5.

Listing 5: Exemplo usando Ciclos Imbricados

1 num = InputBox( " Introduza ␣um␣ i n t e i r o ␣ p o s i t i v o " )2 Do Unt i l num < 03 f a c t o r i a l = 14 contador = 15 Do Unt i l contador > num6 f a c t o r i a l = f a c t o r i a l ∗ contador7 contador = contador +18 Loop9 num = InputBox( " Introduza ␣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ãopositivo. É um exemplo de sentinela constituído não por um valor específico mas poruma 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.

Listing 6: Exemplo de Sub-rotina usando Ciclos Imbricados

1 Sub Fi l lRange ( )2 Num = 13 For Row = 1 To 104 For Col = 1 To 105 Ce l l s (Row, Col ) . Value = Num6 Num = Num + 17 Next Col8 Next Row9 End Sub

O exemplo da Listagem 6 ilustra a utilização de dois ciclos imbricados para preencheruma tabela em Excel com valores que vão de 1 até 100 (o número de elementos databela). O ciclo interior preenche as células de uma linha da tabela. O ciclo exteriorrepete isso para cada um das linhas da tabela. O preenchimento das células é efectuadopela instrução 5, que usa o método Cells(Row, Col) para aceder acada célula da gama aque se aplica..

53

Page 54: Programming in VBA v2a

6 Variáveis indexadas - vectores e matrizesAté 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çãode um novo valor a essa variável implica o desaparecimento do valor anteriormente nelacontido.

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 domesmo tipo. Estamos, portanto, a utilizar agora variáveis que se podem classificar comovariáveis múltiplas. Na Figura 29 podemos observar representações de uma variávelsimples do tipo integer e de uma variável múltipla (um vector uni-dimensional) contendovalores inteiros. Cada elemento do vector é identificado por um valor numérico específico.

Figura 29: Um vector é uma variável múltipla

Um vector é uma lista ordenada de variáveis simples do mesmo tipo. Pode tambémser visto como um conjunto de variáveis simples agrupadas. Todos os elementos dessevector partilham o mesmo nome (o nome do vector) e são identificados individualmentemediante o valor dum índice, que determina qual a sua posição dentro do vector. É porisso 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 valordo í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

Page 55: Programming in VBA v2a

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 vectorcomo armazenado os nomes dos membros de uma equipa de futebol, os sucessivos valoresdo índice podem ser vistos como os correspondentes números das suas camisolas. Note-seque estamos, neste caso, a forçar os valores do índice a iniciar em 1.

6.1 Declaração estática de vectores

Como qualquer outra variável, uma variável do tipo Array deve também ser declarada(criada) antes de poder ser usada. Para tal, deve ser usada a instrução Dim, que reservaespaço em memória suficiente para armazenar o número previsto de elementos do vector20. Uma das formas de utilizar a instrução Dim para declarar vectores é a seguinte:

Dim nome_vector(num_elementos) As Tipo

Exemplos:

Dim var_Multipla(8) As IntegerDim notas(30) As SingleDim nomes(100) As String

Note- se que num_elementos não se refere ao valor máximo que a variável índicepode assumir (7, no caso do vector var_Multipla) mas sim ao número de elementos dovector (8, neste caso). Por este processo, a declaração do limite inferior faz-se de formaimplícita: por defeito assume-se como limite inferior do índice o valor zero (ou 1 se talfor especificado mediante a instrução Option Base 1 ).

Uma forma alternativa de utilizar a instrução Dim para declarar vectores implica autilizaçã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:20Adicionalmente, 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

Page 56: Programming in VBA v2a

Dim numeros(100 To 200) As DoubleDim valores(-100 to 100) As Single

6.2 Declaração dinâmica de vectores

As formas de criar variáveis do tipo Array descritas anteriormente partem do princípioque as necessidades de armazenamento de informação são conhecidas previamente, i.e,que o programador pode avaliar antecipadamente qual deverá ser a dimensão do vectora armazenar. Isso nem sempre acontece. Sendo este o caso, e não se querendo errar nempor defeito nem por excesso, tentando adivinhar o que seria uma dimensão adequada, épossível utilizar uma técnica alternativa, a declaração dinâmica de Arrays. Este tipo dedeclaração é efectuada não inserindo a dimensão entre parêntesis na instrução Dim:

Exemplo:

Dim vector() As Single

Esta declaração será inserida na zona habitual no início do programa. Quando chegaro momento em que seja possível avaliar de forma mais exacta a dimensão necessária parao vector, usar-se-á a instrução ReDim para atribuir essa dimensão ao Array.

Exemplo:

ReDim vector(100)

A instrução ReDim pode igualmente ser usada para re-dimensionar um vector caso severifique que a dimensão inicialmente atribuída não foi adequada. Nessa situação, casose pretenda manter os valores já existentes no vector, dever-se-á usar a opção Preserve.

Exemplo:

ReDim Preserve vector(200)

6.3 Processamento de vectores

Sendo um vector uma variável múltipla composta de elementos do mesmo tipo agrupadosna mesma estrutura, a forma mais adequada de executar uma mesma acção sobre umaparte ou a totalidade dos seus elementos é utilizar uma estrutura de controlo repetitivoou ciclo.

Para perceber de forma mais clara o porquê da afirmação contida no parágrafo an-terior, observe-se o problema descrito na Figura 31 na página seguinte e atente-se nasdiferentes soluções propostas.

Quando confrontado com o problema de armazenar e actualizar a informação relativaao preço de 100 produtos, um programador poderia ser tentado a criar 100 variáveisindividuais para guardar cada um desses preços. Isso, no entanto, obrigá-lo-ia a incluirno seu programa 100 instruções Dim para criar outras tantas variáveis individuais. Poroutro lado, quando necessitasse de actualizar os preços em, por exemplo, 5%, teria queinserir 100 instruções do tipo preçoN = preçoN * 1,05.

56

Page 57: Programming in VBA v2a

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:em vez de 100 variáveis individuais teremos apenas um vector de 100 elementos, cada umdeles capaz de armazenar o preço de um produto. Consequentemente, teremos apenasuma instrução Dim, no caso, algo como Dim preços As single. E quando for necessárioactualizar os preços, como o vector é uma variável múltipla indexada, haverá apenas queconstruir um ciclo que percorra automáticamente o vector, actualizando cada um dosseus elementos.

Listing 7: Exemplo de processamento de um vector

1 Private Sub cmdGo_Click ( )2 Dim vectorSqr (100) As Double3 Dim i As Integer4 Dim r e s As S ing l e5 l s tTabe l a .Clear6 For i = 0 To txtMaior7 r e s = Sqr ( i )8 vectorSqr ( i ) = r e s9 l s tTabe l a .AddItem Format( res , " 0 .000 " )

10 Next i11 End Sub

O programa descrito na Listagem 7 permite calcular e apresentar sob a forma de umatabela as raízes quadradas de todos os números inteiros compreendidos entre 0 e um

57

Page 58: Programming in VBA v2a

limite superior a especificar pelo utilizador na TextBox txtMaior (a largura do intervalonão deve exceder 100, visto ser esta a dimensão do vector). Os valores calculados sãoarmazenados num vector para eventual futura utilização.

Listing 8: Outro exemplo de processamento de um vector

1 Private Sub cmdGo_Click ( )2 Dim vec to r (100) As Double3 Dim i As Integer4 Dim i n d i c e As Integer5 Dim r e s As S ing l e6 Dim l i nha As String7 l s tTabe l a .Clear8 i n d i c e = 09 For i = txtMenor To txtMaior

10 r e s = Sqr ( i )11 vec to r ( i nd i c e ) = r e s12 l i nha = Format(Str ( i ) , "##0" ) + "␣−␣" + _13 Format( vec to r ( i nd i c e ) , " 000 .000 " )14 l s tTabe l a .AddItem l i nha15 i n d i c e = ind i c e + 116 Next i17 End Sub

Na variante desta sub-rotina, contida no exemplo descrito na Listagem 8, é possívelespecificar também o limite inferior do intervalo, para além de se demonstrarem algumastécnicas de formatação da saída de dados.

De notar que na primeira versão do programa se usou a mesma variável i para controlaro ciclo For e para armazenar os valores dos índices do vector. Tal aconteceu porque foipossível estabelecer naquele caso uma correspondência directa entre os valores da variávelde controlo do ciclo i e os valores do índice que controla as posições dos elementos dovector.

Já na segunda variante do programa tal não era possível, visto que a variável de con-trolo do ciclo iria conter valores (desde o limite inferior ao limite superior do intervalo) quenão deveriam corresponder às posições do vector em que o armazenamento dos resultadosse iria efectuar.

Em qualquer das variantes apresentadas, o processamento dos elementos do vectorconsistiu em operações de escrita (de atribuição) que modificaram o seu valor. É igual-mente possível efectuar operações de leitura sobre todos ou parte dos elementos dumvector. Neste caso, como é óbvio, a variável do tipo Array deverá encontrar-se do ladodireito de uma operação de atribuição:

var = vector(indice)

A instrução acima copia o conteúdo de vector na posição índice para a variável var.

58

Page 59: Programming in VBA v2a

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 paraidentificar 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 (vectorbidimensional) serão precisos dois ciclos encadeados.

Figura 32: Ciclos encadeados para processar um vector bidimensional

Na Figura 32 pode ser visto um fragmento de código em VBA que permite calculara soma de duas matrizes (m1 e m2), colocando o resultado noutra matriz (ms). Nodiagrama pode ser observada a existência de um ciclo interior que processa uma linhada matriz (correspondendo, no fundo, a um vector uni-dimensional), coluna a coluna, eque se encontra integrado no corpo de um ciclo exterior que repete esse processamentopara todas as linhas da matriz.

Analizando mais em detalhe o código apresentado na Figura 32, pode verificar-se aexistência de dois índices, concretizados nas variáveis i e j (a 1a para controlar as linhas e a2a para as colunas). Estas variáveis foram também utilizadas como variáveis de controle

59

Page 60: Programming in VBA v2a

dos ciclos For. Dessa maneira, vão ser percorridos automaticamente os intervalos devalores dos índices de 1 até nl (variável contendo o no de linhas) e de 1 até nc (variávelcontendo o no de colunas).

Listing 9: Soma de matrizes

1 Option Base 12 Const Linhas = 103 Const Colunas = 104

5 Private Sub cmdCalc_Click ( )6 Dim m1( Linhas , Colunas ) As Integer ,7 Dim m2( Linhas , Colunas ) As Integer8 Dim ms( Linhas , Colunas ) As Integer , l i nha As String9 Dim nl As Integer , nc As Integer , i As Integer , j As Integer

10

11 nl = Val ( txtNL . Text )12 nc = Val ( txtNC . Text )13 I f nc < 1 Or nc > Colunas Or n l < 1 Or nl > Linhas Then14 MsgBox "Dimensoes␣ e r radas ! "15 Else16 For i = 1 To nl ’ l e i t u r a da matr iz 117 l i nha = ""18 For j = 1 To nc19 m1( i , j ) = Val (InputBox( "M1[ " & i & " , " & j & "]=" ) )20 l i nha = l i nha & "␣␣␣␣" & m1( i , j )21 Next22 lstM1 .AddItem l i nha23 Next24 For i = 1 To nl ’ l e i t u r a da matr iz 225 l i nha = ""26 For j = 1 To nc27 m2( i , j ) = Val (InputBox( "M2[ " & i & " , " & j & "]=" ) )28 l i nha = l i nha & "␣␣␣␣" & m2( i , j )29 Next30 lstM2 .AddItem l i nha31 Next32 For i = 1 To nl ’ c a l c u l o da soma de m1 com m233 l i nha = ""34 For j = 1 To nc35 ms( i , j ) = m2( i , j ) + m1( i , j )36 l i nha = l i nha & "␣␣␣␣" & ms( i , j )37 Next38 lstMS .AddItem l i nha39 Next40 End I f41 End Sub

60

Page 61: Programming in VBA v2a

Na Listagem 9 na página precedente pode ser encontrado o código completo de umprograma 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údodas três matrizes noutras tantas caixas de listagem.

No código pode ser observada a utilização de constantes para facilitar a escrita eeventual alteração do programa. Foram inicialmente definidas as duas constantes Linhase Colunas que vão ser em seguida utilizadas por várias vezes ao longo do programa. Sehouver necessidade de alterar as dimensões das matrizes, bastará modificar a definiçãoinicial das constantes.

As instruções contidas nas linhas 20, 28 e 36 são usadas para acrescentar à string aadicionar às ListBox o conteúdo (devidamente formatado) do elemento da matriz que seencontra a ser processado no momento.

61

Page 62: Programming in VBA v2a

7 Funções e ProcedimentosNesta secção vamos falar da organização interna de um programa. Em vez de incluir todasas instruções numa única entidade, é possível e aconselhável organizar um programa emvá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 emsubproblemas e estes por sua vez em problemas de ainda menor dimensão até atingirum nível de complexidade suficientemente baixo para ser resolvido sem dificuldade. Umavez resolvidos os subproblemas de nível mais baixo, começa um processo inverso, deintegração de módulos individuais num todo coerente.

A construção de um programa baseia-se num processo idêntico. Deve ser seguido ométodo de subdividir o problema nas suas partes constituintes e encontrar solução paracada uma delas, integrando no fim as partes no todo. Cada uma dessas partes podeconstituir um módulo independente que será utilizado pelo programa principal, usandoum mecanismo que se pode descrever como de "subcontratação".

Usando este mecanismo, o programa principal vai utilizar os serviços dos módulosespecializados 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ãocircunscritas a esse módulo, evitando efeitos secundários indesejáveis.

7.1 Funções

Os programas descritos nos exemplos que têm sido apresentados destinam-se a executartarefas. Por exemplo, as rotinas descritas na Secção 2.6 na página 13 têm como objectivoa monitorização dos valores contidos em determinadas células da folha de cálculo. Estetipo de rotinas é designado por procedimentos ou sub-rotinas (em linguagem VBA).Destinam-se a realizar tarefas e não têm necessariamente que devolver qualquer resultado.

No entanto, não é possível utilizar estes procedimentos em fórmulas duma folha decálculo, ao contrário do que acontece com as funções standard disponíveis no Excel, comoseja a função If referida atrás, ou a função Sum, que calcula a soma do conteúdo numéricodas várias células contidas numa dada gama. Isso acontece porque, para poderem serutilizadas em fórmulas, elas terão que ser estruturadas como funções, e comportarem-sede maneira idêntica à das funções standard.

Uma função, seja ela pré-existente no Excel, ou criada pelo utilizador, deve poderreceber a informação de que necessita, e de conseguir devolver o resultado do seu trabalho,de modo a esse resultado poder ser utilizado na fórmula ou expressão que a utilize. Umafunção devolve obrigatóriamente um, e só um, resultado. Deverá possuir uma estruturadefinida pela sintaxe seguinte:

1 Function Nome ( argumento1 , argumento2 , . . . )2 ’ L i s t a de i n s t r u co e s3 Nome = re su l t ado4 End Function

Repare-se que para além das diferenças óbvias no cabeçalho e no delimitador final emrelação às sub-rotinas estudadas anteriormemte, verifica-se o seguinte:

62

Page 63: Programming in VBA v2a

Figura 33: Funções como caixas pretas

1. A seguir ao nome da função e entre parênteses encontra-se uma lista de argumen-tos, através dos quais a função vai receber as informações essenciais à realização do seutrabalho.

2. O resultado dos cálculos efectuados será entregue à fórmula ou expressão queinvocou a função, depositando-o no seu próprio nome, como se este fosse uma variável.

Atentemos na seguinte fórmula Excel:

= 10 * sin(angulo)

Para calcular a fórmula, ir-se-á multiplicar por 10 o resultado fornecido pela funçãostandard sin. Esta, por sua vez, para poder fornecer o resultado deverá ter recebido ainformaçã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 queocupava na fórmula.

Para o utilizador da função, não interessa conhecer o seu funcionamento interno, masapenas 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, elase comporta como uma caixa preta, à qual é fornecida informação e que, com base nela,produz um resultado (Figura 33).

7.2 Exemplos de funções criadas pelo programador

Vamos agora criar uma função que permita calcular a margem de lucro percentual de umdeterminado produto sabendo o seu custo e o seu preço de venda. Supõe-se que essesdados se encontrarão previamente armazenados em duas células da folha de cálculo. Umasolução possível será a seguinte:

Listing 10: Função mLucro

1 Public Function mlucro (v As s i ng l e , c As s i n g l e ) As s i n g l e2 mLucro = (v − c ) / v3 End Function

63

Page 64: Programming in VBA v2a

Observe-se que função mlucro possui dois parâmetros de entrada, v e c, através dosquais receberá os dados das vendas e dos custos respectivamente. Estes dois parâmetrosestão preparados para receber dados do tipo single. Note-se ainda que o resultado daexpressão que calcula a margem de lucro é atribuído directamente ao próprio nome dafunção. É esse o processo pelo qual uma função consegue fornecer o resultado do seutrabalho à entidade que a invocou. O tipo de resultado fornecido pela função é especificadona parte direita do cabeçalho, também do tipo single, neste caso21.

Figura 34: Utilização da função margemLucro numa fórmula

Esta função poderá ser utilizada em qualquer fórmula contida numa célula da folha decálculo, da mesma maneira que qualquer das funções pré-existentes o seria. Um exemplode 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 naFigura 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údodestas duas células são passadas à função. Esta recebe-os através dos parâmetros deentrada respectivos, v e c. O resultado do seu cálculo será deixado na fórmula, quando afunção termina o seu trabalho.

Listing 11: Função factorial

1 Function f a c t o r i a l (ByVal n as Integer ) as Double2 Dim i as Integer , f as Double3 f = 14 For i = 2 To n5 f = f ∗ i6 Next i7 f a c t o r i a l = f8 End Function

Vamos agora apresentar outro exemplo de função criada pelo programador e de comoesta pode ser utilizada num programa. Trata-se de uma função que calcula o factorial deum número inteiro. Já que o factorial de um número é obtido à custa da multiplicação

21Quer no que respeita ao tipo de resultado devolvido, quer ao tipo de dados recebido pela funçãoatravés dos parâmetros de entrada, é possível omitir a sua especificação no cabeçalho da função. Issoterá como consequência que o VBA parta do princípio que se trata de dados do tipo Variant. Osinconvenientes de usar este tipo de dados já foram referidos na Secção 3.4 na página 20.

64

Page 65: Programming in VBA v2a

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 11na página precedente usa um ciclo For para repetir a instrução f = f * i, responsávelpela actualização da variável f. No final do ciclo, essa variável conterá o resultado dassucessivas multiplicações, ou seja, o próprio factorial. Atente-se a que essa variável deveser 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 permitirque 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 aresposta do botão de comando cmdCombina ao evento click.

Listing 12: Programa de cálculo de Combinações

1 Private Sub cmdCombina_Click ( )2 Dim n As Integer , p As Integer3 n = Abs ( [D4 ] )4 p = Abs ( [D5 ] )5 I f n > 0 And p > 0 And n >= p Then6 [D7 ] = f a c t o r i a l (n) / f a c t o r i a l (n − p) / f a c t o r i a l (p)7 Else8 MsgBox "Erro : ␣dados␣ i n v a l i d o s ! " , vbOKOnly9 End I f

10 End Sub

O programa lê os valores da população e da amostra contidos nas células D4 e D5,respectivamente, após o que, caso os valores de n e p sejam válidos, calcula as combinaçõesde n, p a p, através da instrução na linha 6. Esta instrução guarda na célula D7 oresultado da expressão de cálculo de combinações23. Para perceber melhor como essaexpressão é avaliada, na Figura 35 é descrito o processo passo a passo.

Figura 35: Análise passo a passo da expressão de cálculo das combinações

22Programa adaptado de um exemplo dos textos de apoio do prof. Ângelo Martins.23A fórmula de cálculo de combinações é

(np

)= n!

(n−p)!p! .

65

Page 66: Programming in VBA v2a

Em 1o lugar, são copiados os valores das variáveis do programa principal para osparâmetros de entrada da função24. Assim n e p são substituídos pelos valores presentesnesse 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. Emseguida, a função é sucessivamente invocada com os valores previamente obtidos. Comesses valores, a função faz o cálculo do factorial e terminando o seu trabalho, deixa no seulugar o rsultado do cálculo (Passo 4). Só falta agora calcular o resultado da expressão earmazenar o seu resultado na célula D7.

7.3 Passagem de parâmetros ByVal

Nesta secção vamos analisar em maior detalhe o processo de passagem de parâmetrosentre as funções e procedimentos e os programas que os invocam.

Para poder trabalhar, uma função precisa de dados, que lhe são passados atravésde parâmetros. Esses dados são processados, e, no caso das funções, um resultado éproduzido e devolvido ao programa que a chamou, através do seu próprio nome.

Uma função é invocada numa expressão, usualmente do lado direito de uma operaçãode atribuição. A instrução que a invoca tem que, ao mesmo tempo, entregar-lhe os dadosde que a função necessita para o seu trabalho (no caso da função factorial, o número cujofactorial se pretende conhecer). Esses dados são passados como argumentos da função.No exemplo seguinte, a função factorial é invocada passando-lhe como argumento oconteúdo da variável num:

fac = factorial(num)

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á possuirum parâmetro de entrada por onde essa informação possa entrar. No caso da funçãofactorial, n é esse parâmetro de entrada e está preparado para receber dados do tipointeger.

Figura 36: Comunicação da função com o programa que a invoca

24Para ver em detalhe esse proceeso, consultar a Secção 7.3

66

Page 67: Programming in VBA v2a

Na Figura 36 na página precedente está assinalado o parâmetro n com o sendo a viade 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 ByValimediatamente antes do nome do argumento. Esta palavra indica que a função esperaque um argumento lhe seja passado "por valor", ou seja, que aquilo que venha a receberatravé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 aindicação de onde esse valor poderá ser encontrado ou, por outras palavras, o endereçoda variável em que o valor a utilizar se encontrará. O uso de ByRef tem ainda outrasconsequê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 asinvocam 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 doque um resultado. Nesses casos, uma função não pode ser utilizada. Teremos que usarum procedimento (ou sub-rotina) 25 e usar a técnica de passagem de parâmetros porreferência (ByRef ).

Se bem que já tenhamos por várias vezes lidado com procedimentos, está na alturade formalizar o processo da sua criação. A sintaxe utilizada é a seguinte:

Sub <nome>(Lista_de_argumentos )i n s t r u c o e s

End Sub

Antes da palavra reservada Sub é possível acrescentar Private ou Public, conforme oo âmbito do procedimento esteja ou não circunscrito ao módulo em que o procedimentoesteja inserido 26. A Lista de argumentos é composta por elementos do tipo "Nome AsTipo" separados por vírgulas.

Note-se que um procedimento não tem que devolver resultados. Pode limitar-se aexecutar uma ou mais tarefas que não implicam o cálculo e devolução de resultados.Nesse caso, podem ser vistos apenas como um sub-programa especializado na execuçãode uma tarefa específica.

Enquanto que uma função apenas pode ser invocada no interior de uma expressãoe, portanto, aparece vulgarmente do lado direito de uma operação de atribuição, já umprocedimento é invocado como uma instrução. A forma geral será algo como:

nome_do_procedimento argumento1, argumento 2,...argumentoN

Na Listagem 13 na página seguinte (linha 11) pode ser observado um exemplo deinvocação de um procedimento.

25Como foi referido na Secção 7.1 na página 62 não é obrigatório que um procedimento devolva resul-tados. Pode limitar-se a executar uma tarefa que não implique fornecer o resultado de um cálculo.

26Na prática, Public Sub ou Sub têm exactamente o mesmo efeito.

67

Page 68: Programming in VBA v2a

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)

7.5 Passagem de parâmetros ByRef

Dissemos que para um procedimento poder fornecer vários resultados teremos que recorrerà passagem de parâmetros por referência. No fundo, um procedimento receber o endereçode uma variável do programa principal, que é o que acontece quando um argumento lheé passado ByRef, equivale a receber autorização do programa para que aceda livrementea essa variável, não só para ler o seu conteúdo mas igualmente para o modificar. Se umprocedimento for autorizado a aceder a múltiplas variáveis do programa que o invocar,terá oportunidade de devolver resultados múltiplos, colocando um resultado em cadavariável.

Conforme foi referido na Secção 3.3 na página 18 as variáveis têm um âmbito próprio.Em regra geral, uma variável criada num dado procedimento apenas será conhecida nolocal em que foi criada e, como tal, só poderá ser acedida nesse procedimento. A excepçãosão as variáveis globais que, por serem declaradas fora de qualquer módulo, são accessíveisa partir de qualquer um. A passagem de parâmetros ByRef é um mecanismo que permitetambém o acesso a variáveis exteriores ao módulo em que foram criadas.

Listing 13: Diferentes resultados na passagem por valor e por referência

1 Private Sub proc1 ( )2 Dim a As Integer3 Dim b As Integer4

5 a = 1006 b = 4007

8 ’ v a l o r e s de a e b antes da chamada de proc29 [ I3 ] = a

10 [ J3 ] = b11

12 proc2 a , b13

14 ’ v a l o r e s de a e b depo i s da chamada de proc215 [ I4 ] = a16 [ J4 ] = b17 End Sub18

19 Sub proc2 (ByRef v1 As Integer , ByVal v2 As Integer )20 v1 = v1 ∗ 1 .121 v2 = v2 ∗ 1 .122 End Sub

68

Page 69: Programming in VBA v2a

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 umacópia do conteúdo da variável b. Dentro de proc2 são modificados os valores dos seusparâmetros de entrada v1 e v2 em que, na altura da sua invocação, foram colocados umareferê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, conformeapresentados na Figura 37.

Figura 37: Resultados do código da Listagem 13 na página anterior

Verfica-se que enquanto o contéudo de a mudou, o conteúdo de b manteve-se inal-terado. De facto, enquanto que através do primeiro parâmetro foi passado a proc2autorização para alterar a variável a, já no caso do segundo parâmetro o que foi enviadofoi meramente uma cópia do conteúdo de b. Esse valor foi alterado dentro de proc2 masessa alteração fica estritamente circunscrita a esse procedimento.

Torna-se assim claro que quando um programa invoca um procedimento passando-lhecomo argumentos referências a variáveis suas, está efectivamente a autorizá-lo a manipularessas variáveis. Assim sendo, o procedimento terá agora possibilidade de colocar nessasvariáveis os resultados dos seus cálculos. Como não há um limite prático para o número deargumentos que se pode passar a uma rotina, um procedimento poderá devolver múltiplosresultados ao programa que o invocar, contornando a limitação existente no caso dasfunções.

7.6 Como aceder às funções standard do Excel

Se bem que o VBA possua várias dezenas de funções pré-definidas, é muito convenientepoder utilizar num macro qualquer uma das centenas de funções standard oferecidas peloExcel. Para poder aceder a elas a partir do VBA é necessário utilizar a propriedadeWorsheetFunction do objecto Application27. Por exemplo, para, num macro, calcular ovalor médio de uma gama de células (identificada pelo nome "Dados") poderia ser usadaa seguinte instrução:

med = Application.WorksheetFunction.Average(Range("Dados"))27Claro que só as funções do Excel que não se encontram duplicadas no VBA podem ser acedidas por

meio da propriedade WorsheetFunction.

69

Page 70: Programming in VBA v2a

Esta instrução permite aceder à função standard Average do Excel, à qual é passadoum 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 quecompõem essa gama.

70

Page 71: Programming in VBA v2a

8 Programação do Excel usando VBANesta secção vamos aprender a trabalhar com os objectos do Excel mais comuns: o Work-book (Livro de trabalho), aWorksheet (Folha de cálculo) e o Range (gama de células). Sãoobjectos que pertencem, por sua vez, ao objecto principal que é a Application (Aplicação,neste caso, o próprio Excel).

8.1 Trabalhar com objectos Workbook

Usando estes objectos, o VBA pode criar novos livros de trabalho, abrir ou fechar exis-tentes, entre outras acções possíveis. Para especificar qual o livro de trabalho com quequeremos trabalhar podemos fazê-lo de três maneiras diferentes:

• Usando o objecto Workbooks que representa o conjunto dos ficheiros Excel abertosnaquele momento (Workbooks(Nome));

• Usando o objecto ActiveWorkbook que representa o ficheiro com que se está demomento a trabalhar;

• Usando o objecto ThisWorkbook que representa o ficheiro em que o próprio pro-grama em VBA (e não necessariamente o utilizador) está a operar.

Para abrir um Livro de Trabalho aplica-se o método Open ao objecto Workbooks :

Sintaxe:Workbooks.Open Nome_do_ficheiro

Exemplo:Workbooks.Open "C : \Documentos\Excel\Dados.xls"

Os métodos Save e Close são utilizados de forma similar para salvaguardar o conteúdodum ficheiro e para o fechar, respectivamente.

8.2 Trabalhar com objectos Worksheet

Normalmente um livro de trabalho possui mais do que uma folha de cálculo (é normal-mente criado logo à partida com três). Para escolher qual a folha de cálculo com que sepretende trabalhar usa-se o objecto Worksheets especificando um índice ou o nome dafolha de cálculo em causa, conforme se exemplifica a seguir:

Worksheets(2)Worksheets("Custos")

8.2.1 Propriedades de Worksheet

Nesta secção são referidas algumas das suas propriedades mais úteis:

71

Page 72: Programming in VBA v2a

• Worksheet.Name - permite mudar ou obter o nome da folha de cálculo. O exemploabaixo muda o nome de "Folha 1" para "Medidas":

Worksheets("Folha 1").Name = "Medidas"

• Worksheet.StandardWidth - permite especificar a largura standard das colunas dumafolha de cálculo.

8.2.2 Métodos de Worksheet

Eis alguns dos métodos normalmente aplicados a este tipo de objectos:

• Worksheet.Activate - torna activa a folha de cálculo especificada28. O exemploseguinte torna activa a folha de cálculo "Custos" do livro de trabalho "Dados 2007":

Workbook("Dados 2007").Worksheets("Custos").Activate

• Worksheet.Copy - copia a folha de cálculo especificada para outra posição dentrodo livro de trabalho.

Sintaxe:Worksheet.Copy [Position]

O argumento Position é opcional e pode ter o valor Before ou After indicando aposição onde a cópia será inserida. Caso o argumento não seja incluído, a cópiaserá inserida num novo livro de trabalho.

Exemplo:Worksheets(2).Copy After:=Worksheets(3)

O exemplo anterior faz uma cópia da 2a folha de cálculo e insere-a a seguir à 3a.O método Move usa uma sintaxe idêntica para mover uma determinada folha decálculo para outra posição.

• Worksheet.Delete - permite eliminar a folha de cálculo especificada.

• Worksheet.Add - permite acrescentar uma nova folha de cálculo ao livro de trabalho.

Sintaxe:Worksheet.Add [Position]

Também aqui o argumento Position é opcional. Se for omitido, a nova folha decálculo será inserida imediatamente antes da folha activa.Exemplo:Worksheets.Add After:=Worksheets("Medidas")

28A folha de cálculo activa é aquela que está visível no momento.

72

Page 73: Programming in VBA v2a

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 representaruma célula individual.

Para nos referirmos a uma célula ou gama de células podemos aplicar o método Rangeao 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 contendoas células que se quer especificar. Caso se omita a referência a Worksheet em qualquerdas sintaxes anteriores, o VBA pressupõe que se trata da folha de cálculo activa naquelemomento.

Exemplos:Range("C5").Value = 100Range("D1","D10").Value = 0Worksheets(3).Range("Dados").ClearContents

O 1o exemplo guarda o valor 100 na célula C5 da folha de cálculo activa. O 2o exemploatribui o valor zero a todas as células da gama D1 a D10. Nestes dois exemplos é utilizadaa propriedade Value dos objectos Range que permite conhecer ou modificar o seu valor.No 3o exemplo limpa-se o conteúdo das células da gama "Dados" da 3a folha de cálculo,mediante a aplicação do método ClearContents.

Caso queiramos identificar apenas uma célula podemos também utilizar o métodoCells.

Sintaxe:Objecto.Cells(Linha,Coluna)

Na sintaxe acima, a entidadeObjecto pode ser um objecto Worksheet ou Range. Maisuma vez, a sua omissão, leva o VBA a partir do princípio que se trata da folha de cálculoactiva. Linha e Coluna são valores numéricos indicando qual a linha e qual a coluna naintersecção das quais a célula se encontra30. Veja-se o seguinte exemplo:

1 For coluna = 2 To 132 Ce l l s (2 , Coluna ) . Value = "Mes␣" & coluna − 13 Next

O exemplo acima usa um ciclo For...To para preencher todas as células da gama C2 aC13 com o texto "Mês X" em que X é o no do mês. É usado o operador de concatenaçãode strings & para efectuar a colagem.

29Atribuídos em Excel usando o Menu "Insert/Name/Define".30Se o objecto for do tipo Range, os argumentos Linha e Coluna referir-se-ão à linha e à coluna dentro

da gama de células especificada.

73

Page 74: Programming in VBA v2a

Caso se pretenda identificar uma linha ou coluna completa, podem ser utilizados osmé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 In s e r eL inhas (gama As Range , num As Integer )2 Dim num_linhas As Integer , u lt ima_linha As Integer3 Dim i As Integer4 With gama5 num_linhas = .Rows .Count6 ult ima_linha = .Rows( num_linhas ) .Row7 For i = 1 To num8 . Rows( ult ima_linha + i ) . I n s e r t9 Next

10 End With11 End Sub

Esta sub-rotina recebe como argumentos uma gama de células (um objecto do tipoRange) e um inteiro especificando o número de linhas a inserir abaixo da última linhadessa gama. A estrutura With...End...With é muito prática porque permite executarum conjunto de instruções sobre um determinado objecto, neste caso qualquer objectoRange que a sub-rotina receba como argumento. Dentro da estrutura With...End...Withomite-se qualquer referência a esse objecto, usando-se apenas os seus métodos e propri-edades. Assim, .Rows.Count refere-se ao número total de linhas da gama especificadae .Rows(num_linhas).Row fornece-nos o índice da última linha dessa gama. O cicloFor...To repete num vezes a aplicação do método Insert à ultima linha da gama.

Para testar a sub-rotina InsereLinhas, use-se a seguinte rotina de teste:

1 Sub i n s e r eTe s t e ( )2 In s e r eL inhas Worksheets ( 3 ) . Range ( "Dados" ) , 33 End Sub

Apresentamos outro exemplo, agora referido ao método Columns :

Columns(5).ColumnWidth = 15

Aplicando o método Columns ao objecto Columns(5) (a coluna de índice 5, ou seja,a coluna E) o efeito obtido é a mudança da sua largura para 15.

Existe uma propriedade dos objectos Range particularmente útil. Trata-se da propri-edade Offset que permite definir um deslocamento em relação a um objecto Range, porexemplo, em relação à célula activa.

31Adaptado de um exemplo contido em [1].

74

Page 75: Programming in VBA v2a

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 casoA foi armazenado o valor 2 na célula B5 (duas linhas abaixode 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 especificoua posição de uma célula em relação a um referencial fixo (B3).

Figura 38: Exemplos de utilização da propriedade Offset

Usando esta propriedade podemos escolher uma célula especificando a sua coluna oua sua linha (ou as duas) de forma relativa, ou seja, em relação ao objecto Range a quese aplica. Isto pode não parecer à primeira vista especialmente útil. No entanto, sepensarmos que linha ou coluna podem ser constituídos por variáveis, cujo valor podeser controlado por uma estrutura de repetição, podemos ver que temos aqui uma formaexpedita de executarmos uma mesma acção sobre um conjunto de células definido deforma relativa em relação a uma dada célula, que podemos considerar como uma espéciede âncora.

75

Page 76: Programming in VBA v2a

9 Adicionando uma interface gráficaO acesso aos macros faz-se, conforme referido na Secção 2.3, mediante a combinação deteclas ALT-F8. Pode ainda associar-se a um macro uma combinação de teclas especialque permite accioná-lo directamente. No entanto, em muitos casos, é mais convenientepoder interagir com o macro através de uma interface própria, concebida especialmentepara 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 Boxese 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.

9.1 Instalação da Form

Uma Form é uma janela, em si mesma um objecto, utilizada como um contentor paraoutros objectos gráficos (ver Secção 4.3.3 na página 32). Pode-se criar um objecto daclasse UserForm no Editor do VBA através do Menu "Insert/User Form".

Figura 39: Criação de uma Form no 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

Page 77: Programming in VBA v2a

possível manipular várias características da Form (como, aliás, de qualquer controlo queesteja seleccionado).

9.2 Instalação dos Controlos

Usando a Caixa de Ferramentas (Toolbox ), é possível escolher e instalar os controlos naForm. Para o efeito, basta accionar o símbolo do controlo pretendido e desenhá-lo como rato na Form. A seguir, quer agindo directamente sobre o controlo, quer utilizando aJanela de Propriedades, podem-se fazer os ajustes necessários das suas características. Sebem que cada classe de controlos possua a sua lista específica de propriedades, existemalgumas propriedades importantes que são comuns à maioria delas (ver Secção 4.1 napágina 23).

Conforme referido na Secção 4.3 na página 29 no ambiente de desenvolvimento doVBA encontram-se disponíveis diversos tipos de controlos: botões de comando (CommandButtons), etiquetas (Labels), caixas de texto (Text Boxes), quadros (Frames), botões deopção (Option Buttons), caixas de verificação (Check Boxes) e caixas de listagem (ListBoxes), entre outros.

9.3 Associação da Form ao procedimento

Uma vez construída a form é preciso associá-la ao programa que a vai utilizar. Nestafase há três aspectos a considerar:

1. Visualização da Form

2. Tratamento dos eventos que ocorram enquanto a Form estiver visível

3. Processamento dos resultados fornecidos pela Form

O 2o ponto, referente ao tratamento dos eventos, foi já discutido anteriormente. Osrestantes serão tratados nas secções seguintes.

9.3.1 Como visualizar e terminar uma Form

Para visualizar a UserForm usa-se o método Show :

Exemplo:MinhaForm.Show

Se, em alternativa, se pretender arrancar com a Form mas sem a visualizar nessemomento, usa-se a instrução Load :

Exemplo:Load MinhaForm

Quando se pretender tornar a Form visível, aplicar-se-á então o método Show.Após a sua utilização, quando uma Form deixar de ser necessária, deve-se utilizar a

instrução Unload para a desactivar:

Exemplo:

77

Page 78: Programming in VBA v2a

Unload Me

No entanto, desactivar uma Form através da instrução Unload não implica que estadeixe de estar em memória. Para garantir a sua efectiva remoção, que se traduzirá nageração do evento Terminate, haverá que se usar a seguinte técnica:

1 Exemplo :2 Set MinhaForm = Nothing

9.3.2 Tratamento de eventos através de Event Handlers

Este tema foi já introduzido na Secção 4.1.3 na página 25. Pelo menos um controloinstalado na form deve ter um Event Handler associado. Vamos agora considerar oexemplo de um Event Handler utilizando a instrução Unload Me e associado a um controlo(neste caso, como é habitual, um botão de comando) presente na Form. Nesta instrução,a palavra Me indica ao VBA que a Form a desactivar será aquela a que o Event Handlerdiz respeito.

Um exemplo de um Event Handler que termine uma Form pode ser:

Listing 15: Handler do objecto cmdFechar para o evento click

1 Private Sub cmdFechar_Click ( )2 Dim op As Integer3 op = MsgBox( " Sa i r ?(Yes/No) " , vbYesNo + vbQuestion )4 I f op = vbYes Then5 Unload Me6 End I f7 End Sub

A sub-rotina acima vai especificar a reacção do botão de comando cmdFechar aoevento Click, neste caso apresentar uma MsgBox que confirme a intenção do utilizadorde fechar a Form.

Outro evento importante é o Change que ocorre sempre que se altera o conteúdo deobjectos como as Text Box. Na Secção 9.4 na página 82 encontra-se um exemplo de umEvent Handler associado a este tipo de evento.

O tratamento de qualquer evento a ocorrer na Form, ou em qualquer dos controlosnela presentes, deverá basear-se num Event Handler que defina a resposta adequada.

9.3.3 Como recolher os resultados de uma Form

Uma UserForm é muitas vezes utilizada para pedir informação ao utilizador. Nesse caso,será necessário recolher os dados introduzidos ou as opções seleccionadas nos controlosapropriados.

Para tal é preciso aceder às propriedades Value dos diversos controlos existentes naForm e copiar os seus valores actuais para células da folha de cálculo.

O conteúdo da propriedade Value nas principais classes de controlos encontra-se re-sumida na seguinte tabela:

78

Page 79: Programming in VBA v2a

Classe ConteúdoCheckBox True ou False conforme esteja ou não activada

OptionButton True ou False conforme esteja ou não activadaListBox A posição da linha seleccionadaTextBox 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.

9.3.4 Exemplo de aplicação

Vamos finalmente aplicar estes conceitos e técnicas na construção e integração de umaUserForm (descrita na Figura 40 na página seguinte) que permita a introdução conjuntados dados de um aluno (Nome, Número e Curso) sem necessidade de recorrer a trêsInput Boxes separadas. Esta UserForm conterá duas Text Boxes para inserção do Nomee Número do aluno e uma Combo Box para selecção do seu Curso. Conforme referidona Secção 4.3.10 na página 36, uma Combo Box é um controlo semelhante a uma ListBox em que a lista está normalmente invisível, só aparecendo quando o campo superioré activado. Aplicam-se-lhe os mesmos métodos da classe ListBox.

Listing 16: Exemplo de sub-rotina de invocação de uma UserForm

1 Public Sub testUserFormInput ( )2 usrFrmInput .Show3 Set usrFrmInput = Nothing4 End Sub

O macro da Listagem 16 chama a UserForm com o nome usrFrmInput e remove-a dememória quando ela termine o seu trabalho. Para facilitar a sua invocação, é convenienteassociar ao macro uma combinação de teclas específica, usando uma das técnicas jáaprendidas (ver parte final da Secção 2.6).

Listing 17: Exemplo de sub-rotina de inicialização de uma UserForm

1 Private Sub UserForm_In i t ia l i z e ( )2 cmbCursos .AddItem " C i v i l "3 cmbCursos .AddItem " In fo rmat i ca "4 cmbCursos .AddItem " E l e c t r o t e cn i a "5 cmbCursos .AddItem "Geotecnia "6 cmbCursos .AddItem "Quimica"7 cmbCursos .AddItem " Instrumentacao ␣Medica"8 End Sub

A sub-rotina da Listagem 17 é um event handler especial que trata do evento Initialize.Este evento ocorre quando a UserForm é criada. Assim sendo, esta sub-rotina é executadade forma automática sempre que a UserForm arranca. Neste caso, trata de inicializar aCombo Box "cmbCursos" com os nomes dos diferentes cursos da escola.

79

Page 80: Programming in VBA v2a

Figura 40: A UserForm para Entrada Múltipla de Dados

Listing 18: Handler do objecto cmdFechar para o evento Click

1 Private Sub cmdFechar_Click ( )2 With Worksheets (4 )3 . [ H5 ] = txtNome . Value4 . [ I5 ] = txtNum . Value5 . [ J5 ] = cmbCursos . Text6 End With7 Unload Me8 End Sub

O Event Handler da Listagem 18 está associado ao botão cmdFechar e é chamadoquando sobre ele ocorre o evento Click. Antes de fechar a UserForm usando Unload,copia o conteúdo das duas Text Box e o da linha seleccionada da Combo Box para trêscélulas contíguas da folha de cálculo, permitindo assim memorizar os dados introduzidospelo utilizador.

Nessa listagem pode observar-se que as três instruções de atribuição a outras tantascélulas da folha de cálculo "Worksheets(4)" estão encapsuladas pela estrutura With..EndWith. Esta estrutura permite a omissão da referência ao objecto (neste caso a "Workshe-ets(4)") a que pertencem as células em causa. Isto é também válido quando queremosespecificar propriedades ou aplicar métodos a um mesmo objecto. Veja-se o exemplo naSecção 9.4.

9.4 Exemplo de aplicação mais elaborado

Neste exemplo mais elaborado vamos introduzir o controlo Tabstrip existente no VBA.Este objecto permite a apresentação de diferentes conjuntos de valores mediante a selecçãode diferentes separadores ("tabs"). Na Figura 41 na página seguinte pode-se encontrarum exemplo de um objecto deste tipo.

Numa Tabstrip é usual inserirem-se outros controlos, um pouco como se faria numamini-Form ou num quadro. No exemplo da figura, encontram-se três TextBox.

80

Page 81: Programming in VBA v2a

Figura 41: Objecto da classe Tabstrip

Conforme já referido anteriormente (Secção 4.1 na página 23), para que um controlopossa reagir a acções provocadas pelo utilizador, como o "clicar" do rato, é preciso queo programador crie sub-programas especiais, chamados Event Handlers (tratadores deeventos) e que esses sub-programas sejam associados aos controlos respectivos. EssesHandlers 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 permitemespecificar 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-gem 19). Este evento ocorre automaticamente quando, após o arranque do programa, aform é criada.

Listing 19: Sub-rotina de inicialização da UserForm

1 Private Sub UserForm_In i t ia l i z e ( )2 With TabStrip13 . Tabs ( 0 ) . Caption = " C i v i l "4 . Tabs ( 1 ) . Caption = " In fo rmat i ca "5 . Tabs .Add " E l e c t r o t e cn i a "6 End With7 With Worksheets (4 )8 txtNumAlunos . Text = . [ D5 ]9 txtPercAprov . Text = . [ D6 ] ∗ 100

10 txtMedia . Text = . [ D7 ]11 End With12 End Sub

Este procedimento vai inicializar os dois separadores do controlo Tabstrip1 com queele é 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ídosa cada uma das TextBox contidas na Tabstrip1 os conteúdos das três células da folha de

81

Page 82: Programming in VBA v2a

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 precedidado nome do objecto a que se aplicam (TabStrip1 ). Da mesma forma, nas instruções 8,9 e10, as referências às células D5, D6 e D7 teriam que ser precedidas da indicação de quala folha de cálculo a que pertenciam (Worksheets(4)).

O próximo procedimento (Listagem 20) é o Event Handler do controlo Tabstrip1para 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 quetraduz qual o separador que está activo. Em função do valor recolhido na variável v, aestrutura condicional imbricada If...Then...Else irá escolher o conjunto de valores corres-pondente e armazená-los nas caixas de texto respectivas.

Listing 20: Handler associado ao objecto Tabstrip1 para o evento Change

1 Private Sub TabStrip1_Change ( )2 Dim v As Integer3 With Worksheets (4 )4 v = TabStrip1 . Value5 I f v = 0 Then6 txtNumAlunos = . [ D5 ]7 txtPercAprov = . [ D6 ] ∗ 1008 txtMedia = . [ D7 ]9 ElseIf v = 1 Then

10 txtNumAlunos = . [ E5 ]11 txtPercAprov = . [ E6 ] ∗ 10012 txtMedia = . [ E7 ]13 Else14 txtNumAlunos = . [ F5 ]15 txtPercAprov = . [ F6 ] ∗ 10016 txtMedia = . [ F7 ]17 End I f18 End With19 End Sub

82

Page 83: Programming in VBA v2a

10 Manipulação de textoO VBA representa texto através de strings (cadeias de caracteres). Não existe um tipode dados específico para representar caracteres individuais, pelo que se utiliza o mesmotipo usado para cadeias de caracteres.

10.1 Funções de manipulação de strings

Nesta secção são introduzidas algumas funções especializadas no tratamento de stringse que serão utilizadas nos exemplos de programas de manipulação de texto apresentadosna Secção 10.2 na página 85.

10.1.1 Trim, LTrim e RTrim

Estas funções retornam uma cópia da string original, mas sem os eventuais espaços noinício ou fim da string.

Exemplos:

Dim s1 As String , s2 As Strings1 = "␣␣ISEP␣ C i v i l ␣␣"s2 = Trim( s1 ) ’ Resu l tado : "ISEP C i v i l "s2 = LTrim( s1 ) ’ Resu l tado : "ISEP C i v i l "s2 = RTrim( s1 ) ’ Resu l tado : " ISEP C i v i l "

Os espaços que ocorram no interior da string não são afectados por estas funções. Astring original mantem-se inalterada.

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 Integers1 = "␣␣ISEP␣ C i v i l ␣␣"n = Len( s1 ) ’ Resu l tado : n = 14n = Len(Trim( s1 ) ) ’ Resu l tado : n = 10

10.1.3 Left, Right

Estas funções copiam n caracteres da string s a partir da esquerda (Left) ou da direita(Right).

Sintaxe:Left(s As String, n As Integer) As String

Exemplos:

83

Page 84: Programming in VBA v2a

Dim s1 As String , s2 As String , n As Integers1 = "ISEP␣ C i v i l "n = 2s2 = Left ( st1 , n ) ’ Resu l tado : s2 = "IS"s2 = Right ( st1 , n ) ’ Resu l tado : s2 = " i l "

’ El iminar o pr imeiro carac t e r de uma s t r i n g .s1 = Right ( s1 , Len( s1 )−1) ’ Resu l tado : s1 = "SEP C i v i l "

Esta última instrução usa a função Right para seleccionar os primeiros Len(s1)-1caracteres contados a partir da direita. Se Len(s1) nos dá o número de caracteres dastring então os caracteres seleccionados serão todos menos o primeiro. Como esta novastring é de novo guardada em s1, estamos efectivamente a eliminar o 1o caracter da strings1.

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 (o3o argumento é opcional), será copiado tudo desde i até ao fim da string.

Exemplos:

Dim s1 As String , s2 as Strings1 = "ISEP␣ C i v i l "s2 = Mid( s1 , 2 , 2) ’ Resu l tado : s2 = "EP"s2 = Mid( s1 , 6 , 10) ’ Resu l tado : s2 = " C i v i l "s2 = Mid( s1 , 6) ’ Resu l tado : s2 = " C i v i l "

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çãoi 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çãona string s1 em que o padrão s2 começa. Caso não tenha sucesso, será devolvido o valorzero.

Exemplos:

Dim s As String , n As Integers = "ISEP␣ C i v i l "n = Instr ( s , "␣" ) ’ Resu l tado : n = 5n = Instr (5 , s , "␣" ) ’ Resu l tado : 0n = InStr ( s , " C i v i l " ) ’ Resu l tado : 6

84

Page 85: Programming in VBA v2a

10.1.6 UCase, LCase

Sintaxe:UCase(s As String) As StringLCase(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 depontuação mantem-se inalterados.

Exemplos:

Dim s1 As String , s2 As Strings1 = " i109123X"s2 = UCase( s1 ) ’ Resu l tado : s2 = "I100Y"s2 = LCase( s1 ) ’ Resu l tado : s2 = " i100y "

10.2 Algoritmos

Nesta secção são discutidos métodos que permitem dividir uma string nos caracteres quea constituem e dividir uma frase em palavras 32.

10.2.1 Separação duma string em caracteres

Para decompor uma string nos caracteres que a compõem, vamos apresentar dois métodosdiferentes:

1. Método destrutivo da string original, usando um ciclo e as funções Left e Right -Listagem 21

2. Método não-destrutivo, usando um ciclo e a função Mid - Listagem 22 na páginaseguinte

Listing 21: Separação de string em caracteres - 1o Método

1 Dim s As String , c As String2 Do While s <> ""3 c = Left ( s , 1)4 ’ Processamento do carac t e r que acabou de ser i s o l a d o5 s = Right ( s , Len( s ) − 1)6 Loop

O método baseia-se na repetição das instruções nas linhas 3 e 5 para cada elementoda string. A 1a instrução usa a função Left para isolar o 1o caracter da string, copiando-opara a variável c. Conforme analizado na Secção 10.1.3 na página 83 a 2a instrução vaiarmazenar a string s uma vez expurgada do 1o caracter. Será essa string amputada quevai ser processada na próxima iteração do ciclo. Este terminará quando s contiver a stringvazia. O conteúdo da string original ficará assim perdido.

32Os exemplos desta Secção são adaptações dos incluídos nos textos de apoio do prof. Ângelo Martins.

85

Page 86: Programming in VBA v2a

Listing 22: Separação de string em caracteres - 2o Método

1 Dim s t As String , c As String , v As Integer2 For v = 1 To Len( s )3 c = Mid( s , v , 1)4 ’ Processamento do carac t e r que acabou de ser i s o l a d o5 Next

Este 2o método baseia-se na instrução da linha 3, que usa a função Mid. Comodescrito 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 seufuncionamento, todos os valores desde 1 até Len(s), ou seja, a posição do último caracterda string. Não há qualquer alteração do conteúdo da string original.

10.2.2 Divisão de uma frase em palavras

Para efeitos desta secção, considera-se uma palavra qualquer destes conjuntos: caracteresentre espaços, entre o início da string e o primeiro espaço, entre o último espaço e o fimda string, ou ainda todos os caracteres da string, se esta não contiver espaços.

Listing 23: Separação de frase em palavras

1 Dim s As String , pa l As String , p As Integer2

3 s = Trim( s )4 Do While s <> ""5 p = InStr ( s , "␣" )6 I f p > 0 Then7 pal = Left ( s , p − 1)8 s = LTrim(Right ( s , Len( s ) − p ) )9 Else

10 pal = s11 s = ""12 End I f13 ’ Processamento da pa lavra cont ida em pa l14 Loop

O algoritmo descrito na Listagem 23 usa um método destrutivo, segundo o qual seprocura sistematicamente o 1o espaço contido na string (instrução 5). Sabendo nós queo início da string e esse espaço delimitam uma palavra, está achada a 1a palavra, que écopiada para a variável pal (instrução 7) e de seguida eliminada da string (instrução 8).Nesta última instrução vale a pena atentar no seguinte:

1. Len(s) - p é o comprimento da string restante se lhe retirarmos a 1a palavra

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

Page 87: Programming in VBA v2a

3. A função LTrim limita-se a descartar o espaço existente entre a 1a palavra e o restoda string.

4. A atribuição a s desta string truncada destroi a string original, preparando ascondições para que na próxima iteração do ciclo seja destacada uma nova palavra.

A utilização da estrutura If..Then..Else permite detectar se existem ou não espaçosna string, testando o conteúdo da variável p. Se a função InStr encontrar um espaço (p> 0) é porque (ainda) existe uma palavra na string. Se não encontrar (p = 0) é porquea string é constituída por uma só palavra. Nesse caso as instruções executadas serão asque se encontram entre Else e End If (linhas 10 e 11), a 1a copiando s para pal, a 2a

atribuindo a s a string vazia, o que terá como consequência a paragem do ciclo.

87

Page 88: Programming in VBA v2a

11 Notas finaisAlguns 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.

[2] António Silva. Sebenta de Introdução à Computação - Visual Basic, ISEP.

88

Page 89: Programming in VBA v2a

ÍndiceActiveWindow, 9

Dialog Box, 76

Event Handlers, 25, 81

IDE, 12InStr, 84

LCase, 85Left, 83Len, 83

Macro, 9Mid, 84

Offset, 74

Right, 83

Trim, 83

UCase, 85User Form , 76

With .. End With, 80, 82

89