Vous êtes sur la page 1sur 56

Introdução

O objetivo desse material é apresentar os fundamentos de resolução de problemas


empresariais através de programas de computador e as técnicas básicas de construção de
programas. A apresentação prática de exemplos e exercícios é feita utilizando a
linguagem Visual Basic para Aplicativos, inserida no pacote Microsoft Excel para
Windows(c).

Os capítulos do livro obedecem à sequência de aulas apresentadas na disciplina de


Introdução à Computação. Assim, esperamos que o leitor que estude do primeiro ao
último capítulo, resolvendo todos os exercícios e projetos propostos, termine sua leitura
preparado para resolver os mais diferenciados problemas empresariais através da
construção de programas e utilização avançada dos recursos do Microsoft Excel para
Windows.

No Capítulo 1 descrevemos de forma sucinta o funcionamento interno do computador e


de programas em geral. No Capítulo 2 apresentamos o funcionamento de planilhas
eletrônicas em geral e do pacote Microsoft Excel para Windows em particular. No
Capítulo 3 iniciamos o estudo de programação propriamente dito, com a incorporação
de funções pré-programadas nas planilhas.

No Capítulo 4 apresentamos os comandos de seleção. No Capítulo 5 apresentamos o


comando básico de iteração. No Capítulo 6 apresentamos os conceitos de subrotina e
macro e mostramos como efetuar entrada e saída de dados sem necessariamente utilizar
uma planilha de apoio. No Capítulo 7 tratamos de simulação de programas para teste.
Nesse capítulo tratamos também de novos tipos de dados, especificamente dos dados
``booleanos''. No Capítulo 8 estudamos como transmitir dados entre planilhas e
programas. No Capítulo 9 tratamos da subdivisão de programas em funções, macros e
subrotinas. No Capítulo 10 apresentamos como trabalhar simultaneamente com várias
planilhas. No Capítulo 11 estudamos como trabalhar com vetores e matrizes. No
Capítulo 12 estudamos programas para ordenação de valores, que além de permitirem
utilizar boa parte do que foi estudado até aquele capítulo constituem uma classe de
programas muito utilizados como procedimentos em outros programas. Finalmente, no
Capítulo 13 estudamos manipulação e edição de strings por programas.
O que É um Computador
Os computadores que usamos hoje em dia têm uma composição e uma organização
comum, que passamos a apresentar a seguir.

A Unidade Central de Processamento executa a função principal do computador, que


é processar as instruções armazenadas na memória. ``Processar'' significa:

1. buscar a próxima instrução na memória,


2. executar a instrução,
3. voltar para 1.

As instruções ficam codificadas na memória do computador, em uma linguagem própria


chamada de Linguagem de Máquina. Uma instrução, por exemplo, é a instrução
1001000101001100011. O resultado da execução dessa instrução varia de acordo com o
tipo de computador utilizado: um Macintosh fará uma coisa, um computador da linha
PC fará outra, etc. Cada instrução identifica uma alteração e/ou inspeção do valor de
uma posição da memória do computador.

Construir um programa diretamente na linguagem de máquina pode ser muito tedioso e


demorado. Além disso, como a linguagem de máquina muda de computador para
computador, a mesma solução de um problema requer diferentes programas em
linguagem de máquina para ser aproveitada em diferentes computadores. Para sanar
esses dois problemas, foram desenvolvidas as Linguagens de Alto Nível, que são
códigos intermediários - mais interessantes de se usar do ponto de vista do programador
- para os quais foram desenvolvidos ``tradutores'' para as linguagens de máquina dos
diversos computadores. Assim, uma mesma solução de um problema codificada em
uma linguagem de alto nível pode ser ``traduzida'' e utilizada em diferentes
computadores. Por exemplo, a linguagem Visual Basic para Aplicações é uma
linguagem de alto nível para a qual foram desenvolvidos ``tradutores'' denominados de
Interpretadores: o mesmo programa pode ser usado em um Macintosh ou em um PC,
bastando para isso que o interpretador apropriado (no caso, a versão apropriada do
Microsoft Excel para Windows) esteja instalada no computador em uso.

A Memória do computador é aonde ficam armazenados os dados e instruções. Ela é


organizada em Endereços de Memória, identificados por um código numérico que
possibilita a identificação e acesso ao conteúdo de cada endereço.

O conteúdo da memória se apaga cada vez que o computador é desligado. Para


armazenar de forma mais perene dados e programas, é preciso utilizar Dispositivos de
Armazenamento: discos rígidos, disquetes, CD's, discos de Zip Drives, mini disks,
fitas DAT, etc.

A ligação da Unidade Central de Processamento com o mundo exterior (ou seja, você) é
feita através dos Dispositivos de Entrada e Saída: a tela do computador, o teclado,
impressoras, o mouse, auto-falantes, câmeras e microfones para programas multimídia,
scanners, etc.
A tradução das instruções de uma linguagem de alto nível para a linguagem de máquina
pode ser feita de duas maneiras diferentes:

1. através de um interpretador, que traduz os comandos ``passo-a-passo'' e na medida


da necessidade;
2. através de um compilador, que primeiro traduz todos os comandos encontrados e
armazena a tradução na memória como um conjunto de instruções na linguagem de
máquina, e só depois executa todas essas instruções.

A principal diferença entre um interpretador e um compilador é que o segundo


possibilita armazenar as instruções na linguagem de máquina diretamente, na forma de
um arquivo de programa executável.

Toda a atividade da Unidade Central de Processamento, incluindo o controle dos


dispositivos de armazenamento e de entrada e saída, é efetuada através de um programa
especial, denominado de Sistema Operacional. Existem diversos sistemas operacionais
disponíveis no mercado, cada um com suas peculiaridades e possibilidade de uso em
computadores específicos: MacOS (que só funciona em computadores da linha
Macintosh), Windows95 (que só funciona em computadores da linha PC), Unix (que
tem diferentes versões e funciona em computadores diversos), etc.

A sequência usual para se resolver um problema utilizando o computador é:

1. estudar e analisar o problema para entender a sua estrutura;


2. codificar a resolução do problema como uma sequência lógica e ordenada de
operações;
3. traduzir essa sequência de operações como instruções em uma linguagem de alto
nível;
4. executar as instruções através do interpretador ou compilador apropriado.

Nos próximos capítulos estudaremos as técnicas específicas para desenvolver essa


sequência em diferentes situações práticas.

Exercícios
1. Inserir a seguinte planilha de gastos pessoais:
A B C D E F
1 Gastos Cinema Almoço Gasolina Cônjuge Teatro
2 285 10 20 35 200 20

2. Formatar a tabela de várias formas:

• Adicionar ``,00'' após os números de forma automática;


• Colocar o símbolo ``R$'' diante dos valores monetários,
automaticamente;
• Mudar a formatação dos cabeçalhos das colunas.
3. Salvar o documento:

• no disco;
• em disquete;
• movendo o arquivo do disco para o disquete.

4. Abrir um documento salvo.


Introdução à Manipulação de Planilhas
Eletrônicas
Planilhas Eletrônicas são tabelas usadas para comunicar informações de forma clara,
precisa e sucinta. Além de permitirem a comunicação de informações, elas também
permitem a manipulação automática dessas informações através de fórmulas.

Assim, os dados que podemos inserir numa planilha podem ser dos seguintes tipos:

1. texto;
2. valores numéricos;
3. fórmulas.

Cada posição de uma planilha é chamada de Célula. Para se inserir um texto ou um


número em uma célula, basta selecionar a célula e digitar o que se deseja:

• a seleção da célula pode ser feita usando o mouse ou as setas do teclado;


• uma vez selecionada a célula, podemos editar seu conteúdo diretamente na
planilha ou no campo de edição localizado no topo da planilha;
• para alterar uma célula que já contém algo escrito, primeiro selecionamos a
célula e depois temos 3 alternativas:

1. um duplo clique com o mouse nesta célula, que aciona um cursor que indica
que podemos editar o seu conteúdo;
2. a tecla F2 no teclado, que produz o mesmo efeito do duplo clique com o
mouse;
3. um clique com o mouse sobre o campo de edição no topo da planilha, que
aciona um cursor no campo de edição e permite editar o conteúdo da célula a
partir do campo de edição.
As Fórmulas se distinguem das células de texto e de números por serem iniciadas pelo
símbolo `='. Por exemplo, uma célula contendo a expressão =3 + 4 é uma fórmula, que
se avaliada produz o resultado esperado (ou seja o valor numérico 7); já uma célula
contendo apenas a expressão 3+4 (sem o símbolo `=') é sómente um texto composto por
três caracteres: ``3'', ``+'' e ``4''.

Após o término da edição de uma fórmula, não obtemos a cadeia de caracteres que foi
digitada, mas sim o valor computado a partir dela. Por exemplo, após digitarmos = 3 * 5
+ (7 - 2)obtemos o valor 20. No entanto, a cadeia de caracteres que define a fórmula (ou
seja, ``= 3 * 5 + (7 - 2)'') aparece no campo de edição no topo da planilha.

Cada célula na planilha possui um nome. O nome da célula é dado no formato ``batalha
naval'': cada coluna da planilha é nomeada com uma letra, e cada linha é nomeada com
um número. Por exemplo, a célula que se encontra terceira linha da coluna D é a célula
D3.

Nas fórmulas, em qualquer lugar em que podemos inserir um número numa expressão
aritmética podemos também inserir uma referência a uma célula. Por exemplo, suponha
que queiramos que na terceira linha da planilha a terceira célula seja a soma da primeira
com a segunda. Para isso, escrevemos:

A B C
1
2
3 7 3 =A3+B3

Neste caso, a célula C3 mostrará o valor 10.

Quando trabalhamos com tabelas, muitas vezes queremos repetir em todas as linhas
uma mesma operação. Por exemplo, se tivermos uma tabela com quatro linhas e
quisermos que a terceira coluna seja sempre a soma das duas primeiras, basta escrever a
fórmula na primeira linha e copiá-la para as outras linhas.

A título de ilustração, vamos supor que temos uma tabela com valores de Capital Inicial
($) e Taxa de Juros Mensal (%) e desejamos calcular o Capital Final, a juros simples, no
final de 6 meses. A fórmula para o Capital Final é Cf = Ci * (1 + n * i/100), onde Ci é
dado na primeira coluna, i é dado na segunda coluna e n é sempre igual a 6. Começamos
com a tabela:

A B C
1 Capital Inicial Ci Taxa de Juros i Capital Final Cf
2 100,00 2,00 =A2*(1+6*(B2/100))
3 100,00 3,00
4 200,00 2,50
5 200,00 3,50

Em seguida, copiamos a fórmula em C2 para as demais linhas. Isso é feito colocando o


mouse sobre o canto inferior direito da célula (o cursor deve se transformar em um
``+''), clicando e arrastando o mouse sobre as linhas desejadas. O resultado é:

A B C
1 Capital Inicial Ci Taxa de Juros i Capital Final Cf
2 100,00 2,00 =A2*(1+6*(B2/100))
3 100,00 3,00 =A3*(1+6*(B3/100))
4 200,00 2,50 =A4*(1+6*(B4/100))
5 200,00 3,50 =A5*(1+6*(B5/100))

Observe que a própria planilha modificou apropriadamente as referências às células das


diferentes linhas. Caso isso não fosse desejado (se as cópias desejadas fossem sempre
referenciando a célula B2, por exemplo), então a fórmula inicial deveria ser escrita

como . Isso significa que todas as fórmulas geradas usariam o valor da célula B2,

ao invés de como acima. O mesmo vale para cópias de fórmulas através de


linhas da planilha.

Exercícios
1. Insira numa planilha a tabela de juros simples vista acima.

2. Crie uma outra planilha igual à primeira, só que desta vez usando juros compostos. A
fórmula para juros compostos é Cf = Ci * (1 + i )n, onde:

• Cf: Capital final


• Ci: Capital inicial
• i: taxa de juros mensal
• n: número de meses

3. Considere a seguinte tabela de importação:


Produto Valor (US$) Valor (R$)
Cranberry Sauce 1.74
Whisky Cardu 12 anos 18.89
Queijo Cheddar Maturado 5.89
Massa instantânea p/ panquecas 3.78
Custo total

Preencha a coluna de valor em R$, baseada na conversão de US$ 1,00 = R$


1,95.

4. Considere a fórmula de conversão de temperatura entre graus Celsius e Farenheit:

C/5 = (F - 32)/ 9

Construa uma tabela com as informações:

Temperatura Farenheit Temperatura em Celsius


Faça a primeira coluna variar a temperatura Farenheit de 0 a 100 em intervalos
de 10. A segunda coluna deverá conter a temperatura correspondente em
Celsius.
Programação e Utilização de Funções
Além de números e referências a células, as fórmulas em uma planilha podem conter
Chamadas de Funções.

Uma chamada de função tem o formato Nome-da-Função( Lista-de-Parâmetros),


onde Nome-da-Função é um nome qualquer iniciando com uma letra (de A a Z) e
Lista-de-Parâmetros é um número fixo de parâmetros que precisam ser fornecidos na
ordem correta. Os parâmetros no Microsoft Excel para Windows em português são
separados por `;' e no Microsoft Excel para Windows em inglês por `,'. Os parâmetros
podem ser:

1. números;
2. referências a células;
3. expressões aritméticas quaisquer.

No exemplo abaixo vemos uma função de nome JurosSimples com 3 parâmetros. Os


dois primeiros parâmetros são referências a células e o último é um número. Neste caso,
o primeiro parâmetro deve conter o Capital Inicial, o segundo a Taxa de Juros Mensal e
o terceiro o Número de Meses. A função deve retornar o capital final calculado a juros
simples:

A B C
1 1000 25 =JurosSimples(A1; B1; 6)

O Símbolo de `=' na frente da chamada de função indica que a chamada da função


ocorre dentro de uma fórmula. Num exemplo um pouco mais sofisticado, temos
expressões aritméticas passadas como parâmetros:

A B C
1 1000 25 =JurosSimples(A1/2; B1+10; 6)

Uma chamada a função pode ocorrer em uma fórmula exatamente nos mesmos lugares
em que podem ocorrer números ou referências a células. Muitas vezes, como nos
exemplos acima, a fórmula contém apenas a chamada da função. Suponhamos agora
que nós temos a função de nome INT que recebe como parâmetro um número e retorna
a parte inteira do número. Por exemplo, na situação abaixo a fórmula deve retornar o
valor 5, resultado da soma da parte inteira de 2,5 com 3.

A B
1 2,5 =INT(A1)+3
As funções no Excel são divididas em dois tipos:

1. funções pré-definidas: estas funções ``vêm dentro'' do Excel. A função INT do


exemplo acima é uma função pré-definida. Há uma lista bastante grande destas funções,
mas não nos ocuparemos dela agora.

2. funções programadas: estas funções não existem ``dentro'' do Excel e nós precisamos
criá-las. Ou seja, precisamos programar a função para que depois possamos usá-la
numa planilha (ou numa outra função). Por exemplo, a função JurosSimples acima não
existe pré-definida e se quisermos usá-la precisaremos programá-la. Boa parte dos
próximos capítulos será dedicada a ensinar como se programa uma função. Vamos
agora começar a examinar os ingredientes necessários para a construção de uma função.

O primeiro passo necessário para construir uma função é criar um Módulo. Toda função
que definirmos deverá estar dentro de um módulo. Para criarmos um módulo no Excel
basta ativarmos o menu Inserir|Macro|Módulo (nas versões mais recentes do Excel
este procedimento pode ser diferente). Uma vez criado, o módulo passa a ser parte
integrante do documento, da mesma forma que as várias planilhas que compõem o
documento, e vai ser salvo e aberto junto com o documento.

Um módulo, tal como uma planilha, também possui um nome, que fica localizado na
aba na parte inferior da janela do Excel. Dentro do módulo podemos definir uma ou
mais funções. Todas as funções definidas nos módulos podem ser chamadas de qualquer
planilha do mesmo documento.

A definição de uma função possui 3 partes:

1. o cabeçalho: informa que estamos definindo uma função, qual o seu nome, quais são
seus parâmetros e que tipo de valor a função retorna.
2. o corpo da função: é a parte que define qual a computação que deverá ser processada
quando a função for chamada.
3. o término da função: indica que terminou a definição da função.

Uma outra função poderá ser definida logo em seguida. O formato genérico de uma
função é o seguinte:

Function NomeDaFunção( Param1 As Tipo, ..., ParamN As Tipo ) As Tipo


Aqui vem o corpo da função
NomeDaFunção = Valor de Retorno
End Function

As palavras em negrito são palavras reservadas da linguagem e devem aparecer desta


forma e nesta posição. A primeira linha é o cabeçalho; a última linha é o término. Tudo
que fica entre o cabeçalho e o término é o corpo da função. Note que imediatamente
antes do término da função colocamos a expressão de retorno da função. Vamos agora
detalhar os elementos que aparecem na definição da função. O cabeçalho da função
possui o formato genérico Function NomeDaFunção( Param1 As Tipo, ..., ParamN As
Tipo ) As Tipo. Um exemplo de cabeçalho de função é o seguinte: Function
JurosSimples( CapitalInicial As Double, Taxa As Double, NMeses As Integer ) As
Double. Neste exemplo, vemos que o nome da função é JurosSimples, e que a função
possui 3 parâmetros. Cada parâmetro é uma variável do programa, e está associado a um
tipo de dados. No exemplo, temos dois tipos de dados sendo usado: o tipo Double, que
indica que a variável deve ser tratada como um número real (com parte inteira e
fracionária); e o tipo Integer, que indica que a variável deve ser tratada como um
número inteiro. Os parâmetros são separados por meio de vírgulas. Note que a função
como um todo também está associada a um tipo de retorno, que é o tipo de dado
retornado pela função; no caso, o tipo Double. Note também que o cabeçalho foi
dividido em várias linhas.

Cada comando do programa (inclusive o cabeçalho) deve ser colocado inteiramente


numa linha. Quando isto não é possível, precisamos indicar que a próxima linha é, na
realidade, continuação da linha anterior. Fazemos isso colocando o símbolo de
sublinhado no final da linha.

Vejamos agora um programa completo que calcula juros simples:

Function JurosSimples( CapitalInicial As Double,


Taxa As Double, NMeses As Integer ) As Double
Dim CapitalAcrescido As Double
CapitalAcrescido = CapitalInicial * (Taxa/100) * NMeses
JurosSimples = CapitalInicial + CapitalAcrescido
End Function

A primeira observação é que o programa é basicamente uma manipulação de variáveis.


Neste programa, temos as seguintes variáveis: CapitalInicial, Taxa, NMeses,
CapitalAcrescido, JurosSimples. Varíaveis são os elementos do programa que
armazenam informações. A informação armazenada em uma variável é o seu conteúdo.
O nome da variável (por exemplo CapitalInicial no exemplo acima) é fixo, mas o seu
conteúdo pode mudar (daí o nome variável). Toda variável tem um tipo (Integer,
Double, etc.). As variáveis que constam no cabeçalho da função têm seu tipo declarado
no próprio cabeçalho. As variáveis internas devem ser declaradas com seus respectivos
tipos. No exemplo acima, temos a declaração Dim CapitalAcrescido As Double que
declara a variável interna CapitalAcrescido como sendo do tipo Double, ou seja, um
número real calculado usando dupla precisão. Para alterarmos o valor de uma variável,
usamos um comando de atribuição. Por exemplo, o comando CapitalAcrescido =
CapitalInicial * (Taxa/100) * NMeses no exemplo acima, que atribui o resultado da
expressão à variável CapitalAcrescido.

Observe que o comando de atribuição é diferente da igualdade algébrica com que


estamos habituados: por exemplo, os comandos

X=0

X=1

apresentados nessa sequência são perfeitamente coerentes, atribuindo o valor 0 à


variável X e posteriormente o valor 1 à mesma variável. Isso não é o mesmo que
afirmar que 0 = 1. Como um outro exemplo, o comando X = X+1 soma 1 ao valor atual
de X e atribui o resultado como novo valor de X. Obviamente, essa expressão não faria
sentido se a interpretássemos como uma indicação de igualdade.

Até aqui já utilizamos dois tipos de dados: números inteiros (Integer) e reais (Double).
Mais adiante também encontraremos o tipo String, que é o tipo de dados das variáveis
que armazenam texto. Também encontraremos o tipo Boolean, que é um tipo de dados
que possui apenas 2 dois valores: TRUE e FALSE.

Exercícios
1. Faça uma função CMparaPOL que recebe uma medida em centímetros e a devolve
em polegadas, onde 1 polegada = 2,54 cm. Faça também a função inversa POLparaCM,
que converte de polegadas para centímetros.

2.Considere um polinômio do segundo grau p(x) = a * x2 + b*x + c.


(a):Escreva uma função PDEX que recebe números reais (isto é, números do
tipo DOUBLE) a, b, c e x e calcula o valor de um polinômio do segundo grau.
Use uma variável interna que armazena o valor de x2.
(b) :Crie uma planilha com três colunas, que avalia o polinômio p(x) = x2 - 7*x +
12 para valores de x de 0 a 10. A primeira coluna contém os valores de x, a
segunda os de p(x) e a terceira escreve o texto ``Raiz'' caso p(x) seja 0; caso
contrário não escreve nada.

3.Considere uma equação do segundo grau a * x2 + b*x + c = 0.


(a):Escreva uma função DELTA, que recebe como parâmetros os números reais
a, b e c e retorna o valor do discriminante da equação, b2 -4ac.
(b):Crie uma planilha de 5 colunas. As três primeiras contêm os coeficientes da
equação do segundo grau. A quarta contém o valor do discriminante. A quinta
contém o texto:

• ``Uma única raiz'', se o discriminante for nulo.


• ``Nenhuma raiz real'', se o discriminate for negativo.
• ``Duas raizes reais'', se o discriminante for positivo.

(c):Invente valores para as três primeiras colunas que gerem os três tipos de
determinante. Insira uma sexta coluna que, no caso de discriminante nulo,
calcula esta raiz única, que será igual a -b/2a.
Comandos de Seleção (IF-THEN e IF-
THEN-ELSE)
Os comandos IF-THEN e IF-THEN-ELSE permitem selecionar quais os comandos que
serão executados dependendo de uma condição.

O comando IF-THEN tem o seguinte formato:

If Condição Then
Comando 1

Comando N
End If
Comando N+1

O comportamento do comando IF-THEN é o seguinte: primeiramente a condição é


avaliada, podendo resultar em dois valores: TRUE (verdadeiro) ou FALSE (falso). Se a
condição for verdadeira, os comandos 1 até N serão executados e, em seguida, o
comando N+1. Se a condição for falsa, nenhum dos comandos de 1 a N será executado e
o programa irá diretamente para o comando N+1. Por outro lado, o comando IF-THEN-
ELSE tem o seguinte formato:

If Condição Then
Comando 1

Comando N
Else
Comando N+1

Comando N+M
End If
Comando N+M+1

O comportamento do comando IF-THEN-ELSE é o seguinte: A condição é avaliada; se


ela for verdadeira, os comandos de 1 até N serão executados; se a condição for falsa, os
comandos de N+1 a N+M serão executados. Em ambos os casos, o comando posterior a
ser executado será o comando N+M+1.

Vejamos como exemplo o cálculo de juros progressivos em um investimento financeiro.


Se a conta contém um saldo inferior a R$10.000,00, então o banco paga juros mensais
de 2%. Para saldo superiores a R$10.000,00 o banco paga 3%. A função
TaxaProgressiva1 calcula o saldo da conta no final de um mês.

Function TaxaProgressiva1 (Saldo As Double) As Double


'saldo ao fim de um mes
'com taxa progressiva
'Declaracoes
Dim Taxa As Double

'Descobre o valor da taxa


If Saldo < 10000 Then
Taxa = 0.02
Else
Taxa = 0.03
End If
'Retorno da funcao
TaxaProgressiva1 = Saldo * (1+ Taxa)
End Function

Outra forma de se computar exatamente a mesma função:

Function TaxaProgressiva2 (Saldo As Double) As Double


'saldo ao fim de um mes
'com taxa progressiva

'Declaracoes
Dim Taxa As Double
Dim Acrescimo As Double

'Descobre o valor da taxa


If Saldo < 10000 Then
Taxa = 0.02
Acrescimo = Saldo * Taxa
Else
Taxa = 0.03
Acrescimo = Saldo * Taxa
End If
'Retorno da funcao
TaxaProgressiva2 = Saldo + Acrescimo
End Function

Conforme vimos no exemplo acima, as expressões condicionais são formadas por


comparadores (o símbolo < no exemplo acima).

Uma expressão condicional simples tem o formato Expressão Aritmética comparador


Expressão Aritmética. Os comparadores lógicos podem ser:

• = (igual a)
• < (menor que)
• > (maior que)
• <= (menor ou igual a)
• >= (maior ou igual a)
• <> (diferente)

Desta forma, podemos formar expressões condicionais como (X + 2 <= Y*Z).


As expressões condicionais simples podem ser combinadas para formarem expressões
condicionais compostas. Temos os seguintes combinadores lógicos:

• AND (conjunção)
• OR (disjunção)
• NOT (negação)

Por exemplos, uma expressão condicional que testa se uma variável X está entre os

valores MIN e MAX (inclusive) é

Se quisermos verificar se Y NÃO está entre MIN e MAX, podemos fazê-lo de duas

formas: ou .
Retomando o exemplo dos juros progressivos, se a conta contiver um saldo inferior a
R$10.000,00 então o banco pagará juros mensais de 2%. Para cada R$5.000,00
adicionais acima de R$10.000,00 o banco pagará 0,5% a mais, até atingir a taxa limite
de 4%. A função TaxaProgressiva3 fica:

Function TaxaProgressiva3 (Saldo As Double) As Double


'saldo ao fim de um mes
'com taxa progressiva
'Declaracoes
Dim Taxa As Double
'Descobre o valor da taxa
If Saldo < 10000 Then
Taxa = 0.02
ElseIf Saldo < 15000 Then
Taxa = 0.025
ElseIf Saldo < 20000 Then
Taxa = 0.03
ElseIf Saldo < 25000 Then
Taxa = 0.035
Else
Taxa = 0.04
End If
'Retorno da funcao
TaxaProgressiva3 = Saldo * (1+ Taxa)
End Function

Exercícios
1. Considere a seguinte classificação de consumidores, baseada na percentagem do
salário gasto com itens da cesta básica:
Esbanjador até 25% (inclusive)
Gastador entre 25% e 53% (inclusive)
Comedido entre 53% e 75% (inclusive)
Essencial entre 75% e 95% (inclusive)
(a) Fazer um programa ClassificaConsumo, que recebe um número de 0 a 100
(real), representando a percentagem do salário gasta por uma família com itens
da cesta básica, e retorna uma cadeia (string), contendo a classificação
correspondente.
(b) Fazer uma planilha com duas colunas. Na primeira, a percentagem do salário
gasta por uma família com itens da cesta básica, que deve ir variando de 0 a
100% em intervalos de 10%. A segunda coluna contém a classificação.
(c) O que acontece com 100%?

2.Na vida real, as fronteiras de classificação são menos definidas. Suponha que nós
tenhamos a seguinte classificação, ``com buracos'':
Esbanjador até 20%
Gastador entre 25% e 45%
Comedido entre 53% e 75%
Essencial entre 80% e 95%
(a) Fazer um programa ClassificaConsumo2 tal que, se algum percentagem for
fornecida que não é coberta pelos intervalos acima, o programa deve fornecer a
cadeia "INDEFINIDO".
(b) Fazer uma planilha semelhante à do exercício anterior.

3.Considere uma equação do segundo grau (a * x2 + b*x + c = 0). Utilizando a função


DELTA desenvolvida nos exercícicios do capítulo anterior, escreva um programa que
calcula a(s) raíz(es) desta equação, tal que:
(a) Se não houver raízes (Delta < 0), o programa retorna -9999.
(b) Se houver uma única raiz (Delta = 0), o programa retorna o valor da raiz
única igual a -b/2a.
(c) Se houver duas raízes (Delta 0) o programa calcula as duas raízes: (x1 = ( -b -
SQRT(Delta) )/ (2*a)) e (x2 = ( -b + SQRT(Delta) )/ (2*a))onde SQRT(X) é uma
função pré-definida que calcula a raiz quadrada. O programa deve retornar a
maior das duas raízes.

Crie uma planilha de 4 colunas. As três primeiras contêm os coeficientes da


equação do segundo grau. A quarta contém o valor da maior raiz.
Comando de Iteração (DO WHILE-
LOOP)
A idéia básica da iteração é fazer com que uma série de comandos seja repetida
enquanto uma determinada condição for verdadeira; quando a condição se tornar falsa, a
repetição termina.

O comando básico de iteração (embora não seja o único comando capaz de iterar) é o
comando DO WHILE-LOOP. Este comando possui o seguinte formato:

Do While Condição
Comando 1

Comando N
Loop
Comando N+1

A região entre o início do comando, em Do While, e seu fim, em Loop, é chamada de


malha, laço, ciclo ou, no original em inglês, ``loop''.

O comportamento do comando DO WHILE-LOOP é o seguinte: inicialmente a


condição é testada. Se for falsa, nenhum comando dentro da malha é executado, e a
execução prossegue no comando N+1. Se a condição for verdadeira, o programa
prossegue executando um a um os comandos de 1 a N. Ao terminar o comando N, ou
seja, ao atingir a instrução Loop, o programa volta ao início da malha e testa a condição
novamente. Se ela continuar verdadeira então novamente são executados os comandos
de 1 a N; caso contrário, a iteração termina e o programa sai da malha e prossegue a
partir do comando N+1.

Desta forma, a condição de entrada controla quantas vezes a iteração será repetida.
Enquanto ela permanecer verdadeira, o interior da malha será repetido. Pode ser que ela
nunca fique falsa; isso quer dizer que o programa não pára nunca, e é um programa
defeituoso. Portanto, bastante cuidado com o uso da iteração.

Por exemplo, vejamos o programa elevadoa(X,Y) que calcula XY. A idéia básica é
multiplicar o número X por ele mesmo Y vezes, ou seja:

XY = 1 * X * ... * X onde X aparece Y vezes.

O valor 1 aparece como um valor inicial e, obviamente, não influencia o resultado final.
Além disso, a presença do número 1 no cáculo garante que o resultado seja correto
mesmo quando Y = 0, pois nesse caso X0 = 1:

Function elevadoa(Num As Integer, expoente As Integer) As Integer


Dim cont As Integer
Dim result As Integer
'Inicialização
result = 1
cont = 0
'Malha principal
Do While cont < expoente
result = result * Num
cont = cont + 1
Loop
'Finalização
elevadoa = result
End Function

Vejamos agora como calcular o fatorial de um número inteiro N, normalmente


representado por N!:

N! = N * N-1 * N-2 * ... * 2 * 1

Uma das formas possíveis para computarmos o fatorial de um número é procedermos da


direita para a esquerda, ou seja, começamos com um contador com o número 1, vamos
incrementado-o e armazenado o valor da multiplicação em um acumulador de
resultados intermediários, da seguinte forma: a cada passo da iteração, incrementamos o
contador e multiplicamos esse valor pelo acumulador, armazenando o resultado no
próprio acumulador. O processo continua até que o contador alcance o valor de N.
Nesse instante o acumulador terá o valor do fatorial desejado:

Function fatorial(Num As Integer) As Integer


Dim cont As Integer
'contador do numero atual
Dim result As Double
'acumulador do resultado parcial
'Inicialização
result = 1
cont = 1
'Malha principal
Do While cont <= Num
result = result * cont
cont = cont + 1
Loop
'Finalização
fatorial = result
End Function

Vamos estudar o caso agora de juros compostos com uma taxa de juros que varia
progressivamente com o tempo, em incrementos fixos. Por exemplo, podemos ter uma
taxa de juros inicial de 2% e incrementos de 0.1% mensais: no primeiro mês a taxa de
juros será de 2%, no segundo será 2,1%, etc. até o décimo-primeiro mês, quando será de
3%. Um dado capital inicial deverá sofrer juros compostos (acumulados) onde a taxa
mensal varia progressivamente. Uma função que calcula o capital acumulado ao final de
vários meses é a seguinte:

Function JurosProgr(CapIni As Double,TaxaIni As Double,IncrTaxaMensal As


Double,NMeses As Integer) As Double
'Computa o capital final com juros progressivos: a taxa de juros
'vai sendo incrementada mensalmente pelo valor IncrTaxaMensal (que
'pode ser negativo!!!)
Dim mes As Integer
'Número de meses desde o início do investimento
Dim TaxaAtual As Double
'Taxa do mes corrente
Dim CapAtual As Double
'Capital ao final do mes corrente
'Inicialização
CapAtual = CapIni
'Capital no iníco do primeiro mês
TaxaAtual = TaxaIni
'Taxa no início primeiro mês
mes = 1
'Primeiro mes

'Malha principal
Do While mes <= NMeses
'Calcula o capital no final do mês corrente
CapAtual = CapAtual * (1 + TaxaAtual / 100)
'Próximo mês
mes = mes + 1
'Calcula a taxa do próximo mês
TaxaAtual = TaxaAtual + IncrTaxaMensal
Loop
'Retorno da função
JurosProgr = CapAtual
'Capital ao fim de NMeses
End Function

Exercícios
1. Fazer um programa que calcule a soma dos N primeiros números inteiros: 1 + 2 + 3 +
... + N

Fazer uma planilha que testa este programa para valores de N= 1, 5, 10, 15, 25

2. Fazer uma função S(N) que calcule a seguinte soma para N termos:

Fazer uma planilha que testa este programa para valores de N= 1, 5, 10, 15, 25.

3. Dados dois inteiros positivos N e P, escreva uma função que calcula a combinação de
N sobre P:
Note que tanto o numerador quando o denominador possuem P fatores. A

combinação de N sobre P pode ser também expressa por .


Computacionalmente, a primeira versão é a mais eficiente, voce sabe explicar
por quê? (Dica: conte o número de iterações em cada caso). A função deve

retornar 1 se .

Fazer uma planilha para N=10 e P variando de 0 a 15.

4.
(a) Fazer uma função PA(N,A1,R) que calcula o N-ésimo termo de uma
progressão aritmética de termo inicial A1 e razão R. Lembre-se de que Ai = R +
Ai-1.
(b) Fazer uma função PG(N,A1,R) que calcula o N-ésimo termo de uma
progressão geométrica de termo inicial A1 e razão R. Lembre-se de que Ai = R *
Ai-1.
Subrotinas, Macros, Entrada e Saída de
dados
Até agora vimos apenas programas no formato função. Funções possuem as seguintes
propriedades:

• Para acioná-las, podemos inserir uma chamada dentro de uma fórmula de uma
planilha. No entanto, não sabemos (ou não temos como) chamar uma função
``de fora'' da planilha.
• A única forma de passar dados para uma função é através dos parâmetros de
entrada (veremos mais adiante que isso pode ser relaxado um pouco, mas, de
qualquer forma, os dados obtidos por uma função vão sempre se originar da
planilha).
• A única forma de uma função passar dados de volta para a planilha é através de
um (único) valor ao final da computação.

Vamos agora ver uma forma de ativar programas de maneira independente de uma
planilha, obter informações de ``fora'' da planilha e poder não retornar nenhum valor, e
comunicar resultados ao usuário por meio de janelas.

A isso se dá o nome de subrotina ou procedimento. Uma subrotina possui o seguinte


formato

Sub NomeSub( <Lista de Parâmetros> )

End Sub

Subrotinas diferem de funções por não retornarem um valor. Por isso, não associamos
um tipo de dados às subrotinas. Tampouco podemos utilizar o nome da subrotina como
variável.

Uma classe especial de subrotinas que nos é muito interessante é a classe de subrotinas
em que a lista de parâmetros é vazia. Neste caso, a subrotina é chamada de macro e
pode ser ativada de forma independente da planilha.

A ativação de macros é feita acionando-se o menu Ferramentas|Macros, que fará


aparecer uma janela contendo uma lista de todas as macros existentes nos módulos do
programa. Como não há passagem de parâmetros para macros, basta selecionar uma
macro nesta lista, e acionar o botão Executar.

Mas se não há passagem de parâmetros nem retorno de valor, como passar e receber
dados de uma macro? Para isso, o código da macro precisa acionar comandos de
entrada e saída, que gerarão janelas de comunicação através das quais se fará a
passagem da informação. Se quisermos entrar com algum dado, deveremos inserir na
subrotina uma chamada à função via InputBox, da seguinte maneira:

Texto = InputBox( ``Entre com um valor'' )


Ao executarmos este comando, primeiramente aparecerá uma janela contendo:

• o texto ``Entre com um valor'' enviando uma mensagem ao usuário;


• um campo em branco para ser preenchido;
• e um botão de OK.

Deveremos preencher o campo em branco e então clicar no botão (ou apertar ENTER).
O String digitado no campo será atribuído à variavel Texto, que deverá, portanto, ser
do tipo String.

Se desejarmos ler um valor numérico ao invés de String, o valor inserido será


convertido para o tipo apropriado. Para isso, utilizamos as duas funções pré-definidas
CDbl(String) e CInt(String) que convertem o parâmetro String respectivamente em
um valor equivalente do tipo Double ou Int.

Em geral, fazemos a chamada a InputBox e a conversão por CDbl ou CInt num


mesmo comando, como mostra o exemplo abaixo:

Dim Nprods As Integer


Dim Preco1 As Double

Nprods = CInt( InputBox( ``Entre a quantidade de produtos:'' ))


Preco1 = CDbl( InputBox( ``Preço do primeiro produto'' ))

que terá o efeito de primeiro mostrar uma janela de diálogo cujo valor preenchido
deverá ser o número de produtos, e em seguida uma outra caixa de diálogo que deverá
ser preenchida com o preço do primeiro produto.

Além de solicitar dados ao usuário, uma macro pode exibir alguma informação, por
exemplo o resultado de alguma computação. Esta comunicação pode ser feita na forma
de uma janela que mostra o texto ao usuário e um botão de OK que o usuário pode
clicar ao terminar de ler a mensagem.

O comando que faz isso é o comando MsgBox(String), que mostra o conteúdo do


String ao usuário em uma janela. Por exemplo, supondo que a variável MIN é do tipo
Double e contém o valor 27,32,

MsgBox( ``O melhor preço é: '' & MIN )

faz aparecer uma janela com a mensagem:

O melhor preco é: 27,32

Se quisermos que a mensagem exibida seja quebrada em diversas linhas, devemos


incluir nos pontos desejados o caracter que codifica o comando ``mude de linha''. Por
exemplo,

MsgBox( ``Isto aqui é uma'' & Chr(13) & ``linha quebrada.'' )

produz como resultado:


Isto aqui é uma
linha quebrada.

Vejamos por exemplo a macro SomaNum que nos solicita 4 valores (representando por
exemplo preços de vários produtos para um pedido de compra) e calcula a sua soma:

Sub SomaNum()
Dim Soma As Double
Dim Cont As Integer
Dim Valor As Double
'Inicialização
Soma = 0
Cont = 0
Valor = 0 '(Desnecessário, apenas ajuda a entender o programa)
Do While Cont < 4
'Le novo valor, convertendo-o para Double
Valor = CDbl(InputBox(``Entre com o valor ''))
'Atualiza a soma
Soma = Soma + Valor
'Prepara a próxima iteração
Cont = Cont + 1
Loop
'Apresenta resposta
MsgBox (``A soma é: '' & Soma)
End Sub

Esta macro pode ser ``embelezada'' de forma a não ficar presa a um número fixo de
valores nos solicitando, no início da execução, qual o número desejado de valores.
Também podemos ``embelezar'' a solicitação dos valores, indicando a posição na
seqüência de cada valor. Desta forma, criamos SomaNum1:

Sub SomaNum1()
Dim Soma As Double
Dim Cont As Integer
Dim Valor As Double
Dim N As Integer
'Inicialização
Soma = 0
Cont = 0
Valor = 0 'Desnecessário
N = CInt(InputBox(``Número de valores a serem somados: ''))
Do While Cont < N
'Le novo valor, convertendo-o para Double
Valor = CDbl(InputBox(``Entre com o valor '' & (Cont + 1)))
'Atualiza a soma
Soma = Soma + Valor
'Prepara a próxima iteração
Cont = Cont + 1
Loop
'Apresenta resposta
MsgBox (``A soma dos '' & N & `` valores é: '' & Soma)
End Sub

Podemos sofisticar ainda mais este programa, nos liberando de dizer no início quantos
valores iremos entrar. Podemos assumir que todos os valores são positivos e assim, ao
entrarmos um número negativo, estaremos encerrando a seqüência de preços. Assim,
criamos SomaNum2:

Sub SomaNum2()
'Calcula a soma até encontrar um número menor ou igual a 0.
Dim Soma As Double
Dim Valor As Double
'Inicialização
Soma = 0
Valor = CDbl(InputBox(``Entre com um valor.'' & Chr(13) & ``[Valor negativo para
terminar]''))
'Chr(13) é o caracter para mudar de linha
Do While Valor > 0
'Atualiza a soma
Soma = Soma + Valor
'Prepara a próxima iteração
'Le novo valor, convertendo-o para Double
Valor = CDbl(InputBox(``Entre com um valor.'' & Chr(13) & ``[Valor negativo para
terminar]''))
Loop
'Apresenta resposta
MsgBox (``A soma dos valores é: '' & Soma)
End Sub

Para finalizar, mostramos um programa que solicita 4 preços do usuário e retorna o


menor:

Sub MelhorPr()
Dim Min As Double
'menor preço até o momento
Dim Preco As Double
'valor do produto atual
Dim Cont As Integer
'contador de produtos
'Inicialização
Min = 9E+99 'Este eh um valor muito alto: 9*1099
Cont = 0
MsgBox (``Você deverá entrar com o preço de'' & Chr(13) & ``um produto para quatro
fornecedores.'')
Do While Cont < 4
'Lê o preço do produto, convertendo-o para Double
Preco = CDbl(InputBox( ``Preço do produto do fornecedor '' & (Cont + 1) & ``:'' ))
'Verifica se preço é menor que o mínimo atual
If Preco < Min Then
Min = Preco 'Novo valor mínimo encontrado
End If
'Prepara próxima iteração
Cont = Cont + 1
Loop
'Fornece a resposta
MsgBox (``O menor preço é: '' & Min)
End Sub

Exercícios
1. Altere MelhorPr para aceitar um número qualquer de preços.
2. Fazer uma macro que lê N valores e apresenta a soma dos valores positivos apenas.
3. O Departamento de Contabilidade Forênsica da Universidade Municipal de Uauá
(BA) estuda casos famosos de fraude bancária. O mundialmente famoso Teste de Uauá
realiza o seguinte procedimento:
Dado um capital inicial, uma taxa mensal de juros e um capital final, determinar
se é consistente que o capital final foi obtido ao longo do tempo a partir do
capital inicial sob juros compostos.
Fazer uma macro que realiza o Teste de Uauá. No caso de consistência
detectada, indicar o número de meses necessários para gerar o capital final. No
caso de inconsistência, apenas mostrar em uma janela a mensagem ``Fraude
detectada''.

4. Fazer uma macro que, lê o número N de alunos matriculados em Introdução à


Contabilidade Forênsica e suas notas na primeira prova, e calcula:

• A média da turma.
• A maior nota.
• A menor nota.
Simulação de Programas
Para simular um programa no computador você deverá proceder da seguinte maneira:

1. Ativar a barra de ferramentass de programas. Normalmete, a barra de ferramentas de


programas é ativada quando criamos um módulo (é aquela janelinha, com botõezinhos
de mãozinha, oculinhos, etc). Caso esta não esteja ativa, você deverá ativá-la através do
menu ``Exibir|Barras de Ferramentas'', selecionando ``Programa''.
2. Marcar a parada no inicio do programa. Coloque o cursor em cima do cabeçalho da
função ou procedimento que você deseja simular. Em seguida, com o mouse, acione na
barra de ferramentas de programas o botão da mãozinha (que significa: pare). O
cabeçlho deve ficar com fundo vermelho.

Neste ponto, já se pode acionar o programa, que deverá ativar uma janela de
depuração e parar no início da função/procedimento marcado.

3. Selecionar variáveis que serão observadas na simulação. Para isso, marcar a variável
(uma expressão também pode ser marcada e observada). Em seguida, na barra de
programa, clicar no oculinhos e pedir para adicionar a variável. Selecionar a aba de
``Inspecionar'' para ver as variáveis selecionadas.
4. Simular. Para isso, os dois últimos botões da barra de programas podem ser usados (a
diferença entre eles está na ativação de outras funções e procedimentos de dentro de um
programa, como veremos mais adiante.

Na simulação, o comando (linha) selecionado será aquele ainda por executar. Após a
execução de cada comando, o valor das variáveis inspecionadas pode mudar. No
término do programa, a janela de depuração desaparece.

O Tipo de dados Boolean

O tipo de dados chamado de Booleano possui apenas dois valores: TRUE e FALSE.
Uma variável pode ser declarada como booleana assim:

Dim Teste As Boolean

Esta variável pode receber um valor booleano:

Teste = True

Uma variável booleana pode aparecer em expressões nos lugares onde uma condição
poderia aparecer. Por exemplo:

If Teste Then

Essa expressão equivale a:

If Teste = TRUE Then


Vejamos por exemplo uma função que executa o Teste de Uauá (ver exercícios do
capítulo anterior). Este teste recebe como parâmetros um capital inicial, uma taxa de
juros e um capital final. O teste retorna um valor booleano: Verdadeiro se é possivel que
o capital final foi alcançado por meio de juros compostos aplicados ao capital inicial na
taxa indicada; Falso em caso contrário.

Function TesteUaua(CapIni As Double, Taxa As Double, CapFim As Double) As


Boolean
' Testa se é plausível que CapFim tenha sido obtido
' a partir de CapIni sob juros compostos com Taxa mensal
Dim CapAtual As Double 'Capital até o momento
Dim NMeses As Integer 'Número de meses
Dim Resultado As Boolean
'Inicialização
CapAtual = CapIni
NMeses = 1
Resultado = False 'Começa assumindo teste falso
'Principal
Do While CapAtual <= CapFim
'Testa o sucesso do resultado
If CapAtual = CapFim Then
Resultado = True
End If
'Prepara próxima iteração
CapAtual = CapAtual * (1 + Taxa)
NMeses = NMeses + 1
Loop
'Retorno
TesteUaua = Resultado
End Function

Podemos simular este programa no computador. Tente a seguinte chamada da planilha:


=TesteUaua(1000;0,1;1331) e =TesteUaua(1000;0,1;1300).

Um segundo exemplo: vamos fazer uma macro que lê uma sequência de inteiros
positivos e informa ao usuário se esta sequência está em ordem crescente. A seqüência é
terminada por um número menor que zero.

Sub EmOrdem()
' Lê uma sequência de inteiros positivos e informa ao usuário
' se esta sequência está em ordem crescente
Dim Atual As Integer
Dim Velho As Integer
Dim AindaEmOrdem As Boolean
'Inicializações
AindaEmOrdem = True
Atual = CInt(InputBox(``Entre com um inteiro:''))
Velho = Atual 'Velho inicia com o mesmo valor que atual
'Principal
Do While Atual >= 0
If AindaEmOrdem And (Atual < Velho) Then
'Teste falhou
AindaEmOrdem = False
End If
'Prepara a próxima iteração
Velho = Atual
Atual = CInt(InputBox(``Entre com mais um inteiro:''))
Loop
If AindaEmOrdem Then
MsgBox(``Seqüência em ordem.'')
Else MsgBox(``Desordenado.'')
End If
End Sub

Teste esse programa para as seqüências 1, 3, 7, 22, -1 e 1, 7, 2, 4, -23.

Exercícios
1. Alterar o programa acima para parar e dar a resposta assim que descobrir que a
seqüência não está em ordem.
2. Simular no computador as suas soluções para os exercícios 1 e 2 do capítulo 5, para
os valores de N=5 e N=6.
3. O resto da divisão inteira de X por Y é calculada por X MOD Y. O número X é
divisível por Y se X MOD Y = 0. Neste caso, também dizemos que X é um mútiplo de Y.

Pede-se construir uma função MaxMultiplo(MIN,MAX,DIV) que encontra o


maior múltiplo de DIV entre MIN e MAX. Resolver este problema de duas
maneiras:

• Ir testando todos os números a partir de MIN e armazenar o múltiplo


mais recentemente encontrado, até testar todos os números entre MIN e
MAX.
• Começar testando os números de maneira decrescente a partir de MAX.
Ao encontar o primeiro múltiplo de DIVpodemos parar, pois este será o
maior divisor no intervalo.

Simular para MaxDivisor(5,10,3) e MaxDivisor(10,20,4).

Fazer uma planilha para MaxDivisor(0,100, X) onde X varia de 11 a 31, de 2 em


2.

4. Numa conta bancária, as movimentações de débito são representadas por números


negativos e as movimentações de crédito por números positivos. Fazer uma macro que
lê as movimentações de uma conta em um dia e:

• calcula, separadamente, o total de créditos e débitos;


• lê o saldo no início do dia e calcula o saldo no início do próximo dia.
Você pode escolher entre solicitar, no início, o número de movimentações, ou
usar algum valor especial (muito grande) como sinal de parada.

Simular para 5 valores, 2 de crédito e 3 de débito.


Leitura e Escrita de Planilhas por
Programas
Até agora, a única forma de comunicação vista entre uma planilha e uma função é a
passagem de parâmetros. No entanto, podemos querer que uma função leia um dado de
uma planilha sem que tenhamos que explicitamente passar o valor para o programa. Por
exemplo, se quisermos somar os valores positivos de uma coluna:

A B
1 Produto Quantidade em Estoque
2 Vassoura 125
3 Rodo -2
...
53 Esfregão 12

Neste caso, vamos pensar que a planilha é uma Matriz de dimensão 2x2. A posição
(I,J) da matriz corresponde à linha I e à coluna J. Por exemplo, na planilha acima, a
posição (2,1) contém o valor ``Vassoura'' de tipo String e a posição (53,2) possui o valor
12 de tipo inteiro (ou double).

De maneira geral o valor da planilha que fica na posição de interseção da linha I com a
coluna J pode ser lido através do comando Valor = Cells( I, J ).

Um programa que lê a soma dos itens em estoque (só os itens positivos, pois os itens
negativos indicam falta de produto) pode ser o seguinte:

Function ItensEmEstoque() As Integer

'Este é um programa que conta o número de itens em


'estoque conforme armazenado na segunda coluna da Planilha.

Dim Soma As Integer 'Soma de itens em estoque


Dim Valor As Integer 'Valor da linha atual
Dim I As Integer 'Indice da linha
'Inicializacões
Soma = 0
I = 2 'Começamos na segunda linha
Valor = 0
'Principal
Do While I <= 53 'Terminamos na linha 53
'Lê o valor da Planilha
Valor = Cells( I, 2 ) 'Valor lido na linha I, coluna 2
'Atualiza soma
If Valor > 0
Soma = Soma + valor
End If
'Próxima linha
I=I+1
Loop
'Retorno
ItensEmEstoque = Soma
End Function

Suponhamos agora que não sabemos a priori qual a última linha da coluna de valores.
Há uma forma de saber se uma posição está vazia numa planilha, usando a função
IsEmpty() . Por exemplo, a condição IsEmpty( cells( I, J ) ) retorna True se a célula
(I,J) está vazia e retorna False se algo estiver escrito nela.

O programa anterior pode ser reescrito, sem limite de linhas, como:

Function ItensEmEstoque1() As Integer


'Este é um programa que conta o número de itens em
'estoque conforme armazenado na segunda coluna da Planilha.
Dim Soma As Integer 'Soma de itens em estoque
Dim I As Integer 'Indice da linha
'Inicializacoes
Soma = 0
I = 2 'Começamos na segunda linha
Valor = 0
'Principal
Do While Not IsEmpty(Cells(I,2)) 'Terminamos na linha vazia
'Atualiza soma
If Cells( I, 2 ) > 0
Soma = Soma + Cells( I, 2 )
End If
'Próxima linha
I=I+1
Loop
'Retorno
ItensEmEstoque = Soma
End Function

Escrita de dados na planilha não pode ser feita a partir de funções, apenas a partir de
subrotinas. Isto porque as funções não possuem autorização para mudar a planilha,
apenas para lê-las e retornar um único valor.

Para escrever um valor na posição (I,J) da planilha, é preciso usar o comando cells( I, J
) = <valor>. Se quisermos simplesmente apagar um valor contido numa célula,
podemos usar cells( I, J ) = Empty.

Para exemplificar este fato, uma planilha resumindo as movimentações bancárias de


diversos clientes:

A B C D
1 Nome Saldo Anterior Crédito Débito Saldo Atual
2 Aarão 132,45 12,12 4321,12
3 Abel -987,65 78,90 56,56
...

Vamos preencher a coluna de Saldo Atual = Saldo Anterior + Crédito - Débito.

Sub SaldoAtual()
' Saldo Anterior na coluna 2
' Credito na coluna 3
' Débito na coluna 4
' Saldo atual na coluna 5
Dim Anterior As Double
Dim Credito As Double
Dim Debito As Double
Dim Atual As Double
Dim I As Integer 'Contador das linhas
I = 2 'Primeira linha
'Não há necessidade de inicialização pois as
' variáveis internas são lidas no início de cada ciclo
Do While Not IsEmpty( Cells(I,1) )
'Lê dados da planilha
Anterior = Cells( I, 2)
Credito = Cells( I, 3)
Debito = Cells( I, 4)
Atual = Anterior + Credito - Debito
'Escreve dados na Planilha
Cells(I, 5) = Atual
'Próxima Linha
I=I+1
Loop
End Sub

Note que poderíamos dispensar todas as variáveis internas (exceto I), sendo que as 5
primeiras atribuições do loop ficariam comprimidas em um único (e quase
incompreensível) comando:

Cells(I, 5) = Cells( I, 2 ) + Cells( I, 3 ) - Cells( I, 4 )

Exercícios
1. Considere uma planilha que descreve para cada produto, a quantidade em estoque, o
estoque mínimo e o estado do estoque.
A B C D
1 Produto Quantidade em Estoque Estoque Mínimo Status
2 Vassoura 125 100
3 Rodo 2 10
...
53 Esfregão 12 20

Fazer uma macro que escreve na coluna de Status escreve ``OK'' se o estoque
existente for maior que o estoque mínimo, ou escreve ``ATENÇÃO!!!'' se o
estoque estiver abaixo do mínimo. Resolver o problema em dois casos:

• Para 52 produtos, como mostra a figura.


• Para um número indefinido de produtos, send que o último produto é
sinalizado por uma linha vazia.

Por exemplo, sua macro deve alterar a planilha acima para:


A B C D
1 Produto Quantidade em Estoque Estoque Mínimo Status
2 Vassoura 125 100 OK
3 Rodo 2 10 ATENÇÃO!!!
...
53 Esfregão 12 20 ATENÇÃO!!!

2. Fazer uma macro que copia uma coluna de um lugar para outro da planilha. Assumir
que:

• a coluna origem e a coluna destino são requisitadas ao usuário via


InputBox.
• As colunas são descritas por números inteiros, ex: 1=A, 2=B, etc
• Os dados da coluna começam na linha 1
• Os dados da coluna terminam com uma linha vazia.

Fazer uma macro para cada um dos dois casos abaixo:

• a coluna de origem NÃO é apagada (Copiar).


• a coluna de origem é apagada (Mover).

Por exemplo, no primeiro caso, se pedimos a cópia da coluna origem 1 para a


coluna de destino 3, devemos transformar a planilha:
A B C
1 10 2
2 3 1
3 -7
4
na planilha
A B C
1 10 2 10
2 3 3
3 -7 -7
4
Utilizando Funções e Macros Auxiliares
O objetivo desse capítulo é mostrar como resolver um problema computacional
razoavelmente grande, dividindo-o em problemas menores: ao encarar um problema
computacional, vamos utilizar funções e macros auxiliares que resolverão parte do
problema. Em seguida, vamos criar outros programas que utilizam estas pequenas
soluções para compor soluções maiores, e desta forma comporemos soluções
progressivamente mais complexas.

Vamos supor que nós temos a seguinte planilha, que realiza o controle de estoque de
uma empresa.

A B C D
PRODUTO Em Estoque Estoque Mínimo Pedido de Compra
1 Vassoura 12 100
2 Rodo 120 70
3 Esfregão 5 50
...

Cada produto em estoque está associado a um estoque mínimo. Vamos fazer um


programa que, ao detectar um produto cuja quantidade em estoque está abaixo do
mínimo, decide quantas unidades devem ser compradas para restabelecer o estoque
mínimo.

Por onde começamos?

A idéia inicial é formular a solução do problema de forma esquemática, que servirá de


guia para dividir este problema em problemas menores. Basicamente, o que o programa
deve fazer é o seguinte:

0. Para cada linha da planilha:


1. Descobrir o quantidade de itens faltantes no estoque
2. Atualizar a coluna Pedido com o valor calculado

Esta descrição serve de ``esqueleto'' para o desenvolvimento. O item 2 nós sabemos


fazer: é só usar cells(linha,coluna) = valor, onde o valor foi calculado no item 1. Então
vamos supor que há uma função que, para uma dada linha, calcula o valor faltante no
estoque. A nossa representação esquemática pode ser refinada para:

0. Para cada linha da planilha:


1. valor = RepoeEstoque( linha )
2. cells( linha, ``coluna do Pedido de Compra'' ) = valor

Então vamos escrever a função RepoeEstoque que calcula a quantidade de estoque que
precisa ser reposta.
Const ColunaProd = 1 'cria um ``apelido'' (ColunaProd) para a Constante 1
Const ColunaEs = 2
Const ColunaMin = 3
Const ColunaPed = 4
Const ColunaUnit = 5
Const ColunaCusto = 6
Function RepoeEstoque(Linha As Integer) As Integer
'Este programa descobre qual a quantidade de produto
' necessária em um pedido de compra para que o estoque
' atual iguale o estoque mínimo na Linha da planilha
Dim emEstoque As Integer
Dim estoqueMin As Integer
Dim faltando As Integer
'Inicializações
emEstoque = Cells(Linha, ColunaEs)
estoqueMin = Cells(Linha, ColunaMin)
faltando = 0 'Assume inicialmente que estoque está OK
'Principal
If emEstoque < estoqueMin Then
faltando = estoqueMin - emEstoque
End If
RepoeEstoque = faltando
End Function

Inicialmente, note as primeiras linhas na forma

Const <NOME> = <VALOR>

Este comando declara uma Constante, que pode ser usada em qualquer parte do módulo
em lugar do número. E para que usar constantes? Em primeiro lugar, porque o programa
fica mais claro (ColunaMin é muito mais expressivo que o número 3 para sabermos a
que este número se refere). Em segundo lugar, se houver várias ocorrências da constante
no programa, para mudar seu valor basta alterar o valor associado a ela na declaração
Const. Sem usar Const, teríamos que sair ``caçando'' as ocorrênicas do número e alterá-
la no corpo do programa. No exemplo, usamos Const para o número das colunas, uma
mudança de ordem nas colunas da planilha necessita apenas uma mudança nas
declarações Const. (Dê uma olhada no programa e imagine como seria fácil
cometermos um erro se não usássemos Const).

A função RepoeEstoque recebe como único parâmetro o número da linha corrente, e


retorna 0 se não há estoque a repor. Ela é uma função bastante ordinária, sem nada de
especial.

Especial é o fato de podermos utilizá-la como função auxiliar para resolver o problema
de atualização da coluna de Pedido de compra na planilha. O resultado final almejado é
uma macro que transforme a planilha inicial na seguinte planilha

A B C D
PRODUTO Em Estoque Estoque Mínimo Pedido de Compra
1 Vassoura 12 100 88
2 Rodo 120 70
3 Esfregão 5 50 45
...

A macro que faz esta transformação (usando RepoeEstoque) é a seguinte:

Sub PedidoCompra()
'Monta o pedido de compra para toda a planilha
Dim compra As Integer
Dim lin As Integer
'Inicialização
lin = 2 'Primeira linha de dados
'Varre toda a planilha
Do While Not IsEmpty(Cells(lin, ColunaProd))
'Descobre qtdd a comprar para o produto corrente
compra = RepoeEstoque(lin)
If compra > 0 Then
'Insere pedido de compra na planilha
Cells(lin, ColunaPed) = compra
End If
'Próxima linha
lin = lin + 1
Loop
End Sub

Suponha agora que nós queremos não apenas saber quantas unidades comprar, mas
também calcular o custo do pedido de compra. Para isso precisamos de duas novas
colunas na planilha, uma delas com o preço unitário do produto e a outra com o custo da
compra para cada produto. No final queremos também computar o custo total do pedido
de compra.

A B C D E F
PRODUTO Em Estoque Estoque Pedido de Preço Custo
Mínimo Compra Unitário Compra
1 Vassoura 12 100 R$2,50
2 Rodo 120 70 R$3,00
3 Esfregão 5 50 R$1,25

O esquema geral da solução é o seguinte:

1. Monta Pedido de Compra


2. Calcula o Custo
O Item 1 nós já sabemos fazer, basta usar a macro PedidoCompra. O Item 2 pode ser
refinado em

0. Para cada linha da planilha


1. Calcula o preço da compra
2. Atualiza a planilha

O cálculo do item 1, pode, por exemplo, ser feito por uma função auxiliar
CustoCompra.

Function CustoCompra(Linha As Integer) As Double


Dim quant As Integer
Dim precoUnit As Double
quant = Cells(Linha, ColunaPed)
precoUnit = Cells(Linha, ColunaUnit)
CustoCompra = quant * precoUnit
End Function

Em seguida, podemos fazer uma macro que compõe a coluna Custo Compra utilizando
a função CustoCompra:

Sub CustoPedido()
Dim custolin As Double
Dim lin As Integer
Dim total As Double 'custo total do pedido
'Inicia
lin = 2
total = 0
Do While Not IsEmpty(Cells(lin, ColunaProd))
custolin = CustoCompra(lin)
Cells(lin, ColunaCusto) = custolin
total = total + custolin
'proxima linha
lin = lin + 1
Loop
'Escreve custo total sob os custos
Cells(lin, ColunaCusto) = "Custo total: " & total
End Sub

O resultado da utilização consecutiva das macros MontaPedido e Custo Pedido é a


seguinte planilha:

A B C D E F
PRODU Em Estoque Pedido de Preço Custo Compra
TO Estoque Mínimo Compra Unitário
1 Vassoura 12 100 88 R$2,50 220
2 Rodo 120 70 R$3,00
3 Esfregão 5 50 45 R$1,25 56,25
CustoTotal:
276,25

Agora, ao invés de chamarmos consecutivamente as duas macros, podemos ter uma


macro que faça exatamente isso:

Sub MontaPedido()
PedidoCompra
CustoPedido
End Sub

Exercícios
Considere a seguinte planilha:

Aluno Média Provas Média EPs Média Final Resultado


Adalberto 7,0 9,0
Belinda 3,0 6,0
Clementino 4,5 9,0
Danusa 5,5 4,0
Eleutério 2,0 4,0
1. Fazer uma função auxiliar CalculaMédia que calcula a média final de acordo com a
fórmula:
MF = (3 * MP + MEP)/4, se MP >= 4 e MEP >= 4
MF = min( MP, MEP), caso contrário.

Quantos parâmetros esta função deve receber?

2. Fazer uma função auxiliar Resultado que retorna um string de acordo com as médias,
da seguinte maneira:

• Aprovado. Se a média final é maior ou igual a 5,0.


• Reaval de Prova. Se a média final e a média de provas estão entre 3,0 e
5,0, e a média de EPs é maior ou igual a 5,0.
• Reaval de EP. Se a média final e a média de EPs estão entre 3,0 e 5,0, e
a média de provass é maior ou igual a 5,0.
• Reaval de Prova e EP. Se a média final e a média de provas e a média
de EPs estão entre 3,0 e 5,0.
• Reprovado. Caso contrário.

Quais são os parâmetros passados para a função?


3. Fazer uma macro que, usando as funções auxiliares CalculaMedia e Resultado,
preenche a planilha acima.
Trabalhando com Várias Planilhas
Cada planilha tem um nome. Este nome inicialmente é, na versão em português do
Excel, Plan1, Plan2, etc. Mas este nome pode ser mudado, bastando para isso clicar
duas vezes sobre a aba que contém um nome e editar este nome na caixa de edição que é
ativada.

A importância do nome da planilha é que será através dele que poderemos nos referir
aos dados quando trabalharmos com diversas planilhas.

Quando editamos fórmula em uma planilha, utilizamos referências relativas, como C4,
ou referências absolutas, como $C$4. Ambas as referências dizem respeito à planilha
em que as fórmulas ocorrem. No entanto podemos nos referir a células em outras
planilhas.

Por exemplo, suponha que nós temos duas planilhas, Moedas e Importações. Suponha
que numa fórmula em Importações queiramos nos referir à célula C4 em Moedas. Para
isso, não podemos usar apenas C4 pois este se refere a célula situada na linha 4 e coluna
3 da planilha atual, ou seja, Importações. Em vez disso, usamos

Moedas!C4

para uma referência relativa. Para uma referência absoluta, usamos

Moedas!$C$4

Quando estamos lidando com várias planilhas em um programa, precisamos dizer


qual a planilha na qual queremos ler e/ou escrever. Por exemplo, se queremos ler o
valor da célula C4 na planilha Moedas, usamos o comando

<Var> = Worksheets(``Moedas'').Cells(4,3)

E se queremos escrever o resultado de uma expressão na célula E2 da planilha


Importações, usamos

Worksheets(``Importações'').Cells(2,5) = <expr>

Por exemplo, vamos construir planilhas para lidar com importações de produtos.
Uma planilha, chamada Moedas, contém a cotação de diversas moedas.

A B C
1 Moeda País Valor em Reais
2 Dolar EUA 1,19
3 Libra Reino Unido 2,2
4 Marco Alemanha 1,07
5 Yen Japão 0,006993007
6 Lira Itália 0,001278772
7 Dracma Grécia 0,43

Uma segunda planilha contém bens importados dos Estados Unidos, e a ela damos
o nome de ImportUS.

A B C
1 Produto Preço em US$ Preço em R$
2 Computador 2000 =B2 * Moedas!$C$2
3 Torradeira 70 =B3 * Moedas!$C$2
4 Chaleira 30 =B4 * Moedas!$C$2
5 Geladeira 500 =B5 * Moedas!$C$2

Finalmente, temos uma planilha ImportMundo que trata da importação de


produtos de todo o mundo, e portanto deve tratar da conversão de diversas
moedas para o Real.

A B C D
1 Produto Moeda Preço Original Preço em R$
2 Computador Dolar 2000
3 TV Yen 600
4 Whisky Libra 26
5 Camelo Dinar 400

O preenchimento desta tabela é consideravelmente mais complexo que o da tabela


anterior, pois envolve uma busca da cotação de cada moeda na planilha Moedas
para cada caso. Neste caso, podemos escrever uma macro (e um conjunto de
programas auxiliares) que nos ajude a solucionar o problema.

Const ColMoeda = 1
Const ColCota = 3
Const LinInicial = 2
Const PLAN2 = "ImportMundo"
Const ColProd = 1
Const ColTipo = 2
Const ColPreco = 3
Const ColReal = 4
Function BuscaCotação(moeda As String) As Double
'Encontra a cotação na planilha "Moedas" para
' uma dada moeda. Se a moeda não for encontrada,
' retorna -1.
Dim lin As Integer
Dim cotação As Double
'Inicialização
lin = LinInicial
cotação = -1 'assume que cotação não foi encontrada ainda
'Realiza busca
Do While (Not IsEmpty(Worksheets("Moedas").Cells(lin, ColMoeda)) And
cotação = -1)
'Encontrou a moeda?
If moeda = Worksheets("Moedas").Cells(lin, ColMoeda) Then
cotação = Worksheets("Moedas").Cells(lin, ColCota)
End If
'Próxima linha
lin = lin + 1
Loop
'Retorno
BuscaCotação = cotação
End Function

Sub PreencheMundo()
'Preenche o preço em Reais dos produtos
' na planilha ImportMundo
Dim i As Integer
i = LinInicial
'Varre a planilha
Do While Not IsEmpty(Worksheets(PLAN2).Cells(i, ColProd))
Call preencheLinhaMundo(i)
i=i+1
Loop
End Sub

Sub preencheLinhaMundo(lin As Integer)


Dim tipoMoeda As String
Dim cotação As Double
Dim precoOriginal As Double
'Descobre o tipo de moeda
tipoMoeda = Worksheets(PLAN2).Cells(lin, ColTipo)
'Descobre a cotação da moeda
cotação = BuscaCotação(tipoMoeda)
'Descobre preco original
precoOriginal = Worksheets(PLAN2).Cells(lin, ColPreco)
'Escreve preco em reais na planilha
If cotação >= 0 Then
Worksheets(PLAN2).Cells(lin, ColReal) = precoOriginal * cotação
Else
Worksheets(PLAN2).Cells(lin, ColReal) = "??"
End If
End Sub
Exercícios
1. Suponha uma planilha de 4 colunas. Fazer uma macro que copia esta planilha para
uma outra planilha, só que na ordem inversa das linhas, ou seja, o programa deve
copiar:
1 2 3 4
10 20 30 40
100 200 300 400
a b c d
para
a b c d
100 200 300 400
10 20 30 40
1 2 3 4

O programa deve funcionar para planilhas com qualquer número de linhas,


teminadas por uma linha em branco.

Sugestão: criar uma função auxiliar que conta o número N de linha e usar esta
informação para inverter. A inversão deve mapear as posições:

LINHA_INICIAL em N + LINHA_INICIAL - 1 [ = LINHA_FINAL ]


LINHA_INICIAL + 1 em N + LINHA_INICIAL - 2
...
LINHA_INICIAL + i em N + LINHA_INICIAL - i - 1
...
LINHA_FINAL em N + LINHA_INICIAL - N [ = LINHA_INICIAL ]

Como você alteraria o seu programa para tratar de um número qualquer de


colunas (terminadas por uma célula vazia)?

2. Um importador de automóveis tem a seguinte planilha de previsão de vendas de


unidades de cada modelo:
Modelo Total 1997 1o trimestre 98 2o tri 98 3o tri 98 4o tri
Ferrari TR 115
Ferrari Nera 15
Ferrari SL 215
Mazzerati A1 43
Mazzerati A1-i 122
Zorro 16V 1223
Zorro 8V 130

Suponha que a previsão de vendas é a seguinte: no primeiro trimestre deverão


ser vendidos 30% do total do ano. E nos outros trimestres espera-se um aumento
de 5% sobre cada trimestre anterior.

Preencha esta planilha da forma que achar mais adequada (fórmulas ou macro).
Lembre-se de arredondar os resultado para números inteiros.

Suponha agora que haja uma segunda planilha de ordem de compra com as
colunas:

Modelo Compras 1o tri 2o tri 3o tri 4o tri

Fazer uma macro que preencha tal planilha de planejamento de importações


dado que:

• Havia em estoque, no final do ano de 1997, 2 unidades de cada modelo.


• Aqui você tem a possibilidade de escolher entre uma opção fácil e outra
nem tão fácil assim.
o (+ Fácil) Suponha que, ao final de cada trimestre, deva haver 2
unidades de cada modelo no estoque. Isso quer dizer que basta
somar 2 a cada valor da planilha inicial.
o (+ Interessante) O pedido de compra de cada modelo deve ser
feito em lotes de tamanho igual a 40% do total das unidades
vendidas do ano anterior. Neste caso pode haver sobra de carros
em um período, e há de se decidir quantos lotes se deve comprar
para suprir a demanda estimada: 0, 1, 2, ...
Vetores
Até agora todos os tipos de dados vistos (Integer, Double, String, Boolean, ) foram
tipos de dados atômicos. O tipo de Dados Vetor é um tipo de dados composto por
outros tipos de dados.

Basicamente, um vetor é uma seqûência de dados do mesmo tipo. Desta forma,


podemos ter um vetor de inteiros, um vetor de strings, etc. O que caracteriza um
vetor é o fato de possuir um tamanho, que é o conjunto de posições contidas no
vetor, e o fato de estas posições de dados poderem ser acessadas através de um
índice.

Uma declaração de um vetor de 20 posições de inteiros é feita da seguinte maneira:

Dim vet(20) as Integer

Em geral, costuma-se deixar o valor de um vetor representado na forma de uma


constante:

Const TAM_VET = 20
Dim vet(TAM_VET) as Integer

A primeira posição do vetor é a posição 1. A última é a posição TAM_VET. As


posições do vetor podem ser acessadas através de um índice inteiro. Eis aqui
alguns exemplos de manipulação do vetor vet:

vet(1) = 22
i=2
vet(i) = 20
vet(i+1) = vet(i) - vet(i-1)

Acessos ao vetor com valores de índice fora do intervalo padrão 1..TAM_VET são
considerados ilegais e causam erros de execução no programa. Podemos alterar os
valores deste intervalo padrão na declaração, por exemplo:

Dim lucroAnual(1985 To 2010) as Double

faz com que os valores legais de índice para o vetor estejam no intervalo
1985..2010. Note que o tamanho do vetor lucroAnual é 26 = 2010 - 1985 + 1 (a
mesma fórmula é usada no cálculo dos vetores no caso padrão: o tamanho de vet é
20 = 20 - 1 + 1; em geral tamanho = PosiçaoFinal - PosiçãoInicial + 1.)

Podemos ter vetores multidimensionais. Um vetor bidimensional é, em geral,


chamado de matriz. A declaração dos vetores multidimensionais segue o mesmo
padrão da declaração dos vetores unidimensionais:

Dim matriz(50, 10) as String 'Matriz de 50 linhas por 10 colunas


Dim multiDimensional(5, 10, 2) as Double
O acesso a uma matriz se dá através de dois índices; similarmente, um vetor de n
dimensões é acessado através de níndices. Em geral, quando mencionamos vetores,
temos em mente o caso unidimensional, e é a ele que vamos nos restringir nesta
seção.

Com relação ao uso de vetores como parâmetros de funções e procedimentos:

• Vetores podem ser passados como parâmetros em funções e procedimentos. O


tipo do vetor é declarado no cabeçalho da função, mas não o seu tamanho.
Informação de tamanho de vetor deve ser passada em outro parâmetro.
• Funções não podem retornar vetores.

Como conseqüência deste último fato, a alteração de vetores dentro de uma função
ou procedimento se dá por efeito colateral. Com isso queremos dizer que, se um
vetor é passado para uma função e, no interior desta função este vetor é alterado,
esta alteração será percebida na função ou procedimento que chamou a função.

Isto é o que ocorre na função ColVet() abaixo, que lê uma coluna e copia seus
valores um um vetor. Esta função recebe um vetor como parâmetro e, ao retornar,
além de retornar o número de posições lidas, o valor do vetor está alterado,
contendo uma cópia dos valores contidos na coluna.

Vamos considerar um exemplo. Considere uma planilha que contém, em uma


coluna, valores positivos e negativos. Queremos eliminar os valores negativos (pois
supostamente representam valores ilegais) eliminar as células ocupadas por estes
valores. Por exemplo, queremos transformar:

12,50 12,50
-4,00 5,20
5,20 em 7,00
-9,50
7,00

Para resolver este problema, vamos dividi-lo em uma série de funções e macros
auxiliares, de acordo com a seguinte descrição geral da solução:

• 1. Copiar a coluna a ser manipulada num vetor


• 2. Modificar, no vetor, todos os números negativos para 0
• 3. Compactar o vetor, eliminando todos os 0s
• 4. Copiar o vetor compactado sobre a coluna original
• 5. Apagar os valores restantes da coluna original (em número igual ao número
de valores negativos encontrados).

Antes de iniciar o detalhamento, vamos mostrar as constantes usadas no módulo.

Const TamVet = 20
Const LinhaInicial = 2
Const ColunaFoco = 1
Começamos mostrando a macro principal, que invoca todas as outras funções e
procedimentos , além de realizar a compactação do vetor no item 3.

Sub EliminaNeg()
Dim i As Integer
Dim tam1 As Integer 'Tamanho inicial do vetor
Dim tam2 As Integer 'Tamanho do vetor compactado
Dim iniVet(TAM_VET) As Double 'Vetor inicial
Dim CompactVet(TAM_VET) As Double 'Vetor compactado
'Lê coluna sob Foco, no máximo TAM_VET posições
tam1 = ColVet(ColunaFoco, iniVet(), LinhaInicial, TamVet)
tam2 = 0
'Zera posições negativas
Call ApagaNeg(iniVet(), tam1)
i=1
'Principal
Do While i <= tam1
If iniVet(i) > 0 Then
'Copia de iniVet para CompactVet
tam2 = tam2 + 1
CompactVet(tam2) = iniVet(i)
End If
i=i+1
Loop
'Copia CompactVet para a coluna
Call VetCol(ColunaFoco, compactVet(), LinhaInicial, tam2)
'Esvazia demais posições
Call Esvazia(ColunaFoco, tam2 + LinhaInicial, tam1 + LinhaInicial - 1)
End Sub

Em seguida mostramos o item 2, que é uma subrotina que altera um vetor,


mudando todos os valores negativos para 0. Como parâmetro, recebe o vetor e o
seu tamanho:

Sub ApagaNeg(vet() As Double, tam As Integer)


Dim i As Integer
i = 1 'Inicialização
Do While i <= tam
If vet(i) < 0 Then
vet(i) = 0
End If
i = i + 1 'Proxima linha
Loop
End Sub

Em seguida, o item 1 é feito pela função ColVet(), que recebe como parâmetros a
coluna a ser copiada, o vetor a ser alterado, o valor da primeira linha a ser copiada
e o número máximo de posições que o vetor suporta. A função retorna o número
de posições realmente lidas, que pode ser menor que o tamanho máximo.
Function ColVet(col As Integer, vet() As Double, iniLin As Integer, tamMax As
Integer)
Dim i As Integer
Dim lin As Integer
i=1
lin = LinhaInicial
Do While i <= tamMax And Not IsEmpty(Cells(lin, col))
'Lê célula atual
vet(i) = Cells(lin, col)
'Próxima linha
i=i+1
lin = lin + 1
Loop
'Retorno
ColVet = i - 1
End Function

O item 4 é feito pelo procedimento VetCol(), o oposto de ColVet(), que copia um


vetor para uma coluna da planilha. Os parâmetros são os mesmos e não há
necessidade de retornar nenhum valor, uma vez que o tamanho do vetor já é
conhecido.

Sub VetCol(col As Integer, vet() As Double, iniLin As Integer, tam As Integer)


Dim i As Integer
i=1
Do While i <= tam
Cells(i + iniLin - 1, col) = vet(i)
i=i+1
Loop
End Sub

Por fim, o procedimento que apaga as linhas restantes.

Sub Esvazia(col As Integer, iniLin As Integer, fimLin As Integer)


Dim lin As Integer
lin = iniLin
Do While lin <= fimLin
Cells(lin, col) = Empty
lin = lin + 1
Loop
End Sub

Exercícios
Nota: Algumas versões do Excel podem vir com o padrão de indexação diferente
daquele apresentado nesse cap'itulo. Para garantir que todos os vetores possuem a
primeira posição indexada por 1 (e não por 0), basta adicionar no início do seu
módulo (antes das declarações de Const) a seguinte instrução:
Option Base 1
1. Fazer um programa que inverte uma coluna. Por exemplo, uma coluna que contem
``1, 2, 3, 4'' deverá ser transformada em ``4, 3, 2, 1''. O programa deve:
(a) solicitar ao usuário qual a coluna a ser invertida (ColVet);
(b) copiar a coluna para um vetor; o tamanho da coluna já é sabido pois foi
retornado por ColVet;
(c) inverter o vetor (ver enunciado do Exercício 1 da Lista 10). Você deve usar
um segundo vetor para isso;
(d) copiar o vetor invertido por sobre a coluna inicial (VetCol).
Não é necessário usar funções ou procedimentos auxiliares além de ColVet e
VetCol.

2. Fazer uma macro que lê uma coluna em um vetor e mostra, numa janela, a linha e o
valor da menor célula na coluna. A coluna em questão deve ser solicitada ao usuário,
bem como a posição da primeira linha a ser considerada.

Você deve usar uma função auxiliar que recebe um vetor e retorna o índice da
posição que contém o menor valor. Não se esqueça que este valor do índice não
é o mesmo que o valor da linha que contém o menor valor, pois a linha inicial na
coluna considerada não é necessariamente a primeira.
Ordenação
O objetivo deste capítulo é descrever um método de ordenação de dados.
Estaremos ordenando um conjunto de dados em um vetor (que pode ter sido, por
exemplo, copiado de uma coluna da planilha). Existem vários métodos de
ordenação, e nós vamos nos concentrar no método de Ordenação por Bolhas.

Uma bolha nada mais é que um par de números ordenados, por exemplo, ( 2, 7 ) ou
( 7, 4 ). A primeira destas bolhas está ordenada crescentemente, enquanto a
segunda não. Toda vez que encontrarmos uma bolha desordenada, vamos invertê-
la, transformando ( 7, 4 ) em ( 4, 7 ).

As bolhas são assim chamadas pois ``sobem pela seqüência'' da mesma forma
como bolhas de gas na água. Vamos explicar o método através de um exemplo.
Suponhamos que nós queremos ordenar a seqüência 4,2,12,7,4,1 de 6 elementos.
Um passo de ordenação pelo método de bolhas irá produzir as seguintes alterações
nos dados:

(4 2) 12 7 4 1
2 (4 12) 7 4 1
2 4 (12 7) 4 1
2 4 7 (12 4) 1
2 4 7 4 (12 1)
2 4 7 4 1 12

O passo de ordenação faz uma bolha deslocar-se pelo vetor da esquerda para a
direita, ordenando a bolha se esta estiver desordenada e, em seguinda, movendo a
bolha para a direita. As bolhas acima aparecem entre parênteses e, quando estão
desordenadas, também estão em negrito.

Note que o maior número da seqüência, 12, foi parar na posição mais à direita.
Portanto, se realizarmos o passo de ordenação uma segunda vez, o segundo maior
número, 7, irá parar na segunda posição à direita.

(2 4) 7 4 1 12
2 (4 7) 4 1 12
2 4 (7 4) 1 12
2 4 4 (7 1) 12
2 4 4 1 (7 12)
2 4 4 1 7 12

Se realizarmos este passo de ordenação N vezes, onde N é o número de elementos


na seqüência, a seqüência estará ordenada.
Para implementar a ordenação pelo método de bolhas, utilizaremos as rotinas
ColVet e VetCol do capítulo anterior, para realizar a leitura de uma coluna da
planilha para um vetor e para realizar a cópia do vetor ordenado de volta para a
planilha.

Para que o programa possa rodar, precisaremos copiar ColVet e VetCol no mesmo
módulo que a macro principal, chamada de OrdenaCol. A coluna a ordenar é
solicitada ao usuário.

Const TamVet = 20
Const LinhaInicial = 2

Sub OrdenaCol()
Dim colAOrdenar As Integer 'Coluna a ordenar
Dim vetorColuna(TamVet) As Double 'vetor que abriga a coluna
Dim tamCol As Integer 'numero de elementos a serem ordenados
colAOrdenar = CInt(InputBox("Qual a coluna a ser ordenada?"))
'Lê a coluna
tamCol = ColVet(colAOrdenar, vetorColuna(), LinhaInicial, TamVet)
'Ordena a coluna
Call OrdenaPorBolhas(tamCol, vetorColuna())
'Escreve a coluna ordenada
Call VetCol(colAOrdenar, vetorColuna(), LinhaInicial, tamCol)
End Sub

Em seguida, vamos detalhar a rotina OrdenaPorBolhas(tam, vetor()), que realiza a


ordenação por bolhas. Na chamada da rotina o vetor não está ordenado mas, por
efeitos colaterais, no seu término o vetor estará em ordem crescente.

Sub OrdenaPorBolhas(tam As Integer, vet() As Double)


'Ordena o vetor vet() de tam posições pelo
' método das bolhas. Ao final, vet() está ordenado
Dim vez As Integer 'Número de vezes que se repete o passo de ordenação
vez = 1
'Repete (tam - 1) vezes, pois vetor de tamanho 1 já está ordenado
Do While vez <= tam - 1
Call PassoOrdenação(tam, vet())
vez = vez + 1
Loop
End Sub

Para finalizar, basta detalhar o passo de ordenação, que também recebe como
parâmetros o tamanho do vetor e o vetor. Esta rotina também funciona por efeito
colateral, devolvendo o vetor alterado por um passo de ordenação por bolhas.

Note que a inversão da bolha necessita de uma variável auxiliar.

Sub PassoOrdenação(nPos As Integer, vet() As Double)


'Passo de Ordenação do vetor vet.
' Ao fim da execução da rotina, o maior valor
' de vet está na posição de maior índice (nPos).
Dim i As Integer 'Indice do vetor
Dim aux As Double 'Auxiliar na inversão da bolha
i = 1 'Primeira posição
'Repita a inversão da bolha (nPos -1) vezes
Do While i <= nPos - 1
'Verifica se a bolha é inversível
If vet(i) > vet(i + 1) Then
'Inverte a bolha
aux = vet(i)
vet(i) = vet(i + 1)
vet(i + 1) = aux
End If
i = i + 1 'Próxima bolha
Loop
End Sub

Exercícios
1. Alterar o programa de ordenação acima para gerar a coluna em ordem decrescente.
Note que para isso basta alterar uma linha do passo de ordenação.

2. O passo de ordenação do método de bolhas garante que o maior valor da seqüência


estará à direita. Não há necessidade, portanto, de se considerar este valor no próximo
passo de ordenação, uma vez que ele já está em sua posição definitiva.

No exemplo acima, o primeiro passo produziu:

2 4 7 4 1 12
onde 12 foi parar na posição final e definitiva. O segundo passo produziu
2 4 4 1 7 12
onde 7 foi parar na posição definitiva (e 12 permaneceu na mesma posição).

Altere o programa para, a cada passo, propagar a bolha até uma posição a menos
que na vez anterior.

Dica: uma pequena alteração na rotina OrdenaPorBolhas() resolve o problema.

3. Muitas vezes o vetor já está ordenado antes da execução dos Npassos de ordenação.
Por exemplo, se o vetor já está ordenado de início, não há motivos para continuar
aplicando os passos de ordenação.

Altere seu programa para que este pare de aplicar o passo de ordenação assim
que a aplicação do passo de aplicação não realizar nenhuma inversão de ordem.
O programa pode parar pois, garantidamente neste caso, o vetor já está
ordenado.
Manipulação de Strings
Já sabemos como construir uma cadeia de caracteres (String) a partir de outras
usando concatenação, representada pelo operador &:

``Banana'' & ``Madura'' = ``BananaMadura''

Vamos agora tratar da operação inversa, ou seja, construir um String que é um


``pedaço'' de outro. Para isso, basta entender que os caracteres em um String
podem ser indexados da mesma forma que as posições em um vetor (mas Strings
não são apenas vetores de caracteres, pois não possuem tamanho fixo). Por
exemplo, o String ``BananaMadura'' pode ser indexado como ilustrado abaixo:

B a n a n a M a d u r a
1 2 3 4 5 6 7 8 9 10 11 12

Para extrair um vetor de outro, usamos a função MID$:

Mid$( <String>, <Posiçao Inicial>, <Número de caracteres a extrair>).

Alguns exemplos:

str = ``BananaMadura''

str2_7 = Mid$( str, 2, 6 ) 'str1 recebe ``ananaM''

char10 = Mid$( str, 10, 1 ) 'char10 recebe ``u''

Uma importante função é aquela que nos dá o tamanho de um String, Len(


<String> ) (do inglês, length = comprimento). Por exemplo:

n = Len(``BananaMadura'') 'n recebe 12


x = Len(``12 34'') 'x recebe 5

Outras vezes, gostaríamos de saber se um caracter extraído de um string


representa um número ou não. Neste caso usamos a função IsNumeric. Por
exemplo,

OK = IsNumeric(``1'') 'OK é verdadeiro


OK = IsNumeric(``;'') 'OK é falso
OK = IsNumeric(`` '') 'OK é falso
OK = IsNumeric(``x'') 'OK é falso

Vamos ilustrar o uso das funçoes Mid$, Len e IsNumeric construindo uma função
que, dado um String, filtra todos os caracteres que não são numéricos. Por
exemplo, dado o CPF ``123.456.789-01'', retorna o string ``12345678901'',
eliminando toda a pontuação.
Function FiltraAlgarismo(strIn As String) As String

Dim pos As Integer 'posicao no string


Dim tamStr As Integer 'tamanho do string
Dim strOut As String 'string de saída
Dim letraCorr As String 'Letra corrente em strIn
pos = 1
tamStr = Len(strIn)
strOut = ""
Do While pos <= tamStr
letraCorr = Mid$(strIn, pos, 1)
If IsNumeric(letraCorr) Then
strOut = strOut & letraCorr
End If
pos = pos + 1 'próxima posição
Loop
FiltraAlgarismo = strOut
End Function

Esse exemplo transforma, por efeito colateral, um string num vetor de caracteres
(com a ressalva que o vetor de caracteres tem que ter tamanho pelo menos igual ao
do string).

Sub stringVet(str As String, vet() As Integer)


'Assumimos que o tamanho de vet é
' maior que Len(str)
Dim pos As Integer
Dim strAux As String
strAux = FiltraAlgarismo(str)
pos = 1
Do While pos <= Len(strAux)
vet(pos) = CInt(Mid$(strAux, pos, 1))
pos = pos + 1 'próxima posição
Loop
End Sub

Outro exemplo é a normalização de datas. Neste caso, uma data (dada por um
string) do tipo ``3/2/98'' é transformada em ``19980203'', ou seja, uma data do tipo
``Dia/Mes/Ano'' é transformada em Ano1Mes1Dia1, onde Ano1 está com 4
algarismos, Mes1 e Dia1 com dois.

Function FormataData(data As String) As String


'transforma uma data Dia/Mes/Ano em
' um string AnoMesDia onde
Dim ano As String, mes As String, dia As String
Dim pos As Integer
Dim letraCorr As String
'Inicialização
ano = ""
mes = ""
dia = ""
pos = 1
'obtem o dia, procurando pela primeira '/'
letraCorr = Mid$(data, pos, 1)
Do While letraCorr <> "/"
dia = dia & letraCorr
pos = pos + 1 'próxima posição
letraCorr = Mid$(data, pos, 1)
Loop
If Len(dia) = 1 Then
dia = "0" & dia
ElseIf Len(dia) > 2 Or Len(dia) < 1 Then
dia = "00"
End If
'obtem o mes, procurando pela segunda '/'
pos = pos + 1 'vai para a próxima posição
letraCorr = Mid$(data, pos, 1)
Do While letraCorr <> "/"
mes = mes & letraCorr
pos = pos + 1 'próxima posição
letraCorr = Mid$(data, pos, 1)
Loop
If Len(mes) = 1 Then
mes = "0" & mes
ElseIf Len(mes) > 2 Or Len(mes) < 1 Then
mes = "00"
End If
'obtem o ano, varrendo data até o fim
pos = pos + 1 'vai para a próxima posição
letraCorr = Mid$(data, pos, 1)
Do While pos <= Len(data)
ano = ano & letraCorr
pos = pos + 1 'próxima posição
letraCorr = Mid$(data, pos, 1)
Loop
If Len(ano) = 2 Then
ano = "19" & ano
ElseIf Len(ano) <> 4 Then
ano = "0000"
End If
'Retorno
FormataData = ano & mes & dia
End Function

Por fim, temos uma função que verifica se uma data é valida (com alguns errinhos:
quais?) que usa FormataData.

Function DataLegal(data As String) As Boolean


Dim ok As Boolean
Dim ano As Integer
Dim mes As Integer
Dim dia As Integer
Dim dataFormatada As String
ok = True
dataFormatada = FormataData(data)
ano = CInt(Mid$(dataFormatada, 1, 4))
mes = CInt(Mid$(dataFormatada, 5, 2))
dia = CInt(Mid$(dataFormatada, 7, 2))
If ano < 1900 Or ano > 2050 Then
ok = False
End If
If mes < 1 Or mes > 12 Then
ok = False
End If
If dia < 1 Or mes > 31 Then
ok = False
End If
'Retorno
DataLegal = ok
End Function

Exercícios
1. Fazer uma função que recebe um string como parâmetro e retorna um string obtido ao
se eliminar os espaços em branco no início e fim do string:
" Bom dia, senhor " deve ser transformado em "Bom dia,
senhor"
"Bom dia, senhor " deve ser transformado em "Bom dia,
senhor"
" Bom dia, senhor" deve ser transformado em "Bom dia,
senhor"

2. Fazer uma função que codifica um string pelo método ZENIT-POLAR:


Z E N I T
P O L A R

Ou seja, onde aparece um ``Z'' no string de entrada, aparecerá um ``P'' na saída;


e, semelhantemente, onde aparece um ``P'' no string de entrada, aparecerá um
``Z'' na saída. Isto deve ocorrer para todos os pares em ZENIT-POLAR,
maiúsculas e minúsculas. As outras letras não são alteradas

Por exemplo, o string ``Parabens a voce'' é codificado para ``Zitibols i veco''.

Ao se aplicar duas vezes a transformação, obtém-se o mesmo string, ou seja, a


codificação de ``Zitibols i veco'' é ``Parabens a voce''.

3. Fazer uma função que inverte um string. ``Parabens a voce'' vira ``ecov a snebaraP''.

Vous aimerez peut-être aussi