Escolar Documentos
Profissional Documentos
Cultura Documentos
Visual Basic
Visual Basic
1/61
1.1 VARIVEIS ................................................................................................................. 4 1.1.1 DECLARAO DE VARIVEIS ................................................................................... 5 1.2 CONSTANTES ............................................................................................................. 5 1.2.1 DECLARAO DE CONSTANTES ................................................................................ 5 1.3 EXPRESSES .............................................................................................................. 5 1.3.1 EXPRESSES NUMRICAS ......................................................................................... 6 1.3.2 EXPRESSES BOOLEANAS ........................................................................................ 7 1.3.3 EXPRESSES DO TIPO STRING................................................................................. 10 2 PROGRAMAO.................................................................................................... 11 2.1 ATRIBUIES ........................................................................................................... 11 2.1.1 EXEMPLOS ............................................................................................................. 11 2.2 COMENTRIOS ......................................................................................................... 12 2.3 INSTRUES CONDICIONAIS ................................................................................... 13 2.3.1 INSTRUES IF ...................................................................................................... 13 2.3.2 INSTRUO SELECT CASE.................................................................................. 19 2.4 FUNES .................................................................................................................. 21 2.5 COLECES ............................................................................................................. 25 2.6 INSTRUES CCLICAS ............................................................................................ 26 2.6.1 CICLOS FOR EACH .............................................................................................. 26 2.6.2 CICLOS FOR .......................................................................................................... 30 2.6.3 CICLOS WHILE ..................................................................................................... 36 2.6.4 ANLISE COMPARATIVA DE INSTRUES CCLICAS ............................................... 42 3 APLICAO DO VISUAL BASIC EM EXCEL.................................................. 44 3.1 INTRODUO AOS CONCEITOS DO EXCEL .............................................................. 44 3.1.1 REFERNCIAS A CLULAS NA FOLHA DE CLCULO................................................ 46 3.1.2 REFERENCIA A CLULAS NOUTRAS FOLHAS DE CLCULO ....................................... 50 3.2 COLECES DE CLULAS........................................................................................ 53 3.3 EXEMPLOS DE APLICAO DO VB AO EXCEL ........................................................ 54 3.4 EXEMPLOS AVANADOS.......................................................................................... 58
2/61
3/61
1 Definies Bsicas
Programar consiste em definir uma sequencia de comandos para o computador executar. Tipos de dados simples tipos Boolean Integer Long Single Variant String valores possveis True, False nmeros inteiros de -32768 a 32767 nmeros inteiros de 2.147.483.648 a 2.147.483.647 nmeros reais com limites muito grandes qualquer valor texto de comprimento varivel
1.1 Variveis
identificadores definidos pelo programador para armazenar valores Uma varivel tem sempre associado, explicitamente ou implicitamente, um tipo de dados. Os valores armazenados nas variveis podem ser alterados durante o programa. Os identificadores das variveis podem ser compostos por letras e nmeros e alguns caracteres especiais. Os caracteres no permitidos so o espao, !,@,&,$ e #. Para alem disso todos identificadores de variveis devem comear por uma letra Exemplos de identificadores invlidos: A minha morada 1aluno a#2 Exemplo de identificadores vlidos: aMinhaMorada a_minha_morada um_aluno umAluno a_2 Para efeitos de legibilidade do programa os identificadores devem ser escolhidos de forma a indicar qual o significado dos valores armazenados nas variveis associadas. Por
4/61
exemplo ao definir uma varivel para armazenar um nmero de aluno, os seguintes identificadores tm sentido: numAluno num Ao usar um dos indicadores acima a legibilidade do programa aumenta. Por outro lado se utilizssemos identificadores como por exemplo a ou x12 a dificuldade de leitura do programa seria aumentada desnecessariamente.
1.2 Constantes
identificadores definidos pelo programador para armazenar valores fixos Uma constante no pode ser alterada durante a execuo do programa. A utilizao de constantes permite escrever programas mais legveis e mais fceis de alterar.
1.3 Expresses
Em termos genricos uma expresso um conjunto de operaes ou simplesmente um valor. O tipo de uma expresso o tipo de dados do valor do seu resultado.
5/61
Note-se que os tipos de dados das variveis que integram a expresso no tm necessariamente de ter o mesmo tipo do resultado da expresso. Por exemplo uma expresso que calcule o comprimento de um texto devolve um resultado inteiro, sendo portanto do tipo Integer ou Long. No entanto a varivel presente na expresso, cujo valor o texto do qual se pretende saber o comprimento, do tipo de dados String.
10 \ 6 d como resultado 1
O operador mod devolve como resultado da operao o resto da diviso inteira, por exemplo: 5 mod 2 10 mod 6 d como resultado 1 d como resultado 4
Tabela dos operadores aritmticos: operador + * / \ mod significado adio subtraco multiplicao diviso diviso inteira resto da diviso inteira
O operador NOT aplicvel a uma varivel ou expresso booleana. O seu resultado a negao do valor do seu argumento. NOT x NOT expresso booleana so expresses vlidas. O resultado ser True se o argumento for False, e vice-versa.
7/61
Em Portugus o correspondente seria a palavra NO. Ou seja, a frase "no fui ao cinema" falsa se de facto fui ao cinema, ou seja se o argumento "fui ao cinema" for verdadeiro. O operador AND um operador binrio, isto realiza uma operao com duas expresses booleanas. Supondo que x e y so variveis ou expresses booleanas a expresso x AND y uma expresso vlida. O resultado desta expresso depende do valor de x e y, s sendo True (Verdade) no caso em que ambos x e y sejam True. A tabela seguinte apresenta o resultado da expresso para os valores possveis de x e y. valor de y False valor de x False True False False True False True
Em Portugus o correspondente seria a palavra E. Ou seja a frase "A Maria comprou o casaco e o guarda-chuva" s verdade se de facto ambos o casaco e o guarda-chuva foram comprados. Sendo falsa se nada se comprou, ou se s um dos artigos foi comprado. O operador OR, semelhana do operador AND, tambm um operador binrio. O resultado desta operao True se pelo menos uma das expresses for True. A sua tabela de resultados x OR y valor de y False valor de x False True False True True True True
Em Portugus o correspondente mais prximo seria a palavra OU. A frase "o Joo vai ao cinema ou ao pub" ser verdade se o Joo for ao cinema ou se o Joo for ao pub. Note-se que no entanto que a interpretao relativamente ambgua no caso em que o Joo visitou ambos os locais, j que a frase pode implicitamente querer dizer que o Joo ir somente a um local. Por exemplo uma me pode dizer a um filho "levas o Homem Aranha ou o Power Ranger", querendo implicitamente dizer que ambos os brinquedos esto fora de questo mas que um deles est garantido. O significado da frase depende do
8/61
contexto em que ela proferida. No caso dos brinquedos, o operador apropriado em Visual Basic o XOR. O operador XOR tambm um operador binrio. O seu resultado True quando um e s um dos seus argumentos for True. Se ambos forem False, ou se ambos forem True o resultado False. A sua tabela de resultados a seguinte: x XOR y valor de y False valor de x False True False True True True False
Relativamente s precedncias a ordem a seguinte: 1. NOT 2. AND 3. OR 4. XOR Seguem-se alguns exemplos: Na expresso NOT b AND c primeiro calcula-se a negao de b (NOT), e seguidamente a conjuno(AND). Na expresso a OR b AND c primeiro calcula-se a conjuno (b AND c) e depois a disjuno (OR). 1.3.2.1 Operadores de Comparao Uma expresso booleana pode tambm ser construda custa de operadores de comparao. Alguns dos operadores de comparao definidos so os seguintes: operador < <= exemplo a<b a <= b resultado Verdade se a for menor que b Verdade se a for menor ou igual a b
9/61
Verdade se a for maior que b Verdade se a for maior ou igual a b Verdade se a for diferente de b Verdade se a for igual a b
Note-se que os operadores aritmticos tm precedncia sobre todos os operadores de comparao. Ou seja primeiro efectuam-se os clculos e depois as comparaes. possvel combinar os operadores booleanos e de comparao numa expresso booleana. Por exemplo: c < b AND c < a a expresso acima s ser verdade se c for o menor dos trs valores: a, b e c. Exemplos: definir a expresso que dado uma varivel nota inteira do tipo Integer que representa uma nota devolva um resultado booleano que indique se a varivel maior ou igual a 10. nota > 10
10/61
2 Programao
Programar consiste em definir uma sequncia de instrues, ou comandos. As instrues so seguidas letra pelo computador por isso necessrio muito cuidado ao escrev-las. Dentro dos tipos de instrues existentes, os seguintes sero abordados nesta cadeira: Atribuies Condicionais Cclicas
2.1 Atribuies
Instruo que atribui a uma varivel o valor de uma expresso. O resultado da expresso tem de ser do mesmo tipo que a varivel. Sintaxe identificador = expresso As seguintes atribuies so vlidas
Dim Dim a = b = a As Integer b As Integer 3 a + 2
2.1.1 Exemplos
Definir a atribuio de forma a que a varivel a fique com o dobro do valor de b
Dim a As Integer Dim b As Integer a = 2 * b
Definir uma instruo que atribua varivel positiva o valor True se a varivel nota for superior a 9
Definir uma instruo que atribua varivel preoFinal a expresso que multiplica um determinado preo de custo, representado pela varivel preoCusto, por uma margem de lucro de 10%, e pelo IVA de 17%.
11/61
Por razes de clareza neste ltimo exemplo poderamos optar por uma soluo mais longa mas mais legvel:
Dim preoFinal As Single Public Const IVA As Single = 1.17 Public Const MargemLucro As Single = 1.1 preoFinal = preoCusto * Margem * IVA
Dim tp1, tp2, nt1, nt2 As Integer Dim notaFinal As Integer notaFinal = (tp1 + tp2 + nt1 + nt2) / 4
2.2 Comentrios
Os comentrios na programao so pequenas notas em linguagem corrente includas no texto do programa que facilitam a leitura do programa pelos programadores. A utilizao dos comentrios uma prtica que se recomenda vivamente. Os comentrios no fazem parte do programa propriamente dito, sendo inclusivamente ignorados pelo compilador ou interpretador. No entanto a sua utilizao fundamental para a boa programao. Para inserir um comentrio em Basic escreve-se o smbolo ' seguido do texto do comentrio. O Basic ao encontrar este smbolo ignora o texto dessa linha a partir do local onde o smbolo foi encontrado. Para escrever um comentrio com vrias linhas deve-se colocar o smbolo em todos as linhas. Exemplo:
' Isto um comentrio Dim a As Integer 'O meu segundo comentrio ' tem duas linhas a = 3
Atravs de comentrios possvel documentar o texto do programa de forma a facilitar a sua leitura. A titulo de exemplo vejamos o seguinte excerto de um programa sem comentrios: n = (t1+t2+p1+p2) / 4 em seguida apresentada a verso comentada:
' o nmero mdio de alunos na sala a mdia dos nmeros das aulas ' tericas e prticas para os dois turnos n = (t1+t2+p1+p2) / 4
12/61
2.3.1 Instrues IF
Em Visual Basic existe uma forma de definir instrues condicionais utilizando a instruo IF. A sintaxe desta instruo a seguinte: If expresso booleana Then ... sequencia de instrues End If Nesta instruo, a sequencia de instrues definida no seu interior s executada quando a expresso booleana for verdadeira. Assumindo que temos o valor da nota terica e prtica nas variveis teo e prat, respectivamente, podemos expressar a expresso booleana que traduz o facto "nota terica superior a 18" por teo > 18 O excerto de cdigo para realizar esta atribuio condicional poderia ser o seguinte: ...
nota = (teo + prat) / 2 If teo > 18 Then nota = nota + 1 End If
Note-se que no exemplo acima possvel obter uma nota incorrecta, se um aluno tiver 20 valores de nota final, com o bnus ficara com 21. Ao programar necessrio prever estes casos que potencialmente podem gerar erros e resolve-los atempadamente. Para um bom funcionamento de um programa crucial prever todas as situaes passveis de gerar erros. No exemplo acima poder-se-ia resolver o problema de duas formas: 1. atribuir o bnus aos alunos cuja nota terica seja superior a 18 obtendo assim a nota final bonificada. Caso esta nota seja superior a 20 valores ento o valor da nota bonificada seria reduzida para 20 valores garantindo assim que no final da operao a nota vlida. 2. atribuir o bnus aos alunos cuja nota terica fosse superior a 18, somente nos casos em que a nota final seja menor que 20 valores garantindo assim que a nota nunca assume valores incorrectos.
13/61
Note-se que neste caso trivial definir o caso em que a atribuio de bnus leva a uma nota invlida, no entanto nem sempre assim. Por vezes a soluo preventiva (soluo 2) demasiado complexa, sendo prefervel a soluo "curativa" (soluo 1). Considere-se agora a expresso para clculo do preo de venda de um determinado produto. Anteriormente foi apresentada uma expresso da seguinte forma:
Dim preoFinal, preoCusto As Single Public Const IVA As Single = 1.17 Public Const MargemLucro As Single = 1.1 preoFinal = preoCusto * Margem * IVA
Assuma agora que o preo final pode ter um desconto de 5 ou 10 por cento, conforme o valor da varivel preoFinal seja inferior a 100.000$, caso em que o desconto de 5%, ou o preoFinal seja igual ou superior a 100.000$, caso em que o desconto de 10%. Pode-se reescrever o programa da seguinte forma utilizando instrues condicionais:
Dim preoFinal, preoCusto, desconto As Single Public Const IVA As Single = 1.17 Public Const MargemLucro As Single = 1.1 preoFinal = preoCusto * Margem * IVA ' Se o valor for igual ou superior a 100 contos o ' desconto de 10%
14/61
If (preoFinal >= 100000) Then desconto = 0.9 End If ' Se o valor for inferior a 100 contos o ' desconto de 5% If (preoFinal < 100000) Then desconto = 0.95 End If ' Clculo do preo final com desconto preoFinal = preoFinal * desconto
Note-se no entanto que a atribuio de descontos exclusiva, isto uma venda tem um desconto de 10% ou de 5%, mas nunca de ambos. A analise das condies de ambas as instrues condicionais reflecte este facto. Se uma das condies for True ento a outra ser False. A exclusividade no exemplo acima implicitamente definida pelas expresses condicionais utilizadas. Nestes casos, convm tornar a exclusividade explicita, ou seja em vez de escrever: se o preo for inferior a 100000 ento o desconto de 5% se o preo for superior ou igual a 100000 ento o desconto de 10% deve-se escrever: se o preo for inferior a 100000 ento o desconto de 5%, seno o desconto de 10% Em Visual Basic a ultima alternativa corresponde a escrever:
If (preoFinal < 100000) Then desconto = 0.95 Else desconto = 0.90 End If
A primeira sequencia de instrues, A, executada quando a expresso definida for verdadeira. A segunda sequencia de instrues, B, executada sempre que a expresso definida seja falsa.
15/61
0 5% 10%
O excerto de cdigo para clculo do desconto poderia ser escrito da seguinte forma:
1 2 3 4 5 6 7 ' Sem desconto desconto = 1 ' Atribuio dos descontos para valores superiores a 100 contos If (preo >= 1000) Then desconto = 0.90 Else If (preo >= 100) Then desconto = 0.95 End If preoFinal = preo * desconto
Nota: os nmeros de linha no devem ser escritos no Visual Basic. Note-se que no exemplo acima a instruo Else tambm leva uma expresso booleana. Esta expresso traduz uma condio parcial para atribuio do desconto de 5%. Note-se que a expresso completa implicaria testar se o valor inferior a 1000 contos. No entanto a escrita da expresso completa desnecessria uma vez que a segunda condio (preo >= 100) s ser testada caso a expresso booleana definida na primeira condio (preo >= 1000) seja falsa. De seguida ir-se- simular o comportamento do Visual Basic ao executar o excerto de cdigo acima apresentado. Para tal define-se uma tabela com a seguinte estrutura: nmero de linha actual valor actual das variveis desconto e preoFinal aps a execuo da linha (um trao representa indefinido). observaes
0.9
de cdigo para a condio (preo >= 1000) a instruo If terminada e a linha seguinte a linha que contem End If 6 7 0.9 4500 atribuio varivel preoFinal
Neste caso o Visual Basic executaria as linhas 1,2,3,6 e 7. A excluso das restantes linhas deveu-se ao facto da a primeira condio da instruo If ser verdadeira. A tabela seguinte representa a simulao da execuo do Visual Basic no caso em que o preo de 300 contos.
num 1 2 desconto 1 1 preofinal obs. atribuio varivel desconto do valor 1 Teste se o valor de preo maior ou igual a 1000. Esta condio falsa., logo a linha seguinte a linha 4, onde se definiu a segunda condio. Esta condio verdadeira, 300 >= 100, logo o bloco de instrues associado vai ser executado atribuio varivel desconto do valor 0.95. Aps a execuo desta instruo terminou-se o bloco de cdigo para a condio (preo >= 1000) a instruo If terminada e a linha seguinte a linha que contem End If atribuio varivel preoFinal
4 5
1 0.95
6 7
0.95 0.95
285
6 7
1 1
50
Como se pode ver pelas trs simulaes acima apresentadas o percurso de execuo do Visual Basic depende da verificao de condies presentes em instrues If, podendo
17/61
executar um s bloco, ou nenhum no caso em que todas as expresses definidas sejam falsas.
booleanas
Retornando ao exerccio apresentado acima, uma outra alternativa para a escrita do cdigo seria:
If (preo >= 1000) Then desconto = 0.90 Else If (preo >= 100) Then desconto = 0.95 Else desconto = 1 End If
O ultimo Else no apresenta nenhuma condio. A sequencia de instrues associada (desconto = 1) executada sempre que todas as condies especificadas anteriormente (preo >= 1000 e preo >= 100 ) sejam falsas. No caso genrico a sintaxe da instruo If pode ser sumariada da seguinte forma:
If condio1 Then sequencia de instrues 1 Else If condio 2 Then sequencia de instrues 2 Else If condio 3 Then sequencia de instrues 3 ... Else If condio n Then sequencia de instrues n Else sequencia de instrues n+1 End If
sendo o ultimo Else opcional. Note-se que s o ultimo Else pode prescindir de expresso. No caso geral em que existe um Else sem ter expresso definida sempre executada uma e s uma sequencia de instrues. Caso o ultimo Else tambm tenha uma expresso ento possvel que nenhuma sequencia de instrues seja executada se todas as condies forem falsas. Finalmente convm referir que existe a possibilidade de construir instrues condicionais dentro de instrues condicionais. A titulo de exemplo vejamos uma outra forma de escrever a instruo If no caso dos descontos:
If (preo >= 1000) Then desconto = 0.90 Else ' Vamos agora calcular o desconto caso o preo seja inferior a 1000 If (preo >= 100) Then desconto = 0.95
18/61
Else End If
desconto = 1
End If
Note-se que o exemplo acima no est escrito da forma mais eficiente. Como exerccio procure reescreve-lo de uma forma mais eficiente Neste caso a instruo If est dependente de uma varivel, ou seja todas as expresses se referem varivel ms. Nestes casos possvel utilizar uma outra instruo fornecida pelo Visual Basic de forma a obter um excerto de cdigo mais compacto e simultaneamente mais legvel.
1 2 3 4 5 Select Case (mes) Case 1, 3, 5, 7, 8, 10, 12: dias = 31 Case 4, 6, 9, 11: dias = 30 Case Else: dias = 29 End Select
A primeira linha define qual a varivel que ser utilizada nas expresses definidas dentro da instruo Select Case. As linhas 2 e 3 utilizam o valor desta varivel e comparam-no com os valores definidos nas listas. Se o valor da varivel ms for igual a um dos valores da lista a instruo correspondente executada e o programa termina a instruo Select Case. A ultima linha (Case Else) aplicada nos casos em que o valor da varivel mes no se encontra em nenhuma das listas apresentadas. agora apresentado uma simulao de execuo considerando que o ms Abril, ou seja 4.
num 1 2 3 dias 30 obs. Inicio da instruo Select Case O valor 4 no se encontra na enumerao desta linha logo passa-se linha seguinte. O valor 4 encontra-se presente nesta enumerao logo a instruo associada executada. Uma vez que o valor se encontra presente na enumerao aps a execuo da
19/61
instruo associada a instruo Select Case termina. 5 1 Fim da instruo Select Case
A sintaxe deste comando permite um elevado nmero de variaes. Por exemplo, possvel definir um nmero entre 1 e 5 de duas formas: Enumerando os possveis valores Case 1,2,3,4,5: sequencia de instrues Definindo um intervalo Case 1 To 5: sequencia de instrues
A titulo de exemplo considere-se que se pretende traduzir um valor numrico, correspondente a uma nota, para um texto que atribui uma categoria classificao obtida:
1 2 3 4 5 6 7 Select Case (nota) Case 1 To 5: categoria = Case 6 To 9: categoria = Case 10 To 13: categoria Case 14 To 17: categoria Case 18 To 20: categoria End Select "Medocre" "Insuficiente" = "Suficiente" = "Bom" = "Muito Bom"
Considere-se o exemplo hipottico em que a nota era 21. Apresenta-se em seguida a simulao da execuo do Visual Basic para este caso.
num 1 categoria obs. Inicio da instruo Select Case
20/61
2 3 4 5 6 7
O valor 21 no se encontra no intervalo desta linha logo passa-se linha seguinte. O valor 21 no se encontra no intervalo desta linha logo passa-se linha seguinte. O valor 21 no se encontra no intervalo desta linha logo passa-se linha seguinte. O valor 21 no se encontra no intervalo desta linha logo passa-se linha seguinte. O valor 21 no se encontra no intervalo desta linha logo passa-se linha seguinte. Fim da instruo Select Case
Neste caso o valor de categoria permanece indefinido j que nenhuma das instrues definidas no interior da instruo Select Case foi executada. possvel misturar numa mesma expresso Select Case vrios tipos de condies: por enumerao e intervalo. O exemplo seguinte utiliza ambas as construes para reescrever o exemplo anterior.
Select Case (nota) Case 1 To 5 : categoria = "Medocre" Case 6 To 9: categoria = "Insuficiente" Case 10 To 13: categoria = "Suficiente" Case 14 To 17: categoria = "Bom" Case 18,19,20 : categoria = "Muito Bom" End Select
As vantagens desta instruo sobre a instruo If so evidentes neste caso. O cdigo necessrio utilizando instrues If seria muito mais longo e menos claro. A titulo de exerccio reescreva utilizando instrues If o cdigo acima apresentado.
2.4 Funes
At agora todos os exemplos apresentados continham expresses que trabalhavam somente com operadores. Embora o conjunto de operadores definidos seja significativo, a especificao de uma tarefa pode tornar-se longa e pouco clara. medida que os programas crescem, a sua legibilidade diminui forosamente. A estratgia para lidar com este tipo de situaes consiste em dividir o problema original em problemas mais pequenos, repetindo se necessrio o processo de diviso de forma a que no final cada um dos sub problemas identificados seja simples e fcil de implementar. Atravs desta estratgia consegue-se escrever programas para resolver problemas extremamente complicados. Devido diviso do problema original em sub problemas a legibilidade do programa aumenta consideravelmente permitindo assim que os erros de implementao sejam eliminados de uma forma mais fcil.
21/61
Outra situao que ocorre geralmente na implementao da soluo de problemas consiste na reutilizao de excertos de cdigo. Por exemplo um determinado excerto de cdigo pode ser utilizado diversas vezes no mesmo programa. desejvel que se possa escrever esse mesmo excerto uma s vez e reutiliza-lo sempre que necessrio. Quase todas as linguagens de programao oferecem um mecanismo que permite agrupar uma sequencia de instrues de forma a que esta possa ser utilizada durante o programa de forma simples e clara. Em Visual Basic um destes mecanismos so as funes. Atravs da utilizao de funes pode-se dividir o cdigo de um programa em fragmentos, sendo cada um deles idealmente de dimenso reduzida e portanto potencialmente de melhor legibilidade. A sintaxe geral da construo de funes a seguinte:
Function nome() sequencia de instrues End Function
Uma funo recebe um nmero de argumentos e devolve um e um s resultado. O exerccio do clculo da nota agora revisitado de forma a solucionar o mesmo incorporando funes. O objectivo dividir o problema original em sub problemas e utilizar uma funo para resolver cada um dos sub problemas identificados. Apresenta-se de seguida o cdigo utilizado anteriormente para resolver este problema.
If ( frequncia terica Else terica End If nota = (terica > exame ) Then = frequncia = exame + prtica) / 2
O problema original pode-se dividir em dois sub problemas: 1. clculo da nota terica: mximo da nota de frequncia e exame 2. clculo da nota final: mdia da nota terica e prtica. Sendo assim os dois sub problemas identificados so calcular o mximo de dois nmeros e calcular a mdia de dois nmeros. Considere-se a funo para calcular o mximo dos valores contidos em duas variveis. Neste caso os parmetros sero as variveis, o resultado ser o mximo dos valores aceites como parmetro. Function mximo(a, b) ' definir uma varivel para armazenar o valor pretendido Dim aux ' clculo do mximo de dois valores
If (a > b ) Then
22/61
Else End If
aux = a aux = b
' o resultado pretendido esta armazenado em aux ' para devolve-lo atribui-se ao nome da funo o valor de aux mximo = aux End Function
Como se pode ver no exemplo acima apresentado o Visual Basic utiliza o nome da funo dentro do cdigo com um objectivo particular: indicar qual o valor a ser devolvido. No esquecer que uma funo tem sempre um e um s resultado. A sintaxe para indicar qual o resultado da funo em Visual Basic consiste em atribuir ao nome da funo o valor pretendido. A funo para calcular a mdia de dois nmeros tambm tem dois argumentos. O cdigo apresentado a seguir:
Function mdia(a, b) mdia = (a + b) / 2 End function
agora apresentado o cdigo que utiliza as funes acima definidas para resolver o problema original:
terica = mximo(frequncia, exame) nota = mdia(terica, prtica)
Note-se que ao definir as funes mximo e mdia utilizou-se variveis com nomes distintos da sua utilizao. Ao definir uma funo, os nomes das variveis so da escolha do programador, no tendo relao nenhuma com os nomes que posteriormente se utilizam na sua invocao. Mesmo que se os nomes fossem iguais, para o Visual Basic seriam variveis distintas. O Visual Basic estabelece a relao necessria entre os argumentos da utilizao e parmetros da definio ao utilizar a funo. Por exemplo na primeira linha do ultimo excerto de cdigo apresentado o Visual Basic ir "invocar" a funo mximo com os argumentos frequncia e exame. Esta funo tem dois parmetros a e b. Neste caso o Visual Basic estabelece a relao entre frequncia e a, e entre exame e b. O ultimo excerto de cdigo apresentado poderia por sua vez ser tambm parte de uma funo:
Function nota( frequncia, exame, prtica) terica = mximo(frequncia, exame) nota = mdia(terica, prtica) End Function
23/61
Sendo assim de onde vem os valores das variveis argumento da funo? Talvez de outra funo que por sua vez utilize esta funo, ou ento de uma folha de clculo Excel. Embora existam outras alternativas, o seu estudo no ser realizado no mbito desta cadeira. A funo nota acima apresentada em cima, apresenta um grau de abstraco elevado para o problema original, o clculo de uma nota com base na frequncia, exame e prtica. Assumindo que os nomes atribudos s funes tem algum significado, ao ler a funo sabe-se que a nota terica o mximo entre a frequncia e o exame. Sabe-se tambm que a nota final a mdia da nota terica e prtica. Tudo isto sem entrar em pormenores de como calcular o mximo e a mdia. Ou seja a leitura da funo acima apresentada fornece tanta informao como a leitura do cdigo completo, apresentado de seguida, sem utilizar funes.
If ( frequncia terica Else terica End If nota = (terica > exame ) Then = frequncia = exame + prtica) / 2
Este um dos objectivos das funes: permitir a escrita de programas facilmente legveis. Outro objectivo tambm muito importante permitir a utilizao de um excerto de cdigo parametrizado (ou seja uma funo com parmetros) mltiplas vezes num programa sem reescrever o excerto utilizado. Para ilustrar este ponto ir-se- aumentar o exerccio do clculo da nota definido anteriormente. Considere que a nota de frequncia calculada com base nas frequncias de Fevereiro e Junho. assuma que as classificaes obtidas nas frequncias est armazenada nas variveis fev e jun para a primeira e segunda frequncia respectivamente. Considere ainda que a nota prtica a mdia dos dois trabalhos prticos, cujas classificaes esto armazenadas nas variveis tp1 e tp2. Sendo assim o seguinte excerto de cdigo sem funes resolve o problema:
prtica = (tp1 + tp2) / 2 frequncia = (fev + jun) / 2 If ( frequncia > exame ) Then terica = frequncia Else terica = exame End If nota = (terica + prtica) / 2
Utilizando as duas funes definidas acima, mdia e mximo, o cdigo resultante seria:
prtica = mdia (tp1,tp2) frequncia = mdia(fev, jun) terica = mximo(frequncia, exame) nota = mdia(terica, prtica)
24/61
O cdigo utilizando funes claramente mais legvel, aproximando a escrita em Visual Basic da nossa formulao do problema, e eliminando de uma primeira leitura pormenores desnecessrios. Caso subsistam duvidas sobre o clculo da nota pode-se sempre recorrer leitura do cdigo das funes utilizadas. No entanto se os nomes atribudos s funes reflectirem o seu funcionamento, este passo geralmente desnecessrio, salvo em caso de erro. Como ultima nota pretende-se salientar que os programas no se medem linha! A clareza de um determinado excerto de cdigo no tem relao directa com o nmero de linhas escritas. Para ilustrar este ponto apresenta-se a seguinte linha que produz exactamente o mesmo resultado que ambos os excertos apresentados acima: nota = mdia(mximo(mdia(fev, jun),exame),mdia(tp1,tp2)) Embora esta ultima verso seja decididamente mais curta, ela representa o pesadelo de um programador: de muito difcil leitura! Uma troca de parntesis e est tudo perdido...
2.5 Coleces
At agora os tipos de dados definidos permitiam armazenar um s valor. Em Visual Basic existe o conceito de coleco para permitir armazenar numa s varivel uma sequencia de valores. A sintaxe para definir uma coleco a seguinte: Dim x As New Collection Em Visual Basic, Collection na realidade um objecto e no um tipo de dados. A distino entre estes dois conceitos est fora do mbito desta cadeira. As diferenas na sua utilizao ao nvel sintctico sero no entanto apresentadas de forma a permitir a sua utilizao. Note-se que por x ser um objecto necessrio utilizar a palavra New na sua declarao para o inicializar. Para adicionar um elemento a uma coleco o Visual Basic fornece a funo Add que adiciona ao fim da coleco um determinado valor:
Dim x As New Collection x.Add(327) x.Add(425)
Note-se que para objectos, a invocao de uma funo precedida do nome do objecto sobre o qual se ir realizar a operao. Para consultar o valor do elemento na posio i de uma coleco utiliza-se a funo Item.
x.Item(i)
Note-se que uma consulta a uma posio para alm dos nmero de elementos da coleco produz um erro em Visual Basic terminando a execuo do programa. Para determinar qual o nmero de elementos de uma coleco o Visual Basic fornece a funo Count. Exemplo: aps a execuo do seguinte excerto de cdigo o valor da varivel a 2.
Dim x As New Collection x.Add(327) x.Add(425) a = x.Count()
Um exemplo apropriado para esta instruo realizar a soma de todos os elementos de uma coleco. Para tal define-se uma funo que recebe como parmetro uma coleco. Este tipo de processos iterativos realiza-se por acumulao, ou seja, inicialmente o valor de soma zero, ou seja, antes de se iniciar a operao o total zero. Seguidamente queremos acumular no valor de soma o primeiro elemento da coleco. A operao repete-se at ao ultimo elemento da coleco, altura em que soma conter como valor o somatrio de todos os elementos. Para cada elemento da coleco, a instruo que realiza a acumulao do seu valor com a soma anterior : soma = soma + elemento Sendo assim a funo completa ficar:
26/61
1 2 3 4 5
Function total(coleco) soma = 0 For Each elem In coleco soma = soma + elem Next elem total = soma End Function
A instruo Next fornece-nos o prximo elemento da coleco caso ainda no se tenha atingido o fim da coleco, caso contrrio o resultado desta instruo a sada do ciclo. Note-se que o nome da varivel nesta instruo tem de coincidir com o nome utilizado na definio For Each. Para a simulao de execuo que se segue considere que a coleco fornecida como parmetro funo, tem os seguintes elementos: < 4, 3, 5, 2>.
num 1 2 3 4 3 4 3 4 3 4 elem 4 4 3 3 5 5 2 2 soma 0 0 0+4=4 4 4+3=7 7 7 + 5 = 12 12 12 + 2 = 14 14 obs. Inicialmente o valor de soma zero. elem toma o valor do primeiro elemento da coleco, 4. atribudo a soma a acumulao do seu valor prvio com o valor de elem. elem toma o valor do prximo elemento da coleco, neste caso o segundo. atribudo a soma a acumulao do seu valor prvio com o valor de elem. elem toma o valor do prximo elemento da coleco, neste caso o terceiro. atribudo a soma a acumulao do seu valor prvio com o valor de elem. elem toma o valor do prximo elemento da coleco, neste caso o quarto. atribudo a soma a acumulao do seu valor prvio com o valor de elem. No existem mais elementos na coleco, logo o ciclo termina. Note-se que o valor de elem indefinido aps esta instruo. instruo que define que o valor de soma o resultado da funo
14
De seguida apresentado um outro exemplo de utilizao do ciclo FOR EACH para clculo do valor mximo de uma coleco. O calculo do mximo de uma determinada coleco um processo iterativo em que se vai comparando os elementos da coleco com um valor mximo calculado at altura, ou seja, se o ciclo se encontrar no terceiro elemento, deve existir uma varivel que contenha
27/61
o mximo dos dois primeiros elementos. Essa varivel ento comparada com o terceiro elemento e caso seja inferior o seu valor actualizado para o valor do terceiro elemento. O processo continua iterativamente percorrendo os restantes elementos da coleco substituindo o valor da varivel que contem o valor mximo sempre que seja encontrado um valor superior.
1 2 3 4 5 6 Function mximo(coleco) mximo = 0 For Each elem In coleco If elem > mximo Then mximo = elem End If Next elem End Function
Para a simulao de execuo que se segue considere que a coleco fornecida como parmetro funo, tem os seguintes elementos: < 4, 3, 5, 2>.
num 1 2 3 elem 4 4 mximo 0 0 0 obs. Inicialmente o valor de mximo zero. elem toma o valor do primeiro elemento da coleco, 4. O valor de mximo inferior a elem, logo a condio da instruo If verdadeira e por conseguinte a instruo definida dentro do If ser executada. mximo toma o valor de elem. elem toma o valor do prximo elemento da coleco, neste caso o segundo. O valor de mximo superior a elem, logo a condio da instruo If falsa e por conseguinte a instruo definida dentro do If no ser executada. elem toma o valor do prximo elemento da coleco, neste caso o terceiro. O valor de mximo inferior a elem, logo a condio da instruo If verdadeira e por conseguinte a instruo definida dentro do If ser executada. mximo toma o valor de elem. elem toma o valor do prximo elemento da coleco, neste caso o quarto e ltimo. O valor de mximo superior a elem, logo a
28/61
4 5 6 3
4 4 3 3
4 4 4 4
5 6 3
3 5 5
4 4 4
4 5 6 3
5 5 2 2
5 5 5 5
condio da instruo If falsa e por conseguinte a instruo definida dentro do If no ser executada. 5 6 2 5 5 No existem mais elementos em coleco e por isso termina o ciclo.
Note-se que na linha 1 da funo acima definida atribui-se o valor 0 varivel mximo. O valor inicial desta varivel importante j que pode influenciar o resultado. A titulo de exemplo considere que na linha 1 da funo acima definida em vez de
1 mximo = 0
se tinha escrito
1 mximo = 10
Neste caso o valor da varivel mximo permaneceria inalterado durante todo o ciclo, sendo o seu valor final 10, o que claramente errado! A razo pela qual o valor de mximo permanece inalterado que a condio especificada na instruo IF, linha 3,
3 If elem > mximo Then
Caso o valor inicial de mximo seja superior a todos os elementos da coleco ento o valor final da varivel mximo incorrecto. Sendo assim qual a regra para atribuir o valor inicial varivel mximo de forma a obter um resultado correcto no final do ciclo, i.e. o valor mximo presente na coleco? O valor inicial da varivel mximo deve ser tal que exista sempre pelo menos um valor na coleco superior ao valor inicial escolhido. Desta forma garante-se que a condio especificada na instruo If, linha 3, ser verificada para pelo menos um valor e portanto o valor final de mximo realmente o mximo da coleco e no um elemento maior que todos os elementos da coleco. Se considerarmos que a coleco contem preos, ento seguro dizer que o mximo zero, j que no existem preos inferiores a esse valor. Caso se trate de uma coleco que contenha ambos nmeros positivos e nmeros negativos ento a nica soluo seria inicializar a varivel mximo com o menor nmero possvel, no caso de nmeros inteiros o seu valor seria 32768. O problema inverso verifica-se com o clculo do valor mnimo. Neste caso o valor inicial da varivel que conter o valor mnimo da coleco deve ser inicializada com um valor superior ao mnimo actual da coleco. Como no caso geral no se conhece o valor
29/61
mnimo de uma coleco ento a forma segura de inicializar o valor mnimo e atribuir-lhe o maior valor possvel, no caso dos inteiros este valor 32767. Uma vez que o valor inicial destas variveis depende da coleco em causa, uma possvel soluo inicializar a varivel com o primeiro valor da coleco, ou seja, por exemplo mximo = A.item(1) ou mnimo = A.item(2)
A instruo Next i corresponde a incrementar o valor de i por uma unidade e de seguida, caso o valor de i no seja superior a limite_final ento voltar de novo para dentro do ciclo. Considere de novo o exemplo do calculo da soma de todos os elementos de uma coleco. Neste caso o limite_inicial 1, ou seja o primeiro elemento, e o limite_final a posio do ultimo elemento, ou seja o nmero total de elementos. O Visual Basic fornece uma funo que determina o nmero total de elementos de uma coleco, count(), ver seco referente s coleces. O esqueleto da funo utilizando a funo count() ser:
1 2 3 4 5 Function total(coleco) soma = 0 For i = 1 To coleo.count() instruo para acumular o valor de soma Next i total = soma End Function
A instruo para acumular o valor da soma, linha 3 da funo acima apresentada, pode ser definida informalmente como:
soma = soma + valor do elemento que se encontra na posio i
Para determinar o valor de um elemento numa determinada posio i, utiliza-se a funo item(i), ver seco referente s coleces. A funo completa em seguida apresentada:
30/61
1 2 3 4 5
Function total(coleco) soma = 0 For i = 1 To coleo.count() soma = soma + coleo.item(i) Next i total = soma End Function
Para a simulao da execuo desta funo considere que a coleco tem os seguintes elementos < 2 4 3>.
num 1 2 3 i 1 1 soma 0 0 0+2=2 obs. Inicialmente o valor de soma zero. Atribui-se a i o valor do limite inicial do ciclo, ou seja 1. atribudo a soma a acumulao do seu valor prvio,0, com o valor do elemento da coleco na posio i, ou seja o primeiro elemento da coleco. i incrementado de uma unidade. Uma vez que i no superior ao limite final, coleo.count() a simulao prossegue na linha 3. atribudo a soma a acumulao do seu valor prvio com o valor do elemento da coleco na posio i, ou seja o segundo elemento da coleco. i incrementado de uma unidade. Uma vez que i no superior ao limite final, coleo.count() a simulao prossegue na linha 3. atribudo a soma a acumulao do seu valor prvio com o valor do elemento da coleco na posio i, ou seja o terceiro elemento da coleco. i incrementado de uma unidade. Uma vez que i superior ao limite final, coleo.count() o ciclo terminado e a simulao prossegue na linha 5. instruo que define que o valor de soma o resultado da funo
2+4=6
6+3=9
Pelo exemplo apresentado acima evidente que para percorrer completamente uma coleco a escrita de uma funo utilizando o ciclo FOR definitivamente mais complicada que a mesma funo utilizando o ciclo FOR EACH. De facto para percorrer completamente uma coleco os ciclos FOR EACH so os mais apropriados.
31/61
No entanto os ciclos FOR permitem realizar operaes que os ciclos FOR EACH no permitem como por exemplo percorrer somente os n primeiros elementos de uma coleco. Ou seja nos ciclos FOR existe a liberdade de seleccionar limites iniciais e limites finais diferentes de 1 e o numero total de elementos respectivamente. De facto o ciclo FOR EACH um caso particular dos ciclos FOR em que os limites inicias e finais so respectivamente o primeiro e ultimo elemento de uma coleco. Por exemplo a seguinte funo realiza a soma dos elementos que se encontram entre a quinta e a dcima posio numa coleco.
1 2 3 4 5 Function total(coleco) soma = 0 For i = 5 To 10 soma = soma + coleo.item(i) Next i total = soma End Function
Note-se que se a coleco no possuir pelo menos dez elementos a funo provoca um erro de "Index Out of Bounds", ou seja tentativa de acesso a um elemento numa posio fora da gama de posies da coleco. Considere agora um outro exemplo: a procura de um determinado valor numa coleco. Esta funo ter de ter dois parmetros: o elemento a encontrar, e a coleco onde se pretende procurar. Sendo assim o esqueleto da funo poder ser algo do gnero:
Function procura(elem, coleco) ... End Function
Basicamente o que se pretende determinar para cada elemento da coleco verificar se este igual ou diferente ao elemento que se pretende procurar. Caso seja igual o resultado final deve ser false, caso contrrio este resultado ser true. Apresenta-se agora uma primeira tentativa para a resoluo deste problema:
1 2 3 4 5 6 7 Function procura(elem, coleco) For i = 1 To coleo.count() If (elem = coleo.item(i)) Then procura = true Else procura = false End If Next i End Function
Considerando que a coleco <8,6,7,5> e sendo 6 o valor procurado procede-se de seguida a uma simulao de execuo para esta funo.
num i procura obs.
32/61
Atribui-se varivel i o valor do limite inicial do ciclo. A varivel procura, que tambm o resultado da funo permanece indefinido. Testa se elem = coleo.item(1), ou seja 8. A condio falsa logo a linha seguinte a executar a linha 5. Termina a instruo If i incrementado de uma unidade. Uma vez que i no superior ao limite final, coleo.count() a simulao prossegue na linha 3. Testa se elem = coleo.item(2), ou seja 6. A condio verdadeira logo a linha seguinte a executar a linha 4. atribudo a procura o valor true. Terminou o bloco de instrues para a condio verdadeira, logo a prxima instruo a executar encontra-se na linha 6 Termina a instruo If i incrementado de uma unidade. Uma vez que i no superior ao limite final, coleo.count() a simulao prossegue na linha 3. Testa se elem = coleo.item(3), ou seja 7. A condio falsa logo a linha seguinte a executar a linha 5. Termina a instruo If i incrementado de uma unidade. Uma vez que i no superior ao limite final, coleo.count() a simulao prossegue na linha 3. Testa se elem = coleo.item(4), ou seja 5. A condio falsa logo a linha seguinte a executar a linha 5. Termina a instruo If i incrementado de uma unidade. Uma vez que i superior ao limite final termina o ciclo FOR.
5 6 7
1 1 2
false
true
6 7
2 3
true true
true
5 6 7
3 3 4
false
5 6 7
4 4 5
33/61
O resultado desta funo false, no entanto o valor 6 encontra-se presente na coleco passada como parmetro. Podemos ento concluir que esta funo est mal construda j que o resultado correcto seria true. Exerccio: Existem dois casos particulares em que a funo acima apresentada dar um resultado correcto: d exemplos de parmetros para os quais a funo de resultados correctos, e identifique as razes que levam a funo a devolver resultados correctos. Analisando a simulao de execuo da funo pode-se concluir o seguinte: ao encontrar o elemento pretendido atribudo ao valor da varivel procura o valor true. No entanto, logo de seguida o valor da varivel procura passa a false mal a funo se depare com um elemento da coleco que no seja igual ao elemento procurado. O problema reside no facto de se alterar para todos os elementos o valor da varivel procura e aceitar o ultimo valor como sendo o resultado real. Esta funo deve ser reescrita da seguinte forma: 1. inicialmente define-se que o valor da varivel procura false, ou seja, antes de se procurar nada se pode encontrar! 2. seguidamente realiza-se o ciclo FOR tal com na funo anterior sendo a nica diferena o facto de s se alterar o valor da varivel procura case se encontre o elemento pretendido. Sendo assim o cdigo da funo fica:
1 2 3 4 5 6 Function procura(elem, coleco) procura = false For i = 1 To coleo.count() If (elem = coleo.item(i)) Then procura = true End If Next i End Function
obs.
false
5 6
1 2
false false
prossegue na linha 3. 3 2 false Testa se elem = coleo.item(2), ou seja 6. A condio verdadeira logo a linha seguinte a executar a linha 4. atribudo a procura o valor true. Terminou o bloco de instrues para a condio verdadeira, logo a prxima instruo a executar encontra-se na linha 6 Termina a Instruo If. i incrementado de uma unidade. Uma vez que i no superior ao limite final, coleo.count() a simulao prossegue na linha 3. Testa se elem = coleo.item(3), ou seja 7. A condio falsa logo a linha seguinte a executar a linha 5. Termina a instruo If i incrementado de uma unidade. Uma vez que i no superior ao limite final, coleo.count() a simulao prossegue na linha 3. Testa se elem = coleo.item(4), ou seja 5. A condio falsa logo a linha seguinte a executar a linha 5. Termina a instruo If i incrementado de uma unidade. Uma vez que i superior ao limite final termina o ciclo FOR.
true
5 6
2 3
True true
true
5 6
3 4
true true
true
5 6
4 5
true true
Esta funo devolve o resultado correcto. fcil ver que caso o elemento no pertena coleco o resultado ser sempre false. A titulo de exerccio construa uma simulao de execuo tomando como parmetros a coleco <9,8,7,6> e o elemento 5. O cdigo desta funo no muito inteligente. Considere a seguinte analogia para ilustrar a falta de eficincia desta funo. Um gestor de uma empresa pede ao seu assistente uma cpia de um relatrio sobre a situao financeira da empresa. Na secretria do assistente encontra-se uma pilha de relatrios na qual se deve encontrar o relatrio pretendido. O assistente comea a procura do relatrio pelo topo da pilha, e vai procurando at encontrar o dito relatrio. Quando encontra, suspira aliviado, posa o relatrio na beira da secretria, e... continua a sua operao de procura at chegar ao fim da pilha!? Porque continuar a procurar aps encontrar? Porque na funo acima definida no h maneira de especificar que a busca termina aps procura assumir o valor true. Os ciclos FOR s permitem especificar os limites inicial e final. Atingir o limite final a nica sada possvel do ciclo. Na analogia acima o assistente s poderia terminar a sua busca
35/61
aps procurar em toda a pilha de relatrios, mesmo que encontre o relatrio pretendido a meio do processo. Na seco seguinte vamos apresentar um novo tipo de ciclos que permite resolver este tipo de problemas de forma adequada.
Sendo condio uma expresso booleana que determina enquanto o ciclo deve prosseguir, ou seja o ciclo no termina enquanto a expresso for verdadeira. Considere de novo a funo soma. Neste caso pretende-se percorrer a coleco completa desde o primeiro elemento at ao ltimo. Ao definir o ciclos FOR para esta funo os limites eram especificados na prpria definio da instruo. Para os ciclos WHILE, a situao diferente. S possvel especificar uma condio de continuao do ciclo, ou seja, o ciclo ir ser executado enquanto a posio do elemento actual no exceder o total de elementos. Apresenta-se de seguida o cdigo desta funo:
1 2 3 4 5 6 Function soma(col) soma = 0 i = 1 While i <= col.count() soma = soma + col.item(i) i = i + 1 Wend End function
A varivel i utilizada para percorrer a coleco, indicando a posio do elemento actual. A condio do ciclo WHILE i <= col.count() indica que o ciclo ser executado enquanto a posio do elemento actual no exceder o total de elementos da coleco. Note-se que na definio do ciclo WHILE no existe referencia ao valor inicial da varivel i. Esta definio de valor inicial deve ser feita antes do ciclo comear. Ao terminar o ciclo necessrio explicitar que se pretende passar ao elemento seguinte, ou seja ao elemento que se encontra na posio i+1, dai a instruo i=i+1
36/61
Ao terminar um ciclo FOR com a instruo Next i, est-se de facto a realizar duas operaes: 1. incrementar o valor de i por uma unidade, ou seja i = i + 1 2. definir o fim da instruo FOR Como se pode inferir do exemplo anterior, nos ciclos WHILE necessrio realizar o incremento da varivel i explicitamente. Os ciclos WHILE so portanto mais complexos, no entanto essa complexidade permite realizar operaes de uma forma mais eficiente. Antes de se prosseguir para o prximo exemplo considere a seguinte simulao de execuo da funo soma assumindo que a coleco passada como parmetro tem os seguintes elementos:<2,4,3>.
num 1 2 3 i 1 1 soma 0 0 0 Uma vez que a condio verdadeira, ou seja o valor de i no superior a col.count() as instrues dentro do ciclo sero executadas. atribudo a soma a acumulao do seu valor prvio com o valor do elemento na posio i. a varivel i incrementada por uma unidade. a instruo Wend determina o fim da instruo WHILE e provoca um salto para a linha onde se encontra o inicio da definio desta instruo, ou seja a linha 3. Uma vez que a condio verdadeira, ou seja o valor de i no superior a col.count() as instrues dentro do ciclo sero executadas. atribudo a soma a acumulao do seu valor prvio com o valor do elemento na posio i. a varivel i incrementada por uma unidade. Salto para a linha onde se encontra o inicio da definio desta instruo, ou seja a linha 3. Uma vez que a condio verdadeira, ou seja o valor de i no superior a col.count() as instrues dentro do ciclo sero executadas. atribudo a soma a acumulao do seu valor prvio com o valor do elemento na posio i. a varivel i incrementada por uma unidade. Salto para a linha onde se encontra o inicio da definio desta instruo, ou seja a linha 3. A condio falsa, ou seja o valor de i superior a col.count() o ciclo termina e a prxima instruo ser a instruo imediatamente a seguir instruo Wend. Neste caso como no
37/61
4 5 6
1 2 2
0+2 = 2 2 2
4 5 6 3
2 3 3 3
2+4 = 6 6 6 6
4 5 6 3
3 4 4 4
6+3 = 9 9 9 9
Considere agora o caso em que se pretende realizar uma procura de um determinado elemento numa coleco, sendo ambos os valores passados como parmetro. O esqueleto da funo equivalente ao definido anteriormente para os ciclos FOR, ou seja:
Function procura(elem, col) ... End Function
Apresenta-se de seguida uma verso da funo procura semelhante apresentada com ciclos FOR mas desta vez utilizando ciclos WHILE.
Function procura(elem, col) procura = false i = 1 While (i <= col.count()) If elem = col.Item(i) Then procura = true End If i = i + 1 Wend End Function
A funo acima apresentada sofre do mesmo problema que a sua homnima com ciclos FOR. No entanto com ciclos WHILE possvel resolver o problema da ineficincia presente na soluo com ciclos FOR. A essncia da questo definir quando sair do ciclo WHILE, ou por outras palavras, enquanto permanecer dentro do ciclo. A funo acima define como condio de permanncia no ciclo o facto de a varivel i referenciar uma posio dentro dos limites da coleco. No entanto a varivel procura completamente ignorada nesta condio. Ou seja traduzindo para Portugus corrente actualmente a condio especificada : Procurar at ao fim, ignorando o facto de se encontrar a meio Na realidade o que se pretende a conjuno das duas condies apresentadas a seguir: 1. Procurar at ao fim 2. Procurar at encontrar. A condio 1 j se encontra definida. Resta agora definir a condio 2. De acordo com o cdigo acima apresentado sabe-se que enquanto o elemento no for encontrado na coleco a varivel procura ser false. Sendo assim a segunda condio poder ser: procura = false O cdigo completo com a nova condio agora apresentado:
38/61
Function procura(elem, col) procura = false i = 1 While (i <= col.count()) AND (procura = false) Then If elem = col.Item(i) Then procura = true End If i = i + 1 Wend End Function
O cdigo acima pode ser reescrito de forma a simplificar o ciclo. Considere a seguinte funo como uma primeira tentativa para resolver o problema:
Function procura(elem, col) 1 i = 1 2 While (i <= col.count()) AND (elem <> col.Item(i)) Then 3 i = i + 1 4 Wend End Function
A condio desta ultima funo especifica que o ciclo ser executado enquanto: 1. a posio actual, varivel i, estiver dentro dos limites da coleco 2. o elemento for diferente do elemento actual A segunda condio garante que mal se encontre um elemento na coleco igual ao elemento passado como parmetro o ciclo terminado. A funo no est completa uma vez que nunca definido qual o resultado da funo, ou seja no existe nenhuma atribuio varivel procura (nome da funo). Duas simulaes de execuo so agora apresentadas, a primeira em que o elemento existe na coleco, a seguinte em que o elemento no se encontra na coleco. Simulao de execuo da ultima verso da funo procura com os seguintes parmetros: elem = 2, col = <3,2,4>
num 1 2 3 4 2 i 1 1 2 2 2 col.item(i) 3 3 2 2 2 Salto para a linha 3 A condio falsa porque elem = col.item(i). Salto para o fim da funo. Condio verdadeira. obs.
O valor de i 2, ou seja indica a posio em que elem se encontra na coleco. Considere agora que os parmetro eram: elem = 5, col = <3,2,4>.
39/61
num 1 2 3 4 2 3 4 2 3 4 2
i 1 1 2 2 2 3 3 3 4 4 4
col.item(i) 3 3 2 2 2 4 4 4 -
obs.
Condio verdadeira. Salto para a linha 3. Condio verdadeira. Salto para a linha 3. Condio verdadeira. Salto para a linha 3. A condio falsa porque 4 superior a col.count(), ou seja a posio actual, 4, est fora dos limites da coleco. Salto para o fim da funo.
Neste caso o valor da varivel i 4. Este valor indica que o elemento procurado no se encontra na coleco, uma vez que o processo de procura foi terminado por termos esgotado os elementos da coleco. Pode-se ento concluir que, ao terminar o ciclo, caso a varivel i esteja dentro dos limites da coleco ento o elemento existe na coleco, caso contrrio, ou seja se i for maior que o nmero de elementos da coleco, ento o elemento no existe na coleco. Sendo assim deve-se acrescentar as seguintes linhas a seguir ao ciclo:
If i <= col.count() Then procura = true Else procura = false End If
O cdigo completo :
Function procura(elem, col) i = 1 While (i <= col.count()) AND (elem <> col.Item(i)) Then i = i + 1 Wend If i <= col.count() Then procura = true Else procura = false End If End Function
40/61
Um ultimo pormenor de interesse nesta funo reside na ordem das condies do ciclo WHILE. Caso a ordem fosse inversa ou seja,
While (elem <> col.Item(i)) AND (i <= col.count()) Then
ento o Visual Basic terminaria a execuo em erro caso o elemento no existisse na coleco. O erro deve-se ao facto de o valor final de i ser superior ao nmero de elementos da coleco (porque o elemento no existe), logo col.Item(i) no se encontra definido. Na ordem original,
While (i <= col.count()) AND (elem <> col.Item(i)) Then
este problema no se levanta porque a primeira condio falsa, e ao realizar a conjuno de condies (AND), desde que uma das condies seja falsa a conjuno tambm falsa e logo no necessrio calcular as restantes condies. Ou seja, para o valor final de i, como a condio i <= col.count() falso o VB no calcula a outra condio, uma vez que a conjuno de uma condio falsa com outra condio sempre falsa, independentemente do valor da outra condio. Resumindo o VB s calcula o estritamente necessrio para obter um resultado. A esta estratgia d-se o nome de "lazy evaluation". Nas funes anteriores o resultado devolvido corresponde em Portugus a "encontrei" ou "no encontrei". No entanto esta resposta pode no ser a pretendida, muitas vezes pretende-se saber no s se o elemento existe na coleco mas tambm caso exista em que posio se encontra. A funo apresentada acima pode ser reescrita para devolver false caso o elemento no se encontre na coleco e a sua posio caso o elemento exista. Uma vez que a varivel i representa a posio do elemento caso este exista na coleco o cdigo final desta verso ser:
Function procura(elem, col) i = 1 While (i <= col.count()) AND (elem <> col.Item(i)) Then i = i + 1 Wend If i <= col.count() Then procura = i Else procura = false End If End Function
41/61
FOR
Function soma(col) soma = 0 For i = 1 To col.count() soma = soma + col.item(i) Next i End function
WHILE
Function soma(col) soma = 0 i = 1 While i <= col.count() soma = soma + col.item(i) i = i + 1 Wend End function
A verso que utiliza o ciclo FOR EACH a mais simples, no necessrio especificar limites para o ciclo. A forma de se obter o elemento tambm mais simples utilizando a instruo FOR EACH, no sendo necessrio recorrer a ndices. A instruo FOR implica a definio dos limites, ou seja col.count(). A terceira verso implica a inicializao separada do limite inferior , assim como o incremento manual da varivel i. Em termos de simplicidade as trs instrues poderiam ser apresentadas pela seguinte ordem, da mais simples mais complexa: 1. FOR EACH 2. FOR 3. WHILE Em termos de versatilidade a ordem exactamente a inversa. Isto natural uma vez que a simplicidade advm do facto de se restringir a utilizao a casos concretos. A instruo FOR EACH s deve ser utilizada quando se pretende percorrer uma coleco do principio ao fim. A instruo FOR permite definir intervalos diferentes do inicial, 1, e final, count() sendo portanto mais verstil. Por sua vez a instruo WHILE permite especificar qualquer tipo de condio. A vantagem da utilizao dos ciclos WHILE evidente quando se realiza uma operao cujo critrio de sada do ciclo no depende de um limite fixo. Um exemplo deste tipo de operaes a procura de um determinado elemento em que no se sabe partida a sua posio na coleco. 2.6.4.1 Converso de instrues cclicas FOR EACH - FOR possvel realizar a converso de qualquer instruo cclica FOR EACH para uma instruo FOR. A regra para a converso a seguinte: Para o esqueleto da instruo a converso realizada tal como se apresenta na tabela em baixo:
FOR EACH elem in coleco ... Next elem FOR i = 1 to coleo.count() ... Next i
42/61
Para o corpo de instrues dentro dos ciclos as alteraes a realizar prendem-se com o facto de ser necessrio substituir as referencias a elem, no caso dos ciclos FOR EACH, por referencias a coleo.item(i), para os ciclos FOR. De seguida apresentam-se as funes completas para o caso da soma com as diferenas sublinhadas:
Function soma(col) soma = 0 For Each elem In col soma = soma + elem Next elem End function Function soma(col) soma = 0 For i = 1 To col.count() soma = soma + col.item(i) Next i End function
Note-se que a passagem de ciclos FOR para ciclos FOR EACH nem sempre possvel. S possvel converter um ciclo FOR num ciclo FOR EACH no caso em que os limites iniciais e finais correspondem ao inicio e fim da coleco. Para alem disso necessrio que as indexaes a elementos nos ciclos FOR sejam todas do tipo col.item(i) sendo i a varivel utilizada no ciclo. A titulo de exemplo apresenta-se agora um ciclo FOR que no pode ser convertido para um ciclo FOR EACH.
Function soma5a10(col) soma = 0 For i = 5 To 10 soma = soma + col.item(i) Next i End function
2.6.4.2 Converso de instrues cclicas FOR - WHILE Um ciclo FOR pode ser sempre convertido para um ciclo WHILE seguindo um processo automtico da seguinte forma:
Function xpto(col) soma = 0 For i = inicio To fim Function xpto(col) soma = 0 i = inicio While i <= fim instrues i = i + 1 Wend End function
As instrues dentro do ciclo no sofrem qualquer alterao ao converter o ciclo de FOR para WHILE. A converso no sentido inverso nem sempre possvel. Por exemplo a funo soma pode ser escrita com um ciclo WHILE ou com um ciclo FOR, no entanto a funo procura escrita com um ciclo WHILE no tem traduo directa para um ciclo FOR uma vez que a conjuno de condies no pode ser especificada em ciclos FOR.
43/61
O Excel permite introduzir formulas para clculo de valores a partir dos valores existentes na folha de clculo. Por exemplo poder-se-ia seleccionar a clula D2 e introduzir a formula para o clculo da variao diria.
Para escrever uma formula em Excel necessrio digitar o smbolo "=" antes de escrever a formula propriamente dita. A formula da figura 3.2 realiza a subtraco entre os valores das clulas C2 e B2. Note-se que a conveno no Excel para definir uma clula consiste em especificar primeiro a coluna e depois a linha pretendida. Escrever a frmula "=C2-B2" implica que o Excel execute os seguintes passos: 1. calcule o valor dessa expresso 2. e que atribua o valor da expresso clula activa, neste caso D2. Para aplicar a formula s outras linhas basta copi-la para D3,D4,etc... O Excel automaticamente refaz as referencias s clulas dentro das frmulas, ou seja, ao copiar a formula da clula D2 para a clula D3, desceu-se uma linha, logo o Excel automaticamente altera todas as referencias da frmula de forma a que sejam referentes linha 3. A frmula resultante da cpia :
44/61
=C3-B3 Considere-se agora um outro exemplo: pretende-se calcular o preo com IVA de um conjunto de artigos, aplicando o IVA ao preo. Na folha de clculo, figura 3.3, acrescentou-se uma clula com o valor do IVA em vez de utilizar o valor directamente. Com esta estratgia pretende-se a reduo das alteraes necessrias caso a taxa do IVA seja modificada. Caso se utilizasse o valor do IVA directamente na frmula, =B2*1.17, seria necessrio alterar todas as frmulas quando a taxa fosse modificada, desta forma basta alterar o valor da clula E1. Como ilustrado na figura que se segue, a frmula correcta para o clculo do preo com IVA : = B2 * $E$1
Os smbolos $ indicam que a referncia a esta clula no varia quando a frmula copiada, ou seja caso a frmula seja copiada para a clula C3, a frmula resultante ser: = B3 * E1 S a referncia clula B2 foi alterada para B3, a referncia a E1 manteve-se. Em Visual Basic pode-se definir a seguinte funo:
Function IVA(a, b) IVA = a * b End Function
Para invocar esta funo escreve-se = IVA(B2,$E$1) tal como ilustrado na figura que se segue.
45/61
Como se pode inferir do cdigo da funo acima os conceitos de Visual Basic apresentados anteriormente so directamente aplicveis ao Excel.
Em VB o acesso a uma clula feito segundo regras diferentes das do Excel. Enquanto em Excel se referncia uma clula atravs da sua coluna e linha, em VB utiliza-se a funo Cells que tem dois argumentos, a linha e a coluna. Note-se que a ordem de referncia entre o Excel e o VB inversa, ou seja em Excel primeiro indica-se a coluna e depois a linha, enquanto que em VB especifica-se primeiro a linha e depois a coluna. Apresentam-se de seguida alguns exemplos: Excel A2 B1 E1 Visual Basic Cells(2,1) Cells(1,2) Cells(1,5)
46/61
Note-se que ao alterar o valor da clula E1 o resultado desta funo no imediatamente alterado. Por omisso, o Excel s actualiza automaticamente as clulas com formulas que referenciam nos seus parmetros clulas que foram alteradas. A ultima verso da funo IVA no contem como parmetro a clula E1, logo no automaticamente actualizada. Para actualizar todos os resultados deve-se utilizar a opo "Calculate Full" disponvel no Excel 2000. Esta opo realiza as actualizaes pretendidas, ou seja, se a clula E1 for alterada, ento todas as clulas s quais a funo IVA foi aplicada tambm sero actualizadas embora no existe nenhuma referencia clula E1 no cabealho da funo IVA. Na ultima verso da formula reduziu-se o nmero de parmetros desta de 2 para 1. A questo que se pe qual a vantagem da reduo do nmero de parmetros de uma funo? No caso geral se um parmetro pode ser calculado custa de outro ento desnecessrio. A sua eliminao da lista de parmetros evita erros de invocao da funo como por exemplo: Preo(B2, E1) em vez de Preo(B2, $E$1) No entanto em Excel existe potencialmente uma desvantagem de eliminar parmetros que sejam referencias a clulas caso se altera a estrutura da folha de clculo. Ao utilizar o comando "Insert Column" do Excel este desloca todas as colunas desde o ponto de insero uma coluna para a direita. Sendo assim caso se utilizasse o comando "Insert Column" na coluna C, localizao da clula do IVA passaria a F1.
figura 3.5 Resultado da insero de uma coluna com o comando "Insert Column"
Como se pode ver na figura 3.5 a frmula utilizando dois parmetros automaticamente actualizada. O Excel refaz todas as referencias a clulas presentes em frmulas de forma a compensar a operao realizada, neste caso a insero de uma nova coluna. No caso da segunda verso, em que s existe um parmetro: a clula do preo, o Excel no actualiza o cdigo da funo onde a referencia realizada (Cells(1,5)). Para obter um resultado correcto aps a insero da coluna utilizando o comando "Insert Column" seria necessrio actualizar manualmente o cdigo da funo.
47/61
Resumindo: desde que se garante que a estrutura da folha de clculo no alterada vantajoso reduzir o nmero de parmetros de forma a evitar erros de invocao como exemplificado acima. No entanto se no se puder garantir que a estrutura no alterada ento necessrio considerar se convm introduzir todos os parmetros. Uma vez que o mbito desta seco referenciar clulas de uma folha de clculo em Visual Basic sero apresentados mais exemplos onde o nmero de parmetros reduzido ao mnimo possvel. No entanto ao realizar um trabalho em Excel necessrio ter em ateno as consideraes acima enunciadas sobre os prs e contras da reduo de parmetros e analisar caso a caso qual a melhor estratgia. Considere agora que na folha de clculo acima definida era acrescentada mais uma coluna com uma percentagem de desconto para cada item. Pretende-se definir uma funo em VB para o clculo do preo final de acordo com a seguinte expresso em Excel:
A funo em VB :
Function Preo(a, b) Preo = a * ((100 - b)/100) * Cells(1,5) End Function
Por razes de clareza pode-se dividir a funo em vrias linhas, por exemplo:
Function Preo(a, b) IVA = Cells(1,5) Preo = a * ((100 - b)/100) * IVA End Function
Ou ainda
48/61
Function Preo(a, b) IVA = Cells(1,5) PercentagemPagar = (100 - b) / 100 Preo = a * PercentagemPagar * IVA End Function
Desta forma a leitura da funo fica facilitada. Uma leitura atenta desta ultima funo permite concluir que afinal s necessrio um parmetro. O segundo parmetro sempre a clula na coluna seguinte do primeiro argumento. Pode-se ento simplificar a invocao da frmula de forma a s ter um parmetro. Ou seja, a invocao seria = Preo(B2) necessrio modificar a funo em VB de forma a reflectir a alterao desejada. O cabealho da funo fica portanto alterado de modo a reflectir a reduo do nmero de parmetros para:
Function Preo(a)
.... O problema reside no facto de como referenciar a clula que se encontra na coluna a seguir coluna do primeiro argumento, sendo a linha comum. A funo Cells devolve uma referncia a uma clula. Por omisso o VB entende a referencia clula como o seu valor. No entanto uma clula representa um conjunto de propriedades que a definem e no s o seu valor, entre estas temos: valor (Value) no necessrio especificar, j que o VB por omisso assume que se pretende o valor da clula linha (Row) coluna (Column)
Sendo assim, assumindo que o parmetro da funo a, possvel saber a coluna da linha referenciada atravs da expresso: a.Column Analogamente para a linha: a.Row Sendo assim a referncia clula na coluna seguinte clula do primeiro argumento Cells(a.Row, a.Column+1) A funo em VB portanto:
Function Preo(a) Preo = a * ((100-Cells(a.Row, a.Column+1)) / 100) * Cells(1, 5) End Function
49/61
desconto = Cells(a.Row, a.Column + 1) PercentagemPagar = ((100 -desconto) / 100) Preo = a * PercentagemPagar * IVA End Function
figura 3.8 - Folha de Clculo Excel com os artigos e respectivos tipos de desconto
Para definir os escales de descontos utiliza-se uma nova folha de clculo cuja estrutura apresentada na figura seguinte. Nesta folha de clculo o escalo de desconto 1 apresentado na linha 1, o escalo 2 na linha 2, e assim sucessivamente.
Nota: Os nomes das folhas de clculo de um "Livro" Excel so apresentados numa barra na parte inferior da aplicao.
50/61
figura 3.10 - Barra com os nomes das folhas de clculo de um "Livro" Excel
Os nomes apresentados so os atribudos por omisso pelo prprio Excel. Para facilitar a legibilidade das frmulas e /ou funes VB deve-se alterar esses nomes de forma a atribuir carga semntica.
Nota: Para alterar os nomes de uma folha de clculo faz-se um duplo clique no nome que pretende alterar e introduz-se o novo nome. Recapitulando: A folha de clculo da figura 3.8 a folha "artigos" e a folha da figura 3.9 a folha "escales". Qual o PVP do artigo "Camisa Riscas"? Sabe-se que o seu preo de 4750$00, o IVA 1.17, e o desconto a aplicar 25% (escalo 3). O desconto 25% porque se consultou a linha 3 da folha "escales", ou seja, os descontos esto na folha "escales", na coluna A e na linha indicada pela coluna "Escalo" na folha "artigos". Do ponto de vista da escrita da expresso do clculo do preo em Excel, este exemplo levanta um problema: Como referenciar em Excel a clula na folha de clculo "escales" na coluna A e na linha indicada na coluna C da folha "artigos"? Para resolver este problema necessrio ir por partes: 1. para referenciar uma clula noutra folha de clculo escreve-se o nome da folha, seguido de ! e da referncia clula. Por exemplo para referenciar a clula A1 da folha "escales" escreve-se: escales!A1 2. No nosso caso sabe-se que o desconto est na folha "escales", na coluna A, na linha indicada pela coluna "Escalo" da folha "artigos". Por exemplo, se se considerar o artigo "Camisa Riscas", sabe-se que a referncia clula que contm o desconto a aplicar : escales!A3 3. Infelizmente no se pode escrever algo do gnero: escales!A(valor de C3) 4. Pode-se no definir um texto que represente a referncia correcta. A parte fixa deste texto "escales!A", sendo a parte varivel o numero da linha, ou seja supondo que a frmula est a ser escrita para a segunda linha, o valor da clula C2. Se juntarmos estes dois valores ficamos com o texto "escales!A1" que representa a referncia pretendida.
51/61
5. Para juntar um texto a outro texto, ou a um valor, utiliza-se a funo CONCATENATE, ou seja a referncia textual clula que contm o desconto para o artigo na linha 2 da folha "artigos" : CONCATENATE("escales!A",C2) pois o valor de C2 indica a coluna onde se encontra o valor a descontar para o artigo da linha 2. 6. O problema agora resume-se a dada uma referncia em formato de texto obter a clula desejada. Para tal utiliza-se a funo INDIRECT, ou seja para obter o valor do desconto para o artigo na linha 2 temos de escrever algo do gnero: INDIRECT(CONCATENATE("escales!A",C2)) Podemos finalmente escrever a nossa expresso em Excel para o clculo do PVP como se ilustra na figura seguinte:
figura 3.12: Frmula para clculo do PVP com referncia a outra folha de clculo
Felizmente em VB as coisas so mais simples! Os conceitos j apresentados so quase suficientes para escrever a frmula, sendo s necessrio introduzir uma funo para acesso a uma clula noutra folha de clculo. Ao escrever Cells(linha, coluna) por omisso, a referencia a uma clula na folha de clculo activa. Para referenciar uma clula noutra folha de clculo escreve-se Worksheets(nome_da_folha_de_clculo).Cells(linha, coluna) Sendo assim a funo em VB fica
Function PVP(preo) IVA = Cells(1, 5) escalo = Cells(preo.Row, preo.Column + 1) desconto = Worksheets("escales").Cells(escalo, 1) PercentagemPagar = (100 - desconto) / 100 PVP = preo.Value * PercentagemPagar * IVA End Function
1 2 3 4 5
Apresenta-se de seguida a simulao de execuo desta funo assumindo que invocada com o parmetro B2, ou seja PVP(B2).
num 1 2 escalo 1 escalo 1 desconto percentagemPagar obs. IVA = valor da clula E1, ou seja 1.17 escalo = valor da clula C2,
52/61
ou seja a clula na coluna a seguir a B2. O valor 1. 3 1 1 15 desconto = valor da clula A1 (escalo = 1) da folha de clculo "Escales", ou seja, 15. 0.85 0.85 percentagemPagar = (100-15)/100 5 1 1 15 Como todos os dados agora calcula-se o PVP, ou seja PVP = 4500 * 0.85 * 1.17
15
Diferena entre esta verso da funo em VB e a anterior em que os descontos eram definidos artigo a artigo pequena, mas em Excel enorme!!! A formula em Excel de muito difcil leitura quando comparada com a funo em VB. Para tarefas com um grau de complexidade razovel o VB permite definir a soluo de forma mais clara e legvel.
A figura 3.13 apresenta uma folha de clculo onde se realiza a invocao de uma funo soma que recebe como parmetro uma coleco de clulas. O cdigo da funo exactamente igual ao definido para coleces de valores em 2.6.1:Ciclos FOR EACH.
Function total(coleco) soma = 0 For Each elem In coleco soma = soma + elem Next elem
53/61
O primeiro exemplo aqui apresentado consiste em definir uma funo que determine em que coluna se encontram os dados de uma determinada empresa. O parmetro desta funo o nome da empresa. Para implementar esta funo deve-se percorrer a primeira linha da folha de clculo desde a segunda coluna at encontrar o nome da empresa ou at encontrar uma clula vazia (EMPTY).
Function procuraEmp(nome) col = 2 linha = 1 While (Cells(linha, col) <> Empty And Cells(linha, col) <> nome) col = col + 1 Wend If Cells(linha, col) = nome Then procuraEmp = col Else procuraEmp = "No Existe" End If End Function
Resultados desta funo sero: Invocao =procuraEmp("EDP") =procuraEmp("PT") =procuraEmp("EPT") Resultado 2 4 "No existe"
De seguida apresenta-se uma funo que dada uma coluna onde se encontram os dados de uma empresa devolve a ultima cotao disponvel. Para implementar esta funo define-se um ciclo que percorra a coluna passada como parmetro desde a segunda linha, primeira cotao, at encontrar uma clula vazia. O valor da clula na linha acima da linha onde se encontra a clula vazia o valor da ultima cotao.
Function ultimacot(coluna)
54/61
linha = 2 While Cells(linha, coluna) <> Empty linha = linha + 1 Wend ultimacot = Cells(linha - 1, coluna) End Function
Resultados desta funo sero: Invocao = ultimacot (2) = ultimacot (3) = ultimacot (4) Resultado 25.3 48.5 44.2
Seguidamente apresenta-se uma funo para determinar qual a linha onde se encontra uma determinada data. Esta funo semelhante apresentada para procurar uma empresa dado o seu nome, s que desta vez a procura realizada nas linhas e no nas colunas.
Function procuraData(data) col = 1 linha = 2 While (Cells(linha, col) <> Empty And Cells(linha, col) <> data) linha = linha + 1 Wend If Cells(linha, col) = data Then procuraData = linha Else procuraData = "No Existe" End If End Function
Finalmente apresenta-se uma funo que utilizando as funes acima definidas ir calcular a cotao de uma empresa numa determinada data. Para tal necessrio determinar em que coluna se encontra a empresa, seguidamente encontrar em que linha se encontra a data e finalmente devolver como resultado o valor da clula na linha e coluna encontradas.
Function cotao(emp, dia) col = procuraEmp(emp) linha = procuraData(dia) cotao = Cells(linha, col) End Function
Exemplo: escrever uma funo que tem como argumento um ndice de uma linha. O resultado desta funo o ndice da coluna que contem a primeira clula vazia.
Function procuraVazia(linha) i = 1 While (Cells(linha, i) <> Empty) i = i + 1
55/61
Caso se invocasse procuraVazia(2) Exerccio proposto: implemente uma funo para determinar a posio da ensima clula vazia. A funo dever receber como parmetro um ndice de uma linha. Exerccio: Escrever uma funo que some os elementos de uma linha desde o elemento a seguir primeira clula vazia at encontrar a segunda clula vazia.
Function soma2(linha) soma2 = 0 i = procuraVazia(linha) + 1 While (Cells(linha, i) <> Empty) soma2 = soma2 + Cells(linha, i) i = i + 1 Wend End Function
No caso da folha de clculo acima apresentada o resultado seria 6+7 = 13. Exerccio: Escreva uma funo que determine a soma dos elementos de uma coleco, considerando somente os elementos superiores mdia: Primeiro vamos calcular a mdia, e seguidamente realizaremos a soma.
Function mdia(A) soma = 0 For Each elem In A soma = soma + elem Next elem mdia = soma / A.Count() End Function
Esta primeira verso de uma funo para calcular a mdia contabiliza os elementos vazios no clculo da mdia. A verso seguinte no conta os elementos vazios.
Function mdia2(A) soma = 0 contador = 0
56/61
For Each elem In A soma = soma + elem If elem <> Empty Then contador = contador + 1 End If Next elem mdia2 = soma / contador End Function
O resultado desta funo 17. Verifique! Exerccio proposto: faa uma simulao de execuo para as funes acima apresentadas.
57/61
Note-se que a varivel linha ao sair do ciclo indica a primeira linha no preenchida. O resultado da funo a linha anterior, ou seja a ltima linha preenchida. Para saber qual a cotao de um determinado dia precisamos tambm de saber qual a linha e coluna em que o valor se encontra. A coluna obtm-se como explicado anteriormente, para descobrir a linha temos de fazer uma procura de uma determinada data.
Function procuraData(d) linha = 2 // primeira linha onde aparecem datas While (Cells(linha,1) <> d) linha = linha + 1 Wend procuraData = linha End Function
Nesta funo assumimos que a data existe. Podemos agora construir a funo pretendida:
Function variao(empresa, data) emp = procura(1,2,empresa)
58/61
linhaUltimaData = procuraUltimaData() linhaData = procuraData(data) ultimaCotao = Cells(linhaUltimaData, emp) cotaoData = Cells(linhaData, emp) variao = ultimaCotao - cotaoData End Function
Um exemplo de invocao para determinar a variao da Brisa em escudos desde 6 de Janeiro de 99 seria:
Vejamos como seria a funo variao se no tivssemos decomposto o problema, ou seja se escrevssemos todo o cdigo numa s funo:
Function variao(empresa, data) emp = 2 While (Cells(1, emp) <> empresa) emp = emp + 1 Wend linhaUltimaData = 2 While (Cells(linhaUltimaData, 1) <> Empty) linhaUltimaData = linhaUltimaData + 1 Wend linhaUltimaData = linhaUltimaData - 1 linhaData = 2 While (Cells(linhaData, 1) <> data) linhaData = linhaData + 1 Wend ultimaCotao = Cells(linhaUltimaData, emp) cotaoData = Cells(linhaData, emp) variao = ultimaCotao - cotaoData End Function
Como podemos ver a leitura desta ltima funo bastante mais complicada, no entanto o resultado o mesmo, assim como a sua invocao. Ao decompor o problema nos sub problemas que o definem obtemos uma maior legibilidade. Podemos ainda complicar um pouco mais e pedir qual a coluna da empresa que registou a variao mxima em escudos. Ou seja uma funo para calcular o mximo das
59/61
variaes calculadas anteriormente. Esta funo s tem um parmetro, a data. A empresa no parmetro uma vez que todas as empresas vo ser testadas.
Function maxVar(data) col = 2
' col inicializado com a primeira coluna ' onde aparecem empresas
mximo = -99999
' o mximo colocado a um valor inferior ' a qualquer variao que se possa verificar
' o ciclo termina quando no existirem mais empresas ' calculo da variao da empresa da coluna col ' para uma varivel auxiliar, var1
' se a variao for superior ao mximo at ento, ' alterar o mximo e a coluna da empresa ' que verificou a variao
col = col + 1
Note-se que esta funo extremamente ineficiente j que ao invocar a funo variao para cada empresa estamos sempre a procurar a linha da data assim como da ultima data. Uma verso optimizada da funo poderia ser escrita reescrevendo a funo variao de modo a retirar as procuras nela existentes:
Function variao2(col_empresa, linhaData, linhaUltimaData) ultimaCotao = Cells(linhaUltimaData, col_empresa) cotaoData = Cells(linhaData, col_empresa) variao2 = ultimaCotao - cotaoData End Function
60/61
Nesta verso da funo variao temos como parmetros as linhas e a coluna em que se encontram os valores pretendidos, a funo s faz o clculo da diferena. A funo maxVar deve ento incluir as procuras necessrias para fornecer os parmetros funo variao
Function maxVar(data) col = 2 mximo = -99999 linhaData = procuraData(data) linhaUltimaData = procuraUltimaData() While (Cells(1, col) <> Empty) var1 = variao2(col, linhaData, linhaUltimaData) If var1 > mximo Then mximo = var1 maxVar = col End If col = col + 1 Wend End Function
A invocao exactamente igual da verso anterior, no entanto esta ltima funo mais eficiente pois s executa uma vez as funes procuraData e procuraUltimaData.
61/61