A declarao
O tipo de varivel
A funo CRIAVAR()
A inicializao
Padronizao de variveis
A Declarao
Deve ser feita sempre no incio da rotina que for utiliz-la, como no exemplo:
Function a910VerCod()
Local cCod910 := 001
Return
O Tipo de Varivel
O tipo de varivel serve para identificar a utilizao que a mesma ter no decorrer da rotina.
Toda varivel deve estar tipada durante sua criao. Quando programamos nativamente em
C, isto se torna obrigatrio. Devemos fazer o mesmo no AP5, pois isto demonstra que a
varivel foi conscientemente declarada.
Tipos Existentes
PUBLIC: Esta varivel ser inicializada em um valor lgico falso (.F.) at que seja
atribudo um valor especfico a ela. Esta varivel permanece definida por toda a durao da
aplicao e pode ser vista (assim como usada, alterada e avaliada) por qualquer funo.
Esta varivel gera um token (indicao) na tabela de smbolos, isto significa que o mdulo
principal conter smbolos para esta classe de varivel, o que, por sua vez, ocupa mais
espao de memria. Deve-se evitar a utilizao deste tipo, a no ser em casos extremos.
PRIVATE: Esta varivel ser inicializada em valor nulo (NIL) e uma vez declarada,
permanecer assim durante toda a durao do fluxo da funo, at que este volte ao
procedimento inicial que a chamou. Em essncia, uma varivel de memria PRIVATE
inicializada logo no incio do Protheus, agir como um varivel PUBLIC. Esta varivel
pode ser vista por uma sub-rotina da funo e modificada de maneira correspondente. Esta
varivel tambm gera um token na tabela de smbolos comentada acima.
LOCAL: Esta varivel de memria ser inicializada com valor nulo (NIL) e s visvel
dentro da funo que a inicializa, mesmo que esta ltima, contenha funes incorporadas a
seu contedo. Este tipo de varivel o mais adequado a ser utilizado em funes, pois no
gera smbolos na tabela de smbolos, por conseqncia ocupa pouco espao de memria e,
o compilador avalia as variveis LOCAL e STATIC mais rapidamente que os outros tipos
(PUBLIC e PRIVATE). Cuidado para no sucumbir teoria de que se pode obter economia
de memria, mudando qualquer referncia PRIVATE para uma referncia LOCAL. Se voc
fizer isso, as funes podem no funcionar corretamente, embora funcionassem na verso
anterior s alteraes.
STATIC: A varivel STATIC idntica classe de armazenamento LOCAL, com uma
exceo. Uma varivel STATIC retida dentro de sua sub-rotina, mesmo depois que o
fluxo da funo a tenha deixado. Isto particularmente til para funes independentes tipo
caixa-preta, que contm seu prprio conjunto de variveis exclusivas e devem manter
esses valores de interao em interao.
Inicializao
Quando no atribumos nenhum valor a uma varivel no momento de sua declarao,
corremos o risco de utiliz-la com valor NIL e causar erros fatais. Por isso, a
inicializao de uma varivel de extrema importncia.
Padronizao de Variveis
importante que ao lermos o nome de uma varivel, possamos saber se o seu tipo
numrico, caracter, data ou lgico. O nome da varivel de get no deve coincidir com uma
varivel de outro programa, pois toda varivel de get possui um help especfico.
Exemplo:
a varivel DBaixa (get da baixa no programa de Ttulos a Receber), j possui um texto help
que indica seu conteudo e no dever ser criada outra varivel para outra finalidade com
este mesmo nome.
Para tanto, definimos a seguinte padronizao :
N -> Numricas
L -> Lgicas
D -> Data
C -> Caracter
A -> Array (matriz)
O -> Objeto
U -> Sem definio
Variveis de Relatrios
Na criao de um relatrio algumas variveis e seus tipos so convencionados para a
utilizao da biblioteca de funes de relatrio.
Varivel
Tipo
Contedo
wnRel
Local
cbCont
Local
Contador
Cabec1
Local
Cabec2
Local
Cabec3
Local
Tamanho
Local
cDesc1
Local
cDesc2
Local
cDesc3
Local
Limite
Local
Titulo
Local
Ttulo do Relatrio
aReturn
Private
Nomeprog
Private
cString
Private
Li
Private
m_pag
Private
aOrd
Private
nLastKey
Private
cPerg
Private
aLinha
Private
Tipos de Dados
O AdvPl no uma linguagem de tipos rgidos (strongly typed), o que significa que
variveis de memria podem diferentes tipos de dados durante a execuo do programa.
Variveis podem tambm conter objetos, mas os tipos primrios da linguagem so:
Numrico
O AdvPl no diferencia valores inteiros de valores com ponto flutuante, portanto pode-se
criar variveis numricas com qualquer valor dentro do intervalo permitido. Os seguintes
elementos so do tipo de dado numrico:
2
43.53
0.5
0.00001
1000000
5
Uma varivel do tipo de dado numrico pode conter um nmero de dezoito dgitos
incluindo o ponto flutuante, no intervalo de 2.2250738585072014 E308 at
1.7976931348623158 E+308.
Lgico
Valores lgicos em AdvPl so identificados atravs de .T. ou .Y. para verdadeiro e .F. ou .N.
para falso (independentemente se os caracteres estiverem em maisculo ou minsculo).
Caracter
Strings ou cadeias de caracteres so identificadas em AdvPl por blocos de texto entre aspas
duplas (") ou aspas simples ('):
"Ol mundo!"
'Esta uma string'
"Esta 'outra' string"
Uma varivel do tipo caracter pode conter strings com no mximo 1 Mb, ou seja, 1048576
caracteres.
Data
O AdvPl tem um tipo de dados especfico para datas. Internamente as variveis deste tipo
de dado so armazenadas como um nmero correspondente a data Juliana.
Variveis do tipo de dados Data no podem ser declaradas diretamente, e sim atravs da
utilizao de funes especficas como por exemplo ctod que converte uma string para data.
Matriz (Array)
Matrizes so um tipo de dado especial. a disposio de outros elementos em colunas e
linhas. O AdvPl suporta matrizes uni ou multidimensionais. Os elementos de uma matriz
so acessados atravs de ndices numricos iniciados em 1, identificando a linha e coluna
para quantas dimenes existirem.
Bloco de Cdigo
O bloco de cdigo um tipo de dado especial. utilizado para armazenar instrues
escritas em AdvPl que podero ser executadas posteriormente.
nTotalGeralMensal := 100
nTotalGeralAnual := 300
Alert("Valor mensal: " + cValToChar(nTotalGeralMensal))
Quando o contedo da varivel nTotalGeralMensal exibido, o seu valor ser de 300. Isso
acontece porque no momento que esse valor foi atribuido varivel nTotalGeralAnual, o
AdvPl considerou apenas os 10 primeiros caracteres (assim como o faz quando deve exibir
o valor da varivel nTotalGeralMensal), ou seja, considerou-as como a mesma varivel.
Assim o valor original de 100 foi substituido pelo de 300.
Limitao de caracteres no nome. Os nomes das variveis devem sempre comear por
uma letra ou o caracter de sublinhado ( _ ). No restante, pode conter letras, nmeros e o
caracter de sublinhado. Qualquer outro caracter, incluindo espaos em branco, no so
permitidos.
O AdvPl permite a criao ilimitada de variveis, dependendo apenas da memria
disponvel. A seguir esto alguns nomes vlidos para variveis:
TOT01
cNumero
VAR_QUALQUER
M_CARGO
A11
E alguns invlidos:
Se esta linha for executada em um programa AdvPl, ocorrer um erro de execuo com a
mensagem "variable does not exist: nPercentual", pois esta varivel est sendo utilizada em
uma expresso de clculo sem ter sido declarada. Para solucionar este erro, deve-se declarar
a varivel previamente:
Local nPercentual,nResultado
Store 10 To nPercentual
nResultado := 250 * (1 + (nPercentual / 100))
ou
ou
10
02
03 xVariavel := "Agora a varivel caracter..."
04 Alert("Valor do Texto: " + xVariavel)
05
06 xVariavel := 22 // Agora a varivel numrica
07 Alert(cValToChar(xVariavel))
08
09 xVariavel := .T. // Agora a varivel lgica
10 If xVariavel
11 Alert("A varivel tem valor verdadeiro...")
12 Else
13
14 Endif
15
16 xVariavel := Date() // Agora a varivel data
17 Alert("Hoje : " + DtoC(xVariavel))
18
19 xVariavel := nil // Nulo novamente
20 Alert("Valor nulo: " + xVariavel)
21
22 Return
11
varivel que pode conter diversos tipos de dados, segundo a Notao Hngara (consulte
documentao especfica para detalhes). Este programa troca os valores da varivel e exibe
seu contedo para o usurio atravs da funo alert. Essa funo recebe um parmetro que
deve ser do tipo string de caracter, por isso dependendo do tipo de dado da varivel
xVariavel necessrio fazer uma converso antes.
Apesar dessa flexibilidade de utilizao de variveis, deve-se tomar cuidados na passagem
de parmetros para funes ou comandos, e na concatenao (ou soma) de valores. Note a
linha 20 do programa de exemplo. Quando esta linha executada, a varivel xVariavel
contem o valor nulo. A tentativa de soma de tipos de dados diferentes gera erro de execuo
do programa. Nesta linha do exemplo, ocorrer um erro com a mensagem "type mismatch
on +". Excetuando-se o caso do valor nulo, para os demais deve-se sempre utilizar funes
de converso quando necessita-se concatenar tipos de dados diferentes (por exemplo, nas
linhas 07 e 17.
Note tambm que quando uma varivel do tipo de dado lgico, ela pode ser utilizada
diretamente para checagem (linha 10):
If xVariavel
o mesmo que
If xVariavel = .T.
12
Matrizes
Matrizes, ou arrays, so colees de valores. Ou, de uma maneira mais fcil de entender,
uma lista. Uma matriz pode ser criada atravs de diferentes maneiras. Consulte a
documentao sobre Inicializao de Matrizes para maiores detalhes.
Cada item em uma matriz referenciado pela indicao de sua posio numrica na lista,
iniciando pelo nmero 1. O exemplo a seguir declara uma varivel, atribui uma matriz de
trs elementos a ela, e ento exibe um dos elementos e o tamanho da matriz:
Local aLetras
// Declarao da varivel
13
aFunct1 := {"Pedro",32,.T.}
Esta matriz contem uma string, um nmero e um valor lgico. Em outras linguagens como
C ou Pascal, este "pacote" de informaes pode ser chamado como um "struct" (estrutura
em C, por exemplo) ou um "record" (registro em Pascal, por exemplo). Como se fosse na
verdade um registro de um banco de dados, um pacote de informaes construdo com
diversos campos. Cada campo tendo um pedao diferente de dado.
Suponha que no exemplo anterior, o array aFunct1 contenha informaes sobre o nome de
uma pessoa, sua idade e sua situao matrimonial. Os seguintes #defines podem ser criados
para indicar cada posio dos valores dentro da matriz:
#define FUNCT_NOME 1
#define FUNCT_IDADE 2
#define FUNCT_CASADO 3
14
Alert(aFunct1[FUNCT_NOME])
Alert(aFunct2[FUNCT_NOME])
Alert(aFunct3[FUNCT_NOME])
Agora, ao invs de trabalhar com variveis individuais, pode-se agrup-las em uma outra
matriz, do mesmo modo que muitos registros so agrupados em uma tabela de banco de
dados:
aFuncts uma matriz com 3 linhas por 3 colunas. Uma vez que as variveis separadas
foram combinadas em uma matriz, os nomes podem ser exibidos assim:
15
Local nCount
For nCount := 1 To Len(aFuncts)
Alert(aFuncts[nCount,FUNCT_NOME])
// O acesso a elementos de uma matriz multidimensional
// pode ser realizado tambm desta forma:
// aFuncts[nCount][FUNCT_NOME]
Next nCount
A varivel nCount seleciona que funcionrio (ou que linha) de interesse. Ento a
constante FUNCT_NOME seleciona a primeira coluna daquela linha.
16
Inicializando Matrizes
Algumas vezes o tamanho da matriz conhecido previamente. Outras vezes o tamanho da
matriz s ser conhecido em tempo de execuo.
01 Local nCnt
02 Local aX[10]
03 Local aY := Array(10)
04 Local aZ := {0,0,0,0,0,0,0,0,0,0}
05
06 For nCnt := 1 To 10
17
07
08 Next nCnt
Este cdigo preenche a matriz com uma tabela de quadrados. Os valores sero 1, 4, 9, 16 ...
81, 100. Note que a linha 07 se refere varivel aX, mas poderia tambm trabalhar com aY
ou aZ. O objetivo deste exemplo demonstrar trs modos de criar uma matriz de tamanho
conhecido no momento da criao do cdigo.
Na linha 02 a matriz criada usando aX[10]. Isto indica ao AdvPl para alocar espao para
10 elementos na matriz. Os colchetes [ e ] so utilizados para indicar o tamanho necessrio.
Na linha 03 utilizada a funo array com o parmetro 10 para criar a matriz, e o retorno
desta funo atribudo varivel aY.
Na linha 03 efetuado o que se chama "desenhar a imagen da matriz". Como pode-se notar,
existem dez 0s na lista encerrada entre chaves ({}). Claramente, este mtodo no o
utilizado para criar uma matriz de 1000 elementos. O terceiro mtodo difere dos anteriores
porque inicializa a matriz com os valores definitivos. Nos dois primeiros mtodos, cada
posio da matriz contm um valor nulo (Nil) e deve ser inicializado posteriormente.
A linha 07 demonstra como um valor pode ser atribudo para uma posio existente em
uma matriz especificando o ndice entre colchetes.
01 Local nCnt
02 Local aX[0]
03 Local aY := Array(0)
04 Local aZ := {}
05
06 For nCnt := 1 To nSize
18
07
aAdd(aX,nCnt*nCnt)
08 Next nCnt
A linha 02 utiliza os colchetes para criar uma matriz vazia. Apesar de no ter nenhum
elemento, seu tipo de dado matriz.
Na linha 03 a chamada da funo array cria uma matriz sem nenhum elemento.
Na linha 04 est declarada a representao de uma matriz vazia em AdvPl. Mais uma vez,
esto sendo utilizadas as chaves para indicar que o tipo de dados da varivel matriz. Note
que {} uma matriz vazia (tem o tamanho 0), enquanto {Nil} uma matriz com um nico
elemento nulo (tem tamanho 1).
Porque cada uma destas matrizes no contem elementos, a linha 07 utiliza a funo aadd
para adicionar elementos sucessivamente at o tamanho necessrio (especificado por
exemplo na varivel nSize).
Blocos de Cdigo
Blocos de cdigo so um conceito existente h muito tempo em linguagens xBase. No
como algo que apareceu da noite para o dia, e sim uma evoluo progressiva utilizando a
combinao de muitos conceitos da linguagem para a sua implementao.
Um Primeiro Lembrete
O AdvPl uma linguagem baseada em funes. Funes tm um valor de retorno. Assim
como o operador de atribuio :=.
Assim, ao invs de escrever:
Posde-se escrever:
19
A expresso x:=10 avaliada primeiro, e ento seu resultado (o valor de X, que agora 10)
passada para a funo cvaltochar para a converso para caracter, e em seguida para a
funo alert para a exibio. Por causa desta regra de precedncia possvel atribuir um
valor a mais de uma varavel ao mesmo tempo:
Z := Y := X := 0
Por causa dessa regra, essa expresso avaliada como se fosse escrita assim:
Z := ( Y := (X := 0) )
Apesar do AdvPl avaliar expresses da esquerda para a direita, no caso de atribuies isso
acontece ao contrrio, da direita para a esquerda. O valor atribudo varivel X, que
retorna o valor para ser atribudo varivel Y e assim sucessivamente. Pode-se dizer que o
zero foi "propagado atravs da expresso".
Outro Lembrete
Em AdvPl pode-se juntar diversas linhas de cdigo em uma nica linha fscia do arquivo.
Por exemplo, o cdigo:
If lAchou
Alert("Cliente encontrado!")
Endif
O ponto-e-vrgula indica ao AdvPl que a nova linha de cdigo est para comear. Pode-se
ento colocar diversas linhas lgicas de cdigo na mesma linha fsica atravs do editor de
texto utilizado.
Apesar da possibilidade de se escrever todo o programa assim, em uma nica linha fsica,
isto no recomendado pois dificulta a legibilidade do programa e, conseqentemente, a
manuteno.
Lista de Expresses
A evoluo dos blocos de cdigo comea com as listas de expresses. Nos exemplos a
seguir, o smbolo ==> indicar o retorno da expresso aps sua avaliao (seja para atribuir
em uma varivel, exibir para o usurio ou imprimir em um relatrio), que ser impresso em
um relatrio por exemplo.
==>
10
@00,00 PSAY y := 20
==>
20
Cada uma das linhas ter a expresso avaliada, e o valor da varivel ser ento impresso.
Alert( cValToChar( x := 10 ; y := 20 ) )
==>
10
Apesar desse cdigo se encontrar em uma nica linha fsica, existem duas linhas lgicas
separadas pelo ponto e vrgula. Ou seja, esse cdigo equivalente a:
21
Alert( cValToChar( x := 10 ) )
y := 20
Portanto apenas o valor 10 da varivel x ser passado para as funes cvaltochar e alert
para ser exibido. E o valor 20 apenas ser atribudo varivel y.
22
X := 10 ; Y := 20
If X > Y
Alert("X")
Z := 1
Else
Alert("Y")
Z := -1
Endif
Aqui temos o mesmo conceito, escrito utilizando listas de expresses na funo iif:
X := 10 ; Y := 20
iif( X > Y , ;
( Alert("X"), Z := 1 ) , ;
( Alert("Y"), Z := -1 ) )
O AdvPl permite criar funes, que so pequenos pedaos de cdigo, como se fosse um
pequeno programa, utilizados para diminuir partes de tarefas mais complexas e reaproveitar
23
Function Lista()
X := 10
Y := 20
Return Y
E a linha de exemplo com a lista de expresses pode ser substituda, tendo o mesmo
resultado, por:
( X := 10 , Y := 20 ) // Lista de Expresses
{|| X := 10 , Y := 20 } // Bloco de Cdigo
24
Essa funo recebe como parmero um bloco de cdigo e avalias todas as expresses
contidas neste bloco de cdigo, retornando o resultado da ltima expresso avaliada.
Passando Parmetros
J que blocos de cdigo so como pequenas funes, tambm possvel a passagem de
parmetros para um bloco de cdigo. Os parmetros devem ser informados entre as barras
verticais (||) separados por vrgulas, assim como em uma funo.
B := {| N | X := 10, Y := 20 + N}
Porm deve-se notar que j que o bloco de cdigo recebe um parmetro, um valor deve ser
passado quando o bloco de cdigo for avaliado.
C := Eval(B, 1) ==> 21
25
Esta matriz pode ser ordenada pelo primeiro nome, utilizando-se a chamada da funo
asort(A), resultado na matriz com os elementos ordenados dessa forma:
A ordem padro para a funo asort ascendente. Este comportamento pode ser modificado
atravs da informao de um bloco de cdigo que ordena a matriz de forma descendente:
B := { |X, Y| X > Y }
aSort(A, B)
O bloco de cdigo (de acordo com a documentao da funo asort) deve ser escrito para
aceitar dois parmetros que so os dois elementos da matriz para comparao. Note que o
bloco de cdigo no conhece que elementos est comparando - a funo asort seleciona os
elementos (talvez utilizando o algortmo QuickSort) e passa-os para o bloco de cdigo. O
bloco de cdigo compara-os e retorna verdadeiro (.T.) se se encontram na ordem correta, ou
falso (.F.) se no. Se o valor de retorno for falso, a funo asort ir ento trocar os valores
de lugar e seguir comparando o prximo par de valores.
Ento, no bloco de cdigo anterior, a comparao X > Y verdadeira se os elementos esto
em ordem descendente, o que significa que o primeiro valor maior que o segundo.
Para ordenar a mesma matriz pelo ltimo nome, tambm em orden descendente, pode-se
utilizar o seguinte bloco de cdigo:
26
Finalmente, para ordenar um sub-elemento (coluna) de uma matriz por exemplo, pode-se
utilizar o seguinte bloco de cdigo:
27
cRes := MEMVAR->NOME
Esta linha de comando identifica que o valor atribudo varivel cRes deve ser o valor da
varivel de memria chamada NOME.
cRes := FIELD->NOME
28
Neste caso, o valor atribudo varivel cRes ser o valor do campo NOME existente no
arquivo ou tabela aberto na rea atual.
O identificador FIELD pode ser substitudo pelo apelido de um arquivo ou tabela aberto,
para evitar a necessidade de selecionar a rea antes de acessar o contedo de terminado
campo.
cRes := CLIENTES->NOME
Para maiores detalhes sobre abertura de arquivos com atribuio de apelidos, consulte a
documentao sobre acesso a banco de dados ou a documentao da funo dbUseArea.
Operadores Comuns
Na documentao sobre variveis h uma breve demonstrao de como atribuir valores a
uma varivel da forma mais simples. O AdvPl amplia significativamente a utilizao de
variveis atravs do uso de expresses e funes. Uma expresso um conjunto de
operadores e operandos cujo resultado pode ser atribudo a uma varivel ou ento analisado
para a tomada de decises. Por exemplo:
Neste exemplo so utilizadas algumas expresses para calcular o salrio lquido aps um
aumento. Os operandos de uma expresso podem ser uma varivel, uma constante, um
campo de arquivo ou uma funo.
Operadores Matemticos
Os operadores utilizados em AdvPl para clculos matemticos so:
29
Adio
Subtrao
Multiplicao
Diviso
** ou ^
Exponenciao
Operadores de String
Os operadores utilizados em AdvPl para tratamento de caracteres so:
+
Concatenao de strings com eliminao dos brancos finais das strings intermedirias
Operadores Relacionais
Os operadores utilizados em AdvPl para operaes e avaliaes relacionais so:
<
Comparao Menor
>
Comparao Maior
Comparao Igual
==
<=
>=
<>
30
ou
#
ou
!=
Operadores Lgicos
Os operadores utilizados em AdvPl para operaes e avaliaes lgicas so:
.And.
E lgico
.Or.
OU lgico
.Not. ou !
NO lgico
Operadores de Atribuio
Os operadores utilizados em AdvPl para atribuio de valores a variveis de memria so:
=
Atribuio Simples
:=
Atribuio em Linha
+=
-=
*=
31
/=
**= ou ^=
%=
Atribuio Simples
O sinal de igualdade utilizado para atribuir valor a uma varivel de memria.
nVariavel = 10
Atribuio em Linha
O operador de atribuio em linha caracterizado por dois pontos e o sinal de igualdade.
Tem a mesma funo do sinal de igualdade sozinho, porm aplia a atribuio s variveis.
Com ele pode-se atribuir mais de uma varivel ao mesmo tempo.
por
32
O operador de atribuio em linha tambm pode ser utilizado para substituir valores de
campos em um banco de dados.
Atribuio Composta
Os operadores de atribuio composta so uma facilidade da linguagem AdvPl para
expresses de clculo e atribuio. Com eles pode-se economizar digitao:
Operador
Exemplo
Equivalente a
+=
X += Y
X=X+Y
-=
X -= Y
X=X-Y
*=
X *= Y
X=X*Y
/=
X /= Y
X=X/Y
**= ou ^=
X **= Y
X = X ** Y
%=
X %= Y
X=X%Y
Operadores de Incremento/Decremento
A linguagem AdvPl possui operadores para realizar incremento ou decremento de variveis.
Entende-se por incremento aumentar o valor de uma varivel numrica em 1 e entende-se
por decremento diminuir o valor da varivel em 1. Os operadores so:
33
++
Incremento Ps ou Pr-fixado
--
Decremento Ps ou Pr-fixado
Local nA := 10
Local nB := nA++ + nA
Local nA := 10
Local nB := ++nA + nA
Resulta em 22, pois o operador incremental aumentou o valor da primeira nA antes que seu
valor fosse considerado.
Operadores Especiais
Alm dos operadores comuns, o AdvPl possui alguns outros operadores ou identificadores.
Estas so suas finalidades:
34
()
Agrupamento ou Funo
[]
Elemento de Matriz
{}
->
Identificador de Apelido
&
Macrosubstituio
35
Alterao da Precedncia
36
37
Macro Substituio
O operador de macro substituio, simbolizado pelo "e" comercial (&), utilizado para a
avaliao de expresses em tempo de execuo. Funciona como se uma expresso
armazenada fosse compilada em tempo de execuo, antes de ser de fato executada.
Considere o exemplo:
01 X := 10
02 Y := "X + 1"
03 B := &Y // O contedo de B ser 11
A varivel X atribuda com o valor 10, enquanto a varivel Y atribuda com a string de
caracteres contendo "X + 1".
A terceira linha utiliza o operador de macro. Esta linha faz com que o nmero 11 seja
atribudo varivel B. Pode-se perceber que esse o valor resultante da expresso em
formato de caractere contida na varivel Y.
Utilizando-se uma tcnica matemtica elementar, a substituio, temos que na segunda
linha, Y definido como "X + 1", ento pode-se substituir Y na terceira linha:
03 B := &"X + 1"
38
03 B := X + 1
Pode-se perceber que o operador de macro remove as aspas, o que deixa um pedao de
cdigo para ser executado. Deve-se ter em mente que tudo isso acontece em tempo de
eecuo, o que torna tudo muito dinmico. Uma utilizao interessante criar um tipo de
calculadora, ou avaliador de frmulas, que determina o resultado de algo que o usurio
digita.
39
Controlando o Fluxo
O AdvPl suporta vrias estruturas de controle que permitem mudar a seqncia de fluxo de
execuo de um programa. Estas estruturas permitem a execuo de cdigo baseado em
condies lgica e a repetio da execuo de pedaos de cdigo qualquer nmero de
vezes.
Em AdvPl, todas as estruturas de controle podem ser "aninhadas" dentro de todas as demais
estruturas contanto que estejam aninhadas propriamente. Estruturas de controle tm um
identificador de incio e um de fim, e qualquer estrutura aninhada deve se encontrar entre
estes identificadores.
Tambm existem estruturas de controle para determinar que elementos, comandos, etc em
um programa sero compilados. Estas so as diretivas do pr-processador #ifdef...#endif e
#ifndef...#endif. Consulte a documentao sobre o pr-processador para maiores detalhes.
As estruturas de controle em AdvPl esto divididas em Estruturas de Repetio e Estruturas
de Deciso.
40
Repetio de Comandos
Estruturas de repetio so deseginadas para executar uma seo de cdigo mais de uma
vez. Por exemplo, imagiando-se a existncia de uma funo para imprimir um relatrio,
pode-se desejar imprimi-lo quatro vezes. Claro, pode-se simplesmente chamar a funo de
impresso quatro vezes em seqncia, mas isto se tornaria pouco profissional e no
resolveria o problema se o nmero de relatrios fosse varivel.
Em AdvPl existem dois comandos para a repetio de sees de cdigo. O comando
FOR...NEXT e o comando WHILE...ENDDO.
O Comando FOR...NEXT
A estrutura de controle FOR...NEXT, ou simplesmente o loop FOR, repete uma seo de
cdigo em um nmero determinado de vezes.
Sintaxe
FOR Variavel := nValorInicial TO nValorFinal [STEP nIncremento]
Comandos...
[EXIT]
[LOOP]
NEXT
Parmetros
Variavel
41
nValorInicial TO
nValorFinal
STEP
nIncremento
Comandos
EXIT
LOOP
Comentrios
Uma varivel ou um elemento de uma matriz utilizado como um contador para especificar
quantas vezes os comandos AdvPl dentro da estrutura FOR...NEXT so executados. Os
comandos AdvPl depois do FOR so executados at que o NEXT seja alcanado. O
contador (Variavel) ento incrementado ou decremantado com o valor em nIncremento
(se a clusula STEP for omitida, o contador incrementado em 1). Ento, o contador
comparado com o valor em nValorFinal. Se for menor ou igual ao valor em nValorFinal, os
comandos seguintes ao FOR so executados novamente. Se o valor for maior que o contido
em nValorFinal, a estrutura FOR...NEXT terminada e o programa continua a execuo no
primeiro comando aps o NEXT.
Os valores de nValorInicial, nValorFinal e nIncremento so apenas considerados
inicialmente. Entretanto, mudar o valor da varivel utilizada como contador dentro da
estrutura afetar o nmero de vezes que a repetio ser executada. Se o valor de
nIncremento negativo e o valor de nValorInicial maior que o de nValorFinal, o contador
ser decrementado a cada repetio.
Exemplo
42
Local nCnt
Local nSomaPar := 0
Return
Este exemplo imprime a soma dos 100 primerios nmeros pares. A soma obitida atravs
da repetio do clculo utilizando a prpria varivel de contador. Como a clusula STEP
est sendo utilizada, a varivel nCnt ser sempre incrementada em 2. E como o contador
comea com 0, seu valor sempre ser um nmero par.
O Comando WHILE...ENDDO
A estrutura de controle WHILE...ENDDO, ou simplesmente o loop WHILE, repete uma
seo de cdigo enquanto uma determinada expresso resultar em verdadeiro (.T.).
Sintaxe
WHILE lExpressao
Comandos...
[EXIT]
43
[LOOP]
ENDDO
Parmetros
lExpressao
Comandos
EXIT
LOOP
Comentrios
Os comandos entre o WHILE e o ENDDO so executados enquanto o resultado da
avaliao da expresso em lExpressao permanecer verdadeiro (.T.). Cada palavra chave
WHILE deve ter uma palavra chave ENDDO correspondente.
Exemplo
Local nNumber := nAux := 350
nAux := Int(nAux / 2)
Return
Desviando a Execuo
Estruturas de desvio so deseginadas para executar uma seo de cdigo se determinada
condio lgica resultar em verdadeiro (.T.). Em AdvPl existem dois comandos para
execuo de sees de cdigo de acordo com avaliaes lgicas. O comando IF...ENDIF e
o comando DO CASE...ENDCASE.
O Comando IF...ENDIF
Executa um conjunto de comandos baseado no valor de uma expresso lgica.
Sintaxe
IF lExpressao
Comandos
[ELSE
Comandos...]
ENDIF
Parmetros
lExpressao
45
Comentrios
Pode-se aninhar um bloco de comando IF...ENDIF dentro de outro bloco de comando
IF...ENDIF. Porm, para a avaliao de mais de uma expresso lgica, deve-se utilizar o
comando DO CASE...ENDCASE.
Exemplo
Local dVencto := CTOD("31/12/01")
If Date() > dVencto
Alert("Vencimento ultrapassado!")
Endif
Return
O Comando DO CASE...ENDCASE
Executa o primeiro conjunto de comandos cuja expresso condicional resulta em
verdadeiro (.T.).
Sintaxe
DO CASE
CASE lExpressao1
46
Commandos
[CASE lExpressao2
Commandos
...
CASE lExpressaoN
Commandos]
[OTHERWISE
Commandos]
ENDCASE
Parmetros
Quando a primeira expresso CASE resultante em verdadeiro (.T.) for
encontrada, o conjunto de comandos seguinte executado. A execuo
CASE
lExpressao1 do conjunto de comandos continua at que a prxima clusula CASE,
Comandos... OTHERWISE ou ENDCASE seja encontrada. Ao terminar de executar
esse conjunto de comandos, a execuo continua com o primeiro
comando seguinte ao ENDCASE.
Se uma expresso CASE resultar em falso (.F.), o conjunto de comandos
seguinte a esta at a prxima clusula ignorado.
Apenas um conjunto de comandos executado. Estes so os primeiros
comandos cuja expresso CASE avaliada como verdadeiro (.T.). Aps
a execuo, qualquer outra expresso CASE posterior ignorada
(mesmo que sua avaliao resultasse em verdadeiro).
OTHERWISE
Commandos
Comentrios
47
:= Month(Date())
DO CASE
CASE nMes <= 3
cPeriodo := "Primeiro Trimestre"
CASE nMes >= 4 .And. nMes <= 6
cPeriodo := "Segundo Trimestre"
CASE nMes >= 7 .And. nMes <= 9
cPeriodo := "Terceiro Trimestre"
OTHERWISE
cPeriodo := "Quarto Trimestre"
ENDCASE
Return
48
tFont
Classe que encapsula fonte de edio.
Hierarquia
tFontAbs -> tFont
Descrio
Utilize objeto tFont para modificar a fonte padro de controles visuais.
Mtodos
New
Descrio
Construtor do objeto.
Sintaxe
New([acName], [nPar2], [anHeight], [lPar4], [alBold], [nPar6], [lPar7], [nPar8], [alItalic],
[alUnderline])
Parmetros
acName
49
nPar2
Reservado.
anHeight
lPar4
Reservado.
alBold
nPar6
Reservado.
lPar7
Reservado.
nPar8
Reservado.
alItalic
alUnderline
Retorno
O objeto criado.
Exemplo
#include protheus.ch
50
Return
MSDialog
Classe de dilogo de entrada de dados.
Hierarquia
tSrvObject -> tWindow -> tDialog -> MSDialog
Caractersticas
MSDialog deve ser utilizada como padro de janela para entrada de dados. MSDialog um
tipo de janela dilogo modal, isto , no permite que outra janela ativa receba dados
enquanto esta estiver ativa.
Propriedades
Vide classes ancestrais.
Mtodos
New
51
Descrio
Mtodo construtor da classe.
Sintaxe
New([anTop], [anLeft], [anBottom], [anRight], [acCaption], [cPar6], [nPar7], [lPar8],
[nPar9], [anClrText], [anClrBack], [oPar12], [aoWnd], [alPixel], [oPar15], [oPar16],
[lPar17])
Parmetros
anTop
anLeft
anBottom
anRight
acCaption
cPar6
nPar7
lPar8
nPar9
anClrText
anClrBack
oPar12
aoWnd
alPixel
oPar15
oPar16
lPar17
Retorno
O dilogo construdo.
52
Exemplo
#include protheus.ch
// cria dilogo
Local oDlg:=MSDialog():New(10,10,300,300,Meu dialogo;
,,,,,CLR_BLACK,CLR_WHITE,,,.T.)
Return
53
MsGetDados
Objeto tipo lista com uma ou mais colunas para cadastramento de dados baseado em um
vetor.
Caractersticas
A MsGetDados precisa que sejam declaradas as variveis abaixo sendo tipo Private:
aRotina.
Vetor com as rotinas que sero executadas na MBrowse e que definira o tipo de operao
que esta sendo executada (incluso, alterao, excluso, visualizao, pesquisa, ...) no
formato:
Elemento
Contedo
Ttulo
54
Rotina
Reservado
aHeader
Vetor com informaes das colunas no formato:
Elemento
Contedo
Ttulo
Campo
Mscara
Tamanho
Decimal
Validao
Reservado
Tipo
Reservado
10
Reservado
55
aCols
Vetor com as linhas a serem editadas. As colunas devem ser construdas com base no
aHeader mais uma ultima com valor lgico que determina se a linha foi excluda.
lRefresh
Varivel tipo lgica para uso reservado.
A MsGetDados cria a varivel publica n que indica qual a linha posicionada do aCols.
As funes passadas como parmetro para a MsGetDados (cLinhaOk, cTudoOk, ...) no
podero ser declaradas como Static Function.
A consulta padro, validao do usurio e gatilhos estaro habilitados se o campo estiver
cadastrado no Dicionrio de Dados (SX3/SX7) e apresentar estas opes disponveis.
Mtodos
New
Descrio
Cria o objeto MsGetDados.
Sintaxe
MSGETDADOS():NEW( nSuperior, nEsquerda, nInferior, nDireita, nOpc, [ cLinhaOk ], [
cTudoOk ], [ cIniCpos ], [ lApagar ], [ aAlter ], [ uPar1 ], [ lVazio ], [ nMax ], [ cCampoOk
], [ cSuperApagar ], [ uPar2 ], [ cApagaOk ], [ oWnd ] ) -> objeto
Argumentos
Descrio
nSuperior
nEsquerda
nInferior
nDireita
nOpc
cLinhaOk
cTudoOk
cIniCpos
lApagar
aAlter
uPar1
Parmetro reservado.
lVazio
nMax
cCampoOk
cSuperApagar
uPar2
Parmetro reservado.
cApagaOk
oWnd
Retorno
Objeto.
57
ForceRefresh
Descrio
Atualiza a MsGetDados com o aCols e posiciona na primeira linha.
Sintaxe
oObjeto:ForceRefresh()
Hide
Descrio
Esconde a MsGetDados.
Sintaxe
oObjeto:Hide()
Show
Descrio
Mostra a MsGetDados.
Sintaxe
58
oObjeto:Show()
Exemplo
User Function Exemplo()
Local nI
Local oDlg
Local oGetDados
Local nUsado := 0
Private lRefresh := .T.
Private aHeader := {}
Private aCols := {}
Private aRotina := {{"Pesquisar", "AxPesqui", 0, 1},;
{"Visualizar", "AxVisual", 0, 2},;
{"Incluir", "AxInclui", 0, 3},;
{"Alterar", "AxAltera", 0, 4},;
{"Excluir", "AxDeleta", 0, 5}}
DbSelectArea("SX3")
DbSetOrder(1)
DbSeek("SA1")
While !Eof() .and. SX3->X3_ARQUIVO == "SA1"
If X3Uso(SX3->X3_USADO) .and. cNivel >= SX3->X3_NIVEL
nUsado++
Aadd(aHeader,{Trim(X3Titulo()),;
SX3->X3_CAMPO,;
59
SX3->X3_PICTURE,;
SX3->X3_TAMANHO,;
SX3->X3_DECIMAL,;
SX3->X3_VALID,;
"",;
SX3->X3_TIPO,;
"",;
"" })
EndIf
DbSkip()
End
Aadd(aCols,Array(nUsado+1))
For nI := 1 To nUsado
aCols[1][nI] := CriaVar(aHeader[nI][2])
Next
aCols[1][nUsado+1] := .F.
DEFINE MSDIALOG oDlg TITLE "Exemplo" FROM 00,00 TO 300,400 PIXEL
oGetDados := MSGETDADOS():NEW(05, 05, 145, 195, 4, "U_LINHAOK",
"U_TUDOOK", "+A1_COD", .T., {"A1_NOME"}, , .F., 200, "U_FIELDOK",
"U_SUPERDEL", , "U_DELOK", oDlg)
ACTIVATE MSDIALOG oDlg CENTERED
Return
60
ApMsgStop("LINHAOK")
Return .T.
61
MXsGetDb
Objeto tipo lista com uma ou mais colunas para cadastramento de dados baseado em uma
tabela temporria.
Caractersticas
A MsGetDB precisa que sejam declaradas as variveis abaixo sendo tipo Private:
aRotina.
Vetor com as rotinas que sero executadas na MBrowse e que definira o tipo de operao
que esta sendo executada (incluso, alterao, excluso, visualizao, pesquisa, ...) no
formato:
Elemento
Contedo
Ttulo
Rotina
Reservado
aHeader
Vetor com informaes das colunas no formato:
Elemento
Contedo
Ttulo
62
Campo
Mscara
Tamanho
Decimal
Validao
Reservado
Tipo
Reservado
10
Reservado
lRefresh
Varivel tipo lgica para uso reservado.
A tabela temporria utilizada pela MsGetDB dever ser criada com base no aHeader mais
um ltimo campo tipo lgico que determina se a linha foi excluda.
A MsGetDB cria a varivel publica nBrLin que indica qual a linha posicionada do aCols.
As funes passadas como parmetro para a MsGetDB (cLinhaOk, cTudoOk, ...) no
podero ser declaradas como Static Function.
A consulta padro, validao do usurio e gatilhos estaro habilitados se o campo estiver
cadastrado no Dicionrio de Dados (SX3/SX7) e apresentar estas opes disponveis.
Mtodos
New
Descrio
Cria o objeto MsGetDB.
Sintaxe
63
nEsquerda
nInferior
nDireita
nOpc
cLinhaOk
cTudoOk
cIniCpos
lApagar
aAlter
nCongelar
lVazio
uPar1
cTRB
cCampoOk
Parmetro reservado.
Alias da tabela temporria.
Funo executada na validao do campo.
64
lConditional
lAdacionar
oWnd
Reservado
lDisparos
uPar2
Parmetro reservado.
cApagarOk
cSuperApagar
Retorno
Objeto.
ForceRefresh
Descrio
Atualiza a MsGetDB com a tabela e posiciona na primeira linha.
Sintaxe
ForceRefresh()
Exemplo
User Function Exemplo()
Local nI
Local oDlg
Local oGetDB
65
Local nUsado := 0
Local aStruct := {}
Private lRefresh := .T.
Private aHeader := {}
Private aCols := {}
Private aRotina := {{"Pesquisar", "AxPesqui", 0, 1},;
{"Visualizar", "AxVisual", 0, 2},;
{"Incluir", "AxInclui", 0, 3},;
{"Alterar", "AxAltera", 0, 4},;
{"Excluit", "AxDeleta", 0, 5}}
DbSelectArea("SX3")
DbSetOrder(1)
DbSeek("SA1")
While !Eof() .and. SX3->X3_ARQUIVO == "SA1"
If X3Uso(SX3->X3_USADO) .and. cNivel >= SX3->X3_NIVEL
nUsado++
Aadd(aHeader,{Trim(X3Titulo()),;
SX3->X3_CAMPO,;
SX3->X3_PICTURE,;
SX3->X3_TAMANHO,;
SX3->X3_DECIMAL,;
SX3->X3_VALID,;
"",;
66
SX3->X3_TIPO,;
"",;
"" })
Aadd(aStruct,{SX3->X3_CAMPO,;
SX3->X3_TIPO,;
SX3->X3_TAMANHO,;
SX3->X3_DECIMAL})
EndIf
DbSkip()
End
Aadd(aStruct,{"FLAG","L",1,0})
cCriaTrab := CriaTrab(aStruct,.T.)
DbUseArea(.T.,__LocalDriver,cCriaTrab,,.T.,.F.)
DEFINE MSDIALOG oDlg TITLE "Exemplo" FROM 00,00 TO 300,400 PIXEL
oGetDB := MSGETDB():NEW(05, 05, 145, 195, 3, "U_LINHAOK", "U_TUDOOK",
"+A1_COD", .T., {"A1_NOME"}, 1, .F., , cCriaTrab, "U_FIELDOK", , .T., oDlg,
.T., ,"U_DELOK", "U_SUPERDEL")
ACTIVATE MSDIALOG oDlg CENTERED
DbSelectArea(cCriaTrab)
DbCloseArea()
Return
67
Return .T.
68
MsmGet
Conjunto de objetos tipo MsGet/MsCombo para cadastramento de dados baseado no
Dicionrio de Dados.
Caractersticas
A MsMGet tambm poder criada a partir da funo Enchoice a qual recebe os mesmos
parmetros do mtodo New porm no retorna o objeto criado.
A MsMGet se baseia no Dicionrio de Dados para verificar campos obrigatrios,
validaes, gatilhos, consulta padro etc. assim como para a criao das Pastas de Cadastro.
A MsMGet pode usar tanto variveis de memria do tipo Private como diretamente os
campos da tabela a que se refere.
Mtodos
69
New
Descrio
Cria o objeto MsMGet.
Sintaxe
MSMGET():NEW( cAlias, nReg, nOpc, [ uPar1 ], [ uPar2 ], [ uPar3 ], [ aACho ], [ aPos ],
[ aCpos ], [ uPar4 ], [ uPar5 ], [ uPar6 ], [ uPar7 ], [ oWnd ], [ uPar8 ], [ lMemoria ], [
lColuna ], [ uPar9 ], [ lSemPastas ] ) -> objeto
Argumentos
Descrio
cAlias
nReg
uPar1
Parmetro reservado.
uPar2
Parmetro reservado.
uPar3
Parmetro reservado.
aAcho
aPos
aCpos
uPar4
uPar5
Parmetro reservado.
uPar6
Parmetro reservado.
uPar7
Parmetro reservado.
70
oWnd
uPar8
Parmetro reservado.
lMemoria
lColuna
uPar9
Parmetro reservado.
lSemPastas
Retorno
Objeto.
Refresh
Descrio
Atualiza os objetos contidos na MsMGet.
Sintaxe
Refresh()
Hide
Descrio
Esconde a MsMGet.
Sintaxe
71
Hide()
Show
Descrio
Mostra a MsMGet.
Sintaxe
Show()
Exemplo
User Function Exemplo()
Local i
Local oDlg
Local oMsMGet
Local lInit
Local cCampo
DbSelectArea("SA1")
For i := 1 To FCount()
cCampo := Field(i)
lInit := .F.
If ExistIni(cCampo)
lInit := .t.
M->&(cCampo) := InitPad(SX3->X3_RELACAO)
If ValType(M->&(cCampo)) = "C"
72
M->&(cCampo) := Padr(M->&(cCampo),SX3->X3_TAMANHO)
EndIf
If M->&(cCampo) == NIL
lInit := .F.
EndIf
EndIf
If !lInit
M->&(cCampo) := FieldGet(i)
If ValType(M->&(cCampo)) = "C"
M->&(cCampo) := Space(Len(M->&(cCampo)))
ElseIf ValType(M->&(cCampo)) = "N"
M->&(cCampo) := 0
ElseIf ValType(M->&(cCampo)) = "D"
M->&(cCampo) := CtoD(" / / ")
ElseIf ValType(M->&(cCampo)) = "L"
M->&(cCampo) := .F.
EndIf
EndIf
Next
DEFINE MSDIALOG oDlg TITLE "Exemplo" FROM 00,00 TO 19,80
MSMGET():NEW("SA1",0,3,,,,,,,,,,,,,.T.)
ACTIVATE MSDIALOG oDlg CENTERED ON INIT EnchoiceBar(oDlg,{|| oDlg:End()},
{|| oDlg:End()})
Return
73
MBrowse
Monta um Browse com menu de opes.
74
Sintaxe
MBROWSE( [ uPar1 ], [ uPar2 ], [ uPar3 ], [ uPar4 ], cAlias, [ aFixos ], [ cCpo ], [
uPar5 ], [ cFun ], [ nPadrao ], [ aCores ], [ cExpIni ], [ cExpFim ], [ nCongela ] ) ->
nil
Argumento
Obrigat.
Tipo
Descrio
uPar1
No
Parmetro reservado.
uPar2
No
Parmetro reservado.
uPar3
No
Parmetro reservado.
uPar4
No
Parmetro reservado.
cAlias
Sim
aFixos
No
cCpo
No
uPar5
No
Parmetro reservado.
cFun
No
nPadrao
No
aCores
No
cExpIni
No
cExpFim
No
nCongela
No
Descrio
As variveis cCadastro e aRotina (*) precisam ser declarados como private acima da
chamada da funo.
75
76
IncProc
Incrementa rgua de progresso.
Sintaxe
INCPROC() -> nil
Descrio
Para incrementar a rgua criada pela funo Processa(), utilizamos a funo IncProc()
Exemplo
User Function <nome-da-funo>( )
Local bAcao := {|lFim| Exemplo(@lFim) }
Local cTitulo := ''
Local cMsg := 'Processando'
Local lAborta := .T.
Processa( bAcao, cTitulo, cMsg, lAborta )
Return
77
If lFim
Exit
EndIf
INCPROC()
Next nI
Return
78
25/11/2003
EXERCCIOS
Analisar a situao e verificar a possibilidade da utilizao de Pontos de Entrada,
validaes de usurio ou gatilhos.
1) Necessito limitar o nmero de Itens no Pedido de Venda, de modo que o
usurio informe apenas 6 Itens por Pedido, nao mais que isso. Dever ser
mostrada uma mensagem informando a limitao ao usurio.
79