Você está na página 1de 31

Revista The Club Megazine - 01/2002

A utilizao, reproduo, apropriao, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criaes intelectuais em cada publicao da revista The Club so terminantemente proibidos sem autorizao escrita dos titulares dos direitos autorais.

Copyright The Club 2002

EDITORIAL

Editorial
THE CLUB
Rua Acre, 950 - Avar - SP - CEP 18.700-260 Informaes: (0xx14) 3732-3689 Suporte: (0xx14) 3733-1588 Fax: (0xx14) 3732-0987

Internet
http://www.theclub.com.br Cadastro: cadastro@theclub.com.br Suporte: suporte@theclub.com.br Informaes: info@theclub.com.br

Dvidas
Correspondncia ou fax com dvidas devem ser enviados ao - THE CLUB, indicando "Suporte".

Opinio
Se voc quer dar a sua opinio sobre o clube em geral, mande a sua correspondncia para a seo "Tire sua dvida".

Mais um ano comea. Como toda e qualquer pessoa e empresa, bem como o THE CLUB queremos comear o ano novo com o p direito. Desejamos a todos um prspero Ano Novo, que todos os projetos se realizem, e claro, que a nossa vida fique cada vez melhor, com muita sade. Como vocs j puderam notar, desde o final do ano passado ns estamos fechando acordos com vrias empresas para divulgao de informaes sobre o mundo da programao, para que voc se mantenha sempre atualizado com o mundo da informtica. E no vamos parar por aqui, continuaremos a trabalhar para lhe trazer o que h de mais novo no mundo da informtica. Caso voc tenha alguma sugesto sobre o nosso site, nossa revista e nosso atendimento por favor mande seu comentrio para ns. Ser um prazer conversar com voc. O e-mail sugestoes@theclub.com.br At o ms que vem !

Reproduo
A utilizao, reproduo, apropriao, armazenamento em banco de dados, sob qualquer forma ou meio, de textos, fotos e outras criaes intelectuais em cada publicao da Revista The Club so terminantemente proibidos sem autorizao escrita dos titulares dos direitos autorais.

Copyright The Club 2002 Impresso e acabamento:


Impressos Gril - Gril Grfica e Repr. Ind. Ltda.
Tel.: (0xx14) 3762.1345 - Fax: (0xx14) 3762.1259 Rua So Paulo, 447 - Cep 18.740-000 Taquarituba - SP Tiragem: 5.000 exemplares

Celso Jefferson Paganelli Presidente - The Club

Diretor - Presidente

Celso Jefferson M. Paganelli


Diretor Tcnico

Mauro SantAnna
Colaboradores
Mrio Camilo Bohm - Claudenir C. Andrade Anderson Haertel Rodrigues - Marcio Alexandroni
Delphi marca registrada da Borland International, as demais marcas citadas so registradas pelos seus respectivos proprietrios.

Editorial ......................................................................................... 03 Mantendo estado em pginas ASP.NET ............................................. 04 Estruturando datamarts em bases Oracle ......................................... 09 Trabalhando com eventos no Interbase ............................................ 12 Trabalhando com excees no Delphi .............................................. 17 Acessando as mensagens da Stored Procedure do SQL Server .......... 20 Automao Comercial (ECF - Emissor de Cupom Fiscal - Parte 3 ...... 21 Ferramentas de desenvolvimento para Palm .................................... 25 Dicas & Truques .............................................................................. 28

MeGAZINE

COLUNA DO SANTANNA

Mantendo estado em pginas ASP.NET


Mauro um MSDN Regional Director, consultor e instrutor da MAS Informtica (www.mas.com.br), tendo ministrado treinamentos na arquitetura .NET desde outubro de 2000 para diversas empresas, dentre as quais a prpria Microsoft. E-mail: mas_mauro@hotmail.com

Em um programa Windows, manter estado (ou valores) enquanto o usurio utiliza um formulrio algo trivial: basta armazen-los em variveis e pronto. Em uma pgina Web, a questo bem mais complicada. Nem o protocolo HTTP nem o padro HTML prevem maneiras simples e diretas de manter valores na pgina. Note que no estamos falando de armazenar estado do aplicativo, onde passamos informaes de uma pgina outra e sim de estado da pgina, onde a prpria pgina passa informaes a ela mesma, como em um formulrio que tem algum valor modificado pelo usurio. Tradicionalmente em ASP, os programadores adotam alguma das seguintes tcnicas: Geram links na pgina contendo valores que podem ser lidos na query string. uma maneira bastante complexa, pois requer modificaes na gerao de todos os links da pgina. Alm disto, a quantidade de informao que pode ser colocada na query string limitada em muitos navegadores a apenas 255 caracteres. Colocam o valor em uma varivel de sesso. Esta maneira mais simples, mas usa recursos preciosos do servidor e cria complicaes em instalaes grandes que usam vrios computadores para servir as mesmas pginas. Como podemos ver, as duas maneiras tradicionais apresentam problemas. O ASP.NET utiliza uma outra tcnica: define um campo escondido chamado __VIEWSTATE e coloca no seu valor toda a informao de estado da pgina. Esta tcnica tem vrias vantagens: Os componentes ASP.NET sabem interagir com esta varivel automaticamente, mantendo o prprio estado sem a necessidade de programao; No usa recursos do servidor, j que os valores ficam na

pgina no cliente; compatvel com qualquer navegador, j que os campos escondidos so um recurso antigo do HTML; Os limites de tamanho, se existirem, so bem maiores. No pude achar nada explcito sobre campos escondidos, mas para campos do tipo TEXT, o padro como documentado em www.w3c.org, fala em tamanho ilimitado. Os valores a serem armazenados no campo __VIEWSTATE so codificados em uma string juntamente com um checksum para detectar eventuais alteraes no contedo. Note que embora exista uma segurana adicional em relao a um campo escondido comum, no existe nenhuma segurana criptogrfica. O VIEWSTATE uma boa soluo de uso geral para armazenar estado da pgina. Existem no entanto algumas pequenas restries: Deve existir um formulrio HTML para conter o campo escondido. Como os WebForms sempre contm um formulrio, isto no um grande problema; O campo __VIEWSTATE vai e volta sempre que o usurio pede uma ao do servidor (postback). Por esta razo, caso o campo fique muito grande ele pode afetar negativamente a performance.

Ligando e desligando
O uso de VIEWSTATE comandado por propriedades EnableViewState, presente tanto no formulrio como nos componentes individuais. Caso a propriedade EnableViewState do formulrio seja desligada, nenhum componente manter estado. Pode ser interessante desligar o VIEWSTATE de componentes que so sempre inicializados quando da carga da pgina, de forma a melhorar a performance. Por exemplo, DataGrids e Tables que tem seu contedo preenchido no evento Page_Load.

MeGAZINE

COLUNA DO SANTANNA

VIEWSTATE em ao
Crie um novo projeto Web e d a ele o nome Estado:

Coloque sobre o formulrio dois TextBox, um Button e um ListBox:

MeGAZINE

COLUNA DO SANTANNA
Escreva o seguinte cdigo no evento Click do boto: private void Button1_Click(object sender, System.EventArgs e) { double N1 = Convert.ToDouble (TextBox1.Text); double N2 = Convert.ToDouble (TextBox2.Text); double R = N1 + N2; ListBox1.Items. Add(R.ToString()); } Rode o programa: (figura ao lado) No entre nada nos campos e pea para visualizar o fonte da pgina:

MeGAZINE

COLUNA DO SANTANNA

Observe o campo escondido __VIEWSTATE. O valor do campo (dDwxMTg2Mzg2MTU1Ozs+, no meu caso) pode ser um pouco diferente no seu navegador: <input type=hidden name=__VIEWSTATE value=dDwxMTg2Mzg2MTU1Ozs+ /> Agora entre nmeros no navegador: Clique o boto e veja o fonte da pgina:

MeGAZINE

COLUNA DO SANTANNA
Observe o valor do campo __VIEWSTATE: <input type=hidden name=__VIEWSTATE value=dDwxMTg2Mzg2MTU1O3Q8O2w8aTwxPjs+O2w8dDw7bDxpPDc+ Oz47bDx0PHQ8O3A8bDxpPDA +Oz47bDxwPDgwMjM1O zgwMjM1Pjs+Pjs+Ozs+Oz4+Oz4+Oz4= /> // Pega valor atual object Valor = ViewState[Contador]; // Se for null, a primeira vez if (Valor == null) // Coloca um ViewState[Contador] = 1; else { // Pega valor atual int N = (int) Valor; // Incrementa N++; // Coloca de volta ViewState[Contador] = N; } // Exibe Label1.Text = ViewState[Contador].ToString(); } No podemos colocar qualquer tipo de valor no VIEWSTATE e sim apenas os do tipo que podem ser convertidos de e para string. Uma outra alternativa usar um componente do tipo Literal, selecionar a propriedade Visible False e usar a propriedade Text para guardar o valor.

Desligando
Experimente alterar a propriedade EnableViewState do formulrio para False. Veja que o ListBox no mais mantm o valor. O campo __VIEWSTATE ainda existe, mas seu contedo no cresce. O que o __VIEWSTATE contm O campo __VIEWSTATE contm, essencialmente, os valores das propriedades que foram alterados em relao ao valor original. Elas aparecem em negrito na janela de propriedades no Visual Studio .NET. Note que as propriedades TEXT no so armazenadas no __VIEWSTATE porque o navegador consegue envi-las de volta ao servidor em um postback.

Valores do aplicativo
s vezes interessante usar o VIEWSTATE para armazenar valores do nosso programa. Uma das alternativas atravs da propriedade ViewState, que funciona como um dicionrio. Veja um exemplo que conta quantas vezes a pgina chamada em seqncia: private void Page_Load(object sender, System.EventArgs e) {

Concluso
A manuteno de estado do formulrio feita automaticamente pelos componentes ASP.NET sem que precisemos fazer nada a respeito.

MeGAZINE

ORACLE

Estruturando datamarts em bases Oracle...


Mrio Camilo Bohm - Bohm,Interal Fone (011) 4221.6151 - mario@bohminteral.com.br

Depois de tudo o que j vimos em matria de desempenho, vamos agora considerar um aspecto importante para desenvolvedores profissionais e muito atual: a criao de datamarts, bases destinadas especificamente a consulta de dados estatsticos de corporaes, que so o alicerce do conceito de business intelligence. Embora tambm possamos criar instncias Oracle especialmente configuradas para essa finalidade especfica, alm de muitos outros recursos que temos em ambiente Oracle, esse no ser o nosso foco inicial. Vamos discutir inicialmente como, dentro de bases fortemente transacionais, criar mdulos destinados fornecer dados estatsticos. A idia central bastante simples. Em bases fortemente transacionais, se montarmos nossas consultas diretamente nas tabelas originais, estaremos concorrendo com as transaes correntes e no teremos tanta flexibilidade na configurao das tabelas para atender nossa necessidade de montagem de sries histricas. Assim, fica muito mais racional separarmos as informaes necessrias em uma base especfica, seja em tabelas distintas, seja em um usurio distinto ou em um instncia Oracle distinta.

O primeiro passo
Um primeiro e importante passo definirmos quais informaes so importantes e como iremos disponibiliza-las para o usurio comum. Neste aspecto, podemos segmentar datamarts distintos para cada grande centro de informao. Por exemplo, um datamart para as informaes de faturamento da empresa, outro para as informaes de compras, outro para informaes de produo, etc. Vamos tomar como exemplo um datamart de informaes de faturamento. claro que as informaes de faturamento para consulta precisaro incluir as informaes de clientes, de produtos e da venda especfica, item a item, para que possamos ter uma base flexvel e detalhada. claro tambm que essas informaes estaro em tabelas distintas, como CLIENTES, PRODUTOS, NOTAS e NOTAS_ITENS, por exemplo. Assim, para que possamos ter todos os detalhes de cada item vendido em uma nica linha, podemos criar uma tabela que unifique todas essas informaes, o que nos dar grande ganho de desempenho nas consultas. Vamos imaginar ento que tenhamos as seguintes estruturas de tabelas:

CLIENTES Chave Nome CGC Inscricao Telefone Chave

PRODUTOS Chave Data_Emissao Chave_Cliente Tipo Valor_Total

NOTAS Chave

NOTAS_ITENS

Codigo Descricao Preco_Base

Chave_Nota Chave_Produto Preco_Venda Valor_Item

MeGAZINE

ORACLE
Para unific-las, podemos criar uma nica tabela, que contenha uma linha para cada item vendido, com o seguinte comando: DROP TABLE FATURAMENTO_1; CREATE TABLE FATURAMENTO_1 AS SELECT NOTAS_ITENS.CHAVE, NOTAS_ITENS.CHAVE_NOTA, NOTAS_ITENS.CHAVE_PRODUTO, NOTAS_ITENS.PRECO_VENDA, NOTAS_ITENS.VALOR_ITEM, NOTAS.DATA_EMISSAO, NOTAS.CHAVE_CLIENTE, NOTAS.TIPO, NOTAS.VALOR_TOTAL, PRODUTOS.CODIGO, PRODUTOS.DESCRICAO, CLIENTES.NOME, CLIENTES.CGC, CLIENTES.INSCRICAO FROM NOTAS_ITENS, NOTAS, PRODUTOS, CLIENTES WHERE (NOTAS.CHAVE = NOTAS_ITENS.CHAVE_NOTA) AND CLIENTES.CHAVE = NOTAS.CHAVE_CLIENTE) AND PRODUTOS.CHAVE = NOTAS_ITENS.CHAVE_PRODUTO); A tabela FATURAMENTO_1 ento, ficaria com a seguinte estrutura:

CAMPO CHAVE CHAVE_NOTA CHAVE_PRODUTO PRECO_VENDA VALOR_ITEM DATA_EMISSAO CHAVE_CLIENTE TIPO VALOR_TOTAL CODIGO DESCRICAO NOME CGC INSCRICAO

CONTEDO Valor contido no campo CHAVE da tabela NOTAS_ITENS Valor contido no campo CHAVE_NOTA da tabela NOTAS_ITENS Valor contido no campo CHAVE_PRODUTO da tabela NOTAS_ITENS Valor contido no campo PRECO_VENDA da tabela NOTAS_ITENS Valor contido no campo VALOR_ITEM da tabela NOTAS_ITENS Valor contido no campo DATA_EMISSAO da tabela NOTAS Valor contido no campo CHAVE_CLIENTE da tabela NOTAS Valor contido no campo TIPO da tabela NOTAS Valor contido no campo VALOR_TOTAL da tabela NOTAS Codigo do produto referenciado Descrio do produto referenciado Nome do Cliente referenciado CGC do Cliente referenciado Inscrio Estadual do Cliente referenciado

Desta forma, todas as informaes relativas a cada item vendido, estejam elas originalmente onde estiverem, ficam disponveis em nica linha. Embora essa tcnica seja condenvel sob todos os aspectos em tabelas transacionais, para a finalidade a que nos propomos a atender de grande utilidade. Qualquer campo que o usurio comum queira utilizar para segmentar anlises estar disponvel sem a necessidade da montagem de SELECTs complexos.

Note, atentamente, o universo de possibilidades que essa tcnica abre para os usurios comuns, de forma simples e descomplicada! E para tornar essa tcnica ainda mais contundente em termos de performance, podemos criar ndices para praticamente todos os campos que sejam potencialmente objetos de segmentao ou, se desejado, para todos os campos da tabela.

10

MeGAZINE

ORACLE
Embora um nmero elevado de ndices seja prejudicial performance em bases transacionais (ver matrias anteriores), neste caso esse problema deixa de existir, pois vamos atualizar a tabela de consulta em poucas ocasies e sem prejuzo base transacional. Assim, podemos criar ndices com os comandos: CREATE INDEX FAT_1_CHAVE ON FATURAMENTO_1 (CHAVE) PCTFREE 10; CREATE INDEX FAT_1_CHAVE_NOTA ON FATURAMENTO_1 (CHAVE_NOTA) PCTFREE 10; CREATE INDEX FAT_1_CHAVE_PRODUTO ON FATURAMENTO_1 (CHAVE_PRODUTO) PCTFREE 10; CREATE INDEX FAT_1_DATA_EMISSAO ON FATURAMENTO_1 (DATA_EMISSAO) PCTFREE 10; CREATE INDEX FAT_1_CHAVE_CLIENTE ON FATURAMENTO_1 (CHAVE_CLIENTE) PCTFREE 10; CREATE INDEX FAT_1_TIPO ON FATURAMENTO_1 (TIPO) PCTFREE 10; CREATE INDEX FAT_1_CODIGO ON FATURAMENTO_1 (CODIGO) PCTFREE 10; CREATE INDEX FAT_1_DESCRICAO ON FATURAMENTO_1 (DESCRICAO) PCTFREE 10; CREATE INDEX FAT_1_NOME ON FATURAMENTO_1 (NOME) PCTFREE 10; CREATE INDEX FAT_1_CGC ON FATURAMENTO_1 (CGC) PCTFREE 10; CREATE INDEX FAT_1_INSCRICAO ON FATURAMENTO_1 (INSCRICAO) PCTFREE 10;

Atualizando o Datamart
Vamos discutir, no prximo ms ento, como atualizar o datamart criado... At l!

MeGAZINE

11

INTERBASE

Trabalhando com eventos no InterBase


Por Anderson Haertel Rodrigues (AHR) administrador de bancos de dados, desenvolvedor de sistemas e componentes. Mora em Florianpolis/SC e pode ser contactado em anderson.hr@bol.com.br.

Introduo:
Evento um recurso que o banco de dados InterBase disponibiliza aos usurios. Os eventos como a prpria palavra cita, so notificaes que o Banco de Dados InterBase manda para a sua aplicao. A aplicao por sua vez resgatou o Evento enviado pelo InterBase e vai disparar e ou executar alguma rotina na aplicao. Podendo inclusive interagir com o InterBase atravs de uma execuo de Stored Procedure! Interessante No?!

Tem a funo de retornar linhas de Dados para a aplicao. Stored Procedure Executvel EXECUTE PROCEDURE NOME_SP. Tem a funo de retornar parmetros de alguma operao feita no Servidor.

Triggers:
So programas associados a reaes de atualizao da Tabela e ou View em questo. Uma Trigger no pode ser disparada pela sua aplicao como feito com a SP, trigger s disparada pelas aes de INSERT/UPDATE/DELETE. No InterBase existem dois tipos de Trigger: BEFORE; AFTER; Isto , disparado um gatilho antes do INSERT/UPDATE/ DELETE e ou disparado um gatilho aps o INSERT/UPDATE/ DELETE. Para maiores detalhes da sintaxe da criao de SPs e ou Trigger, consulte os manuais do InterBase.

Stored Procedures e Triggers:


Eventos s podem ser disparados por Stored Procedure (vulgo SP) e ou Trigger (vulgo Gatilho). Vou explicar de uma forma mais genrica o que so SPs e Triggers.

Stored Procedure:
So programas em linguagem SQL que so compilados e armazenados no Banco de Dados InterBase. Um dos principais objetivos da SP a performance, pois, a mesma executada no servidor e retorna apenas os parmetros e ou linha do ResultSet para a aplicao. Existem dois tipos de SP: SELETVEIS; EXECUTVEIS; Stored Procedure Seletvel SELECT * FROM NOME_SP.

Eventos do InterBase:
O mecanismo de envio dos eventos consiste em trs partes: A)A Trigger e ou a SP posta o evento para o gerenciador de

12

MeGAZINE

INTERBASE
eventos do InterBase; B) O evento entra em uma fila de Eventos gerenciada pelo Gerenciador de Eventos e notifica as estaes que ocorrereu um evento; C) A Aplicao/Estao registra ou no o interesse do Evento. Isto , a aplicao que toma a deciso ou no de registrar o evento. A aplicao no tem o controle de dizer ao InterBase para o mesmo no postar o evento!* *Existem dois artifcios da aplicao para dizer ao InterBase que no deseja receber tal evento. O 1o de no registrar o evento e ser explicado mais adiante, o 2o s funciona com SP, onde voc pode passar um parmetro para a Stored Procedure indicando que no deseja que o InterBase poste tal evento! POST_EVENT <nome_do_evento>; Este comando responsvel por notificar as estaes que ocorreu um evento no Banco de Dados. O nome_do_evento Case-Sensitive, isto , se voc declarou um evento com o nome de: POST_EVENT Incluso_Cliente; A sua aplicao tem que fazer referncia ao nome exatamente como est descrito no POST_EVENT. At a verso 6.0 do InterBase e o FireBird, o tamanho mximo do nome do evento de 64 caracteres. Vejamos um exemplo de utilizao do POST_EVENT dentro de uma Stored Procedure. Nota: No Banco de Dados de Exemplo que acompanha o FireBird/InterBase 6, existe um evento declarado na tabela SALES para a Trigger AFTER INSERT. Como mostra a nossa tela: O evento tem o nome de: new_order e POST_NEW_ORDER o nome da Trigger. Para nosso artigo, irei mostrar como usar em uma SP o recurso de Eventos do InterBase. Criei um Banco de Dados InterBase com o seguinte nome: EVENTOS.GDB Neste Banco de Dados InterBase, eu criei uma SP com o seguinte nome: EVENTOSDEMO, e na declarao da SP iremos encontrar o seguinte cdigo SQL: SET TERM ^; CREATE PROCEDURE EVENTOSDEMO (EVENTO VARCHAR(64)) AS BEGIN POST_EVENT :evento; END^ SET TERM^; Ok! Nosso Banco de Dados de Eventos foi criado e nele vamos encontrar a nossa SP que ser responsvel em disparar o evento! Vamos criar nossa aplicao Demo de Eventos no Delphi. Abra o Delphi, e inicie uma nova aplicao. Nosso projeto se chamar: EventosIB. Para o nosso projeto, eu utilizei os componentes da ABA InterBase do Delphi, estes componentes so chamados de InterBase Express (vulgo IBX), a verso do IBX

Figura 1: A declarao do Evento na Tabela SALES

MeGAZINE

13

INTERBASE
usada neste exemplo : 6.02, mas, deve funcionar com uma verso menor. Caso queira atualizar o seu IBX, v at o seguinte site da Internet: http://codecentral.borland.com/codecentral/ccweb.exe/ author?authorid=102 Vamos adicionar ao nosso projeto um DataModule DM que ter os seguintes componentes: -IBDataBase com a propriedade Name= IBDatabaseEventos; -IBTransaction com a propriedade Name= IBTransactionEventos; -IBStoredProc com a propriedade Name= StoredProcEventos; IBEvents com a propriedade Name= IBEventoAlerta; Ok. J temos a interface do nosso projeto pronta! Voltamos ao DataModule, vamos indicar ao IBDataBase onde est o nosso EVENTOS.GDB. Duplo clique no componente IBDataBase e ir abri o DataBase Editor conforme figura 4:

Figura 2: O DataModule da Aplicao. Temos tambm no nosso projeto um formulrio com o nome uEvento que contm os seguintes componentes: - Dois TGroupBox; - Um TLabel - Um TEdit; - Um TButton; - Um TListBox;

Figura 4: DataBase Editor do Componente IBDataBase. Em Connection, escolha a opo Local, em DataBase especifique o caminho onde se encontra o seu EVENTOS.GDB, ex: D:\Anderson\MeusArtigos\IB\Eventos\AplicativoDelphi\EVENTOS.GDB User Name coloque SYSDBA, Password=masterkey, SQL_Role deixe em branco, Character Set=None, e desmarque a opo Login Prompt. Ok. Temos a nossa tela 4 e j criamos a nossa conexo com o Banco de Dados EVENTOS.GDB. No DataModule ainda, no IBDataBase indique na propriedade DefaultTransaction o nosso IBTransaction, no IBTransaction na propriedade DefaultDataBase indique o nosso IBDataBase, no IBStoredProc na propriedade DataBase indique o nosso IBDataBase e em Transaction indique o nosso IBTransaction, no IBEvent indique na propriedade DataBase nosso IBDataBase! Ufa! Pronto, criamos a nossa conexo! Se tudo estiver certo, faa o nosso IBDataBase se conectar com o

Figura 3: O Formulrio da Aplicao

14

MeGAZINE

INTERBASE
Banco atravs da propriedade Connected, logo aps, no esquea de retornar para False novamente! end; end; no cdigo mostrado acima que a nossa estao registra os eventos que ela pode receber. A mgica est nos mtodos UnregisterEvents e RegisterEvents, onde, cada um responsvel pela ao de registrar os eventos e de no registrar/aceitar os eventos! Ainda no DataModule, precisamos programar mais dois eventos: O OnDestroy do DataModule e o OnEventAlert do IBEvents: procedure TDMEventos.DataModuleDestroy(Sender: TObject); begin if IBDatabaseEventos.Connected then begin { Se a transao est aberta, precisamos fechla} if IBTransactionEventos.InTransaction then IBTransactionEventos.Commit; { Se existe o registro de eventos, precisamos desalocar estes recursos} if IBEventoAlerta.Registered then IBEventoAlerta.UnRegisterEvents; { Fecha a conexo com o Banco de Dados} IBDatabaseEventos.Close; end; end; O cdigo j est comentado, desta forma, acredito que no preciso explicar o mesmo! procedure TDMEventos.IBEventoAlertaEventAlert(Sender: TObject;EventName: string; EventCount: Longint; var CancelAlerts: Boolean); begin { Adiciona a linha com os nomes do eventos que foram disparados pelo Boto Gerar o Evento do Formulrio} frmEventos.LstBxRecebidos.Items.Add(EventName); end; Veja que o DataModule e o Formulrio esto ligados entre si atravs da clasula uses da implementation de cada um! Finalizamos a programao do nosso DataModule. Vamos agora programar o nosso formulrio. Nosso formulrio tem apenas um evento, o evento OnClick do boto Gerar o Evento.

Arquivo de Configurao para receber os eventos


Como foi explicado mais acima no artigo, o InterBase dispara o evento e a sua aplicao que a responsvel em decidir se ir ou no registrar o evento disparado pelo Banco. A sada para este caso, termos um arquivo texto para cada estao indicando quais os eventos do Banco de Dados cada estao pode e vai receber*. No nosso exemplo, junto com o executvel existe um arquivo chamado EventosEstacao.cfg e neste arquivo texto existe o nome de cada evento cadastrado no Banco de Dados que a estao vai registrar! Segue um exemplo de como est no nosso exemplo:

Figura 5: Nosso arquivo de Configurao para cada estao. Ok. Vamos agora para a parte de codificao do projeto. No ovento OnCreate do nosso DataModule coloque o seguinte cdigo: procedure TDMEventos.DataModuleCreate(Sender: TObject); var ArqEventos: TStrings; begin IBDatabaseEventos.Open; ArqEventos := TStringList.Create; try { Abre o arquivo de configurao dos registros.} ArqEventos.LoadFromFile(EventosEstacao.cfg); with DMEventos.IBEventoAlerta do begin UnregisterEvents; Events.Text := ArqEventos.Text; { Registra os eventos! } RegisterEvents; end; finally ArqEventos.Free;

MeGAZINE

15

INTERBASE
Veja o cdigo: procedure TfrmEventos.btnGerarEventoClick(Sender: TObject); begin with DMEventos do begin {Iniciamos a transao.} IBTransactionEventos.StartTransaction; StoredProcEventos.Prepare; { O nome do evento digitado no TEdit.} StoredProcEventos.Params[0].AsString := EdtEvento.Text; StoredProcEventos.ExecProc; { Fechamos a transao.} IBTransactionEventos.Commit; end; end; Nosso cdigo simples e j est comentado! Mas, vou citar que se voc digitar um nome de evento que no exista no arquivo de configurao, no ser adicionado nada no nosso ListBox, por que o mesmo no foi registrado no arquivo de configurao, mas, ele foi gerado pelo InterBase e est na fila de eventos registrados pelo Banco InterBase! Vale mencionar novamente, que os nomes de Eventos so Case-Sensitive, ento se voc digitar algum caracter, o mesmo no ser adicionado ao nosso ListBox! A nossa tela com os trs eventos registrados, disparados e resgatados pela aplicao: (figura 6) Alguns mtodos disponveis em nosso IBEvents; tem a mesma funo do mtodo RegisterEvents.

Eventos :
OnEventAlert: Ocorre quando algum evento recebido pelo Objeto. OnError: Ocorre quando houver algum erro na captura do Evento.

Principais Mtodos:
QueueEvents: Indica a sua aplicao, que foi inicializada o recebimento de eventos. RegisterEvents: Registra ao IBDataBase, os eventos listados em IBEvents. UnRegisterEvents: Diz ao Banco de InterBase, que est retirando os registros do IBEvents.

Concluso:
Eventos um poderoso recurso que o Banco de Dados InterBase nos oferece, podemos atravs dele saber quando houve um mudana em uma Tabela do Banco de Dados. Com os eventos, podemos resolver o problema** de refresh de nossas estaes em relao a tabela do Banco de Dados, onde, podemos programar o evento para o mesmo fechar a nossa tabela e abrir novamente, sendo assim, temos exatamente em nossa tela o novo registro includo/alterado e se for o caso deletado por outra estao! Este exemplo est disponvel para download na pgina do The Club no endereo www.theclub.com.br/revistas/eventosib.zip *Nota1: Foi citado que a nica sada para a configurao dos eventos em cada estao, termos um arquivo de configurao para cada estao! Citei est forma por ser a mais fcil e rpida de ser feita, mas, acredito que a melhor maneira para resolver este problema de cada estao ter o seu arquivo o mesmo arquivo de configurao apenas no servidor. Mas, a estrutura do arquivo de configurao mudaria, e neste caso podemos usar a mesma estrutura de um arquivo .INI, onde o cabealho de cada seo pode ser o nome da estao e ou o IP da mquina. Podemos ento acessar cada seo atravs da classe do Delphi TIniFile que est declarada na unit IniFiles! **Nota2: Foi citado tambm um problema de refresh entre estaes, para as estaes enxergarem o que as outras esto fazendo, necessrio no seu aplicativo que a transao em questo esteja com a opo ReadCommited, isto , enxergar as mudanas das estaes em relao ao estado atual do seu Banco de Dados. Sucesso a todos,

Propriedades:
AutoRegister: Registra automaticamente os eventos cadastros em Events quando houver a conexo com o Banco de Dados InterBase. Events: Nome dos eventos cadastrados no Banco de Dados. Registered: Indica que IBEvents registrou todos os eventos, Figura 6: A nossa aplicao final com os eventos registrados e resgatados.

16

MeGAZINE

DELPHI

Trabalhando com excees no Delphi


Este artigo ir lhe mostrar um pouco sobre a estrutura de excees no Delphi.

Utilizando excees
Existem dois tipos de excees: try...finally e try...except. Normalmente ns utilizamos o try...finally para tratar recursos e o try...except para tratar erros dentro de um bloco de cdigo. Os cdigos abaixo mostram a utilizao destes dois tipos de excees, veja: procedure TForm1.Button1Click(Sender: TObject); var Strings: TStringList; begin Strings := TStringList.Create; try Strings.Add(Suporte tcnico do The Club); Strings.SaveToFile(ChangeFileExt(ParamStr(0), .txt)); finally Strings.Free; end; end; Exemplo 1 Utilizando o try finally procedure TForm1.Button2Click(Sender: TObject); var Strings: TStringList; begin Strings := TStringList.Create; try Strings.Add(Suporte tcnico do The Club); try Strings.SaveToFile(ChangeFileExt(ParamStr(0), .txt));

except on E: Exception do begin ShowMessage(A informao no pode ser salva :#13#10 + Strings.Text); end; end; finally Strings.Free; end; end; Exemplo 2 Utilizando o try except e o try finally O primeiro exemplo mostra uma forma simples de utilizao do try...finally. Ns criamos um objeto TStringList, e como ns adquirimos um recurso ( memria, neste caso), ns queremos ter certeza que ele ser liberado. Existem muitas coisas que poderiam falhar no resto do cdigo, talvez no exista memria suficiente para criar uma nova string, ou ns no temos permisso para escrever um novo arquivo, ou tenhamos excedido a cota do disco, etc. Ns no sabemos todas as possveis causas de falha, mas ns queremos que a memria seja liberada. O bloco try...finally nos d esta possibilidade. O segundo exemplo nos mostra um exemplo simples do bloco try...except. Ns no podemos salvar a string para um arquivo, ento ns alteramos o seu comportamento e mostramos a string para o usurio. Note que o bloco try...except est dentro do bloco try...finally, neste caso ns ainda queremos que a memria seja liberada.

Excesses excepcionais
Voc ver agora alguns outros exemplos de cdigo, que

MeGAZINE

17

DELPHI
mostra alguns usos interessantes de excees. Result := TWhatever.Create; try InitializeWhatever; except Result.Free; raise; end; end; Cada classe tem um constructor, o qual usado para criar instncias daquela classe. O constructor chamado na prpria classe e no no objeto, para o qual a razo de escrevemos o seguinte: Strings := TStringList.Create; e no Strings := Strings.Create; ou Quando ns chamamos um construtor, ns estamos assegurando que qualquer um que o chame receba um objeto vlido, ou se a chamada falhar os recursos sejam liberados. Isto porque ns podemos colocar um constructor diretamente antes de um bloco try...finally; se o constructor apresentar uma exceo, no existir nada para liberar. Ns devemos manter a mesma semntica para CreateStringsFromFile. Se ns apresentarmos uma exceo, ns queremos certificar-se de que no h nada a se liberar. Se ns retornarmos corretamente, a seguir ns temos um objeto vlido. Neste caso, ns completamos este cdigo utilizando um bloco try...except. Primeiro ns criamos um objeto, se ele falhar, ns no apontamos a exceo. Se ns recebermos a memria com sucesso, ento ns iremos ler o contedo do arquivo. Aqui existem milhes de coisas que poderiam dar errado se uma exceo for lanada, ns liberaremos a memria que foi alocada (porque no foi retornado um objeto vlido) neste caso nosso chamador pode trat-lo inteligentemente, como por exemplo sugerir ao usurio um outro arquivo ou tentar novamente. Criando uma rotina genrica Tentando entender tudo isto, lembre desta pequena regra: para rotinas que criam e retornam um objeto inicializado, tenha certeza de colocar todo o cdigo dentro do bloco try...except. function CreateWhatever: TWhatever; begin Strings.Create; O mtodo Free muito especial: Se voc cham-lo em uma instncia para a qual esteja configurado para nil, ele no ir gerar uma exceo. Portanto o cdigo seguinte absolutamente correto. Strings := nil; Strings.Free; Isto algo importante para recordar ao ler a prxima seo: Neste exemplo vamos demonstrar como proteger muitos objetos com blocos aninhados de excees, e como fazer a mesma coisa em um bloco try...except. procedure TForm1.Button5Click(Sender: TObject); var Strings1: TStringList; Strings2: TStringList; Strings3: TStringList; begin Strings1 := TStringList.Create; try Strings2 := TStringList.Create; try Strings3 := TStringList.Create; try

Criao de rotinas
function CreateStringsFromFile(const FileName: string): TStringList; begin Result := TStringList.Create; try Result.LoadFromFile(FileName); except Result.Free; raise; end; end; Este primeiro exemplo cria um TStringList, carregado com o contedo do arquivo. Esta rotina tem a inteno de ser uma substituio para TStringList.Create. Isto porque, ns queremos certificar que mantemos a mesma semntica de alocamento.

18

MeGAZINE

DELPHI
Strings1.Add(Hello, world!); Strings1.SaveToFile(ChangeFileExt(ParamStr(0), .txt)); { This will raise an exception, but all resources will be freed correctly. } Strings2.Delete(51); finally Strings3.Free; end; finally Strings2.Free; end; finally Strings1.Free; end; end; procedure TForm1.Button4Click(Sender: TObject); var Strings1: TStringList; Strings2: TStringList; Strings3: TStringList; begin Strings2 := nil; Strings3 := nil; Strings1 := TStringList.Create; try Strings2 := TStringList.Create; Strings3 := TStringList.Create; Strings1.Add(Hello, world!); Strings1.SaveToFile(ChangeFileExt(ParamStr(0), .txt)); { This will raise an exception, but all resources will be freed correctly. } Strings2.Delete(51); finally Strings1.Free; Strings2.Free; Strings3.Free; end; end; Como voc pode ver, o segundo exemplo mais curto e claro. De qualquer forma ns temos que ter certeza que podemos processar o bloco finally corretamente se ele executado antes de todos os objetos serem criados. Ento ns temos certeza que todos os ponteiros esto determinando o mesmo valor (o compilador ir gerar um aviso se voc no fizer desta maneira). Lembre que uma chamada para Free no far nada se o objeto tiver o valor nil, assim seguro cham-lo mesmo se o objeto no foi construdo. O prximo exemplo mostrar a voc como liberar recursos antes de esperar o bloco finally executar. procedure TForm1.Button4Click(Sender: TObject); var Strings1: TStringList; Strings2: TStringList; begin Strings2 := nil; Strings1 := TStringList.Create; try Strings2 := TStringList.Create; Strings1.Add(Hello, world!); Strings1.SaveToFile(ChangeFileExt(ParamStr(0), .txt)); FreeAndNil(Strings1); { This will raise an exception, but all resources will be freed correctly. } Strings2.Delete(51); finally Strings1.Free; Strings2.Free; end; end; Suponha que Strings1 estava usando muitos recursos e ns no necessitamos mant-lo at que o bloco estivesse finalmente executado. Ns podemos liber-lo no meio do cdigo protegido, mas ns precisamos ter certeza que a varivel est configurada para nil por outro lado, o programa ir gerar um access violation quando tentar liberar o objeto duas vezes. FreeAndNil, para usurios do Delphi 5 ou superior, executam exatamente esta funo. Usurios de verses mais antigas do Delphi podem escrever sua prpria rotina ou simplesmente o seguinte cdigo: Strings1.Free; Strings1 := nil;

Concluso
Bem, isto apenas um comeo para que voc possa usar excees. A utilizao correta de excees far com que seu programa seja mais amigvel, muito mais estvel, muito mais profissional.

MeGAZINE

19

SQL

Acessando as mensagens da Stored Procedure do SQL Server.


Muitos usurios esto querendo usar o comando PRINT, mas no esto conseguindo. Isto porque o BDE no suporta este comando. O BDE suporta apenas o RAISERROR. Mas para quem utiliza o ADO isto no problema. O ADO considera as mensagens enviadas pelo comando PRINT como nvel de segurana 0 - demasiadamente baixo para chamar uma exceo atravs do RAISERROR - mas com isso as mensagens so escritas na lista de erros do ADO, que no Delphi, uma propriedade do componente TADOConnection. Um outro fato digno de apontamento que as mensagens so colocadas na lista de erros se o comando do ADO for executado com a opo eoExecuteNoRecords ajustada para TRUE. Como ns recuperamos esta mensagem na prtica? Veja um exemplo de Stored Procedure: CREATE PROCEDURE [SP_TESTE] @Parametro varchar(30) AS if (@Parametro = MOSTRA_CLIENTES) select * from clientes else BEGIN print Parametro invlido: + @Parametro RETURN 1 END GO Como voc pode ver esta Stored Procedure retornar um resultado se o parmetro de entrada for MOSTRA_CLIENTES, se no ele exibir a mensagem Parametro invlido e retornar um cdigo de retorno. Como vamos tratar isto no Delphi ? Se ns usarmos apenas um componente TADODataSet, ns arriscamos receber uma exceo quando um resultado no retornado pela Stored Procedure. Neste caso ento melhor usar um componente TADOCommand e um TADODataSet. O mtodo EXECUTE de um TADOCommand pode retornar um objeto RecordSet, para que ns possamos atribuir propriedade RecordSet do TADODataSet. Se a Stored Procedure no retornar um resultado, o RecordSet ser retornado, mas em um estado fechado, para o qual ns possamos testar. A seguir voc pode ver um exemplo simples que nos permite ver a utilizao do comando PRINT. Para testarmos este exemplo voc deve incluir no seu form os seguintes componentes: 01 componente ADOConnection que ir acessar o banco de dados, 01 componente ADOCommand que ir acessar a stored procedure, 01 componente ADODataSet que ir acessar os dados, 01 componente Edit para digitar o opo desejada, 01 componente Button para digitar o cdigo abaixo. Voc deve tambm incluir a unit ADOInt na clausula uses. procedure TForm1.Button1Click(Sender: TObject); var Retorno : Integer; i : Integer; RecordSet : _RecordSet; begin ADOCommand1.Prepared := True; ADOCommand1.Parameters.ParamByName(@Parametro).Value := Edit1.Text; RecordSet := ADOCommand1.Execute; if RecordSet.State = adStateOpen then begin ADODataSet1.Recordset := RecordSet; ADODataSet1.Open; end else begin ADOCommand1.ExecuteOptions := [eoExecuteNoRecords]; ADOCommand1.Execute; Retorno := ADOCommand1.Parameters.ParamByName(@RETURN_VALUE).Value; for i := 0 to ADOConnection1.Errors.Count - 1 do begin ShowMessage( Format(A Stored Procedure %s falhou com o cdigo de retorno %d e a mensagem %s, [ADOCommand1.CommandText,Retorno,TrimRight (ADOConnection1.Errors[i].Description)]) ); end; end; end; Como j foi mencionado, quando ns executamos a procedure pela primeira vez, ns estamos esperando que um resultado seja retornado. Isto significar que a lista de erros no estar preenchida. Se o resultado configurado no for retornado, ns devemos executar a procedure uma segunda vez com a opo eoExecuteNoRecords. As stored procedures do SQL Server utilizam alguns caminhos para se comunicar com o usurio. Um destes caminhos o comando PRINT. Este comando utilizado para mostrar mensagens a nvel de informao. Se voc necessitar mostrar uma exceo por exemplo aconselhvel que voc utilize o comando RAISERROR.

Concluso

20

MeGAZINE

DELPHI

Automao Comercial
(ECF Emissor Cupom Fiscal)

TEF Transferncia Eletrnica de Fundos Parte 3 (Parte Final)


Por Claudenir C. Andrade claudenir@bematech.com.br Analista de Sistemas para Automao Comercial
At aqui estudamos sobre como enviar comandos para o ECF utilizando a BemaFI32.dll, que desenvolvemos na Bematech. Esperamos que voc tenha se capacitado com este pequeno curso para construir aplicativos de automao comercial tirando o mximo de proveito das dicas que aqui publicamos. Este caminho das pedras termina no TEF, to falado e misterioso TEF. Ento vamos l!! Segundo o convnio ICMS (anexo regulamentao principal da lei de 1994 que legisla o uso do ECF) agora obrigatrio que o TEF (Transferncia Eletrnica de Fundos) seja realizada pelo ECF. - Como assim? - Bem, hoje quando nos dirigimos a qualquer estabelecimento comercial que aceite como forma de pagamento carto de crdito (Visa, Amex, Credicard, etc.) ou carto de dbito (Bancos, Debito Automtico, RedShop, Cheque Eletrnico, etc.) o pagamento de nossa compra com o carto considerado um TEF, ou Transao Eletrnica de Fundos, e quem realiza esta operao so aquelas impressorinhas que ficam espalhadas pelo balco de atendimento, que muitas vezes para atender todas as bandeiras de carto o comerciante obrigado a amontoar no balco cinco ou seis impressoras com seus teclados ou Pin Pads. Muito bem, o uso destas impressoras, para todo estabelecimento obrigado a utilizar um ECF, est proibida!!! A impresso do comprovante de pagamento em carto deve ser emitida no ECF, isso mesmo, no ECF!!! - Aqui vale um comentrio: - No confunda o cupom fiscal com o comprovante de compra em carto. O cupom fiscal registra a compra fiscalmente, contabilizando o ICMS ou ISS devido pelo estabelecimento comercial. O comprovante de compra em carto registra que sua compra foi autorizada pela administradora e que o valor que consta neste recibo o valor que ser cobrado em sua fatura de carto ou o dbito que ser realizado em sua conta-corrente. Ento j que o uso das maquininhas est proibido e necessitamos efetuar a operao atravs do ECF como preparar o meu programa para que o mesmo possa realizar o TEF?

TEF Primeiros Passos


Existem hoje duas maneiras de se realizar o TEF. De forma discada ou dedicada. A tabela1 indica a diferena entre elas. O TEF atravs da linha discada mais lento que a linha dedicada, observe que colocamos lento entre aspas porque quando voc decidir que tipo de TEF colocar ou indicar para seu cliente dever levar em considerao o tempo mdio de emisso de cupom fiscal e o nmero de vendas que so realizadas em carto. Exemplo: Um supermercado obviamente optaria por colocar uma

MeGAZINE

21

DELPHI
ou mais linhas dedicadas, pois discar e efetuar uma conexo normal por modem (como o processo discado) invivel para um supermercado de mdio porte onde a velocidade um fator crtico e as compras com carto so constantes, ou seja, o tempo mdio de emisso chega a 10 cupons a cada 15 minutos. J em um mini-mercado ou material de construo a emisso de 10 cupons (10 clientes) leva at 50 minutos, pois a rotatividade baixa e o nmero de clientes que paga em carto tambm baixa, talvez pela localizao e o perfil dos consumidores da regio. Agora quando falamos em um estabelecimento com 3 PDVs deve ser analisado o custo-beneficio da colocao de um TEF discado ou dedicado. Se a combinao Tempo Mdio de Emisso e Velocidade para este perfil de cliente um fator crtico, sem dvida o dedicado ser a melhor soluo. Vamos falar sobre o TEF discado onde cada PDV ter um Modem no computador para que possa efetuar a transao TEF da compra realizada em carto. Alm de decidir qual TEF colocar, tambm necessrio para TEF discado baixar um GP, Gerenciador Padro, programa fornecido pelas bandeiras em parcerias com empresas homologadoras e certificadoras como a Software Express e a SevenPDV. - Certificadoras? Isso mesmo!!! Calma, isso no significa que a Software Express, empresa autorizada pelas bandeiras a certificarem o uso do GP , estaro aprovando ou no sua aplicao de automao comercial. O objetivo deles certificar que seu aplicativo est Falando de maneira correta como o GP e realizando as operaes de acordo com o que indicado no Roteiro de Homologao e exigido pelas bandeiras (este roteiro e o GP podem ser obtidos atravs o e-mail suporte@softwareexpress.com.br )

Fluxograma de Funcionamento
O Gerenciador Padro um aplicativo Win32 que em sua execuo ficar na zona de TaskService (ao lado do relgio do windows onde ficam todas as aplicaes residentes que podem sofrer interveno direta do usurio) e fica buscando arquivos em um diretrio especfico. Existe um GP para cada modalidade de transao. Na modalidade carto de crdito existe o TEF_DIAL.exe e para a modalidade carto de dbito e cheque eletrnico existe o TEF_DISC.exe. Ambos buscam arquivos em diretrios respectivos, C:\TEF_DISC ou C:\TEF_DIAL, que devem ser criados dentro de um padro. Toda a transao realizada atravs de arquivos texto. Esses arquivos contm o texto que deve ser impresso no ECF. Exatamente o que impresso nas maquininhas antigas devolvido agora em arquivo para que sua aplicao manipule e imprima isso no ECF. Graficamente este o funcionamento do GP e o TEF com impressoras Bematech:

22

MeGAZINE

DELPHI
Tabela 1 - Tipos de TEF TEF Discado - O software aplicativo de automao comercial, dever certificar que o computador em que o software foi instalado tenha um modem e uma linha telefnica aonde ser necessria uma "discagem", seja atravs de ramal ou no, para que a transao seja autorizada e realizada - Nesta modalidade necessrio que cada computador em que a aplicao de automao comercial instalada tenha um Modem. TEF Dedicado - Os PDVs ou computadores em que o aplicativo de automao comercial estiver instalado no necessita possuir um Modem e sim uma rede - ponto a ponto ou qualquer outro tipo de rede - para que possa se comunicar com o servidor que possuir uma placa modem e uma linha dedicada ( ou LP, linha privativa) aonde estar a qualquer momento preparada para efetuar a transao e vrias delas caso necessrio.
artigos anteriores da revista The Club indicamos que necessrio para utilizar nossa dll) caso voc no tenha este modulo poder baixar em nosso site - www.bematech.com.br Mude o nome de seu form para TEFBEMATECH, e salve o projeto como TEFDELPHIBEMATECH. Adicione 2 botes, altere as propriedades destes botes para: Button1 - Name e Caption = Button2 - Name e Caption = CupomTef CupomTefResumido

OBS: Vamos analisar duas maneiras de fazer o TEF, uma delas com vrias formas de pagamento entre elas o carto, a outra quando o carto a nica forma de pagamento, facilitando ainda mais nossa vida. Passo 2: Adicione o seguinte trecho de cdigo ao Boto CupomTEF Em Azul esto as funes especficas do TEF. iRetorno := Bematech_FI_AbreCupom (Pchar(12345678)); iRetorno := Bematech_FI_VendeItem Pchar(1234), Pchar(teste), Pchar(FF), Pchar(I), Pchar(10), Pchar(2), Pchar(0,50), Pchar($), Pchar(0)); iRetorno := Bematech_FI_VendeItem Pchar(1234), Pchar(teste), Pchar(FF), Pchar(I), Pchar(10), Pchar(2), Pchar(1,50), Pchar($), Pchar(0)); iRetorno := Bematech_FI_IniciaFechamentoCupom (Pchar(A), Pchar($), Pchar(0); iRetorno := Bematech_FI_EfetuaFormaPagamento (Pchar(Dinheiro), Pchar(5,00)); iRetorno := Bematech_FI_EfetuaFormaPagamento (Pchar(Cheque), Pchar(5,00)); iRetorno := Bematech_FI_EfetuaFormaPagamento (Pchar(Cartao Xyz), Pchar(10,00)); iRetorno := Bematech_FITEF_VendaCartao (Pchar(1), Pchar(10,00)); iRetorno := Bematech_FI_TerminaFechamentoCupom (Pchar(Obrigado Volte Sempre!!)); iRetorno := Bematech_FITEF_ImprimeTEF (Pchar(1), Pchar( Cartao Xyz), (Pchar(10,00)); showmessage(Confirmar Venda);

Atalho Dll de Comunicao Bemafi32.dll !!!


Conforme estamos destacando desde o comeo do curso, a dll de comunicao casada com a plataforma de desenvolvimento Borland Dephi funcionam de forma perfeita e sem problemas de incompatibilidades ou truques. Adicionamos no ms de Outubro de 2001 funes de TEF na BemaFi32.dll . - Porque? - Bem, para voc deixar sua aplicao OK com o gerenciador padro e fazendo TEF de forma esperada pelo roteiro de homologao, voc tem de conhecer muito bem a impressora Bematech e o uso dos drivers. O arquivo de comunicao deve ser criado dentro do padro esperado no roteiro. Por exemplo: o arquivo de resposta deve ser recebido e trabalhado antes da impresso, so efetuados na certificao testes de desligar a impressora, desligar o micro, cancelar a impresso do no-fiscal vinculado e imprimir novamente no relatrio gerencial. Toda esta Regra de Negcio do TEF colocamos dentro de funes inteligentes em nossa dll, que basicamente se resume em trs. Vamos analis-las. Passo 1 Crie um projeto no Delphi e Cole a este projeto as Declaraes das funes de nossa dll de alto nvel (que a dois

MeGAZINE

23

DELPHI
iRetorno := Bematech_FITEF_ConfirmaVenda (Pchar(1), Pchar(10,00), Pchar(CNF)); showmessage(Venda Confirmada); Todo controle de impressora desligada e mensagem automtica de venda realizada controlado pela dll. Experimente desligar a impressora no meio da impresso do TEF e ver o resultado. Deixe a dll trabalhar por voc, no reinvente a roda!!! Passo 3: Adicione o seguinte trecho de cdigo ao Boto CupomTEFResumido Em Azul esto as funes especficas do TEF Com este cdigo abaixo conseguimos o mesmo resultado caso nosso cliente esteja pagando toda a compra com o Carto de Crdito. iRetorno := Bematech_FI_AbreCupom (Pchar(12345678)); iRetorno := Bematech_FI_VendeItem (Pchar(123456), Pchar(Teste de Descrio), Pchar(FF), Pchar(I), Pchar(1), Pchar(2), Pchar(10,00), Pchar(%), Pchar(0)); iRetorno := Bematech_FITEF_FechaCupomComTEF (Pchar(Cartao Amex), Pchar(10,00), Pchar(Obrigado Volte Sempre), Pchar(1)); iRetorno := Bematech_FITEF_ConfirmaVenda (Pchar(1), Pchar(10,00), Pchar(CNF)); showmessage(Venda Confirmada);

Explicando o Cdigo:
Declaramos uma varivel do tipo string na qual, caso necessrio o uso desta varivel, armazenamos 100 espaos para passar como referncia da funo Bematech_FI_NumeroCupom. Depois montamos um cupom fiscal, com a venda de dois itens, um de 15,00 reais e outro de 10,00 reais. Efetuamos o fechamento do cupom fiscal de forma detalhada (dizemos detalhada porque possvel utilizar a funo FechaCupomResumido, com nica forma de pagamento) pois nosso cliente est utilizando vrias formas de pagamento, est pagando uma parte em dinheiro, outra cheque e a maior parte em carto com o valor de 10,00 reais, que o que nos interessa. Logo aps iniciamos a operao TEF com a funo Bematech_FITEF_VendaCarto. Como parmetro esta funo necessita de um ID para cada operao a carto realizada, este ID dever ser contabilizado por seu software, e os outros parmetros so a forma de pagamento do cupom e o valor. Esta funo ir criar o arquivo texto de comunicao com o GP, copiar este arquivo para o diretrio do GP e ficar monitorando o arquivo de resposta do GP. A partir da o GP abre na tela de seu computador para que voc escolha a bandeira de carto e ele ser o responsvel por discar e efetuar a comunicao com o Modem, etc.. Depois da comunicao realizada o GP sai de cena e volta para a tela de seu aplicativo onde a seguinte linha com a funo Bematech_FI_TerminaFechamentoCupom executada, ou seja, encerramos o cupom fiscal. Aps encerrar o cupom fiscal necessrio imprimir o comprovante de compra do carto, tudo isso a dll faz para voc . Chamamos a funo iRetorno: = Bematech_FITEF_ImprimeTEF(1, Cartao Xyz, 10,00) e logo aps a rotina para confirmar a venda ou no. Fcil!!! Com apenas 3 funes da BemaFi32.dll voc deixa seu aplicativo falando com o GP, realizando TEF e imprimindo isso no ECF .

Explicando o Cdigo
Observe que a FechaCupomComTEF j realiza todas as operaes para voc: inicia o GP, envia o arquivo de comando, recebe o arquivo de resposta, fecha o cupom fiscal e imprime no ECF o comprovante de compra do carto.

Finalizando!!!
Bem, terminamos aqui nosso curso de ECF, espero que todos tenham tirado proveito das dicas aqui oferecidas, agradeo ao THE CLUB pela oportunidade de levar estes esclarecimentos a meus companheiros escovadores de Bits e coloco a disposio meu e-mail e o e-mail de nosso suporte para qualquer dvida, Um Abrao a Todos!!!

Por Claudenir C. Andrade claudenir@bematech.com.br Analista de Sistemas para Automao Comercial

24

MeGAZINE

PALM

Ferramentas de desenvolvimento para Palm


por: Ricardo Gruber Bernstein e Marcio Alexandroni

Na edio anterior, falamos sobre o PocketStudio, uma ferramenta de desenvolvimento para a plataforma Palm baseada em Pascal e neste artigo, falaremos sobre algumas outras ferramentas de desenvolvimento disponveis para esta plataforma, alm de uma viso geral do que possvel desenvolver em um Palm. As perguntas mais comuns dos iniciantes na plataforma Palm so: O que posso desenvolver com um Palm? Como comear a desenvolver ? Que ferramenta utilizar ? O Palm se encaixa na famlia dos PDAs, os conhecidos Personal Digital Assistants, que so equipamentos que fornecem aplicativos bsicos ao controle das atividades dirias das pessoas, como Agenda de Endereos, Lista de Contatos, Calculadora, etc. Mas ento, o Palm uma agenda/calculadora? Sim, mas no s isso! O Palm tambm um computador com processador, memria RAM, memria ROM e possui uma tima interface com o usurio e um sistema de reconhecimento de escrita baseado na tecnologia Graffiti, licenciado por outras empresas fabricantes de PDAs. Existem modelos de Palm com 2MB de memria RAM, outros com 4MB e os mais novos tem 8MB e aceitam cartes de memria que hoje chegam a 64MB, mas j existem prottipos de cartes com capacidade de 1Gb (isto mesmo, 1 Gigabyte!) de memria. As aplicaes desenvolvidas para Palm so muito pequenas, medidas em KB, raramente ultrapassam os 100K

quando desenvolvidas por uma ferramenta que no utiliza runtime, caso do PocketStudio e das ferramentas baseadas na linguagem C. Hoje, alm de softwares de organizao pessoal, existe uma variedade muito grande de aplicaes para Palm e o mercado corporativo est aproveitando para utiliz-lo como ferramenta que pode ajudar nos negcios. Um bom exemplo disto um Sistema de Automao de Fora de Vendas, o popular AFV. Vrias empresas desenvolvedoras criaram suas aplicaes AFV possibilitando a integrao ao sistema que a empresa j possui. Isto quer dizer que vendedores externos captam pedidos ou qualquer outra informao em campo e transmitem estes dados para sua central seja via modem (linha convencional ou celular) conectando um servidor central ou via Internet. Outros exemplos de sistemas desenvolvidos para o Palm vo desde coleta de dados em pesquisas de opinio at controle e configurao de mquinas industriais, via interface serial do Palm. Pela interface serial tambm possvel conectar equipamentos GPS, mini impressoras trmicas, modems, mini leitoras de carto magntico, entre outros dispositivos. Agora que mostramos o que possvel fazer com um Palm, vamos mostrar como comear a desenvolver e quais ferramentas esto disponveis. Antes mesmo da avaliao e escolha da ferramenta de desenvolvimento, faa o download do emulador do Palm OS, o Palm OS Emulator (POSE), em www.palmos.com/dev/tech/tools/

MeGAZINE

25

PALM
emulator. Voc pode desenvolver suas aplicaes na ferramenta escolhida e test-las no emulador, que um programa executado na tela de seu micro e que simula o funcionamento de modelos diferentes do Palm. Existem vrias ROM disponveis para download em http://www.uol.com.br/palmsys/Programacao/ Programacao.htm#ROM, que permitem simular cada um desses modelos. Ao acionar o emulador, voc pode escolher que modelo (ROM) deseja emular. O emulador uma ferramenta muito importante e caso voc tenha dvida na sua configurao, visite a pgina de artigos do ClubePalm (www.clubepalm.com.br/ artigos), onde h alguns artigos que o ajudaro nesta tarefa. altamente recomendvel que, antes que voc coloque sua aplicao para funcionar em seu Palm, teste-a no Emulador. Isso poder salv-lo de um Hard-Reset (Reset do Palm com perda total dos dados armazenados), caso voc tenha feito alguma coisa errada em seu programa. Antes de escolher a ferramenta de desenvolvimento, o desenvolvedor deve ter em mente que muitos projetos envolvero pelo menos dois tipos de programas: 1. Aplicativo executado no Palm Esse o programa que ser executado no Palm, desenvolvido com a ferramenta de programao escolhida. 2. Conduit O Conduit uma aplicao que roda no desktop, responsvel pela troca de dados entre Palm e Micro nos dois sentidos. Falamos sobre este assunto em uma edio anterior. Alguns conceitos bsicos formam pr-requisitos para o entendimento da linguagem que utilizaremos a seguir, na avaliao e escolha da ferramenta de desenvolvimento: PDB: o banco de dados nativo do Palm, mas no como um banco de dados relacional, no permite SQL, Chave Primria, etc., mas uma tecnologia que permite o armazenamento de dados em forma de registros. PRC e Runtime: PRC a extenso do aplicativo desenvolvido para rodar no Palm. Em linguagem simplificada, equivalente ao EXE ao qual estamos acostumados. Algumas ferramentas geram um PRC aps o processo de compilao, o qual instalamos em seguida diretamente no Palm; outras ferramentas trabalham com runtime, ou seja, em modo interpretado. Geralmente o runtime instalado no Palm durante o processo de instalao da prpria ferramenta e nem sempre o arquivo gerado fica visvel, mas o importante que ele transportado para o Palm durante a sincronizao, juntando-se ao runtime da ferramenta. Ao ser executado, o runtime aciona o aplicativo, interpretando os comandos e executando-o. Falando sobre ferramentas, no existe a melhor ferramenta. Existe sim a ferramenta mais adequada para aquele projeto especfico ou aquela que se adequa realidade tcnica de cada desenvolvedor. Antes de escolher a ferramenta, a anlise do projeto deve ser realizada pensando em todos os parmetros possveis, tais como: - Tamanho e Performance do aplicativo X Facilidade e Rapidez de desenvolvimento claro que os aplicativos desenvolvidos em linguagem C e em PocketStudio tero um tamanho bem menor do que os demais. Se for bem escrito, sua perfomance poder ser bem diferenciada. O resultado final com certeza ser bem melhor. Se o programador conseguir montar uma biblioteca de funes, o problema do tempo ser reduzido. A flexibilidade da linguagem C e do PocketStudio nos d um poder muito grande, como por exemplo acessar todas as funes do PalmOS. O desenvolvedor deve saber que a linguagem C tem uma curva de aprendizado muito longa, comparando com outras ferramentas de desenvolvimento. J o PocketStudio mais fcil de aprender por ser baseada na linguagem Pascal, muito utilizada pelos desenvolvedores Delphi, e ter alguns wizards que ajudam na produtividade, mas a ferramenta tambm exige um pouco mais de dedicao do desenvolvedor, que precisa conhecer, alm da linguagem, um pouco da API do PalmOS. Vale aquela velha regra: quanto maior a facilidade e rapidez de desenvolvimento, maior a possibilidade de termos um aplicativo com tamanho grande, ou um aplicativo no to grande porm sujeito a trabalhar com runtime. Podemos separar as ferramentas de desenvolvimento em categorias, onde os principais termos de comparao so FLEXIBILIDADE x FACILIDADE/RAPIDEZ de desenvolvimento. Na categoria FCIL e RPIDO, porm POUCO FLEXVEL e ainda sujeito runtime instalado no Palm, esto ferramentas como Satelite Forms, AppForge, NSBasic, CASL Tools e o Pendragon Forms. So ferramentas para desenvolvedores bem acostumados a ambientes RAD. Na categoria FLEXVEL e LEVE, porm com uma curva lenta de aprendizado, com o pr-requisito de muito conhecimento em linguagem C, esto o CodeWarrior e o GCC. Nesta mesma categoria se encaixa o PocketStudio, com uma curva de aprendizado melhor que as ferramentas baseadas em linguagem C. No poderamos detalhar cada ferramenta neste artigo, mas colocamos um quadro comparativo para que voc conhea cada ferramenta separadamente e seus fornecedores.

26

MeGAZINE

PALM
Possui Runtime Curva de Aprendizado Lenta Possui Conduit Link prprio No www.metrowerks.com

Ferramenta

Preo

Flexibilidade

CodeWarrior GCC (s compilador, no tem IDE) Falch.net (IDE para o GCC) PocketStudio

US$ 499

No

Grande

Grtis

No

Grande

Lenta

No

www.palmos.com/dev/tech/ tools

US$ 339 US$ 199

No

Grande

Lenta

No

www.falch.net www.pocket-technologies. com www.java.sun.com embedded.oti.com www.wabasoft.com www.appforge.com

No

Grande

Mdia

No

Java

Grtis

Sim 80/300K

Mdia

Mdia

No

AppForge

US$ 699 US$ 150 US$ 799 US$ 84,95 US$ 1.140 US$ 25

Sim 300 K

Mdia

Rpida

No

NSBasic Satellite Forms CASL Tools Pendragon Forms PDA Toolbox

Sim 80 K

Mdia

Rpida

No

www.nsbasic.com www.pda.com.br www.pumatech.com www.caslsoft.com

Sim 83 K

Mdia

Rpida

Sim

Sim 50 K

Mdia

Rpida

Sim

Sim 166 K

Pequena

Rpida

Sim

www.pendragon-software.com

No

Pequena

Rpida

No

www.pdatoolbox.com

Conclumos nosso artigo e esperamos t-lo ajudado a conhecer melhor a plataforma Palm e suas ferramentas de desenvolvimento. Em breve,

o Clubepalm estar ministrando Cursos de Desenvolvimento para Palm. Para maiores informaes consulte www.clubepalm.com.br. At a prxima!

MeGAZINE

27

DICAS & TRUQUES

RichEdit com Formatao Igual ao Editor do Delphi


Neste exemplo mostraremos como ir destacando palavras em um RichEdit durante a digitao das mesmas, algo semelhante ao Editor do IDE do Delphi, onde as palavras reservadas vo sendo destacadas automaticamente, com opo de definir combinaes de cores diferentes. { Neste exemplo iremos utilizar os seguinte componentes: . RichEdit, name = Editor; . PopupMenu, name = PopStyle, items = Default, Classic, Twilight, Ocean . ToolBar, name = ToolBar1 . ToolButton, name = BT_Style, DropDownMenu = PopStyle, Style = tbsDropDown . ToolButton, name = BT_Sair } implementation {$R *.DFM} // Funo responsvel pela Formatao. procedure CodeColors(Form: TForm; Style: String; RichE: TRichedit); const // smbolos. CodeC1: array[0..20] of String = (#,$,(,),*,,,.,/ ,:,;,[,],{,},<,>,,=,+,,@); // palavras reservadas. CodeC2: array[0..45] of String = (and,as,begin, case,char,class,const,downto, else,end,except,finally,for, forward,function,if,implementation,interface,

is,nil,or,private,procedure,public,raise, repeat,string,to,try,type,unit,uses,var, while,external,stdcall,do,until,array,of, in,shr,shl,cos,div, then); var FoundAt : LongInt; StartPos, ToEnd, i : integer; T : String; FontC, BackC, C1, C2 ,C3 ,strC, strC1 : TColor; PosInicial: Integer; begin // tratamento para no tremer ao atualizar. RichE.OnChange := Nil; LockWindowUpdate(RichE.Handle); LockWindowUpdate(Form.Handle); // guarda posio atual do Cursor. PosInicial := RichE.SelStart; // Determinada Font e atributos. with RichE do begin Font.Name := Courier New; Font.Size := 10; if WordWrap then WordWrap := False; SelectAll; SelAttributes.color := clBlack; SelAttributes.Style := []; SelStart := 0; end; // Variveis para manuteno das cores. BackC := clWhite; FontC := clBlack; C1 := clBlack; C2 := clBlack; C3 := clBlack; strC := clBlue; strC1 := clSilver; // De acordo com o estilo selecionado, //atribui as cores para a variveis... if Style = Twilight then begin

28

MeGAZINE

DICAS & TRUQUES


BackC := clBlack; FontC := clWhite; C1 := clLime; C2 := clSilver; C3 := clAqua; strC := clYellow; strC1 := clRed; end else if Style = Default then begin BackC := clWhite; FontC := clBlack; C1 := clTeal; C2 := clMaroon; C3 := clBlue; strC := clMaroon; strC1 := clSilver; end else if Style = Ocean then begin BackC := $00FFFF80; FontC := clBlack; C1 := clMaroon; C2 := clBlack; C3 := clBlue; strC := clTeal; strC1 := clBlack; end else if Style = Classic then begin BackC := clNavy; FontC := clYellow; C1 := clLime; C2 := clSilver; C3 := clWhite; strC := clAqua; strC1 := clSilver; end else // Se no escolheu nenhum dos // estilos pr-definidos, gera erro! begin with RichE do begin T := {+Style+ = Estilo Invlido, utilize [Default,Classic,Twilight,Ocean] somente!}; Lines.Insert(0,T); StartPos := 0; ToEnd := Length(Text) - StartPos; FoundAt := FindText(T, StartPos, ToEnd, [stWholeWord]); SelStart := FoundAt; SelLength := Length(T); SelAttributes.Color := clRed; SelAttributes.Style := [fsBold]; StartPos := 0; ToEnd := Length(Text) - StartPos; FoundAt := FindText(somente!, StartPos, ToEnd, [stWholeWord]); SelStart := FoundAt; SelLength := 4; SelAttributes.Color := clRed; SelAttributes.Style := [fsBold,fsUnderLine]; end; end; // Faz a formatao de acordo com o // estilo pr-definido. RichE.SelectAll; RichE.Color := BackC; RichE.SelAttributes.color := FontC; for i := 0 to 100 do begin with RichE do begin StartPos := 0; ToEnd := Length(Text) - StartPos; FoundAt := FindText(IntToStr(i), StartPos, ToEnd, [stWholeWord]); while (FoundAt <> -1) do begin SelStart := FoundAt; SelLength := Length(IntToStr(i)); SelAttributes.Color := C1; SelAttributes.Style := []; StartPos := FoundAt + Length(IntToStr(i)); FoundAt := FindText(IntToStr(i), StartPos, ToEnd, [stWholeWord]); end; end; end; // Smbolos. for i := 0 to 20 do begin with RichE do begin StartPos := 0; ToEnd := Length(Text) - StartPos; FoundAt := FindText(CodeC1[i], StartPos, ToEnd, []); while (FoundAt <> -1) do begin SelStart := FoundAt; SelLength := Length(CodeC1[i]); SelAttributes.Color := C2; StartPos := FoundAt + Length(CodeC1[i]); FoundAt := FindText(CodeC1[i], StartPos, ToEnd, []); end; end; end; // Constantes. for i := 0 to 45 do begin with RichE do begin StartPos := 0; ToEnd := Length(Text) - StartPos; FoundAt := FindText(CodeC2[i], StartPos,

MeGAZINE

29

DICAS & TRUQUES


ToEnd, [stWholeWord]); while (FoundAt <> -1) do begin SelStart := FoundAt; SelLength := Length(CodeC2[i]); SelAttributes.Color := C3; SelAttributes.Style := [fsBold]; StartPos := FoundAt + Length(CodeC2[i]); FoundAt := FindText(CodeC2[i], StartPos, ToEnd, [stWholeWord]); end; end; end; // Entre apstrofe. Startpos := 0; with RichE do begin FoundAt := FindText(, StartPos, Length(Text), []); while FoundAt <> -1 do begin SelStart := FoundAt; Startpos := FoundAt+1; FoundAt := FindText(, StartPos, Length(Text), []); if FoundAt <> -1 then begin SelLength := (FoundAt - selstart)+1; SelAttributes.Style := []; SelAttributes.Color := strC; StartPos := FoundAt+1; FoundAt := FindText(, StartPos, Length(Text), []); end; end; end; // Entre chaves. Startpos := 0; with RichE do begin FoundAt := FindText({, StartPos, Length(Text), []); while FoundAt <> -1 do begin SelStart := FoundAt; Startpos := FoundAt+1; FoundAt := FindText(}, StartPos, Length(Text), []); if FoundAt <> -1 then begin SelLength := (FoundAt - selstart)+1; SelAttributes.Style := [fsItalic]; SelAttributes.Color := strC1; StartPos := FoundAt+1; FoundAt := FindText({, StartPos, Length(Text), []); end; end; end; RichE.SetFocus; RichE.SelStart := PosInicial; RichE.SelAttributes.Color := clBlack; RichE.SelAttributes.Style := []; // Volta evento onChange aps atualizao. LockWindowUpdate(0); RichE.OnChange := Form1.EditorChange; end; procedure TForm1.FormShow(Sender: TObject); begin // no onShow do Form, seta estilo Ocean. Style := Ocean; // Chama a funo para mostrar formatado. CodeColors(Self, Style, Editor); end; procedure TForm1.BT_StyleClick(Sender: TObject); begin // Estilo default, no boto de estilos. Style := Ocean; end; procedure TForm1.Twilight1Click(Sender: TObject); begin // alterar estilos, utiliza o caption do //tem do PopUpMenu. Style := StringReplace(TMenuItem(Sender).Caption, &, , [rfReplaceAll, rfIgnoreCase]); // Chama funo para alterar o estilo. CodeColors(Self, Style, Editor); end; procedure TForm1.BT_SairClick(Sender: TObject); begin // Fecha o Form. Close; end; procedure TForm1.EditorChange(Sender: TObject); begin // A cada alterao no RichEdit, chama funo para manuteno da formatao. CodeColors(Self, Style, Editor); end; end. O projeto de exemplo referente esta dica est disponvel para download em nosso site no endereo www.theclub.com.br/revista/ richdelphi.zip.

30

MeGAZINE

rainbow igual a ltima revista The Club 12/2001

MeGAZINE

31