Académique Documents
Professionnel Documents
Culture Documents
OBS: Este tutorial presume que voce j tenha conhecimentos bsicos sobre arquivos, registros, indices e
demais estruturas de programao como laos, variveis, etc. Ele no pretende esgotar o assunto mas apenas
iniciar o leitor no dataflex verso 2.3 e 3.0 procedural.
Dvidas consulte o autor.
O Dataflex uma linguagem de programao e acesso a banco de dados (tambm Dataflex), voltada para o
desenvolvimento rpido de arquivos de dados e ferramentas de consulta, cadastro, relatrios, e muitas outras
voltadas a esta base de dados. Suas principais vantagens so a facilidade de desenvolvimento de aplicativos
com grande portabilidade para diferentes sistemas operacionais (Windows, DOS, Unix, AIX, Linux,
Solaris,etc), bastando apenas a recompilao dos arquivos fontes. Para os usarios do sistema exitem as
vantagens da facilidade de uso, rapidez de cadastro, velocidade e confiabilidade no acesso aos dados,
interface agradvel podendo ser grfica ou modo texto. Existe o Visual Dataflex para windows, mas nesta
apostila falaremos apenas do dataflex para DOS e UNIX verses 3.0 e 2.3 usando lgica de programao
procedural (a 3.0 suporta P.O.O. e procedural). Com o dataflex vem diversos aplicativos, eis os principais
deles que sero explicados com maiores detalhes mais adiante:
DFCOMP - Compilador dataflex que compila o arquivo texto de extenso (.FRM por padro) para um
arquivo executvel de extenso .FLX. Usa-se DFCOMP <nome do programa + extenso>.
DFRUN - Executa um programa dataflex. Note que o FLX no pode rodar sozinho precisa do programa dfrun
para poder executar. Um programa dataflex s funciona numa mquina que tenha pelo menos instalado o run-
time do dataflex. Mas se a empresa precisa frequentemente mexer nos programas ai vai precisar do dataflex
verso desenvolvedor (completo e mais caro).Usa-se: DFRUN <nome do programa sem extenso>
DFFILE - Usado para criar arquivos de dados (.DAT) , arquivos de indices (.K1,.K2,etc) e tambm
relacionamentos. Com este utilitrio voce cria todos os campos do arquivo e depois cria os indices. Voce
tambm pode gerar arquivo de dados (vazio claro!) tambm a partir de definies de arquivos (.DEF) que
so arquivos textos.
DFQUERY - Consultas rpidas a arquivos. Voce v a estrutura do arquivo, campos, indices, quantidade de
registros e pode selecionar padres de consulta comparando um ou vrios campos com faixas de valores que
voce fixa (semelhante a clasula where do SQL). As consultas podem ser direcionadas para arquivos texto,
vdeo ou impressora e podem ser ordenadas por um indice opcionalmente. muito usado este utilitrio na
exportao (gerando arquivo texto) e conferncia dos dados.
READ - importa arquivos textos pra arquivo de dados em formatos separados por linhas ou ponto e virgla.
usado para gerar programas de importao de dados.
ENTERDEF - Gera executveis de entrada de dados com macro enter automaticamente a partir de arquivos
texto de definio de arquivo(.DEF)
DFINDEX - Ferramenta para reindexar arquivos de dados.
DFSETUP - Utilitrio para alterar configuraes internas do dataflex.
AUTODEF - utilitrio pra se criar uma aplicao de cadastro (macro enter) atravs de uma imagem.
MENUDEF - usado pra se criar menus e sub-menus. Ex: menu pricipal, menu da expedio, menu da vendas,
etc.
Note que o banco de dados dataflex (verses 3.0 e 2.3) no relacional. Para um nico arquivo de dados
(.DAT) criado so criados alguns arquivos adicionais como indices(.K1,.K2,.K3,etc) definio de
arquivo(.DEF), "apelidos" de campos de arquivos usados na compilao (.FD), arquivo de dados compactado
da verso 3.0 (.VLD), arquivo de nomes de campos de arquivos (.TAG). Veremos adiante mais detalhes sobre
estes arquivos.
Tenha em mente que o dataflex uma exelente ferramenta multi-sistema operacinal, com grande
confiabilidade e velocidade de acesso. Eu trabalhei alguns anos com esta linguagem num ambiente Unix com
servidor RISC da IBM com a verso 2.3 com terminais e micros emulando terminias numa firma de grande
volume de cadastros e consultas, com cerca de 100 usurios, 500 arquivos alguns com quase 1 milho de
registros e nunca tive problemas srios com arquivos (bom o RISC ajudou muito...). Os problemas que
raramente ocorreram foram nada que no pudesse ser resolvido com simples reindexao de arquivo. Bom ai
quem gosta de horas-extras em CPD vai preferir outras tecnologias "modernas"...
No dataflex voce trabalha com um registro por vez do arquivo em disco que lido no buffer do arquivo (na
memria) e do buffer pra tela, segundo o esquema abaixo:
Quando voce edita ou grava um registro voce esta fazendo isto na tela mas atravs de um comando (entry)
que ja tambem edita o buffer e depois no final da entrada ou edio vem a gravao fsica dos dados no HD.
Isto a nvel do usurio muito pratico porque ele vai colocando os dados e apertando enter at receber uma
mensagem de confirmao (opcional) e com novo enter grava os dados. As busca por valores so
extremamente simples tambm. O usurio preenche uma entrada parcialmente (desde que ele faa parte de um
indice) e aperta F8 ou TAB e j vem o registro mais prximo para a tela que esta pronto pra ser editado. Aps
a edio de um campo aperta F10 e salva os dados ou aperta F9 e limpa a tela tudo sem a lentido do mouse.
Voce j percebeu como lento cadastrar procurando os campos com o mouse? Ou como complicado usar
aquelas barras de navegao com inmeros botes, tipo o dbnavigator do delphi? Pro usurio o dataflex
permite uma enorme facilidade e desempenho tanto no cadastro, na edio e na busca por registros. Outra
vantagem so a versatibilidade da linguagem que permite relatrios de qualquer tipo e tambm grficos na
tela ou impressos, alm de leitura e impresso de cdigo de barras. Bom com o decorrer do tempo voce ver
como o dataflex uma tima ferramenta com grande produtividade e aceitao pelos usurios!
Captulo 2 - Criando a base de dados
O utilitrio para criao e edio de arquivos o DFFILE. Assim o primeiro passo para a criao de um
programa verificar quais arquivos ele vai usar e com o dffile imprimir uma listagem de cada arquivo. A
listagem de um arquivo impressa (que o .DEF do arquivo) fica mais ou menos assim:
-----------------------------------------------------------------------------
DATA: 28/05/2002 HORA: 14:50 PAGINA: 1
DEFINICAO PARA O ARQUIVO: PRODUTOS (# 4)
-----------------------------------------------------------------------------
NOME BASE : PRODUTOS
NOME PARA USUARIO : PRODUTOS
NOME PARA DATAFLEX : PRODUTOS
-----------------------------------------------------------------------------
TAMANHO DO REGISTRO : 256 (USADO: 178 )
No. MAXIMO DE REGISTROS : 16711679 (USADO: 12520)
COMPRESSAO DO ARQUIVO : Rapida
REUTILIZAR ESPACOS EXC. : Sim
RELEITURA MULTI-USUARIA : Sim
-----------------------------------------------------------------------------
Bem acima est a data e hora de criao do arquivo. Depois vem sua posio no FILELIST que um numero
que corresponde geralmente a ordem de criao do arquivo e que o dataflex utiliza internamente, junto com o
numero do campo.
Com relao aos campos temos o numero do campo que sequencial, depois o nome do campo, depois o tipo
do campo, seu tamanho, a posio, o indice a qual ele faz parte e finalmente a qual outro campo de outro
arquivo que ele est relacionado.
O Filelist mais ou menos assim:
1 - Produtos - arq001
2 - Unidades - arq002
3 - Embalagens - embs01
etc...
TEXT - campo para texto sem formatao (na verso 2.3 no existe)
BLOB - campo para grandes objetos tipo fotos (na verso 2.3 no existe)
Logo depois dos campos vem as informaes sobre indices. No caso acima o indice 1 exclusivo porque no
aparece nele o recnum. Quando voce deseja tirar a exclusividade de um indice acrescente no final dele o
recnum.
RECNUM um campo tipo numero inteiro (>0) que corresponde geralmente a ordem de criao do registro,
tipo o primeiro registro gravado tem recnum= 1 o segundo registro gravado tem recnum= 2 e assim por
diante. O recnum um campo que sempre existe num arquivo e tem valor exclusivo. Mesmo se um arquivo
for criado sem indices o recnum pode ser usado como indice. Quando voce deleta um registro aquele recnum
reutilizado pelo dataflex numa futura insero de registro. Em arquivos onde no se deleta registros o
recnum pode ser usado como um cdigo sequencial exclusivo.
Bom falamos no caso do arquivo j estar criado. Se no existir o arquivo que voce quer muito fcil cria-lo
usando o DFFILE, porque ele um utlitario que cria tudo passo a passo sem codificao.
Recomendaes:
1-Use nome de campos claros tipo COD_PRODUTO e nao CPR, vai te facilitar a vida e dos outros
programadores.
2-Use o mesmo nome do campo em diferentes arquivos, exemplo: PRODUTOS.COD_PRODUTO e
MOVIMENTOS.COD_PRODUTO pois tambm facilita!
3-Procure colocar os campos principais que faro parte do indice principal no comeo do arquivo na mesma
ordem que vo aparecer no indice.
4-Evite indices com muitos campos grandes, use overlaps.
5-Crie indices inteligentes e s os crie na medida da necessidade.
6-No duplique informao desnecessariamente gravando a mesma informao em dois arquivos, normalize
os arquivos.
7-No crie muitos indices exclusivos prefira indices no exclusivos.
8-Lembre que o FILELIST comporta 255 arquivos no crie arquivos desnecessariamente.
9-Crie os arquivos que no existem, imprima as definies de todos os arquivos que sero abertos no
programa e s ai comece a programar.
Captulo 3 - Telas de um programa dataflex (procedural)
//**************************************
//programa P-001
//sistema: agencia de empregos
//finalidade: cadastro de profissionais
//feito por Paulo Miranda 17/01/2003
//atualizado por Simone 25/02/2003
//**************************************
/Tela1
Codigo: _________.
Nome: __________________________________________________
Endereco: __________________________________________________
E-mail: __________________________________________________
/Telamens
___________________________________________________ _
/Aviso
janelas...
/*
Acima temos o exemplo da declarao de 3 telas em dataflex. Observe que o nome da tela deve comear com
"/" tipo "/Nome_da_tela". A primeira etapa desenhar as telas, claro que d pra caprichar mais do que no
exemplo acima e fazer sombra, contorno e se for modo grfico ento nem se fala. Todo programa comea
com as telas e depois vem o simbolo "/*" colocado sempre totalmente a esquerda e depois das telas pra iniciar
o cdigo.
Janelas so chamados os locais de entradas de dados (diferente de janela no windows). Por exemplo
"____.__" uma janela para entrada numrica de 4 inteiros e dois decimais.
Tipos de janelas:
ASCII: ______________________
So para entradas de dados ascii
Observe que uma boa prtica dimensionar a janela com o mesmo tamanho e tipo do campo de arquivo. Mais
tarde voce vera como conectar a janela com seu campo de arquivo respectivo.
Quando voce cria uma tela as janelas tem nomes padro que depois podero ser redefinidos. A nomenclatura
funciona assim:
TELA1.1 seria o codigo
TELA1.2 a primeira janela que corresponde ao nome.
TELA1.3 o endereo
TELA1.4 a terceira janela da direita pra esquerda e de cima pra baixo que coresponderia ao codigo da
cidade
TELA1.5 corresponderia ao nome da cidade
TELA1.6 seria a UF ou estado
E assim sucessivamente seguindo a regra: Nome_da_tela.indice_janela
Teriamos Telamens.1 e Telamens.2 na outra tela.
Obseve que nem todas telas tem janelas (pode ser uma tela apenas pra help ou aviso) mas toda janela tem que
estar definida numa tela.
Quando o usurio estiver usando o programa ele inserir uma informao numa janela em seguida apertar
ENTER e o cursor vai pr janela seguinte pra nova entrada, isto veremos melhor depois.
IMPORTANTE: O simbolos "/" sempre deve estar encostado no inicio da linha quando se referir a nome de
tela ou "/*" inicio de programaao.
Recomendaes:
1-Capriche no layout das telas e procure seguir padres que seus usuarios ficaram satisfeitos. Evite telas
muito carregadas de janelas e tambm evite programas com muitas telas pra entrada de dados.
No capitulo anterior fizemos as telas do nosso primeiro programa. Agora vamos comear a codificar. Logo
aps o simbolo "*\" comearemos cdigo:
/*
//=======[ Inicio da Programao ]===========
// Usa-se barra barra para comentrio!
#include biblioteca.inc
#include fmar.inc
At aqui parece que d pra entender no ? INCLUDE para incluir bibliotecas com seus prprios comandos.
Falaremos como criar comandos depois.
PAGE SET o comando que posiciona a tela no vdeo. Aqui estamos usando modo texto de 80 colunas X 25
linhas.
OPEN pra abrir o arquivo e AS opcional.
Depois vem:
Esta parte de names opcional mas bom sempre colocar, procurando colocar o nome da janela igual o nome
do campo de arquivo. Observe que isto ir facilitar a programao mas a janela pode ter o nome que voce
quizer menos nome de comando ou palavras reservadas do dataflex.
Se voce bom observador precebeu que coloquei name tela1 na primeira linha e depois acaba com ponto e
vrgula. O ponto e virgula pra string no dataflex continuar na outra linha.
O comando name aceita uma string com um mximo de 255 caracteres por isso depois eu coloco outro
NAME pras prximas janelas pra no estourar o tamanho da string de comando, observando que no repito o
nome da tela porque o dataflex entende que estou me referindo a tela1.
Se eu no colocar names nas janelas quando precisar inserir uma janela ser necessrio varias alteraes no
programa. Observe:
Se no tenho names os nomes padro ficam tela1.1, tela1.2, tela1.3 at tela1.19. Imagine que eu queira inserir
uma nova janela entre tela.4 e tela.5, esta janela passar a ser a tela.5, a tela.5 passa ser a tela.6 e assim por
diante. Como no dataflex muitos comandos fazem referencias a nomes de janelas se eu tiver muito cdigo no
programa precisarei fazer muitas alteraes porque na insero da tela.5 nova todas as janelas seguintes
mudaram seu names. Ento USE SEMPRE NAMES!
Vamos continuar com nosso programa exemplo:
//============================================
TIPOS DE VARIAVEIS NO DATAFLEX:
STRING - String de tamanho padro 80 caracteres se voce cita o comprimento depois do nome da string voce
redefine este valor, observe que no existe o tipo char ento quando se usa uma string de tamanho 1 como
um char.
Ex: string letra 1
DATE - Data no formato dd/mm/aaaa. O dataflex suporta todas operaes com datas, tipo somar data com
inteiro e outras.
INDICATOR - o tipo booleano de valor FALSE ou TRUE, so de grande utilidade no controle do fluxo do
programa.
No dataflex como toda linguagem de programao que se preze existem laos, antes porm vamos dizer mais
sobre indicadores, que so importantes controladores de fluxo nos programas.
Declaramos indicadores assim:
Pra mudar seu valor (quando criado esta falso) usamos o comando indicate:
na sentena acima o valor de meu_indicador (true ou false) ser o mesmo do valor de outro_indicador. No
exemplo acima meu_indicador ser false aps a sentena porque ele copiou o valor de outro_indicador que
era false.
Ou atribuimos indicadores comparando de outras formas:
No programa o indicador aparece entre colchetes tipo [ MEU_INDICADOR ] quando esta controlando blocos
de cdigo, laos, ou depois do AS. Falaremos deles muito mais vezes no se preoculpe. Mas observe que um
indicador SEMPRE contm um valor que falso (false) ou verdadeiro (true).
[ meu_indicador ] comando_x
[~meu_indicador ] comando_y
Se meu_indicador estiver true s o comando_x ser excutado caso contrrio s o comando_y ser executado.
[ meu_indicador ] BEGIN
comando_x
comando_y
[ outro_indicador ] BEGIN
comando_z
comando_k
END
END
INDICADORES COMBINADOS:
EQ o igual (= no pascal e == no C)
NE o diferente (<> no pascal e != no C)
LT o menor (<)
LE o menor ou igual (<=)
GT o maior (>)
GE o maior ou igual (>=)
NOT a negao e tambm representado por ~ dependendo do caso.
OR o ou (or no pascal e || no C)
Obs: infelizmente o AND no exite e tem que ser feito com if ou indicadores.
O comando MOVE usado pra mover valores pra vriveis, janelas e campos de arquivos. bom frisar que
uma grande vantagem do dataflex que podemos mover dados de inmeras formas, como por exemplo
variavel pra uma janela, somar variavel com campo de arquivo, somar janela data com inteiro, e muito mais.
Sintaxe do move:
Exemplos:
Agora os LAOS:
(1) IF - pode ser usado de vrias formas mas sua lgica IF <condiao> comando
sua traduao se a condiao for verdadeira executado o comando.
exemplos:
IF numero LT 10 BEGIN
<COMANDOS>
END
ELSE BEGIN
<COMANDOS>
END
REPEAT
comando_x
comando_y
UNTIL [ MEU_INDICADOR ]
REPEAT
comando_z
UNTIL numero LE 10
exemplos:
down significa que esta decrescendo e step o valor que a vriavel de controle decrementada (o default 1)
se dentro do for forarmos a variavel de controle chegar no valor limite isto uma forma de sair do for. Ex
acima: move 100 to num
exemplos:
WHILE [ indicador ]
comando_x
comando_y
LOOP
(6) GOTO Label um recurso que existe mas deve ser usado com cuidado, procure usar os outros laos que
daro mais legibilidade e coerencia para os seus programas.
exemplos:
LB_INICIO:
<comandos>
IF resp EQ "N" GOTO LB_INICIO
No prximo capitulo veremos mais comandos... no entrei em detalhes nos laos porque voce deve te-los
visto em outras linguagens espero.
Capitulo 6 - Mais comandos dataflex (os mais usados)
ABORT - este comando termina um programa dataflex e volta pro programa pai que pode ser um menu
dataflex, outro programa ou o sistema operacional.
ACCEPT - aceita uma entrada de tecaldo numa janela, a entrada terminada com o pressionamento da tecla
enter. Exemplo:
name telamens mens resp
inicio:
<comandos>
move "Dados corretos para gravar? (S/N)" to mens //mosta a mensagem
move "S" to resp //valor padro da resposta
accept resp {Capslock,check="SN"} //opa isso de capslock falaremos depois
if resp eq "N" goto inicio
<comandos>
abort //fim do programa
AUTOPAGE - pra poder dar entry's sem precisar citar a janela, mas segue a ordem das janelas. EX:
autopage tela1
entry produtos.cod_tipo
entry produtos.cod_produto
entry produtos.desc_produto
...
ASCII - usa-se ascii str to var_int, isto , obtem o valor inteiro de um caracter ascii e guarda-o numa varivel.
Veja CHARACTER.
CHARACTER - var_int to str. Obtem o caracter ascii correspondente ao inteiro e quarda-o numa variavel
string.
CIC_CHECK, CGC_CHECK testam a validade do cic e do cgc e devovlvem o resultado em ERR = true se
invlido, ERR = false se vlido. Ex:
repeat
entry clientes.cgc cgc
cgc_check cgc
until [~err]
CURRENT_WINDOW - varivel inteira interna do dataflex que guarda o valor da janela corrente.
CURRENT_IMAGE - varivel inteira interna do dataflex que guarda o valor da imagem (tela) corrente.
DISPLAY - sintaxe: display <arquivo.campo> to janela. Mostra o conteudo do campo com formataes
diferentes do entry. (signrt,fill,float$,etc)
ENTDISPLAY - mostra os campos nas janelas com entrys, geralmente aps uma busca. Ex:
entry produtos.codigo codigo
entry produtos.desc desc
entry produtos.val_unit val_unit
<comandos>
findkey eq produtos by index.1 ;
for produtos.codigo eq 11135
[ found] entdisplay produtos
ENTERMODE - impede o cusor de voltar pra janelas anteriores a sua chamada. Este comando no deve ser
usado no meior de entrys.
ENTRY - opa este um comando importante que mostraremos com detalhes nos prximos captulos. Ele faz
a ligao da janela com o campo de arquivo. Ele da um accept e joga o valor da janela no buffer.
usado na macro enter ou entergroup, nunca fora delas!
Exemplo:
ENTRY Produtos.Cod_produto Cod_produto
ENTRY Clientes.Nome Tela1.4 {Capslock}
ENTER - macro enter, proporciona um ambiente completo de entrada de dados, ser vista em breve.
ERROR - Da uma mensagem de erro pro usurio com numero e com beep.
Ex: error 200 "Codigo invalido!"
FIND, FINDKEY, SEARCHKEY - So comandos de busca de registros no dataflex que setam found e
finderr aps a busca ser efetuada
Exemplos:
(1)
move "P" to clientes.nome //inicializa a chave
find gt clientes by index.2
[ found ] move clientes.codigo to tela1.3
vai mostrar o prximo nome c/valor maior que "P",por exemplo "Patricia Souza"
find pode ser find gt, find ge, find le, find le
(2)
findkey eq produtos by index.1 ;
for produtos.cod_tipo eq 10202 ;
produtos.cod_produto eq "1166665P"
findkey usado quando o indice exclusivo e todos campos esto preenchidos
(3)
searchkey ge produtos by index.4 ;
comparing produtos.cod_inter eq cod_inter
searchkey usado para indices no exclusivos
FINDERR - indicador pr-definido que indica se foi achado registro numa busca. Se no acho finderr = true.
Juntamente com o found setado aps um comando de busca em arquivo (find,findkey,searchkey).
FOUND - indicador pr-estabelecido que indica se foi achado registro ou no aps um comando de busca tipo
find, findkey, searchkey etc. Quando chega no final do arquivo de dados o found = false e finderr = true.
GOSUB - subrotinas so muito boas pra dar legibilidade e facilitar a manuteno dos seus programas,
infelizmente na verso 2.3 elas no retornam valores, devendo trabalhar sempre com variveis do tipo global
declarados no inicio do seu programa. Exemplo:
<comandos>
GOSUB Calcula_media
<comandos>
ABORT
//===[ Subrotinas ]====
Calcula_media:
<comandos>
RETURN
Observe que o comando RETURN volta pro ponto logo a seguir a chamada da subrotina com GOSUB.
LEFT, RIGHT e MID - movem parte de dados de um local pra outro. Exemplo:
integer dia mes ano
string strdata 10
move clientes.data_cadastro to strdata
right strdata to ano 4
mid strdata to mes 2 4
left strdata to dia 2
Peceba que left e right usa-se com um parametro que o tamanho a ser movido e mid tem dois parametros um
o tamanho e o segundo a posio de inicio pra mover. So comandos muito uteis.
IFCHANGE - indicador predefinido que indica se houve alterao. Ex:
ifchange tela1.1 begin
<comandos>
end
INKEY - captura uma tecla do teclado sem precisar apertar enter. Ex:
string letra 1
inkey letra
if letra eq "R" gosub relatorio
INKEY$ - usado pra capturar teclas em loops, sem parar o loop, bom pra por em loops muito demorados
pro usuario poder abortar se quizer.Ex:
string letra 1
<comandos>
repeat
<comandos>
inkey$ letra
if letra eq "A" abort
until [ found ]
INSERT - insere uma substring numa string numa posio determinada. Ex.
insert substr IN str AT 04
LENGTH - retorna o tamanho de uma string. Ex: For num from 1 to length(str)
MOVESTR, MOVE - so comandos usados pra mover dados. S que o movestr move exatamente o dado sem
formatalo.
OPEN e OPEN .. AS - abre arquivo pra leitura/gravao. Se usarmos file_mode podemos abrir s pra leitura.
EX:
open "C:\bdados\meu_arq" as meu_arq
file_mode read_only //==s leitura
OUTFILE - prepara um arquivo ou dispositivo pra ser a saida padro, fecha com OUTCLOSE. Ex:
outfile "arquiv1.txt"
outfile "LST:", pra impressora
OUTPUT - manda uma tela pra saida padro que pode ser redirecionada. Ex:
outfile "LST:"
output tela1 //imprime a tela1
outclose
PAGE - mosta uma tela no video, esta embutido em comandos como accept e entry. Ex: page telamens
PAGESET - ajusta uma tela no video. Ex: page set tela1 at 05 06 colors 10 11 o colors opcional.
PAUSE - faz uma pausa no programa esperando digitao e mostrando uma mensagem pro usurio. Ex: pause
"Pressione tecla para continuar..."
POS - posicao de uma substring numa string tipo pos substr in str to num, o pos seta o indicador found
tambm. (found = true se achou)
REPLACE - muda o valor de uma substring numa string por outra string, e devolve o valor de found = true se
achou a substring e found = false se no a achou. Exemplos:
move "paula" to str
replace "a" in str with "o" //resulta str="poula"
move "paula" to str
while [ found ]
replace "a" in str with "o
loop
//resulta str= "poulo"
move "paula" to str
replacle "pau" in str with "" //resulta str="la"
REPORT - macro report proporciona grande facilidade pra relatrios, ser estudada c/detalhes
posteriormente.
RETURN - volta de um gosub, se usarmos RETURN RETURN volta da subrotina e da rotina que chamou
aquela subrotina (2 nveis).
SAVE - salva o registro no buffer, e move os dados do arquivo principal pros arquivos relacionados
secundrios salvando-os em seguida. Nunca use save dentro da macro enter ou entergroup, pois os dados no
foram ainda movidos pro buffer. Use-o fora depois do enterend ou depois do endgroup.
SAVERECORD - salva o regitro no buffer mas no caso de arquivos relacionados no move os dados do
arquivo principal pros arquivos relacionados secundrios. Ex: SAVERECORD CLIENTES
No use saverecord dentro de macro enter ou entergroup pelo mesmo motivo do comando save.
SHOW e SHOWLN pra mostrar uma mensagem direto na tela sem janelas.
SUBTOTAL - comando usado na macro report pra totalizar. Ser visto mais adinate com detalhes. Ex:
subtotal body.2 to subtotal1.1
WINDOWINDEX - variavel que contm o indice da janela, seu uso facilita muito a programaao.Ex:
/tela1
___. ___. ___. ___. ___. ___. ___. ___. ___. ___. ___. ___.
/*
<comandos>
move ( mes - 1 ) to windowindex
calc ( valor + tela1.1& ) to tela1.1&
Observe que a windowindex tem que ser acessada usando o simbolo "&", no exemplo acima se o mes 5 ele
acumula o valor na tela1.5
No dataflex verses 2.3 e 3.0 a integridade dos dados dependente das aplicaes de cadastro. Bons
programas de cadastro resultam num bom banco de dados. Claro que voce pode criar uma ferramenta pra
atualizar a base de dados mas o ideal os dados serem o mais coerentes possveis j na entrada.
So usadas aps comandos como entry e accept ou no comando format. Sempre usamos os simbolos "{" e "}"
para as formataes, tipo {formatao1,formatao3,...formataoN}
DISPLAYONLY - quando a janela s de leitura. O displayonly a combinaco de noenter com noput. Ex.
ENTRY PRODUTOS.DESC DESC {DISPLAYONLY}
NOENTER - impede um enter na janela mas grava seu valor no buffer. usado quando temos 2 ou mais
entrys numa janela, para evitar que o usuario tenha que apertar mais de uma vez a tecla enter numa mesma
janela. Ex.
ENTRY PRODUTOS.COD_PRODUTO COD_PRODUTO {AUTOFIND,FINDREQ}
ENTRY MOVIMENT.COD_PRODUTO COD_PRODUTO {NOENTER}
ENTRY NOTAS_FI.COD_PRODUTO COD_PRODUTO {NOENTER}
observe que a janela cod_produto esta relacionada com 3 arquivos.
CAPSLOCK - faz com que tudo que o usurio digite seja convertido pra letras mausculas. Ex. ENTRY
CLIENTES.ENDERECO ENDERECO {CAPSLOCK}
REQUIRED - impede o cursor de sair da janela sem que o usurio digite algo. Ex: ENTRY
CLIENTES.ENDERECO ENDERECO {CAPSLOCK,REQUIRED}
CHECK - checa se o conteudo da janela esta contido na string de checagem. Ex. ACCEPT RESP
{CAPSLOCK,CHECK="SN"} e resp uma janela ascii de tamanho 1.
ACCEPT UF {CAPSLOCK,CHECK="SPxRJxMGxES"} e uf janela de tamanho 2.
AUTORETURN - quando o usurio preeche o contedo da janela o cursor pula pra prxima janela, sem
precisar apertar o enter.
AUTOFIND - usado em janelas associadas a um campo que chave exclusiva, pra quando o usurio digitar
e apertar enter se o registro existir j trazido pra tela. Todos os campos do indice devem estar completos. Ex.
Exemplo1:
(index1 = codigo)
ENTRY CLIENTES.CODIGO CODIGO {AUTOFIND}
Exemplo2:
(index1 = cod_tipo + cod_produto)
ENTRY PRODUTOS.COD_TIPO COD_TIPO
ENTRY PRODUTOS.COD_PRODUTO COD_PRODUTO {AUTOFIND}
Exemplo3:
(index3 = bairro + rua + numero + apto)
ENTRY CLIENTE.BAIRRO BAIRRO
ENTRY CLIENTE.RUA RUA
ENTRY CLIENTE.NUMERO NUMERO
ENTRY CLIENTE.APTO APTO {AUTOFIND}
Quando o indice exclusivo usado possuir mais de um segmento, a opp autofind deve estar no ultimo campo
do ndice.
Se usarmos AUTOFIND,FINDREQ ser obrigatrio o usurio entrar na janela com uma entrada que seja
existente no arquivo. Observe que o findreq impede o usurio de gravar novos regitros porque ele exige que j
exista o registro.
Exemplo 4:
(index2 = cod_inter + cod_material)
ENTRY MATERIAL.COD_INTER TELA.2
ENTRY MATERIAL.COD_MATERIAL TELA.3 {CAPSLOCK,AUTOFIND,FINDREQ}
AUTOFIND_GE - sua funo a mesma do autofind s que procura por um valor maior ou igual ao da
janela. Ex:
Exemplo1:
(index1 = nome + sobrenome)
ENTRY FUNCIONARIO.NOME NOME {CAPSLOCK}
ENTRY FUNCIONARIO.SOBRENOME SOBRENOME {CAPSLOCK,AUTOFIND_GE}
FORCEPUT - fora gravar no buffer do arquivo, usado quando por existencia de muitos autofind o valor do
campo esta sendo destruido no buffer.
FORMAT - usado geralmente pra formatar grupos de janelas. Quando for colocar entry ou accepts em loops
use format, porque em loops a formatao individual no funciona. Ex:
format tela1.1 thru tela1.10 {capslock}
format hora_in {required,range=8,18}
for windowindex from 0 to 9
accept tela1.1& //nao adianta formatar aqui que no funciona!!!
loop
RETAIN - Mantm os dados na janela, mesmo quando apertado o F9 (key.clear). Pra limpar estas janelas
preciso apertar duas vezes o F9.
RETAINALL - Os dados jamais sero apagados com F9, apenas usando o comando blankform eles podero
ser apagados.
SKIPFOUND - uma opo que aparece normalmente com um autofind ou autofind_ge. Sua funo se caso
seja achado um registro, mostrar os dados na janela e pular pra prxima, sem deixar que ela possa ser
modificada.
***KEYPROCS***
Keyprocs so teclas de atalho associadas a labels e indicadores. O dataflex possui teclas de atalho padro que
podem ser reprogramadas com o dfsetup. Na verso 2.3 funciona assim:
F1 - key.help - ajuda
F2 - backwind - tela anteriror
F3 - superfind - superbusca
F4 - key.print - impresso
F5 - key.calculte - executa calculos na janela (5+4 retorna 9)
F6 - key.delete - deleta registro
F7 - key.user - voce define
F8 - key.user2 - voce define
F9 - key.clear - limpa tela
F10 - key.save - salvar dados
TAB - find - procura
PGUP - key.previous - registro anterior
PGDOWN - key.next - prximo registro
-> - key.right - seta pra direita
<- - key.left - seta pra esquerda
- key.up - seta pra cima
- key.down - seta pra baixo
ENTER - key.return - confirmao
keyproc key.help
page telahelp
pause ""
entagain
return
Keyproc Key.print
gosub imprime_relatorio
return
keyproc key.delete
move "Deseja deletar o registro? (S/N)" to mens
move "N" to resp //defaut
accept resp {capslock,check="SN"}
if resp eq "S" begin
delete arquivo
return entrysec //label da macro enter (prximo capitulo)
end
entagain
return
//=== Salvar o recnum (como no exemplo anterior) uma tcnica muito usada quando voce esta lendo um
arquivo e chama uma subrotina que l o mesmo arquivo por outro indice. Ex:
integer registro
clear clientes
repeat
find gt clientes by index.1
[ found] begin
...
move clientes.recnum to registro //salva o recnum
gosub novo_loop_do_arquivo //loop no MESMO arquivo
findkey eq clientes by recnum ;
for clientes.recnum eq registro //recupera o recnum
indicate found true //recupera o found
end;
until [~found]
...
novo_loop_do_arquivo:
clear clientes
move data_de to clientes.dt_cad
repeat
find gt clientes by index.2 //indice por data
[ found ] indicate found as clientes.dt_cad le data_ate
[ found ] begin
...
end
until [~found]
return
//=== pra importar de um arquivo texto o cdigo o mesmo s trocando direct_output por direct_input e os
writeln por readln. Observe que o utilitrio READ gera este cdigo automaticamente pra voce.
//=== Criar matrizes e vetores muito fcil, estas estruturas no existem na linguagem mas podem ser
emuladas com imagens tipo esta do exemplo anterior.
EX:
/vetor_meses
jan fev mar abr mai jun jul ago set out nov dez
___. ___. ___. ___. ___. ___. ___. ___. ___. ___. ___. ___.
Obs: nem todas imagens que voce cria sero mostradas pro usurio, algumas so pra uso interno do programa.
Captulo 9 - A macro enter (entrada de dados) e relacionamentos
Voce lembra daquele programa exemplo da agencia de empregos do capitulo 3 e 4, agora podemos termina-
lo. Seu cdigo ser este:
//**************************************
//programa P-001
//sistema: agencia de empregos
//finalidade: cadastro de profissionais
//feito por Paulo Miranda 17/01/2003
//atualizado por Simone 25/02/2003
//**************************************
/Tela1
Codigo: _________.
Nome: __________________________________________________
Endereco: __________________________________________________
E-mail: __________________________________________________
/Telamens
___________________________________________________ _
/Aviso
janelas...
/*
//=======[ Inicio da Programao ]===========
#include biblioteca.inc
integer ultimo
date data
clearform tela1
gosub acha_ultimo
move (ultimo + 1) to cod_candidato
enter empregados
blankform telamens
repeat
entry empregados.cic cic
cic_check cic
until [~err]
return
entry.find:
return
enterend
abort
acha_ultimo:
clear empregados
move 99999999 to empregados.codigo
find lt empregados by index.1
[ found ] move empregados.codigo to ultimo
[~found ] move 0 to ultimo
clear empregados
return
cep_mask:
string str 9 letra 1
integer num //mesmo definindo aqui so variveis GLOBAIS!
return
Keyproc key.escape
abort
Keyproc key.clear
return lb_inicio
Keyproc key.save
entagain
return
Keyproc key.delete
move "Deseja deletar o registro? (S/N)" to mens
move "N" to resp
accept resp {capslock}
if resp eq "S" begin
delete empregados
return lb_inicio
end
entagain
return
A macro enter fornece um ambiente de entrada de dados, vamos analisar sua estrutura:
ENTER ARQUIVO_PRINCIPAL
ENTRY.FIND:
//BUSCAS EM ARQUIVOS
RETURN
ENTER.SAVE:
RETURN
ENTER.DELETE:
RETURN
ENTER.CLEAR:
RETURN
ENTER.EXIT:
RETURN
ENTEREND
ABORT
A macro enter s pode ser usada uma nica vez no programa. Observe que a macro enter um loop e as
sees enter.save, entry.find e outras so opcionais no precisando ser declaradas quando no vo ser usadas.
Elas podem ser entendidas como sub rotinas padro da macro enter e so chamadas automaticamente
(parecido com eventos) dependendo do que est acontecendo no programa ou do pressionameto de keyprocs.
Voce pode chama-las explicitamente se quizer tipo com GOSUB ENTRY.FIND, que as vezes necessrio
fazer assim. A macro enter tem alguns indicadores e labels internos.
ENTRYSEC - label interno da macro enter. Goto entrysec impede que o registro seja gravado.
ENT$QUERY - indicador interno da macro enter que indica se o registro foi alterado. comum usar indicate
ent$query false antes de autofinds pra evitar bugs em determinados casos.
USO DE VARIAS MACRO ENTER - As vezes temos programas de ITENS E HEADER (ou itens e
cabealho), que so programas que voce cadastra um header e pra ele cadastra vrios itens, em arquivos
distintos, tipo o cabealho de uma nota fiscal, que tem a razo social da firma, CNPJ, data, numero nota,
endereco, etc. E os items da nota de numero variavel que so os produtos, seus valores unitarios, valores
totais, etc. Como no podemos usar vrias macro enter mas apenas uma, fazer este tipo de programa da forma
tradicional uma coisa chata. Voce poderia usar a entergroup mas tambm no o ideal. O melhor neste caso
trabalhar com dois programas como se fosse um s, usando chain! A voce ficar com uma macro enter pro
header, totalmente normal, e o subprograma dos items, com outra macro enter simples. Pro seu usurio vai
parecer que um programa s, e maior trabalho passar alguns parmetros do programa chamador pro
programa filho...
Como vimos no captulo anteriror a macro enter nos fornece muitas comodidades pra fazer cadastros:
- O arquivo principal salvo automaticamente
- Ela cria um loop pra cadastrar o prximo registro
- Existem sub-rotinas prontas pra serem usadas: entry.find, enter.save, enter.delete e outras.
- As teclas de funo funcionam automaticamente, tipo:
F10 - salva registro
F6 - deleta registro
F9 - limpa a tela
PGDOWN - proximo registro
PGUP - registro anterior
TAB - super-busca
etc.
Todavia em certas ocasies mais conveniente o programador definir estes procedimentos ele prprio, e
isto que faz a ENTERGROUP: permite mais liberdade ao programador ao custo de mais cdigo. Outra
diferena da entergroup que ela pode aparecer vrias vezes num programa, ao contrrio da macro enter que
s pode ser usada uma nica vez no programa.
Sintaxe:
ENTERGROUP
ENDGROUP
ENTERGROUP
<NOVO BLOCO>
ENDGROUP
/*
//=======[ Inicio da Programao ]===========
#include biblioteca.inc
integer ultimo
date data
clearform tela1
gosub acha_ultimo
move (ultimo + 1) to cod_candidato
entergroup
clear empregados
blankform telamens
repeat
entry empregados.cic cic
cic_check cic
until [~err]
endgroup
loop
return
acha_ultimo:
clear empregados
move 99999999 to empregados.codigo
find lt empregados by index.1
[ found ] move empregados.codigo to ultimo
[~found ] move 0 to ultimo
clear empregados
return
cep_mask:
return
Keyproc key.escape
abort
Keyproc key.clear
return lb_inicio
Keyproc key.save
entagain
return
Keyproc key.delete
move "Deseja deletar o registro? (S/N)" to mens
move "N" to resp
accept resp {capslock}
if resp eq "S" begin
delete empregados
return lb_inicio
end
entagain
return
Neste exemplo no seria sensato usar a entergroup, pois perderiamos muitas facilidades da macro enter sem
ganho algum. Mas em alguns casos sua aplicao necessria:
Imagine uma situao que voce faz vrias buscas num mesmo arquivo em janelas de uma mesma imagem,
como por exemplo, no caso abaixo que eu tenho 3 fornecedores por produto e eu desejo cadastrar estes
fornecedores no arquivo de produtos:
/tela
_________________________________________ _
/*
open fornecedores
open produtos
repeat
clear produtos
blankform mens
blankform resp
entergroup
endgroup
entergroup
endgroup
entergroup
endgroup
entergroup
loop
key.escape
abort
mostra_cadastrados:
loop
return
Observe que este programa no funcionaria bem com a macro enter porque quando buscassemos um
fornecedor pelo cdigo todas as outras janelas de codigo de fornecedores apresentariam valores iguais, ou
seja, se o forn1 fosse 1001 o forn2 e forn3 apareceriam 1001 tambm, que um efeito indesejvel nesta
situao. Lembre que queremos 3 fornecedores diferentes! Na entergroup a busca de um bloco no interfere
no outro mesmo que se refiram ao mesmo arquivo. Um outro uso comum da entergroup em seleo de
dados pra relatrios como veremos mais pra frente.
No proximo captulo veremos a macro report.
Captulo 11 - A macro report
Do mesmo modo que a macro enter nos fornece vrias facilidades para cadastros a macro report vai facilitar
muito a criao de relatrios simples ou complexos. Mas tambm poderemos fazer relatrios sem usar a
macro report, escrevendo muito mais cdigo... Do mesmo modo que a macro enter a report aparece uma nica
vez no programa.
Sintaxe:
SECTION HEADER
<COMANDOS>
OUTPUT HEADER
SECTION SUBHEADERX
<COMANDOS>
OUTPUT SUBHEADERX
SECTION SUBHEADERY
<COMANDOS>
OUTPUT SUBHEADERY
SECTION BODY
<COMANDOS>
OUTPUT BODY
SECTION SUBTOTALX
<COMANDOS>
SECTION SUBTOTALX
SECTION SUBTOTALY
<COMANDOS>
SECTION SUBTOTALY
SECTION TOTAL
<COMANDOS>
OUTPUT TOTAL
REPORTEND
SECTION HEADER - o cabecalho da pgina, impresso a header toda vez que iniciamos uma nova
pgina.
SECTION SUBHEADER1 - impressa toda vez que o primeiro campo do indice inicia.
SECTION SUBHEADER2 - impressa toda vez que o segundo campo do indice inicia.
OBS1: Observe que como um indice tem at nove campos no mximo podemos ter at a SUBHEADER9 e
SUBTOTAL9 num relatrio.
OBS2: Para cada section declarado (opcionalmente) deve haver obrigatoriamente uma tela correspondente
com o mesmo nome!
Ex. Section Body ==> /BODY
Section Header ==> /HEADER
A macro report tem algumas variveis, labels e indicadores internos, as vezes ser preciso mudar seus valores.
So eles:
END.OF.REPORT - label do fim do relatrio. Uas-se return end.of.report pra encerrar o relatrio.
SELECT - indicador interno que indica se um registro foi selecionado ou no. No final do arquivo select fica
false.
importados? _ (N)acionais,(I)mportados,(T)odos
copias: _.
_______________________________________ _
/*
//===Abertura arquivos=======
open "setores" as setores //===plasticos, vidros, cosmticos, etc
open "produtos" as produtos
//====Page sets==============
page set tela1 at 05 10
//====Variaveis==============
indicator imp todos
integer num
//====Names de janelas=======
name tela1 setor desc_setor impor copias mens resp
//====Loop principal=========
Inicio:
repeat
blankform tela1
gosub seleciona_dados
for num from 1 to copias
gosub imprime_relatorio
loop
loop
//=====keyprocs==============
keyproc key.escape
abort
keyproc key.clear
return inicio
//=====subrotinas============
Selecina_dados:
repeat
entegroup
entry setores.setor setor {autofind,findreq}
entry setores.desc_setor desc_setor {displayonly}
endgroup
move "N" to impor
accept impor {capslock,check="NIT"}
indicate imp as impor eq "I"
indicate todos as impor eq "T"
move 1 to copias
accept copias {range=1,10}
move "Dados corretos para gerar relatorio?" to mens
move "S" to resp
accept resp {capslock,check="SN"}
until resp eq "S"
return
Imprime_relatorio:
clear produtos
move setor to produtos.cod_setor
//indice.1 = setor + cod_produto
report produtos by index.1 break produtos.setor
[ select ] indicate select as produtos.setor eq setor
[~select ] return end.of.file
[~todos imp] indicate select as produtos.flag_impor eq "I"
[~todos ~imp] indicate select as produtos.flag_impor eq "N"
section header
print pagecount to header.1 {fill="0"}
sysdadte header.2 header.3 header.4
print header.3 to header.3 {fill="0"}
print header.4 to header.4 {fill="0"}
output header
section subheader1
print produtos.cod_setor to subheder1.1
findkey eq setores by index.1 for
setores.setor eq subheader1.1
output subheader1
section body
print produtos.cod_produto to body.1
print produtos.desc_produto to body.2
print produtos.qtd_estoque to body.3
print produtos.val_unit to body.4
output body
section total
print reccount to total.1
output total
reportend
formfeed
outclose
return
//=======fim=================
No prximo captulo mais exemplos da report.
Captulo 12 - Mais exemplos com a report
TEORIA:
(1) Uso do BREAK: No dataflex o comando break opcional e significa que quando o indice quebrar, uma
imagem sera impressa.
Sintaxe: REPORT arquivo BY index.n {BREAK arquivo.campox,arquivo.campoy,...}
Vamos exemplificar: Suponha um arquivo de items de notas fiscais cujo index.3 composto dos campos:
setor+cod_produto+val_item+recnum. Se quizermos usar report items_nfs by index.3 break cod_produto
teremos que definir uma section subtotal2 porque cod_produto o segundo campo do indice. Sempre
seguiremos est lgica. E quando no houver breaks, no existiro sections subtotal nem subheader.
(2) Quando criamos uma janela tipo body.1 o dataflex automaticamente aloca uma variavel body.1% que
acumula o valor dessa janela, pra que esse valor possa ser retornado com o comando subtotal, na section
subtotal1 por exemplo. A sintaxe seria SUBTOTAL body.1 TO subtotal1.1
(3) Quando voce precisar de um relatrio com vrias opes de formato, e leituras do arquivo com diferentes
indices, o melhor a fazer criar varios subprogramas, usando chain pra executar cada um a partir das opcoes
selecionadas no programa principal. Assim voce pode usar vrias macro report usadas de forma simples em
cada subprograma. Exemplo:
string programa parametros
move "relprod" to programa
accept opcao {capslock,check="ABCDEF"} //cada opcao um tipo de relatorio
append programa opcao parametros
chain wait programa
...
(4) Pro programa funcionar melhor declare todas as imagens da report como RESIDENT. Exemplo
/body resident
__. ______________
/total resident
Bom acredito que a melhor forma de aprender a usar a report vendo sua aplicao na prtica, ento vamos
l:
EXEMPLO1 - Usando a section body pra acumular. Veja esta subrotina que usa a macro report:
IMPRIME_RELATORIO:
CLEAR SCOA233
[ ~TODOS ] MOVE USUARIO TO SCOA233.CODU
[ ~TODOS ] MOVE DATA_DE TO SCOA233.DATA
REPORT SCOA233 BY INDEX.2 BREAK SCOA233.CODU SCOA233.DATA ;
SCOA233.TOT_HS_DECIMAL
[ ~TODOS SELECT ] INDICATE SELECT AS SCOA233.CODU EQ USUARIO
[ ~TODOS SELECT ] INDICATE SELECT AS SCOA233.DATA LE DATA_ATE
[ ~TODOS ~SELECT ] RETURN END.OF.REPORT
[ TODOS ] INDICATE SELECT AS SCOA233.DATA LE DATA_ATE
[ TODOS SELECT ] INDICATE SELECT AS SCOA233.DATA GE DATA_DE
SECTION HEADER
PRINT PAGECOUNT TO HEADER.1
SYSDATE HEADER.2 HEADER.3 HEADER.4
PRINT HEADER.3 TO HEADER.3 {FILL="0"}
PRINT HEADER.4 TO HEADER.4 {FILL="0"}
PRINT DATA_DE TO HEADER.5
PRINT DATA_ATE TO HEADER.6
OUTPUT HEADER
SECTION SUBHEADER1
FINDKEY EQ SGSA004 BY INDEX.1 FOR ;
SGSA004.IDEN EQ SCOA233.CODU
PRINT SGSA004.NOME TO SUBHEADER1.1
FINDKEY EQ FPCE BY INDEX.1 FOR ;
FPCE.CODIGO EQ SCOA233.DEPTO
PRINT FPCE.DESCRICAO TO SUBHEADER1.2
OUTPUT SUBHEADER1
SECTION BODY
PRINT SCOA233.TOT_HS_DECIMAL TO BODY.1 //***Opa! a body no imprime
SECTION SUBTOTAL1 //***ela s acumula...
SUBTOTAL BODY.1 TO SUBTOTAL1.1
RIGHT SUBTOTAL1.1 TO MINUTOS 2
LEFT SUBTOTAL1.1 TO HORAS 3
PRINT HORAS TO SUBTOTAL1.2 {FILL="0"}
MOVE (ROUND ( MINUTOS * 60 / 100)) TO SUBTOTAL1.3
PRINT SUBTOTAL1.3 TO SUBTOTAL1.3 {FILL="0"}
OUTPUT SUBTOTAL1 //***quem imprime a subtotal
SECTION TOTAL
SUBTOTAL SUBTOTAL1.1 TO TOTAL.1
RIGHT TOTAL.1 TO MINUTOS 2
LEFT TOTAL.1 TO HORAS 3
PRINT HORAS TO TOTAL.2 {FILL="0"}
MOVE (ROUND ( MINUTOS * 60 / 100)) TO TOTAL.3
PRINT TOTAL.3 TO TOTAL.3 {FILL="0"}
OUTPUT TOTAL
REPORTEND
OUTCLOSE
RETURN
EXEMPLO2 - Uma situao que voce quer imprimir varios items pra cada registro, como por exemplo pra
cada nota apacem os items que a compe no relatrio. Voce pode criar loops e subrotinas na report bem como
imprimir imagens sem ser as imagens padro da report.
EMITE_RELATORIO:
MOVE 0 TO PAGECOUNT
SECTION HEADER
SECTION BODY
MOVE 0 TO FIELDINDEX
REPEAT
UNTIL SCOLA29.VAL1& EQ 0
CLEAR SCOLA30
MOVE NOTA TO SCOLA30.NF
INDICATE SAIR FALSE
REPEAT
UNTIL [ ~FOUND]
SECTION SUBTOTAL1
SUBTOTAL BODY.5
SECTION TOTAL
SUBTOTAL SUBTOTAL1.1
OUTPUT TOTAL
OUTPUT CONFIRME
REPORTEND
FORMFEED
OUTCLOSE
RETURN
Captulo 13 - Exemplo de impresso de etiquetas
Como a impresso de etiquetas muito comum vamos dar um exemplo de impresso de etiquetas pra mala
direta de clientes em impressora de formulrio contnuo.
Formulario OK.?.(Y/N).: _
________________________________________
________________________________________
________________________________________
________________________________________
______________________________ ______________________________
_________ ______________________________ __ _________
______________________________ __
/*
#INCLUDE BIBLIOTE.INC
#INCLUDE TITULO.INC
//===Variaveis
STRING TECLA 1 CEP 9
INTEGER ETIQCORRENTE CONT CONT2
INDICATOR OK
//===Page sets
PAGE SET TELA AT 17 05 COLORS 15 143
INICIO:
PAGE TELA
REPEAT
BLANKFORM TELA
CLEAR SCOLA23
ENTERGROUP
ENDGROUP
//inicializa variaveis
MOVE 1 TO ETIQCORRENTE
MOVE 0 TO PAGEEND //pra no pular de folha no formulario
MOVE 0 TO CONT
UNTIL [ OK ]
BLANKFORM BODY
CLEAR SCOLA23
[ ~TODOS] MOVE TELA.1 TO SCOLA23.COD_CLIENTE //se apenas 1 cliente
SECTION BODY
REPORTEND
IF ETIQCORRENTE NE 1 BEGIN
OUTPUT BODY //sobrou alguma etiqueta ? - imprime
IF BODY.1& NE "" MOVE (CONT2+1) TO CONT2
END
FORMFEED
OUTCLOSE
PAUSE ""
ABORT
KEYPROC KEY.ESCAPE
ABORT
KEYPROC KEY.CLEAR
BLANKFORM TELA
RETURN INICIO
//---------------
Se fosse uma linha com 3,4 ou mais etiquetas a lgica a mesma e o uso da windowindex facilita bem.
Captulo 14 - Criando comandos
Bom j vimos muitos comandos do dataflex e agora chegou a hora de ver como criar nossos prprios
comandos. O comando pode ser definido no prprio programa, mas o melhor criar uma biblioteca, que nada
mais que um arquivo texto contendo os comandos. Depois se voce precisar daquele comando que voce
criou, voce da um include da biblioteca que deve ter extenso ".inc". Tipo nossos programas aparece #include
biblioteca.inc mas poderia ser #include sua_biblioteca.inc ou qualquer nome.
Antes de mais nada precisamos ver algumas diretivas de compilao do dataflex. Diretivas de compilao do
informaes pro DFCOMP de como o nosso programa deve ser compilado. Outra coisa legal do comando: ele
aceita vrios parmetros (9 no maximo) e pode modificar todos estes parametros.
Sintaxe do comando:
#COMMAND nome_do_comando
<COMANDOS>
#ENDCOMMAND
#IF - if de compilador
#ELSE - mesma coisa do else normal
#ENDIF - usa-se pra delimitar o bloco if de compilador
#IFDEF - se j foi definida varivel
#IFNDEF - se no foi definida a varivel
#IFSAME - se um parametro o memo que...
!0 - numero de parametros
!1 - primeiro parametro
!2 - segundo parametro
!3 - terceiro parametro
e assim por diante at !9
EXEMPLO 1 - Este comando usado pra depurar, porque mostra o conteudo de 1 a 9 variveis na tela e da
um pause
Exemplo de uso: marbreak clientes.cod_cliente valor data
#COMMAND MARBREAK
//AUTOR: MARCIO LUIZ OLIVEIRA
#ENDCOMMAND
#COMMAND CURSOR
//AUTOR: MARCIO LUIZ OLIVEIRA
GOTOXY 23 77
#IFSAME !1 OFF //se o parametro 1 igual OFF
SHOW "[?25l [.0" //sequencia de escape pra desligar o cursor
#ELSE
SHOW "[?25h [.3" //sequencia pra deixa-lo visvel
#ENDIF
GOTOXY 23 77
SHOW " "
#ENDCOMMAND
EXEMPLO 3 - Exelente comando pra formatar e desmembrar datas, seu cdigo mais complexo que os
anteriores. Lembre-se o dataflex usa internamente a data como um inteiro que o numero de dias desde
01/01/0001.
IF (LENGTH(!1)) EQ 5 ;
IF DATA_VAR LT 693975;
IF DATA_VAR GE 10958;
CALC (DATA_VAR + 693975) TO !1
IF (LENGTH(!1)) EQ 4 ;
IF DATA_VAR LT 10958 IF DATA_VAR GT 1 ;
CALC (DATA_VAR + 730500) TO !1
IF !1 NE "" ;
IF !1 LT "01/01/1900" BEGIN
SHOW ""
SHOW ""
SHOW ""
GOTOXY 21 14
SHOW "ATENCAO !! DATA NAO PODE SER INFERIOR A 01/01/1900."
GOTOXY 21 14
PAUSE ""
SHOW " "
END
IF !1 GE "01/01/1900" BEGIN
#IF !0>1
LEFT !1 TO !2 2
#IF !0>2
MID !1 TO !3 2 4
#ENDIF
#IF !0>3
RIGHT !1 TO !4 4
#ENDIF
#IF !0>4
MOVE "" TO !5
IF !3 EQ 1 APPEND !5 !2 " de Janeiro de " !4
IF !3 EQ 2 APPEND !5 !2 " de Fevereiro de " !4
IF !3 EQ 3 APPEND !5 !2 " de Marco de " !4
IF !3 EQ 4 APPEND !5 !2 " de Abril de " !4
IF !3 EQ 5 APPEND !5 !2 " de Maio de " !4
IF !3 EQ 6 APPEND !5 !2 " de Junho de " !4
IF !3 EQ 7 APPEND !5 !2 " de Julho de " !4
IF !3 EQ 8 APPEND !5 !2 " de Agosto de " !4
IF !3 EQ 9 APPEND !5 !2 " de Setembro de " !4
IF !3 EQ 10 APPEND !5 !2 " de Outubro de " !4
IF !3 EQ 11 APPEND !5 !2 " de Novembro de " !4
IF !3 EQ 12 APPEND !5 !2 " de Dezembro de " !4
#ENDIF
#ENDIF
END
#ENDCOMMAND
OBS: Voce pode chamar comandos do dataflex e tambm seus prprios comandos dentro de 1 comando seu.
Mas se um comando usa uma imagem ela obrigatoriamente tem que ser definida no programa seno d erro
de compilao. Infelizemte na verso 2.3 uma imagem no pode ser definida dentro de um comando (na 3.0 j
possivel!).
DICAS:
- Ao declarar variveis em comandos procure usar nomes pouco provveis de alguem querer usar tipo
confirma$_ok,ou $$$_num_x por exemplo.
- Crie comandos o mais independente possivel do seu programa assim eles podero facilmente ser usados em
vrios programas.
- Evite uso de comandos associados a imagems dentro dos seus comandos, prefira usar show, pause, inkey
que so comandos que no usam imagens.
- Tenha uma unica biblioteca pra todos os programadores, assim evita de existir comandos diferentes pra fazer
a mesma coisa.
- Comandos podem fazer tudo que feito no programa, como abrir arquivos usar laos e tudo mais, mas
procure cria-los apenas pra resolver coisas que se repetem frequentemente, poupando seu tempo no futuro.
Captulo 15 - Grficos em dataflex
string temp 1
chart_init
graph_value "JAN" 700
graph_value "FEV" 900
graph_value "MAR" 800
graph_value "ABR" 600
graph_value "MAI" 500
graph_value "JUN" 100
graphic on
clearscreen 0
graphic off
abort
Este programa precisa de micro ou terminal grfico pra rodar, se voce no tem terminais grficos (como na
minha empresa) ento d pra fazer grficos de uma forma mais trabalhosa (com timo resultados) usando
windowindex como no exemplo abaixo:
Este exemplo um questinrio de avaliao de clientes pra 11 perguntas onde no grfico aparece a mdia das
respostas pra cada pergunta.
/GRAFICO
AVALIACOES DE CLIENTES _.-_______________ (ANO ___. SEMESTRE _.)
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 10.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 9.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 8.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 7.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 6.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 5.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 4.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 3.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 2.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____ 1.0
____ ____ ____ ____ ____ ____ ____ ____ ____ ____ ____
(1) (2) (3) (4) (5) (6) (7) (8) (9) (10) (11)
/*
...
MOSTRA_RESULTADOS:
BLANKFORM GRAFICO
MOVE 01 TO GRAFICO.1
MOVE EMPRESA TO GRAFICO.2
MOVE ANO TO GRAFICO.3
MOVE SEMESTRE TO GRAFICO.4
LOOP
KEYPROC ON
[~RELAT ] BEGIN
PAGE GRAFICO
GOTOXY 23 72
PAUSE "<ENTER>"
END
[ RELAT ] GOSUB IMPRIME_RELATORIO
RETURN
ENCHE_COLUNA:
LOOP
(1) Sysfile - muito util deixar o primeiro arquivo de cada filelist como um sysfile, ou seja, um arquivo de
apenas um registro que contem algumas informes do sistema como nmero de sequencia de notas fiscais,
numero do usurio, etc.
(2) Arquivo temporrio - arquivo que usado por vrios relatrio pra acumular dados. Tanto seus campos
como seus indices devem ser o mais reutilizveis possivel e deve usar nome de campos genrico. Exemplo:
arquivo: phtemp
usuario number 6.0 //sempre o numero do usuario aqui
campo_ascii ascii 10
campo_date date
campo_float number 8.2
...
index.1 <1> <2> <3> <4>
index.2 <1> <3> ...
index.3 <1> ... //Todos indices quebram no campo do usurio
...
Cada relatorio abre o sysfile pega o numero do usurio e o incrementa salvando novamente no sysfile.
integer usuario
clear sysfile
find gt sysfile by recnum
move sysfile.usuario to usuario
if usuario eq 999999 move 0 to usuario
move (usuario + 1) to sysfile.usuario
saverecord sysfile
No final de um relatrio o conteudo do temporario apagado apenas dos registros do usurio que terminou
aquele relatrio. Perceba que se no hover quebra no indice por usurio, o temporrio misturar registros
gravados por diferentes aplicaes.
(3) Campo usurio do sysfile - este um campo muito util em ambientes multiusuario, que contem um
numero inteiro. Pra cada arquivo temporario a primeira quebra dos indices deve ser o usurio. Porque assim
conseguimos separar os resultados dos relatorios tanto pra consulta dos registros como pra sua deleo.
Lembre que cabe a cada aplicao limpar os registros por ela gravados. Exemplo de rotina:
Limpa_temporario:
gotoxy 20 05
showln "Limpando o temporario..."
clear phtemp
move usuario to phtemp.usuario
repeat
find gt phtemp by index.1
[ found ] indicate found as phtemp.usuario eq usuario
[ found ] delete phtemp
until [ ~found ]
return
(4) Arquivos fantasmas - cria-se com o dffile um arquivo com campos identicos ao original e na abertura
fazemos:
Exemplo:
criamos produtos e produtosfant com o mesmo .def
open "produtos" as produtos
open "produtos" as produtosfant
Isto muito til quando queremos ler o arquivo por dois indices diferentes numa mesma rotina.
(5) Estruturao da programao e hidentao do cdigo - isto bom em qualquer linguagem...
Procure separar o cdigo em gosubs:
/*
name ...
open ...
repeat
gosub seleciona_dados
gosub grava_temporario
gosub mostra_grafico
gosub imprime_relatorio
gosub limpa_temporario
loop
keyproc key.escape
abort
subrotina_quaquer:
repeat
while [ ok]
<comando>
loop
until [~found]
loop
return
subrotina_quaquer:
for cont from 1 to num
repeat
while [ ok]
<comando>
loop
until [~found]
loop
return
(6) Uso dos indicadores associados as keyprocs. Toda keyproc tem um indicador associado a ela tipo
[ key.save ], [ key.next], [ key.return ] e outros. As vezes precisamos desabilitar as keyprocs e trabalhar direto
com estes indicadores, que indicam se a tecla foi pressionada ou no, mas com a keyproc desabilitada eles no
pulam automaticamente pra rotina da keyproc. Ex:
keyproc off
repeat
<comandos>
[ key.escape ] abort
until [ key.return ]
keyproc on
(7) Criao do efeito hi-ligth, ou seja tipo uma caixa de seleo do windows ou uma list-box, com varios
items um em cada janela, e voce pressiona seta pra-cima e o hi-ligth vai pro item de cima deixando ele
"selecionado", se voce pressiona seta pra baixo volta pro item de baixo. Ele feito com windowindex e
screenmode. Se alguem quizer mando esta rotina.
Ufa! por ora acho que este tutorial vai ficar por aqui... Sei que t faltando coisas mas tenham pacincia! Vou
melhorando se surgiirem duvidas.