5. Funções e procedimentos
5.1. Funções predefinidas do VBScript
A riqueza de uma linguagem deriva em grande parte da sua biblioteca de funções, uma vez que estas funções podem ser encapsuladas em objetos sob o nome de métodos. A este respeito, o VBScript pode ser considerado bastante limitado.
A tabela seguinte lista as funções do VBScript fora dos objetos. Não entraremos em detalhes sobre elas. Os seus nomes indicam geralmente a sua finalidade. Os leitores devem consultar a documentação para obter detalhes sobre uma função específica.
Abs | Array | Asc | Atn |
CBool | CByte | CCur | CDate |
CDbl | Chr | CInt | CLng |
Conversões | Cos | CreateObject | CSng |
Date | DateAdd | DateDiff | DatePart |
DataSerial | Valor da data | Dia | Matemática derivada |
Avaliação | Exp | Filtro | Formato de moeda |
Formato de data e hora | Formato numérico | Formato de percentagem | GetLocale |
GetObject | ObterReferência | Hex | Hora |
Caixa de Entrada | InStr | InStrRev | Int, Fixs |
IsArray | IsDate | IsEmpty | IsNull |
É numérico | ÉObjeto | Juntar | LBound |
LCase | Esquerda | Len | CarregarImagem |
Log | LTrim; RTrim; e Trims | Matemática | Mid |
Minuto | Mês | Nome do mês | Caixa de mensagem |
Agora | Out | Substituir | RGB |
Direita | Rnd | Redondo | ScriptEngine |
Versão da compilação do ScriptEngine | Versão principal do ScriptEngine | ScriptEngineMinorVersion | Segundo |
SetLocale | Sgn | Pecado | Espaço |
Divisão | Sqr | StrComp | String |
Tan | Time | Timer | TimeSerial |
TimeValue | Nome do tipo | LimiteSuperior | Maiúsculas |
VarType | Dia da semana | Nome do dia da semana | Ano |
5.2. Programação modular
Descrever a solução programada para um problema significa descrever a sequência de operações básicas que podem ser executadas pelo computador e que são capazes de resolver o problema. Dependendo da linguagem de programação, estas operações básicas variam em complexidade. Exemplos incluem:
- ler dados do teclado ou do disco
- escrever dados no ecrã, numa impressora, num disco, etc.
- calcular expressões
- navegar por um ficheiro
- ...
Descrever um problema complexo pode exigir vários milhares destas instruções básicas ou mais. Por isso, é muito difícil para a mente humana compreender o panorama geral de um programa. Confrontados com esta dificuldade em compreender o problema como um todo, dividimo-lo em subproblemas que são mais fáceis de resolver. Considere o seguinte problema: Ordenar uma lista de valores numéricos introduzidos através do teclado e apresentar a lista ordenada no ecrã.
Podemos inicialmente descrever a solução da seguinte forma:
début
lire les valeurs et les mettre dans un tableau T
trier le tableau T
écrire les valeurs triées du tableau T à l'écran
fin
Dividimos o problema em 3 subproblemas, que são mais fáceis de resolver. A notação algorítmica é frequentemente mais formalizada do que a anterior, e o algoritmo seria escrito da seguinte forma:
onde T representa uma matriz. As operações
são operações não elementares que, por sua vez, devem ser descritas por operações elementares. Isto é feito no que se denomina módulos. Os dados T são denominados parâmetros do módulo. Trata-se de informação que o programa chamador passa para o módulo chamado (parâmetro de entrada) ou recebe do módulo chamado (parâmetro de saída). Os parâmetros de um módulo são, portanto, a informação trocada entre o programa chamador e o módulo chamado.
módulo read_array(T) | ![]() |
módulo sort_array(T) | ![]() |
módulo read_array(T) | ![]() |
O módulo read_array(T) pode ser descrito da seguinte forma:
début
écrire "Tapez la suite de valeurs à trier sous la forme val1 val2 ... : "
lire valeurs
construire tableau T à partir de la chaîne valeurs
fin
Aqui, descrevemos de forma exaustiva o módulo read_array. De facto, as três ações necessárias têm uma tradução imediata para VBScript. A última exigirá a utilização da função Split. Se o VBScript não dispusesse desta função, a ação 3 teria, por sua vez, de ser dividida em ações elementares com um equivalente imediato em VBScript.
O módulo write_array(T) poderia ser descrito da seguinte forma:
début
construire chaîne texte "valeur1,valeur2,...." à partir du tableau T
écrire texte
fin
O módulo write_array(T) poderia ser descrito da seguinte forma (assumindo que os índices dos elementos de T começam em 0):
début
N<-- indice dernier élément du tableau T
pour IFIN variant de N à 1
faire
//on recherche l'indice IMAX du plus gd élément de T
// IFIN est l'indice du dernier élément de T
chercher_max(T, IFIN, IMAX)
// on échange l'élément le plus grand de T avec le dernier élément de T
échanger (T, IMAX, IFIN)
finfaire
FIN
Aqui, o algoritmo volta a utilizar ações não elementares:
. chercher_max(T, IFIN, IMAX)
. échanger(T, IMAX, IFIN)
find_max(T, IFIN, IMAX) devolve o índice IMAX do maior elemento da matriz T cujo último elemento tem o índice IFIN.
![]() |
swap(T, IMAX, IFIN) troca dois elementos da matriz T, os que se encontram nos índices IMAX e IFIN.
![]() |
Devemos, portanto, descrever as novas operações não elementares.
módulo find_max(A, IFIN, IMAX) | |
módulo de troca(T IMAX, IFIN) |
O problema inicial foi descrito na íntegra utilizando operações básicas do VBScript e pode, portanto, ser agora traduzido para esta linguagem. Note-se que as operações básicas podem diferir de uma linguagem para outra e, por isso, a análise de um problema deve, em algum momento, ter em conta a linguagem de programação utilizada. Um objeto que existe numa linguagem pode não existir noutra, alterando assim o algoritmo utilizado. Assim, se uma linguagem tivesse uma função de ordenação, seria absurdo não a utilizar aqui.
O princípio aqui aplicado é conhecido como análise top-down. Se delinearmos a estrutura da solução, temos o seguinte:
![]() |
Temos uma estrutura em árvore.
5.3. Funções e procedimentos VBScript
Depois de realizada a análise modular, o programador pode traduzir os módulos do seu algoritmo em funções ou procedimentos VBScript. Tanto as funções como os procedimentos aceitam parâmetros de entrada/saída, mas uma função devolve um resultado que permite a sua utilização em expressões, ao passo que um procedimento não o faz.
5.3.1. Declaração de funções e procedimentos VBScript
A declaração de um procedimento VBScript é a seguinte
e o de uma função
Para devolver o seu resultado, a função deve incluir uma instrução de atribuição que atribua o resultado a uma variável com o mesmo nome que a função:
nomeDaFunção=resultado
A execução de uma função ou procedimento termina de duas formas:
- ao encontrar a instrução end function ou end sub
- ao encontrar a instrução exit function ou exit sub
No caso de uma função, note que o resultado deve ter sido atribuído a uma variável com o nome da função antes de a função terminar com uma instrução end function ou exit function.
5.3.2. Modos de passagem de parâmetros para uma função ou procedimento
Na declaração dos parâmetros de entrada-saída de uma função ou procedimento, é especificado o modo (byRef, byVal) de passagem de parâmetros do programa chamador para o programa chamado:
sub nomProcédure([Byref/Byval] param1, [Byref/Byval] param2, ...)
function nomFonction([Byref/Byval] param1, [Byref/Byval] param2, ...)
Quando o modo byRef ou byVal não é especificado, é utilizado o modo byRef.
Parâmetros reais, parâmetros formais
Considere uma função VBScript definida como
Os parâmetros paramForm1 utilizados na definição da função ou procedimento são denominados parâmetros formais. A função anterior pode ser chamada a partir do programa principal ou de outro módulo utilizando uma instrução como:
Os parâmetros paramEffi utilizados na chamada à função ou ao procedimento são designados por parâmetros reais. Quando a execução da função functionName tem início, os parâmetros formais recebem os valores dos parâmetros reais correspondentes. As palavras-chave byRef e byVal determinam o modo de transmissão desses valores.
Modo de passagem por valor (byVal)
Quando um parâmetro formal especifica este modo de passagem, o parâmetro formal e o parâmetro real são duas variáveis diferentes. O valor do parâmetro real é copiado para o parâmetro formal antes da função ou procedimento ser executado. Se a função ou procedimento modificar o valor do parâmetro formal durante a execução, isso não afeta o valor do parâmetro real correspondente. Este método de passagem é adequado para os parâmetros de entrada de uma função ou procedimento.
![]() |
Modo de passagem por referência (byRef)
Este modo de passagem é o padrão se nenhum modo de passagem de parâmetros for especificado. Quando um parâmetro formal especifica este modo de passagem, o parâmetro formal e o parâmetro real correspondente são a mesma variável. Assim, se a função modificar o parâmetro formal, o parâmetro real também é modificado. Este modo de passagem é adequado para:
- parâmetros de saída, uma vez que os seus valores têm de ser devolvidos ao programa de chamada
- parâmetros de entrada cuja cópia é dispendiosa, tais como matrizes
![]() |
O programa a seguir mostra exemplos de passagem de parâmetros:
Programa
Sub proc1(byval i, ByRef j, k)
' i is passed by value (byval) - the effective parameter and the formal parameter are then different
' j is passed by value (byref) - the effective parameter and the formal parameter are then identical
' the k passage mode is not specified. The default is by reference
i=i+1
j=j+1
k=k+1
affiche "dans proc1",i,j,k
End Sub
Sub affiche(byval msg, ByVal i, ByVal j, ByVal k)
' displays the values of i and j and k
wscript.echo msg & " i=" & i & " j=" & j & " k=" & k
End Sub
' ------------- calls to functions and procedures
' init i and j
i=4:j=5 : k=6
' check
affiche "dans programme principal, avant l'appel à proc1 :",i,j,k
' call proc1 procedure
proc1 i,j,k
' check
affiche "dans programme principal, après l'appel à proc1 :",i,j,k
' end
wscript.quit 0
Resultados
dans programme principal, avant l'appel à proc1 : i=4 j=5 k=6
dans proc1 i=5 j=6 k=7
dans programme principal, après l'appel à proc1 : i=4 j=6 k=7
Comentários
- Num script VBScript, não existe um local específico para funções e procedimentos. Podem estar em qualquer parte do código-fonte. Geralmente, são agrupados no início ou no final, e o programa principal é estruturado como um bloco contínuo.
5.3.3. Sintaxe para chamar funções e procedimentos
Seja p um procedimento que aceita parâmetros formais pf1, pf2, ...
- a chamada ao procedimento p assume a forma
sem parênteses em torno dos parâmetros
- se o procedimento p não aceitar parâmetros, pode-se usar tanto a chamada p como p() e a declaração sub p ou sub p()
Seja f uma função que aceita parâmetros formais pf1, pf2, ...
- A função f é chamada na forma
Os parênteses em torno dos parâmetros são obrigatórios. Se a função f não aceitar parâmetros, pode-se usar tanto a chamada f como f() e a declaração function f ou function f().
- O resultado da função f pode ser ignorado pelo programa de chamada. A função f é então considerada um procedimento e segue as regras para a chamada de procedimentos. Escrevemos então f pe1, pe2, ... (sem parênteses) para chamar a função f.
Se a função ou o procedimento for um método de objeto, as regras parecem ser um pouco diferentes e inconsistentes.
- Assim, podemos escrever MyFile.WriteLine "Isto é um teste." ou MyFile.WriteLine("Isto é um teste.")
- mas, embora possamos escrever wscript.echo 4, não podemos escrever wscript.echo(4).
Seguiremos as seguintes regras:
- sem parênteses em torno dos parâmetros de um procedimento ou função utilizada como procedimento
- parênteses em torno dos parâmetros de uma função
5.3.4. Alguns exemplos de funções
Seguem-se alguns exemplos de definições e utilizações de funções:
Programa
Function plusgrandque(byval i, ByVal j)
' returns boolean true if i>j, boolean false otherwise
' data verification
If isnumeric(i) And isnumeric(j) Then
If i>j Then
plusgrandque=true
Else
plusgrandque=false
End If
Else
wscript.echo "Arguments (" & i & "," & j & ") erronés"
plusgrandque=false
End If
Exit Function
End Function
Function rendUnTableau(byval n)
' makes an array of n elements
tableau=array()
' check validity of parameter n
If isnumeric(n) And n>=1 Then
ReDim Preserve tableau(n)
For i= 0 To n-1
tableau(i)=i
Next
Else
wscript.echo "Argument [" & n & "] erroné"
End If
' we return the result
rendUnTableau=tableau
End Function
Function argumentsVariables(byref arguments)
' arguments is an array of numbers whose sum is returned
somme=0
For i=0 To ubound(arguments)
somme=somme+arguments(i)
Next
argumentsVariables=somme
End Function
' two parameter-free functions declared in 2 different ways
Function sansParametres1
sansParametres=4
End Function
Function sansParametres2()
sansParametres=4
End Function
' ------------- calls to functions and procedures
' calls function plusgrandque
wscript.echo "plusgrandque(10,6)=" & plusgrandque(10,6)
wscript.echo "plusgrandque(6,10)=" & plusgrandque(6,10)
wscript.echo "plusgrandque(6,6)=" & plusgrandque(6,6)
wscript.echo "plusgrandque(6,'a')=" & plusgrandque(6,"a")
' calls to the rendUnTableau function
monTableau=rendUnTableau(10)
For i=0 To ubound(monTableau)
wscript.echo monTableau(i)
Next
monTableau=rendUnTableau(-6)
For i=0 To ubound(monTableau)
wscript.echo monTableau(i)
Next
' calls to the argumentsVariables function
wscript.echo "somme=" & argumentsVariables(array(-1,2,7,8))
wscript.echo "somme=" & argumentsVariables(array(-1,10,12))
' function calls without parameters
res=sansParametres1
res=sansParametres1()
sansParametres1
sansParametres1()
res=sansParametres2
res=sansParametres2()
sansParametres2
sansParametres2()
' end
wscript.quit 0
Resultados
plusgrandque(10,6)=Vrai
plusgrandque(6,10)=Faux
plusgrandque(6,6)=Faux
Arguments (6,a) erronés
plusgrandque(6,'a')=Faux
0
1
2
3
4
5
6
7
8
9
Argument [-6] erroné
somme=16
somme=21
somme=10
Comentários
- A função `rendUnTableau` demonstra que uma função pode devolver vários resultados em vez de apenas um. Basta colocá-los numa variante de matriz e devolver essa variante como resultado.
- Por outro lado, a função `argumentsVariables` demonstra que é possível escrever uma função que aceite um número variável de argumentos. Aqui, também, basta colocá-los numa variante de matriz e tornar essa variante um parâmetro da função.
5.3.5. Parâmetro de saída ou resultado da função
Suponha que a análise de uma aplicação tenha demonstrado a necessidade de um módulo M com parâmetros de entrada Ei e parâmetros de saída Sj. Recorde-se que os parâmetros de entrada são informações que o programa chamador fornece ao programa chamado e, inversamente, os parâmetros de saída são informações que o programa chamado fornece ao programa chamador. No VBScript, existem várias soluções para os parâmetros de saída:
- Se houver apenas um parâmetro de saída, este pode ser definido como o resultado de uma função. Nesse caso, deixa de existir um parâmetro de saída, passando a ser simplesmente um resultado da função.
- Se houver n parâmetros de saída, um deles pode servir como resultado da função, com os restantes n-1 a atuarem como parâmetros de saída. Em alternativa, em vez de uma função, pode-se utilizar um procedimento com n parâmetros de saída. Também se pode utilizar uma função que devolva uma matriz contendo os n valores a devolver ao programa chamador. Recorde-se que o programa chamado devolve os seus resultados ao programa chamador por valor. Esta cópia é evitada quando os parâmetros de saída são passados por referência. Esta última solução poupa, portanto, tempo.
5.4. O programa VBScript para ordenar valores
Começámos a nossa discussão sobre programação modular com um estudo algorítmico da ordenação de valores numéricos introduzidos através do teclado. Aqui está a implementação em VBScript que poderia ser utilizada:
Programa
' main program
Option Explicit
Dim T ' the table of values to be sorted
' reading values
T=lire_tableau
' value sorting
trier_tableau T
' display of sorted values
ecrire_tableau T
' end
wscript.quit 0
' ---------- functions & procedures
' -------- lire_tableau
Function lire_tableau
' values are requested
wscript.stdout.write "Tapez les valeurs à trier sous la forme val1 val2 ... valn : "
' we read them
Dim valeurs
valeurs=wscript.stdin.readLine
' we put them in a table
lire_tableau=split(valeurs," ")
End Function
' -------- ecrire_tableau
Sub ecrire_tableau(byref T)
' displays the contents of table T
wscript.echo join(T," ")
End Sub
' -------- trier_tableau
Sub trier_tableau (byref T)
' sorts array T in ascending order
' find the imax index of the T[0..ifin] array
' to exchange T[imax] with the last element of array T[0..ifin]
' then start again with an array with 1 fewer element
Dim ifin, imax, temp
For ifin=ubound(T) To 1 Step -1
' find the imax index of the T[0..ifin] array
imax=chercher_max(T,ifin)
' we exchange the max with the last element of array T[0..ifin]
temp=T(ifin):T(ifin)=T(imax):T(imax)=temp
Next
End Sub
' -------- chercher_max
Function chercher_max(byRef T, ByVal ifin)
' find the imax index of the T[0..ifin] array
Dim i, imax
imax=0
For i=1 To ifin
If cdbl(T(i))>cdbl(T(imax)) Then imax=i
Next
' We return the result
chercher_max=imax
End Function
Resultados
Comentários:
- O módulo de permuta identificado no algoritmo inicial não foi implementado aqui como um módulo VBScript, pois foi considerado demasiado simples para justificar um módulo separado.
5.5. O programa TAX em formato modular
Revisamos o programa de cálculo de impostos, desta vez escrito em formato modular
Programa
' calculating a taxpayer's tax liability
' the program must be called with three parameters: married children salary
' married: character Y if married, N if unmarried
' children: number of children
' salary: annual salary without cents
' mandatory variable declaration
Option Explicit
Dim erreur
' retrieve arguments and check their validity
Dim marie, enfants, salaire
erreur=getArguments(marie,enfants,salaire)
' mistake?
If erreur(0)<>0 Then wscript.echo erreur(1) : wscript.quit erreur(0)
' retrieve the data needed to calculate taxes
Dim limites, coeffR, coeffN
getData limites,coeffR,coeffN
' the result is displayed
wscript.echo "impôt=" & calculerImpot(marie,enfants,salaire,limites,coeffR,coeffN)
' leave without error
wscript.quit 0
' ------------ functions and procedures
' ----------- getArguments
Function getArguments(byref marie, ByRef enfants, ByRef salaire)
' must retrieve three values passed as arguments to the main program
' an argument is passed to the program without spaces in front and behind it
' use regular expressions to check data validity
' returns an error array variant with 2 values
' error(0): error code, 0 if no error
' error(1): error message if error otherwise empty string
Dim syntaxe
syntaxe= _
"Syntaxe : pg marié enfants salaire" & vbCRLF & _
"marié : caractère O si marié, N si non marié" & vbCRLF & _
"enfants : nombre d'enfants (entier >=0)" & vbCRLF & _
"salaire : salaire annuel sans les centimes (entier >=0)"
' we check that there are 3 arguments
Dim nbArguments
nbArguments=wscript.arguments.count
If nbArguments<>3 Then
' error msg
getArguments= array(1,syntaxe & vbCRLF & vbCRLF & "erreur : nombre d'arguments incorrect")
' end
Exit Function
End If
Dim modele, correspondances
Set modele=new regexp
' marital status must be among the characters oOnN
modele.pattern="^[oOnN]$"
Set correspondances=modele.execute(wscript.arguments(0))
If correspondances.count=0 Then
' error msg
getArguments=array(2,syntaxe & vbCRLF & vbCRLF & "erreur : argument marie incorrect")
' we leave
Exit Function
End If
' the value
If lcase(wscript.arguments(0)) = "o"Then
marie=true
Else
marie=false
End If
' children must be an integer >=0
modele.pattern="^\d{1,2}$"
Set correspondances=modele.execute(wscript.arguments(1))
If correspondances.count=0 Then
' error
getArguments= array(3,syntaxe & vbCRLF & vbCRLF & "erreur : argument enfants incorrect")
' we leave
Exit Function
End If
' the value
enfants=cint(wscript.arguments(1))
' salary must be an integer >=0
modele.pattern="^\d{1,9}$"
Set correspondances=modele.execute(wscript.arguments(2))
If correspondances.count=0 Then
' error
getArguments= array(4,syntaxe & vbCRLF & vbCRLF & "erreur : argument salaire incorrect")
' we leave
Exit Function
End If
' the value
salaire=clng(wscript.arguments(2))
' finished without error
getArguments=array(0,"")
End Function
' ----------- getData
Sub getData(byref limites, ByRef coeffR, ByRef coeffN)
' we define the data needed to calculate the tax in 3 tables
limites=array(12620,13190,15640,24740,31810,39970,48360, _
55790,92970,127860,151250,172040,195000,0)
coeffr=array(0,0.05,0.1,0.15,0.2,0.25,0.3,0.35,0.4,0.45, _
0.5,0.55,0.6,0.65)
coeffn=array(0,631,1290.5,2072.5,3309.5,4900,6898.5,9316.5, _
12106,16754.5,23147.5,30710,39312,49062)
End Sub
' ----------- calculerImpot
Function calculerImpot(byval marie,ByVal enfants,ByVal salaire, ByRef limites, ByRef coeffR, ByRef coeffN)
' the number of shares is calculated
Dim nbParts
If marie=true Then
nbParts=(enfants/2)+2
Else
nbParts=(enfants/2)+1
End If
If enfants>=3 Then nbParts=nbParts+0.5
' we calculate the family quotient and taxable income
Dim revenu, qf
revenu=0.72*salaire
qf=revenu/nbParts
' tax calculation
Dim i, impot
i=0
Do While i<ubound(limites) And qf>limites(i)
i=i+1
Loop
calculerImpot=int(revenu*coeffr(i)-nbParts*coeffn(i))
End Function
Comentários
- A função getArguments recupera as informações do contribuinte (cônjuge, filhos, salário). Aqui, elas são passadas como argumentos para o programa VBScript. Se isso fosse alterado — por exemplo, se esses argumentos viessem de uma interface gráfica de utilizador —, apenas o procedimento getArguments precisaria de ser reescrito, e não os outros.
- A função getArguments consegue detetar erros nos argumentos. Quando isso acontece, poderia ter-se optado por interromper a execução do programa dentro da função getArguments utilizando uma instrução wscript.quit. Isto nunca deve ser feito dentro de uma função ou procedimento. Se uma função ou procedimento detetar um erro, deve sinalizar isso de alguma forma ao programa de chamada. Cabe ao programa de chamada decidir se interrompe a execução ou não, e não ao procedimento. No nosso exemplo, o programa de chamada pode decidir pedir ao utilizador para voltar a introduzir os dados incorretos através do teclado, em vez de interromper a execução.
- Aqui, a função getArguments devolve uma variante de matriz em que o primeiro elemento é um código de erro (0 se não houver erro) e o segundo é uma mensagem de erro, caso tenha ocorrido um erro. Ao verificar o resultado devolvido, o programa de chamada pode determinar se ocorreu ou não um erro.
- O procedimento getData recupera os dados necessários para calcular o imposto. Aqui, estes dados são definidos diretamente dentro do procedimento getData. Se estes dados viessem de outra fonte — como um ficheiro ou uma base de dados —, apenas o procedimento getData precisaria de ser reescrito, e não os outros.
- A função `calculerImpot` calcula o imposto assim que todos os dados forem obtidos, independentemente da forma como foram obtidos.
- Note, portanto, que a codificação modular permite a (re)utilização de determinados módulos em diferentes contextos. Este conceito tem sido amplamente desenvolvido nos últimos vinte anos no âmbito do conceito de objetos.







