You are on page 1of 288

1

DELPHI APOSTILA III

AUTOMAO COMERCIAL
AUTORES RENATO BARROS FRANCISCO FERREIRA DA SILVA 2006

NDICE
1 2 3 4 4.1 4.2 CONTEDO CLASSES TIPOS DE MTODOS E CAMPOS COMPONENTES Override A criao do Primeiro Componente 4.2.1 Criando o componente 4.2.2 Implementando o procedimento KeyPress 4.2.3 Instalando o componente 4.3 Mais um exemplo de criao de componente 4.3.1 Criando um componente DBEdit com mascara 4.3.2 A mascara 4.3.3 SCRCOPY 4.3.4 Testando o componente 4.3.5 Programao do componente EdtCpf TEMPLATE 5.1 Um template simples 5.2 Abrindo um novo projeto atravs do template CDIGO DE BARRAS 6.1 Surgimento do cdigo de barras 6.2 Cdigo de barras do tipo UPC 6.3 Os tipos de cdigos EAN 6.4 O padro EAN 6.5 Definio do cdigo 6.6 O funcionamento do cdigo de barras 6.7 A representao dos campos do cdigo EAN 6.8 Durao do cdigo de barras 6.9 Cdigo de barras do tipo EAN-8 6.10 Cdigo ISBN 6.11 Cdigo ESSN 6.12 Cdigo EAN-14 6.13 Cdigo de uso interno 6.14 Localizao do cdigo de barras 6.15 Calculo do dgito verificador do EAN-13 6.16 Criao do componente para fazer leitura do cdigo de barras 6.16.1 - Programando as propriedades 6.16.2 - Programao do Procedimento KeyPress 6.16.3 - O tratamento do cdigo EAN-13 para uso interno. 6.17 - Programao da Unit CodigoDeBarras 6.18 - Exerccio: 6.19 - Utilizando o cdigo de barras 6.20 - Exemplo de programao de procedimento usando o componente de cdigo de barras

3 7 DESINSTALAO DE COMPONENTES 8 CRIAO AUTOMTICA DE FORMULRIOS. 8.1 - O comando Destroy 9 - DLL 9.1 - Problemas com a DLL 9.2 - Como construir uma DLL 9.3 - Programao das rotinas 9.4 - Gerando a DLL 9.5 - Programao da DLL 9.6 - Fazendo um aplicativo para testar a DLL 9.6.1 - Para usar a DLL 9.6.2 - A rotina Divide. 9.6.2.1 - Programao do boto Divide 9.7 - Como criar formulrios dentro da DLL. 9.8 - Programao da Unit U_teste: 9.9 - Criando uma DLL para chamar este formulrio. 9.9.1 - Programao das rotinas. 9.10 - Programao da DLL 9.11 - Criando outro Projeto para Teste 9.12 - Programao da Unit Chama tela 9.13 - Exerccio: 10 - PROVAS APLICADAS 10.1 - Prova A 10.2 - Prova B 10.3 - Prova C 10.4 - Prova D 11 IMPRESSORA FISCAL 11.1 - Cupom Fiscal 11.2 - Relatrios emitidos pela Impressora Fiscal 11.3 - Os Arquivos de Configurao. 11.4 - O emulador. 11.5 - Exemplos de integrao 11.6 - Configurando a Impressora 11.7 - A memria de trabalho do emulador. 11.8 - As rotinas 11.9 - PCHAR 11.10 - Possveis retornos da Funo (INTEIRO): 11.11 - Comandos Retorno da Impressora retirado do arquivo Ajuda BEMAFI32.DLL 11.11.1 - Estados de ST1 11.11.2 - Estados de ST2 11.11.3 Lgica de tratamento 11.12 Itens Rotina Vende Item 11.13 - Rotina Iniciar Fechamento do Cupom Fiscal 11.14 Rotina Bematech FI EfetuarFormaPagamentoMFD 11.15 - Fechamento do Cupom Fiscal. 11.16 Implementando o programa para uso com banco de dados.

4 12 DECISION CUBE 12.1 - BI ( ) - Negcio Inteligente 12.2 - A implementao da ferramenta 12.2.1 - Descrio: 12.2.1.1 DecisionCube. 12.2.1.2 DecisionQuery. 12.2.1.3 DecisionSource 12.2.1.4 DecisionPivot 12.2.1.5 DecisionGrid 12.2.1.6 Decision Graph 12.3 Criando uma aplicao exemplo 12.3.1 - Decision Query 12.3.2 - DecisionCube 12.3.3 - DecisionSourse 12.3.4 - DecisionPivot 12.3.5 - DecisionGrid 12.3.6 - DecisionGraph 12.4 - Executando o Aplicativo 12.4.1 - Exemplo 1: 12.4.2 - Exemplo 2: 12.4.3 - Exemplo 3 12.4.4 - Exemplo 4 12.4.5 - Exemplo 5 12.4.6 - Exemplo 6 12.4.7 - Exemplo 7 12.4.8 - Exemplo 8 12.4.9 - Exemplo 9 12.4.10 Exerccio Trabalho: 13 - CORREIO ELETRNICO 13.1 - Email no Delphi 13.2 - Diferena ente servidor ftp e pop3 13.3 - Criando o Formulrio 13.3.1 - CheckBox Confirmar recebimento 13.3.2 - Memo 13.3.3 - Componente OpenDialog 13.3.4 - Componente - IBMessage 13.3.5 - Componente IdsMTP 13.4 - A programao. 13.4.1 - Boto Anexar 13.4.2 - Boto Enviar 13.5 - Programao completa do aplicativo 14 CONEXO ADO 14.1 - O que ODBC? 14.2 - A paleta ADO 14.2 .1 - Componentes da Paleta ADO 14.3 - Como criar uma conexo. 14.3 1 - A Porta

5 14.4 - Criao de conexo via ODBC. 14.5 - Caixa de dilogo Instalao do Microsoft ODBC para Oracle 14.6 - Para usar no Delphi 14.6.1 - Colocando uma tabela. 14.7 - Um exemplo pratico 14.7.1 - Colocando uma tabela. 14.8 - O componente TDCOMConnection 15 PROGRAMAO EM TRS CAMADAS 15.1 - Introduo 15.2 As trs camadas 15.2.1 - O cliente, o servidor de aplicao e o banco de dados. 15.2.2 - Atualizao. 15.2.3 - Desvantagem. 15.2.4 - Performance 15.3 - Antes, um histrico 15.4 - Como o DCOM distribui as tarefas. 15.5 - Criando uma nova Aplicao. 15.5.1 - Projeto Cliente 15.5.2 - Tabela Temporria 15.5.3 - Outro exemplo: 15.6 - Propriedades de Expression (TAggregateField) 15.6.1 - Descrio 15.7 - Colocando um campo Total Parcial. 15.8 - Uma regra de negcio num programa 15.8.1 - Fazendo a configurao 15.8.1.1 -Componente SQLConnection 15.8.1.2 - Componente SQLDataSet 15.8.1.3 - Componente DataSetProvider 15.8.1.4 - Os dois clientes 15.8.1.5 - A programao 15.8.1.6 - Alterando nomes dos campos 15.8.1.7 - Propriedades dos componentes DataSetProvider (data access) e ClientDataSet (data access) 15.8.1.8 - DataSetProvider (data access) 15.8.1.9 - ClientDataSet (data access) 15.8.2 Tabelas do banco de dados para teste: 15.9 - As Trs Camadas de fato 15.9.1 - O servidor 15.9.2 - Fornecedor de recursos 15.9.3 Montando o Servidor 15.9.4 - Os Clientes 15.9.5 - Primeira forma de conexo via DCOM 15.9.6 - A propriedade PacketRecords 15.9.7 - Fazendo mais uma exportao. 15.9.8 - Tratamentos 15.9.8.1 - Auto Numerao de Cdigo (ID) 15.9.9 - Programando o evento BeforeUpdataRecord.

6 15.9.10 - Refresh da tela (Atualizao) 15.9.11 - Programao dos projetos Servidor e Cliente 16 BALANA COMERCIAL 16.1 - Instalando o Componente 16.1.1 - Descrio da pasta leia-me 16.1.2 - Instalao 16.2 - Um Exemplo 16.2.1 - A programao do componente. 16.2.2 - A configurao do DEVICE 16.2.2.1 - Baud Rate 16.2.2.2 - Parity (paridade) 16.2.2.3 - Stop Bits (Bits de parada) 16.3 - Mais um exemplo: 16.3.1 - A programao 16.3.2 Melhorando o exemplo: 16.3.3 - Fazendo a programao: 17 INSTALL SHIELD 17.1 - Criando a Instalao. 17.2 - Organizao do Setup.

FIGURAS
Figura 1 Paletas de Componentes Figura 2 Caixa de dilogos para instalao de componentes. Figura 3 Preenchimento da caixa de dialogo para instalao de componentes. Figura 4 Preenchimento das propriedades do novo componente Figura 5 Modulo de programao do componente. Figura 6 Campo protected criao de procedimentos. Figura 7 - Caixa de dialogo para instalao de componentes. Figura 8 Confirmao da instalao. Figura 9 Registro do componente. Figura 10 Pacotes de componentes. Figura 11 Formulrio utilizando o novo componente. Figura 12 Demonstrao da utilizao do componente instalado. Figura 13 Criao do componente TEdtCPF Figura 14 Reinstalando o componente. Figura 15 Compilando o componente. Figura 16 Formulrio utilizando o componente criado. Figura 17 Formulrio compilado e em execuo. Figura 18 Visualizao do formulrio Template Figura 19 Caixa de dilogo para adicionar Template em um repositrio. Figura 20 Confirmao para salvar o Template. Figura 21 Formulrio de Novos Itens Figura 22 Formulrio aberto atravs de um Template. Figura 23 Programao do formulrio aberto atravs de um Template. Figura 24 Exemplo de cdigo EAN-13 Figura 25 Exemplo de cdigo de barras EAN-13 Figura 26 Exemplo de cdigo de barras EAN-8 Figura 27 Caixa de dilogos para criao de novo componente. Figura 28 Cdigo de programao do componente CodigoDeBarras. Figura 29 Procedimento para seleo do evento KeyPress. Figura 30 Caixa de Instalao de componentes. Figura 31 Pacotes de componentes. Figura 32 Remoo de componentes. Figura 33 Caixa de confirmao de remoo de componentes. Figura 34 Opes de Projetos. Figura 35 Relao de componentes de uma paleta. Figura 36 Tela de um projeto. Figura 37 Tela de Cadastro de Clientes. Figura 38 Opes de projeto para o sistema. Figura 39 Tela de Units de um projeto. Figura 40 Tela de projeto de um sistema. Figura 41 Caixa de projetos Novos itens. Figura 42 Programao inicial de uma DLL Figura 43 Compilao da DLL.

8 Figura 44 Formulrio de uma calculadora simples. Figura 45 Projeto calculadora em execuo atravs de uma DLL. Figura 46 Execuo do projeto calculadora com novos parmetros. Figura 47 Formulrio para teste Figura 48 Projeto teste para chamar tela com DLL Figura 49 - Projeto Chama tela compilado. Figura 50 Tela aberta atravs de uma DLL. Figura 51 Tela do site www.bematech.com.br. Figura 52 Tela do emulador EMULFITH VR.1.02 Figura 53 Tela da ajuda da Bemafi32.DLL. Figura 54 Formulrio de teste para Cupom Fiscal. Figura 55 Funes de inicializao para Impressora Fiscal. Figura 56 Tela de ajuda Bematech Bematech_FI_AbreCupomMFD. Figura 57 Teste Impressora em execuo Figura 58 Emulfith vr.1.02 mostrando dados da impressora fiscal. Figura 59 Aspecto do formulrio Forma de pagamento para a venda. Figura 60 Componentes da paleta Decision Cube. Figura 61 Tabela Vendas.DB no paradox. Figura 62 Formulrio exemplo do Decision Cube. Figura 63 Parmetros do DataBase. Figura 64 Decision Query Editor. Figura 65 Comandos SQL para a tabela do Decision Cube. Figura 66 Controle de memria do Decision Cube Editor. Figura 67 Formatao da Data no Decision Cube. Figura 68 Amostra de Opcionais vendidos. Figura 69 Grfico de amostra por idades de clientes. Figura 70 Amostra de idade e opcionais. Figura 71 Formulrio de email no Delphi. Figura 72 Object Inspector do componente odAnexos (TOopenDialog) Figura 73 Editor de filtro no Object Inspector do componente odAnexos. Figura 74 Object Inspector do componente idMessage. Figura 75 Object Inspector do componente idSMTP. Figura 76 Object Inspector do componente LB_Anexos (TlistBox). Figura 78 Clientes e banco de dados. Figura 79 Administrador de fonte de dados ODBC. Figura 80 Tela para criar nova fonte de dados. Figura 81 - Instalao do Microsoft ODBC para Oracle. Figura 82 Formulrio com componente ADO. Figura 83 Formulrio do componente ADOConnection. Figura 84 Formulrio de propriedades de vinculao de dados. Figura 85 Fontes de conexo do componente ADO. Figura 86 Aspecto do formulrio de teste para conexo ADO. Figura 87 Configuraes e conexo do componente SQLConnection. Figura 88 Grid adicionada ao formulrio e ligada ao DataSourse. Figura 89 Formulrio para teste de conexo ADO. Figura 90 Formulrio do componente ADOConnection. Figura 91 Propriedade de vinculao de dados.

9 Figura 92 Informao de teste de conexo. Figura 93 String de conexo. Figura 94 Aspecto do formulrio usando exemplo de fonte do Delphi Figura 95 Representao de cliente ligado ao banco de dados. Figura 96 Tela de visualizao de servios de componentes. Figura 97 Aplicativos COM+ em servios de componentes. Figura 98 Editor de propriedades Figura 99 Formulrio de Teste de tabela temporria. Figura 100 Editor de propriedades de componente. Figura 101 Campos do componente Tbl_Teste, mostrando o campo TotalGeral. Figura 102 Formulrio com o campo Total. Figura 103 Editor de propriedades de componente. Figura 104 Formulrio de Teste de tabela temporria, Figura 105 Object Inspector do componente DS_Ativ (DataSetProvider). Figura 106 Aspecto do formulrio com duas grids representando dois clientes. Figura 107 Formulrio com dois clientes em execuo. Figura 108 Mensagem de erro mostrando violao de chave. Figura 109 Campos do componente SQLDataSet (Tbl_Atividade). Figura 110 Object Inspector da Tabela de Atividades (Tbl_Atividade) Figura 111 Mensagem de erro. Figura 112 Formulrio de teste Figura 113 Propriedade de mensagem de erro. Figura 114 Mensagem de erro. Figura 115 Transactional Data Module. Figura 116 Tela de dilogo do Data Modulo Figura 117 Tela de dialogo do DataModuloRemoto. Figura 118 Tela do Servidor Data Modulo. Figura 119 Componentes do DataModuloRemoto. Figura 120 Tela de Units. Figura 121 Programao gerada do P_Serv_Tbl. Figura 122 Servios de componentes. Figura 123 DataModuloRemoto no Install COM. Figura 124 Nome do Servidor. Figura 125 Informao de sucesso de registro do ActiveX. Figura 126 Servidor de Aplicao criado no Servios de componente. Figura 127 Object Inspector do componente DCOM_Conexo. Figura 128 Object Inspector do componente Tbl_Ativ (ClientDataSet). Figura 129 Formulrio de Clientes. Figura 130 Object Inspetor do componente SQL_Ativ. Figura 131 Formulrio cliente em execuo. Figura 132 Object Inspector do componente SQL_Ativ. Figura 133 Editor SQL. Figura 134 Balana Toledo Figura 135 Contedo do pacote ACBr Figura 136 Mensagem de instalao do pacote ACBr. Figura 137 Informaes de instalao do pacote ACBr Figura 138 - Paleta ACBr com todos os seus componentes instalados.

10 Figura 139 Formulrio do demo BalancaTeste Figura 140 Propriedades da paleta ACBr Figura 141 Campo genrico do formulrio demo BalancaTeste. Figura 142 Propriedades do componente ACBrBAL o Device Figura 143 Formulrio teste Figura 144 Criao da tabela Produto no Paradox Figura 145 Preenchimento da tabela Produto no Paradox. Figura 146 Preenchimento das propriedades do Database Figura 147 - Aspecto do formulrio depois de pronto Figura 148 - Aspecto do formulrio depois de executado. Figura 149 - Tela de Menu do InstallShield Figura 150 - Criando um novo projeto. Figura 151 - Tela de boas vindas Figura 152 Criando um Novo Projeto Figura 153 - Informaes da aplicao. Figura 154 Atualizaes do Software. Figura 155 - Informaes do Software Figura 156 Apresentao da Aplicao. Figura 157 Arquivos para instalao. Figura 158 Arquivos Instalados. Figura 159 Criao de Shortcuts. Figura 160 - Registro do sistema. Figura 161 Dilogos. Figura 162 Sumrios. Figura 163 Organizao do Setup.

11

Delphi Apostila III


AUTOMAO COMERCIAL 1 Contedo
Classes Criao de Componentes Herana Paleta personalizada de componentes Template Cdigo de Barras Implantao de Cdigo de Barras no Sistema Criao de DLL Para que serve Como funciona Como criar uma DLL Como Usar Impressora Fiscal Cupom Fiscal Emisso de Cupom Fiscal Como Cancelar Cupom Fiscal Forma de pagamento Localizao de nmero de Srie da Impressora Web dentro do Delphi Desision Cube Instalao de Programas com InstallShield

12

2 CLASSES
A partir de agora faremos literalmente a programao orientada a objeto. Em uma declarao TYPE, estamos definindo o tipo para o Delphi. como se fosse criar um novo tipo de varivel, estamos definindo uma nova tipagem. Quando abrimos um formulrio dentro do Delphi, estamos criando um tipo chamado TForm1. A letra T antes do nome sempre vai existir. Exemplos: TEdit, TForm TBgrid. Este T um tipo. Vamos definir uma estrutura de dados para ele. Isso uma nomenclatura usada e no obrigatria, s colocado para saber que um tipo. Da mesma forma que damos um nome a um formulrio (Frm_NomeDoForm), ali ele pe um T antes do NomeDoForm. Ento criamos esse Form que uma classe derivada de TForm. Em Pascal, num registro RECORD, temos uma estrutura, por exemplo: nome,endereo, telefone, definida no campo TYPE. Reg1 = Record Cod_Cli:integer; Nome_Cli: string; End_Cli: string; End; Para declarar uma varivel denominada Registro do tipo Reg1, basta incluir sua declarao aps a palavra reservada VAR: Var Registro: Reg1; A estrutura ns colocamos <Reg1.Nome> <Reg1.Endereo> A idia de classe a mesma. A classe um super-record, alm de definirmos tipos como cdigo, endereo, telefone, podemos definir mtodos, procedimentos internos que manipulam esses dados. Um pouco diferente do outro, podemos colocar procedimentos, por exemplo: Calcular o cdigo. S existe para aquele dado que definirmos da mesma classe, no funciona fora disso. Para os procedimentos especficos, declaramos tudo dentro dessa classe, alm de colocar dados, podemos colocar programao. --> uma classe um super-record. Uma classe tambm tem diversos campos. A definio de um tipo de classe pode ser feita de forma bastante semelhante de um tipo de varivel composta, bastando substituir a palavra reservada Record por Class.

13 Se quisermos criar uma classe denominada Reg1 em vez de um tipo composto chamado Reg1, basta incluir o seguinte trecho de cdigo aps a palavra reservada TYPE: Reg1 = Class Cod_Cli:integer; Nome_Cli: string; End_Cli: string; End; Agora temos uma classe denominada Reg1, em vez de um tipo de varivel composta chamada Reg1 Podemos ento declarar um objeto denominado Registro, da classe Reg1, incluindo a sua declarao aps a palavra reservada VAR: Var Registro: Reg1; Anteriormente foi criado um tipo de varivel e foi declarada uma varivel daquele tipo. Agora criamos uma classe e declaramos um objeto daquela classe. O que tem dentro da classe? Quando falamos em classe, podemos ter uma herana desta classe. Herdar alguma coisa pegar as caractersticas do objeto Pai. Exemplo: Como o filho? Num casamento, o filho herda caractersticas do pai, tipo de cabelo, cor de pele. Da mesma forma que acontece na vida natural, aqui tambm. Se criarmos uma classe, tudo que for definido entre parnteses herdado. O filho tem todas as caractersticas prprias, mais o que herdar do pai. No formulrio do Delphi, temos as caractersticas: borda, cor de fundo, boto maximizar, minimizar, fechar, eventos programados que algum j fez. Se for criado um novo Form herdada as caractersticas do Form principal. Este formulrio criado uma classe chamada TForm. TForm uma classe criada pelos programadores da Borland para que ns possamos criar outro formulrio herdando suas caractersticas. Este novo formulrio criado igual ao formulrio Pai TForm e neste novo formulrio podemos fazer as modificaes que por padro, antes da modificao, idntico ao Pai, o TForm. A vantagem de trabalhar com classe herdar caractersticas. Podemos construir uma classe, por exemplo, de manipulao de Impressora fiscal padro e as caractersticas como escolha de impressora e tipo. Essa classe herda todas as rotinas prontas e s colocaremos o que for preciso a mais, com isso economizamos muitas linhas de programao criando classes. No necessrio programar tudo de novo, porque j foi herdado. Para ter acesso aos campos de um objeto da classe, basta utilizar a notao de ponto. Para atribuir valores aos campos do objeto Registro (da classe Reg1), basta incluir as seguintes linhas de cdigo: Registro.cod_Cli := 100;

14 Registro.Nome_Cli: =Fulano; Registro.End_Cli:= Rua x;

15

16

3 TIPOS DE MTODOS E CAMPOS


Na linguagem Delphi, uma classe pode ter os seguintes tipos de mtodos e campos: A diretiva public detona campos e mtodos que so livremente acessveis por qualquer outra poro de uma programa tanto quanto a unit em que esto definidos. private (privados) - A diretiva private denota campos e mtodos de uma classe que no so acessveis fora da unit que declara a classe. protected (protegidos) - A diretiva protected usada para indicar mtodos e campos com visibilidade limitada. Somente a classe atual e suas derivadas podem acessar elementos protected. Mais precisamente, somente a classe, subclasses, e qualquer cdigo na mesma unit que a classe podem acessar os membros protected.

public (pblicos) -

Alem desses temos ainda os tipos: - published semelhante ao tipo publico, mas seu valor pode ser visualizado no Object Inspector e ser visto logo mais na criao de componentes. - Automated tem as mesmas regras de visualizao do tipo public e geralmente usado em classes derivadas da classe TAutoObject (definida na unit OleAuto). Ento, qual a diferena da programao entre Private e Public? Se definirmos uma rotina dentro do private no formulrio TForm, como uma classe chamada PintadeAzul, e criarmos um TForm1 (que uma herana) com todas as caractersticas do TForm. Como a definio de PintaDeAzul esta dentro do campo private do TForm ela no vai estar disponvel para o TForm1 porque privativa somente para o formulrio Pai. Se esta definio fosse criada dentro do campo public, certamente iria funcionar no Tform1. Fazendo um Teste: Abra a programao de um formulrio recm criado. clique em F12. Criamos no mtodo private definindo a seguinte varivel: A do tipo integer. Criamos uma classe chamada Pessoa que tem dentro dela uma nica varivel que no tem mtodo, j funciona para a classe pessoa. Criamos uma outra classe chamada Aluno que herda as caractersticas de pessoa e que no tem nada no private e nem no public. Basicamente a classe aluno igual classe Pessoa. Colocamos no formulrio um boto, com uma varivel aluno do Tpessoa. Essa classe do tipo Tpessoa, tem s o cdigo e o nome, e tem mais uma varivel TAluno que tem as caractersticas Tpessoa. O que acontece? Quando apontamos em TAluno, conseguimos ver as caractersticas de Tpessoa porque do mesmo tipo, tem a mesma herana. Se tivermos outra classe e passamos o mesmo modo, no conseguimos. Como no foi definido em outro form, porque

17 ento est mostrando? Porque esta definido na mesma Unit, por isso que consegue enxergar. Se a classe TPessoa e TAluno tiverem sido definidas em Units diferentes j no conseguiramos enxergar. Quando fizemos a definio de TAluno, ele mostrou a varivel A. Mostrou o A porque estava dentro do formulrio, na mesma Unit, mas se estivesse em Units diferentes, j no iria aparecer. Tudo que tiver dentro do Privat na mesma Unit possvel enxergar. No caso do componente, uma Unit que ser criada, no consegue enxergar se for colocada algum comando de linha no Privat. Em dois formulrios, Form1 e Form2, no Form2 vamos criar uma caracterstica, varivel aux do tipo integer que s existe no Form2 e foi criado como sendo Private. Na Unit1, se colocarmos o comando USE UNIT2.<qualquercoisa> no mostrar a varivel Aux, porque est em outro formulrio no campo Private. Se no Form2, colocarmos a varivel Aux no campo Public, ento na Unit1 aparecer o comando Form2.<qualquercoisa> e a varivel ser mostrada. Obs.: No esquea de atribuir algum valor para a varivel criada, seno no mostra no form. Agora o comando permitiu mostras a varivel Aux porque ela foi colocada no campo Public. No Primeiro exemplo, foi mostrado o acesso a um campo privado porque estava na mesma Unit, ento no tem privacidade. No segundo exemplo, em Units diferentes, antes de acessar, ele define se public ou Private, para verificar se pode ou no acessar.

18

4 - COMPONENTES
Um componente nada mais do que uma listagem, uma programao que j est feita e quando herdada j vem tudo pronto (create, close, print, resize). Esses eventos programados esto no campo public que podem ser modificados. Na herana, uma classe herda caractersticas de outra classe. Podemos colocar procedimentos e disponibilizar dados. Alm de dados podemos criar outros procedimentos. Para criar um procedimento que outros podem acessar, colocamos no campo public esses procedimentos. Ex: No campo public podemos colocar Procedure PintaDeAzul - Para definir esse procedimento, criamos o nome do procedimento. - Posicionamos o cursor em cima do nome do procedimento, no caso PintaDeAzul - Pressionando as Teclas CTRL + SHIFT + C as linhas deste procedimento criada logo abaixo com os campos Procedure begin end - para depois colocarmos a programao dentro deste campo. Esta programao se refere ao Form2 Quando definimos a classe TForm2, este procedimento PintaDeAzul s existe no Tform2. No TForm1 se for criada uma classe herdando caractersticas do TForm1 no vai existir o procedimento PintaDeAzul, mas se for herdada do TForm2, ento vai ganhar esta caracterstica do PintaDeAzul. Basicamente, quando criamos componentes, estamos disponibilizando vrios procedimentos, vrias rotinas, que quando aparecer um cone, nele herdada todas as caractersticas automaticamente. Tem tudo o que o Pai tinha mais a programao que for feita parte. Se tivermos uma classe chamada TForm (formulrio) e criamos nossa prpria classe chamada TNovoFormulario, herdando caractersticas de TForm, neste formulrio gravamos nosso evento Close e no queremos que execute o evento Close do TForm, mas sim este close que criamos, um novo close. Como fazer para ele saber qual dos closes a executar, se o close do Pai ou o close do filho? Neste caso, sempre vai tentar usar o do filho. Para isso escrevemos Override (Virtual) aps o comando, no evento do formulrio Pai, porque estamos indicando para o Delphi que ele pode ser substitudo, se existir o procedimento no filho, ele pode, se quiser, substituir o do Pai. Se for procurado no Filho e no localizar, ento executa o do Pai. Se no for definido isso, por padro, ser executado o evento close do formulrio Pai. Primeiro procura na classe Pai, e executa, depois executa do filho.

19

4.1 - Override
Existe um create na classe pai e toda vez que for usado vai executar este create, mas podemos fazer o nosso create. Em vez de usar o create do pai podemos fazer um create especial, e na hora que usar, por exemplo, pintar de alguma cor, ento este create pode ser substitudo, deixando uma instruo que virtual (Override) Em toda programao podemos substituir o mtodo por outra classe que permita que possa colocar uma programao diferente. Para isso defina o mtodo a ser substitudo como Override (virtual). O mtodo existe mas pode ser substitudo, diferente de outros procedimentos, por exemplo, habilitar alinhamento no pode ser substitudo, mesmo que for feito este procedimento no Filho, vai executar o do Pai. Geralmente na programao do componente ele vem como virtual (Override), podendo permitir opcionalmente efetuar sua prpria programao. Em funes que no podem ser substitudas no colocamos Override.

4.2 - A criao do primeiro Componente


Para o exemplo, vamos criar um componente Edit que quanto digitarmos letras minsculas, ele transforma tudo em letras maisculas. J existe um componente pronto no Delphi, ento o que o novo componente vai ter? Ter tudo o que o Edit1 tem mais a caracterstica de passar tudo para maisculo. Ento vai ter uma rea para digitar, vai ter todas as propriedades do Edit pai mais as propriedades que quisermos definir. 4.2.1 Criando o componente Para criar o componente faa: Clique na paleta Component. New component

Figura 1 Paletas de Componentes

20

Figura 2 Caixa de dilogos para instalao de componentes. Queremos criar um componente, parecido com quem? Digite o nome TEdit, componente que deseja herdar as caractersticas, no campo Ancestor type, que mostrar uma listagem dos componentes que o Delphi j tem. (fig. 3).

Figura 3 Preenchimento da caixa de dialogo para instalao de componentes. Ai aparece dois tipos de TEdit um TEdit (QStdCtrls) e um TEdit (StdCtrls). Qual deles herdar as caractersticas? - Tudo que tiver um Q na frente para Linux . No ClxAplication Tudo que for para Linux tem a palavra Q na frente e tudo que for para Windows sem o Q. No caso do nosso exemplo a aplicao para Windows. Escolha TEdit (StdCtrls). Qual o nome a ser dado para o componente? Esse nome o que vai ser dado para a classe criada.

21 Coloque o nome de TeditMaiusculo no campo Class Name, conforme figura abaixo: Palette Page Nome da paleta a ser criada: O componente pode ser criado dentro de uma paleta que j existe, ou pode ser criada sua prpria paleta. De o nome da paleta de Unilins escrevendo no campo Palette Page. (fig. 4)

Figura 4 Preenchimento das propriedades do novo componente OBS: Cada vez que criar um componente, no crie um monte de paleta, mas escolha uma paleta j criada, ou crie uma exclusiva de novos componentes e salve seus componentes nela. Para gravar essa Unit do componente criada, escolha um arquivo existente ou crie seu prprio arquivo no campo Unit file name. O local que vai ficar gravada ser dentro do Delphi 7, no diretrio Lib, vai criar um arquivo chamado EdtMaiusculo.pas, conforme mostrado: c:\arquivos de programas\borland\delphi7\Lib\EdtMaiusculo.pas Mas se quisermos escolher outro local para criar esse componente s escolher outro Path. Obs.: Na prova, voc ter que escolher outro path para salvar seu componente e transferi-lo para o disquete. Na hora que criar um componente, salve dentro do seu projeto nas pastas criadas para transferi-lo para o disquete. Para esta pasta pode ser dado o nome de componentes. J criamos uma Unit chamada EditMaiuscula no Path escolhido acima. Clique em OK. Vai ser mostrado o mdulo de programao abaixo: (fig 5)

22

Figura 5 Modulo de programao do componente. A classe TEditMaiuscula herda todas as caractersticas do TEdit pai mais algumas coisas, entre essas caractersticas, a transformao do que foi digitado para maisculo. Neste arquivo de cdigo a nova classe TEditMaiuscula, ser derivada por herana da classe TEdit, como mostrado o trecho do cdigo abaixo: type TEdtMaiusculo = class(TEdit) Foi definido ainda um procedimento chamado Register que faz uma chamada a outro procedimento denominado RegisterComponents. Este procedimento recebe como parmetro o nome da categoria da Tool Palette na qual os novos componentes sero inseridos e se a pgina no existir ento ser criada. procedure Register; begin RegisterComponents('Unilins', [TEditMaiusculo]); end; { TEditMaiusculo } Quando esta classe filha foi criada apareceu na interface os campos private, protected, public e published. Private e public j estavam na classe pai. type TEditMaiusculo = class(TEdit) private

23 { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end; Private s dentro do prprio formulrio temos acesso, mas em outro formulrio, mesmo herdada as caractersticas, no podemos ter acesso.

Num exemplo, se tivermos uma Unit1 e uma Unit2, definimos uma classe Tpessoa, uma classe que tem algo como private = varivel a do tipo integer. O que acontece? Fazendo a programao var a: integer; Isto vlido? a: = text.a isto funciona? No Considerando que a varivel a tipo integer no exista. Apesar de herdar todas as caractersticas, no vai herdar o que esta no campo private de outro formulrio. Mas para fazer com que a classe filha herde as caractersticas do pai temos que criar comandos no campo protected, isto far com que o filho herde tambm as caractersticas do pai. Se for definida no campo protected, campo T do tipo integer, no campo private no funciona, mas neste campo, sim. Se for protected, funciona dentro da prpria Unit e tambm fora dela, se forem herdadas as caractersticas exatas do mesmo pai. Como protected, se for do mesmo tipo do outro, ento pode usar as caractersticas herdadas. Published - Tudo que tiver como published o que vai aparecer no Object Inspector. 4.2.2 - Implementando o procedimento KeyPress A nova funo do KeyPress neste novo componente, quando for digitado, passara todos os caracteres para maisculo (UpCase). Esta funo j foi definida em algum lugar e para verificar a definio, veja no campo protected tudo o que pode ser modificado. No campo protected precione as teclas CTRL + barra de espao (fig. 6).

24

Figura 6 Campo protected criao de procedimentos. Ai aparecer tudo que poder ser modificado: procedure, function, todas as funes que podemos escolher para o Edit. Estes comandos (procedures) esto escritos seguidos com a funo Override, isto , pode ser substitudo. No caso, queremos trocar uma letra, o evento usado ser ento o OnKeyPress, quando for digitadas letras minsculas, elas sero trocadas para maisculas. Se for digitado OnKeyPress, aparece mensagem dizendo que um evento do tipo Keypress, mas se for digitado KeyPress, tambm existe. No Objecto Inspector tem um evento chamado onKeyPress, dando um duplo clique neste evento, ele cria um evento chamado KeyPress. OnKeyPress s o nome da propriedade e nesta propriedade est gravada o evento a ser chamado. OnKeypress uma propriedade que est armazenada no evento a ser chamado. A palavra on vem antes da propriedade que s armazena o evento a ser chamado. O evento em si no tem esta palavra (on) na frente. Ento se queremos programar um evento do Keypress, ser chamado apenas Keypress. A palavra on s uma propriedade para aparecer no Objecto Inspector. Tudo que for Published vai aparecer no objecto inspector. O nome a ser utilizado o KeyPress, que ao ser selecionado cria um procedimento chamado Override, porque poder ser substitudo/reutilizado se quisermos fazer outro procedimento KeyPress.

25 De duplo clique na procedure KeyPress selecionada o procedimento ir aparecer no campo protected onde estava o cursor. Para abrir a programao deste procedimento coloque o cursor em cima da palavra KeyPress e precione as teclas CTRL + Shift + C procedure TEditMaiusculo1.KeyPress(var Key: Char); begin inherited; end; end. A primeira linha que aparece, se chama inherited, o que isso? Significa: Execute o que tinha sido programado no Pai. Se por acaso no pai tivesse algum tratamento que precisasse ser feito, primeiro executada a programao no pai e depois executar a programao no filho para depois sair. Na programao queremos que a chave (Key) seja igual a prpria chave sendo UpCase. Queremos que essa tecla se torne maisculo. Aps colocada as linhas de programao, salve o componente e instale-o. File > Save Observe que ainda no existe a Paleta UNILINS. O comando para colocar essa paleta o procedimento que foi criado chamado Regis. Quando clicar em instalar, automaticamente executar uma procedure chamada Regis (Registro), isto far com que registre o componente criando a paleta Unilins e coloca dentro desta paleta o componente criado. Na hora que for executado, o componente TEditMaiusculo instalado na paleta Unilins. 4.2.3 - Instalando o Componente clique em component > Install Componente.

26

Figura 7 - Caixa de dialogo para instalao de componentes. Clique em OK Na caixa de dilogos abaixo pedir a confirmao da instalao.

Figura 8 Confirmao da instalao. clique em YES Na caixa de dilogos perguntar se o componentes EditMaisculo que voc quer instalar. Confirme.

Figura 9 Registro do componente. Compile clicando no boto Compile.

27

Figura 10 Pacotes de componentes. O sistema mostra mensagem dizendo que o componente foi instalado e registrado. Percorra o campo das paletas e verifique se o componente foi instalado no final. Para verificar a funcionalidade do componente, crie uma nova aplicao. File > New > Apllication. Coloque um Edit comum no formulario e o componentes EditMaiusculo criado. Compile e teste. No Edit comum podemos digitar letras tanto minsculas, quanto maisculas. No EditMaiusculo, automaticamente as letras digitadas sero transformadas em maisculas. O componente na verdade o aproveitamento de outro componente que tem muitos procedimentos. Voc aproveita alguma coisa que algum j tenha feito e cria novos procedimentos e funes que achar importante. Para compartilhar, a programao colocada no campo Protected se tiver herana entre pai e filho. Private, ningum acessa, Public todos tem acesso e Published aparece no Objecto Inspector.

At agora foi criado s um evento. Se quiser criar seu prprio evento ou Propriedade tambm d. Para criar uma propriedade no Objecto Inspector, chamada maisculo local, se for colocado True, passa para maisculo, se False deixa parecer um Edit Comum. O programador decide se deseja maisculo ou no. Teremos uma propriedade chamada maisculo, se for colocado True, passa para maisculo, se False no passa para minsculo. Criaremos uma propriedade chamada maisculo do tipo global.

28 Importante: Quando definirmos uma propriedade, temos que especificar se de leitura ou gravao, isto , se s podemos ler ou tambm modificar o campo. If maiscula = true then (faa alguma coisa), est fazendo uma comparao, e faz uma leitura. Se o valor for verdadeiro, faz a comparao e executa alguma coisa. Isto ler uma propriedade. Se quiser permitir alterar a propriedade gravao. Ento hora de definir se a permisso para s gravar, ler ou ler e gravar. Geralmente as propriedades do Objecto Inspector so como leitura e gravao, podendo consultar o que est l dentro ou alterar, mas podemos fazer uma propriedade que permita somente leitura e no consegue modificar o valor da propriedade. Neste exemplo, vamos permitir a modificao. Para permitir a leitura e a gravao, temos que ter uma varivel tipo Read e do tipo Higth. Quando falamos em propriedade, ele vai pegar a propriedade maisculo e armazenar em algum lugar. Precisamos de uma varivel interna para armazenar, porque o nome maisculo no uma varivel, mas o nome que vai aparecer no objecto Inspector e o valor do local tem que ser armazenado em algum lugar. Essa varivel tem que ser criada, do tipo boolean. Por exemplo, se tivermos uma varivel com o nome Mai e outro que vai dentro desta varivel do tipo Mai. Essa varivel que vamos ter que criar. Quando tivermos uma propriedade chamada maisculo do tipo boolean , na hora que for alterada l dentro ele vai gravar o valor dentro desta varivel chamada EMaiusculo. Se precisar gravar, grava dentro do Emaiusculo. S que temos que criar esta varivel no campo Private, porque o valor s pode ser manipulado via Objecto Inspector. Essa varivel vai existir, mas no pode ser vista e nem alterada. Somente atravs da propriedade do Objecto Inspector poder ser mudado o valor. Ateno - Toda vez que for criada uma propriedade, obrigatoriamente deve existir uma varivel para atribuir o valor e tem que ser declarado no campo Private. Foi criada a propriedade maiscula, e queremos utilizar aqui dentro, ento utilizamos Fmaiu. private { Private declarations } fmaiu: boolean;

Passamos para maisculo: se o fmaiu for True ento passamos para Maisculo. If fmaiu = true then - passa para maisculo. No campo Public precionando as Teclas CTRL + barra de espao, procure o campo Create public constructor Create(AOwner: TComponent); override; { Public declarations }

29

Coloque o cursor em cima da palavra Create e precione CTRL+SHIFT+C para criar o campo de programao do mtodo create. O campo Create, ao criar na tela o componente, executa antes de mais nada o mtodo create. Ele cria na memria tudo o que precisa e depois passa o valor da propriedade para true. No campo protected cada vez que carregar o mtodo, queremos que no create, por padro cada vez que for criado o componente na tela, essa propriedade seja True. Criado o mtodo create aps pressionadas as teclas CTRL + Shifit + C, fazemos um alterao, colocando a varivel fmaiu sendo True por padro. constructor TEditMaiusculo.Create(AOwner: TComponent); begin inherited; fmaiu:= true; end; Salve o componente. OBS: Se tentarmos executar, no vai funcionar, porque componente no se executa, componente para ser instalado. Instale o componente de novo clicando em Componente > Install Component selecionando o componente > compile novamente. Aparecer uma mensagem que o componente j existe, mas queremos que seja recompilado novamente para atualiza-lo. A programao do componente unit EditMaiusculo; interface uses SysUtils, Classes, Controls, StdCtrls; type TEditMaiusculo = class(TEdit) private { Private declarations }

30 fmaiu: boolean; protected procedure KeyPress(var Key: Char); override; { Protected declarations } public constructor Create(AOwner: TComponent); override; { Public declarations } published { Published declarations } property Maiusculo: boolean read fmaiu write fmaiu; end; procedure Register; implementation procedure Register; begin RegisterComponents('Unilins', [TEditMaiusculo]); end; { TEditMaiusculo } constructor TEditMaiusculo.Create(AOwner: TComponent); begin inherited; fmaiu:= true; end; procedure TEditMaiusculo.KeyPress(var Key: Char); begin inherited; if fmaiu = true then Key := UpCase(Key); end; end.

Para testar, feche o que est sendo feito. Abra um novo projeto e insira o componente TeditMaiusculo e um Tedit Comum. clique no componente TEditMaiusculo. No Objeto inspector verifique se a propriedade Maiscula est como True Se estiver como true porque no mtodo create colocamos a propriedade padro como True. Do jeito que est como True se for executado e digitando qualquer palavra, automaticamente ir transformar para maisculo.

31

Figura 11 Formulrio utilizando o novo componente.

Figura 12 Demonstrao da utilizao do componente instalado. Voltando na propriedade do Objeto Inspector e mudando para False, aps executar, as letras no sero convertidas para maisculas. Podemos ter uma propriedade que verifica o CPF vlido, herando do Edit se for true, criamos um procedimento checar CPF no evento onKeyPress, quando apertar o Enter, executada uma rotina, ou no OnExit , quando perder o foco. Agora podemos construir componentes com vrias funcionalidades. A vantagem que esses componentes criados ficam disponveis com vrios programas. Podemos ter um conjunto de componentes e se for preciso distribuir um componente para algum entregamos o arquivo criado que ser instalado no InstallComponente. Podemos ter uma biblioteca com vrios componentes que mais usamos. Um exemplo desse uso com Cdigo de barras, um componente que faz a leitura de cdigo de barras. Conseguimos fazer um cadastro inteiro, em minutos, ganhando tempo, usando herana na construo de componentes e formulrios.

32

4.3 - Mais um exemplo de criao de componentes


Quando foi criado o componente anterior, foi salva em uma pasta fora do delphi, mas se o componente for de uso definitivo em seus trabalhos, ento j deixe gravado no delphi. A herana feita atravs da linha de comando Inherited que faz com que seja executada a programao do componente Pai. Para criar um novo componente: Existem muitas coisas a serem trabalhadas, por exemplo, no componente Edit: trocar de cor, filtros com alguma validao (validar um componente que s recebe nmeros ou s recebe letras. 4.3.1 - Criando um componente DBEdit com mascara Clique na paleta component > New Component Escolha o componente DBEdit (TEdit (StdCtrl) salve na paleta UNILINS Salve no Path desejado no caso em sua pasta componente dentro de seu projeto. Campos Class Name : TEdtCPF Palette Page: Unilins Unit file name: Escolha o Path

Figura 13 Criao do componente TEdtCPF Clique em OK

33 A programao da Unit ser feita conforme mostrada abaixo: unit EdtCPF; interface uses SysUtils, Classes, Controls, StdCtrls; type TEdtCPF = class(TEdit) private { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end; procedure Register; implementation procedure Register; begin RegisterComponents('Unilins', [TEdtCPF]); end; end.

Foi aberta uma nova classe que no tem propriedades e nem eventos . Vai ser derivada do componente Edit normal, onde ser feita a programao. Conforme forem digitados os nmeros, contar quantos caracteres foram digitados e aps o terceiro caractere colocar um ponto. Esta mascara constituir dos seguintes campos: xxx.xxx.xxx-xx. Temos que definir como ser feita esta mascara. Conforme for digitando vai preenchendo os campos com os pontos e hfen ou digita primeiro todos os campos e depois que apertar o enter aparece a mascara com os zeros tambm preenchidos. O evento onKey Press dever ser tratado, tratar tanto com o enter e testar todo o calculo e alm disso vai ficar procurando toda hora se a quantidade digitada de zero a nove. No campo protected precione as Teclas CONTROL+BARRA DE ESPAO digite KeyPress e no combo mostrado selecione o procedimento KeyPress

34 type TEdtCPF = class(TEdit) private { Private declarations } protected procedure KeyPress(var Key: Char); override; { Protected declarations } public { Public declarations } published { Published declarations } end; Toda programao nestes campos vem seguida do comando Override isto significa que ela pode ser substituda Coloque o cursor em cima da palavra Key press e pressione as Teclas CTRL + SHIFT + C Isto far que o campo da programao abra embaixo. Esta programao vem com a linha de comando inherited, isto significa faa tudo o que est programado no pai e depois execute as linha de comandos abaixo. Se este comando for apagado o procedimento no executar as funes do Pai. procedure TEdtCPF.KeyPress(var Key: Char); begin inherited; end;

Defina para o procedimento KeyPress as linhas de comando abaixo aps a palavra inherited: procedure TEdtCPF.KeyPress(var Key: Char); begin inherited; if not (key in ['0'..'9',#8,#13]) then key :=#0; end;

35 Primeiro filtro Se a tecla no estiver dentro deste conjunto a tecla Key recebe vazio. Qualquer caractere que for digitado e que no esteja dentro do conjunto, ento apaga. Se for digitado uma letra qualquer ser apagado. Esta programao aceitar todos os caracteres de zero a nove, o backspace. Qualquer outra tecla que for digitado e no seja nenhuma destas definidas na programao, ento apaga. Segundo filtro Se for Enter gera mascara O evento doExit Na hora que o Edit perder o foco gera a mascara. Este evento doExit o que perde o foco. No campo protected - precione CTRL + barra de espao para aparecer os procedimentos. digite a palavra Exit e no combo mostrado selecione o evento DoExit. protected { Protected declarations } procedure KeyPress(var Key: Char); override; procedure DoExit; override; Coloque o cursor em cima da palavra DoExit e pressione as telas CTRL+SHIFT+C para formar o campo de programao do evento. procedure TEdtCPF.DoExit; begin inherited; end;

Neste campo temos que ter um nmero mnimo a ser digitado. - Temos que saber qual o nmero de caracteres para depois clicar em OK. - Temos que saber ainda se na digitao aparecer os caracteres da esquerda para a direita ou vice-versa. - Se for digitado um nmero errado, podemos fazer com que o campo seja apagado. OBS: No de mensagens para o usurio porque no podemos saber como est o nosso componente. O que pode ser feito, se quiser criar uma propriedade e no final, quando for perdido o foco, de a mensagem se deu certo ou no. Conforme digitamos o valor, se conseguir aplicar a mascara colocamos true. Se perdeu o foco porque foi digitado errado, colocamos false, dando uma mensagem na

36 tela. Com esta varivel possvel fazer o tratamento que quiser, porque nunca sabemos como o usurio quer tratar a interface. O campo Protected o que aparece no Object Inspector, desde que seja de leitura e gravao, porque no tem sentido aparecer no Object inspector uma propriedade que no podemos mudar. Se criarmos uma propriedade somente leitura, podemos somente ler o valor e ela no aparece no Object Inspector porque no de gravao.

READ o que define o tipo de leitura e gravao do nome que aparecer no Object Inspector. Internamente temos que trabalhar com outra varivel, no podemos trabalhar com a mesma. o nome que aparece no object inspector internamente. Geralmente temos que trabalhar com outro nome bem diferente. Crie a varivel fvalido tipo boolean dentro do campos private Criamos ento essa varivel interna dentro do campo private, porque no podemos correr o risco de algum tentar mudar alguma propriedade. private { Private declarations } //colocar a propriedade fvalido em private para no ser modificada fvalido : boolean;

A vantagem que o usurio no tem acesso direto programao, no tem como atribuir nenhum valor. Ao sair, primeiro temos que verificar a quantidade de dgitos colocados. O CPF pode ter no mnimo 8 at no mximo 11 caracteres e no podemos deixar que o numero digitado tenha mais de 11 caracteres. Se acontecer de ser digitado mais de 11 caracteres, colocamos uma mensagem que no foi possvel aplicar a mascara. Podemos usar a propriedade Length de no mximo 11 posies. Duas formas de fazer: 1- Digita-se o nmero e quando perder o foco exibe a mascara com 8 at 11 posies, ou; 2- Conforme for digitando, s vai deixar de digitar at dar 11 caracteres e se tentar digitar mais, apaga tudo. No evento onKeyPresss, implementamos at o mximo de 11 caracteres, usando a propriedade Length.

37 OBS: Em qualquer propriedade ou mtodo no coloque o nome da propriedade.<mtodo> , j coloque direto a palavra text. Ele assume que o Edit o prprio componente. procedure TEdtCPF.KeyPress(var Key: Char); begin inherited; if not (key in ['0'..'9',#8,#13]) then key :=#0; if (Length(text) >= 11) and (key <> #8) and (Key <> #13) then Key := #0; end;

Se o tamanho for >= 11 j tem 11 dgitos e entra com mais um, ento apaga, no recebe nada. Se o caractere length o KeyPress no est contando ainda. Se no tem o caractere ainda e for efetuando um KeyPress o evento chamado antes de aparecer o caractere, e no foi contado ainda. Mesmo que tiver alguns caracteres, o caractere que estiver sendo pressionado no conta neste ponto (o caractere atual) Se o tamanho estiver completo no 12 digito, apaga. Se o tamanho for maior que 11 ou diferente que o Backspace ou Enter ento apaga, com isso estamos limitando o mximo de caracteres que podem ser digitados. No procedimento doExit. Se Length (tamanho) dessa varivel for menor que 8 caracteres, a varivel fvalido recebe false e no conseguimos converter, seno fvalido recebe true (o nmero de caracteres legal), ento consegue converter. procedure TEdtCPF.DoExit; var aux : string; begin inherited; if (Length (text) < 8) then fvalido := false else begin fvalido := true; end; end;

Em uma propriedade normal qualquer, dentro do Delphi, usamos por exemplo Edt_valor.text que vai executar o comando (text) depois do ponto. No caso do componente, se colocarmos o mesmo comando descrito, pode at funcionar no componente, s que

38 depois que usurio cria um componente e muda o nome (herdando os valores), por exemplo para btn_sair, o que acontece? Mudamos o nome de programao e quando for executado o cdigo, para o boto o nome btn_sair. O Delphi verifica que no tem o btn_sair, no existe um Edt_valor. Para evitar esse problema, dentro do componente no coloque o nome, s coloque a propriedade direto. Toda vez que o delphi achar essa propriedade e no tem o nome na frente, ento assume que o prprio componente.

4.3.2 - A Mscara Tem 8 ou 11 caracteres. Se for 11 comeamos com um nmero vlido, mas se o CPF tiver 8 caracteres, preenche com zeros at completar onze caracteres. Em pascal o primeiro caractere guarda o nmero de caracteres que tem a string. O comando Length verifica quantos caracteres existem. Uma string em Pascal permite at 256 caracteres. A primeira posio a posio zero, depois em diante a seqncia determinada pela varivel. Da posio 1 at a 11 colocamos um comando for variando de 1 at Length. Esse cdigo verifica se as posies vai de 1 at 11 caracteres. Criamos uma varivel auxiliar para armazenar o valor e depois atribui-la para o campo text de Edit. procedure TEdtCPF.DoExit; var aux : string; i: integer; begin inherited; if (Length (text) < 8) then fvalido := false else begin fvalido := true; if length (text) = 8 then text := '0'+ text; {montando a mascara} for i := 1 to length do begin if i = 3 aux := aux + text[i]; end; end; end;

aux varivel auxiliar para armazenar os valores digitados.

39 Text:= 0+text este cdigo completa com zeros se o cpf tiver 8 caracteres (concatena) at 11 caracteres, depois s copiar para a varivel auxiliar de 3 em 3 caracteres. Aux:= aux + text[i] - do jeito que esta o comando coloca toda a string do aux e coloca no outro, mas no isso que queremos, ento colocamos uma condio if para cada mltiplo de 3 (if i=3), mas esta condio no coloca ponto e nem trao.

4.3.3 - SCRCOPY Comando copy. Uma linha de comando que no usa o for. Neste comando colocamos a string que queremos entre parentes. No exemplo copy(text,1,3) copiamos os trs primeiros caracteres e aps concatenamos um ponto. Neste comando podemos copiar de trs em trs blocos concatenando os pontos e o trao final. Podemos fazer uma nica linha de comando sem usar o for. copy(text,1,3)+'.'+ (a partir da primeira posio, copiamos trs campos e somamos (concatena) um ponto). copy(text,4,3)+'.'+ (a partir da quarta posio, copiamos mais trs campos e somamos (concatena) mais um ponto). copy(text,7,3)+'-'+ (a partir da stima posio, copiamos mais trs campos e somamos (concatena) um trao). copy(text,10,2); (a partir da dcima posio, copiamos mais dois campos).

text:= aux; - Aux: - Guarda a String completa. Agora jogamos aux para ser mostrada no campo Edit. OBS: Se no usarmos o comando IF, ento no precisamos da varivel i. procedure TEdtCPF.DoExit; var aux : string; begin inherited; if (Length (text) < 8) then fvalido := false else begin fvalido := true; if length (text) = 8 then text := '0'+ text; {montando a mascara} aux:= copy(text,1,3)+'.'+ copy(text,4,3)+'.'+ copy(text,7,3)+'-'+ copy(text,10,2); text:= aux; end;

40 Reinstale o componente para atualiza-lo. Install component.

Figura 14 Reinstalando o componente. Clique em ok

Figura 15 Compilando o componente. Clique em Compile para instalar. 4.3.4 Testando o Componente Dentro de um novo form, coloque um Edit comum e o EdtCPF que acabamos de criar.

41

Figura 16 Formulrio utilizando o componente criado. Compile e teste seu componente.

Figura 17 Formulrio compilado e em execuo. Se tentarmos digitar letras este componente no aceita. Aps digitar os nmeros e teclar enter (perder o foco ) ele executa a mascara, colocando pontos e trao. OBS: S podemos fazer componentes se estivermos logados como administrador, porque temos que escrever na pasta do delphi. 4.3.5 - Programao do Componente EdtCPF unit EdtCPF; interface uses SysUtils, Classes, Controls, StdCtrls; type TEdtCPF = class(TEdit) private { Private declarations } // colocar a propriedade fvalido em private para no ser modificada fvalido : boolean; protected

42 { Protected declarations } //precionar CTRL + barra de espao para aparecer os procedimentos procedure KeyPress(var Key: Char); override; procedure DoExit; override; public { Public declarations } published { Published declarations } //propriedade criada para verificar se o numero digitado esta correto property cpfvalido: boolean read fvalido; end; procedure Register; implementation procedure Register; begin RegisterComponents('Unilins', [TEdtCPF]); end; { TEdtCPF } {procedimento aparece apos efetuar CTRL+shift+ C com o cursor em cima da palavra Key Press do procedimento acima no campo protected} procedure TEdtCPF.DoExit; var aux : string; {se fizer com o comando Copy nao eh necessario usar a variavel "i"} //i : integer; begin inherited; {Ao perder o foco, gerar a mascara} if (Length (text) < 8) then fvalido := false else begin fvalido := true; // forca 11 caracteres, completando com zero if length (text) = 8 then text := '0'+ text; {montando a mascara} {for i := 1 to length do begin if i = 3 aux := aux + text[i]; end;}

43

aux:= copy(text,1,3)+'.'+ copy(text,4,3)+'.'+ copy(text,7,3)+'-'+ copy(text,10,2); text:= aux; end; end; procedure TEdtCPF.KeyPress(var Key: Char); begin inherited; //primeiro filtro : digitar somente nmeros, apagar e enter. {Se no for digitado os algarismos de 0 a 9 ou barra espao ou enter ento aparecera vazio} if not (key in ['0'..'9',#8,#13]) then key :=#0; // verificar o tamanho maximo (11 caracteres) {os dgitos podem ser colocados ate a posio 11 e eliminar os caracteres apagados com o backspace ou tecla enter} if (Length(text) >= 11) and (key <> #8) and (Key <> #13) then Key := #0; end; end.

44

5 - TEMPLATE
uma maneira de copiarmos toda uma programao sem usar uma nica linha de cdigo. Uma automatizao de tarefas. Qualquer componente que colocarmos na tela do template, no podemos depois mudar o nome. A propriedade Name vai ser fixa. O nome que forem colocados para os botes, tabelas tem que serem genricos

5.1 - Um template simples.


Podemos fazer um formulrio com alguns componentes e programa-los como um form padrao. Ento salvamos dentro do delphi numa pasta chamada Template ou outro nome que voc quiser. Dentro do Delphi criamos um arquivo chamado U_Cadastro (nosso formulrio de cadastro padro). Salve o formulrio em uma pasta qualquer, o importante estar salvo par evitar que se perca. ento salve na pasta alunos Trocamos o nome do formulrio para Frm_CadPad. No caption coloque um nome genrico (Cadastro de...) para que possa ser completado nos formulrios criados a partir deste. Coloque trs botes com o nome primeiro, anterior e prximo com desenhos. Um DataSourse e uma Table Mude o nome do Botes, para Btn_Primeiro, Btn_Anterior e Btn_Proximo em caption. Coloque o nome da table Tbl_Mster. Nome do DataSourse associado Ds_Mster. Associe a Tbl_Mster ao DS_Mster. Na tabela, no foi preenchido o Databasename e nem o TableName ento no est funcionando.

A tela ficar com o aspecto mostrado abaixo:

45

Figura 18 Visualizao do formulrio Template

Programando os botes Programe o boto - duplo clique em cada boto para entrar no modulo de programao. procedure TFrm_CadPad.Btn_primeiroClick(Sender: TObject); begin tbl_master.First; end; procedure TFrm_CadPad.Btn_AnteriorClick(Sender: TObject); begin tbl_master.Prior; end; procedure TFrm_CadPad.Btn_ProximoClick(Sender: TObject); begin tbl_master.Next; end; Salve o formulrio Para salvar o formulrio como template clicamos o boto direito do mouse em cima do formulrio e em Add to Repository Em Title coloque o nome do formulrio que vai aparecer, no exemplo: Cadastro

46 Em Page (paleta) - pode ser escolhida uma que j existe ou digitar o nome de sua pasta no exemplo coloque o nome Unilins. Pode ser colocado um cone para simbolizar o template.

Figura 19 Caixa de dilogo para adicionar Template em um repositrio. Clique em OK

Figura 20 Confirmao para salvar o Template. Confirme. A partir de agora este template est gravado no sistema.

5.2 Abrindo um novo projeto atravs do template


Para abrir um novo projeto e usarmos esta aplicao para completar um cadastro: File > New > Other > procure a paleta chamada Unilins criada o formulrio criado deve estar l dentro

47

Figura 21 Formulrio de Novos Itens Para criar outro cadastro coloque a opo de inherit (faa uma herana) e clique em OK. Foi criado um novo formulrio com o nome de Frm_CadPad2, herdando as caractersticas do form Frm_CadPad.

Figura 22 Formulrio aberto atravs de um Template.

48

Figura 23 Programao do formulrio aberto atravs de um Template. No foi programado nada no formulrio, pois ele j herda toda a programao do formulrio pai. Neste formulrio efetuada uma herana, isto , executa a programao que tinha no formulrio padro Observe a palavra inherited. A partir da criao do novo formulrio selecionamos uma tabela na Tbl_Master, podemos criar outros botes, adicionar procedimentos. Para adicionar outros componentes em todos os formulrios, podemos abrir o template e acionar no formulrio padro que vai aparecer em todos os formulrios criados a partir deste. Isto til num sistema que tem muitos formulrios, podemos efetuar no template uma alterao de programao que far com que todos os formulrios que herdam suas caractersticas tambm faam esta programao. A vantagem que se tivermos um template de cadastro, podemos fazer um cadastro completo em alguns minutos usando a herana.

49

6 CDIGO DE BARRAS
Na aula anterior foram construdos componentes para serem testados. No foi includo algoritmos para no ficarem pesados. A inteno foi s para testar componente, porque daqui para frente teremos que criar um componente novo, quer seja componente para trabalhar com cdigo de barras, para impressora fiscal, etc. A idia da disciplina que saibamos o que um componente. A cada componente teremos que colocar peculiaridades novas.

6.1 - Surgimento do cdigo de barras


A idia do cdigo de barras velha, de 1973/75. A necessidade do cdigo de barras foi devido ao crescimento das vendas. Antes os produtos eram vendidos digitando um cdigo e o preo. Era um tipo de cdigo interno e para um novo produto, era gerado um novo cdigo interno e este fixado no produto. Cada vez que tinha um novo produto, era necessrio inclu-lo no cadastro. Esses produtos eram nicos, no existia uma uniformidade de dados. Ao passar pelo caixa, era preciso digitar o cdigo e o preo. O problema e as conseqncias eram filas longas e a demora e muitas vezes o cdigo e o preo poderiam ser digitados errados.

6.2 - Cdigo de barras do tipo UPC


O Cdigo de Produto Universal (UPC) foi a primeira simbologia de cdigo de barras adotada para comrcio. Foi criado em 3 de abril de 1973, nos Estados Unidos, quando a indstria de carnes instituiu oficialmente o cdigo UPC como o cdigo de barras padro para marcar seus produtos. Interesses estrangeiros no cdigo UPC levaram ao desenvolvimento e adoo de um cdigo similar, o cdigo EAN, em dezembro de 1976. O cdigo UPC Americano composto de 12 dgitos. Usado nos Estados Unidos e no Canad. Somente so usados os campos cdigo da empresa e o cdigo do produto, no tem o cdigo do pas. A partir de 1977, surgiu a Empresa EAN, um grupo que fez a padronizao dos cdigos de barra. Essa padronizao no nova. O inicio foi dado pelos Estados Unidos em 1973. Aps 1977, a EAN difundiu sua padronizao para o mundo inteiro e o padro mundial hoje ditado por ela. A empresa EAN foi criada na Europa e estabeleceu o padro utilizado no mundo todo. A Associao Brasileira de Automao Comercial foi criada em 1994 e atualmente utiliza o nome EAN Brasil. Como os Estados Unidos j tinha seu padro UPC, a EAN difundiu seu cdigo para o restante do mundo, mas hoje os produtos dos Estados Unidos j usam cdigos EAN.

50

6.3 - Os tipos de cdigos EAN


Existem vrios tipos de codificao EAN, as principais delas so EAN8, EAN13 e AN14, que so usadas no front de caixa. Outros cdigos como o EAN12, EAN128, no so usados no front de caixa. A maioria dos leitores de cdigo de barras no consegue ler o EAN12 e EAN128, necessrio um leitor especifico. O cdigo EAN128 exige um leitor a laser. O leitor padro o leitor modelo CCD manual (com gatilho) que consiste num equipamento com um bocal que emite luz proveniente de um conjunto de LEDs. Para fazer a leitura necessrio encostar o bocal do leitor no cdigo de barras. Essa luz ento refletida por um conjunto de lentes at um circuito integrado sensvel luz, semelhante a clulas fotoeltricas, que capta a imagem do cdigo de barras. Os leitores a laser requerem uma certa distancia da barra, como o caso dos leitores usados em supermercados. Para os cdigos EAN128 existem aparelhos especficos para fazer a leitura porque o alcance tem que ser maior. O EAN128 geralmente usado em grandes volumes. O leitor de cdigo de barras normalmente usado em conjunto com o teclado. No h diferena na programao, seja para os leitores de cdigos comuns (front de caixa) e leitores a laser que requerem uma distncia para efetuar leitura. Os hardwares so usados para a mesma funo - ler cdigos de barras. Quando passamos o leitor em cima do cdigo de barras a mesma coisa que digitar o valor no teclado.

6.4 - O Padro EAN


EAN-8 EAN-13 EAN-14 EAN-128 tem 9 dgitos. tem 13 dgitos. tem 14 dgitos. um caso particular

O EAN-8 usado para embalagens pequenas mas este cdigo em relao ao preo muito caro em termos de custos. O padro utilizado na grande maioria dos produtos expostos venda o EAN-13.(fig 24).

6.5 - Definio do cdigo


O cdigo EAN definido da seguinte forma: - uma margem branca para comear o cdigo a partir dele - uma margem sem nenhuma numerao.

Figura 24 Exemplo de cdigo EAN-13

51 - um cdigo de incio. Aps isso localiza o primeiro cdigo que o numero 6. Este numero indica o inicio da leitura e no est representado numericamente para no confundir na digitalizao. No meio do cdigo tem outro nmero 6 e no final tem outro numero para finalizar a String e saber que foi feita a leitura inteira do cdigo. Quanto compra de um cdigo de barras necessrio entrar em contado com a EAN Brasil, filiar-se empresa e obter o cdigo. O taxa de uso paga anualmente e mais a filiao pela primeira vez.

6.6 - O funcionamento do cdigo de barra


O cdigo de barras um smbolo composto de barras paralelas de largura e espaamento variveis. Depende muito da variao do espaamento para produzir um cdigo diferente. Os padres mais importantes so: EAN-8, EAN-13, EAN-14, EAN-128, o UPC americano, o 2 de 5 e o 3 de 9 A leitura das barras feita da direita para a esquerda. Quando a luz incide no cdigo, tudo que for branco ou refletir luz ser interpretado como digito 1 e as barras que no emitirem luz sero interpretadas como digito 0. Esta codificao feita em bit. Utilizadas para gerenciamento do controle de Estoque, principalmente quando se tem um volume muito grande de dados. No sistema financeiro, na parte de caixa, pagamento de bancos. Ao utilizar o cdigo de barras no necessria a etiquetao de produto a produto. Antes eram usados o cdigo do produto e o preo e muitas vezes quando o preo do produto era alterado, tinha que ser alterado na gndola o preo das etiquetas. Na utilizao do cdigo de barras podemos controlar qualquer alterao de preo diretamente no caixa. Geralmente no se troca o preo no perodo de funcionamento de uma empresa, mas sim durante noite.

6.7 - A representao dos campos do cdigo EAN


Os trs primeiros dgitos do cdigo EAN representa o pais, por exemplo o Brasil o 789 e cada pas tem um nmero codificado. Com isso podemos saber a origem de determinado produto. OBS: O cdigo do pas necessariamente no indica que a origem do produto seja daquele pas, mas sim registrado. Os prximos quatro ou cinco dgitos representam o cdigo da empresa. Neste caso existem dois tipos de cdigo de barras - um de 4 e outro de 5 dgitos que representam a empresa. Exemplo: uma empresa como a Nestl que tem uma linha de produtos muito grande registrou no Brasil com o cdigo 789 (do pas). Quatro dgitos para representar a empresa e

52 cinco dgitos para representar o produto (numa representao de at 100.000 produtos) que so comeados pelo 0 at 99.999 unidades. Ao comprar um cdigo de barras com 5 dgitos para a empresa, permitimos para o cdigo do produto uma faixa de at 9.999 unidades (10.000 produtos). Se o cdigo de barras conter 5 dgitos para a empresa, permitimos que o cdigo do produto v at 9.999 unidades. Se ocupar mais espao para o cdigo da empresa sobra menos espao para o cdigo do produto. O cdigo que usa somente quatro dgitos para o cdigo da empresa o mais caro e geralmente comea com o nmero 1. Se o cdigo comea com um (1) ento uma das empresa que pode ir at 99.999 cdigos para representar os produtos. Por ltimo, temos o digito verificador que confirma se o nmero da barra foi lido corretamente. As barras das extremidades e central so iguais e obrigatrias em todos os cdigos. Margem de Silncio - o espao em branco antes de comear o cdigo que contm os dados. Se tiver uma margem escura ou um quadro antes de comear as barras, aqueles so interpretados como se fizessem parte do cdigo, ento para evitar isso necessrio um espao em branco antes de comear o cdigo - a margem de silencio. As combinaes de corres. Os Cdigos de Barras tem que ter as combinaes de corres corretas: Barra Preto Azul Escuro Marrom Verde Escuro Fundo Branco Amarelo Vermelho Rosa

e e e e

No funcionam as combinaes de cores de cdigo fora do padro especificado pela EAN. O ideal para um cdigo de barras a impresso de barras pretas em fundo branco. Margem clara, caractere que representa o incio (seis caracteres para codificar tabela A ou B, o cdigo da empresa representada por 4 ou 5 caracteres, o caractere central, 4 ou 5 caracteres que representam o cdigo do produto, o digito verificador e por ltimo o caractere de guarda que ao final indica que terminou o cdigo de barras. A compra do cdigo de barras fornecida com o cdigo do pas e o cdigo da empresa, a numerao correspondente ao produto gerada pela prpria empresa, seqencial para cada produto. Para cada produto, um novo cdigo.

53 Se uma empresa comprar outra empresa, ter que manter o cdigo da empresa comprada (o cdigo de barras) porque ainda existem produtos dessa empresa expostos venda em estabelecimentos comerciais que ainda no foram vendidos ao consumidor final.

6.8 - Durao do Cdigo de barras.


O cdigo de barras de um produto que teve sua fabricao suspensa, no pode ser reutilizado para outro produto. Exemplo: A reutilizao do cdigo de barras para produtos comestveis em media de um a dois anos para permitir que o estoque venda seja esgotado. Para os produtos no comestveis, pelo menos cinco anos. Quando terminar o perodo, podemos reutilizar o cdigo mas necessrio informar s empresas consumidoras que o produto referente quele cdigo no existe mais e foi reutilizado para outro produto, assim essas empresas podem atualizar o cadastro referente a esse cdigo de barras em seu sistema (banco de dados). O prazo de cinco anos necessrio para manter durante esse tempo um arquivo fiscal de tudo que foi vendido na empresa. Se tiver um produto que foi modificado, por exemplo a frmula, contedo, embalagem, etc, ter que ser gerado um novo nmero. Pode acontecer de ser colocado uma quantidade a mais e grtis numa embalagem, ento no necessrio trocar o cdigo do produto, porque no est sendo cobrado esse contedo a mais.

6.9 - Cdigo de barras do tipo EAN8


O cdigo de barras do tipo EAN8 foi desenvolvido a partir do EAN13. Na verdade ele uma verso compacta do EAN13 visando embalagens pequenas, como cigarros, caixa de fsforos, lpis, canetas, etc. A diferena para o EAN13 est no mtodo de codificao e no menor nmero de caracteres de dados. Neste formato no existe o cdigo do fabricante, s tem o cdigo do pas, o cdigo do produto e o digito verificador. Veja no exemplo abaixo como o cdigo de barras EAN8 bem menor que o EAN13: Exemplo: Para o EAN13 tem o seguinte cdigo:

789 4401 00004 1 Figura 25 Exemplo de cdigo de barras EAN-13

7894401000041 789 4401 00004 1

o cdigo completo cdigo do pas - Brasil cdigo do fabricante cdigo do produto dgito verificador

54

Para codificar a mesma fita utilizando o cdigo EAN8, o smbolo gerado ficaria bem mais compacto. Exemplo abaixo:

789 0004 1

Figura 26 Exemplo de cdigo de barras EAN-8 789 0004 1 789 0004 1 o cdigo completo cdigo do pas - Brasil cdigo do produto dgito verificador

O cdigo que identifica o fabricante omitido e o cdigo do produto fica com quatro casas em vez de cinco. Com isto o cdigo utilizado fica com oito dgitos em vez de treze. O smbolo gerado fica mais compacto. Quando for necessrio usar o cdigo EAN-8, compra-se um nico cdigo, individualmente. S existem 10.000 cdigos disponveis pela EAN que verificar antes de tudo se no possvel colocar um cdigo EAN-13.

6.10 - Cdigo ISBN


(International Standard Book Number) impressos em livros. Tornou-se padro na identificao internacional de livros. um padro de 13 dgitos tambm, com trs dgitos iniciais identificando que o produto se trata de um livro (978 ou 979), seguido da numerao ISBN (nove dgitos) e o dgito de verificao.

6.11 - Cdigo ESSN


Cdigo serial para publicaes de peridicos Comea com 977 e depois o nmero do peridico. No precisa fazer o controle de qual o pas.

6.12 - Cdigo EAN-14


Usado para serem usados em embalagem que contm mais de uma unidade. O EAN-14 o mesmo EAN-13 com um dgito a mais no incio. Os 13 dgitos do prprio cdigo e o dgito a mais representa de que forma esta sendo vendido o produto, representa a quantidade no lote.Ex: 1 Embalagem com 6 unidades. 2 Embalagem com 12 unidades. 3 Embalagem com 24 unidades. Esse cdigo permite vender produtos em lote com at 9 tipos de quantidade. Sua localizao padro geralmente em embalagem de plstico em cima desta embalagem.

55

6.13 - Cdigo de uso interno


Para venda de produtos, por exemplo hortifrutigranjeiros e aougues. Todo cdigo de uso interno tambm tem 13 dgitos. A diferena est no primeiro dgito: - Sempre comea com 2 uso interno reservado. - O prximo dgito indica o tipo de cobrana a ser feito se por peso ou por preo. Por exemplo: 0 para peso e 1 para preo. - Depois o cdigo do produto com 5 dgitos para especificar o produto. - Mais cinco dgitos para representar a quantidade ou o peso. - E o digito verificador. Quando o produto vendido por peso, o peso mximo que podemos vender 99.999 gramas (100 quilos). Para o cdigo do produto 100.000 produtos disponveis. Se for vendido por preo, o processo o mesmo, o que muda o segundo dgito que representa o preo. O valor mximo que podemos representar R$ 999,99 reais. Geralmente os aougues trabalham com preo. Se um produto muda muito o preo, por exemplo, produtos importados, geralmente usamos colocar o peso, porque s alterar no sistema o peso e no preciso remarcar o cdigo de barras. Produtos que no so vendidos com facilidade podem ter seu cdigo de barras colocados por preo.

6.14 - Localizao do Cdigo de barras


A etiqueta ou impresso do cdigo de barras colocada de preferncia e seguindo uma padronizao no canto esquerdo ou direito inferior. - Produtos na promoo: Se for vendida duas unidades na promoo necessrio embala-las numa nica unidade para colocar outro cdigo de barras, para que as barras das unidades no fiquem expostas com o risco de serem lidas ao passar pelo caixa.

6.15 - Calculo do digito verificador no EAN-13.


Como calcular o ltimo nmero que analisa se o cdigo esta certo ou errado? Vamos tomar por base o cdigo de nmero: 7 8 9 1 0 1 0 2 2 0 0 9 789 1010 22009 nmero que representa o Brasil. representa o fabricante representa o produto

Obs: O nmero 22009, no significa que tem 22.000 produtos porque pode ser que um ou mais produtos saiam de linha e no permitido usar esses cdigos enquanto no vencer o prazo estabelecido em Lei. O calculo do dgito verificador feito da seguinte forma neste cdigo: Numere cada caractere do cdigo, da esquerda para a direita.

56 Ex: 7 13 8 12 9 11 1 10 0 9 1 8 0 7 2 6 2 5 0 4 0 3 9 2 ? 1

1) - Soma-se todos os nmeros que esto nas posies mpares a partir da posio 3: 0 + 2 + 0 + 0 + 9 + 7 = 18 2) - Soma-se todas as posies pares: 9 + 0 + 2 + 1 + 1 + 8 = 21 3) - O nmero que foi obtido no passo 2 (pares) deve ser multiplicado por 3: 21 X 3 = 63 4) - Soma-se o valor do passo 1 (18) com o valor do numero obtido no passo 3 (63): 18 + 63 = 81 5) - Obtenha o mltiplo de 10 maior que o nmero do passo 4 (81) Mltiplo de 10 > 81 = 90 6) - Faa a subtrao do numero obtido (90) do numero do passo 4 (81): 90 - 81 = 9 O numero 9 o dgito verificador do cdigo acima.

O cdigo de barras representa os dgitos binrios 0 e 1, determinados pela espessura das barras. Cada barra preta ou branca representa um nico dgito. J existem componentes que geram o cdigo de barras. A impresso ideal de cdigo de barras feita em impressora laser. No cdigo EAN 128 pode ser codificadas letras que permita colocar a descrio do produto, por exemplo. Nos Estados Unidos temos um microship em teste para ser usado no lugar do cdigo de barras. A inveno atende pelo nome de Radio Frequency Identification (RFID), que em portugus significa "Identificao por Radiofreqncia". Dentro de pouco tempo, esta tecnologia ser to familiar quanto o prprio carrinho de supermercado. Alm disso, estar presente em uma infinidade de produtos, de pizzas congeladas e refrigerantes a CDs e televisores. A RFID, que est cada vez mais difundida, se caracteriza por um microcircuito eletrnico que armazena informaes sobre todos os tipos de objetos, e at de animais. Permite, alm

57 disso, a localizao destes em poucos segundos, e a transmisso de seus dados a um dispositivo receptor situado a poucos metros ou a vrios quilmetros de distncia.

6.16 - Criao de componente para fazer leitura do cdigo de barras


Clique na barra Component > New Component No campo Ancestor type escolha o TEdt (StdCtrls) conforme figura abaixo: No campo Class Name (Nome da classe) coloque TCodigoDeBarras. Em Palette Page coloque Unilins. Em Unit file name: Coloque o diretrio a ser salvo. Geralmente no diretrio por voc criado ou se for usa-lo definitivamente pode deixar na pasta LIB.

Figura 27 Caixa de dilogos para criao de novo componente. Aps criado > clique em OK Depois de criado aparecer o cdigo da unit abaixo: (fig. 28)

58

Figura 28 Cdigo de programao do componente CodigoDeBarras. Classe TcodigoDeBarras derivado de TEdit 6.16.1 - Programando as propriedades A primeira propriedade a ser feita o evento OnKeyPress. Dentro do evento protected clique em CTRL + Barra de espao para abrir a caixa de dilogos abaixo > selecione o evento KeyPress. (fig.29).

Figura 29 Procedimento para seleo do evento KeyPress. Vai aparecer o procedimento KeyPress abaixo com a declarao override:

59

protected { Protected declarations } procedure KeyPress(var Key: Char); override; Coloque o cursor em cima de KeyPress e pressione as teclas CTRL+SHIFT+C que criar o procedimento na ultima linha da unit, conforme mostra abaixo: procedure TCodigoDeBarras.KeyPress(var Key: Char); begin inherited; end; end.

Alm do evento KeyPress temos que criar uma propriedade que retorna o cdigo, outra que retorna se deu certo ou no e qual o tipo de cdigo se EAN-13, EAN-14, interno, etc. Precisamos de trs propriedades, todas elas somente de leitura. No campo published criamos trs propriedades Published { Published declarations } property codigo:string read fcod; {codigo lido}
Esta propriedade no pode ser do tipo inteiro porque o numero muito grande e o inteiro s vai at 32.000 O nome da varivel interna vai se chamar fcod

property valido:boolean read fval; {valido ou nao}


Esta propriedade indica de deu certo ou no tambm de leitura

property gtipo:integer read ftipo; {EAN13,EAN14,8 OU ITERNO}


Esta propriedade retorna o tipo.

Colocamos mais trs propriedades: property medida:boolean read fmed;

{peso(true) ou preo(false)}

Se for colocado o preo por quilo, pode ser inteiro e trabalhamos todas as medidas em gramas

property peso:real read fpeso ; {peso do produto} property preco:real read fpreco ; {preco do produto} end; Agora precisamos criar as variveis. Como so todas de uso interno do componente, criamos no campo private:

60

{ Private declarations } fcod:string; fval:boolean; ftipo:integer; fmed:boolean; fpeso:real; fpreco:real;

Temos que efetuar trs tratamentos: Digito verificador, tipo de cdigo se EAN-8, EAN13,EAN14 e se de uso Interno ou Externo. Para no ficar repetindo os mesmos comandos, criamos uma rotina extra para fazer o calculo do dgito verificador. Entramos com o valor de uma string e esta rotina verifica se esta correto ou no: Esta rotina ser criada no campo private para que no se tenha acesso a ela. Private { Private declarations } fcod:string; fval:boolen; ftipo:integer; fmed:boolean; fpeso:real; fpreco:real; function verifica(cod:string):boolean; {verifica o dv}

Esta funco retorna se foi lido o cdigo corretamente. Coloque o cursor em cima da palavra verifica e pressione CRTL+SHIFT+C: function TCodigoDeBarras.verifica(cod: string): boolean; var i:integer; vpar,vimpar,vtot:integer; begin end;

No colocaremos o comando overhide porque teoricamente no permitiremos que o usurio modifique os comandos, principalmente porque ele o usurio nem tem acesso a esse Edit.

61

O algoritmo: {1 soma as posies impares 2 soma as pares 3 multiplica-as por 3 4 soma o resultado da multiplicao com a soma das pares 5 subtrai o total do prximo mltiplo de 10 }

function TCodigoDeBarras.verifica(cod: string): boolean; var i:integer; vpar,vimpar,vtot:integer; begin {1 soma as posioes impares 2 soma as pares 3 multiplica as por 3 4 soma a multiplicaao com as pares 5 subtrai do proximo multiplo de 10 }
Zerar as variaveis vpar, vimpar e vtot.

vpar:=0; vimpar:=0; vtot:=0; for i:=length(cod)-1 downto 1 do begin


Verificamos se o campo par ou impar

if (i mod 2)=0 then Se for par, a varivel vpar recebe o prprio valor do campo mais o caractere daquela posio (cd(i)); begin {par} vpar:=vpar+strtoint(cod[i]); end else {impar} begin vimpar:=vimpar+strtoint(cod[i]); end;
Se o valor for impar o mesmo procedimento acima realizado. Detalhe: Tanto faz se for feita a multiplicao por 3 da varivel vpar antes ou depois do lao. Se for colocada a multiplicao dentro do lao, para cada lao que for realizado efetuada a multiplicao, ento fora do lao ganha um pouco de desempenho.

vtot:=vpar*3 + vimpar;

62

J temos o total, falta descobrir o mltiplo de dez maior que o vtot. Temos duas opes de calculo: Ou procuramos at achar o mltiplo que queremos, ou pegamos o numero da varivel vtot e calculamos o mod 10. Depois comparamos se igual ao digito verificador. O cdigo uma string e queremos comparar dois nmeros inteiros, ento convertemos.

if (10 -(vtot mod 10)mod 10)=strtoint(cod[length(cod)]) then


Se o digito verificador for correto ento retorna a rotina verifica = true.

verifica:=true else
Se deu errado retorna a rotina verifica = false

verifica:=false; end; end;

A funo Verifica s para confirmar o digito verificador, declarada no campo private para o usurio no ter acesso a ela. Esta funo de uso interno. Retorna True ou False com a funo de validar o cdigo de barras . J temos o tratamento do cdigo verificador. Se os cdigos forem iguais, verifica recebe true, caso contrrio retorna false. 6.16.2 - Programao do Procedimento KeyPress procedure TCodigoBarras.KeyPress(var Key: Char); begin inherited; {tratamento do cdigo de barras. Necessitamos realizar o tratamento do:} - digito verificador - tipo de cdigo se 14,13,8 etc... - se interno ou externo}
Este if verifica se foi pressionada a tecla ENTER. Se for enter ento inicia toda a investigao

if not (Key in[0..9,#8) and (key<>#13]) then Key:= #0; if(length(text) >= 4) and (key <> #8) and (key <> #13) then Key:= #0; if Key = #13 then begin {verificar se valido}
Primeiro temos que verificar se o dgito vlido ou no

Fval:= verifica (text); {verifica o tipo}


Para verificar se o tipo vlido ou no, temos que usar a propriedade chamada valido que retorna true ou

63
false.. A propriedade fval recebe a funo verifica, passando a string digitada e verifica se falso ou no. Depois verifica o tipo do cdigo Caso Length (tamanho) for do tamanho do tipo 14, 13,8 ento fara alguma coisa. A propriedade chamada ftipo se for 14 ftipo recebe 14. Pode ser usada o comando Case para cada tipo independente se do tipo 13, 14, etc.

case Length(text) of 14: ftipo:= 14; 13: begin {verifica se um cdigo de uso interno. Isto s possvel se a empresa utilizar o EAN13 e o cdigo de barras iniciar com 2} if text[1]= '2' then begin {uso interno} ftipo:= 2; {apos verificar o primeiro digito e descobrir que de uso interno, temos que verificar se o calculo ser realizado por peso ou por preo. Para tal, basta olhar o contedo do 2 digito} {0 = preo ou 1 = peso} Fmed:= ('1' = text[2]); {copiar o cdigo do produto} Fcod := Copy(text,3,5); { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text,8,5))/1000; end else begin fpreco:= strtofloat(Copy(text,8,5))/100; end; end else ftipo:= 13; end; 8: ftipo:= 8; end; end; end;

64 Agora vamos ver qual o cdigo que est sendo usado, se 14, 13, 8 ou de uso interno. Para verificar o tipo de cdigo usamos o Length (tamanho). Antes, temos que determinar se a tecla pressionada o enter atravs do comando if. Se for pressionado enter entra no comando case if Key = #13 then begin end; Determinar se um digito vlido ou no verificao do tipo. Fval:= verifica (text); Esta validao feita atravs da rotina verifica e passamos como parmetro a String digitada que ser valida ou no. Para verificar se o cdigo de uso interno temos que certificar se o cdigo o EAN-13 e o cdigo de barras inicia com 2. if text[1]= '2' then begin {uso interno} ftipo:= 2; S podemos usar internamente o cdigo EAN-13 legalmente que comea com 2. Fazemos o tratamento do cdigo s quando for o EAN-13, porque no da para tratar o uso interno de outros cdigos (nem do EAN-8 e nem do EAN-14). 6.16.3 - O tratamento do cdigo EAN-13 para uso interno. Primeiro temos que saber se comea com o nmero 2. if text[1]= '2' then begin Se o caractere na primeira posio for o 2 ento de uso interno ento ftipo recebe 2, ftipo:= 2; Para verificar se o cdigo por preo ou por peso, temos que ler o segundo digito. Apos verificar o primeiro digito e descobrir que de uso interno, temos que verificar se o calculo ser realizado por peso ou por preo. Para tal, basta olhar o contedo do segundo digito: 0 = preo 1 = peso Esta definio de preo ou peso no tem padronizao. Existe uma propriedade que define se por preo ou por peso. H duas maneiras de estabelecer esta condio:

65 1 por peso (fmed:= true) - se 1 for igual a text na posio 2 estabelece a condio direto. Estamos comparando se o contedo na posio 2 for igual a 1(que por peso) ento atribumos true para fmed, caso contrario atribui false. 2 Se a segunda posio for igual a 1 fmed recebe true seno fmed recebe false esta condio ficar como comentrio na programao mas tambm funciona. Ns temos 4 tipos de cdigos e temos que descobrir qual o tipo se EAN8, 13, 14, interno. O EAN 13 composto de: 1 Tipo 2 Cd. 0 ou 1 3 Cdigo Produto 4 Preo ou Peso 5 Dig. Verificador

Posies: 1 Se de uso interno ou no. Se de uso interno comea pelo numero 2. 2 Cdigo 0 ou 1 se por preo ou por peso. 3 Cdigo do Produto. 4 Preo ou peso do produto. 5 Digito Verificador. Tanto faz se o campo 4 for por preo ou peso, o cdigo do produto ser o mesmo. O preo ter duas casas decimais representando os centavos. O peso ter trs casas decimais representando a medida de peso em gramas.

Fcod foi copiado para dentro do campo. Se for por peso (fmed:= true). Nota: No precisamos colocar (se for = true) porque um cdigo booleano e retorna true ou false. Fazemos a cpia do cdigo atravs do comando Copy. {copiar o cdigo do produto} Fcod := Copy(text,3,5);

Depois temos que copiar o valor - Para copiar o valor comparamos o fmed. Se fmed for true, a medida por peso. Se for por peso temos que transformar em valor.. Ex.: Se tivermos 10 K e 200g podemos copiar o numero 10 e concatenar com 200. Isso vai dar 10.200g. Ao salvar transformamos em float. (strtofloat - convertendo em dinheiro).

66 Ou Fazemos a leitura de todos os dgitos de uma nica vez (10.200) e dividimos por 1000 que dar os 10.200g.

Se por peso, o fpeso recebe a string que acabamos de copiar. Ela comea na oitava posio e copia cinco caracteres. Como string temos que transformar em numero (strtofloat). Aps transformar em nmero dividimos por 1000. { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text,8,5))/1000; end Com isso conseguimos transformar o peso em gramas else begin fpreco:= strtofloat(Copy(text,8,5))/100; end;

Para o preo, como utilizado com duas casas decimais, dividimos por 100 Se for por peso dividimos por 1000. Se for por preo dividimos por 100. O cdigo: Exemplo (2 0 08100 00071 4) como de uso interno vai armazenar os cinco dgitos do cdigo do produto (08100). Ento quando for feito um comando LooKup, este comando para o cdigo e localiza o produto especifico daquele cdigo. if text[1]= '2' then begin {uso interno} ftipo:= 2; Se aparecer o campo 2 de uso interno l o prximo campo Nota: Quando o cdigo de uso externo fazemos a busca pelo cdigo inteiro, mas quando de uso interno, temos que destrinchar o cdigo. Ento quando efetuamos uma busca, no passamos o text como parmetro, mas sim o cdigo do produto (o campo especifico do cdigo).

67 A propriedade cdigo (property codigo) que retorna o cdigo de barras tem que ser atribudo no comeo no campo published porque independente de qual seja, por padro, o cdigo de barras o que est na propriedade teste, o que foi digitado. Ento se for digitado 789101000001 8, por exemplo, esta linha um text que ser atribudo por padro. Ento por padro o cdigo igual ao text (Fcod = text) Quando for de uso interno comeo com o nmero 2 depois 0 ou 1 (dependendo se por preo ou peso), depois 5 digitos do cdigo do produto (12345) e cinco dgitos que indica o valor (55532). Se for por peso ser 55 quilos e 532 gramas. Se for por preo ser R$ 555,32. E por ltimo o dgito verificador. Como para todos os cdigos 12, 13, 14 tanto faz, colocamos Fcod recebe text (Fcod = text). Estamos atribuindo varivel Fcod o valor de text para depois descartar quando no mais precisar. Para esse cdigo que ser feita busca no banco de dados, por padro , vamos pegar todos os dgitos com exeo quando for de uso interno, que ser substitudo. Se valido ou no, calcula o digito verificador. O tipo j est sendo atribudo. Para um deles atribudo o tipo, no caso do 13 est faltando atribuir qual o tipo. O cdigo de barras est pronto.

6.17 - Programao da Unit CodigoDeBarras


unit CodigoDeBarras; interface uses SysUtils, Classes, Controls, StdCtrls; type TCodigoDeBarras = class(TEdit) private { Private declarations } fcod:string; fval:boolean; ftipo:integer; fmed:boolean; fpeso:real; fpreco:real; function verifica(cod:string):boolean; {verifica o dv} protected { Protected declarations } procedure KeyPress(var Key: Char); override;

68
public { Public declarations } published { Published declarations } property codigo:string read fcod; {codigo lido} property valido:boolean read fval; {valido ou nao} property gtipo:integer read ftipo; {EAN13,EAN14,8 OU ITERNO} property medida:boolean read fmed; {peso(true) ou preo(false)} property peso:real read fpeso ; {peso do produto} property preco:real read fpreco ; {preco do produto} end; procedure Register; implementation procedure Register; begin RegisterComponents('unilins', [TCodigoDeBarras]); end; { TcodigoDeBarras } procedure TCodigoDeBarras.KeyPress(var Key: Char); begin inherited; {tratamento do codigo de barras} //digito verificador //tipo de codigo se 14,13,8 etc... // se interno ou no if not (Key in[0..9,#8) and (key<>#13]) then Key:= #0; if(length(text) >= 4) and (key <> #8) and (key <> #13) then Key:= #0; if Key = #13 then begin {verificar se valido} Fval:= verifica (text); {verifica o tipo} case Length(text) of 14: ftipo:= 14; 13: begin {verifica se um cdigo de uso interno. Isto s possvel se a empresa utilizar o EAN13 e o cdigo de barras iniciar com 2} if text[1]= '2' then begin {uso interno} ftipo:= 2; {apos verificar o primeiro digito e descobrir que de uso interno, temos que verificar se o calculo ser realizado por peso ou por preo. Para tal, basta olhar o contedo do 2 digito} {0 = preo ou 1 = peso} Fmed:= ('1' = text[2]);

69

{copiar o cdigo do produto} Fcod := Copy(text,3,5); { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text,8,5))/1000; end else begin fpreco:= strtofloat(Copy(text,8,5))/100; end; end else ftipo:= 13; end; 8: ftipo:= 8; end; end; end; {realiza o calculo do dv verificador} function TCodigoDeBarras.verifica(cod: string): boolean; var i:integer; vpar,vimpar,vtot:integer; begin {1 soma as posioes impares 2 soma as pares 3 multiplica as por 3 4 soma a mulptiplicaao com as pares 5 subtrai do proximo multiplo de 10 } vpar:=0; vimpar:=0; vtot:=0; for i:=length(cod)-1 downto 1 do begin if (i mod 2)=0 then begin {par} vpar:=vpar+strtoint(cod[i]); end else {impar} begin vimpar:=vimpar+strtoint(cod[i]); end; end; vtot:=vpar*3 + vimpar; if (10 -(vtot mod 10)mod 10)=strtoint(cod[length(cod)]) then verifica:=true else verifica:=false; end; end.

70

O mesmo cdigo com algumas variaes.


unit EdtCodigoBarras; interface uses SysUtils, Classes, Controls, StdCtrls; type TEdtCodigoBarras = class(TEdit) private { Private declarations } fcod: string; fval: boolean; ftipo: integer; fmed: boolean; fpeso: real; fpreco: real; fvalido: boolean; function verifica(cod:string):boolean; {para confirmar o digito verificador} protected { Protected declarations } procedure KeyPress(var Key: Char); override; procedure DoExit; override; procedure Change; override; public { Public declarations } published { Published declarations } property codigo: string read fcod;{codigo que foi lido} property valido: boolean read fval; {codigo valido ou nao} property codtipo: integer read ftipo; {codigo EAN13,14,interno,externo} property medida: boolean read fmed; {preo(false) peso(true)} property peso: real read fpeso; {peso do produto} property preco: real read fpreco; {preco do produto} end; procedure Register; implementation procedure Register; begin RegisterComponents('Samples', [TEdtCodigoBarras]); end; { TEdtCodigoBarras } procedure TEdtCodigoBarras.Change; begin inherited; end;

71

procedure TEdtCodigoBarras.DoExit; begin inherited; if(Length(text)<1) then fvalido:=false else begin fvalido:= true; if length(text) = 1 then text:= '0'+text; end; end; procedure TEdtCodigoBarras.KeyPress(var Key: Char); begin inherited; {tratamento do codigo de barras} //digito verificador //tipo de codigo se 14,13,8 etc... // se interno ou no if not (key in['0'..'9',#8,#13])then Key:= #0; if (length(text)>=4)and(key<>#8)and(key<>#13) then Key:= #0; if Key = #13 then begin {verificar se e valido} Fval:= verifica (text); {verifica o tipo} case Length(text) of 14: ftipo:= 14; 13: begin {verifica se e um codigo de uso interno. Isto so e possivel se a empresa utilizar o EAN13 e o codigo de barras iniciar com 2} if text[1]= '2' then begin {uso interno} ftipo:= 2; {apos verificar o primeiro digito e descobrir que e de uso interno, temos que verificar se o calculo sera realizado por peso ou por preco. Para tal, basta olhar o conteudo do 2 digito} {0 = preco 1 = peso} Fmed:= ('1' = text[2]); {copiar o codigo do produto} Fcod := Copy(text,3,5); { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text,8,5))/1000; end else begin fpreco:= strtofloat(Copy(text,8,5))/100; end; end else ftipo:= 13; end;

72
8: ftipo:= 8; end; end; end; function TEdtCodigoBarras.verifica(cod: string): boolean; var i:integer; intpar, intimpar, inttot: integer;

{1 soma as posioes impares 2 soma as pares 3 multiplica as por 3 4 soma a mulptiplicaao com as pares 5 subtrai do proximo multiplo de 10 }
begin intpar:= 0; intimpar:= 0; inttot:= 0; for i:= length(cod)-1 downto 1 do begin if (i mod 2)=0 then {verifica se o campo e par ou impar} {se for par, a variavel intpar recebe o proprio valor do cmpo mais o caractere daquela posicao(cod[i])} begin //par intpar:= intpar + StrToInt(cod[i]); end else //impar {se o valor for ompar o mesmo procedimento acima e realizado} begin intimpar:= intimpar + StrToInt(cod[i]); end; inttot:= intpar * 3 + intimpar; if(10-(inttot mod 10)mod 10)= StrToInt(cod[length(cod)]) then {se o digito verificador for correto ento retorna a rotina verifica = true} verifica:= true else {se deu errado retorna a rotina verifica = false} verifica:= false; end; end; end.

16.18 - Exerccio:
Faa um componente que na propriedade cdigo retorne o valor a ser localizado no banco de dados. Aps isso criar um sistema de vendas usando esse componente que realiza a busca do produto e calcule o valor a pagar, independente se o cdigo for por preo ou por peso de uso interno ou externo Detalhe: quando digitar o cdigo de barra e apertar enter, ter que ser feita a validade, por padro ser o 1 do item 2 abaixo. Quando for digitado o valor e apertar enter, j l o cdigo, verifica o cdigo, faz a busca, faz o insert na tabela de itens, preenche o cdigo do produto,

73 preenche a descrio, preenche a quantidade, faz o calculo do valor se for por peso e calcula o total. 1 - Quando for de uso interno fazer a verificao. 2 Se for por preo ou peso- cdigo 0 ou 1. 3 Cinco dgitos que indica o cdigo do produto. 4 Cinco dgitos que indica o valor. 5 O digito verificador. 1 digito 1 digito 5 digitos 5 digitos 1 digito

Para uso externo s verifica se o cdigo esta correto atravs do digito verificador.

6.19 - Utilizando o cdigo de barras


Abrir componente > install component Selecione o cdigo de barras no esquea de salvar. depois manda instalar. Recompile para alterar o que j existia.

O sistema d um aviso que o valor Vtotal no usado e isso no tem nenhum problema para o exemplo. Em cada tela, cada vez que for chamado, o componente inserido e comandado um Free depois. O componente est no cdigo de barras. Abra um novo sistema, pode ser usado um j criado em aulas anteriores um sistema de vendas para mostrar como utilizar o componente. Neste sistema o usurio seleciona um novo item (produto) pela descrio, o valor e a quantidade. Coloque o componente de cdigo de barras no sistema. Ser digitado o valor e o cdigo de barras est com Enter automtico. No evento OnKeyPress ser executado todo o tratamento quando for digitado o Enter, quando o tipo for igual a 13. Se tipo for igual a 13 ento verifica de de uso interno. Para fazer a busca no banco de dados, fazer na tabela de itens. Quando for escolhido o tipo 13 que o Enter confirmando. Por padro a quantidade ser 1(um). Neste sistema no d para vender por peso porque no d para fazer abaixo de 1,5 e a tabela foi criada como tipo inteiro no campo quantidade.

74

Ter que ser preenchida a quantidade do produto vendida. Temos que fazer um locate localizar o cdigo do produto. O valor que tem que ser buscado. Em que local est o cdigo de barras a ser localizado. Se for de 5 dgitos vai buscar na tabela de cinco dgitos, se for de oito busca na tabela de 8 dgitos e assim por diante. Como cdigo pode deixar em branco. Quando for dado o comando Locate, cada vez que digitar o cdigo, o sistema tenta localizar o cdigo que foi passado (todo o tratamento que foi efetuado dentro do banco de dados). Se for encontrado ser atribudo para dentro do cdigo do produto. Para fazer essa atribuio faa: Tbl_Prod.FieldBbyName(Cod_Prod). Estamos procurando o cdigo dentro do banco de dados. Quantidade, cdigo, descrio automtica e fica faltando s o preo que tirado da tabela de produtos. O preo do campo Valor_prod do tipo real. Cabe um comando if para verificar se do tipo 2 (uso interno). Se for de uso interno temos uma opo que o preo que j vai estar inserido dentro. Em vez de buscar no banco de dados, buscamos direto no componente. if (codbarra1.gtipo=2) then begin if (codbarra1.medida = True) then begin No exemplo desse componente, esse banco de dados no d para tratar esse caso porque o campo do banco de dados esta como tipo inteiro, ento temos que atribuir direto o valor que est guardado no banco porque este no est preparado para outro valor. Na hora que digitar o valor no ser buscado no cdigo de barras, mas sim o que tiver cadastrado no banco de dados. O ideal colocar um comando If, um tratamento, se for por tipo 2, se for por preo, ai em vez de atribuir o preo, recebe direto o valor que est no cdigo de barras. Se for por peso, vai no banco de dados, por exemplo: o peso digitado 50 que multiplicado pelo valor que esta no banco de dados para depois jogar o valor no campo. Ento teria que colocar um comando If. o trabalho que ter que ser feito. Preencheria todos os campos e depois salva com o comando Post. Depois de feita essas execues, coloque a seguinte linha de comando: Tbl_Itens.Post. Esse comando salva no banco de dados.

75

V novamente no cdigo de barras, depois que inserir o valor limpa o campo cdigo de barras. Cada vez que passar o item, insere, limpa e da um SetFocus. Ento vai ficar rodando sem parar at terminar a venda.. Ento, digitando o cdigo de barras, deveria procurar pelo mesmo na tabela de produtos, s que nesta tabela no tem um campo chamado cdigo de barras. Somente para exemplificar, digitamos um produto que j existe, produto 1,2,3. Se fosse 13 dgitos iria fazer a mesma coisa. Talvez no funcione, porque no mnimo oito. O leitor de cdigos leu o cdigo 2 e apertou enter. Toda vez que pressionar enter executado os comandos do cdigo de barras. O cdigo vai estar pronto, e j ter um valor la dentro, da insert na tabela, preenche todos os dados, d Locate para aquele cdigo que esta digitado, j faz todo o tratamento, j tem cinco dgitos, o nmero do tipo necessrio, da Locate e pega os demais dados do sistema. o jeito de usar o cdigo de barras. Vamos imaginar que o usurio digita o 2 e tecla enter (deu violao de chave) Vai mostrar na tabela o valor escolhido (cdigo de barras). Teoricamente se for digitado o cdigo de barras, por exemplo 789010010 depois o cdigo 345, ele tem que encontrar esse cdigo, s que no foi mostrado nenhum valor, se tentar localizar do jeito que est o componente, no localiza nada, est vazio. No funcionou o cdigo. Primeiro vai executar aquela programao do cdigo de barras e no final ele acha o nmero (a herana) e executa essa herana. Verificando como fica agora, tem o cdigo de barras, ento o usurio vai digitar um numero qualquer e clica enter. Primeiro ele faz a verificao para depois trazer o valor. Toda vez que tiver que executar o cdigo do cliente, colocamos o comando If, mas se primeiro tiver que fazer uma programao antes de executar aquele rotina temos que colocar ele antes. Agora s digitar o cdigo, fazer o Locate no banco de dados. A programao a mesma para fazer o exerccio. Esta a parte final da criao de componentes. Gerar cdigo de barras no preocupao, existem muitas ferramentas para isso. Quando comprar uma numerao, provavelmente ter uma numerao 789 que o cdigo do pais, aps adquirir o cdigo da empresa por exemplo a empresa 1010. Esses nmeros so comprados, os demais nmeros so gerados seqencialmente (0001, 0002, 0003, etc.) e mais o dgito verificador.

76 O nmero de uso interno gerado colocando-se o cdigo de uso interno (2), o tipo (0 ou 1) depois o cdigo do produto armazenado no banco de dados (ex: 00012). Vamos supor que o zero seja para preo. O preo obtido no cadastro de produtos (por unidade ou kilo). Supomos que a laranja seja vendida por quilo a R$ 10,00 reais. O cliente compra meio quilo, ento divide-se o peso comprado pelo peso que 1 quilo e multiplica-se pelo valor (0,5 * 10,00 = R$ 5,00). Na gerao do cdigo de barras vai completar com zeros (00500) e por ultimo o digito verificador que ser calculado pelo sistema gerando supostamente o cdigo 20001200500-7. Existem muitos componentes prontos na internet para gerar etiquetas com cdigos de barras. No trabalho permitido deletar itens, o usurio colocou um item na compra e o cliente no quer mais o produto, ento permitido excluir o item. O leitor l e j da o comando Insert, Post, limpa e posiciona novamente para a prxima leitura. Se quiser pode opcionalmente colocar um Edit com o nmero 1 (um). Esse Edit por padro tem o numero um, mas se quiser passar 10 itens, vai no Edit, coloca o valor 10 e faz a leitura do cdigo de barras. O sistema multiplica pele quantidade 10, salva o dez no banco de dados e o Edit volta para a posio 1. Break esse comando para uma rotina e desconsidera as linhas de baixo.

6.20 - Exemplo de programao de procedimento usando o componente de cdigo de barras


procedure TForm1.codbarra1KeyPress(Sender: TObject; var Key: Char); var cod_barra:string; //contm o nmero do cdigo de barra valor:real; //contm o valor do produto achou:string; //valida dados do banco ListaItem:TListItem; //contm uma lista de itens comprados total:real; begin if key = 'q' then begin key:=#0; codbarra1.Text:=''; Edit2.SetFocus; end; if key =#13 then begin libera_valor:=true; achou:=''; cod_barra:=codbarra1.codigo; //Validando se o produto est cadastrado no banco de dados if (cod_barra <> '')and (codbarra1.valido=true) then

77
begin try tbl_produto.Active:=false; cod_barra:=''+cod_barra+''; tbl_produto.DataSet.CommandText:='select * from produtos where prod_cod = '+cod_barra; tbl_produto.Active:=true; achou:=tbl_produto.fieldByName('prod_cod').AsString; except codbarra1.SetFocus; end; end else ShowMessage('CDIGO DE BARRA INVLIDO!!!!!');

if (achou <> '') then //Produto localizado no Banco. begin // qtd automatica se o usuario nao digitar nada if Edit2.Text='' then Edit2.Text:='1'; //Contador de itens inseridos conta:=conta+1; // controla o insert na tbl_pedido if controle then begin tbl_codigo.Active:=true; aux1:=tbl_codigoMAX.AsInteger+1; //Busca o ltimo cdigo inserido num_cupom:=aux1; if aux1=0 then //Controle se no houver pedidos no banco aux1:=1; tbl_pedido.Open; tbl_pedido.Insert; tbl_pedido.FieldByName('ped_cod').AsInteger:=aux1; controle:=false; tbl_pedido.post; tbl_pedido.ApplyUpdates(0); tbl_pedido.Close; vl_tot:=0; end; // calculo do valor do produto por peso ou preo if (codbarra1.gtipo=2) then begin if (codbarra1.medida = True) then begin tbl_busca_val.Active:=false; tbl_busca_val.DataSet.CommandText:='select prod_valor from produtos where prod_cod = '+achou; tbl_busca_val.Active:=true; valor:=codbarra1.peso*tbl_busca_val.FieldByName('prod_valor').AsFloat;

78
libera_valor:=false; end else begin libera_valor:=false; valor:=codbarra1.preco; end; end; // controle da busca do valor produto se o mesmo ja no foi localizado acima if libera_valor=true then begin // busca valor do produto tbl_busca_val.Active:=false; tbl_busca_val.DataSet.CommandText:='select prod_valor from produtos where prod_cod = '+achou; tbl_busca_val.Active:=true; valor:=tbl_busca_val.FieldByName('prod_valor').AsFloat; end; //grava dados na tabela de itens de acordo com o pedido tbl_itens.Open; tbl_itens.Insert; tbl_itens.FieldByName('ped_cod').AsInteger:=aux1; tbl_itens.FieldByName('prod_cod').AsString:=achou; tbl_itens.FieldByName('qtd').AsFloat:=strtofloat(Edit2.Text); tbl_itens.FieldByName('conta').AsInteger:=conta; tbl_itensIT_VALOR.AsFloat:= strtoint(Edit2.text)*valor; total:=tbl_itensIT_VALOR.AsFloat;

// salva na tbl_itens tbl_itens.Post; tbl_itens.ApplyUpdates(0); tbl_itens.Close; vl_tot:=vl_tot+total; edt_total.Text:=floattostr(vl_tot); //===================== layout da lista de itens =========================== //Montando a nota fiscal no ListView ListaItem:= ListViewNota.Items.Add; ListaItem.Caption:=inttostr(conta); ListaItem.SubItems.add(codbarra1.Text); ListaItem.SubItems.Add(edt_descricao.Text); ListaItem.SubItems.Add(Edit2.Text); ListaItem.SubItems.Add(edt_valor.Text); ListaItem.SubItems.Add(Floattostr(strtoint(Edit2.text)*valor)); codbarra1.Text:=''; //============================================================================= end else begin ShowMessage('PRODUTO NO LOCALIZADO!!!!!!'); codbarra1.Text:=''; end; end;

end;

79

7 DESINSTALAO DE COMPONENTES
As vezes deparamos com um componente que foi instalado e esse componente no funciona corretamente ou queremos substitui-lo. Por exemplo: temos um componente de Cdigo de Barras que no funciona corretamente e queremos desinstalar. Clique Component > Install Component

Figura 30 Caixa de Instalao de componentes. necessrio dar um nome <qualquer.ps> s para aparecer a tela abaixo: Essa tela necessria para que possamos retirar o componente desejado, no exemplo o CdigoDeBarras.

Figura 31 Pacotes de componentes.

80

Selecione o arquivo que vai ser removido (fig.31) e clique no boto Remove. Selecione novamente o arquivo e clique em Ok, conforme mostrado abaixo:

Figura 32 Remoo de componentes. Selecione o componente CodigoDeBarras e clique em OK. (fig.32). O sistema pergunta se quer remover o arquivo

Figura 33 Caixa de confirmao de remoo de componentes. Clique em YES. No tendo mais o componente CodigoDeBarras instalado, mande compilar e note que o componente j sumiu da paleta. Se remover os componentes existentes dentro de uma paleta, essa paleta tambm apagada. Isso para as paletas que o usurio criar, portanto tome cuidado para no remover outros componentes. Se for instalada uma paleta no Delphi e no foi voc que criou, de terceiros, geralmente vai estar em Package (pacotes). O pacote tambm pode ser removido. Para isso v no Install Pakage e se tiver um dos pacotes que esteja dando problemas, pode ser selecionado para remover, isso remove a paleta inteira.

81

Figura 34 Opes de Projetos. Quando criado componente individualmente, ele estar relacionado no Package (pacote). Se for uma paleta inteira (de terceiros) v no InstallPackage e tira a paleta selecionando-a e remova-a. Para saber qual a paleta em Install Package aparece os nomes das paletas. Clique no boto Components. Por exemplo: paleta BDE, o que a paleta BDE? Se clicar no componente aparece a listagem dela (DataBase, Query, etc).

82

Figura 35 Relao de componentes de uma paleta. Ateno: Se ocultar algum componente, se escolher essa opo, ser difcil achar o conponente oculto, portanto no invente de ocultar um componente.

83

8 CRIAO AUTOMTICA DE FORMULRIOS.


Muitas vezes, em grandes projetos, imagine que um sistema tem 100 telas diferentes e ao executar esse projeto, essas 100 telas sero criadas na memria do seu computador e no sero todas usadas, fazendo que ocupe um espao muito grande. Para exemplificar, abra um projeto qualquer no sistema. As telas esto no sistema, o formulrio foi salvo como tela de cadastro de clientes (U_Cad_Cli), Frm_Cad_Cli (no importam os nomes). Temos um formulrio qualquer e queremos mostrar esse formulrio, executando o comando: Frm_Cad_Cli.Showmodal;

Figura 36 Tela de um projeto. A tela acima abre outra tela (formulrio) para cadastrar o cliente, clicando no menu Cadastro e depois no sub-menu Clientes. Ento vamos supor que temos 100 telas neste sistema.

84

Figura 37 Tela de Cadastro de Clientes. Se abrirmos a tela Project Options for.... ,esta tela e as outras do sistema estaro como sendo AutoCreate. AutoCreate significa que as telas sero criadas na memria quando mandar executar, mesmo que a tela no seja usada nenhuma vez. Clique em Project > Options O sistema abre a tela abaixo, relacionando no campo Auto_create forms as telas que sero criadas automaticamente.

85

Figura 38 Opes de projeto para o sistema. Por exemplo: podemos ter uma tela bsica como configurao do sistema que s o administrador tem acesso, por padro ele no vai estar no menu para abertura da tela, mas s dentro do sistema. Como ela est como Auto-create, vai ser criada na memria e vai ocupar espao e toda vez que rodar o executvel, tudo que estiver nesta lista alocada espao na memria e deixa pronto. Quando o sistema executado, a criao das telas rpida, s que o sistema demora mais para dar But porque primeiro tem que criar todos aqueles arquivos na memria para depois rodar ocupando espao. Isso no bom para um sistema muito grande, um problema, principalmente para um PC muito simples que tem pouca memria. Esse PC no vai executar esse sistema podendo aparecer a mensagem: Feche um ou mais aplicativo e tente novamente. Para evitar esse tipo de problema, podemos fazer algumas funes: Clique em Control + F12

86

Figura 39 Tela de Units de um projeto. Aparece a listagem de tudo o que tem disponvel, todos os formulrios, e um deles o projeto, por exemplo PSistema. Abrindo o arquivo de projeto PSistema no exemplo.

Figura 40 Tela de projeto de um sistema. Quando esse arquivo aberto, mostrada uma listagem de todos os formulrios que sero criados, ocupando memria entre o espao begin.......end.

87 Para que um formulrio no ocupe a memria, selecione esse formulrio, por exemplo o cadastro de clientes do sistema, a linha de comando Application.CreateForm(TfrmClientes, frmClientes); Aps selecionar clique em Control + X. Ao fazer isso, esse formulrio no vai ser criado na memria, pelo menos no na hora que o sistema estiver rodando. O sistema vai rodar sem criar o formulrio. S que agora se o comando Showmodal for executado do jeito que est na programao, na hora que for executado o comando Show, o formulrio no existe na memria porque foi tirada a criao dele e na hora que for clicado para chamar , dar erro tentando abrir um formulrio que no existe na memria. Para resolver tal situao, antes de dar ShowModal, mande criar o formulrio atravs da linha de comando que foi tirada do arquivo de projeto. procedure TFrmPrincipal.Clientes1Click(Sender: TObject); begin Application.CreateForm(TfrmClientes, frmClientes); frmClientes.ShowModal; end; Cada vez que for chamar a tela, antes chama o formulrio e cria na memria. Para criar o formulrio na memria: Application.CreateForm (que o formulrio que est criando na ela) depois passa qual o tipo de formulrio (TfrmClientes) e o nome (frmClientes), geralmente o nome e o tipo so iguais, s usa o T na frente no tipo. Ento o tipo e depois indicamos o nome da varivel que queremos abrir. Colocamos o nome do aplicativo que queremos rodar, chamamos a tela. Se deixar do jeito que est, o sistema cria na memria a tela e se chamar essa tela dez vezes, dez vezes ela ser criada na memria, ento fica pior ainda. O nico jeito de liberar a tela da memria colocar o comando Free na seguinte linha de comando: procedure TFrmPrincipal.Clientes1Click(Sender: TObject); begin Application.CreateForm(TfrmClientes, frmClientes); frmClientes.ShowModal; frmClientes.Free; end; Criamos o formulrio que mostrado na tela e depois libera (limpa a memria).

88 Esse jeito funciona no cadastro de clientes do exemplo, terminou, fechou e libera. Primeira forma: colocamos o Free na programao mostrado acima. Se colocar s o comando Show em vez de Showmodal, acontece que quando chamamos o cadastro de clientes ele s aparece momentaneamente e depois desaparece, porque quando executa o Show ele mostra o formulrio e j executa a linha de baixo ( o comando Free) e finaliza a execuo. Modal chama o formulrio, fica executando e s vai para a prxima linha quando fechar o form, ai ele executa a linha de baixo. Toda vez que tiver um comando Modal, quer dizer que o comando vai ser executado, formulrio mostrado na tela e s quando for fechado, ser executado a linha de baixo: o comando Free. Mas se quiser colocar o comando Show, retire o comando Free colocado anteriormente no formulrio principal e no formulrio que est sendo usado no caso FrmClientes v no evento onClose do formulrio. procedure TFrmClientes.FormClose(Sender: TObject; var Action: TCloseAction); begin action:=caFree; end; OnClose do formulrio tem um parmetro chamado Action (ao). Neste evento informe que a ao ser free (Action recebe caFree). A programao do formulrio principal que vai chamar o formulario de clientes ficara conforme abaixo sem o comando Modal: procedure TFrmPrincipal.Clientes1Click(Sender: TObject); begin Application.CreateForm(TfrmClientes, frmClientes); frmClientes.show; end; Cada vez que for fechar o formulrio libera automaticamente a memria. Mesmo que executar o comando Show o formulrio mostrado e na hora que fechar libera a memria. Qual a diferena? Se for usado ShowModal, colocamos o comando Free logo em seguida porque s vai executar o comando free quando fechar a tela. Se usar Show, obrigatoriamente temos que colocar na condio de quando for fechar o formulrio recebe action := caFree.

89 Em resumo Dentro do Principal, aquela programao da linha do formulrio do sistema que voc no quer, coloca ela antes do ShowModal. <nome do formulrio.Free> se for Modal. Se no for modal, coloca um Show comum e no evento OnClose do formulrio faa com que Action receba caFree. Obs: Use o comando CTRL + X para cortar a linha de programao e CTRL + C para colar essa linha no local desejado. Isso evita de errar ao digitar a linha de programao. Esses comandos so interessantes nas aplicaes porque gasta pouca memria. Na maioria dos sistemas, no so usadas todas as telas. Nos PCs antigos a capacidade de memria o equivalente a todas as telas abertas ao mesmo tempo. Em sistemas quando tem muitos banco de dados, ao criar as telas tambm abre os bancos de dados, ficando um monte de conexes abertas ligadas a bancos e o sistema fica carregado e lento.

8.1 - O comando Destroy


Se fizermos um teste substituindo o caFree pelo comando Destroy, na execuo, aparentemente far a mesma coisa. A diferena entre o comando free e Destroy a seguinte: Free: antes de apagar ele verifica se existe o arquivo na memria, ento libera. Destroy: Acha um bloco de memria do mesmo tamanho, no verifica e apaga. Vamos supor que existe o comando Free, ento vai apagar da memria o arquivo solicitado. Se executar um Destroy esse comando acha um pedao de bloco de memria do mesmo tamanho e apaga o que tiver l dentro. S que o que pode estar dentro desse bloco pode ser um pedao do Windows, do Delphi, da aplicao. Simplesmente apaga e no pergunta se est sendo usado o aplicativo. A prpria Borland recomenda no usar o Destroy. O Free foi construdo em cima do Destroy que a classe pai.

90

9 - DLL
DLL (Dynamic Link Libraries) Bibliotecas de vinculao dinmica. Uma DLL um arquivo executvel com vrias rotinas. Dentro de uma DLL vamos encontrar um monte de rotinas, um monte de procedimentos e funes que pode ser compartilhada com outros procedimentos do sistema. A grande vantagem da DLL o fato dela compartilhar dados. Ex: Temos dois programas na memria, um programa feito em Delphi e outro em C e precisamos comunicar um com o outro. Atravs dos Forms um programa em cada, podemos usar uma DLL para fazer essa comunicao desses processos ou acessar uma rotina que s vezes a linguagem no permite. Vamos supor que temos um bom componente que faz a compactao, mas o form no tem nada parecido para fazer compactao de dados, para isso podemos deixar dentro de uma DLL a origem da compactao. Outro exemplo: Temos um programa A e um programa B, diferentes. As vezes algumas rotinas so comuns para os dois programas: abrir arquivo, imprimir, calculo de uma funo matemtica. Quando uma rotina carregada na memria ao ser chamada pelos dois programas, essa rotina se duplicar ocupando espao nesta memria. O ideal criar uma nica cpia da rotina na memria e quando for chamada por outro programa, no vai criar uma segunda cpia, seria igual a uma Unit. O programa A poderia ser feito em Delphi e o programa B em linguagem C, VB, etc. rodando a mesma rotina uma rotina que serve para qualquer sistema de desenvolvimento. Pode-se ento perder um tempo maior, desenvolver todas as rotinas que so mais usadas e deixar dentro de uma DLL e quando utilizada, vai criar uma nica cpia na memria comunicando-se com vrios sistemas. Ao ativar uma DLL, num primeiro momento ela no fica na memria, no carregada. O primeiro sistema que chamar a DLL, carrega-a na memria ( por isso que dinmica) , roda e quando terminar de usar, sai da memria no ocupando espao. Se um programa j tiver chamado a DLL e outro sistema tambm chamar essa mesma DLL (rodando em paralelo), quando um dos programas terminar a execuo, teoricamente fecharia e apagaria a DLL da memria, s que o Windows verificando que a DLL ainda est sendo usada, espera o outro programa terminar, ai ento tira a DLL da memria. Em uma DLL, podemos ter rotinas, formulrios, pode ser programado um sistema inteiro. Vamos supor que temos um sistema para fazer a converso de imagens, uma rotina. O que fazer? Colocamos essa rotina inteira dentro da DLL, um sistema com telas. Cada vez que for necessrio, chamamos essa tela, executa, faz o que precisa e volta para o sistema que a chamou. Todo sistema de programao que trabalha com Windows, enxerga a DLL.

91 A DLL compilada num arquivo exe e na hora da compilao, gera um executvel. No h diferena entre uma DLL e um exe, dentro a mesma coisa, a programao igual, a diferena o cabealho quando o exe indica que ser executado do comeo ao fim seqencialmente. A DLL no faz isso, porque tem vrias rotinas. O exe, na primeira linha j executa, a DLL tem que procurar as rotinas. Se estiver sendo executadas na mesma memria, ele compartilha dados com outro, por exemplo: se tiver um sistema em Visual Basic e outro em Delphi e queremos comunicar os dois sistemas de alguma forma, pode ser feito via DLL. Cada vez que precisar passar um parmetro, colocamos um valor nessa DLL e depois pedimos para carregar para Leitura, uma maneira de comunicao. Cada vez que precisar de duas aplicaes diferentes, podemos usar uma DLL. Se precisar compartilhar um cdigo em uma empresa que usa dois sistemas, um feito em oracle e outro feito em Delphi. Vamos supor que em sistema, tem alguma rotina que faz um calculo complexo e muito utilizada. Podemos colocar essa rotina dentro de uma DLL. Tanto o programa em pascal, quanto o programa em form (do oracle) tambm vai usar. Se necessrio fazer uma atualizao no sistema, essa atualizao feita somente dentro da DLL. Em vez de criar um componente, podemos programar dentro de uma DLL, um programa que calcula o cdigo de barras, programao de uma calculadora, enfim um sistema inteiro dentro de uma DLL. Podemos ter uma DLL com as principais rotinas que queremos trabalhar, chamando s a rotina que deseja (inserir, editar, imprimir, etc). Toda a programao fica dentro da DLL. A vantagem a manuteno depois. Para dois sistemas diferentes que utiliza essa DLL s fazer a manuteno dentro da DLL que os dois sistemas ficam atualizados. No recomendvel colocar um banco de dados dentro de uma DLL. O calculo do banco de dados um calculo externo. Cada vez que abrir uma instancia da tabela, separada uma da outra, para o sistema seria como duas tabelas independentes. Quando abre, a tabela aberta localmente, ento complicado compartilhar dados pela tabela. Pode compartilhar dados com o valor de uma varivel, mas tabela complicado.

9.1 - Problemas com a DLL


1 2 Se apagar a DLL, o sistema no funciona, e aparece uma mensagem de DLL no encontrada. O sistema fica incompleto. - A DLL fica armazenada ou no diretrio que fica o executvel (exe) ou no diretrio System do Windows (System32).

O Windows procura primeiro a DLL no diretrio do executvel (onde fica o arquivo exe) e se no achar ento procura dentro das pastas do Windows.

92 3 A DLL s roda dentro da prpria mquina. Se tiver rodando em rede e tiver que atualizar o sistema, ter que ser atualizada em todas as mquinas.

Para solucionar esse problema usada o Web Service, uma DLL que roda em rede. Essa DLL alocada num servidor e quando chamada, sua execuo ocorre dentro desse servidor. Funciona como multiplataforma do mesmo jeito de uma DLL comum, o que necessrio a conexo com o servidor. A vantagem a manuteno que pode ser feita uma nica vez no servidor e o desempenho depende da rede. O Web Service roda em cima de um mdulo chamado Swap, um protocolo. Ele cria um servidor e s fornece servios. Acessa uma porta da mquina, chama a rotina e executa dentro da DLL. Para programar uma DLL preciso algumas regras: - Ela precisa estar listada na clausula exports da DLL, Isto torna a rotina visvel para o mundo exterior. - As funes exportadas tambm devem estar declaradas como stdcall para usar a tcnica de passagem de parmetros padro do Win32 em vez de passagem de parmetros de registro otimizado (que o padro do Delphi. Tambm pode ser usada outra conveno de chamada, desde que o outro compilador a entenda (como cdecl, que o padro em compiladores C). - Outros tipos de parmetros de uma DLL devem ser os tipos-padro do Windows (em sua maior parte tipos de dados compatveis com a linguagem C). - Uma DLL pode usar dados globais que no sero compartilhados pelos aplicativos que esto fazendo a chamada. Sempre que um aplicativo carrega uma DLL, ela armazena os dados globais da DLL em seu prprio espao de endereamento. - As biblioteclas do Delphi devem capturar todas as excees internas, a menos que pretenda usar a biblioteca apenas em outros programas em Delphi.

9.2 - Como construir uma DLL


Execute o seguinte procedimento: File > New > Other > DLL Wizard

93

Figura 41 Caixa de projetos Novos itens. Clique em OK Aparecer o Form mostrado abaixo:

Figura 42 Programao inicial de uma DLL A primeira coisa a ser feita aps abrir o formulrio da DLL salvar: Crie uma pasta com o nome DLL dentro da pasta alunos Dentro da pasta DLL crie outra chamada DllOperaes.

94 Salve o projeto File > Save as Pasta DLL > Pasta DllOperaes > nome DllOperaoes Note que no esta sendo colocada a extenso no nome do arquivo e se reparar o formato da DLL Project e no uma UNIT. - O project aquele que gera um executvel, a DLL na verdade um executvel especial. Agora necessrio colocar os procedimentos (as rotinas compartilhadas). Antes do smbolo ($R *.res) colocamos os procedimentos usados na programao. Neste espao teremos as rotinas compartilhadas. No comeo do programa a DLL e as rotinas tem que serem especificadas para utilizao e liberadas no sistema. Pode ter 100 rotinas mas se for especificada 5, s essas cinco sero liberadas.

9.3 - Programao das rotinas


Como exemplo, vamos construir uma DLL para fazer as operaes de soma e dividir. Ateno: A rotina criada em uma DLL diferente, e Casesensitive no nome da rotina porque herda da linguagem C e grava no formato C de programao. Passamos para essa rotina dois parmetros A e B e essa funo vai retornar em real. Queremos disponibilizar outra forma e colocamos o comando stdcall na frente da funo: STDCALL - usa a tcnica de passagem de parmetros padro do Win32 em vez de passagem de parmetros de registro otimizado. Temos que definir se queremos deixar ou no esta rotina visvel para o mundo externo. Quando trabalhamos com componentes, para deixar uma rotina visvel , declaramos no campo Public, protected ou published e quando no queremos que essa rotina seja visvel, declaramos no campo Private. No DLL no tem os campos Private, public, mas se quisermos que a rotina seja vista externamente temos que acrescentar um commando chamado Export e se esse comando no for colocado frente da declarao, essa rotina no visvel para o exterior. Aps a declarao USES e antes do smbolo ($R *.res) coloque as seguintes linhas de comando para a funo soma: function soma(A,B:real):real; stdcall; export; begin soma := (A+B);

95 end; Agora criamos a rotina para a diviso: function divisao (A,B:real):real, stdcall; export; begin divisao := A/B; end; Para que no fique s dividindo um numero pelo outro, podemos fazer um tratamento, comparando se o segundo elemento igual a zero. Se B for igual a zero, ento a diviso recebe zero. Altere as linhas de comando da function diviso: function divisao (A,B:real):real, stdcall; export; begin if (B=0) then divisao := 0 else divisao := A/B; end; Por questo de compatibilidade, depois de terminada a rotina antes do ultimo begin...end, faa o seguinte: Deve ser gerada uma funo Export + nome da rotina + ndice. {$R *.res} exports soma index 0; exports divisao index 1: begin end. Este comando exports colocado no final da programao diferente do comando exports anterior Algumas linguagens de programao mais antigas, no trabalham com o nome da rotina, mas sim com o numero da funo: Ex.: acessar funo 0, acessar funo 1, ento temos que criar um index para que seja possvel achar esse caminho. Na linguagem que for feita em Delphi, o delphi l direto pelo nome da rotina no usando esse ndice. Esse ndice s para compatibilidade de aplicativos mais antigos.

9.4 - Gerando a DLL


At agora s foi feita a programao dessa DLL, mas ela ainda no existe fisicamente - Aps salva a programao da DLL, v pelo seguinte caminho: Project > Buid DllOperacoes

96

Observao: Este projeto no executvel, por isso que temos que usar essa opo. Ao clicar no Buid DllOperaes e se tudo estiver certo, compilado e mostra que o smbolo Index especifico para a plataforma, no caso do Delphi no , s um aviso.

Figura 43 Compilao da DLL. Se a DLL for gerada, verificaremos que no diretrio que foi salvo existe um arquivo compilado e que foi gerado a DLL.

9.5 - Programao da DLL


library DllOperacoes; { Important note about DLL memory management: ShareMem must be the first unit in your library's USES clause AND your project's (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLL--even those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using PChar or ShortString parameters. } uses SysUtils, Classes; //rotinas usadas nos aplicativos function soma(A,B:real):real; stdcall; export;

97
begin soma := (A+B) * 1.10; end; function divisao (A,B:real):real; stdcall; export; begin if (B=0) then divisao := 0 else divisao := A/B; end;

{$R *.res} exports soma index 0; exports divisao index 1; begin end.

9.6 - Fazendo um aplicativo para testar a DLL


Feche a programao da DLL depois de salvar. Nossa aplicao uma calculadora bem simples para poder acessar a DLL. Crie uma nova pasta dentro da pasta DLL com o nome de formulrios. Crie uma nova aplicao: File > New > Application Coloque no form trs Edits, trs Labes e dois botes. Propriedades dos componentes: Caption Calculadora Name Frm_Cal Edt_Op1 Edt_Op2 Edt_Tot

Form1 Edt1 Edt2 Edt3 Label1 Label2 Label3 Buton1 Buton2

Operador 1 Operador 2 Total Soma Divide

Btn_Soma Btn_Divide

98

Figura 44 Formulrio de uma calculadora simples. Salve o Formulrio na pasta formulrios: File > Save as > C:\Alunos\DLL\Formulrios nome: Frm_Calc. Salve o projeto na mesma pasta da DllOperacoes. File > Save Project as > C:\Alunos\DLL\DllOperacoes nome P_Calculadora. Para usar uma DLL o arquivo do projeto criado tem que estar salvo na mesma pasta que foi gerada a DLL, porque o arquivo DLL vai gerar um executvel, ento tem que estar ambos na mesma pasta. Se quiser por exemplo salvar em outra pasta ento copiamos o arquivo atravs de um Path e copiamos a DLL na pasta que vai ficar o executvel do sistema. S tem dois campos que podem estar: ou dentro da pasta do executvel ou dentro da pasta do Windows (Windows Sys32 onde esto as DLLs), ento podemos copiar nossa DLL neste arquivo (Windows Sys32) que tambm funciona

9.6.1 - Para usar a DLL Na programao temos que declarar as rotinas, porque na hora que fizermos a implementao, o sistema no localiza sozinho. Da pasta da DLL da implementao, vamos disponibilizar as rotinas (aquelas com os mesmos nomes que foram colocadas na DLL.

99 Ao invs de escrever export, como no vamos exportar nada e estamos trabalhando com o caminho de fora, temos que dizer que da DLL que vir os dados. Colocamos ento a chamada external. Podemos no mesmo sistema chamar vrias DLLs. Para obter o caminho que queremos existe trs formas: 1- Se tivermos a fonte, ento abrimos e olhamos o caminho. 2- Pela documentao do fabricante da DLL, com as rotinas disponveis. 3- Pela Internet baixamos o software de visualizao da DLL. Esse software, no caso de uma DLL mostra o cabealho da DLL. Ateno: Se a rotina for digitada errada (porque casesensitive) no vai funcionar. Clique em F12 para abrir o modulo de programao do form. Coloque as seguintes linhas de comandos: function soma(A,B:real):real;stdcall;external 'DllOperacoes.dll'; function divisao(A,B:real):real;stdcall;external 'DllOperacoes.dll'; A Pilha: Cada vez que chamamos uma rotina, o sistema empilha a Dll chamada e recusa a rotina e quando terminar a rotina atual, desempilha e volta ao estado original do sistema. Cada vez que chama uma rotina, o sistema executa um shunt (desvio), verifica o estado atual do sistema, guarda numa pilha, depois executa a rotina. A diferena como o armazenamento feito. Podemos armazenar primeiro o nome da rotina e depois os parmetros, ou primeiro os parmetros e depois as rotinas. Ento, a ordem muda de uma linguagem para outra. Estamos padronizando a entrada, porque na hora que digitar a rotina o sistema pode entender errado. Depois de definirmos a rotina, agora s utilizar. De duplo clique no boto soma. Quando for clicado o boto de soma, pega os dois valores e atribua dentro da soma. Coloque as seguintes linhas de comando na programao do boto soma. procedure TFrm_Calc.Btn_SomaClick(Sender: TObject); var X,Y,Z:real; begin X := StrToFloat(Edt_Op1.Text); Y := StrToFloat(Edt_Op2.Text); Z := soma(X,Y); Edt_Tot.Text := FloatToStr(Z): end;

100 Como os tipos so diferentes fazemos a converso de String para Float. Se a declarao do caminho foi feita corretamente, o sistema j reconhece a rotina que foi declarada na DLL. Na programao chamamos a rotina da DLL para fazer o calculo da soma para mostrar o valor no sistema, atravs das linhas de comando abaixo: Z := soma(X,Y); Edt_Tot.Text := FloatToStr(Z): O que esta sendo feito: Estamos chamando uma rotina que no programamos em nosso projeto calculadora. Na hora que o projeto precisar acessar a rotina dentro da DLL e executar, passamos os valores dos parmetros. 9.6.2 - A rotina Divide. Essa rotina parecida com a anterior, a nica diferena que no vai ser criada um bando de aliases, ser feita em uma nica linha. A rotina divide passa como parmetro o primeiro operador, o segundo operador, temos que converter de float para string e atribuir dentro do Edit. 9.6.2.1 - Programao do boto Divide procedure TFrm_Calc.Btn_DivideClick(Sender: TObject); begin Edt_Tot.Text := FloatToStr(divisao(StrToFloat(Edt_Op1.Text),(StrToFloat(Edt_Op2.Text)))); end; O comando o mesmo, a nica diferena que foi passado o primeiro e o segundo parmetro (Edt_Op1 e Edt_Op2) convertidos para uma string. Os dois valores entram na rotina, so convertidos e o resultado mostrado no Edt_Tot. Salve o projeto e compile para executar. Teste colocando os valores nos operadores. Clique no boto soma e verifique. Faa o mesmo para o boto Dividir. Se for diviso por zero e como foi efetuado um tratamento, o resultado 0 (zero).

101

Figura 45 Projeto calculadora em execuo atravs de uma DLL. Se vrios programas executassem a mesma rotina e precisasse ser feito uma mudana na programao, por exemplo, cobrar 10% a mais em cima do calculo efetuado, esta mudana realizada uma nica vez na DLL utilizada pelos forms. Altere a programao da DllOperaes. Salve e execute novamente o sistema da calculadora. function soma(A,B:real):real; stdcall; export; begin soma := (A+B) * 1.10; end; Ateno: No necessrio recompilar de novo o Projeto Calculadora. Qualquer alterao feita na DLL no precisa recompilar o projeto vinculado.

Figura 46 Execuo do projeto calculadora com novos parmetros.

102 Desse jeito podemos ter todas as rotinas dentro de um sistema e colocamos dentro de uma DLL, isso ajudaria na manuteno. Fazemos a manuteno ou alteraes dentro da DLL. Assim podemos separar o sistema em vrias DLLs e s mandamos a DLL que foi modificada.

9.7 - Como criar formulrios dentro da DLL.


Podemos colocar componentes visuais dentro de uma DLL. Exemplo: Num formulrio colocamos um Label e vamos chamar esse Form. Crie uma nova pasta dentro da pasta DLL com o nome de FormTeste Dentro da pasta Form crie outra com o nome de formularios Criar uma nova aplicao. Coloque no Form os seguinte componente: um Label. Propriedades: Caption Teste Name Frm_Teste Lb_Nome

Form1 Label1

Figura 47 Formulrio para teste Dentro desse formulrio passaremos um parmetro para ser exibido neste form Salve o formulrio no diretrio C:\Alunos\DLL\FormTeste\Formulrios com o nome de U_Teste No salvaremos o projeto ainda que ser explicado do porque logo mais. Queremos chamar esse formulrio dentro de uma DLL. Vamos colocar dentro da DLL esse formulrio inteiro para poder chamar a aplicao.

103 Por exemplo: Vamos supor que queremos chamar a DLL dentro do Force Reporte. Ele no tem as tabelas e faz de conta que a Label fosse uma coisa do outro mundo, que fizesse clculos complexos que o Force Reporte no tem e queremos disponibilizar essa tela no aplicativo. Passamos como parmetro o nome que ser exibido no Form. Salvamos o formulrio e fechamos a aplicao. File > Close.

9.8 - Programao da Unit U_teste:


unit U_Teste; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFrm_Teste = class(TForm) Lb_Nome: TLabel; private { Private declarations } public { Public declarations } end; var Frm_Teste: TFrm_Teste; implementation {$R *.dfm} end.

9.9 - Criando uma DLL para chamar este formulrio.


File > New > Other > DLL Wizard > OK Aps abrir o formulrio da DLL salve no diretrio da pasta FormTeste. File > Save as > C:\Alunos\DLL\FormTeste com o nome de FormTeste

104

9.9.1 - Programao das rotinas. Teremos um procedimento protegido chamado procedure ChamaTela procedure chamatela(nome:string); stdcall; export; var frm_teste:Tfrm_teste; begin application.createform(TFrm_teste,frm_teste); frm_teste.Lb_nome.Caption:= nome; frm_teste.showmodal; frm_teste.free; end; Cada vez que for chamado o procedimento ChamaTela passamos como parmetro o nome que queremos mostrar na String frm_teste.Lb_nome.Caption:= nome; Para chamar uma rotina que foi declarada em outro local, usamos o comando Uses com o nome da Unit. No caso Uses U_Teste. Como essa rotina esta dentro de um diretrio colocamos o caminho: u_teste in 'C:\Alunos\DLL\FormTeste\Formularios\u_teste.pas'; uses SysUtils,forms, Classes, u_teste in 'C:\Alunos\DLL\FormTeste\Formularios\u_teste.pas'; O path tem que ser colocado inteiro porque esse formulrio no est no mesmo diretrio da tela que foi chamado. Se tivesse os dois no mesmo diretrio era s colocar u_teste que os dados sero encontrados. No exemplo estamos forando o sistema encontrar o path (caminho) de onde queremos compilar. Para chamar o formulrio, se fizermos o comando Frm_teste.Showmodal, na hora da compilao, como no foi criado na memria, vai dar erro, ento necessrio criar um formulrio para chamar o Frm_teste. Para chamar esse formulrio, criamos uma varivel chamada Frm_teste do tipo Tform_Teste: var frm_teste:Tfrm_teste; Agora temos que criar na memria este formulrio. Este criao feita com os comandos:

105 application.createform(TFrm_teste,frm_teste); Depois de criado e mostrado o formulrio na tela temos que colocar o comando Free para liberar esse formulrio aps executado. frm_teste.showmodal; O que foi feito: Foi criada uma varivel, para chamar o formulrio que geralmente se encontra fora da pasta. Se no temos uma aplicao para ser criada na memria, ento criamos a varivel, chamamos o formulrio e depois liberamos esse formulrio. Logo abaixo da programao aps o smbolo {$R *.res}colocamos o comando: exports chamatela index 0; Esse comando no obrigatrio. somente para alguns programas que usam Windows. Compile o programa. Project > Build FormTeste Neste ponto dar um erro, porque o sistema quer que compile o projeto testes para gerar o arquivo DCU. Para sanar isso abra uma nova tela e compile para que o sistema gera a DCU. Adicione ao projeto essa tela: C:\Alunos\DLL\FormTeste\Formulrios Agora volte DLL e compile.

9.10 - Programao da DLL


library FormTeste; { Important note about DLL memory management: ShareMem must be the first unit in your librarys USES clause AND your projects (select Project-View Source) USES clause if your DLL exports any procedures or functions that pass strings as parameters or function results. This applies to all strings passed to and from your DLLeven those that are nested in records and classes. ShareMem is the interface unit to the BORLNDMM.DLL shared memory manager, which must be deployed along with your DLL. To avoid using BORLNDMM.DLL, pass string information using Pchar or ShortString parameters. } uses SysUtils,forms, Classes, u_teste in C:\Alunos\DLL\FormTeste\Formularios\u_teste.pas; procedure chamatela(nome:string); stdcall; export; var frm_teste:Tfrm_teste;

106
begin application.createform(TFrm_teste,frm_teste); frm_teste.Lb_nome.Caption:= nome; frm_teste.showmodal; frm_teste.free; end; {$R *.res} exports chamatela index 0; begin end.

9.11 - Criando outro Projeto para Teste


Agora temos que criar um outro formulrio com um boto: Propriedades: Caption ChamaTela Name Frm_ChamaTela Btn_Tela

Form1 Button1

Figura 48 Projeto teste para chamar tela com DLL Compilamos e criamos a DLL, agora temos que cham-la dentro do programa Na aplicao criada primeiro temos que salvar dentro do mesmo diretrio. File > Save as > salve dentro do diretrio onde est a DLL. C:\Alunos\DLL\FormTeste\Formulrios\U_ChamaTela. Este sistema vai chamar o outro formulrio. Quando clicar no boto, vai chamar a nova tela atravs da DLL.

107

Para chamar a tela colocamos na programao completando a palavra external o nome da DLL. procedure chamatela(nome:string); stdcall; external 'formteste.dll'; Ento criamos um procedimento chamatela que passamos um nome que queremos que aparea no Label do form. Chamamos a outra tela, passando como parmetro o nome que queremos que aparea na tela pode colocar qualquer mensagem, nome etc. procedure TFrm_ChamaTela.Btn_TelaClick(Sender: TObject); begin chamatela('MENSAGEM'); end; Salve > Compile e execute.

Figura 49 - Projeto Chama tela compilado. Ao clicar no boto acima, a DLL chama a tela abaixo:

Figura 50 Tela aberta atravs de uma DLL. O que acontece:

108 Estamos mudando um formulrio com Showmodal como se estivesse usando o aplicativo. A nica diferena que esse form interno esta dentro de uma DLL. No formulrio criado poderia ter uma table, que poderamos passar como parmetro o nome da tabela, neste caso o sistema busca a tabela, faz uma consulta e mostra o valor. Geralmente em uma DLL tem vrias telas. Podemos fazer uma tela de cadastro padro e passamos como parmetro o tableName da mesma forma que passamos o nome como parmetro.

9.12 - Programao da Unit Chama tela


unit U_ChamaTela; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls; type TFrm_ChamaTela = class(TForm) Btn_Tela: TButton; procedure FormCreate(Sender: TObject); procedure Btn_TelaClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Frm_ChamaTela: TFrm_ChamaTela; implementation procedure chamatela(nome:string); stdcall; external 'formteste.dll'; {$R *.dfm} procedure TFrm_ChamaTela.Btn_TelaClick(Sender: TObject); begin chamatela('MENSAGEM'); end; end.

109

9.13 - Exerccio:
Faa um sistema que contenha uma DLL. Essa DLL deve conter uma tela de busca em uma tabela qualquer. Num campo, por exemplo: Nome gerar essa tabela de busca. Clicando na tela (no campo) passa como parmetro a tabela que deseja carregar. No LooKup digita o nome e manda buscar, na hora que clicar no registro retorna a posio do registro lido. Vai chamar a DLL atravs de uma Function e passa como parmetro a tabela desejada. Nessa DLL vai ter uma tela inteira que tem a propriedade como status e boto de busca. Na busca aparece uma grid que exibe os dados. Na hora que clicar em cima do campo, retorna o cdigo lido. A funo retorna a posio da tela. A tela no pertence ao sistema.

110

10 - PROVAS APLICADAS 10.1 - Prova A


Tempo: 60 minutos. 1) Crie um componente descendente de um banco de dados (por exemplo, TIBtable (interbase) ou TSimpleDataSet (ibexpress)) e modifique este componente de tal forma que ao salvar (aps aplicar um post) algum dado ele execute automaticamente um ApplyUpdates no banco. Se tudo der certo, a propriedade salvo recebe true. Se der errado, recebe false. Criar uma dll com uma rotina de calculo do valor de venda (valor_prod * (1+ taxa_de_ganho)). A taxa de ganho um percentual sobre o valor do produto que o usurio ir informar. Nesta dll, iremos passar o cdigo do produto, a tabela a ser pesquisada e a taxa. O sistema ir chamar a rotina, pesquisar o cdigo na tabela indicada e retornar o valor do produto (aplicando a taxa_de_ganho). Pesos: Componente de banco de dados Dll Se achar necessrio - Banco: Cod_Prod Valor_Prod Descr_Prod QTD_PROD N N A[30] N 3,5 3,5

2)

10.2 - Prova B
Tempo: 60 minutos. 1) Crie um componente derivado do componente DBedit que ao colocar no sistema e pressionar a tecla enter, ele verifique se o contedo uma string e deve colocar a propriedade tipo para string. Caso seja um numero, tipo recebe num. Alm disso, o componente deve contar o numero de vogais do texto e setar a propriedade vogais com o numero delas. 2) Imaginemos que uma empresa deseja implantar cdigo de barras interno. S que em vez de usar o padro, ela cria o seu prprio cdigo de 13 dgitos: inicia com 2 (interno), grava o produto(cdigo), quantidade (comprada) e valor . A estrutura vista abaixo:

111

___

___

__ ___

onde Digito verificador com 1 digito

Cdigo do produto com 3 dgitos

Quantidade com 3 dgitos

Valor com 5 dgitos

Ex: 2 034 003 00500 3 indica: Comprou 3 unidades do produto 034, a um valor de 5 reais por unidade. Pede-se: Criar uma rotina em DLL, que dado o cdigo de barras, retornar o valor da compra No esquea de criar o programa para demonstrar o uso da dll. Pesos: Componente de banco de dados Dll 3,5 3,5

10.3 - Prova C
3) Crie um componente descendente de um SpeedButton e modifique este componente de tal forma que ele possua uma propriedade chamada apertou. Se o usurio realizar um click sobre o componente, esta propriedade deve ficar com true. Caso contrrio deve ficar com false. Alm disso, por padro o boto deve ser do tipo flat e as figuras devem ser colocadas no topo do boto. Criar uma dll com uma rotina de calculo do digito verificador para o cdigo EAN 13. Voc deve informar o cdigo de barras e ela retorna true ou false se deu certo ou no. Tambm dever ser criada a tela para entrada do cdigo a ser gerado o digito (dentro de uma dll tambm).

4)

Pesos: Componente de banco de dados Dll 3,5 3,5

112

10.4 - Prova D
componente e a propriedade cores estiver com true, ele deve trocar a cor da fonte do texto. A seqncia de ver preto ou vermelho, isto , se estiver com preto, fica vermelho. Se estiver vermelho, vai para o preto. 2) Imaginemos que uma empresa deseja implantar cdigo de barras interno. S que ela deseja gerar o cdigo. Criar uma rotina que dado o cdigo do produto, quantidade e valor, todos atravs de parmetros, ela deve gerar o cdigo de barras com 13 dgitos e retornar este cdigo. A estrutura vista abaixo: 2 ___ ___ __ ___ _ onde Digito verificador com 1 digito

Cdigo do produto com 3 dgitos

Quantidade com 3 dgitos

Valor com 5 dgitos

Para a prova, no necessrio gerar o digito verificador. Assumir um valor fixo para este campo (por exemplo, o valor 7) Ex: 2 034 003 00500 7 indica: Comprou 3 unidades do produto 034, a um valor de 5 reais por unidade. Parmetros: Cdigo do produto (inteiro) Quantidade (inteiro) Valor (real) No esquea de criar o programa para demonstrar o uso da dll. Pesos: Componente de banco de dados Dll 3,5 3,5

113

11 IMPRESSORA FISCAL
O emissor de cupom fiscal (ECF), conhecido como Impressora Fiscal um equipamento de impresso de cupons que substitui a Nota fiscal ao consumidor final que deve atender ao convenio ICMS 156/94 bem como suas atualizaes. Para evitar sonegao, a Receita Federal exige a impressora fiscal para quem trabalha com vendas. A comunicao da impressora fiscal com o micro atravs da porta serial RS232 e utiliza o protocolo RTS/CTS. A primeira parte que veremos a instalao de uma impressora fiscal, configurao e zeramento da impressora. O padro de impressora que utilizaremos neste estudo da Bematech, embora existam outros fabricantes. A maioria das impressoras fiscais tem o mecanismo de impresso por agulhas (sistema matricial), mas j existe no mercado a impressora trmica, que utiliza papel de impresso especial e tem apenas uma via. Toda impressora fiscal deve ser lacrada pela Receita Federal. Quando for adquirida uma impressora fiscal temos que fornecer para a Receita Federal ao dados tais como: Razo Social, CNPJ, endereo, o representante que vendeu a impressora, para que a receita possa liberar a impressora zerada e com os dados acima. Se uma impressora for comprada de terceiros, deve estar lacrada, levada at um posto da Receita Federal para que seja zerada e substitudo os dados da empresa anterior e receber um novo lacre. A impressora fiscal tem duas entradas: a mais externa para ser ligada no computador para recebimento dos dados a serem impressos e a mais interna de uso do fisco para leitura de tudo que estiver armazenado dentro.

11.1 - Cupom Fiscal


O cupom fiscal composto das seguintes sees: 1 Seo - Cabealho - Razo Social, endereo, CNPJ e Inscrio Estadual do Estabelecimento Comercial. - Data e hora do inicio da impresso do cupom. - Contador de Ordem de Operaes (COO) e Contador Geral de Comprovante No Fiscal (GNF). - A identificao do cliente opcional. 2 Seo Corpo do cupom No corpo do cupom fiscal que consta os itens da venda subdividida em outros segmentos: - Numero do item (3 dgitos).

114 Cdigo do produto ou servio (13 dgitos). Descrio do produto ou servio (29 caracteres). Quantidade (inteira ou frao). Valor unitrio (duas ou trs casas decimais). Situao tributria Valor total. Desconto se houver desconto, uma terceira linha impressa contendo o valor do desconto.

3 Seo Fechamento Na terceira seo impresso o fechamento: - Informaes do subtotal. - Descontos ou acrscimos. - Forma de pagamento - Valor total. - Troco se houver e mensagem. 4 Seo Final - Impresso nome do fabricante da impressora fiscal. - Modelo da impressora. - Nmero da verso do software do EPROM. - Nmero da loja e do equipamento. - Nmero de srie do ECF. - Data e hora do trmino da impresso. - O Grande Total (GT) criptografado. - Logotipo BR.

11.2 - Relatrios emitidos pela Impressora Fiscal


Leitura X. - Contm informaes do movimento dirio. Resumo de tudo que foi vendido no dia: quanto que foi vendido do produto, imposto a ser pago(IPI, ICMS) um resumo gerencial. - Impresso no inicio do dia de trabalho e quando for trocada a bobina. - A Leitura X pode ser feita vrias vezes por dia. Reduo Z. - Parecido com a Leitura X, mas quando emitido, grava as informaes do Grande Total na memria fiscal. - No final do dia ou quando for fechado o caixa retirada a reduo Z. - Esta operao bloqueia o ECF, por isso tirada uma nica vez no dia porque sua liberao s acontecer quando da virada da meia noite.

115 Se a Reduo Z no for feita aps o trmino do trabalho e for desligada e ligada apenas aps a virada da meia noite, a Reduo Z ser gerada automaticamente, trava a emisso de novos cupons e destrava logo em seguida continuando o trabalho normalmente. Se no for efetuada nenhuma venda no dia a Reduo Z no ser emitida.

A bobina da impressora matricial em duas vias, sendo a primeira via entregue ao cliente e a segunda rebobinada na prpria impressora. A impressora trmica, como foi dito anteriormente, s tem uma via.

11.3 - Os Arquivos de Configurao.


Para serem baixados os arquivos de configurao, entre no site do fabricante Bematech (www.bematech.com.br/desenvolvedores), clique no link produtos -> impressora fiscal. Dentro da impressora fiscal podemos escolher o modelo da impressora, no caso vamos escolher o modelo MP-20FI II.

Figura 51 Tela do site www.bematech.com.br. Em drivers > Downloads. Manual > Drivers de outros arquivos > selecionar Windows.

116

Efetuar o Dowload da biblioteca BEMAFI32.DLL. Esse arquivo deve ser baixado e gravado na pasta C:\windows\system(para windows 95/98/ME) ou C:\winNT\system32 (para windows 2000, NT ou XP). A aplicao precisa chamar essas funes com os devidos parmetros e a DLL se encarrega de enviar os comandos corretos para a impressora.

11.4 - O emulador.
Ferramenta desenvolvida pela Bematech e gratuita. Consiste de um software que roda em ambiente grfico windows e executa as operaes de uma Impressora real que deve ser utilizado somente na fase de desenvolvimento do projeto. Baixe o aplicativo no site da Bematech clicando no link desenvolvedores > downloads e drivers, escolhendo o sistema operacional windows. Aps o download faa o instalao do emulador.

11.5 - Exemplos de integrao


Baixe o exemplo de integrao Delphi 5 completo com cdigo fonte que ser utilizado no projeto do site www.bematech.com.br Arquivo txt baixado do site da Bematech: ========== LEIAME.TXT ==========
Salve os arquivos: -> BemaFI32.dll -> BemaFI32.ini -> BemaMFD.dll -> DAO2535.tlb -> DAO350.dll -> MSJET32.dll No diretrio de sistema de seu Windows. Se for Windows 95, 98 ou ME salve em "\Windows\System". Se for Windows 2000, NT ou XP salve em "\WinNT\System32" Caso voc utilize a funo Bematech_FI_RelatorioSintegraMFD, que gera os registros do Sintegra nas impressoras fiscais MFD MP-2000 TH FI e MP-6000 TH FI (somente), necessrio que os arquivos DAO350.DLL e MSJET35.DLL sejam registrados. Para isso, execute: REGSVR32 /S DAO350.DLL REGSVR32 /S MSJET35.DLL

117
O arquivo BEMAFI32.CHM o arquivo de ajuda da BEMAFI32.DLL. Basta dar um duplo-clique para abri-lo. Neste arquivo, voc encontrar todas as explicaes referente as funes da DLL, alm de exemplos em Visual Basic e Delphi. Para esclarecer suas dvidas em relao ao uso da DLL, voc poder entrar em contato com o nosso suporte tcnico no telefone: 0800 644 2362 ou por e-mail: suporte@bematech.com.br ------------------------------------------------BEMATECH - NOSSO NEGCIO AUTOMAO COMERCIAL!!!

Fonte: www.bematech.com.br Dentro da impressora fiscal existe uma memria EPROM que guarda todos os dados que gera o cupom fiscal, que ser fiscalizado pela receita
;----------------------------------------------------------------------------; ; ; ; BEMAFI32.INI ; ; Ver 5.0.0.0 - Mar/2006 ; ; ; ; Arquivo de inicializacao da dll BemaFI32 para as impressoras fiscais ; ; MP-20 FI II, MP-40 FI II, MP-2000 FI TH, MP-6000 FI TH, MP-25 FI, ; MP-50 FI da Bematech e Y-8000 e Y-8500 da Yanco ; ; ; ;----------------------------------------------------------------------------; [Sistema] Porta=DEFAULT Path=C:\ Status=0 Retorno=0 StatusFuncao=0 ControlePorta=1 ModeloImp=BEMATECH ConfigRede=0 ModoGaveta=0 Log=0 EmulMFD=0 StatusCheque= [MFD] Impressora=0 StatusErro=1 TimeOutZ=3 [Opcional]

118
Favorecido= Cidade= [Formato] ; ; +------------------------------------- coluna do valor numerico ; | +---------------------------------- coluna extenso 1 ; | | +------------------------------- coluna extenso 2 -

Fonte: www.bematech.com.br Aps baixados os arquivos necessrios, descompactar as trs pastas (Exemplo Delphi 5 completo, Emulador Emulfith e BemaFI32.DLL). Abrir a pasta BEMAFI32.DLL Copiar todos os arquivos com exceo do arquivo Bemath 32.HTML (Ajuda) e o Leiame.txt, para a pasta System32 (C:\windows\system32). Esta pasta armazena todas as DLLs do sistema, porque para acessar a DLL, esta tem que estar no mesmo diretrio do executvel ou na pasta SYSTEM32. No caso da impressora fiscal, vamos ter mais um programa trabalhando, assim teramos um monte de cpias espalhadas no sistema, para evitar isso colocamos direto na pasta Win32 onde qualquer sistema pode acessar. Aps copiar os arquivos na pasta System32 registre os arquivos clicando em cima dos arquivos REGSVR32 /S DAO350.DLL e REGSVR32 /S MSJET35.DLL que registram arquivos em lotes do MS-DOS aparecer uma tela do MS-DOS e fecha em seguida. Estes comandos registram os arquivos Bematech.

11.6 - Configurando a Impressora


Agora falta configurar o arquivo BEMAFI32.INI configurao da Impressora fiscal. Este arquivo o arquivo de

Quando der duplo clique em cima deste arquivo, ele abrir um bloco de notas que representa toda a configurao da Impressora fiscal (o path, qual a porta a ser utilizada, se tem gaveta ou no, escrever o nome do favorecido da nota, nome da cidade, etc.). Para que isso? Porque a Impressora Fiscal no tem esses dados gravados dentro do EPROM. Ela s trs gravado o nome da empresa registrada e seus dados, quando efetuado o lacre pela Receita Federal. Por Exemplo: O nome da empresa Jos da Silva ME. S que Jose da Silva me o BAR DO Z. Para aparecer o nome de fantasia BAR DO Z no cupom, ento colocamos como favorecido: BAR DO Z, cidade: LINS SP. Tudo isso opcional. Parmetros EmulMFD = 0 ou 1

119 Se formos utilizar o emulador (Emulfth), para substituir a Impressora Fiscal fsica, quando da execuo do projeto, ento colocamos como parmetro o numero 1 . Para imprimir em uma Impressora Fiscal real, usamos o 0. - Com Impressora Fiscal EmulFMD = 0. - Com o emulador - EmulFMD = 1. Se o emulador Emulfith j estiver instalado, deve aparecer o cone Bematech Emulfith no Desktop. Clique no cone do emulador. Aparece o emulador , conforme figura abaixo:

Figura 52 Tela do emulador EMULFITH VR.1.02 A parte direita em branco, representa o papel da impressora. OBS: J existe uma nova verso do emulador no site www.bematech.com.br A rea esquerda representa o painel da impressora. Ateno - O emulador s para ser usado na etapa do desenvolvimento, ento no deixe este emulador rodando na mquina o tempo todo, porque ocupa muita memria e o computador fica lento. S ative-o quando for fazer um teste.

120

Quando a Impressora fiscal for ligada, aparecer a mensagem que o horrio avanou mais de 30 dias em relao ao ltimo documento armazenado. Se o horrio estiver correto, pressione a tecla PAPER 5 vezes para colocar o equipamento em operao. Isto feito tanto na impressora real , quanto no emulador. Aps efetuado este processo, aparecer mensagem de que o ECF esta desbloqueado, neste ponto emitida a Leitura X e o equipamento est pronto para ser utilizado. Enquanto no aparecer a mensagem de Impressora desbloqueada, no d para ser usada. Para limpar a mensagem do emulador, como se fosse destacar o papel impresso, existe um boto (LIMPAR). Assim a impressora fica preparada para efetuar a operao. Podemos deixar a impressora em OFF-LINE, para poder avanar o papel pressionando o boto PAPER

11.7 - A memria de trabalho do emulador.


a memria fsica o que interessa Receita Federal, quanto tem de ICMS, ISS, no tributados. Na Impressora fiscal, este arquivo s acessvel para a Receita Federal. Esta memria bem grande e quando no tiver mais espao, a impressora deve ser levada na Receita Federal para ser efetuada a leitura e zerada. No emulador pode-se configurar a porta serial, regulagem da hora, o que no permitido na Impressora Fiscal. OBS: De hora em hora a Impressora Fiscal emite uma barra indicando que ela esta ligada e ativa. No arquivo BEMATFI32.INI, instalado na pasta Windows\System32, altere o campo EmulMFD para 1, a fim de usar o emulador, mas se estiver usando a impressora fiscal, no altere. OBS: O arquivo de Helph da Bematech(que tem uma interrogao), vai ser usado para fazer o projeto. Abra a pasta - Ajuda da BEMAFI32.DLL

121

Figura 53 Tela da ajuda da Bemafi32.DLL. Abra este arquivo e minimize. Abra o Delphi. Crie uma nova aplicao. File > New > Application

Coloque um boto:

Figura 54 Formulrio de teste para Cupom Fiscal. Propriedades: Name Frm_TesteImpressora Btn_GerarCupom Caption Teste Impressora Cupom Fiscal

Form TButton

122 Salve a Unit e o projeto Como ainda no temos um banco de dados por ser o primeiro exemplo, colocamos variveis e jogamos valores fixos nestas variveis para mandar imprimir esses valores, depois substituiremos os valores dessa variveis pelos campos do banco de dados. Pressione F12 para abrir o mdulo de programao. Para chamar a rotina de dentro da DLL, temos que saber o nome de cada procedimento. No arquivo de Help, tem a DLL BEMAFI32. Nesta DLL tem os parmetros declarando a DLL. Clicando em declarando a DLL, temos vrias linguagens (Visual Basic, Delphi...) > escolha na verso em Delph.

Abrir todas as rotinas nesta linguagem. Note que tem o comando stdcall e external. Selecione toda a programao copie e cole depois da palavra implementation {$R *.dfm}

Figura 55 Funes de inicializao para Impressora Fiscal. Estas rotinas mudam de acordo com a verso DLL que for baixada. A primeira coisa que fazemos num cupom fiscal imprimir o cabealho que contm o nome da empresa, endereo, CNPJ, campos fixos que no podemos alterar.

123

Aps este campo aparecer a impresso para quem estamos vendendo - Opcional.

11.8 - As rotinas
A primeira rotina chamada Bematech_FI_AbreCupomMFD. Na ajuda da BEMAFI32.DLL > clique em DLL BemaFI32 > Funes da DLL > Cupom Fiscal > Bematech_FI_AbreCupomMFD.

Figura 56 Tela de ajuda Bematech Bematech_FI_AbreCupomMFD. Esta rotina explica o funcionamento e os parmetros necessrios (CPF, nome, endereo do cliente e embaixo quem vendeu). Selecione esta rotina copie e cole na programao do boto Btn_GeraCupom.
// // Exemplo em Delphi cCPF := '10.123.154-98'; cNome := 'Fulano de Tal'; cEndereco := 'R. Sem Fim, 1000'; iRetorno := Bematech_FI_AbreCupomMFD( pchar( cCPF ), pchar( cNome ), pchar( cEndereco ) );

124

Os nomes das variveis podem ser mudadas de acordo com a programao desejada. procedure TFrm_TesteImpressora.BTn_GeraCupomClick(Sender: TObject); var iRetorno: integer; cCPF, cNome: string; begin // Abre o Cupom Fiscal cCPF := '1234567890'; cNome := 'Fulano de Tal'; iRetorno := Bematech_FI_AbreCupomMFD( pchar( cCPF ), pchar( cNome ), pchar( '' ) ); end;

Acima, na Ajuda, tem muitas variveis que podem tambm serem usadas. Na Ajuda possvel ver qual o tipo de cada varivel j definida. 11.9 - PCHAR Dentro desses parmetros tem o pchar Numa string em Pascal, a posio zero guarda o tamanho, depois vem a posio, 1,2,3,4... Para gravar uma P A L A V R A . P 1 A 2 L 3 A 4 V 5 R 6 A 7

Estamos usando at a posio 7. Na tabela ASCII, o caractere que representa esta posio colocado no campo zero indicando que foram usadas 7 posies da string. A posio zero inibe o tamanho total da posio. O maior tamanho de uma string em Pascal 255 (o caractere 255 da tabela ASCII). Na linguagem C a string diferente. Podemos escrever PALAVRA e no final colocamos \0, que o smbolo que indica que terminou a string. Neste tipo de string podemos ter quantos caracteres quisermos. A funo Pchar transforma uma string em Pascal para um string em C. O nome e o endereo podem ser colocados no cupom fiscal. Tambm podem ser passados em branco. Podemos colocar a expresso Venda ao Consumidor Todos esses parmetros so opcionais.

125 Ento para o nosso exemplo, chamamos a rotina AbreCupomMFD e passamos como parmetro o CPF, o nome e o endereo, que exatamente o que est escrito no exemplo das rotinas. Quando for executada esta rotina que uma funo, retorna um valor:

11.10 - Possveis retornos da Funo (INTEIRO):


0: Erro de comunicao. 1: OK. -2: Parmetro invlido na funo. -4: O arquivo de inicializao BemaFI32.ini no foi encontrado no diretrio de sistema do Windows. (O sistema no sabe se vai jogar para o emulador ou para a impressora, em resumo, no est instalada a impressora fiscal). -5: Erro ao abrir a porta de comunicao. (foi esquecido de plugar a impressora fiscal). -27: Status da impressora diferente de 6,0,0 (ACK, ST1 e ST2). (uma srie de erros. Quando der esse erro temos que chamar outra rotina para mostrar o erro que ocorreu. Esse erro pode ser: papel atolado, sem papel, impressora desligada, etc). // iRetorno := Bematech_FI_RetornoImpressora( iACK, iST1, iST2, iST3 ); Nosso programa esta pegando esta funo e jogando para um retorno e por enquanto no vamos usa-lo, mas podemos fazer um comando if (if retorno <> 1 then showmessage Erro: Verifique a Impressora) apenas uma das funes que poderia ser usada com a resposta do retorno. Vamos supor que desse o erro -27, ento chamaramos a prxima rotina (retornoImpressora). Essa rotina tem o retorno do erro, conforme mostra nos comandos de retorno da impressora abaixo:
11.11 - Comandos Retorno da Impressora retirado do arquivo Ajuda BEMAFI32.DLL
Todos as funes, executadas na impressora, possuem bytes de retorno, que significam o estado atual aps o envio. Cada byte tratado da seguinte maneira: ACK (06h ou 6d) : Byte indicativo de recebimento correto. ST1 e ST2 : Bytes de estado da impressora. NAK (15h ou 21d) : Byte indicativo de recebimento incorreto. Observao: - Nas impressoras fiscais Matriciais, os retornos de execuo so obtidos, apenas, pelos bytes ACK, ST1 e ST2. - Nas impressoras fiscal MFD (somente), existe um outro retorno chamado ST3 (retorno estendido), onde informaes mais detalhadas podem ser obtidas, mas este retorno s habilitado pela funo Bematech_FI_HabilitaDesabilitaRetornoEstendidoMFD.

126

11.11.1 - Estados de ST1


Bit 7 6 5 4 3 2 1 0 Descrio do estado Fim do papel Pouco papel Erro no relgio interno Impressora em erro Primeiro dado do comando no foi caractere ESC (27 em decimal) Comando inexistente Cupom aberto Nmero de parmetro do comando invlido Valor retornado 128 64 32 16 8 4 2 1

11.11.2 - Estados de ST2


Bit 7 6 5 4 3 2 1 0 Descrio do estado Tipo de parmetro do comando invlido Memria fiscal lotada Erro na memria RAM no voltil Alquota no programada Capacidade de alquotas programveis esgotada Cancelamento no permitido CNPJ/IE do proprietrio no programados Comando no executado Valor retornado 128 64 32 16 8 4 2 1

11.11.3 Lgica de tratamento


Lgica de Tratamento Cada byte composto de 8 bits. Cada bit, dentro do byte, tem um valor, conforme a tabela acima: O valor recebido da impressora para ST1 e/ou ST2 deve ser comparado com cada bit. As linhas abaixo so uma forma de voc desenvolver um pedao de cdigo para saber quais bits esto "setados": Codificando o ST1 If St1 >= 128 Then // bit 7 St1 = St1 - 128 sMsg = "Fim de Papel" End If If St1 >= 64 Then // bit 6 St1 = St1 - 64 sMsg = "Pouco Papel" End If If St1 >= 32 Then // bit 5 St1 = St1 - 32 sMsg = "Erro no Relgio" End If If St1 >= 16 Then // bit 4 St1 = St1 - 16 sMsg = "Impressora em Erro" End If If St1 >= 8 Then // bit 3 St1 = St1 - 8 sMsg = "Comando no iniciado com ESC" End If If St1 >= 4 Then // bit 2 St1 = St1 - 4 sMsg = "Comando Inexistente" End If If St1 >= 2 Then // bit 1

127
St1 = St1 - 2 sMsg = "Cupom Aberto" End If If St1 >= 1 Then // bit 0 St1 = St1 - 1 sMsg = "Nmero de Parmetro(s) Invlido(s)" End If Codificando o ST2 If St2 >= 128 Then // bit 7 St2 = St2 - 128 sMsg = "Tipo de Parmetro de Comando Invlido" End If If St2 >= 64 Then // bit 6 St2 = St2 - 64 sMsg = "Memria Fiscal Lotada" End If If St2 >= 32 Then // bit 5 St2 = St2 - 32 sMsg = "Erro na Memria RAM" End If If St2 >= 16 Then // bit 4 St2 = St2 - 16 sMsg = "Alquota No Programada" End If If St2 >= 8 Then // bit 3 St2 = St2 - 8 sMsg = "Capacidade de Alquotas Lotada" End If If St2 >= 4 Then // bit 2 St2 = St2 - 4 sMsg = "Cancelamento No Permitido" End If If St2 >= 2 Then // bit 1 St2 = St2 - 2 sMsg = "CNPJ/IE do Proprietrio No Programado" End If If St2 >= 1 Then // bit 0 St2 = St2 - 1 sMsg = "Comando No Executado" End If Teste o exemplo acima com ST1 = 66, e repare que voc ter dois erros, pouco papel (64) e cupom aberto(2).

Fonte: www.bematech.com.br

O cdigo abaixo mais compacto e tem o mesmo efeito e no necessrio efetuar uma subtrao dos valores correspondentes a cada estado retornado. If (ST1 and 128) = 128 then ShowMessage(Fim do Papel!); If (ST1 and 128) = 128 then ShowMessage(Fim do Papel!);

If (ST1 and 64) = 64 then ShowMessage(Pouco Papel!);

128 If (ST1 and 32) = 32 then ShowMessage(Erro no relgio interno!); If (ST1 and 16) = 16 then ShowMessage(Impressora em erro!); If (ST1 and 8) = 8 then ShowMessage(Primeiro dado do comando no ESC!); If (ST1 and 4) = 4 then ShowMessage(Comando inexistente!); If (ST1 and 2) = 2 then ShowMessage(Cupom Aberto!); If (ST1 and 1) = 1 then ShowMessage(Nmero de parmetro do comando invlido!); Basicamente at agora s fizemos a impresso do cabealho, agora verificaremos o segundo campo Os itens da nota.

11.12 Itens Rotina Vende Item


Neste campo temos que fazer um loop (while) para imprimir os itens. A rotina de Impresso dos itens Bematech_FI_VendeItem BEMAFI32.DLL > Funes da DLL > Bematech_FI_VendeItem
// Exemplo em Delphi cCodigo := '123'; cDescricao := 'Caneta'; cAliquota := '1200'; cTipoQtde := 'I'; cQtde := '10'; iCasasDecimais := 2; cValor := '0,25'; cTipoDesconto := '%'; cValorDesc := '0000'; iRetorno := Bematech_FI_VendeItem( pchar( cCodigo ), pchar( cDescricao ), pchar( cAliquota ), pchar( cTipoQtde ), pchar( cQtde ), iCasasDecimais, pchar( cValor ), pchar( cTipoDesconto ), pchar( cValorDesc ) );

Cupom

Fiscal

>

Fonte: www.bematech.com.br

129 procedure TFrm_TesteImpressora.BTn_GeraCupomClick(Sender: TObject); var iRetorno: integer; iACK, iST1, iST2, iST3: integer; cCPF, cNome: string; iCasas: integer; cCodigo, cDescricao, cAliquota, cTipoQuantidade, cQTDE, cValorUnitario, cTipoDesconto, cDesconto: string; cNumeroItem, cDescAcresc, cTipo, cValor: string; cValorDesc: string; begin // Abre o Cupom Fiscal cCPF := '1234567890'; cNome := 'Fulano de Tal'; iRetorno := Bematech_FI_AbreCupomMFD( pchar( cCPF ), pchar( cNome ), pchar( '' ) ); // iRetorno := Bematech_FI_RetornoImpressora( iACK, // iST1, iST2, iST3 ); // Efetua a Venda do Item cCodigo := '1234567890123'; cDescricao := 'Produto de Teste'; cAliquota := 'II'; cTipoQuantidade := 'I'; cQTDE := '5'; iCasas := 2; cValorUnitario := '10,00'; cTipoDesconto := '%'; cDesconto := '00,00'; iRetorno := Bematech_FI_VendeItem( pchar( cCodigo ), pchar( cDescricao ), pchar( cAliquota ), pchar( cTipoQuantidade ), pchar( cQTDE ), iCasas, pchar( cValorUnitario ), pchar( cTipoDesconto ), pchar( cDesconto ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 ); end;

130
Parmetros: Codigo: STRING at 13 caracteres com o cdigo do produto. Descricao: STRING at 29 caracteres com a descrio do produto. Aliquota: STRING com o valor ou o ndice da alquota tributria. Se for o valor deve ser informado com o tamanho de 4 caracteres ou 5 com a vrgula. Se for o ndice da alquota deve ser 2 caracteres. Ex. (18,00 para o valor ou 05 para o ndice). TipoQuantidade: 1 (um) caracter indicando o tipo de quantidade. I - Inteira e F - Fracionria. Quantidade: STRING com at 4 dgitos para quantidade inteira e 7 dgitos para quantidade fracionria. Na quantidade fracionria so 3 casas decimais. CasasDecimais: INTEIRO indicando o nmero de casas decimais para o valor unitrio (2 ou 3). ValorUnitario: STRING at 8 dgitos para valor unitrio. TipoDesconto: 1 (um) caracter indicando a forma do desconto. '$' desconto por valor e '%' desconto percentual. ValorDesconto: String com at 8 dgitos para desconto por valor (2 casas decimais) e 4 dgitos para desconto percentual. Fonte: www.bematech.com.br

Temos que passar a alquota que vamos utilizar (12%, 18%...). Tipo da quantidade tipo da quantidade (se inteiro ou fracionrio). Quantidade 4 dgitos para inteiro, podendo vender at 9.999 itens ou 7 dgitos quando fracionria, com 3 casas decimais. Casas decimais o nmero de casas depois da vrgula para o valor unitrio. Valor unitrio uma string at 8 dgitos. Tipo do desconto se tiver desconto (valor fixo ou percentual). Podemos dar desconto individualmente por item ou na nota inteira.

Exemplo: Vamos vender um item supondo 13 livros. - descrio o nome do produto vendido. - Alquota no caso est selecionando a 2 alquota cadastrada ou poderamos ter colocado 18%. - Colocamos a descrio, a aliquota, o tipo de quantidade (inteira), o nmero de unidades (valor com duas casas decimais 10 reais cada unidade) que no total vai dar R$50,00. - Vamos colocar o tipo de desconto por porcentual e tambm nada de desconto. Chamamos a rotina VendeItem passando todos os parmetros (cdigo, descrio, alquota, tipo). OBS: Por enquanto no temos o banco de dados, apenas estamos demonstrando como imprimir valores fixos , s para saber como chamar os dados, depois , no sistema, substituiremos o valor fixo pelos valores do banco de dados. Depois dos produtos vendidos, com todos os itens, temos que fechar o cupom.

131

11.13 - Rotina Iniciar Fechamento do Cupom Fiscal


Ajuda da BEMAFI32.DLL > Outras funes > funes especificas das impressoras fiscais MFD... > Bematech_FI_IniciaFechamentoCupomMFD
Inicia o fechamento do cupom fiscal. Permite acrscimo e desconto no fechamento do cupom. Parmetros: AcrescimoDesconto: STRING que indica se haver acrscimo no cupom, desconto ou ambos. "A" para acrscimo, "D" para desconto e "X" para acrscimo e desconto. TipoAcrescimoDesconto: STRING que indica se o acrscimo ou desconto por valor ou por percentual. "$" para desconto por valor e "%" para percentual. ValorAcrescimo: STRING com no mximo 14 dgitos para acrscimo por valor e 4 dgitos para acrscimo percentual. ValorDesconto: STRING com no mximo 14 dgitos para desconto por valor e 4 dgitos para desconto percentual.

// Exemplo em Delphi cAcresDesc := 'X'; cTipoAcresDesc := '%'; cValorAcres := '1200'; cValorDesc := '1000'; iRetorno := Bematech_FI_IniciaFechamentoCupomMFD( pchar pchar( cTipoAcresDesc ), pchar( cValorAcres ), pchar( cValorDesc ) );

( cAcresDesc),

Fonte: www.bematech.com.br Copie e cole na programao Como parmetro passamos o Acrscimo ou Desconto que vamos dar na nota. Esse acrscimo ou desconto no total geral. A para dar acrscimo e D para dar desconto. Tipo Se vai ser em percentual ou valor de desconto. Podemos dar R$0,00 de acrscimo e R$2,00 de desconto em cima do valor total do cupom. // D Acrscimo ou Desconto em Item posterior cNumeroItem := '001'; cDescAcresc := 'A'; cTipo := '$'; cValor := '10,00'; iRetorno := Bematech_FI_AcrescimoDescontoItemMFD( pchar( cNumeroItem ), pchar( cDescAcresc ), pchar( cTipo ), pchar( cValor ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 );

132 Bematech_FI_CancelaAcrescimoDescontoItemMFD
Cancela a acrscimo ou a desconto dado no item. Parmetros: Flag: STRING com "A" para cancelar o Acrscimo ou "D" para cancelar o Desconto. Item: STRING de at 3 dgitos com o nmero do item a ser cancelado restrito aos 300 ltimos registros efetuados. // Exemplo em Delphi cAcresDesc := 'A'; cNumeroItem := '005'; iRetorno := Bematech_FI_CancelaAcrescimoDescontoItemMFD( pchar ( cAcresDesc ), pchar( cNumeroItem ) );

Fonte: www.bematech.com.br // Cancela Acrscimo ou Desconto em Item Vendido Posterior cDescAcresc := 'A'; cNumeroItem := '001'; iRetorno := Bematech_FI_CancelaAcrescimoDescontoItemMFD( pchar( cDescAcresc ), pchar( cNumeroItem ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 ); Fazendo um joguinho: podemos dar um desconto em dinheiro no valor de R$5,00 e um acrscimo de R$ 10,00. // Inicia o Fechamento do Cupom Fiscal com Acrscimo e/ou Desconto cDescAcresc := 'X'; cTipo := '$'; cValorDesc := '05,00'; cValorAcre := '10,00'; iRetorno := Bematech_FI_IniciaFechamentoCupomMFD( pchar( cDescAcresc ), pchar( cTipo ), pchar( cValorAcre ), pchar( cValorDesc ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 ); Depois que Iniciamos o Fechamento do Cupom e aps o total ser definido, temos que especificar como vai ser pago: A vista, a prazo, em cheque, no carto, etc...) esta forma de pagamento registrada tambm no cupom fiscal.

133

11.14 Rotina Bematech FI EfetuarFormaPagamentoMFD


Ajuda da BEMAFI32.DLL > Funes da DLL > Funes Especificas das Impressoras Fiscais MFD > Bematech_FI_EfetuarFormaPagamentoMFD Funo Forma de Pagamento Para efetuar a forma de pagamento use esta funo
Imprime a(s) forma(s) de pagamento e o(s) valor(es) pago(s) nessa forma. Parmetros: FormaPagamento: STRING com a forma de pagamento com no mximo 16 caracteres. ValorFormaPagamento: STRING com o valor da forma de pagamento com at 14 dgitos. Parcelas: STRING numrica entre 1 e 24 com o nmero de parcelas em que o pagamento ser realizado. DescricaoFormaPagto: STRING com a descrio da forma de pagamento com no mximo 80 caracteres. Retornos da Funo (INTEIRO): 0 - Erro de comunicao 1 - Ok -2 - Parmetro invlido. -4 - Arquivo ini no encontrado ou parmetro invlido para o nome da porta -5 - Erro ao abrir a porta de comunicao -24 - Forma de Pagamento no programada. -27 - Status da impressora diferente de 6,0,0,0 (Ack, St1, St2 e St3) Observaes: - O nmero de parcelas utilizado para emisso do comprovante no fiscal vinculado. Poder ser emitido um comprovante para cada parcela. - A descrio ser impressa uma linha aps a forma de pagamento. - O fechamento do cupom com formas de pagamento deve ter sido iniciado. Exemplo: // Exemplo em Delphi cFormaPgto := 'Carto VISA'; cValorPago := '50,00'; cNumeroParcelas := '2'; cMsg := 'Compra parcelada'; iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar ( cFormaPgto ), pchar( cValorPago ), pchar( cNumeroParcelas ), pchar( cMsg ) );

Fonte: www.bematech.com.br Primeiro a forma de pagamento vai ser feita atravs de uma TEF (Transferncia Eletrnica de Fundos Carto) e descrita a forma de pagamento. A forma de pagamento vai ser a prazo. Chamamos Efetuar Forma de Pagamento escolhendo o pagamento em 3 vezes. Se o cliente vai fazer o pagamento da entrada dando uma nota de R$100,00, temos que devolver-lhe o troco. Esse valor que o cliente esta dando

134 e o troco que vai receber estaro registrados no cupom fiscal, assim como o numero de parcelas para pagamento a prazo e a descrio da forma de pagamento. // Programa a Forma de Pagamento cForma := 'A Prazo'; cTEF := '0'; iRetorno := Bematech_FI_ProgramaFormaPagamentoMFD( pchar( cForma ), pchar( cTEF ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 ); // Efetua Forma de Pagamento cValor := '100,00'; cParcelas := '3'; cDescForma := 'Compra parcelada em 30, 60 e 90 dias'; iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar( cForma ), pchar( cValor ), pchar( cParcelas ), pchar( cDescForma ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 ); At aqui foram feitos: - Impresso do cabealho da nota fiscal. - Os itens da nota. - Fechamento da nota. - Escolha da forma de pagamento - Escolheu como pagar. - Quanto foi dado em dinheiro e se tem troco ou no da primeira parcela.

Agora falta fechar o cupom

11.15 - Fechamento do Cupom Fiscal.


Ajuda da BEMAFI32.DLL > Funes da DLL > Cupom Fiscal > Bematech_FI_TerminaFechamentoCupom. A rotina que fecha o cupom se chama Termina Fechamento Cupom Fiscal
Termina o fechamento do cupom com mensagem promocional. Parmetro: Mensagem: STRING com a mensagem promocional com at 384 caracteres (8 linhas X 48 colunas), para a impressora fiscal MP-20 FI II, e 320 caracteres (8 linhas X 40 colunas), para a impressora fiscal MP-40 FI II.

135

Possveis retornos da Funo (INTEIRO): 0: Erro de comunicao. 1: OK. -2: Parmetro invlido na funo. -4: O arquivo de inicializao BemaFI32.ini no foi encontrado no diretrio de sistema do Windows. -5: Erro ao abrir a porta de comunicao. -27: Status da impressora diferente de 6,0,0 (ACK, ST1 e ST2). -36: Forma de pagamento no finalizada. Observaes: - A forma de pagamento deve ter sido efetuada. - Na impressora fiscal BEMATECH, sero impressas 8 linhas de texto. - Na impressora fiscal YANCO, sero impressas 4 linhas de texto. Cada linha com 46 colunas. Exemplo: // Exemplo em Delphi cMsgPromocional := 'Obrigado, volte sempre !!!'; iRetorno := Bematech_FI_TerminaFechamentoCupom( pchar ( cMsgPromocional ) );

Fonte: www.bematech.com.br Esta rotina s tem um parmetro A Mensagem Esta mensagem pode ser trocada de acordo com as promoes ou pocas do ano. // Termina o Fechamento do Cupom Fiscal cMensagem := 'Obrigado, volte sempre !!!'; iRetorno := Bematech_FI_TerminaFechamentoCupom( pchar( cMensagem ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 ); end; end.

Para que o programa possa rodar, as variveis tem de ser declaradas. Para verificar o funcionamento, deixe ligado o emulador Emulfith. Salve e compile o programa. Ao clicar no boto imprimir, verifique que no emulador ou na impressora fiscal, foi criado o cabealho, imprimiu o item vendido, o acrscimo e o desconto foram feitos, o cliente pagou com uma nota de R$100,00 e recebeu R$45,00 de troco. Foi uma conta a prazo. No final foi impressa a mensagem Obrigado, volte sempre!!!

136

Figura 57 Teste Impressora em execuo

Figura 58 Emulfith vr.1.02 mostrando dados da impressora fiscal.

****ECF DESBLOQUEADO****
Bematech Ind. e Com. de Equip. Eletronicos S.A. Estrada de Santa Candida, 263 82.630-490 Curitiba - Parana - Brasil CNPJ:82.373.077/0001-71 IE:10181465-30 UF:PR ------------------------------------------------

137
16/04/2006 10:42:27 CCF:000001 COO:000002 -----------------------------------------------CNPJ/CPF consumidor:1234567890 NOME:Fulano de Tal ------------------------------------------------

CUPOM FISCAL
ITEM CDIGO DESCRIO QTD.UN. VL UNITRIO( R$) ST VL ITEM( R$) -----------------------------------------------001 1234567890123 Produto de Teste 5 X 10,00 I1 50,00g Acrscimo item 001 +10,00g Cancelamento Acrscimo item 001 -10,00 -----------------Subtotal R$ 50,00 acrscimo 10,00g desconto -5,00 TOTAL R$ 55,00 A Prazo 100,00 Compra parcelada em 30, 60 e 90 dias TROCO R$ 45,00 -----------------------------------------------Obrigado, volte sempre !!!

11.16 Implementando o programa para uso com banco de dados.


Abra uma nova aplicao com os seguintes dados: Name Frm_Principal Caption Sistema de Vendas ECF -

Form Main Menu IBDataBase IBTransaction

Salvar Como U_Principal. Nota: No comeo da programao do Formulrio de vendas, no campo uses foi introduzida a linha U_Fiscal in Formularios\U_Fiscal.pas, conforme mostrado abaixo: program Venda; uses Forms, U_Principal in 'Formularios\U_Principal.pas' {Frm_Principal}, U_vendas in 'Formularios\U_vendas.pas' {Frm_Vendas}, U_Fiscal in 'Formularios\U_Fiscal.pas', U_Venda_Formapag in 'Formularios\U_Venda_Formapag.pas' {FRM_Venda_FormaPAg}; Crie uma Unit para colocar as rotinas da impressora. File > New > Unit

138 Salve dentro da pasta Formulrios com o nome U_Fiscal. Todas as rotinas da impressora fiscal foram colocadas numa outra Unit para poder chamar depois, porque todas as rotinas iriam se misturar no cdigo fonte. Ento para evitar misturar muitas rotinas e facilitar a leitura do cdigo fonte, foi criada a Unit U_Fiscal. As rotinas da programao da impressora fiscal fica dentro do campo Interface e no final da programao comea o campo Implementation e tudo que for colocado aps este campo no acessvel. Ento colocando dentro do campo Interface disponvel para fora da Unit. Lembra da Classe, onde temos os campos Private e Public. Tudo que colocamos numa interface de uma Unit comparado ao campo Public e tudo que estiver no campo Implementation Private.

unit U_Fiscal; interface // Funes de Inicializao function Bematech_FI_AlteraSimboloMoeda( SimboloMoeda: String ): Integer; StdCall; External 'BEMAFI32.DLL'; function Bematech_FI_ProgramaAliquota( Aliquota: String; ICMS_ISS: Integer ): Integer; StdCall; External 'BEMAFI32.DLL'; function Bematech_FI_CodigoBarrasPLESSEYMFD( Codigo: String ): Integer; StdCall; External 'BEMAFI32.DLL'; function Bematech_FI_CodigoBarrasPDF417MFD( NivelCorrecaoErros: Integer; Altura: Integer; Largura: Integer; Colunas: Integer; Codigo: String ): Integer; StdCall; External 'BEMAFI32.DLL';

implementation end.

Se for necessrio criar uma rotina, colocamos o cabealho no campo Interface e a programao no campo Implementation. Se precisarmos definir uma rotina dentro dessa Unit, uma procedure teste por exemplo, podemos declarar esta funo no campo Interface e no campo Implementation colocamos a programao repetindo o mesmo cabealho nos dois campos.

139

Se agora abrir o Unit vendas e chamar esta procedure teste pressionando as teclas CTRL + Barra de Espao, e digitando a rotina teste, esta aparecer nos campos para ser selecionada. Se tivermos alguma rotina para colocar na programao, podemos colocar nesta Unit e cham-la em outro formulrio, para que a programao fique ordenada e fcil de fazer uma manuteno. Como deixamos as rotinas disponveis dentro desta DLL, agora s chamar na Unit Vendas. Todas as rotinas que quisermos chamar em Bemafh disponvel nesta DLL encontrado na mesma hora como se estivesse feito na Unit chamadora. O que acontece no dia a dia da empresa? O usurio (vendedor) clicando em nova venda, aps abrir o formulrio ainda no selecionou quem o cliente (nome do cliente, CPF e endereo). Se fosse comandado uma impresso para a impressora fiscal sem esses parmetros no campo nova venda: - O primeiro comando abre o cupom passando trs parmetros (CPF, nome e endereo), s que no temos nenhum dos trs porque no foram selecionados ainda. - Se for pedido uma impresso, a impressora fiscal no imprimir esses dados, ficar em branco. Ento no podemos definir o cabealho nesta rotina (Nova Venda), temos que definir em outro local. Dentro desta rotina nova venda, teremos somente o comando Tbl.Insert. procedure TFrm_Vendas.Btn_NovaVendaClick(Sender: TObject); begin // Ao abrir uma nova venda, geramos um novo pedido e abrir // o cupom fiscal. Tbl_Ped.Insert; { possvel chamar a rotina de abrir o cupom aqui? R: No, pois o cliente ainda no foi escolhido. A soluo abrir o cupom ao salvar o pedido} end; Quando for clicado em nova venda, a programao da o Insert na tabela Tbl_Ped. Quando der o Insert na tabela, permite ao usurio escolher o numero, colocar a data ou atribuir direto do sistema e escolher o cliente. Antes de inserir o primeiro item , salvamos a tabela de Pedido, neste momento gerada o cabealho. No evento BeforPost da tabela de pedido fazemos o tratamento do cupom fiscal. procedure TFrm_Vendas.Tbl_PedBeforePost(DataSet: TDataSet); var CPF: String[30]; NumeroSerie : String[15]; NumeroCupom: string[6]; iretorno:integer;

140 begin {o tratamento para abrir um cupom fiscal deve ser realizado no evento befor post (antes de salvar) pois no esta certo que o cupom est fechado e a impressora est ligada. Se algo estiver errado com a impressora, devemos cancelar a venda. Se o tratamento fosse realizado no after post, o pedido j estaria salvo e no poderia apagar mais. } // CNPJ_CPF: STRING at 29 caracteres com o CNPJ ou CPF do cliente (opcional). CPF:= Tbl_Cli.fieldbyname('CPF_Cli').AsString; iRetorno := Bematech_FI_AbreCupom( ( CPF ) ); case iretorno of 0 : begin { erro de comunicao com a impressora. Tratamento especial} try // tratamento Tbl_Ped.Cancel; except showmessage('erro de comunicao com a impressora'); end; {Try} end; {0} 1: // j salva por padrao; { A impressora est liga e imprimiu (abriu) o cupom. Armazenar o numero do cupom e o numero da impressora antes de salvar. } begin //NumeroCupom: Varivel string com 6 posies para receber //o nmero do ltimo cupom. iRetorno := Bematech_FI_NumeroCupom( NumeroCupom ); {****************************************************************** NAO ESQUECER DE CRIAR OS CAMPOS NUMERO DE SERIE E NUMERO DO CUPOM NA BASE DE PEDIDOS ! ********************************************************************} //Tbl_Ped.FieldByName('numerocupom').asstring:= NumeroCupom; Showmessage(NumeroCupom + 'criar no banco!'); // NumeroSerie: Varivel string com o tamanho de 15 posies //para receber o nmero de srie. iRetorno := Bematech_FI_NumeroSerie( NumeroSerie ); //Tbl_Ped.FieldByName('NumeroSerie').asstring:= NumeroSerie;

141 Showmessage(NumeroSerie); end; -27 : // realizar o tratamento para cupom em aberto // ou problemas com a impressora; ; end; {case} end;

O usurio selecionou o cliente e colocou na tabela de pedidos CPF:= Tbl_Cli.fieldbyname('CPF_Cli').AsString; Na tabela de clientes selecionado o CPF escolhido e atribudo na varivel CPF, logo depois Abre Cupom na rotina abaixo, passando como parmetro o CPF: iRetorno := Bematech_FI_AbreCupom( ( CPF ) ); Esta rotina retorna um valor em iRetorno Cada vez que der erro na impressora fiscal, executa esta funo: Se retornar 1 deu certo, se retornar 0 - deu erro (A impressora pode estar desligada, houve um erro de comunicao) Se a impressora fiscal estiver desligada, cancelado o pedido, porque se for salvo o pedido e no for impresso o cupom um problema muito grande. Para evitar esse problema, se retornar 0, cancelamos a nota. iRetorno := Bematech_FI_AbreCupom( ( CPF ) ); case iretorno of 0 : begin { erro de comunicao com a impressora. Tratamento especial} try // tratamento Tbl_Ped.Cancel; except showmessage('erro de comunicao com a impressora'); end; {Try} end; {0} Antes de salvar, chamamos de novo a impressora e capturamos o numero do cupom fiscal que foi gerado seqencialmente ao abrir o cupom fiscal e gravamos em uma varivel que vai ser armazenado dentro do banco de dados. 1: // j salva por padrao; { A impressora est liga e imprimiu (abriu) o cupom.

142 Armazenar o numero do cupom e o numero da impressora antes de salvar. } begin //NumeroCupom: Varivel string com 6 posies para receber //o nmero do ltimo cupom. iRetorno := Bematech_FI_NumeroCupom( NumeroCupom ); {****************************************************************** NAO ESQUECER DE CRIAR OS CAMPOS NUMERO DE SERIE E NUMERO DO CUPOM NA BASE DE PEDIDOS ! ********************************************************************} //Tbl_Ped.FieldByName('numerocupom').asstring:= NumeroCupom; Showmessage(NumeroCupom + 'criar no banco!'); // NumeroSerie: Varivel string com o tamanho de 15 posies //para receber o nmero de srie. iRetorno := Bematech_FI_NumeroSerie( NumeroSerie ); //Tbl_Ped.FieldByName('NumeroSerie').asstring:= NumeroSerie; Showmessage(NumeroSerie); end; Isso servir para que a empresa possa gerenciar seus dados e verificar se um produto foi mesmo vendido em seu estabelecimento comercial. No cupom tem o nmero de srie e o numero da impressora, ento fica fcil verificar se um produto foi vendido ou no em um estabelecimento comercial, porque identificando o numero de serie e o numero da impressora fcil listar os itens vendidos. Guardamos os dois campos, no caso fazemos um comando para guardar no banco. Na tabela de pedidos, guardamos o numero do cupom. //Tbl_Ped.FieldByName('numerocupom').asstring:= NumeroCupom; //Tbl_Ped.FieldByName('NumeroSerie').asstring:= NumeroSerie; No foi criado no campo do banco de dados o nmero de srie e o nmero do cupom, ento foi feito um showmessage na tela para no dar erro, mas tem que ser criado os campos no banco de dados na tabela de pedidos. Showmessage(NumeroCupom + 'criar no banco!'); Showmessage(NumeroSerie); Logo depois que capturar o nmero do cupom, capturamos tambm o nmero de srie da impressora fiscal. Armazenamos os dois campos na tabela de pedido, antes da programao

143 BeforPost, porque se no salvou ainda, ento grava tudo (nmero da Impressora fiscal e nmero de srie da nota). Na impressora j foi salvo ento tem que ser armazenado no banco de dados tambm. -27 : // realizar o tratamento para cupom em aberto // ou problemas com a impressora; Este cdigo de erro serve para indicar outros erros tais como, impressora enroscada, fim do papel e outros erros j descritos anteriormente. Aqui termina a programao de salvar o pedido: Na hora que foi salvo, foi impresso o cabealho, e j gravou o numero da impressora fiscal e seu nmero de srie. Ao digitar ou ler o cdigo de barras e pressionar a tecla enter, efetua a programao OnKeyPress da tecla enter procedure TFrm_Vendas.Edt_BarraKeyPress(Sender: TObject; var Key: Char); var cod,Descr,Alicota,Qtd,Valor,Desconto:string; Decimal,iretorno: integer; tQtd,TDesc:Char; {I= inteiro, F= fracionada} aux:integer; begin if key = #13 then begin if not (Tbl_Prod.locate('cod_prod',Edt_Barra.Text,[])) then showmessage('produto no cadastrado. Verifique o codigo!') else Quando pressionar Enter - OnKeyPress = 13 (if Key= #13) feito o comando Locate para achar o produto, se existe ou no. Se no encontrar o produto mostra mensagem ('produto no cadastrado. Verifique o codigo!') else begin Tbl_Itens.Last; aux:= Tbl_Itens.FieldByName('COD_ITENS').asinteger; Tbl_Itens.Insert; Tbl_Itens.FieldByName('COD_ITENS').asinteger:=aux+1; Tbl_Ped.FieldByName('COD_PED').asinteger:= (Tbl_Itens.FieldByName('cod_ped').asinteger); Se o produto foi encontrado colocamos a tabela de itens no campo do ltimo item e armazenamos o cdigo do item na varivel aux.

144 Colocamos a tabela de Itens em modo de insero e somamos na varivel aux mais um (aux + 1) preenchido os demais dados o cdigo do pedido (cd_ped) da tabela de Itens armazenado na tabela de pedido. O cdigo do produto da tabela de produtos armazenada na tabela de itens. Tbl_Itens.FieldByName('cod_prod').asinteger:= Tbl_Prod.FieldByName('cod_prod').asinteger; Depois de armazenado todos os dados, pegamos o cdigo que foi armazenado na tabela de itens e jogamos dentro da varivel cd que a primeira varivel porque agora temos que chamar a rotina de imprimir cupom cod := inttostr(Tbl_Itens.FieldByName('cod_prod').asinteger); Na rotina de ImprimirCupom temos que passar os parmetros (cdigo, descrio, valor, etc.) Foi salva a descrio da tabela de produtos e armazenada dentro do campo descrio da tabela de itens. Descr:= Tbl_Prod.FieldByName('Desc_prod').asstring; A alquota foi fixada em 18% para o exemplo e salvamos a alquota usada (o cdigo 5 representa a alquota de 18%) //Aliquota: STRING com o valor ou o ndice da alquota // tributria. Se for o valor deve ser informado com o tamanho // de 4 caracteres ou 5 com a vrgula. Se for o ndice da // alquota deve ser 2 caracteres. Ex. (18,00 para o valor // ou 05 para o ndice). Alicota:='18,00'; {o valor vem da tabela produto}

Tbl_Itens.FieldByName('Imposto_Itens').AsString:='05'; No exemplo poderamos ter armazenado o valor da alquota de 18%, porque no dia da compra do item, foi vendido a 18% de alquota, e essa alquota pode mudar. Se o cliente apresentar uma nota fiscal antiga temos que saber quanto foi cobrada a alquota no dia da venda. Em vez de armazenar o cdigo da alquota podemos armazenar a porcentagem cobrada em virtude de mudana de alquota que pode ocorrer, sendo que o cdigo permanece o mesmo.

145 TipoQuantidade se fracionrio ou inteiro. Por exemplo, se o tipo for quilo, fracionrio. Se no for por quilo ento unidade (inteiro) // TipoQuantidade: 1 (um) caracter indicando o tipo de // quantidade. I - Inteira e F - Fracionria. tQtd:='I'; { if Tbl_Prod.fieldbyname('Tipo').asstring = 'Kg' then TQtd:='F' else TQtd:='I'; } Quantidade Por padro a quantidade igual a 1. O nmero de casas decimais estabelecido com at quatro dgitos para quantidade inteira e sete dgitos para fracionarias e na quantidade fracionaria estabelecido trs casas decimais. // Quantidade: STRING com at 4 dgitos para quantidade // inteira e 7 dgitos para quantidade fracionria. // Na quantidade fracionria so 3 casas decimais. Tbl_Itens.FieldByName('qtde_prod').AsInteger:=1; Qtd:= inttostr(Tbl_Itens.FieldByName('qtde_prod').AsInteger) ; O valor da tabela de Produtos armazenado na tabela de Itens: // CasasDecimais: INTEIRO indicando o nmero de casas // decimais para o valor unitrio (2 ou 3). Decimal:=2; // ValorUnitario: STRING at 8 dgitos para valor unitrio. Tbl_Itens.FieldByName('Valor_Venda').asfloat:= Tbl_Prod.FieldByName('Valor_Venda').asfloat; valor floattostr(Tbl_Itens.FieldByName('Valor_Venda').asfloat);

:=

Se existir algum desconto, tambm armazenado, no caso no tem desconto. {O tipo Desconto e o valor do desconto vem da tabela promo Cod_Prod, TDes,ValorDesc,Dataini e Datafim } // TipoDesconto: 1 (um) caracter indicando a forma do desconto. // '$' desconto por valor e '%' desconto percentual.TDesc:='$'; // O campo value substitue todos os tipos as... Tbl_Itens.FieldByName('TipoDesc').Value := TDesc; //ValorDesconto: String com at 8 dgitos para desconto por //valor (2 casas decimais) e 4 dgitos para desconto percentual. Desconto := '00,00'; Por ltimo, chamada a rotina Bematech_FI_VendeItem que imprime os itens no cupom

146

// inserir item na impressora iRetorno := Bematech_FI_VendeItem( ( Cod ), ( Descr ), ( Alicota ), ( tQtd ),( Qtd ), Decimal,( Valor ), ( TDesc ),( Desconto ) ); Lembre-se que a rotina retorna iRetorno, se tentou salvar e deu certo (cdigo 1) Tbl_Itens.Post (salva o item no banco de dados). // salvar no banco. case iretorno of 1: // salvar no banco begin Tbl_Itens.Post; end; Se deu erro (cdigo zero) A impressora estava desligada, ento a venda cancelada. 0: // impressora desligada begin try // Tratamento especial Tbl_Itens.Cancel; Except showmessage('erro de comunicao! Verifique o cabo!'); end; {try} end; {0} end; {case } Edt_Barra.Text:=''; end; {if locate} end; {if #13} end;

Aps ter concludo uma venda, pressionado o boto fechar da venda e escolher a forma de pagamento. Clicando no boto fechar mostrada outra tela para escolher a forma de pagamento: procedure TFrm_Vendas.BitBtn1Click(Sender: TObject); begin Tbl_Ped.Edit; FRM_Venda_FormaPAg.showmodal;

147 end;

Figura 59 Aspecto do formulrio Forma de pagamento para a venda. Aparece o total do pedido, o cliente escolhe a forma de pagamento. Quanto foi recebido para efetuar o pagamento e exibido o troco se existir. Aps selecionado os comandos e pressionada a tecla fechar venda. Quando pressionada esta tecla tem que ser iniciado o fechamento do cupom dando o desconto se existir. procedure TFRM_Venda_FormaPAg.Btn_FechaClick(Sender: TObject); var AcreDes: char; Tipo : char; valor: String[14]; iretorno:integer; cFormaPgto : String[16]; cValorPago : string[14]; cDescricao : string[80]; cMsgPromocional:string; apresentado o cupom fiscal dando o desconto se existir, se vai ser em percentual ou valor Begin // Iniciar o fechamento do pedido (desconto) { **************************** Ateno ************************ Se a empresa trabalha com cartes prprios de desconto ou mantm convnio com outras empresas, devemos incluir os campos Desconto e tipo de desconto na forma de pagamento. ****************************************************************} // AcrescimoDesconto: Indica se haver acrscimo ou desconto no cupom.

148 // 'A' para acrscimo e 'D' para desconto. AcreDes:= 'D'; // TipoAcrescimoDesconto: Indica se o acrscimo ou desconto por valor // ou por percentual. '$' para desconto por valor e '%' para percentual. Tipo:= '%'; // ValorAcrescimoDesconto: STRING com no mximo 14 dgitos para //acrscimo // ou desconto por valor e 4 dgitos para acrscimo ou desconto por percentual. valor:= '0000'; feito os clculos do desconto, mostrado no cupom, faz o fechamento do cupom mostrando se vai ter desconto ou acrscimo (o tipo e o valor desse acrscimo) e inicia o fechamento. iRetorno := Bematech_FI_IniciaFechamentoCupom( pchar( AcreDes ), pchar( Tipo ),( Valor ));

programada a forma de pagamento se a vista ou a prazo, no carto, cheque ou boleto bancrio e gravar no cupom fiscal // Fazer o tratamento especial { *******************cadastar formas de pagamentos **************** // Programa a Forma de Pagamento cForma := 'A Prazo'; cTEF := '0'; iRetorno := Bematech_FI_ProgramaFormaPagamentoMFD( pchar( cForma ), pchar( cTEF ) ); iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK, iST1, iST2, iST3 ); // Efetua Forma de Pagamento cValor := '100,00';cParcelas := '3'; cDescForma := 'Compra parcelada em 30, 60 e 90 dias'; iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar( cForma ), pchar( cValor ), pchar( cParcelas ), pchar( cDescForma ) ); ******************************************************************* } // Escolher a forma de pagamento //Imprime a(s) forma(s) de pagamento e o(s) valor(es) pago(s). //Permite a impresso de comentrios na(s) forma(s) de pagamento // FormaPagamento: STRING com a forma de pagamento com no mximo //16 caracteres./ // ValorFormaPagamento: STRING com o valor da forma de pagamento // com at 14 dgitos. // DescricaoFormaPagto: STRING com a descrio da forma de

149 // pagamento com no mximo 80 caracteres. No final recolhido o valor recebido e chamada a impressora fiscal para terminar a venda mostrando a forma de pagamento, o valor pago e a descrio da forma de pagamento(3, 4, 5 vezes). No final ao fechar o cupom exibida mensagem promocional com at 384 caracteres que teoricamente deve estar gravada no banco de dados. cFormaPgto := Frm_Vendas.Tbl_FPag.fieldbyname('DESC_FORMA').AsString; cValorPago := Edt_Recebido.Text; cDescricao := '10/12/2005 - 25,00 10/01/2006 - 25,00'; iRetorno := Bematech_FI_EfetuaFormaPagamentoDescricaoForma(( cFormaPgto ), ( cValorPago ), ( cDescricao ) ); // Fechar a venda (Mensagem) //Termina o fechamento do cupom com mensagem promocional. //Mensagem: STRING com a mensagem promocional com at 384 //caracteres (8 linhas X 48 colunas), para a impressora fiscal //MP-20 FI II, e 320 caracteres (8 linhas X 40 colunas), para a//impressora fiscal MP-40 FI II. cMsgPromocional := 'Obrigado, volte sempre !!!'; iRetorno := Bematech_FI_TerminaFechamentoCupom( pchar( cMsgPromocional )); Frm_Vendas.Tbl_Ped.Post; end; end.

150

12 DECISION CUBE
CRM - Relacionamento com o cliente Um software de integrao com o cliente. No caso de uma promoo possvel dar 10% de desconto aos clientes que compram entre os perodos A e B, ou que nasceram em uma data especifica. Se o CRM estiver ligado com um sistema CallCenter (telefonia), o prprio sistema liga para o cliente e coloca da base de dados do cliente os funcionrios que atenderam esse cliente pela ltima vez. O sistema CallCenter liga para o cliente verificando qual funcionrio que falou com esse cliente pela ltima vez, ento busca outro vendedor ou atendente que no seja o ltimo que falou com o cliente, porque pode ser que o cliente no tenha sido bem atendido pela ultima vez e descarta esse vendedor. Aps estabelecer contato com o cliente o funcionrio se identifica e com um script pronto na tela, desenvolve um dialogo anotando fatos indispensveis para um relacionamento mais prximo com o cliente, para quando ligar outra vez vai falar desses fatos, dando a impresso ao cliente que o conhece muito. Para efetuar uma venda, o vendedor informa uma promoo para esse cliente, com forma de pagamento em 60 dias um diferencial de uma maneira que obrigue o cliente a comprar, tentando forar uma venda. Quando efetuamos uma venda com o sistema CRM, no campo de observaes, anotamos fatos pessoais do cliente: do que gosta, o que faz isso para criar um vinculo de relacionamento. Quando terminar uma campanha, atravs dessa ferramenta possvel saber quanto foi vendido, quantos clientes compraram e quantos no compraram, qual tipo de reclamao foi relatado. Com base nesses dados e outros anotados possvel fazer uma mudana na empresa.

12.1 - BI (

) - Negcio Inteligente

uma ferramenta para extrao de dados. O funcionamento baseia-se em extrair dados das tabelas de um banco de dados, fazer combinaes desses dados para tomada de deciso gerencial. Uma tabela do banco de dados tem vrios atributos, por exemplo: cdigo do produto, descrio, valor, nome do cliente, endereo, etc.. Com esses dados, essa ferramenta gera um cubo de deciso, combinando informaes e transforma num cubo 3D. Cada combinao gera uma informao diferente que podem ser infinitas. Diferente de uma consulta em SQL, se fizermos um relatrio para consulta, s teremos aqueles dados definidos, mas no BI podemos ter a consulta que quisermos, gera um valor que desejamos. Seria um gerador de consultas.

151

12.2 - A implementao da ferramenta

Figura 60 Componentes da paleta Decision Cube. A paleta do Decison Cube tem um total de seis componentes: 1 DecisionCube, 2 DecisionQuery, 3 DecisionSource, 4 DecisionPivot, 5- DecisionGrid e 6 DecisionGraph. 12.2.1 - Descrio: 12.2.1.1 DecisionCube. Neste componente efetuada toda a programao que existe comparado a um componente DataBase da paleta BDE. Acrescente um objeto TdecisionCube a um form ou data module para permitir uma aplicao para representar o cruzamento de dados. TDecisionCube analisa os dados de uma fonte de informaes para uma estrutura multidimensional onde cada dimenso corresponde a uma sumarizao (um resumo). Alguns dados podem ser usados como fontes de um objeto TDecisionCube, mas mais fcil trabalhar com TDecisionQuery. TDecisionCube possui propriedades e mtodos para formatar dados para um componente TDecisionSource que, por sua vez, disponibilizar para os componentes TDecisionGraph e TDecisionGrid Usualmente, os valores resumidos so calculados para o dataset que a fonte do decision cubes. Contudo , valores mdios podem ser calculados internamente em vez do Decision Cube. Mdias calculadas internamente tem a vantagem que podem ser pivotadas, subtotalizadas, e colocadas corretamente pelo Decision grids que mostra os dados do Decision Cube. TDecisionCube introdus propriedades e mtodos que liga uma tabela para fornecer estes dados a um TDecisionSource. Decision grids e Decision graphs no recuperam dados diretamante do decision cube. Eles usam um TDecisionSource, que representam uma configurao da dimenso do TDecisionCube. O componente decision cube, TDecisionCube, suprimento de dados multidimensional que busca estes dados de um dataset (tipicamente uma estrutura especial SQL declarada atravs de TDecisionQuery ou TQuery). Os dados so armazenados em um formulrio que produzem dados fceis de pivotar (isto , mudam o sentido em que os dados esto organizados e sumariza) sem necessidade de rodar a query.

152

12.2.1.2 DecisionQuery. Comparado a uma Query comum, neste componente a programao feita em SQL. Na hora que preenchemos o SQL temos que indicar os campos que queremos abrir. Use um componente TDecisionQuery como um dataset de um decision cube para assegurar que os dados estejam bem preparados. TDecisionQuery liga as dimenses e sumariza para definir diretamento no dataset analisando em um decision control. Ento fazemos uma SQL query para providenciar a informao daquele dataset em um formato que pode ser usado pelo decision cube. Decision cubes pode usar outros tipos de datasets, mas a informao pode ser estruturada no mesmo caminho para a sada do TDecisionQuery. Nota: No editor Decision Query que mostrado do componenste Decision query, a pergunta inicialmente manuseada em sintaxe ANSI-92 SQL, e transcrita (se necessrio) dentro do dialeto usado pela fonte de dados da query. Use somente padro ANSI SQL no editor Decision Query. Uilize o dialeto da fonte de dados na propriedade SQL do Decision Query. 12.2.1.3 DecisionSource Use TDecisionSource para fornecer dados para um decision grid ou decision graph com tabelas de um decision cube. TDecisionSource representa um piv particular de dimenses do decision cube de linhas e colunas. TDecisionSource tambm fornece mtodos para mostrar a dimenso para focar em um sumrio um valor simples ou ocultar ou mostrar dimenses no piv. Todos os controles de deciso que divide uma fonte de desiso mostra o mesmo estado do piv. Por exemplo, um formulrio pode conter uma decision grid e um decision graph lincados com o mesmo decision sourse. Pivotando a dimenso do decision grid far automaticamente um update da imagem do grafico tratado. Para o display separar em duas projees da informao de um decision cube em um formulario simples, use dois decision sources separados. O estado do piv de uma decision source pode ser trocado pela manipulao de um decision grid ou pelo uso de um decision pivot. 12.2.1.4 DecisionPivot Adicione um decision pivot para permitir o uso de controles de estados do piv do decision graphs e decision grids. Decision pivots contem votes que coprrespondem as dimenses ativas de um decision cube e um drop-down list box para escolher o sumario desejado. Pressione os botes de dimenso para abrir ou fechar a dimenso, controlando se o decision source fornece valores para outras dimenses. Clicando o boto do decision pivot restabelecido um menu que permite usar o controle de estado da dimenso. Exercita o focus da dimenso em um valor simples com a dimenso. Arrastando os botes de um decision pivot reorganizamos as dimenses do decision source dentro de uma nova configurao do piv.

153 Nota: No use o Decision pivot para piv, subtotal, ou exercicio no sumario que no ser aditivado. Sumrios SUM e COUNT sao aditivados, AVERAGE (a menos que calculado pelo Decision cube), MAX, e MIN no. 12.2.1.5 DecisionGrid Utilize um TDecisionGrid para adicionar um decision grid no formulrio. Decision grids apresenta um sumario simples que calculado sobre um numero arbitrrio de dimenses. As dimenses podem aparecer como linhas ou colunas na grid, com o valor de campo das dimenses listadas como labels ao longo do topo e na borda esquerda da grid. O campo que sumarizado e os campos (dimenses) que so sumarizados por cima podem ser chamados dinamicamente aps rodar para mostrar algumas configuraes do sumario e dimenses fechadas para o mapa de dimenses do decision cube. Para chamar as dimenses e sumarios, esta pode ser inicializada pela manipulao direta decision grid, ou usando o objeto TDecisionPivot . TDecisionGrid possui propriedades, eventos e mtodos herdados de TcustomDecisionGrid, mas no introduz novos comportamentos. Para apresentar os dados de um grfico, use TdecisionGraph.. 12.2.1.6 Decision Graph Utilize TDecisionGraph para colocar um decision graph em um formulrio. O grfico Decision graphs um sumario simple que calculado por cima de um nmero de dimenses. As astes do grfico correpondem a estas dimenses, que so providenciadas por um objeto decision source. Por padro a primeira linha da dimenso apresenta-se como o X do eixo e a primeira coluna da dimenso apresenta-se como o Y do eixo. A rea que sumarizada e as reas (dimenses) que so sumarizadas por cima podem ser mudados dinamicamente para mostrar algumas configuraes do sumario escolhendo o dimension map de um decision cube. Mudanas para as dimenses e cumarios podem ser inicializadas usando um objeto TDecisionPivot. TDecisionGraph utiliza muitas das propriedades, eventos e mtodos herdando de TCustomDecisionGraph, mas no introduz novos comportamentos. Para apresentar os dados em uma grid, use TDecisionGrid. Dimenses(Dimensions) Campos usados para as linhas e ttulos de uma coluna e que no levam sinal de igual. So os botes que clicamos para abrir no DecisonPivot. Resumos(Summaries) Todos os campos que tem agregao(sum, count e average). Os campos do banco de dados que iremos usar tem: data do pedido, idade do cliente, categoria, opcionais e valor.

154 Para o exemplo crie no Paradox a seguinte tabela:

Figura 61 Tabela Vendas.DB no paradox. Salve a tabela como Vendas.DB Esses campos so os dados que entraram na programao do SQL que queremos buscar. Temos tambm uma totalizao que podemos somar, contar, verificar o valor mdio. Esses campos so os que tambm podero entrar na programao do SQL SELECT Data_ped, Idade_Cli, Categoria, Opcionais, Valor, SUM( Valor ) valores, COUNT( Data_ped ), COUNT( * ) COUNTALL FROM vendas v GROUP BY Data_ped, Idade_Cli, Categoria, Opcionais, Valor aqui que so colocados os campos que aparecem em percentual. Foi feito um select comum para trazer todos os campos (Select * from vendas) Pedimos todos os campos que queremos que traga e os agrupamentos (agrupados por valor, por valor mximo, mdio, mnimo, percentual, etc.).

155 Como esto agrupados, todos os campos que no pertencem a um SUM, MDIA, tem que aparecer dentro do value por SQL. Vamos fazer um SQL indicando campos normais. Os campos agrupados tem que serem feitos com o comando Select. No exemplo, s estamos utilizando uma tabela de eventos, mas se tivermos 10 tabelas, colocaramos 10 tabelas com clausula Where fazendo as ligaes dos cdigos das tabelas ou valor de uma tabela igual ao valor de outra. Colocamos na programao SQL s os valores que queremos na consulta.

12.3 Criando uma aplicao exemplo


Crie uma nova aplicao com os seguintes componentes: Da Paleta Win32 - 1 PageControl com duas abas. Da Paleta Standard - 1 Panel Da Paleta BDE - 1 componente DataBase Da Paleta Decision Cube 1 componente DecisonQuery 1 componente DecisionCube 1 componente DecisionSourse 1 componente DecisionGrid 1 componente DecisionPivot em cima do Panel 1 componente DecisionGraf na segunda aba do PageControl. Selecione a PageControl e coloque o nome das abas na propriede Caption: Dados e Grfico, respectivamente. Acrescente o Componente DecisionGraf na Aba Grfico. O Formulrio ficar com o seguinte aspecto:

Figura 62 Formulrio exemplo do Decision Cube.

156 Ligue o componente DataBase ao banco de dados criado anteriormente. Para acessar a tabela, s colocamos o Path (nome do diretrio, exemplo: C:\Alunos\software\Dados\) Para acessar a tabela usaremos um comando Select do SQL (Select * from vendas) mostrado logo mais. Coloque em Name do DataBase o nome: teste. Escolha para o Driver name: STANDARD Clique no Defauts da tabela e coloque o nome do diretrio aps o PATH.

Figura 63 Parmetros do DataBase. Desmarque Login prompt. Clique em OK Nas propriedades do componente DataBase coloque Connected = true. 12.3.1 - Decision Query Duplo clique no componente DesisionQuery Abrir a tela abaixo. Na propriedade do componente DecisionQuery indique em DataBaseName o nome do DataBase = teste. Escolha a tabela vendas no campo table que alias nica. Nesta tela aparecem todos os campos. Ento indicamos quem abre dimenso e quem sumario.

157

Figura 64 Decision Query Editor. Nesta tela clicando nos campos da lista da esquerda (List of Available Fields) podemos adicionar para a coluna das dimenses (Dimensions) os campos que desejamos apresentar, como por exemplo: Data_ped, Idade_Cli, Categoria, Opcionais e Valor. Os campos que iro compor a dimenso so aqueles que podemos arrastar de um lado para outro para aparecer na linha ou na coluna da Grid. A soma no arrastamos, aquele que aparece no canto e selecionamos os valores que iro aparecer, podendo escolher o nmero de registros, a soma, a mdia o valor que vai aparecer na Grid como valor de campo. No resumo (Summaries) colocamos os campos que sofrem agregao, podem ser contados e levam sinal de igual, por exemplo, nas SQLs, podemos definir os SUM, COUNT E AVERAGE. Tudo que tiver campo normal, colocamos na Dimenso e tudo que tiver de somatrio colocamos no Sumario. Aps selecionar os campos dentro da Dimenso e do Sumario o sistema automaticamente gera o SQL. Clique em SQL Query para verificar:

158

Figura 65 Comandos SQL para a tabela do Decision Cube. Selecionamos qual SQL da tabela (que o nome dos campos que vamos mostrar). Se tiver somatria media, ou contar o nmero de registros, temos que colocar no campo (SUM, COUNT, MEDIA) da programao SQL, conforme exemplo do quadro acima. Indicamos o nome da tabela (FROM vendas) e indicamos um GROUP BY em todos os valores que no forem totalizados. Na propriedade do componente DecisionQuery colocar Active = true. 12.3.2 - DecisionCube De duplo clique no componente DecisionCube DecisionCube o componente que executa as combinaes, o corao do processo. responsvel por efetuar a anlise dos dados em um dataset e montar a estrutura multidimensional em que cada dimenso corresponde a um campo do dataset sobre as informaes que devem ser resumidas. Ao clicar em MemoryControl, aparece o numero de registros, onde podemos escolher a quantidade de registros que quisermos, tipo grade do Ecxel.

159

Figura 66 Controle de memria do Decision Cube Editor. Ao clicar em Dimension Settings, aparece todos os campos na coluna Available Fields. Por padro no campo Grouping aparece none (campos no agrupados), o nico que agrupamos a data, que pode ser por ms, ano, trimestre. No nosso exemplo utilizamos o agrupamento por ano. Se quisermos totalizar com duas datas, colocamos dois campos tipo Data (Data1 e Data2), podemos colocar um Label para indicar Data1 e outro para indicar Data2. Na programao do SQL colocamos duas datas, a primeira data chamamos de Data1 que usaria o mesmo campo (Data_ped) da Data2. O Data1 podemos totalizar por ms e a outra por Ano, ento podemos saber a venda por ms e por ano.

Figura 67 Formatao da Data no Decision Cube.

160

12.3.3 - DecisionSourse Componente DecisionSourse Liga os dados gerados com os componentes visuais tipo DataSourse Clique no Componente DecisionSourse e informe o DecisionCube que vai relacionar. 12.3.4 - DecisionPivot Os botes de comando o componente DecisionPivot e a nica propriedade que preenchemos o DecisionSourse nas propriedades do componente. 12.3.5 - DecisionGrid A Grid o componente DecisionGrid a propriedade a ser preenchida o DecisionSourse. 12.3.6 - DecisionGraph Se quisermos um grfico, podemos colocar a janela de grficos e preenchemos a propriedade DecisionSourse. Salve o projeto

12.4 - Executando o Aplicativo


Com uma base de apenas 20 registros possvel demonstrar a ferramenta num bando de dados de uma revenda de automveis. O banco de dados tem os seguintes campos: Idade do cliente, categoria do veculo, opcionais que foram vendidos, o valor de venda do veiculo e a data de compra. 12.4.1 - Exemplo 1: Podemos saber quantos carros foram vendidos com e sem ar condicionado - Na combinao feita mostrado que foram vendidos 14 carros com ar e 6 sem ar condicionado num total de 20.

Figura 68 Amostra de Opcionais vendidos.

161

12.4.2 - Exemplo 2: Se quisermos saber por idade, a ferramenta mostra para cada idade que tipo de compra efetuada pelo cliente, se com ou sem ar condicionado. Isso pode ser visualizado num grfico, ento verificamos que pessoas de 24 a 36 anos tem a tendncia de comprar carros que tem ar condicionado. Ento o cliente com mais idade sempre vai comprar um carro que tem ar condicionado? Na maioria dos casos do exemplo, sim. Porque? Provavelmente est mais estabelecido financeiramente e tem condies de comprar esse opcional. Se pensarmos, o cliente que tem uma idade entre 18 e 19 anos, est comprando seu primeiro carro Estamos extraindo informaes.

Figura 69 Grfico de amostra por idades de clientes.

Figura 70 Amostra de idade e opcionais.

162

12.4.3 - Exemplo 3 Se quisermos saber qual a categoria de carro que mais vende com ar e sem ar condicionado: Pode aparecer no grfico, por categoria. Essa pesquisa pode mostrar as categorias que no vendem sem ar condicionado. No exemplo pesquisado verifica-se que carro Esport Utilit praticamente no vende sem ar condicionado, Perua a mesma coisa. Agora, o Sedam praticamente empata com ou sem ar. Se for colocado um carro Sedam sem ar no mercado, provavelmente ser vendido, mas se colocarmos uma perua nova no mercado sem ar condicionado, pelo exemplo no ser vendida. Estamos descobrindo padres.

12.4.4 - Exemplo 4 Se quisermos saber como tem sido a evoluo dos valores desses carros: Exemplificando carros esportivos, verificamos que so vendidos na faixa de R$ 35.000,00. Uma perua est na faixa de preo de venda de R$ 36.000,00. Um Esport Utilit vende bem mais carro, como mostra na ferramenta. 12.4.5 - Exemplo 5 Se quisermos descobrir a evoluo das vendas por ano, podemos colocar a Data e o Valor das vendas por ano. As vendas de cada ano podemos comparar com a faixa dos valores dos carros. Verificamos que foram vendidos os carros na faixa de R$ 35.000,00 12.4.6 - Exemplo 6 Podemos saber quem o comprador de cada categoria quem o comprador de um Sport Utilit. Selecionando a categoria, a idade e os compradores por tipo, verificamos que na faixa de 24 anos o cliente compra uma perua. De 25 o cliente compra um Esportivo. De 36 anos compra-se um Esport Utilit. De 45 anos equilibrado, tanto compra um Sport Utilit, como um Sedam. Ento podemos descobrir por essas combinaes as categorias que so adquiridas em determinada faixa de idade. Nestas combinaes podemos ver tanto em formato de dados , quanto em formato de grficos. 12.4.7 -Exemplo 7 Podemos verificar o volume de vendas e o valor mdio de cada caro por ano. O valor mdio no caso do Esport Utilit tem permanecido o mesmo, mas no caso da perua o valor mdio subiu muito. Se for zero(0) porque no ano anterior no foi vendido nenhum. No caso do esportivo o que mais subiu de preo em relao ao ano anterior. Ento podemos calcular o valor do preo do produto atual, o valor de venda. Podemos saber que tipo de caro vendemos a cada preo, colocando o valor e a categoria. Podemos saber tambm quantos carros vendem por cada faixa de preo, em vez de valor, pegamos um contador (quantos esportivos foram vendidos na faixa de R$ 30.000,00, quantos da faixa de R$ 35.000,00) 12.4.8 - Exemplo 8 Podemos ver a venda s em relao a 2004, selecionando o campo data de venda por ano. clique com o boto direito e...

163 Ver as vendas s de 2005 ou tambm em todo o perodo. Abrimos a dimenso e fazemos o comparativo do ano de 2004 e 2005. Podemos comparar os valores ao longo dos anos ou por ms. 12.4.9 - Exemplo 9 Por opcionais, podemos saber o valor mdio, em que faixa de carro podemos vender com ar condicionado Verificamos carros na faixa de 30 a 35 mil e carros na faixa de 43 a 46 mil 12.4.10 Exerccio Trabalho: Com base no sistema dado em aula (Vendas), faa a modificao do mesmo, contendo as seguintes caractersticas: a) Impressora Fiscal b) Componente de Cdigo de Barras c) C2 d) Decision Cube (BI) com relacionamento de 3 tabelas.

164

13 - CORREIO ELETRNICO
Podemos enviar via email, uma propaganda de um novo produto ou um novo servio. Vamos supor que uma loja de CD de jogos tem no cadastro de clientes os tipos de jogos preferidos por esses clientes. Ento chega um produto novo, e consultando na base, verificamos todos os clientes que gosta daquele novo produto e passamos um email, dizendo que chegou tal tipo de jogo neste email podemos anexar um arquivo do ofice, mandando um prospecto do jogo, a imagem do jogo, o que da para fazer nos jogos, etc. Neste caso podemos ganhar novos clientes sem precisar efetuar ligaes via telefone. Na pesquisa feita no BI fcil descobrir qual o perfil do cliente, o que mais compra , o produto que mais vende, depois achamos o publico alvo e enviamos uma mala direta para esse cliente, pelo BI atravs da internet.

13.1 - Email no Delphi


- Funcionamento da ferramenta - Demonstrao - Quando executamos esse programa aparece o campo onde pode ser colocado vrios endereos de emails. - Pode ser enviado para vrios endereos de email com cpia. Podemos colocar o assunto ou span direto. - Pode ser definida a prioridade do envio do email (baixa, mdia ou alta). - Pode ser requisitada uma confirmao do recebimento do email. - Podemos anexar um ou mais arquivos (um oramento por exemplo). Podemos fazer um teste enviando para ns mesmo um email atravs da ferramenta. Para verificar se o email foi enviado, verifique atravs do outlook e manda baixar seus emails. Abra e verifique se chegou o email teste. O que preciso ter - Abrimos um email em qualquer servidor de email. S um endereo de email e a senha. Ento a ferramenta usa esse email para fazer um Span. Se tivermos um servidor de email, por exemplo: suporte @unilins.com.br - ento colocariamos esse endereo de email (um email retorno), username e a senha para conectar, igual ao endereo do servidor (IP do servidor), estaremos usando a caixa postal daquele email para manda para outros endereos. No fica no servidor, s passa por ele e enviado para os outros. Neste exemplo foi colocado um endereo fixo, mas poderia ser colocado de um banco de dados (uma string). Podemos guardar uma String, acessar essa string posteriormente e colocar no email para envio, atravs de um comando select (seleciona os clientes e passamos um span para todo mundo). A primeira verso do aplicativo no tem um banco de dados, depois adicionamos o banco para a consulta e fazemos um span de verdade..

13.2 - Diferena ente servidor ftp e pop3


Do lado do cliente, se quisermos enviar um email, o protocolo de envio de amail o FMTP. No FMTP temos que enviar: endereo de origem do email (endereo de resposta) a partir da conta que queremos enviar o email e a mensagem ou destinatrio.

165 - O protocolo POP3 o que recebemos mensagem. Precisamos enviar a mensagem indicando o destinatrio, a origem, a senha e retornando a mensagem. - Teoricamente o POP3 bem mais simples que o FMTP. No nosso exemplo no fazemos um programa para email, porque j tem muitos no mercado. Vamos fazer nosso sistema para enviar email e no s para propaganda. Um exemplo de caso peculiar: temos um software e alugamos esse software por ms e todo final do ms ele expira. Fazemos um algoritmo no programa e depois de 30 dias expira comparando datas criptografadas. Todo ms temos que mandar uma chave para o usurio (um nmero que vale por 30 dias). Para fazer uso, geramos um arquivo (igual contas a pagar e a receber) e mandamos para um banco escolhido, gerando um padro de comunicao com o banco (um arquivo txt, tipo arquivo de exportao, importao). Enviamos esse arquivo de cobrana para o banco. Quando o cliente pagar o boleto no banco, esse retorna para ns um arquivo txt tambm. Esse arquivo txt padro e informa qual o cliente que pagou. Todo dia exportamos esse arquivo txt para o banco e quando importar o arquivo txt de volta e sabendo quais os campos, vamos no banco de dados para verificar quais so os clientes que pagaram. Damos a baixa no pagamento e j envia por email a senha para mais 30 dias de uso. Tudo isso automtico no banco de dados. O nico trabalho clicar um boto e importar o arquivo que estamos recebendo do banco, o resto tudo automtico: a importao, a baixa no pagamento e o envio do email ao cliente. O que temos que fazer enviar os dados para um servidor. Para executar nosso exemplo necessrio ter uma conta de email que consiga abrir no Outlook e um servidor FMTP. Para executar o teste crie um conta de email para executar o nosso programa

13.3 - Criando o Formulrio


Abra um novo projeto. File > New > Application Acrescente no formulrio: Da paleta Standard: 4 Edits 6 Labels 1 ComboBox 1 ChekBox 1 ListBox 1 Memo 3 Buttons Da Paleta Dialogs: 1 OpenDialog 1 IdsMTP 1 IdMessage

Da Paleta Indy Clients: Da Paleta Indy Misc:

166

Nomes e propriedades dos componentes: Componente Edit 1 Edit 2 Edit 3 Edit 4 Label 1 Label 2 Label 3 Label 4 Label 5 Label 6 ComboBox Propriedade Name Edt_Para Edt_Copia Edt_CopiaOculta Edt_Assunto cbxPrioridade Caption Para CC CCO Assunto Prioridade Mensagem Items (String) Alta Media Baixa Text Alta

ChekBox ListBox Memo Button 1 Button 2 Button 3 OpenDialog IdsMTP IdMessage

cbxConfirmaLeitura Confirmar recebimento Lb_Anexos mmMensagem Btn_Anexar Anexar Btn_Limpar Limpar Btn_Enviar Enviar odAnexos idMessage IdsMTP -

Para o exemplo o formulrio ficar com o aspecto mostrado abaixo:

167

Figura 71 Formulrio de email no Delphi. - Na propriedae Items do combobox, cadastrar os itens necessrios, no caso: Alta, Media e Baixa prioridade. So trs formas de enviar os emails - Normalmente a prioridade dos emails estar na mdia que o normal. No nosso exemplo colocaremos por padro em Alta Prioridade. O item padro ser a Alta (Item index = 0).

13.3.1 - CheckBox Confirmar recebimento Por padro checkd = false.

13.3.2 - Memo O memo parecido com o Edit, a diferena que o memo pode ter vrias linhas de texto e quanto terminar o quadro do texto gera uma barra de rolagem para continuar escrevendo. Em propriedade Line do memo pode deixar em branco ou deixar uma mensagem.

168 Por exemplo: Se nosso programa quisesse gerar uma String, podemos colocar o nome do componente (MM_Mensagem.Line.Adt) - esta linha vai adicionando as mensagens que se deseja colocar. Bom dia - Caro Senhor - igual a SQL

13.3.3 - Componente OpenDialog Na propriedade Filter mostrado os filtros a serem disponveis. usado para: abrir todos os arquivos (*.*), Documentos(*.Doc), Imagens (*.Jpg, *.Gif, *.bmp) e Executveis (*.exe).

Figura 72 Object Inspector do componente odAnexos (TOopenDialog)

Figura 73 Editor de filtro no Object Inspector do componente odAnexos. Se quiser colocar em documentos entre parnteses (*.DOC) para saber o que buscar fica melhor, seno aparece s o asterisco e no sabemos o que significa). Quando for executado vai aparecer a mascara de busca e trazer duas coisas:

169 - FileName: O nome do arquivo com Path completo. Quando for escolhido o arquivo com Path completo anexado, esse arquivo vai ser copiado dentro do (Programa Label) trazendo o Path e o arquivo, tudo junto. - Initial Dir (Diretrio Inicial) - Se no for colocado nada, vai comear a partir do diretrio que estava com .exe. Se tiver iniciado com meus documentos, o programa entra no arquivo e comea a abrir esta pasta. - se quiser abrir em outro diretrio, por exemplo a partir do disco C, ento coloque C: - O FileName no para ser preenchido a no ser que seja preciso salvar o arquivo. Na hora que o usurio estiver abrindo, ele mesmo seleciona o arquivo 13.3.4 - Componente - IBMessage Adicionar um componente para colocar a mensagem que for utilizar. Entre os itens que temos que passar, temos a mensagem inteira, o pacote inteiro (a mensagem na verdade extenso .txt), combina, gera o arquivo .txt e passa o texto inteiro. o componente para capturar toda mensagem. Se encontra na paleta Indy Misc. Toda paleta Indy para trabalhar com internet. Propriedade Encoding - o formato que vai gerar o txt, porque na verdade sempre um txt que enviado, por padro o meMIME. Na propriedade from, clique no sinal +. Crie um email para teste em um provedor

Temos que preencher a Web - Address (o seu endereo de Email para o cliente retornar depois). Name - o nome que queremos que aparea no Email. Por exemplo: Na hora que aparecer a pessoa recebe (...From<nome>). Em Name podemos colocar o nome de nossa empresa (exemplo: From Sistema de vendas). O lltimo - text - gera sozinho - o nome (Name + Address) - gerado internamente.

170

Figura 74 Object Inspector do componente idMessage.

13.3.5 - Componente IdsMTP Depois precisamos do cliente de coneco para enviar email. IdsMTP - Esse componente que vai gerar realmente a conexo com o banco. Propriedade Host: O nome do provedor que esta mandando o banco de dados, geralmente sMTP.<nome do provedor>.

Figura 75 Object Inspector do componente idSMTP.

171 O host ou o IP da mquina ou o nome da mquina. Mais fcil colocar o nome. Ex: smtp.bol.com.br. Propriedade Port: A porta por padro a que j mostra, mas tem alguns provedores que mudam essa porta. Propriedade Username - nome do usurio da conta criada. Propriedade Password - A senha para acessar a caixa postal. Propriedade MaxLineLength - Numero de linhas - por padro, para a mensagem tem 16K (16 mil caracteres). Propriedade Authentication - Se o programa requer alguma autenticao, ento selecionamos. Por padro a maior parte no requer autenticao antes, podemos enviar mensagem com a senha junto. Existem provedores que primeiro faz a autenticao para depois enviar mensagem.

13.4 - A programao.
Temos duas programaes - uma no boto anexar e outra no boto enviar 13.4.1 - Boto Anexar Quando selecionamos, executa o sistema, mostra uma caixa de dialogo que retorna true ou false. Se selecionar algo e precionar OK - retorna true, se clicar em cancel - retorna false. Se der false no foi selecionado nada, ento no adiciona nada. procedure TForm1.Btn_AnexarClick(Sender: TObject); begin if odAnexos.Execute then LB_Anexos.Items.Add(odAnexos.FileName); end; Toda vez que fazer o execute mostra a tela de carregando o arquivo. No ListBox manda adicionar. Geralmente antes de comear anexar, ao abrir o formulrio temos que limpar este ListBox (LB_Anexos) Para limpar clique em ListBox - eventos - onClick - escolha Btn_LimparClick e faa a programao :

172

Figura 76 Object Inspector do componente LB_Anexos (TlistBox). Clique em Btn_LimparClick e acrescente a seguinte linha de programao. OU Clique direto no boto limpar para abrir o modulo de programao e acresente a programao. procedure TForm1.Btn_LimparClick(Sender: TObject); begin LB_Anexos.Items.Clear; end; Agora temos um boto para anexar e outro para limpar. 13.4.2 - Boto Enviar Programao: procedure TForm1.Btn_EnviarClick(Sender: TObject); var xAnexo : Integer; {numero de anexos} xAnexo: Varivel para controlar o nmero de anexos. begin // Grava os dados da pessoa que ira receber o email IdMessage.Recipients.EMailAddresses := Edt_Para.Text; EmailAddresses: - O endereo para quem vai ser enviado. IdMessage.CCList.EMailAddresses := Edt_Copia.Text; EmailAddresses: A lista de endereos que vai ser enviada cpias. IdMessage.BccList.EMailAddresses := Edt_CopiaOculta.Text;

173

EmailAddresses: Lista de endereos com copia oculta. Este componente o que vai ser construda a mensagem de texto. Ento temos que indicar para quem vai ser mandado o correio, quem vai receber cpia e quem vai receber cpia oculta. //Trata a Prioridade da mensagem case cbxPrioridade.ItemIndex of 0 : IdMessage.Priority := mpHigh; 1 : IdMessage.Priority := mpNormal; 2 : IdMessage.Priority := mpLow; end; Nos campos acima tratada a prioridade das mensagens (Alta, Normal ou Baixa) // Trata o assunto e conteudo da mensagem IdMessage.Subject := Edt_Assunto.Text; IdMessage.Body := mmMensagem.Lines; O conteudo da mensagem: Subject: Assunto. Body (contedo da mensagem): so as linhas inseridas no corpo da mensagem. if cbxConfirmaLeitura.Checked then IdMessage.ReceiptRecipient.Text := IdMessage.From.Text; // Auto Resposta IdMessage.From.Texte: Retorna o nome de usurio e o endereo de Email - o email que ser enviado de volta confirmando a leitura pelo destinatrio. A propriedade ReceiptRecipient a resposta e temos que passar para ele qual o endereo de resposta (o endereo de email) para o destinatrio enviar a resposta. Passamos o mesmo endereo de envio, ento automaticamente j est colocado o endereo de resposta. Se a propriedade estiver em branco, no teremos retorno de resposta, sendo que o usurio ter que clicar em responder. Se a propriedade estiver preenchida j retorna uma resposta automtica, informando que a mensagem foi lida.

//Tratando os arquivos anexos for xAnexo := 0 to LB_Anexos.Items.Count-1 do TIdAttachment.create(idmessage.MessageParts, TFileName(LB_Anexos.Items.Strings[xAnexo]));

174 TIdAttachment.create - O T o tipo - estamos chamando uma classe para fazer a compactao. Quando foi clicado em sMTP j foi dado o use e entre as classes disponveis tem a classe TIdAttachment que compacta o arquivo para poder enviar junto. Ser feito um for que varia de zero at o numero de elementos menos um. (anexo numero zero, anexo numero um, anexo numero dois, etc). Passamos como parmetro quem vai receber as mensagens (idmessage) e o nome do arquivo a ser enviado (LB_Anexos.Items.String[xAnexos]); IdSMTP.Connect; Esta linha faz a conexo. Conecta com o provedor e envia a senha. try IdSMTP.Send(IdMessage); Este comando envia a mensagem passando como parametro a mensagem a ser enviada. finally IdSMTP.Disconnect; Diferente de Exception o comando finally independente de enviar ou no a mensagem desfaz a conexo. end; Application.MessageBox('Email enviado com sucesso!', 'Confirmao', MB_ICONINFORMATION + MB_OK); Neste campo indica que o email foi enviado com sucesso. O MessageBox escreve a confirmao. end; Salve > compile e execute o programa.

13.5 - Programao completa do aplicativo unit U_Envia; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, IdComponent, IdTCPConnection, IdTCPClient, IdMessageClient, IdSMTP, IdBaseComponent, IdMessage, IdMessageCoder, IdMessageCoderMIME; type TForm1 = class(TForm)

175 Label1: TLabel; Label2: TLabel; Label3: TLabel; Edt_CopiaOculta: TEdit; Label4: TLabel; Label5: TLabel; cbxConfirmaLeitura: TCheckBox; Edt_Para: TEdit; Edt_Copia: TEdit; Edt_Assunto: TEdit; cbxPrioridade: TComboBox; Btn_Anexar: TButton; mmMensagem: TMemo; Label6: TLabel; Btn_Enviar: TButton; odAnexos: TOpenDialog; IdMessage: TIdMessage; IdSMTP: TIdSMTP; LB_Anexos: TListBox; Btn_Limpar: TButton; procedure Btn_AnexarClick(Sender: TObject); procedure Btn_EnviarClick(Sender: TObject); procedure Btn_LimparClick(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Btn_AnexarClick(Sender: TObject); begin if odAnexos.Execute then LB_Anexos.Items.Add(odAnexos.FileName); end; procedure TForm1.Btn_EnviarClick(Sender: TObject); var xAnexo : Integer; {numero de anexos} begin // Grava os dados da pessoa que ira receber o email

176 IdMessage.Recipients.EMailAddresses := Edt_Para.Text; IdMessage.CCList.EMailAddresses := Edt_Copia.Text; IdMessage.BccList.EMailAddresses := Edt_CopiaOculta.Text; //Trata a Prioridade da mensagem case cbxPrioridade.ItemIndex of 0 : IdMessage.Priority := mpHigh; 1 : IdMessage.Priority := mpNormal; 2 : IdMessage.Priority := mpLow; end; // Trata o assunto e conteudo da mensagem IdMessage.Subject := Edt_Assunto.Text; IdMessage.Body := mmMensagem.Lines; if cbxConfirmaLeitura.Checked then IdMessage.ReceiptRecipient.Text := IdMessage.From.Text; // Auto Resposta //Tratando os arquivos anexos for xAnexo := 0 to LB_Anexos.Items.Count-1 do TIdAttachment.create(idmessage.MessageParts, TFileName(LB_Anexos.Items.Strings[xAnexo])); IdSMTP.Connect; try IdSMTP.Send(IdMessage); finally IdSMTP.Disconnect; end; Application.MessageBox('Email enviado com sucesso!', 'Confirmao', MB_ICONINFORMATION + MB_OK); end; procedure TForm1.Btn_LimparClick(Sender: TObject); begin LB_Anexos.Items.Clear; end; end.

177

14 CONEXO ADO
ADO (ActiveX Data Objects Objetos de dados ActiveX) Uma camada sobre o OLE DB e referido como uma interface em nvel de aplicativo. Tem semelhana com o BDE e tanto um como o outro suportam navegao e manipulao de conjuntos de dados, processamento de transaes e atualizaes em cache (chamadas atualizaes em lote, no ADO). O ADO de tecnlogia da Microsoft e muito bom para Bancos da Microsoft, ASP e SQLService. Desde a verso do Delphi 2 j existe a conexo via ADO, um tipo de conexo antiga que tem permanecido por conta da Microsoft, mas podemos fazer conexes com outros tipos de bancos que funcionam via ODBC.

14.1 - O que ODBC?


ODBC (Open Database Connectivity conectividade de banco de dados aberta) fornece uma interface padro que liga uma aplicao para acessar diferentes fontes de dados. As fontes de cdigos de aplicaes no devem ser recompiladas para cada data source. Um database driver liga a aplicao para um data source especifico. Um database driver um dynamic-link library que uma aplicao pode invocar exigindo um acesso para um data source particular. Portando, a aplicao pode acessar algum data source para que um database driver exista. A interface ODBC define o seguinte:

Uma funo library of ODBC que permite chamar uma aplicao para conexo com um data source, executando SQL statements, e recuperando resultados. Sintaxe SQL baseada na especificao SQL-99. Um conjunto de cdigo de erros padro. Um caminho padrao para conexo e login com um data source. Uma representao padro para data types.

14.2 - A paleta ADO


Nas paletas do Delphi, procure a paleta chamada ADO. Da mesma forma que trabalha o BDE, esta paleta tambm tem a conexo, a Table e o SQL, isto , bem equivalente ao BDE com basicamente todos os componentes, s que tem a tecnologia Microsoft enquanto o BDE tem a tecnologia Borland. 14.2 .1 - Componentes da Paleta ADO Os componentes da paleta ADO da pgina da paleta de Componentes faz a conexo ao database information usando ActiveX Data Objects (ADO): ADOConnection Estabelece uma conexo com um ADO database e fornece suporte para transaes. ADOCommand Edita comandos SQL diretamente em um ADO database sem retornar um resultado. ADODataSet Representa os dados de uma ou mais tabelas

178 em um ADO database e permite componentes data-aware para manipular estes dados pela conexo com um componente DataSource. Este o controle mais genrico ADO dataset, e pode ser usado no lugar da ADOTable, ADOQuery, ou ADOStoredProc. Representa os dados de uma database table via ADO e permite componentes data-aware para manipular estes dados por conexo com um componente DataSource. Utiliza declaraes SQL para recuperar dados de uma tabela de banco fsica via ADO e permite componentes data-aware para manipular estes dados fazendo conexo com um componente DataSource. Torna possvel uma aplicao acessando stored procedures em servidores usando ADO. Gerencia a organizao dos dados quando um objeto Recordset passado de um processo ou maquina para outro. Utilize TRDSConnection quando contruir aplicaes multicamadas usando business objects (Application Servers).

ADOTable

ADOQuery

ADOStoredProc

RDSConnection

14.3 - Como criar uma conexo.


Se tiver instalado o Banco de Dados oracle num servidor de uma empresa e o cliente encomenda o seguinte sistema: Desenvolver um sistema de vendas, o banco de dados vai ser oracle e toda a base de dados estar em uma mquina especifica para isso. Se a base de dados for remota, estiver em outra mquina, temos que salvar os dados remotamente, tendo a concorrncia de outras CPUs que tambm esto salvando os dados no mesmo Banco de Dados. CPU CPU

BD CPU Figura 78 Clientes e banco de dados. CPU

179

Para fazer a conexo com o Banco de Dados, primeiro temos que criar essa conexo e indicar onde vamos gravar esses dados. No caso do Oracle existe um arquivo no diretrio dependendo da instalao : C:/oracle/Net80/Admin. Test Message - De duplo clique neste arquivo. Esse o arquivo de configurao e indica o local em que se encontra o banco de dados. Esta porta a porta que o oracle est ouvindo, porque dentro da mquina pode ser instalado alm do Oracle, o Interbase, SQLServer, etc... 14.3 1 - A Porta Temos um servidor com endereo IP, por exemplo: 10.2.0.20, no caso do servidor Oracle. Quando instalamos esse protocolo que o protocolo TCP/IP, junto com ele abre um formulrio chamado SERVICE. Tudo que fazemos em cima desse sistema atravs do SERVICE. O sistema faz um chamado. O que esse chamado? - O usurio pede ao servidor que imprima a pgina atual. Essa pgina impressa e entregue ao cliente. - No email pedido ao servidor um servio, digitada a senha e o servio busca a mensagem. Basicamente tudo trabalha com servio da mesma forma que temos servios em nosso dia a dia. Se o servidor fosse uma cidade e dentro dessa cidade tem vrios servios(de correio, limpeza pblica, segurana, educao). Cada servio tem um endereo, situado em uma rua e um nmero. O servidor trabalha da mesma forma, todo servio que ele executa tem um endereo, esse endereo a porta. Dentro de um servidor tem vrios servios: na porta 80 internet, na porta 21 FTP, na porta 1521 o oracle). Qualquer servio que se abra tem um nmero de porta e nunca dois servios pode estar na mesma porta porque d conflito de endereo. Quando mandamos um pacote para uma mquina. Se estamos no cliente e mandamos algum pacote de comunicao, esse pacote sai do cliente para o servidor que tem um cabealho e vai compor a seguinte escolha: - Qual o IP da mquina de origem, por exemplo 10.2.0.50 -> nesta mquina a porta 50. - Porta de origem: A porta que esta enviando, supondo que a porta seja 10.20. - Endereo IP da mquina de destino: a porta do servidor que vai receber a mensagem(pacote) na porta 1521. Quando esse pacote chegar no destino, algum recebe e envia para a porta (endereo) correto. Se for para a porta 1521 do Oracle ele executa e responde para o endereo IP de origem. Em resumo: Trabalha coma porta de origem e de destino (endereo de origem e endereo de destino). Cada vez que vai mandar mensagem de uma mquina para outra tem que ter o endereo e porta de origem e na hora que mandar o pacote de volta tem que mandar exatamente para o mesmo endereo. Para bloquear o endereo de uma porta s desabilita-la. O Firewal para bloquear portas faz o seguinte: As portas que no esto sendo utilizadas, no tem nenhum programa rodando, ele simplesmente desabilita, isso quer dizer que se chegar algum pacote para a uma porta desabilitada, joga fora esse pacote porque pode ter algum vrus dentro dessa

180 porta e se chegar o pacote o programa de vrus pode receber e tomar a iniciativa. Para evitar que algum invada uma mquina mandando um pacote e responder alguma coisa que no deveria, o firewal ento desabilita essa porta. Se na mquina no tiver nenhum Firewal ativo e as portas abertas, outras pessoas podem acessar a mquina, copiar um arquivo e etc. As portas que esto ativas so monitoras. Se for mandado um pacote para a porta 80 pedindo alguma coisa para o servidor WEB, o sistema verifica se o cliente que enviou pode acessar, procurando em uma lista, se pode, ento libera o acesso. Entre os vrios servios que podemos acessar, vamos acessar o servio 1521. Com esse endereo vlido(habilitado), quando chegar um pacote, envia para o Oracle. Essa conexo vai se chamar ORCL. Foi criada uma conexo com o Oracle chamada ORCL e vai se conectar com o banco de dados chamado Oracle, na mquina, acessa o servidor, nesta porta o oracle vai responder. Dentro do oracle, acessamos o banco de dados chamado ORCL. Essa a configurao do Oracle. Fechamos o arquivo.

14.4 - Criao de conexo via ODBC.


Iniciar > Painel de controle > Ferramentas Administrativas > Fonte de Dados ODBC.

Figura 79 Administrador de fonte de dados ODBC.

181 Para criar uma nova conexo indicada para essa mquina que qualquer coisa que chegar ser mandada para o servidor. No exemplo o servidor remoto. Adicionar (ADD) > Microsoft ODBC.Oracle. Selecione o banco de dados do oracle Microsoft ODBC para Oracle Se fosse Interbase ento coloque esse banco ao adicionar. O mesmo procedimento para o Paradox ou qualquer outro banco. No caso usaremos o Oracle.

Figura 80 Tela para criar nova fonte de dados. Clique em Concluir.

182

Figura 81 - Instalao do Microsoft ODBC para Oracle.

14.5 - Caixa de dilogo Instalao do Microsoft ODBC para Oracle


A caixa de dilogo Instalao do Microsoft ODBC para Oracle contm os seguintes controles: Nome da fonte de dados O nome ou identificador usado pelos aplicativos para chamar ou usar esta fonte de dados. Os usurios podem usar qualquer mtodo descritivo para nomear uma fonte de dados. Este campo fica em branco por padro, mas necessrio. Contm qualquer qualificador descritivo; em branco por padro. O nome de usurio para a fonte de dados. O alias de banco de dados criado na SQL*Net Easy Configuration ou uma seqncia de conexo. (Para obter informaes sobre construo de seqncias de caracteres, consulte Atributos da seqncia de conexo. Para obter descries de seqncias de conexo com banco de dados pessoais e remotos, consulte o arquivo de ajuda do Oracle.) Clique em Selecionar para escolher um conversor de dados carregado; o padro No translator (sem conversor).

Descrio Nome de usurio Servidor

Converso

183

Desempenho

O Tamanho do buffer especifica o tamanho, em bytes, alocado para receber dados buscados. O driver otimiza a busca de forma que uma busca no servidor Oracle retorne linhas suficientes para preencher um buffer do tamanho especificado. Os valores maiores tendem a aumentar o desempenho quando se busca muitos dados. Incluir REMARKS em funes de catlogo especifica que o driver deve retornar colunas de comentrios para o conjunto de resultados SQLColumns. Desmarque esta opo para aumentar o desempenho. Incluir SYNONYMS em SQLColumns especifica que, quando definido como True (1), uma chamada API SQLColumns() retornar informaes de coluna para Tabelas, Visualizaes e Sinnimos. Este driver recupera informaes de coluna mais rapidamente quando este valor no definido (ou quando o valor definido como 0).

Personalizao

Impor o padro DayOfWeek do ODBC define o conjunto de resultados com um determinado formato de dia da semana. Se selecionada, essa opo especifica que o conjunto de resultados segue o formato de dia da semana do ODBC (domingo = 1; sbado = 7). Caso contrrio, segue o formato de dia de semana do Oracle (segunda = 1; domingo = 7). SQLDescribeCol sempre retorna um valor para preciso especifica que a chamada SQLDescribeCol retornar 130 para a preciso quando o Oracle no fornecer esta informao. Alguns tipos de dados numricos do Oracle no tm uma preciso fixa, como colunas numricas calculadas e colunas definidas como NMERO sem preciso ou escala. Se esta caixa de seleo estiver desmarcada, o driver retornar 0 para estes tipos de colunas.

Observao As informaes detalhadas e programticas sobre este driver esto localizadas em msdn.microsoft.com.: abra a pgina MSDN Library Online (Biblioteca MSDN on-line) e a pgina Platform SDK (SDK da plataforma), onde voc encontrar o MDAC SDK (SDK do MDAC), que contm uma seo denominada ODBC Drivers (Drivers ODBC). O Microsoft ODBC Driver para Oracle oferece suporte apenas ao SQL*Net 2.3 ou posterior. Para obter mais informaes sobre os produtos Oracle, consulte a documentao Oracle.

184 Nesta tela preencha: - Nome da fonte de dados: por exemplo Oracle esse nome vai ser usado depois na programao ( o Alias). - A descrio se tiver pode ser colocada. - User Name = System - Servidor = ORCL Quando criamos uma conexo para ligar na mquina cliente nesse banco de dados, foi dado um nome para essa conexo de ORCL, ento na hora que ele voltar, vai buscar o ORCL. Quando abrir o ORCL vai ter o endereo IP da mquina, a porta que vai conectar e qual o banco de dados que vai acessar. Clique em OK. Esta criada a conexo. Esta mquina j sabe quem o servidor.

14.6 - Para usar no Delphi


Abra o Delphi Clique na paleta ADO. Em todo banco de dados tem um componente para conexo. No exemplo apresentado vamos fazer somente em um formulrio s para testar essa conexo. Coloque o componente ADOConection.

Figura 82 Formulrio com componente ADO. De duplo clique em cima desse componente.

Figura 83 Formulrio do componente ADOConnection.

185

Ao abrir procure o boto Build Clique no boto Build para ir direto ao editor de strings de conexo da Microsoft. Vamos procurar a conexo que vai criar que j est pronta dentro do Conect. No necessrio criar a conexo porque j esta pronta, basta utilizar. Para indicar o banco de dados, o ADO usa as strings de conexo. possvel digitar uma string de conexo, se souber o que est fazendo, mas em geral usamos o editor de strings de conexo, mostrado na figura acima. No campo Use Connection String escolhemos a conexo oracle. Neste campo feita a opo UserName e senha.

Figura 84 Formulrio de propriedades de vinculao de dados. Selecione Permitir salvamento de senha. Clique em Testar conexo. Se no der certo porque o arquivo TMF est errado.

186

Figura 85 Fontes de conexo do componente ADO. Clique em OK e OK novamente. Em propriedade do componente ADOConection: Connected = true. Em LoginPrompt deixe = false. J est feita a conexo com o oracle, agora s criar as tabelas. Qualquer arquivo que for salvo ser gravado no banco oracle no servidor. 14.6.1 - Colocando uma tabela. Adicione um componente ADOTAble e preencha como se fosse uma tabela comum. Coloque um DataSourse e um componente DBGrid Em propriedades da ADOTable: Connection: ADOConection1 TableName: Selecione a tabela Active: True Em propriedades do DataSourse: DataSet: ADOTable1 Em propriedades da DBGrid: DataSourse: DataSourse1 O form ficar com o aspecto mostrado abaixo:

187

Figura 86 Aspecto do formulrio de teste para conexo ADO. Se tiver vrias conexes acessando o banco com muitas tabelas com o mesmo nome, o sitema fica lento, mas depois da conexo o tempo fica normal. Se for um banco que no tenha uma monte de tabelas com o mesmo nome, o tempo de acesso rpido. O ideal ter tabelas com nomes completamente diferentes uma da outra. Salve, compile e execute o programa. Para ligar uma tabela na outra com MasterSourse e MasterField, existe no ADOTable a propriedade MasterSourseMasterField. Essas propriedades so semelhantes a uma Table comum, no muda nada. A nica preocupao com o gerador de nmeros. Quando cadastrar algum campo, tem que ser programado no banco. Cada um que for conectar, o sistema pede o nmero da mquina e isso tem que ser feito por voc. A conexo com o oracle feita assim. normal como qualquer outra. A conexo tambm pode ser feita com outro componente em vez de usar o ADO, pode ser usado o DBExpress. Para fazer a conexo do DBExpress, dado um duplo clique em cima do componente, manda adicionar uma nova conexo do oracle (nome dessa conexo por exemplo: Teste_oracle). Coloque um componente SQLConnection no form De duplo clique no componente e adicione uma nova conexo do oracle, por exemplo: Teste_oracle. Colocar o nome do Banco de Dados = ORCL Nome Username = System Password = oracle. Clique em OK

188

Figura 87 Configuraes e conexo do componente SQLConnection. Em propriedades do componente: Login Prompt = false. Conected = true. Adicionar o componte SimpleDataSet. Propriedade Connection = SQLConnection1 Banco de dados: Tabela de produtos > Propriedade Active = true. Ligue a tabela (SimpleDataSet). Adicione uma Grid e ligue-a ao DataSourse

Figura 88 Grid adicionada ao formulrio e ligada ao DataSourse.

189 Note a diferena de perfonmance entre os componentes Microsoft e Borland. Enquanto o ADO funciona via ODBC, o componente da Borland (DBExpress) no acessa via ODBC, mas sim com acesso direto, por isso se torna mais rpido e depende de senha porque se for criada qualquer conexo e criar nome, aparecer a tabela referente senha do usurio. Poderia ter sido programada uma historyProcedure no servidor. Ser for usado por exemplo o componente DBExpress, quando for colocado o componente SimpleDataSet, na propriedade DataSet > Command Type tem os parmetros: Table, Query e StoredProcedure. Selecionamos History Procedure e colocamos qual StoredProcedure que queremos. O nome dela est gravada no banco ou selecionamos direto. Tambm tem a opo Params que so os parmetros que sero passados para a history procedure (nome, endereo, etc). Passamos os parmetros e colocamos a tabela em active = true. Suponha que existe uma StoredProcedure programada no banco. Para acessar essa StoredProcedure, na propriedade (Data Set) Comand type selecione a StoredProcedure, depois na propriedade Comand Test, selecionamos a StoredProcedure que existe neste campo (cadastrar, incluir, validar, etc). Se precisar passar parmetros, existe a opo params (parmetros). Se for colocados os parmetros entre colchetes 0,1,2,3,4 a ordem que est na StoredProcedure. Suponha que a StoredProcedure esteja feita. Criar uma tabela com um componente SimpleDataSet Propriedade Name = Tbl_Teste.(???). Na opo DataSet selecione ComandType = StoredProcedure e em ComandText selecione atualize. Para passar os dois parmetros suponha que uma tabela se chama Tbl Ento Tbl.Params[0]. Dentro do colchete colocamos o parmetro zero(0). O zero o primeiro parmetro (.asString) recebe true. Parmetro um [1] .<algumacoisa>: = 3 e depois coloque active = true. Isso mandado para o servidor. No tem diferena em trabalhar com Oracle, Interbase ou Paradox, tudo igual. O DBExpress funciona com todos os bancos, menos com o Paradox. e Cliper. Para funionar bem, o servidor tem que estar configurado. O que no pode criar um monte de conexo de um Software. O ideal ter uma nica conexo com o Banco de Dados.

190

14.7 - Um exemplo prtico


Vamos usar um arquivo Acces MDB instalado pela Borland com o Delphi em C:\Arquivos de programas\Arquivos comuns\Borland Shared\data\dbdemos.mdb Abra o Delphi Clique na paleta ADO. Coloque um componente ADOConection no form.

Figura 89 Formulrio para teste de conexo ADO. De duplo clique em cima desse componente que mostrara o editor abaixo:

Figura 90 Formulrio do componente ADOConnection. Ao abrir procure o boto Build Clique no boto Build para ir direto ao editor de strings de conexo da Microsoft.

191

Figura 91 Propriedades de vinculao de dados. No campo 1 Selecione ou insira o nome de um banco de dados do endereo: C:\Arquivos de programas\Arquivos comuns\Borland Shared\data\dbdemos.mdb Clique em Testar conexo.

Figura 92 Informao de teste de conexo. Clique em OK E OK novamente A string de conexo ser mostrada no campo Use connection string : Provider=Microsoft.Jet.OLEDB.4.0; Data Source=C:\Arquivos de programas\Arquivos comuns\Borland Shared\Data\dbdemos.mdb; Persist Security Info=False

192

Figura 93 String de conexo. Em propriedade do componente ADOConection: Connected = true. Em LoginPrompt deixe = false. 14.7.1 - Colocando uma tabela. Adicione um componente ADOTAble e preencha como se fosse uma tabela comum. Coloque um DataSourse e um componente DBGrid Em propriedades da ADOTable: Connection: ADOConection1 TableName: Customer Active: True Em propriedades do DataSourse: DataSet: ADOTable1 Em propriedades da DBGrid: DataSourse: DataSourse1 O form ficar com o aspecto mostrado abaixo:

Figura 94 Aspecto do formulrio usando exemplo de fonte do Delphi Salve, compile e execute o programa.

193

14.8 - O componente TDCOMConnection


Quando usar DCOM para comunicar com o servidor de aplicao, inclua no cliente de aplicao o componente TDCOMConnection para conexo com o servidor de aplicao. O componente TDCOMConnection usa a propriedade ComputerName para identificar a mquina que est o servidor. Quando a propriedade ComputerName estiver em branco, o componente DCOM connection assume que a aplicao do servidor reside na mesma mquina do cliente ou que o servidor de aplicao est registrado no sistema. Se voc no fornecer o registro do sistema para o servidor de aplicao no cliente quando estiver usando DCOM, e o servidor reside em outra mquina diferente da do cliente, voc deve indicar o ComputerName. Nota: Mesmo quando h um sistema registrado para o servidor de aplicao, podemos especificar o nome do computador para ordenar esta entrada.. Este deve ser especificado para ser til durante o desenvolvimento, testes e compilao. Se tivermos mltiplos servidores que os clientes de aplicao podem escolher, podemos usar a propriedade ObjectBroker instalada para especificar um valor para o nome do computador ( ComputerName). Se a fonte de nomes dos servidores no puderem ser localizados ou acessados , o componente DCOM connection criar um exception na tentativa de abrir uma conexo.

194

15 PROGRAMAO EM TRS CAMADAS


15.1 - Introduo
At agora foram desenvolvidos projetos de 2 camadas: um servidor de banco de dados e um cliente do outro lado que pode estar na mesma mquina ou no. Quando trabalhamos com o interbase ou o oracle, este pode estar na mesma mquina ou rodar remotamente e o software acessando esse banco de dados remotamente. O que muda s o caminho (path) do arquivo de configurao. Dando duplo clique no componente DBExpress por exemplo, pode-se mudar a localizao (host). Pode-se colocar localhosto ou colocar o IP da CPU onde o banco de dados est localizado. At ai no tem diferena nenhuma se o banco est localizado na mesma CPU ou est remotamente sendo acessado. Para o programador, no faz diferena s mudar o path. Observe a figura abaixo:

Cliente

BD

Figura 95 Representao de cliente ligado ao banco de dados. Se o sistema tiver 10 clientes acessando diretamente um banco de dados pago, isso redundaria numa despesa enorme em licenas de uso, alem de tornar complexa a programao e de difcil manuteno. Cada mquina que for acessar o servidor, paga uma conexo como banco de dados (no free). Se cada conexo custar R$ 1.000,00 e tiver 100 mquinas instaladas com o software para acessar o servidor, ter que desembolsar alm do sistema instalado, cem mil reais s com o banco de dados. Para evitar isso, utilizamos e colocamos um componente no formulrio principal (DataBase) com todos os acessos ao banco ligados nele (connection) e ele ligado ao banco de dados (um intermedirio).

Se tiver usando software livre, o Interbase, o Firebird ou Postgree, ento no tem problema. Para acessar o servidor remoto, tem que ser via rede e quando o sistema busca uma tabela, executa um comando SQL (select * from tabela). Manda esse comando SQL para o servidor, l o banco de dados, seleciona todos os campos de uma tabela, faz uma cpia e passa pela rede. E se for um monte de tabelas? Ou se uma tabela tiver 1 Giga? Fica trafegando pela rede um bocado de informaes, entupindo o trafego por melhor que ela seja, principalmente se tiver muitos usurios conectados. Alm desses problemas, existem outros associados: Numa conexo de rede, todos os usurios iro acessar o mesmo ponto, ficando lento o sistema.

195 Se tiver usando oracle para dez estaes (clientes), por exemplo: foi comprado o oracle numa promoo ou usando o racle gratuito de 4 Gigas. Com 10 pessoas acessando este servidor de banco de dados, daqui a alguns meses ele alcana a capacidade mxima de 4 gigas e o sistema para de funcionar, ento dito ao cliente que agora ele tem que comprar uma verso de verdade e que agora tendo 20 estaes ele, o cliente, vai ter que gastar 20 mil (mil reais por cada acesso). Na hora que o cliente tiver o oramento dos gastos que ir ter, ele vai dar um pulo dessa altura, de raiva, porque no foi informado antes. Aps passar a raiva ele pergunta se no tem outro banco de dados para usar e gratuito. Pode usar um Firebird, um Postgree, e ele ento quer passar tudo para o Postgree. Qual o problema a enfrentar agora? Foi criado todo o StoreProcedure em oracle. Em oracle utilizada a linguagem PL SQL que diferente de SQL. Em resumo, toda a programao que tem no banco, ter que ser refeita e praticamente todo o sistema vai ser modificado porque o cliente quer trocar de banco de dadas. Note que s tem problemas. Se precisar dar manuteno: No sistema estava programada a seguinte conta: Comisso = 0.25 * Venda. Ento resolvem mudar de 25% para 30% e a partir da ter que modificar uma constante X:= 25 para X:= 30, recompila o sistema e gera um novo executvel. Se tiver 20 estaes, ter que reinstalar 20 vezes. Isso uma tristeza. Toda estao, para acessar o servidor de banco de dados tem que ter instalado o Driver do banco que est utilizando. Se estiver utilizando o oracle, tem que estar instalado o cliente do oracle. E se for mudado o banco de dados ter que ser mudado tambm o driver em cada uma das estaes para acessar o banco, criar conexo, mquina por mquina. Mudou o servidor, ai vai em todas as estaes e muda o arquivo .ini. Achou alguma vantagem usando programao em duas camadas? Basicamente o que todo mundo faz. Para corrigir esse pequeno problema temos a soluo em 3 camadas.

15.2 As trs camadas


Para programao em trs camadas, teremos um cliente, um servidor de aplicao e um banco de dados. 15.2.1 - O cliente, o servidor de aplicao e o banco de dados. - Antes tinha que salvar a senha de acesso e a localizao para cada estao, agora tem um componente de conexo que faz uma nica conexo com o banco de dados para todas as estaes. - Todas as estaes iro se conectar atravs do componente chamado DCOMConnection e no se paga nada para fazer essa conexo, no gasta mais com um monte de licenas. Se quiser um banco oracle, ser gasto apenas uma licena porque ter apenas uma conexo. - Todo mundo continua acessando, s que em vez de trazer o comando Select * from tabela. Ele vai no banco, trs a tabela selecionada, mas s que no trs ela inteira. Divide em pedaos em quantas linhas que foram especificadas. Por exemplo: pode ser especificada 30 linhas. Se a pasta tem 100 registros, ele seleciona os 30

196 primeiros e manda para o cliente e quanto chegar na ultima linha que a 30, roda a SQL de novo e manda mais 30 registros e assim vai mandando pedaos da base com menos de 1K. Se quiser localizar um produto especifico, executa o comando select atravs de uma busca daquele produto e manda somente ele para o cliente. Ento em vez de mandar a base inteira, manda pedaos dessa base para no congestionar a rede e enquanto tiver memria, vai gerar um cash para quando for necessrio acessar o mesmo registro no preciso buscar de novo no banco, ele estar no cash enquanto tiver memria determinado pelo SO. Quando no tiver mais espao no cash o SO elimina os registros mais antigos para dar espao aos mais novos. Se for necessrio mudar de banco de dados, no estar programado as StoreProcedures no banco, mas estar programada no cliente, assim fica fcil trocar um banco de dados por outro. No banco de dados no tem mais as Triggers e nem as StoredProcedures. 15.2.2 - Atualizao. Se for mudada uma regra de negocio, esta regra mudada s no banco de dados e esta mudana fica pronta para a rede inteira sem a necessidade de recompilar no cliente. 15.2.3 - Desvantagem. Se for necessrio alterar um boto (um layout), ter que ser alterado no formulrio do cliente. 15.2.4 - Performance Para uma rede que tem um servidor rodando pode-se instalar outro servidor de aplicao, colocando metade da rede acessando um servidor e a outra acessando o outro com duas licenas de banco de dados, isto aumenta a performance do sistema, alm de dar segurana aos dados no caso de um dos servidores falhar. Com dois servidores de banco de dados possvel fazer uma sincronizao. Toda estao tem uma lista dos servidores. Se trabalhar com dois servidores e por um acaso um deles ficar off-line, automaticamente as estaes localizam outro servidor para se conectarem e continuar trabalhando. Outro detalhe: no balanceamento de carga, quando se tem dois servidores, o sistema divide o mesmo numero de CPUs para os dois servidores. Se em uma maquina tem muitos clientes conectados, ento o sistema balanceado, mudando alguns clientes para outra mquina, automaticamente. A partir de agora temos dois programas para executar: um programa cliente e um programa servidor. Quando trabalhamos com DLL, tnhamos dois programas A e B. Era possvel acessar uma mquina cliente e uma tabela na mesma DLL. S que a DLL s funciona dentro da mesma mquina. Essa comunicao chamada (Dialog ou COM) ou seja, comunicao entre processos, mas tudo dentro da mesma mquina. Mas existe uma maneira de fazer uma DLL funcionar pela rede (internet). Essa DLL se chama DCOM.

197

15.3 - Antes, um histrico


Com um cliente preciso rodar um programa e para acessar um servidor preciso executar um comando no servidor para que ele mande uma cpia para o cliente. Note que o cliente tem acesso ao servidor, s que o servidor no tem acesso aos dados do cliente. Se tiver um valor avariado dentro da memria do cliente, o servidor no consegue acessar esse valor e dar um boot. O servidor faz os clculos, mas no tem acesso na memria e nem no HD do cliente. Ento tem uma complicao se for necessrio saber um valor para saber qual o registro? ai pensaram tem como acessar o cliente? Chama o servidor e se o servidor precisar acessar o contedo da memria e do HD, busca esse valor, faz as contas e depois retorna. Ento possvel acessar os dois lados. Esse procedimento de acessar os dois lados tem trs protocolos para fazer isso: DCOM, RMI e (CORBA). Os trs fazem a mesma coisa e so de fabricantes diferentes. DCOM vem junto com a Microsoft os Windows a partir da verso 98 tem o DCOM. O que muda com o DCOM Por exemplo: Em programa de jogo existe uma mensagem que manda atualizar a tela. Se num jogo voc vai dar um tiro em um alvo, a posio do mouse neste momento j est definida e voc refaz a posio para localizar o alvo, ento o programa refaz a tela (atualiza) e manda para voc e para jogar em rede estar usando o DCOM. RMI Conhecido como Java. CORBA Tambm faz a mesma coisa, a diferena o fabricante, este protocolo de padro internacional aberto. Quem quiser usar, de graa. O padro de comunicao foi definido e est disponvel, como se fosse um Driver de Banco de Dados. Para usar, este protocolo, assim como os outros, tem que estar instalados na mquina.

15.4 - Como o DCOM distribui as tarefas.


Quando roda um programa com DCOM, um cliente ligado numa determinada porta, acessa um servidor que na verdade tem uma DLL. Ento na hora da programao estar tudo em DLL. Nesta DLL estaro os mtodos e a visibilidade. O DCOM uma DLL. A DLL est disputando uma porta (porta 2021, 211, etc). Quando chegar qualquer coisa na porta 211, que estaria ligada essa DLL, ela roda o programa, executa o que precisa e devolve. uma DLL que vai executar atravs da Internet. possvel visualizar as DLLs do Windows atravs do seguinte endereo: Iniciar > painel de controle > ferramentas administrativas > servios de componentes > computadores > meu computador.

198

Figura 96 Tela de visualizao de servios de componentes. Nos servios de componente instalados na CPU esto todos os aplicativos DCOM Na pasta Aplicativos COM+ esto todos os servidores que esto rodando na mquina.

Figura 97 Aplicativos COM+ em servios de componentes. Quando for criado o servidor de aplicao para o exemplo e se quiser colocar o servidor no estado ON-LINE para acesso em rede s clicar com o boto direito do mouse no servidor criado e mandar iniciar o servio. Se quiser parar s clicar de novo e mandar desativar e ningum mais acessa. Cada vez que for compilar, deve parar o servidor, porque na hora que for substituir algum dado, pode dar erro. Se for compilar, desligue o servidor, faa a compilao e depois ligue novamente.

199

15.5 - Criando uma nova Aplicao.


Esse exemplo explica como trabalhar com o cliente e o servidor de aplicao. so para mostrar um novo componente que vai ser utilizado. um novo tipo de tabela. Para o exemplo ser criada uma tabela temporria, conforme especificada abaixo. Imagine que ser feito um calculo: Temos 100 itens para incluir num pedido e cabe 14 itens por nota. preciso dividir os itens para caber na nota. Pode ser criada uma tabela, no no servidor, mas uma tabela local, uma tabela que existe s na memria cash. Podemos fazer os clculos simplesmente com a tabela na memria (uma tabela temporria).

15.5.1 - Projeto Cliente No Delphi > abra um novo projeto. No cliente ser criada uma tabela temporria. 15.5.2 - Tabela Temporria Porque uma tabela temporria? Se for acessada a tabela no servidor de bando de dados, no s voc ter acesso, assim como outros usurios alterando os registros a todo momento, congestionando a rede. Para evitar isso criada uma tabela temporria na memria e sem registro fsico no HD. No preciso criar um banco de dados inteiro, mas sim pequenas partes que sero armazenadas temporariamente e salvas depois no banco de dados que esta localizado no servidor. Da paleta DataAccess > selecione ClienteDataSet e adicione no form. Em vez de usar uma table, IBTable, a partir de agora nos clientes s vai ter a tabela Cliente DataSet. ClienteDataSet uma tabela muito especial, uma table turbo, uma tabela com vrios recursos adicionais que nenhuma outra tem. Propriedades do componente ClientDataSet: name = Tbl_Teste Ao criar uma tabela temos que ligar ao banco de dados. Neste caso no obrigatrio, podemos criar campos no prprio local, como se fosse uma tabela. De duplo clique no componente. No editor aberto, clique outra vez com o boto direito do mouse. No editor de campos, clique em novo campo (New Field) para abrir o editor mostrado na figura abaixo.

200

Figura 98 Editor de propriedades Digite os campos do quadro abaixo, um de cada vez: Name Type Size Cod (Cdigo) Integer Nome String 30 Qtde(Quantidade) Integer Data Date Valor Float

Field Type Data Data Data Data Data

Faa para cada campo adicionando na tabela Clique em OK. Foram criados os campos como se fosse em uma tabela comum. Para cada campo pode ser trocada na propriedade display label o nome do campo que aparece para o usurio e tambm modificada outras propriedades depois de selecionado esse campo. Criando o DataSet na memria Clique com o boto direito do mouse no componente e depois no campo CreateDataSet. A partir de agora esta tabela j existe. Da paleta DataAccess coloque um DataSourse Propriedades: name: DS_Ativ. DataSet: Tbl_Teste

201 Da paleta Data Controls adicione uma Grid. Na propriedade DataSourse da Grid selecione DS_Ativ. Com o componente selecionado (tabela Tbl_Teste) na propriedade Active coloque true se ainda no estiver ativa. Da paleta DataControls coloque um DBNavigator para testes. O DBNavigator neste caso no necessrio, mas s para teste. Propriedade DataSourse: DS_Ativ. Salve o projeto e compile Rode e coloque alguns dados na tabela. O Resultado da tela a mostrada abaixo:

Figura 99 Formulrio de Teste de tabela temporria. Ao rodar o projeto, o banco de dados estar s na memria. A nica diferena desta tabela que na hora que o formulrio for fechado, os dados se perdem. 15.5.3 - Outro exemplo: Numa tela de pedido, quando feito um pedido, um campo total pode ser criado com um comando SQL para calcular esse total, ou programar as linhas de comando a seguir para fazer o calculo do total: Tbl_Pedido:= first; While not (Tbl_Pedido EOF) do

202 Aux:= aux + valor. E vai acumulando numa varivel para mostrar o valor na tela. Fazendo o campo total. Como esse campo feito agora? Duplo clique na tabela (Componte ClientDataSet). Clique com o boto direito do mouse e depois em New Fild. Na hora que criar um novo campo, crie um campo do tipo agregado Coloque o nome do campo conforme figura abaixo e escolha em Field Type o campo Aggregate

Figura 100 Editor de propriedades de componente. Clique em OK. Campo agregado campo de total. Agora o campo faz os clculos de total e j mostra no final. No Editor de campos abaixo, aps criado o campo agregado, nome que ele aparece separado porque um campo especial, se tentar arrastar ele no obedece e no aparece na grid.

203

Figura 101 Campos do componente Tbl_Teste, mostrando o campo TotalGeral. Para mostrar o campo TotalGeral no formulrio, no campo do editor acima no delphi: Selecione o campo TotalGeral. Na propriedade Expression coloque a expresso matemtica : sum(qtde * valor). Na propriedade Active coloque true para ativar o campo seno no mostra o resultado. O total vai ser igual a soma da quantidade vezes o valor. Aps criado o campo, ative a tabela (Active = true) ou Clique com o boto direito do mouse no componente ClienteDataSet e depois em Create DataSet para ativar a tabela novamente. Para liberar o campo calculado na tabela: Clique na tabela(componente ClienteDataSet) uma nica vez e na propriedade AggregatesActive coloque = true. Para mostrar o campo total criado: Da paleta DataControls coloque um DBEdit. Propriedade DataSourse = DS_Ativ. Propriedade DataField = TotalGeral. Da paleta Standard coloque um Label. Propriedade Caption = Total Geral. Por enquanto no foi programada nenhuma linha. Salve, compile e rode o programa para verificar o funcionamento, digitando dados na tabela.

204

Figura 102 Formulrio com o campo Total. Observe que se for alterado algum valor o campo total tambm ser modificado. Nota: No foi feita nenhuma linha de programao no cliente.

15.6 - Propriedades de Expression (TAggregateField)


Especifica a frmula usada para calcular o valor agregado. Sintaxe no Delphi: Tipo da propriedade Expression: string; 15.6.1 - Descrio Selecione Expression para indicar como os valores agregados devem ser calculados. Expression contm uma expresso que inclui um mais operadores sumrios conforme mostrados na tabela abaixo: Operador Sum Avg Count Uso Total de valores para um campo numrico ou expresso. Computa o valor average para um campo numrico ou date-time ou expresso. especifica o nmero de valores (campos preenchidos) para um campo ou expresso. Use count(*) para contar o numero de registros em um dataset ou subgroup.

205 Min Max Indica o valor mnimo para uma string, numeric, ou campo date-time ou expresso. Indica o valor mximo para uma string, numeric, ou campo date-time ou expresso.

O operador sumrio aciona um valor de campo ou uma expresso embutida no valor de campo usando alguns operadores para criar um filtro. (No podemos aninhar operadores sumrios de qualquer modo). Podemos criar expresses usando operadores sumarizando valores com outros valores sumarizados (rezumidos), ou sumarizando valores e constantes. De qualquer modo, no podemos combinar valores sumarizados com valores de campo, porque expresses semelahntes so ambiguas (no h indicao de como mostrar fontes gravadas para o valor de campo.) Estas regras so ilustradas nas seguintes expresses: Sum(Qty * Price) {legal sumario de uma expresso no campo }

Max(Field1) - Max(Field2) {legal expresso num sumrio } Avg(DiscountRate) * 100{ legal expresso do sumrio e constante } Min(Sum(Field1)) Count(Field1) - Field2 { ilegal no sumrio } { ilegal expresso de sumrio e campo}

Nota: Para especificar o jogo de gravaes sumarizadas por estas expresses , use a propriedade GroupingLevel .

15.7 - Colocando um campo Total Parcial.


Pode ser colocado um campo calculado ( um total parcial). Para colocar um campo do tipo calculado: Duplo clique no componente ClienteDataSet. Clique com o boto direito do mouse e no campo New Field para adicionar um novo campo. Nome do Campo = Total - do tipo float Field Type: Calculated.

206

Figura 103 Editor de propriedades de componente. Clique em OK. Selecione a tabela (componente ClienteDataSet) e no evento OnCalcFields faa a seguinte linha de programao: procedure TForm1.Tbl_TesteCalcFields(DataSet: TDataSet); begin Tbl_Teste.FieldByName('Total').AsFloat:= qtde * valor; end; end. Reative a tabela para que o campo Total aparea na Grid. Salve o rode o sistema colocando valores nos campos para verificar o funcionamento Temos um software comercial com uma linha de programao. Tem muito mais coisas que esse componente capaz de fazer. 15.7.1 - Salvando os dados Para exportar os dados da memria, suponha que esta ligado numa tabela. Como fazer para exportar dados? Para exemplificar coloque um boto no formulrio. Propriedades: Boto Name: Btn_Salvar Caption: Salvar

207

Figura 104 Formulrio de Teste de tabela temporria, Quando clicar no boto salvar sero exportados os dados. Clique no boto para entrar no mdulo de programao Coloque as seguintes linhas de programao: procedure TForm1.Btn_SalvarClick(Sender: TObject); begin Tbl_Teste.SaveToFile('c:\teste.xml',dfXML); end; procedure Tform1.FormCreate(Sender: TObject); begin //Esta linha de programao s funciona aps criado o arquivo XML // a linha de importao do arquivo. Tbl_Teste.LoadFromFile('c:\teste.xml'); end; end. Tbl_Teste.Savetofile<path> no arquivo X e no formato escolhido, no caso a exportao ser no formato XML que poder ser aberta no Office, no Explorer ou outro programa porque XML padro de exportao de dados. um padro que no precisa de Driver para abrir. Pode ser salvo o que foi digitado nos campos da grid. Se for feito um select e tiver 50 registros, quando mandar salvar, vai salvar os 50 que entrou. Pode ser feita uma gerao de exportao do dia. Seleciona tudo que ainda no foi exportado, montando uma tabela e envia pela internet. Do outro lado ser aberta esta tabela e atualizada no sistema (banco de dados).

208

O Funcionamento Execute o programa colocando alguns dados (campos) para testar. Exporte os dados clicando no boto salvar. O arquivo de exportao em formato XML foro gerados. Verifique o formato de como este arquivo ficou, os campos e os valores para cada campo, conforme mostrado abaixo:
<?xml version="1.0" standalone="yes" ?> - <DATAPACKET Version="2.0"> - <METADATA> - <FIELDS> <FIELD attrname="Cod" fieldtype="i4" /> <FIELD attrname="Nome" fieldtype="string" WIDTH="30" /> <FIELD attrname="Qtde" fieldtype="i4" /> <FIELD attrname="Data" fieldtype="date" /> <FIELD attrname="Valor" fieldtype="r8" /> </FIELDS> <PARAMS CHANGE_LOG="1 0 4 2 0 4 3 0 4" /> </METADATA> - <ROWDATA> <ROW RowState="4" Cod="1" Nome="Nome um" Qtde="1" Data="20060601" Valor="10" /> <ROW RowState="4" Cod="2" Nome="Nome dois" Qtde="2" Data="20060602" Valor="20" /> <ROW RowState="4" Cod="3" Nome="Nome tres" Qtde="3" Data="20060603" Valor="30" /> </ROWDATA> </DATAPACKET>

Atravs do Ecxel possvel importar esses dados. Pode ser aplicado um filtro em ordem crescente ou decrescente ou outro modo qualquer. Em resumo: possvel exportar para qualquer lugar. A exportao se no for definida ser em binrio e s o Delphi consegue abrir. Para carregar esse arquivo. Clique no componente (table) e no evento AfterPost coloque a seguinte linha de programao: procedure TForm1.Tbl_AtivAfterPost(DataSet: TDataSet); begin Tbl_Ativ.ApplyUpdates(0); end;

209

Cada vez que for ativado e em vez de salvar ser carregado de um arquivo. Exemplo: Seu amigo mandou um arquivo e voc quer salvar num banco de dados. Carrega o arquivo faz um comando ApplyUpDate e salva automaticamente no banco de dados. Salve, compile e execute o programa Agora se clicar em salvar, a partir de agora, mesmo que abrir a prxima vez, os dados j estaro l, no se perdem mais. Do jeito que est e quando for carregado o arquivo, para salvar no banco de dados basta colocar o nome da tabela a ser salva e fazer o comando ApplyUpDate - o que estiver na tabela e no estiver no banco j exportado na hora. Para exportar faa um comando SQL se for feito Select * from <tabela> no banco de dados tambm funciona. Select * from <tabela> Where (onde por exemplo: flag = true) Neste ponto seleciona um bloco e s traz aquele que no est atualizado e efetua o comando para salvar no arquivo. Na empresa que foi exportado os dados para poder carregar, voc executa o comando para carregar na memria e logo em seguida executa o comando ApplyUpDate para salvar no banco de dados.

15.8 - Uma regra de negcio num programa


Tudo o que foi feito para voc habituar ao poder do componente ClienteDataSet. Nesta verso ser colocado tudo num nico formulrio o servidor e o cliente sem usar o componente DCOM s para ver como funciona a comunicao entre eles e depois ser colocado o componente DCOM numa outra verso. Abra um novo projeto no Delphi. Do lado do cliente. Da paleta DataAccess coloque os componentes: dois ClienteDataSet e dois ClienteDataSourse. Do lado do servidor. Da paleta DataAccess coloque o componente DataSetProvider o componente que vai gerar a DLL. Da paleta DBExpress coloque o componente SQLDataSet e SQLConnection

210 Nota: Todas as estaes que existirem iro se conectar com o DataSetProvider e este componente estar somente no servidor. O componente SQLDataSet quando precisar salvar, joga dentro da tabela e salva dentro do banco de dados atravs de uma conexo (componente SQLConnection). O componente SQLConnection liga as tabelas ao servidor atravs de uma nica ligao com o banco. Dois clientes acessando o mesmo servidor e o servidor acessando o banco de dados. 15.8.1 - Fazendo a configurao Para o servidor tradicional escolher a conexo em propriedades, por exemplo se rodar a base no Interbase: 15.8.1.1 -Componente SQLConnection Clique no componente SQLConnection e escolha a conexo com o banco de dados colocando o Path no campo DataBase. Para o exemplo estamos usando o Interbase. Propriedade do componente: Name = Conexao Login Prompt = false. Connected = true. Neste ponto foi conectado com o banco de dados do outro lado. 15.8.1.2 - Componente SQLDataSet Em propriedades do componente: - Name = TBL_Atividade. - SQLConection = Conexao. - CommandType = ctTable. - CommandText = TAB_ATIVIDADES do Banco de dados BANCO.GDB listado logo abaixo. - Active = true.

15.8.1.3 - Componente DataSetProvider A novidade esse componente. O componente DataSetProvider vai ser o provedor de banco de dados, ento necessrio ligar a tabela com o banco. Todo mundo vai se conectar atravs deste componentee. Quando se conectar vai receber a Tabela de Atividades. Se precisar gravar alguma coisa ser gravada na Tabela de Atividades. Quando chegar algum dado dentro desse componente, ele joga nessa tabela, por isso foi escolhido DataSet. Nas propriedades do componente DataSetProvider foi selecionado DataSet e tudo que chegar e independente do que chegar, vai gravar nesta tabela. Clique no componente DataSetProvider.

211 Em propriedades do componente: - Name = DSP_Ativ. - DataSet = TAB_ATIVIDADES

15.8.1.4 - Os dois clientes O primeiro cliente vai se conectar ao componente DataSetProvider (DSP_Ativ). Componente ClienteDataSet1 - Name = ClienteUm - ProviderName = DSP_Ativ. - Active = true. Componente ClienteDataSet2 - Name = ClienteDois - ProviderName = DSP_Ativ. - Active = true. Componente DataSourse1 - DataSet = ClienteUm Componente DataSourse2 - DataSet = ClienteDois Na Propriedade Options do componente DataSetProvider coloque como true os campos:

Figura 105 Object Inspector do componente DS_Ativ (DataSetProvider). Nas propriedades desse componente coloque por enquanto o AutoRefresh, o PropagateChanges e o IncFieldProps em true isso no servidor. Essas propriedades esto listadas logo abaixo:

212 OBS: O item 16.3.6.3 mostra uma explicao de cada uma das propriedades dos componentes DataSetProvider (data access) e ClientDataSet (data access) No servidor foram estabelecidas as propriedades AutoRefresh, o PropagateChanges e o IncFieldProps. Coloque uma grid para cada cliente s para mostrar os dados cada uma ligada a um DataSourse. Para cada cliente coloque um DBNavigator ligados ao DataSourse. Os dados devem ser mostrados nos dois clientes e cada vez que salvar em um cliente, logo aps ser salvo no outro. O formulrio ficar com o aspecto mostrado abaixo:

Figura 106 Aspecto do formulrio com duas grids representando dois clientes.

15.8.1.5 - A programao Cada vez que os dados forem salvos, se tiver dez registros, s sero salvos no banco de dados quando for executado o comando ApplyUpDate que pode ser programado no evento AfterPost da tabela ou no boto Salvar.

No caso da importao de dados, depois de importar, para gravar no servidor, comandar ApplyUpDate neste exemplo, cada vez que salvar, ser salvo no servidor. Do lado do cliente programe componenteClientDataSet(ClienteUm): clicando no evento AfterPost do

213

procedure TForm1.ClienteUmAfterPost(DataSet: TDataSet); begin ClienteUm.ApplyUpdates(0); ClienteUm.Refresh; end; Faa o mesmo procedimento para o componente ClientDataSet2(ClienteDois): procedure TForm1.ClienteDoisAfterPost(DataSet: TDataSet); begin ClienteDois.ApplyUpdates(0); ClienteDois.Refresh; end; Quando clicar em salvar, salva os dados no Servidor que por enquanto ainda no recebeu nenhuma programao. No tem nenhuma regra programada. Se os dois clientes tiverem o mesmo cdigo para salvar? Se o ltimo registro de cada um o cdigo 16 e um dos clientes salva este registro para depois digitar o cdigo 17, com a descrio AAAA. O outro cliente tambm tem o cdigo 17 para salvar com a descrio ZZZZ. O primeiro foi salvo executando o comando ApplyUpDate e o segundo tambm executou o mesmo comando.

Figura 107 Formulrio com dois clientes em execuo. Aps atualizar as tabelas executando uma atualizao da tela(Refresh) nota-se que o segundo cliente no consegue salvar os dados porque o primeiro j salvou e a mensagem de erro mostrada, conforme abaixo:

214

Figura 108 Mensagem de erro mostrando violao de chave. Isso tem que ser controlado programando uma Trigger no servidor. Suponha que s possvel colocar cdigos maior que zero. Para programar pode ser colocado a condio (if.....then) antes de salvar (BeforPost). necessrio que todas as vezes funcione para todo mundo. Tudo que for geral programado no lado do servidor e automaticamente j transfere para todos os clientes. No servidor Duplo clique no componente SQLDataSet(TBL_Atividade) Adicione todos os campos (ID e Descrio)

Figura 109 Campos do componente SQLDataSet (Tbl_Atividade). Selecione o campo ID Na propriedade CustomConstraints pode ser criada restries igual ao banco de dados. Ex: Que o valor esteja entre 1 e 50. - Agora possvel digitar valores no campo ID somente na faixa de 1 a 50. - Neste campo o numero ID vai ter que ser maior que zero e menor ou igual a cinqenta (ID > 0 and ID <= 50). Esta restrio est sendo programada no servidor. Foi campo(CustomConstraints) e foi programada com a restrio acima. escolhido um

Se for digitado um valor errado (fora da faixa), pode ser colocada a mensagem: Digite um valor entre 1 e 50 no campo ConstraintErrorMessage.

215

Figura 110 Object Inspector da Tabela de Atividades (Tbl_Atividade) Salve, compile e execute o projeto. Coloque um valor fora da faixa especificada para testar o programa. Neste ponto note que o programa no vai obedecer at ser colocado um valor vlido devido constraint. Quando for digitado um valor fora da faixa e tentar ir para outro campo ir receber a mensagem Digite um valor entre 1 e 50.

Figura 111 Mensagem de erro. Se for colocado um valor valido e voc no quer esse valor, ento pode excluir para colocar outro numero. Para o cliente de baixo dever mostrar a mesma mensagem. Veja que no foi necessrio programar nada nos clientes. A programao foi feita uma vez s no servidor que foi compartilhada entre os clientes a constraints. 15.8.1.6 - Alterando nomes dos campos Para alterar um nome, como por exemplo o campo descricao, dentro do servidor selecione o campo descricao e mude o display label para Descrio com inicial maiscula e acentuao. Salve as alteraes > compile novamente e rode o programa.

216 Note que todas as estaes clientes esto atualizadas.

Figura 112 Formulrio de teste A programao e alteraes so feitas somente no servidor. No cliente s vai ter um boto Insert da tabela. Para a programao de uma impressora fiscal, est ser feita no servidor, mas a programao de um boto de salvar ou inserir, por exemplo, ser feita no cliente. Se tiver uma nica impressora, a programao poder ser feita somente no servidor. Agora se precisar que a impressora seja local (no cliente), parte da programao da impressora ter que estar no cliente. O que da impressora fica no cliente e o que de banco de dados fica no servidor, isso se tiver uma impressora para cada mquina, mas se for uma impressora compatilhada ento a programao fica no servidor. Para que o usurio no digite valores de espao em branco obrigatoriamente tem que ser digitada a descrio. No servidor selecione o campo descrio e crie uma constraint. A descrio tem que ser diferente de vazio: descricao <> ; Pode ser colocada uma mensgem se no for digitado nada como do tipo: Digite um valor.

217

Figura 113 Propriedade de mensagem de erro. Faa todos os paos j descritos anteriormente para alterar a programao > Salve e execute o programa para testar. OBS: Ao executar o programa note que um erro aparece porque o Delphi est aberto, que na verdade no um erro, so um aviso igual ao Tray e s acontece porque voc est usando o Delphi e num executvel s aparece a mensagem para o usurio.

Figura 114 Mensagem de erro. Digite um campo e deixe em branco a descrio e salve. Aparece um erro de exception (um try automtico, mas o que o usurio final vai ver a mensagem: Digite a descrio e enquanto no for digitada ele no sai do campo e nem avana, mas se quiser, pode cancelar. A programao do cliente se restringe em Refresh e ApplyUpDate. 15.8.1.7 - Propriedades dos componentes DataSetProvider (data access) e ClientDataSet (data access) 15.8.1.8 - DataSetProvider (data access) Constraints -> se as regras de contrantes sero passadas para o clientes DataSet -> a tabela a ser usada

218 Options poFetchDetailsOnDemand -> em ligaes master/detail, se for false, no inclue os registros do detail. poIncFieldProps-> incluir dados sobre as colunas (tamanho da coluna, formato, valor mximo,currency, editmask, displayvalues, etc.) poCascadeDeletes-> delete feito em cascata no details.(banco deve ter suporte a "ON DELETE CASCADE") poCascadeUpdate-> Atualizaes no master devem ser feitas no detail. poReadOnly -> no pode fazer atualizaes. poAllowMultiRecordUpdate-> atualiza vrios registros de uma s vez se for necessrio (sql com vrias tabelas). poDisableInsert-> indica se o cliente pode ou na inserir novos registros(pode inserir = false) poDisableEdit-> indica se o cliente no pode alterar um registro. poDisableDeletes-> se no pode excluir um registro. poAutoRefresh -> atualizar clientes quando forem aplicadas atualizaes. ResolveToDataset-> True: atualizaes de dados do banco sero feitas usando o dataset (BeforePost, AfterPost, etc, sero habilitados). False: Atualizaes feitas pelo Provider (TSQLResolver). mais rpido. UpdateMode-> upWhereAll - Todas as colunas sero usadas como base para localizar um registro (na clausula where . Bom quando duas ou mais pessoas esto atualizando o mesmo registro). upWhereKeyOnly- Usa apenas a chave primria para buscar um registro e atualizar. ( muito rpido). upWhereChangedOnly - Apenas as colunas modificadas. Mtodos: procedure TForm1.DataSetProvider1AfterApplyUpdates(Sender: TObject; var OwnerData: OleVariant); begin end; O tipo OwnerData pode passar qualquer informao entre o cliente e o provedor.

procedure TForm1.DataSetProvider1BeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); Este evento chamado antes de enviar os dados para o banco de dados. O DeltaDS so os valores vindo do cliente.(NewValue, OldValue, CurValue)

219

procedure TForm1.DataSetProvider1GetData(Sender: TObject; DataSet: TCustomClientDataSet); Evento chamado antes de enviar os dados para o cliente. Atravs do dataset, podemos modificar at os valores a serem enviados para o cliente (o dataset igual ao nome da tabela de destino. Como no sabemos quem , s usar o dataset). 15.8.1.9 - ClientDataSet (data access) Mantm uma copia dos dados vindos do provedor na memria do cliente. AggregatesActive -> campos agregados estaro ativos (sim ou no). So parecidos com o campo calculado, mas tem o expression para definir a expresso. Pode causar perda de desempenho no cliente se usado em demasia. AutoCalcFields-> quando o campo calculado ser acionado. True- > quando o foco for para outro controle. False -> quando o dado enviando para o banco. CommandText -> SQL que ser enviando do cliente para sobrepor o do provedor. S ter efeito se a opo poAllowCommandText do provedor for true. DataSetFields-> representa uma ligao detalhe, onde todo o pacote de dados do mster j vem com os dados do cliente, assegurando a integridade.(como se os dados do detail estivessem dentro da tabela mster). DisableStringTrim -> False: so retirados os espaos em branco. Sero retirados antes de serem salvos. True: gravado do jeito que est. FetchOnDemand -> quando chegar ao final do pacote de dados (PacketRecords), deve buscar outro automaticamente. Os dados esto no pacote armazenado em Data. PacketRecords = quantos registros sero trazidos por vez para o cliente (para evitar lotar a memria e deixar a rede lenta) (-1 = todos, 0 = s os metadados (SQL, sem os valores, isto , s o nome dos campos)). FieldDefs-> informaes sobre tamanho, nome, etc. FileName -> usado para criar tabelas temporrias em arquivos, em vez de usar um banco de dados. Pode ser passado como parmetro em outros eventos. Filter e Fieltered -> aplica um filtro nos dados (where) FilterOptions->

220 foCaseInsensitive (no diferenciar maisculas e minuscular) foNoPartialCompare (comparao parcial) ProviderName-> nome do provedor que o CDS est associado. RemoteServer -> Nome do servidor de aplicaes. Podemos usar a propriedade ConnectionBroker para abstrair a conexo do servidor. Mtodos: revertRecord -> desfaz as modificaes feitas no registro corrente. Updatestatus -> Estado das atualizaes dos registros. usUnModified sem atualizaes pendentes usModified tem modificaes a serem aplicadas. usInserted Registro inserido, mas insero no aplicada. usDelete registro excludo mas modificao ainda no aplicada.

15.8.2 Tabelas do banco de dados para teste: create table tab_atividades( id integer not null, decricao varchar(50) ); create table tab_parceiros( id_parc integer not null, nome varchar(50), cnpj char(18), insc_est char(11) ); create table tab_parceiros_cont( id_parc integer, id smallint not null, nome_contato varchar(50) not null, tel_contato varchar(25), email_contato varchar(35) ); create table tab_parceiros_refer( id_parc integer not null, tp_ref char(1), id smallint not null, nome_ref varchar(30) not null, com_dt_ult_compra date, com_vl_tt_compra numeric(18,2), com_vl_prestacao numeric(18,2),

221 com_dt_vcto_ult_parc date, bco_agencia varchar(25), bco_dt_abert_conta date, bco_cheque_esp char(1) ); alter table tab_atividades add constraint pk_tab_atividades primary key (id); alter table tab_parceiros add constraint pk_tab_parceiros primary key (id_parc); alter table tab_parceiros_cont add constraint pk_tab_parceiros_cont primary key (id,nome_contato); alter table tab_parceiros_refer add constraint pk_tab_parceiros_refer primary key (id,nome_ref); alter table tab_parceiros_cont add constraint fk_1014_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade; alter table tab_parceiros_refer add constraint fk_1015_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade; Commit;

15.9 - As Trs Camadas de fato


Nos tpicos anteriores foram desenvolvidos exemplos de aplicao, s que ainda no esto em trs camadas, mas apenas com uma camada, usando um componente de trs camadas (ClienteDataSet), s para ter uma noo do que se est trabalhando, da facilidade de programao. A partir de agora sero criados exemplos em trs camadas. Ser criado primeiro o servidor e depois o cliente ligados a um banco de dados qualquer. Agora o banco de dados ser apenas um repositrio porque toda a programao ficar no servidor de aplicao. Se for alterada alguma caracterstica no servidor, esta alterao se refletir para toda mquina (cliente) ligado a este servidor. Quando trabalhamos com servidor de aplicao em trs camadas importante criar um Data Modulo Remoto, um local em que vai ser feita a programao. O servidor em si no tem tela, um servio de banco de dados, um programa que vai rodar dentro da mquina servidora que vai ficar monitorando, fornecendo recursos e que no tem tela de exibio de dados, da mesma forma que o oracle ou o interbase roda, no fica nenhuma tela mostrando o que esses bancos esto fazendo. A mesma coisa vai ser aqui, vai rodar sem ningum saber e como no tem tela no possvel colocar um banco de dados numa tela, ento vai ser colocado tudo dentro de um Data Modulo. O Data Modulo um formulrio invisvel.

222

15.9.1 - O servidor Abra o Delphi File > new > Other Em New Itens procure a aba Multitier. Clique no Icone Transactional Data Module

Figura 115 Transactional Data Module. Clique OK Multitier Multitarefa. Roda vrias coisas ao mesmo tempo. um Data Modulo que vai fornecer dados para vrias pessoas ao mesmo tempo. Aps feitas as operaes acima se aparecer uma tela do ActiveX est sendo adicionado o Transactional Object no projeto, mas no foi estardado o ActiveX Library. Quando trabalha com DCOM, toda programao vai ser ActivX, isto significa que a programao em Pascal ser transformada em ActiveX e gravada no servidor, um servidor com a linguagem da Microsoft. Este servio ter que ser iniciado (start) para fazer a converso clicando em OK. Aps clicar em OK aparece a tela de dialogo abaixo:

223

Figura 116 Tela de dilogo do Data Modulo Qual o nome do servidor? No campo CoClassName(?) coloque o nome do servidor: No exemplo DataModuloRemoto tudo junto. Tipo de modelo de Thead: Theading Model teremos os campos Single, Apartment e Both. Tanto Single, Apartment ou Both vai poder suportar. No caso vamos colocar Both (ambos). Modelo de transao (Transaction Model) Toda vez que for modelo de transao sempre carrega uma nova transao e cada pessoa que se conecta ao servidor gerado uma transao para ele. Clique em Requires a New Transaction.

Figura 117 Tela de dialogo do DataModuloRemoto. Clique em OK.

224

Pronto foi criado o Data Modulo, isto , o Servidor.

Figura 118 Tela do Servidor Data Modulo. Antes de mais nada, na propriedade Pooled coloque true. Isso habilita um cash para atender aos clientes, cria um Pool, uma class para quando vrios clientes tiverem acessado, ele torna um pouco mais rpido. Vai ocupar um pouco mais de memria no servidor s que em compensao o acesso dos clientes se torna mais rpido. A inteno que o acesso dos clientes seja rpida e no o servidor. A prioridade so os clientes. Salve o servidor. File > Save as > C:/3Camadas/Servidor/DataModulo. Se no tiver as pastas, crie. Nota: o DataModulo no uma tela, por isso que no foi criada a pasta formulrios. Salve o projeto com o Nome P_Serv. Falta fazer a ligao com o banco. Faa no Interbase o banco de dados abaixo para utilizar no exemplo: Tabela para teste: create table tab_atividades( id integer not null, decricao varchar(50) ); create table tab_parceiros( id_parc integer not null, nome varchar(50), cnpj char(18), insc_est char(11) );

225 create table tab_parceiros_cont( id_parc integer, id smallint not null, nome_contato varchar(50) not null, tel_contato varchar(25), email_contato varchar(35) ); create table tab_parceiros_refer( id_parc integer not null, tp_ref char(1), id smallint not null, nome_ref varchar(30) not null, com_dt_ult_compra date, com_vl_tt_compra numeric(18,2), com_vl_prestacao numeric(18,2), com_dt_vcto_ult_parc date, bco_agencia varchar(25), bco_dt_abert_conta date, bco_cheque_esp char(1) ); alter table tab_atividades add constraint pk_tab_atividades primary key (id); alter table tab_parceiros add constraint pk_tab_parceiros primary key (id_parc); alter table tab_parceiros_cont add constraint pk_tab_parceiros_cont primary key (id,nome_contato); alter table tab_parceiros_refer add constraint pk_tab_parceiros_refer primary key (id,nome_ref); alter table tab_parceiros_cont add constraint fk_1014_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade; alter table tab_parceiros_refer add constraint fk_1015_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade; Commit;

No DataModuloRemoto pode ser colocado o banco de dados que quiser. O componente ADO muito lento, ento ser usado o DBExpress que mais fcil de trocar de banco de dados. Coloque no formulrio (DataModuloRemoto) os componentes SQLConection e SQLDataSet da paleta DBExpress. SQLConection o componente que vai se conectar com o banco de dados. Propriedade Name = conexo.

226 Procure o banco de dados para efetuar a conexo. Propriedade do componente SQLDataSet Name = SQL_Geral SQLConnection = Conexao Aps criada a conexo coloque Active = true na tabela e LoginPrompt = false. 15.9.2 - Fornecedor de recursos O fornecedor de recursos est na paleta DataAccess, componente DataSetProvider. ele que vai fornecer os recursos. Quando o(s) cliente(s) for(em) conectado(s) no servidor, todos iro se conectar primeiro no componente DataSetProvider. Para cada tabela (ClienteDataSet) que tiver dentro do Data Modulo temos que ter um componente DataSetProvider correspondente que acessa a tabela e liga no servidor. O DataSetProvider o fornecedor de recursos, ele que compartilha os servios. Adicione o componente DataSetProvider da paleta DataAccess. O DataSetProvider ser ligado a uma tabela, portanto daremos um nome de programao para ele. Propriedades do DataSetProvider: Name = DSP_Ativ. A propriedade DataSet do componente DataSetProvider a tabela que vai ser gravada que por enquanto no colocamos ainda mas essa propriedade determina em qual tabela ser gravada quando for necessrio gravar alguma coisa. Em trs camadas, todas as tabelas estaro no servidor. Da mesma forma que funcionava a dupla DataSourse e Tabela, agora ser DataSetProvider e Tabela. Da Paleta DBExpress coloque mais um componente SQLDataSet. Vai ser a tabela, para cada vez que precisar de efetuar alguma ligao, esta tabela ser a ligao. Preencher as propriedades do SQLDataSet2 > - SQLConnection = conexo - CommandType = table - Command text = (TAB_ATIVIDADES) - Name = Tbl_Ativ - Active = true. Selecione o componente DSP_Ativ e ligue a propriedade DataSet com a tabela (Tbl_Ativ) que antes no tinha.

227

Figura 119 Componentes do DataModuloRemoto. A propriedade Options tem vrias opes que esto descritas abaixo: Options poFetchDetailsOnDemand -> em ligaes master/detail, se for false, no inclue os registros do detail. poIncFieldProps-> incluir dados sobre as colunas (tamanho da coluna, formato, valor mximo, currency, editmask, displayvalues, etc.) poCascadeDeletes-> delete feito em cascata no details.(banco deve ter suporte a "ON DELETE CASCADE") poCascadeUpdate-> Atualizaes no master devem ser feitas no detail. poReadOnly -> no pode fazer atualizaes. poAllowMultiRecordUpdate-> atualiza vrios registros de uma s vez se for necessrio (sql com varias tabelas). poDisableInsert-> indica se o cliente pode ou no inserir novos registros(pode inserir = false) poDisableEdit-> indica se o cliente no pode alterar um registro. poDisableDeletes-> se no pode excluir um registro. poAutoRefresh -> atualizar clientes quando forem aplicadas atualizaes. Na propriedade Options de DSP_Ativ, componente DataSetProvider coloque true nas opes FetchDetailsOnDemand, IncFieldProps, PropagateChanges e AutoRefresh. No Data Modulo foram colocadas a tabela e a conexo, praticamente j est pronto o servidor. Detalhe importante: Clique Control + F12 Verifique P_Serv_PLB

228

Figura 120 Tela de Units. Antes criava s o provedor que foi salvo - o Data Modulo e foi criado tambm o arquivo P_Serv_TLB. Selecione o arquivo que foi criado e pressione F12. O que mostra uma tela de configurao. O nmero (GUID: {981439C8-2642-49E5-B1D8-8E91EBF6CBB3}) do exemplo indica que toda vez que for trabalhar a partir de agora com comandos ou com aplicaes DCOM, gera um nmero para trabalhar. Internamente no trabalha com servidor de aplicao, mas s conhece nmeros, tudo internamente tratado com um nmero. Cada servidor gera automaticamente um nmero nico que no pode ser apagado ou modificado. A tela gerada a mostrada abaixo:

Figura 121 Programao gerada do P_Serv_Tbl.

229 Esta tela tem um campo chamado Interface. Quando criamos a DLL, tinha os campos chamados Interface e Implementation. Interface para declarar as rotinas mas no tem programao e Implemantation para fazer a programao. Neste caso a mesma coisa, uma tela grfica que depois ser criada a rotina que como antes pode ser pressionado com o boto direito do mouse e criar mtodos e propriedades. Aqui pode ser criada vrias propriedades, especificando que tipo de parmetros dever ser usado. Algumas rotinas sero feitas depois. Volte ao Data Modulo 15.9.3 Montando o Servidor Iniciar > painel de controle > ferramentas administrativas > servios de componentes > computadores > meu computador > aplicativos COM+.

Figura 122 Servios de componentes. Veja que por enquanto no tem o servidor do exemplo instalado ainda. Feche as janelas abertas. Agora execute a instalao. No Delphi Clique em RUN > InstallCOM+ Objects.

230

Figura 123 DataModuloRemoto no Install COM. Selecione DataModuloRemoto para abrir a prxima tela Clique no campo: Install into new Application para instalar um novo servidor

Figura 124 Nome do Servidor. Nesta tela digitamos o nome do servidor. Suponha que tem vrios Data Mdulos, poderia escolher qual deles queira colocar (instalar), porque no queremos que todos os Data Mdulos sejam instalados. Coloque o nome: Servidor de aplicao. Esse o nome do Servidor para o exemplo. OBS: Se a aplicao j existir, selecione o Data Modulo a ser instalado escolhendo o campo install into existing Application. No campo Description pode ser descrito para que serve o novo servidor. O sistema pergunta onde vamos criar. Ser instalado dentro de um servidor.

231

Nota: Estamos criando dentro de uma nova aplicao porque podemos colocar quantos servios quiser dentro de um servidor mas o ideal ter servios separados porque na hora que parar o servidor no para os outros servios que esto sendo executados. Aps criar clique em OK e OK novamente. Agora vamos colocar tudo dentro do Servidor de aplicao. Clique em RUN > Register ActiveX Server Note que aps executado o registro criada uma DLL.

Figura 125 Informao de sucesso de registro do ActiveX. Clique em OK. Aps executado os passos anteriores, verifique no Arquivo de ferramentas Administrativas, servio de componentes a criao do Servidor de Aplicao. Iniciar > painel de controle > ferramentas administrativas > servios de componentes > computadores > meu computador > aplicativos COM+.

Figura 126 Servidor de Aplicao criado no Servios de componente.

232 O Servidor de aplicao est inativo. Para ativa-lo clique com o boto direito do mouse em cima dele e inicialize o servio. Se for solicitado algum servio ao servidor, ele inicializa sozinho. A partir do momento que comea a rodar, se for feita alguma alterao no Delphi e tentar instalar novamente o ActiveX no ser possvel fazer a alterao, ento toda vez que necessitar compilar novamente o servidor, ter que parar o servio, compilar e iniciar novamente. Salve a aplicao. Selecione o COM+ (Objeto COM). Mande que faa uma sincronizao de objetos. Colocar objetos tudo como Pooling. Para cada vez que criar um objeto, crie tambm um Cash para ficar mais rpido o plugin. Pode fechar. O sistema salva as modificaes automaticamente ao fechar. Est pronto o servidor e pode ser executado. 15.9.4 - Os Clientes Inicie uma nova aplicao que vai acessar o servidor criado. A partir de agora tudo que vai ser utilizado estar na paleta DataAccess ou DataControls A tabela vai ser sempre o ClienteDataSet. Da paleta DataAccess coloque o componente ClienteDataSet. Propriedades name = Tbl_Ativ. 15.9.5 - Primeira forma de conexo via DCOM Para conectar a base de dados no podemos usar o componente SQLConnection porque este componente j esta no DataModulo uma conexo s com o banco. Ento como conectar com o banco de dados? Da Paleta DataSnap coloque o componente DCOMConnection que far a conexo. Propriedades: - Name = DCOM_Conexao Na propriedade ComputerName vamos colocar o nome do computador porque o sistema estar rodando em rede e o servidor pode estar em outra mquina. Coloque o nome do Servidor. Como no exemplo que est sendo feito, o servidor est na prpria mquina e se no sabemos o nome da mquina, colocamos localhost.

233 Propriedade SeverName Pode ser colocado o ServerGUID que o nmero gerado na aplicao anterior do servidor. S que provavelmente esse nmero no foi memorizado, ento mais fcil instalar pelo ServerName. Use o nome do Servidor de Aplicao P_Server. Note que quando foi colocado o nome, o nmero gerado na aplicao anterior tambm aparece.

Figura 127 Object Inspector do componente DCOM_Conexo. Coloque a propriedade Conected = true. No componente ClientDataSet ( Tbl_Ativ), determine em que tabela ser ligada. Na propriedade RemoteServer coloque DCOM_Conexao. O Provider No DSPDataSetProvider ser indicada qual o ProviderName, qual a tabela. O DSPAtividade j aparece. Na propriedade ProviderName selecione DSP_Ativ. Agora a tabela j est conectada. Coloque o nome da tabela. Coloque a propriedade Active = true.

234

Figura 128 Object Inspector do componente Tbl_Ativ (ClientDataSet). Se quiser deixar o campo agregado com calculo do total, na propriedade AggregatesActive coloque true. Importante: Se no for preciso o campo agregado, como por exemplo, numa tabela de cliente que no tem nenhum campo total de cliente, deixe falsa sempre que no for utilizar campo agregado, porque isso consome recurso de memria. Essas propriedades so do clientes. Se for necessrio ter campo agregado, na tabela de itens por exemplo, ento deixe a propriedade agregate como true o resto deixe como false para no consumir CPU. 15.9.6 - A propriedade PacketRecords Quando trabalhamos com Cliente Servidor, vinha todos os dados do servidor para cliente. Aqui podemos especificar, neste caso, est com parmetro (-1), isto significa pegar todos os dados do servidor e sai. Do jeito que est ficar com o mesmo problema da arquitetura do Cliente Servidor que traz a tabela inteira. Podemos determinar ento que no traga tudo, mas apenas o necessrio. Mude ento no campo PacketRecords para 30. Quando determinado esse valor, significa que cada vez que for acessado o servidor, trar apenas 30 registros e na hora que clicar para trazer mais dados do banco, vai trazer mais 30 registros. No caso de um supermercado no usa Table, mas sim SQL e busca a tabela atravs de comando SQL e traz os dados, mas se for um cdigo de barras, chama uma SQL e busca somente aquele registro correspondente ao cdigo de barras. J foi colocado o ClientDataSet ligado ao DCOMConnection. Agora colocamos um DataSourse. Da paleta DataAccess coloque um DataSourse. Propriedade Name = DS_Ativ. DataSet = Tbl_Ativ

235 Da paleta DataControl coloque uma Grid e um DBNavigator, somente para mostrar os dados. Lique a Grid e o DBNavigator ao DataSourse. Se os dados no estiverem sendo mostrados verifique se o DataSourse est ligado ou se a tabela est ativa (Active = true). Detalhe: Quando mandar incluir um dado, ser includo somente na memria e s vai salvar no banco do servidor quando for aplicado um comando Post (Salvar). Clique no ClienteDataSet > Eventos > After Post para abrir o modulo de programao. Aps salvar pega a tabela e atualiza. Programao: procedure TForm1.Tbl_AtivAfterPost(DataSet: TDataSet); begin Tbl_Ativ.ApplyUpdates(0); Tbl_Ativ.Refresh; end; Toda vez que executar um Post(salvar) atualiza no servidor. Se deixar para fazer isso no final de um dia? Imagine se for feita 50 vendas e de vez em quando efetua um Post, o nico problema faltar energia ou ter alguma falha na mquina cliente, perde-se todos os dados porque esses dados estaro numa tabela temporria (cash). Assim por segurana, cada vez que salvar j atualiza no servidor, automaricamente. Salve a aplicao com o nome camadas/clientes/U_CadAtiv. Salve o projeto com o nome de P_Cliente. O formulrio ficar com o aspecto mostrado abaixo: U_CadAtiv em C:/Alunos/3

236

Figura 129 Formulrio de Clientes. Nota: Em duas camadas, temos muitas tabelas e uma nica conexo no formulrio principal. Agora temos uma aplicao com muitas tabelas e uma nica conexo tambm no formulrio principal usando o componente DCOM. Execute a aplicao. Se cadastrar o cdigo (-6), o aplicativo permite e salva um cdigo negativo. Para fazer com que o sistema no permita cadastro de nmero (cdigo) negativo ter que sr feito um tratamento. Para colocar somente nmeros maiores que zero, ou programamos em cada estao cliente, ou programamos uma trigger no banco de dados. Feche o aplicativo cliente. Abra o Servidor.

Faa uma restrio, o cdigo ID s pode ser positivo. Duplo clique na tabela. No editor com o boto direito do mouse clique novamente e adicione todos os campos > Add AllField. Selecione o campo ID. Na propriedade CustonConstraint indique que o campo ID ser maior ou igual a zero: ID >=0 Pode ser colocada uma mensagem para o usurio de no caso digitar um valor negativo: Na propriedade ConstraintErro coloque a mensagem: Digite nmeros maiores que zero.

237

Figura 130 Object Inspetor do componente SQL_Ativ. Salve as alteraes efetuadas. Para recompilar , pare o servio do Banco de Dados. S quando parar o Servidor possvel atualizar os dados. Volte no servidor > clique em RUN > registre novamente > Register ActiveX Server. Ative novamente o Servidor. 15.9.7 - Fazendo mais uma exportao. No cliente no vai ser modificado nada. Nos campos ID e Descrio ser feito um exemplo de modificao de campo manipulando somente o Servidor. Abra o Servidor. Duplo clique na Tabela (SQL_Ativ). Selecione o campo ID e na propriedade Display Label Digite Cdigo. Selecione o campo descricao e na propriedade Display Label Digite Descrio com todos os acentos. Pare o servidor e compile novamente Registre novamente o servidor e ative de novo o servio. Execute o aplicativo cliente.

238

Figura 131 Formulrio cliente em execuo. Note que os campos ID e Descrio da Grid foram atualizadas. Qualquer propriedade que for modificada, Display Label, tamanho, etc. ser refletido no cliente. 15.9.8 - Tratamentos Campos em branco (sem preenchimento) Para que no seja permitido campo sem digitao, como por exemplo a descrio, ser criada uma constraint. Duplo clique na tabela SQL_Ativ da aplicao do Servidor. Selecione o campo descrio e na propriedade Constraint ser determinado que o campo chamado Descrio ser diferente de vazio (descricao <> ). Para a mensagem coloque Descrio deve ter valor.

Figura 132 Object Inspector do componente SQL_Ativ. Pare o Servidor e compile novamente. Registre o servidor e ative de novo. Rode o aplicativo cliente para testar. Digite o cdigo e deixe em branco a descrio. Neste ponto ser mostrada a mensagem de erro: Descrio deve ter valor;

239 15.9.8.1 - Auto Numerao de Cdigo (ID) Abra o Servidor.

No DataSetProvider (DSP_Ativ) ser feita a maioria da programao porque entre os eventos tem um chamado BeforeUpdataRecord. Quando for executado esse comando, antes de salvar no banco, vai executar o que est ali dentro e neste ponto que vai ser feita a auto numerao para depois salvar. O evento BeforeUpdataRecord um dos eventos mais importantes do projeto. Se duas pessoas comearem a cadastrar dados na tabela Cliente, um cadastra o nome Joo e outro cadastra o nome Jos e sero salvos no mesmo servidor de aplicao. O primeiro e o segundo executam o comando que nunca, mas nunca sero exatamente no mesmo instante, mesmo que seja por milionsimos de segundos. Esses dados sero colocados numa fila de execuo. Aquele que chegar primeiro executa o evento BeforeUpdataRecord. No importando o numero de cdigo que foi digitado, esse numero vai ser descartado, gerando um novo nmero para o primeiro registro da fila e manda atualizar, salvando no banco de dados e aps isso gera um numero consecutivo para o segundo registro, atualizando no banco BeforeUpdataRecord DeltaDS so os dados que so originados do cliente, um pacote com todos os dados. Por exemplo: para alterar o cdigo DeltaDS.FieldByName(ID.NewField) := <NovoValor>; Ele como se fosse uma tabela, s que os dados provem do cliente. Uma Tabela que s tem um registro acumulado no cliente. Antes de salvar, altere. Exemplo: se temos um numero(old) j registrado, um valor que tinha anteriormente na tabela, se quiser trocar (colocar um comando new), pega um valor anterior e soma mais um. Ento temos um oldt(antigo) e um new(novo) que pode ser colocado no lugar do antigo. Para fazer uma atualizao, numerar e colocar automaticamente, ser feito um comando SQL para efetuar uma consulta no servidor, verificar o ltimo nmero e retornar. Este exemplo para treinamento de comandos no banco de dados, mas pode ser criada uma varivel para armazenar o ltimo nmero existente. No evento BeforeUpDataRecord, em DeltaS vai ter um comando SQL para pegar o ltimo registro. Selecione DBExpress Coloque um componente SQLDataSet no DataModulo da aplicao Servidor. Propriedades: Name = SQL_Geral

240 SQL_Connectio = conexo CommandType = ctQuery CommandText = clique nas reticencias para abrir o editor de SQL. Nesta tabela vai ter uma Query com o seguinte comando: Selecione o Max de ID 0 maior valor do campo ID e soma mais 1. O campo vai se chamar Maior.

Figura 133 Editor SQL. O Select vai pegar o maior valor do campo ID e somar mais um. O FieldByName vai se chamar Maior. Teste o aplicativo. Quando colocar a tabela em Active = true e no der erro porque o cdigo est certo. Deixe a tabela em Active = false.

15.9.9 - Programando o evento BeforeUpdataRecord. Selecione o componente DataSetProvider (DSP_Ativ) para programar o evento BeforeUpdataRecord.

Quando executar o evento, vai pegar a tabela SQL_Geral e colocar true na programao: SQL_Geral.Active := true; Vai ser ativado o SQL, substituindo o valor: DSDelta.FieldByName(ID).NewValue:= SQL_Geral.fieldByName(maior).AsInteger;

241 procedure TDataModuloRemoto.DSP_AtivBeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); begin Sql_geral.Prepared:=true; SQL_Geral.Active:=true; DeltaDS.FieldByName('id').NewValue:= SQL_Geral.fieldbyname('maior').AsInteger; // showmessage(inttostr(SQL_Geral.fieldbyname('maior').AsInteger)); SQL_Geral.Active:=false; Applied:=FALSE; end; O que est vindo do cliente, pega o que esta dentro do campo ID no importando o que tem l dentro e substitui por um novo valor que est programado no SQL. SQL_Geral.FieldByName(maior).AsInteger; que de qualquer tipo, no precisa colocar String ou outro tipo, a conversa feita automaticamente. Depois que tem o valor, desativa a tabela (SQL_Geral.Active = false) para no ficar aberta a conexo que j foi atualizada. Applied Essa propriedade determina quem vai controlar, se o usurio que vai controlar ou se o evento ApplyUpData. No caso ele vai controlar sozinho. Ento coloque a propriedade ApplyUpDate = false. Esse comando s para indicar quem vai controlar o ApplyUpData. O servidor vai controlar. Se for colocado true, ento ter que ser feito um comando de ApplyUpData. Pare o servio do servidor. Recompile o aplicativo e reinicie o servio. Execute o aplicativo para testar. Se dois clientes cadastrar ao mesmo tempo e o ultimo numero registrado o numero 9. Foi colocado o numero 100 e o numero 200 um para cada cliente. Mesmo que colocar um cdigo bem diferente, o programa vai descartar esse cdigo e colocar um valor seqencial que foi determinado na auto-numerao. Para no pegar lixo, colocamos um comando Prepared para limpar e carregar novamente. Salve o Servidor e feche. Abra o cliente. Independente do valor que digitar nos eventos BeforePost (antes de salvar) feche a tabela e coloque um zero no lugar. procedure TForm1.Tbl_AtivBeforePost(DataSet: TDataSet);

242 begin Tbl_Ativ.FieldByName('id').asinteger:=0; end; Ao digitar qualquer valor, este valor ser substitudo por zero e esse zero ser descartado na atualizao colocando um novo valor auto-numerado. OU Desabilite o campo colocando true. Duplo clique da Grid. Clique com o boto direito no editor e adicione todos os campos. Selecione o campo ID e na propriedade ReadOnly coloque true. Salve e execute o programa colocando um novo registro.

15.9.10 - Refresh da tela (Atualizao) Quando salvar nos clientes automaticamente atualiza a tela. Como o banco do aplicativo pequeno, no caso por exemplo de um outro banco que tem uma tabela de pedido, no ficar executando atualizaes da tela a todo momento porque no pedido s vai ser mostrado s o atual e no tem sentido atualizar a tela a todo instante. A atualizao de tela deve ser feita mais vezes no caso de uma tabela de produto ou cliente. Nota: A atualizao s vai ser feita quando o sistema no estiver executando nenhum comando. Da paleta System coloque o componente Timer No eveno BeforPost do componente ClienteDataSet ( Tbl_Ativ) faa a seguinte linha de programao: procedure TForm1.Timer1Timer(Sender: TObject); begin if Tbl_Ativ.State = dsBrowse then Tbl_Ativ.Refresh; end; Vai executar Time, s que vai fazer a atualizao (Refresh) quando estiver em Browser (navegando). Se estiver em insero, edio ou busca, no far atualizao nenhuma.. Pode tambm ser colocada uma mensagem de retorno para saber se foi atualizado ou no. Pare o servidor. Salve o aplicativo. Registre o servidor e ative novamente o servio.

243

Execute o cliente e teste o aplicativo.

15.9.11 - Programao dos projetos Servidor e Cliente unit U_DataModulo; {$WARN SYMBOL_PLATFORM OFF} interface uses Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, ComServ, ComObj, VCLCom, StdVcl, bdemts, DataBkr, DBClient, MtsRdm, Mtx, P_server_TLB, DBXpress, FMTBcd, DB, SqlExpr, Provider; type TDM_ServidorRemoto = class(TMtsDataModule, IDM_ServidorRemoto) Conexao: TSQLConnection; DSP_Ativ: TDataSetProvider; Tbl_Ativ: TSQLDataSet; Tbl_AtivID: TIntegerField; Tbl_AtivDECRICAO: TStringField; SQL_Geral: TSQLDataSet; procedure DSP_AtivBeforeUpdateRecord(Sender: TObject; SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); private { Private declarations } protected class procedure UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); override; public { Public declarations } end; var DM_ServidorRemoto: TDM_ServidorRemoto; implementation {$R *.DFM} class procedure TDM_ServidorRemoto.UpdateRegistry(Register: Boolean; const ClassID, ProgID: string); begin

244 if Register then begin inherited UpdateRegistry(Register, ClassID, ProgID); EnableSocketTransport(ClassID); EnableWebTransport(ClassID); end else begin DisableSocketTransport(ClassID); DisableWebTransport(ClassID); inherited UpdateRegistry(Register, ClassID, ProgID); end; end; procedure TDM_ServidorRemoto.DSP_AtivBeforeUpdateRecord (Sender: TObject;SourceDS: TDataSet; DeltaDS: TCustomClientDataSet; UpdateKind: TUpdateKind; var Applied: Boolean); begin Sql_geral.Prepared:=true; SQL_Geral.Active:=true; DeltaDS.FieldByName('id').NewValue:= SQL_Geral.fieldbyname('maior').AsInteger; // showmessage(inttostr(SQL_Geral.fieldbyname('maior').AsInteger)); SQL_Geral.Active:=false; Applied:=FALSE; end; initialization TComponentFactory.Create(ComServer, TDM_ServidorRemoto, Class_DM_ServidorRemoto, ciMultiInstance, tmBoth); end.

Unit U_CadAtiv; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, DBCtrls, Grids, DBGrids, DB, DBClient, MConnect; type TForm1 = class(TForm) Tbl_Ativ: TClientDataSet;

245 Dcom_Conec: TDCOMConnection; DS_Ativ: TDataSource; DBGrid1: TDBGrid; DBNavigator1: TDBNavigator; Timer1: TTimer; procedure Tbl_AtivAfterPost(DataSet: TDataSet); procedure Tbl_AtivBeforePost(DataSet: TDataSet); procedure Timer1Timer(Sender: TObject); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.Tbl_AtivAfterPost(DataSet: TDataSet); begin Tbl_Ativ.ApplyUpdates(0); end; procedure TForm1.Tbl_AtivBeforePost(DataSet: TDataSet); begin Tbl_Ativ.FieldByName('id').asinteger:=0; end; procedure TForm1.Timer1Timer(Sender: TObject); begin if Tbl_Ativ.State = dsBrowse then Tbl_Ativ.Refresh; end; end.

246

16 - Balana Comercial

Figura 134 Balana Toledo As balanas tem um parmetro de comunicao. H um protocolo que deve existir quando compramos uma balana. A balana Toledo no envia o protocolo, nem a DLL. Com isso o grupo CBR implementou atravs do protocolo de comunicao que essa balana emite dentro de um componente e tambm as funes de uma DLL. A vantagem que quando colocamos o componente no necessrio instalar a DLL, o componente gera um executvel e o protocolo de comunicao vai estar tudo l dentro.

16.1 - Instalando o Componente


Para implementar, em www.sourceforge.net primeiro lugar vamos baixar o componente do site

Na rea de pesquisa, digite ACBr e clique em Search e ao visualizar o componente faa o download. H vrias pastas no download, basta pegar direto o componente e dentro dele tem diversos demos. Aps feito o download, salve dento de uma pasta de sua preferncia, por exemplo: Alunos/<nomesubpasta>

247

Agora s instalar o componente. Para instalar o componente, descompacte o arquivo em uma pasta que ningum possa apagar, por exemplo dentro da pasta do Delphi, isso se for na sua mquina. Dentro do Delphi, crie uma pasta chamada componente e coloque o arquivo l dentro. No arquivo leia-me explicado a instalao que mostra a descrio, licena, compatibilidade, etc.

16.1.1 - Descrio da pasta leia-me


+---------------------------------------------------------------------+ | | | Projeto: Componentes ACBr Versao 0.8.4b | | | | Biblioteca multiplataforma de componentes Delphi para | | interao com equipamentos de Automao Comercial | | utilizados no Brasil | | | | http://acbr.sourceforge.net | | | +---------------------------------------------------------------------+ INDICE 1. Descrio 2. Licena 3. Compatibilidade 4. Como executar os Demos. 5. Instalao 6. Componentes 7. Autores e Colaboradores 8. Como posso ajudar no projeto 9. Vantagens e Desvantagens 10. Tarefas que ainda precisam ser iniciadas, melhoradas ou completadas 11. Histrico do desenvolvimento -------------------------------------------------------------------------------1. DESCRIO O mercado de automao comercial Brasileiro est em franca expanso. Vrios fabricantes vem disponibilizando vrios equipamentos para permitir a criao de Programas de Ponto de Venda. Entre esses equipamentos podemos citar: Impressoras Fiscais, Gavetas de Dinheiro, Impressoras de Cheque, Transferncia Eletrnica

248 de Fundos (TEF), Monitor de Bombas de Combustvel, Display de Mensagens, etc. Quase todos os fabricantes disponibilizam DLL's para acesso a seus equipamentos, entretanto para uma aplicao de Automao Comercial acessar vrios equipamentos so necessrias vrias DLL's,o que dificulta a instalao e manuteno dos Programas. Outro problema a no disponibilizao de SO's, por parte dos Fabricantes, para acesso aos equipamentos em Linux. O objetivo desse projeto desenvolver uma Paleta de Componentes para a Linguagem Delphi com verses VCL e CLX, que permita acesso direto a esses equipamentos, sem DLL's, interagindo com eles direto na porta serial (ou outra porta a qual eles sejam ligados). Alm de permitir a programadores da Linguagem Kylix, acesso direto a esses equipamentos em Linux. -------------------------------------------------------------------------------2. LICENA Esta biblioteca software livre; voc pode redistribu-la e/ou modific-la sob os termos da Licena Pblica Geral Menor do GNU conforme publicada pela Free Software Foundation; tanto a verso 2.1 da Licena, ou (a seu critrio) qualquer verso posterior. Esta biblioteca distribuda na expectativa de que seja til, porm, SEM NENHUMA GARANTIA; nem mesmo a garantia implcita de COMERCIABILIDADE OU ADEQUAO A UMA FINALIDADE ESPECFICA. Consulte a Licena Pblica Geral Menor do GNU para mais detalhes. (Arquivo LICENA.TXT ou LICENSE.TXT) Por favor leia pelo menos a Introduo do arquivo LICENA.TXT, se voc deseja usar essa biblioteca em algum Programa Comercial, ou ainda criar uma modificao dessa Biblioteca. Porque o projeto OpenSource ? realmente muito difcil fazer um projeto desse tamanho sozinho. Conseguir acesso a diversos equipamentos para testes, em diferentes sistemas operacionais e configuraes de mquinas. Por isso acho que compartilhando minhas informaes com a comunidade, tambm serei beneficiado... seja com sugestes, ajuda nos testes, e at mesmo com a colaborao de outros desenvolvedores.

-------------------------------------------------------------------------------3. COMPATIBILIDADE Compatvel com Delphi 5, 6, 7; Kylix 3; e futuramene Lazarus (FreePascal) Pode haver compatibilidade com verses inferiores ao Delphi 5, porm ainda no foi testado...

249 Por enquanto no possvel intalar a verso VCL e CLX da Biblioteca simultaneamente. Durante o desenvolvimento foi usada a seguinte Plataforma: - Windows 98 SE Delphi 7 Professional - Windows XP Home SP2 Delphi 7 Professional - Conectiva 10 Kylix 3 Patchs no oficiais para CLX DEVEM SER APLICADOS ( http://unvclx.sf.net ) -------------------------------------------------------------------------------4. COMO EXECUTAR OS DEMOS Atualmente o ACBr ainda no possui um Manual de Ajuda ou qualquer outra documentao. A melhor maneira de aprender como usar os componentes ACBr observar o cdigo dos Programas de demonstrao... Se voc instalou a verso CLX da ACBr abra apenas os programas de demos da pasta ACBr\Source\Pascal\Demos\CLX. Se voc instalou a versao ACBr\Source\Pascal\Demos\VCL VCL da ACBr, use os demos da pasta

Os Demos Linux precisam da biblioteca QT/Borland (libborqt-6.9-qt2.3.so) disponvel no Kylix (/usr/local/kylix/bin). Para rodar os demos em uma mquina que no possua o Kylix instalado, copie a biblioteca acima para o diretrio /usr/lib. Se voc no possui o Kylix instalado, as bibliotecas de run-time podem ser achadas em: http://kylixlibs.sourceforge.net -------------------------------------------------------------------------------5. INSTALAO 1. Descompacte o arquivo .ZIP na pasta de sua preferncia. 2. Abra o arquivo .DPK para a verso desejada. Na IDE do Delphi acione "File, Open" Localize o arquivo ACBr\Source\Pascal\ACBr_CLX.DPK (para verso CLX) ou ACBr\Source\Pascal\ACBr_VCL.DPK (para verso VCL) ACBr\Source\Pascal\ACBr_D5.DPK (para Delphi 5) 3. Compile e Instale a Biblioteca. Clique em "Compile" e em seguida em "Install". Feche o arquivo DPK necessidade de salvar).

(no h

4. Adicione o diretrio " ACBr\Source\Pascal " no "Library Path". Na IDE do Delphi acione "Tools, Enviroment Options" selecione a guia "Library", clique

250 no boto elptico (...) de "Library Path", clique no boto elptico (...) frente da caixa de texto, localize a pasta " ACBr\Source\Pascal " no diretrio de instalao da Biblioteca, clique em "OK", e em "Add". Click em "OK" para finalizar. 5. A paleta ACBr ser criada com os componentes da Biblioteca ACBr.

***** Nota IMPORTANTE sobre a Verso CLX ***** - Ao iniciar um NOVO projeto em CLX adicione a clausula "VisualCLX" ou "CLX" em "Conditional Defines". - Clique em "Project", "Options" ou SHIFT-CTRL-F11 - Clique na aba "Directories/Conditionals" - Digite VisualCLX em "Conditional Defines" e clique em OK. Nota para o uso das verses VCL / CLX. Se voc j instalou uma verso (VCL ou CLX) e pretende instalar a outra verso... necessrio clicar em "Project, Build ACBr...", antes de "Compile" e "Install". Isso ir gerar corretamente os arquivos DCU para a nova verso, pois algums arquivos so compartilhados entre as duas verses... -------------------------------------------------------------------------------6. COMPONENTES * IMPORTANTE * Durante a fase Beta do Projeto, alguns relases ocorrero sem os devidos testes em alguns modelos de equipamentos. Isso por causa da dificuldade de conseguir Hardware disponvel para testes. Antes de cada release, fazemos o maior esforo possvel para testar o maior nmero de modelos, contactando Colaboradores ou Fabricantes. Muitos fabricantes gentilmente nos ajudaram nos testes, outros nem tanto... Se voc possui acesso a algum equipamento que do escopo do projeto ACBr, SEJA VOC TAMBM UM COLABORADOR..... Ficaremos muito gratos com a sua participao no projeto.

Inicialmente imaginamos desenvolver os seguintes componentes ACBrECF - Para se comunicar com Impressoras Fiscais (ECF). A idia substituir os comandos da DLL por chamadas aos mtodos do componente ACBrECF, com a vantagem imediata de tornar o seu cdigo compatvel a todas os Modelos de Impressoras suportadas pelo ACBrECF, apenas escolha o modelo e pronto... Inicialmente suportando os seguintes modelos: Bematech, Daruma, Schalter, Sweda, Mecaf (e compatveis) ACBrGaveta - Para acionamento de Gavetas de dinheiro. Com suporte a gavetas ligadas a Porta Serial, ou diretamente ao ECF ou ainda ligadas a Impressoras no Fiscais (paralela ou serial). Inicialmente suportando os seguintes modelos: Menno, Gerb.

251 ACBrCheque - Para impresso de Cheques. A impressora de cheques pode ser avulsa ou conjugada ao ECF (ECF 2 estaes). Inicialmente com suporte as Impressoras de Cheque Chronos, Bematech, e todos ECF's 2 estaes suportados por ACBrECF ACBrDisplayCliente - Display de Mensagens de 2 linhas para o Cliente (fica voltado para o Cliente e exibe informaes sobre a venda...). Inicialmente suportando o Gertec ACBrDisplayOperador - Display de Mensagens de 2 linhas acoplado a teclados reduzidos, comunicando pela porta AT. Modelos: Gertec ACBrBombas - Monitor de Bombas de Combustvel, lendo os abastecimentos gerados, alterando os preos das Bombas. Modelo suportado: CompanyTec ACBrLeBarras - Permitindo acesso a informao lida por Leitores de cdigo de Barra ligados a porta serial. ACBrLeCMC7 - Leitor de cdigo CMC7 de Cheques. (Nenhuma experincia do autor). ACBrSintegra - Componente para formatar informaes no LayOut do Sintegra, suportando os registros da serie 50 e 60 ACBrTEF - Componente para facilitar a criao dos arquivos de troca entre a Aplicao Comercial e os programas das Operadoras. (Experincia apenas com TEF Discado) ACBrCalculadora - Mais uma calculadora... mas com algumas frescuras a mais, como por exemplo, um Memo simulando a fita (permitindo salvar) ACBrUtil - Unit contendo diversos procedimentos e funes teis para aplicaes comerciais: ValidaCNPJ, ValidaCPF, ValidaINSCEST, Extenso, etc -------------------------------------------------------------------------------7. AUTORES E COLABORADORES - Daniel Simes de Almeida Administrao do Projeto, Desenvolvimento - Alexandre Rocha Lima e Marcondes Administrao do Projeto e Suporte - Andre Ferreira de Moraes WebMaster, Documentao, Arquivos de ajuda - Projeto Jedi Diversas rotinas e o arquivo ACBr.inc foram baseados no cdigo da JCL e JVCL --------------------------------------------------------------------------------

252

8. COMO POSSO AJUDAR NO PROJETO Se voc possui experiencia em Automao comercial e deseja ajudar, junte-se a ns... ficaremos muito contente com a sua ajuda. * Testando os Componentes: Fizemos o possvel para eliminar os bugs mais bvios... mas em ambientes diferente bugs novos podem aparecer. Por favor ns envie-nos um e-mail com os seus testes. Mesmo que tudo d certo ainda sim gostariamos da sua opnio... * Divulgando o ACBr: Quanto maior o uso da biblioteca mais usurios podem ajudar. Se a biblioteca for bem conhecida e utilizada os Fabricantes de equipamentos de Automao Comercial tero maior interesse em ajudar no desenvolvimento. * Desenvolvendo Componentes: Alguns componentes como o ACBrECF devero ser implementados para vrios modelos de equipamento. Se o equipamento que voc deseja no consta na relao de Equipamentos a compatveis voc pode estudar os Fontes e tentar implementar uma nova Classe para o seu Equipamento (Por favor, entre em contato antes) * Emprestando Equipamentos: Nem sempre temos acesso aos Equipamentos para testes e melhorias. Se voc um fabricante ou possui um equipamento disponvel para emprestimo, entre em contato Em breve estarei relacionando os equipamentos que necessitam de testes... * Efetuando Doaoes: Atualmente a Biblioteca desenvolvida no tempo livre disponvel dos Desenvolvedores.... Doaes podem motivar os desenvolvedores a destinar mais tempo para o andamento do projeto.... pois ... at mesmo os programadores precisam comer.... ;-) -------------------------------------------------------------------------------9. VANTAGENS E DESVANTAGENS Vantagens: - Multiplataforma: Linux / Windows - Programao Limpa e Clara: Basta inserir um componente ACBrECF no seu projeto e configurar o Modelo. O Codigo fonte sempre ir se referir a esse componente, sem se preocupar com implementaes especficas de cada Modelo. - Total controle da Aplicao: J vi DLL's que simplesmente param o processamento do programa (Quem j homologou TEF discado, sabe o que eu quero dizer...) - Facil distribuio: No precisa distribuir e instalar nenhuma DLL - Livre-se do Inferno das DLL's. (Quando o usurio instala outro programa que usa a mesma DLL que voc usa, porm em uma verso antiga (causando Bugs no seu programa)

253 ) Desvantagens: - Se o hardware mudar, ficamos dependendo de novas informaes do fabricante, ou at mesmo de um modelo do equipamento para testes... - Geralmente as DLL's incorporam novos Hardwares do mesmo fabricante.... Aqui teremos que implementar um novo filho das classes Basicas para cada Hardware novo (somente se o novo hardware no for compatvel com o antigo) -------------------------------------------------------------------------------10. TAREFAS QUE AINDA PRECISAM SER INICIADAS, MELHORADAS OU COMPLETADAS Na verso atual existe tanto a fazer e programar que essa seo seria muito grande.... ;-) -------------------------------------------------------------------------------11. HISTRICO DO DESENVOLVIMENTO Por favor leia o arquivo: " ACBr-change-log.TXT "

16.1.2 - Instalao Descompacte o arquivo .ZIP na pasta de sua preferncia. Abra o arquivo .DPK para a verso desejada. Na IDE do Delphi acione "File, Open" Localize o arquivo ACBr\Source\Pascal\ACBr_CLX.DPK (para verso CLX) ou ACBr\Source\Pascal\ACBr_VCL.DPK (para verso VCL) ACBr\Source\Pascal\ACBr_D5.DPK (para Delphi 5) Dando duplo clique neste arquivo, vai abrir o Delphi. Ao abrir o Delphi, aparecer o pacote para instalao e compilao do componente ACBr, conforme mostrado abaixo:

254

Figura 135 Contedo do pacote ACBr Compile e Instale a Biblioteca. Clique em "Compile" e em seguida em "Install". Feche o arquivo DPK necessidade de salvar). (no h

Figura 136 Mensagem de instalao do pacote ACBr. O quadro abaixo informa que a compilao foi bem sucedida. Clique em OK.

Figura 137 Informaes de instalao do pacote ACBr

255 Adicione o diretrio " ACBr\Source\Pascal " no "Library Path". Na IDE do Delphi acione "Tools, Enviroment Options" selecione a guia "Library", clique no boto elptico (...) de "Library Path", clique no boto elptico (...) frente da caixa de texto, localize a pasta " ACBr\Source\Pascal " no diretrio de instalao da Biblioteca, clique em "OK", e em "Add". Click em "OK" para finalizar. A paleta ACBr ser criada com os componentes da Biblioteca ACBr.

Figura 138 - Paleta ACBr com todos os seus componentes instalados.

ACBr VCL um pacote para o Delphi, uma paleta inteira no compilada

16.2 - Um Exemplo
Para exemplificar ganhando tempo, vamos pegar um projeto demo pronto que j est dentro do arquivo ACBr. Abra o Delphi. Clique em File/Open Localize o arquivo na pasta ACBr/Sourse/Pascal/Demo/VCL e abra o projeto BalanaTeste. No salve o projeto. O sistema de comunicao com a balana ser aberto. Rode o Demo

256

Figura 139 Formulrio do demo BalancaTeste Selecione a balana. Escolha a porta de comunicao que no caso o COM mesmo. No ser necessrio modificar nada. A nica escolha a ser feita a balana que no caso da marca Toledo. Aps a escolha mande ativar. Foi feita a leitura, esta ligada e conectada agora faremos a leitura de peso colocando um peso qualquer na balana, mandamos fazer a leitura. No exemplo deu 172 gramas que o peso que foi colocado na balana. A resposta que a balana mandou, o numero 2, indicando que peso. Est enviando peso que 00 99999 gramas lgico que essa balana no agenta 99 quilos, o mximo que essa balana agenta 15 quilos, mas isso s para exemplificar. Se fosse 1200 gramas ento mostraria o 1 (um) e embaixo 200. O smbolo #3 no final para indicar que terminou a leitura do sistema. 16.2.1 - A programao do componente. No exemplo usaremos a balana Toledo. A porta de comunicao estar ligada na prpria Com da mquina (COM1 ou COM2)

257

Figura 140 Propriedades da paleta ACBr object ACBrBAL1: TACBrBAL Porta = 'COM1' OnLePeso = ACBrBAL1LePeso Left = 408 Top = 56 end Esse o componente que faz tudo. O que temos que verificar nele?

Figura 141 Campo genrico do formulrio demo BalancaTeste.

258 Essa parte que ele colocou aqui s para ter a opo de trocar o exemplo pode ser genrico, para servi em qualquer um. Se no mesmo estabelecimento tem que ter a balana e a impressora fiscal, teremos que ter duas portas seriais, uma para a balana e a outra para a impressora. Selecionando o componente, em propriedades, temos que selecionar a porta, o nome de programao que estamos trabalhando que no caso o prprio nome, no modifica nada. O intervalo mostrado o tempo (o nmero 200 d aproximadamente 2 segundos) para que a balana l a cada 2 segundos. Se a balana no responder dentro de 2 segundos, mostrada uma mensagem de erro no campo Mensagem.

Figura 142 Propriedades do componente ACBrBAL o Device Por ltimo o modelo da balana que vai trabalhar. Se Filizola ou Toledo. No caso foi deixado como nenhum para ser genrico.

16.2.2 - A configurao do DEVICE


Se quiser configurar a velocidade de resposta da balana na porta serial essa configurao feita em Device que por padro tem um valor j configurado (9600 (Baud), 8 bits (Data), sem paridade none (Parity), bits de parara = 1 (Stop)). Ento j vem previamente configurado o valor da porta serial porque na porta serial da nossa mquina no est prconfigurada para 9600. OBS: Se for usado o emulador essa configurao ter que ser mudada para 4800 em Baud.

16.2.2.1 - Baud Rate


Como funciona uma porta serial. Temos uma mquina 1 e maquina 2, com um cabo ligado entre as duas, uma teste e a outra um outro tipo. Esta sendo enviada dados de um lado para outro, enviado por 1 e

259 recebido por 2. Para enviar a letra A para o outro lado, que representada pelo nmero binrio 1000001 da tabela ASCII. enviado o primeiro digito 1, depois que chegar do outro lado, envia o prximo dgito, fazendo isso um por um. Quando chegar todos os nmeros no destino, eles sero reunidos novamente. S que para funcionar, as duas mquinas tem que rodar na mesma velocidade. No podemos mandar um bit a 200 por hora e receber a 100 Se forem enviadas 10 letras por minuto o outro lado tem que receber tambm as 10 letras por minuto. No adianta descarregar um caminho de laranjas e no ter um recipiente para receber as laranjas. Se tivermos uma esteira de transporte de laranjas e estamos trabalhando com uma velocidade de 9600 laranjas por segundo, um caminho cheio de laranjas descarrega 9600 laranjas num nico segundo e se tiver um recipiente que receba essas 9600 laranjas, ento no perder nada na descarga. Agora imagine se no tivermos a mesma situao, na hora que for descarregar o caminho, cai 9600 laranjas em cima da cabea de algum. Se o caminho tem a capacidade de descarregar 9600 laranjas e voc pode pegar somente meia dzia por vez, ento sai de baixo porque as laranjas vo te atropelar literalmente. Para evitar perdas de valores, as duas portas tem que estar na mesma velocidade. No caso dessa balana, ela s funciona a 9600, s consegue receber a 9600Kbps. Dividindo por 8 verificamos que ela consegue receber 1200 letras por segundo, um pouco mais que 1K. A cada segundo transferido um 1kb de dados. Cada vez que enviar uma letra, ser enviado sete caracteres por vez. Mas porque? No sempre oito? No. Alguns sistemas trabalham com sete caracteres. Sete bits igual a uma letra, s que uma palavra da tabela ASC e no de ASCII. Oito bits da tabela ASCII que so 255 possveis caracteres. Para caracteres s de letras podemos usar a tabela ASC. A balana trabalha com caracteres especiais e se ns trabalharmos com 7 bits no ser feita a comunicao. O normal 8 bits.

Porque temos que saber isso? Os PCs de hoje em dia, j vem configurado com 56000, tem outros configurados com 128000 e a porta serial das mquinas dificilmente esto em 9600. Se deixar com essa configurao a balana literalmente atropelada, porque ser mandado tantos dados que ela no consegue ler nem do que foi enviado. necessrio baixar a velocidade para a balana conseguir fazer a comunicao. Os dois pontos tem que estar conectados na mesma velocidade e essa configurao feita no Device onde fixada a velocidade da porta, no importando a velocidade configurada, vai trabalhar a 9600 Kbps. 16.2.2.2 - Parity (paridade) Cada vez que um dado enviado, enviado tambm um bit a mais para informar se a soma dos caracteres par ou impar, porque se um dado se perder no meio do caminho ser possvel descobrir o valor Se a soma dos dados der um nmero

260 par, por exemplo: 1 + 1 + ? = 2, o terceiro nmero s pode ser zero porque a soma j dois. No tem fluxo de paridade porque a balana no controla isso. Isso feito se caso houver falha no envio de algum dado, ser possvel saber qual o numero que faltou. 16.2.2.3 - Stop Bits (Bits de parada) bit para identificar que terminou. O comando ativar far a leitura da configurao que tiver sido feita, estando genrico possvel altera se quiser de acordo com a balana escolhida. Ou fixado no componente o valor configurado ou colocamos nos campos criados e na hora que ativar preenchemos os campos depois. Neste caso no ativar, como o negcio genrico, quando fazia o ativar na balana, ele copiava s os dados, o que escolhido, gravado dentro do modelo, gravava dentro da paridade, basicamente preenchendo o valor das propriedades. Depois que estiver pronto pressionamos o boto ativar. O comando ativar manda o caractere #5 para a balana. Quando mandamos o comando para a balana ela comea a fazer a leitura serial com o micro, isso para verificar se existe ou no a balana. Porque pode ser que ela esteja quebrada, desligada ou sem energia, portanto no momento que mandamos o comando para verificar sua funcionalidade, a balana retorna true ou false como resposta. Essa configurao do lado no seria necessrio porque podemos deixar fixo no componente, ento basta dar o comando ativar e depois fazer a leitura. A leitura (lerPeso) e passamos o tempo de espera de resposta. Aqui ele pega o valor do tempo em txt da propriedade teste. Essa propriedade teste o valor que podemos inserir, mas podemos deixar fixo no sistema colocando por exemplo 2000. Poderamos ter feito esse comando em propriedades que funcionria igual. s colocar 2000. Esse 200 so 2000 milisegundos que corresponde a 2 segundos, que o tempo de resposta que a balana dar depois da leitura do peso. A funo lePeso trs um resultado do peso lido 00. Aps chama outra funo. Esse outro lePeso trs o ltimo lePeso lido e a resposta. Converte o valor do peso lido, chamando a rotina lePeso e passa o peso que ele trouxe, faz a formatao porque o peso tem um valor sem formatao nenhuma, um nmero que vai ter que ser dividido em pedaos. Ento faz a formatao aplicando uma mascara. Ai chama a rotina que l o ltimo peso lido que retorna um nmero. - Se for 0 escreve 'Coloque o produto sobre a Balana!' porque leu zero no tem nada. Todo peso que lido teoricamente positivo. Se a balana manda um nmero negativo, algum problema ocorreu. - Se for -1 quer dizer que o peso est instvel, no consegue ler nenhum nmero. -2 =peso negativo foi calibrada a balana para 50 gramas. Por exemplo: num restaurante calibrada a balana para ler 50 gramas ( o peso do prato) e na hora que for colocado um prato cheio lido s o contedo, s que se esquecer de por o

261 prato antes de fazer a leitura, dar peso negativo, porque mandou ler, mas esqueceu de por o prato na balana. Primeiro coloca o prato, depois faz a leitura. 10 Sobre peso Se for colocado um peso a mais do que a balana pode suportar, por exemplo mais de 15 Kg.

O Cdigo da explicao o mostrado abaixo: procedure TForm1.ACBrBAL1LePeso(Peso: Double; Resposta: String); var valid : integer; begin sttPeso.Caption := formatFloat('##0.000', Peso ); sttResposta.Caption := Converte( Resposta ) ; if Peso > 0 then Memo1.Lines.Text := 'Leitura OK !' else begin valid := Trunc(ACBrBAL1.UltimoPesoLido); case valid of 0 : Memo1.Lines.Text := 'TimeOut !'+sLineBreak+ 'Coloque o produto sobre a Balana!' ; -1 : Memo1.Lines.Text := 'Peso Instavel ! ' +sLineBreak+ 'Tente Nova Leitura' ; -2 : Memo1.Lines.Text := 'Peso Negativo !' ; -10 : Memo1.Lines.Text := 'Sobrepeso !' ; end; end ; end;

E uma balana para pesar caminho? O caminho carregado passa pela balana e voc manda fazer a leitura, por exemplo pesou 162 T e esse valor fica armazenado dentro do banco de dados. O caminho descarregado e volta para a balana para ler um novo peso. Agora possvel ver qual a diferena de peso, por exemplo 131 T, a diferena o produto que foi descarregado. Ento podemos controlar a carga de um caminho que chega ou que sai, podemos controlar produto vendido dentro de um supermercado. O processo de funcionamento entre uma balana e outra o mesmo, a diferena est na ordem dos valores, um peso pequeno ou um peso gigantesco.

16.3 - Mais um exemplo:


Abra uma nova aplicao. Coloque o componente ACBrBal no form. Em propriedades do componente especifique no Modelo a balana Toledo

262 Coloque um boto para fazer a leitura. Insira um Edit para ver a leitura na tela.

16.3.1 - A programao
programao do boto var aux :double; begin acbrbal1.ativar; aux:=acbrbal1.lepeso(2000); acbrbal1.desativar; edt_peso.text:= floattostr(aux); end;

Quando clicar no boto j feita a comunicao, faz a leitura e fecha. Crie uma varivel do tipo double. var aux :double; Mande ativar. acbrbal1.ativar; Logo depois faa a leitura do peso. aux:=acbrbal1.lepeso(2000); A rotina que faz a leitura ACBrBAL1.lePeso e por padro passamos o tempos que vai demorar para fazer a leitura, no caso vamos colocar dois segundos. Quando mandar um comando para a balana, espera at dois segundos para ela responder, para que no fique amarrada a resposta no infinito. Se for colocado uma espera de 3 horas, enquanto no receber resposta, fica travada.

Note que uma funo, e se uma funo retorna tipo float com nmero inteiro. Se for colocado 262, vai mostrar um nmero tipo 00262. Coloque dentro de uma varivel, por exemplo AUX:= valor E por ltimo desativa o componente ACBr. acbrbal1.desativar; Essas linhas para receber a leitura da balana ativando-a, armazenando o valor lido e desativar a balana. Coloque um componente para ver o valor a partir da tela.

263 Agora mostramos o valor da leitura: edt_peso.text:= floattostr(aux); Aumente o tamanho da fonte.

Figura 143 Formulrio teste Rode o programa e faa uma leitura. A leitura inicial zero. Pode ser colocada a leitura num formato melhor passando uma string com 3 casas depois da virgula.

FormatFloat -> o valor desejado com formato de 3 casas aps a vrgula depois o valor que queremos mostrar. O formatFloat pega o valor e vai colocar obrigatoriamente 3 casas aps a virgula. Porque FloattoStr porque mandamos converter float para str. 16.3.2 Melhorando o exemplo: Cada vez que for feita uma leitura o sistema baixa o estoque na tabela de produtos Criamos uma tabela de produtos para fazer baixar em estoque e cada vez que for pesado um produto d baixa no estoque. Crie uma tabela no Paradox Abra o Database Desktop no Paradox e crie a seguinte tabela:

264

Figura 144 Criao da tabela Produto no Paradox Salve a base de dados. Abra o banco de dados e digite os valores:

Figura 145 Preenchimento da tabela Produto no Paradox. Feche o banco.

265 Da paleta BDE coloque um componente Database De duplo clique no componente e preencha as propriedades: Propriedades: Name = Banco. Driver Name = STANDARD Clique em Defauts e prencha o PATH com o endereo do banco criado anteriormente. Desmarque Login prompt e clique em OK.

Figura 146 Preenchimento das propriedades do Database Connected = true. Coloque um componente Table da paleta BDE no form. Propriedades da table: DataBaseName = Banco. TableName = Produto.db Name = Tbl_Prod. Active = True

Para fazer a venda: da paleta DataControl coloque uma grid para mostrar os dados do produto. da paleta DataAcces coloque um componente DataSourse Propriedades do DataSourse: DataSet = Tbl_Prod

266

Propriedades da Grid: DataSourse = DataSourse1 Basicamente o usurio clica no produto que ele quer e depois em Ler Peso, que seria a leitura da balana. 16.3.3 - Fazendo a programao: Com o sistema ligado na tabela fazemos a programao procedure TForm1.Button1Click(Sender: TObject); var aux,valor :double; begin acbrbal1.ativar; aux:=acbrbal1.lepeso(2000); acbrbal1.desativar; valor:= tbl_prod.FieldByName('valor_prod').AsFloat; Edt_Peso.Text:= FloatToStr(aux); Edt_Total.Text:= FloatToStr(aux * valor); Tbl_Prod.Edit; Tbl_Prod.FieldByName('Qtd_Prod').AsFloat:= Tbl_Prod.FieldByName('Qtd_Prod').AsFloat - aux; Tbl_Prod.Post; end; end. Coloque mais um Edit para ver o valor total da conta. Propriedade: Name = Edt_Total. Vai multiplicar o valor lido pelo valor do produto cadastrado. Edt_Total.Text:= floattostr(aux * valor); Depois armazenar em uma varivel o valor do produto para fazer o calculo do valor total (valor * qtde) Cria a varivel valor do tipo double. var aux,valor :double;

Para calcular o valor do produto, ele retirado da tabela Produto. valor:= tbl_prod.FieldByName('valor_prod').AsFloat;

267

Agora temos dentro do Edt_Lido o valor que foi lido e o valor dado para pagamento Para calcular o total: Edt_Total.Text:= FloatToStr(aux * valor); Ento o sistema coloca na tela, multiplica o valor, mostra o total e por ltimo atualiza o bando de dados. Coloque a tabela em modo de Edio: Tbl_Prod.Edit; A quantidade vai receber a prpria quantidade menos o que foi lido. Tbl_Prod.FieldByName('Qtd_Prod').AsFloat:= Tbl_Prod.FieldByName('Qtd_Prod').AsFloat - aux;

Por ltimo, salve a tabela Tbl_Prod.Post; O que foi feito Feita a leitura na balana, mostra os dados e altera o que vai sobrar no banco (atualiza o BD)

Figura 147 - Aspecto do formulrio depois de pronto Execute o sistema.

268

Figura 148 - Aspecto do formulrio depois de executado.

Para o produto limo, tinha uma quantidade de 100Kg, se for rodado para fazer a leitura, continua tendo 100 Kg. Se for 0 escreve 'Coloque o produto sobre a Balana!' porque leu zero no tem nada.

Porque mostra a mensagem 'Coloque o produto sobre a Balana!' Foi no banco de dados, procurou o valor e trouxe zero que a propriedade da balana, ento mostra a mensagem (Se o retorno for zero then... Coloque o produto sobre a balana) Se der uma mensagem diferente temos uma tabela de erros: por exemplo: 0 : 'Coloque o produto sobre a Balana!' ; -1 : 'Peso Instavel ! ' + 'Tente Nova Leitura' ; -2 : 'Peso Negativo !' ; -10 :'Sobrepeso !' ;

Na escolha do produto limo a quantidade era 100 e quando clicar para fazer a leitura, faz a leitura do peso e multiplica esse valor pelo preo que foi colocado no produto e j faz a baixa no estoque. Cada vez que for feita uma venda, temos a baixa no estoque. Basicamente a programao se resume em poucas linhas. O padro de comunicao da Toledo, deste a mais simples at a maior balana que faz l peso de caminho o mesmo. A nica diferena a variao do peso em gramas. Enquanto a domstica l peso em grama a outra pode ter uma variao de tolerncia em quilos a mais ou a menos, porque j imaginou um caminho carregado de gado se mexendo, no d para

269 o peso se estabilizar, tem que ter um limite de tolerncia a mais ou a menor para poder fazer a leitura. O emulador para balana Toledo A pessoa digita o valor que quer e manda enviar para a porta. A idia para isso funcionar ter uma mquina com esse programa e a outra com outro sistema, uma mquina para simular a balana e a outra para fazer a leitura. So necessrias duas mquinas, uma para instalar o programa da balana e a outra para o sistema fazer a leitura, no esquecendo de configurar a porta de entrada.

270

17 INSTALL SHIELD
Um software que pode fazer a instalao do sistema desenvolvido e que vem junto com o CD de instalao do Delph. O InstallShield, da empresa InstallShield Software Corporation. uma verso mais simples (Express Borland Limited Edition) do que a verso full, mas com ela conseguimos criar instalaes bastante completas e profissionais para nossos sistemas desenvolvidos em Delphi. Tudo foi testado antes, foi feita simulao, foi criada rede, foi feita a brincadeira completa. O software j foi instalado e testado em uma mquina virtual e j se sabe quais os arquivos necessrios para fazer funcionar esse software Tudo bem, temos tudo isso, agora preciso vender para o usurio, preciso levar o software para instalao. necessrio gerar agora o arquivo de instalao. Para cada projeto criado, um software precisa ser instalado e se for modificado um arquivo s abrir o arquivo de projeto e mandar recompilar, como se fosse o arquivo do Delphi. O que ele faz? Recompila de novo os arquivos modificados e gera um novo software. Compacta tudo. Ento cada vez que for feito um software, tem que ser criado um executvel para instalao que pode ser atravs de um Wizard ou de um formulrio em branco, tanto faz. Tem que ser selecionada a localizao que vai ser salvo o sistema a ser instalado. Temos que selecionar qual tipo de projeto que vamos fazer. Pode ser atravs de Project Wizard ou Blank Setup Project tanto faz selecionar um ou outro. A diferena que um em caixas de dilogos e o outro s preencher os dados do lado, clicando pasta por pasta. Fazendo pelo Wizard nota-se que o outro jeito aparece do lado e vai ser a mesma coisa. 17.1 - Criando a Instalao {Supondo que voc fez um sistema, que est no diretrio C:\Arquivos de Programas\Borland\Delphi7\Demos\Db\CtrlGrid. Com o InstallShield aberto: Na primeira tela, escolha a opo Create a new project

271

Figura 149 - Tela de Menu do InstallShield Aps clicar em Create a new project ser aberta a tela abaixo:
Na segunda tela (create a new project), na caixa Project Type clique no cone Project Wizard e depois em Create

Figura 150 - Criando um novo projeto.

272

A prxima tela de boas vindas clique em Avanar

Figura 151 - Tela de boas vindas Ser aberto um Wizard para auxiliar nos passos iniciais de criao da instalao Vai criar um novo projeto? Qual vai ser o nome do projeto?

273

Figura 152 Criando um Novo Projeto Selecione a opo Create a New Project No campo escreva o nome que quer dar em seu Projeto (Ex. Grid Demos do Delphi) O idioma no caso s tem dois escolha o ingls. A vero Full mais completa. Clique em avanar.

274

Figura 153 - Informaes da aplicao. Qual o nome da aplicao? Nos campos: Application Name: Digite o nome da aplicao. Ex. Grid Demos Delphi. Application Version: Digite o nmero da Verso da aplicao no caso verso 1.0. Default Destination Folder: [ArquivoProgramaFolder]Nome da sua Empresa\Nome do seu produto Se tiver uma correo na verso, a nova verso ser 1.0.1 e na segunda correo ser 1.0.2. Para cada vez que for mudada a verso por motivos de correes, a numerao alterada. Temos ento a Verso, a Sub-verso e a compilao. Podemos compilar 9.999 vezes antes de mudar de sub-verso.

Clique em avanar.

275

Figura 154 Atualizaes do Software. Ativar para receber atualizao via InstallShield UpDataService Isso no resolve nada. s atualizao do instalador. Podendo deixar ativo ou no, porque no faz diferena. Clique em Avanar.

276

Figura 155 - Informaes do Software Nome da companhia: <NomeCompanhia>. Coloque um numero de telefone para que o usurio final possa entrar em contato com o suporte tcnico. Telefone: <CodigoPais> + <CodigoRegio> + <Telefone> Se tiver um Site pode ser colocado o Site da empresa, exemplo: www.unilins.edu.br. basicamente a mesma coisa para a maioria dos casos.

277

Figura 156 Apresentao da Aplicao. Campo Alwayas Install O que isso? Quando for instalar pode ser dividido em pacotes, por exemplo: Num grupo de arquivos que devem ser instalados, um sistema de vendas que foi dividido em vrios mdulos (Tipo de venda, Tipo de compra, Faturamento, Relatrios) o usurio no obrigado instalar na mesma mquina. Se ele faz vendas, instala s o mdulo de vendas. Ento podemos ter vrios tipos de instalao, vrios pacotes diferentes, mas alguns deles sempre ter que ser instalado para o perfeito funcionamento (uma DLL por exemplo). Todos os pacotes usam essa DLL. O pacote que tiver no Alwayas Install sempre ser instalado. Os arquivos que forem colocados neste campo, independente da verso, vai ser instalado. O diretrio escolhido para instalao tambm instala os arquivos colocados neste campo. So os arquivos bsicos uma DLL, um arquivo .INI, Imagens, esses tipos de coisas. Poderia criar um pacote de vendas, compras, etc? Sim, poderia. Quando fazemos a instalao do Office, aparece os campos para instalao de outros arquivos e voc vai clicando (marcando) os arquivos que quer instalar. Os outros arquivos, independentes da instalao dos arquivos escolhidos iro ser copiados porque so essenciais para o funcionamento. Na documentao pode ser escolhido o que vai ser copiado l dentro. Alwayas Install o que vai ser instalado. Sempre vai ter que copiar a DLL procura a DLL independente da verso de escolha assim como o banco de dados.

278

Na tela seguinte, Application Features, podemos definir itens que podero ser selecionados para instalao pelo usurio. No nosso caso, isso no necessrio e, portanto vamos oferecer somente o item Always Install. Na tela Application Files adicionamos todos os arquivos que devero ser instalados na mquina do usurio para o sistema funcionar. Veja um exemplo na Tabela abaixo. Descrio Programa Executvel Ajuda do Sistema Arquivos de Dados Extenso

*.exe *.hlp *.db, *.mdb, *.dbf, *.xml, *. *.ib; *.fbd, *.gdb Tabela. Arquivos que devem ser adicionados na instalao. Para adicionar clique em Add Files e selecione os arquivos necessrios para o funcionamento do sistema, no esquecendo de DLLs ou outros (como arquivo de help, arquivos INI etc.) se esse for o seu caso. Clique em Add Files para adicionar os arquivos a serem instalados.

Figura 157 Arquivos para instalao. Depois se for escolhida a documentao na documentao padro. Em qualquer documentao vai instalar algum arquivo. Para quando for documentao padro queremos que mande um determinado arquivo. Se for colocado em avanada, vamos adicionar o mesmo arquivo. O sistema por padro, vai instalar, por exemplo, vendas junto com os arquivos que vo fazer parte dessa instalao lembrando que tudo que tiver no campo Alwayas Install vai ser instalado.

Cada opo escolhida o arquivo que vai ser gravado (instalado).

279

Figura 158 Arquivos Instalados. Clique em Avanar Na tela Create Shorcuts configura-se os atalhos dos arquivos da instalao. Clique com o boto direito do mouse em cima de Programs Menu e escolha New Folder. Digite o nome do sistema para a pasta e aperte Enter.

280

Figura 159 Criao de Shortcuts. ShortCut em que local vai ser instalado? Voc pode escolher que o ShortCut para Grid Demos do Delphi no prompt vai criar um menu chamado Grid Delphi o atalho. S que necessrio saber qual o arquivo que vai ser executado. Agora para cada uma das instalaes avanadas, personalizada, etc, pode ter um arquivo de registro anexado para cada um deles porque no Windows quando instalamos alguma coisa, existe um arquivo que controla toda a verso que foi feito quando foi instalado, o dia da instalao e a configurao um arquivo de registro (Reg File). Podemos adicionar informaes neste registro basta ser colocado um arquivo neste campo. Uma espcie de TXT que ele executa. Podemos criar um arquivo, apontar o arquivo e dependendo da instalao que for feita, ele executa. Esse arquivo serve para registrar o software, para deixar o Pet bem visualizado, para criar um cone, etc.. Temos duas telas: uma que tem os campos Tpico, Custon, Padro, etc. Depois de escolhido o tipo de instalao pode ser instalado os aplicativos desejados. Ento este jogo de aplicativos que queremos a tela mostrada abaixo: Pode ser especificado o diretrio para a instalao do pacote, o diretrio de banco de dados. Dentro da documentao pode ser colocado vrios subtipos: Documentao Padro, Documentao Avanada. Pode ser criada vrias partes ali dentro em subtipos. Crie algumas pastas para subtipos e clique em avanar.

281

Agora para cada tipo de instalao vai dizer que avanada. No final da instalao de um software, aparece a mensagem Registrando seu Software a hora que executa o arquivo de registro, nada mais que um arquivo TXT cheio de comandos, igual a um arquivo .INI. Para cada tipo de instalao, podemos ter um arquivo de registro, conforme for escolhido, vai registrando o que for necessrio.

Figura 160 - Registro do sistema. Clique em Avanar.

282

Figura 161 Dilogos. Clique em Avanar

Figura 162 Sumrios.

283 Clique em Concluir

17.2 - Organizao do Setup.


Aqui temos toda a organizao: informao geral sobre o software (qual a verso do produto, a letra, o tipo). possvel modificar esses dados. O nome da empresa. O tipo de instalao para cada arquivo. O local. A descrio Quando for clicada na documentao, vai aparecer os documentos explicativos do sistema gerado. Pode ser personalizada cada uma das instalaes.

Figura 163 Organizao do Setup. General Information Se for criado algum pacote que o usurio no pode mexer e obrigatria a sua instalao, ela colocada no campo General Information com o campo YES preenchido.

284

Setup Types Typical - Se no tipo vai ter s o sistema escolha s o sistema. Minimal - Quando for mnimo, no vai ter nada nem o sistema. Custom - Quando clicar em Custon, um tipo de bloco que vamos ter disponvel. Temos um padro de compilao para copiar DLL e pode ser instalada ou no uma imagem. Pode ser criado um arquivo de documentao, mas no obrigatrio, o usurio pode escolher. Recomendado para usurios experientes. Para cada uma das instalaes podemos indicar o que vai ser instalado, que grupo de coisas vai ser instalado. Poderia criar alguns outros. Esses procedimentos esto sendo feito com Wizard. O ideal fazer com a verso full que tem mais opes. Upgrad Paths - neste caso no tem porque no est neste verso, s na verso full. Specify Application Data (Especificaes dos arquivos) File Uma cpia de cada arquivo, a pasta que vai ser colocada. Dentro do Progress Files, no nome da empresa ser criada uma pasta com o nome do produto que ser adicionada, podendo-se mudar cada um desses nomes alterando o nome das pastas. O Path pode ser especificado para cada um dos arquivos. Para cada tipo de instalao, onde ser posto o arquivo. Ento se fosse uma DLL dentro do Windows essa a Destination. Poderia mostrar qual das pastas, se est dentro do Windows no Systen 32. Exemplo: Dentro da pasta Systen ser colocada uma DLL, ento arrasta para a pasta. Quando for feita a instalao copiada para a pasta System 32 tudo o que for direcionada para ela. Pode ser feita a listagem das pastas que queremos que copie. Podemos adicionar as pastas conforme for a necessidade. Todas as pastas do Windows, arquivos comuns, Pasta Pessoal, Meus Documentos, podemos usar a que j existe ou criar outra. Se for preciso criar uma pasta dentro da pasta Progress File ento adicionamos ali dentro. A estrutura que for criada a estrutura que quando o usurio escolher em avanada a que vai ser mostrada. O sistema deixa escolher o local de instalao mas se no for escolhida, o prprio sistema j esta configurado para instalao automtica. Pr-definido o diretrio de instalao, as outras pastas que forem adicionadas dentro desse diretrio tero que ter permisso. Em cada uma das instalaes podemos escolher os arquivos, colocando as pastas escolhidas. Se uma DLL que precisa estar dentro da pasta System 32, selecionada esta pasta e copiamos a DLL dentro dela. Ser mostrada uma listagem para confirmar se est tudo certo, se no est faltando nada. Foram escolhidos os arquivos para instalao que aparecem na listagem para confirmao e checar como vai ficar a instalao. a instalao que vai ser personalizada e vai ser escolhidos os arquivos na instalao avanada. Redistributables (Redistribuio) O que precisa mandar junto no seu sistema. Por exemplo: preciso mandar o DCOM e o ADO juntos para efetuar conexo com o Banco de

285 Dados. Isso tudo vai para a instalao padro e pode ser escolhido o que necessrio. Se tiver algum servio do windows instalado na mquina e quer aproveitar e mandar junto, pode ser feito tambm, assim como mandar um banco de dados, um script, etc. Dependencies (Dependncia) S na verso Full que pode ser colocado OCX, DXB, System, algumas DLLs. Do jeito que est, a no ser que seja colocada dentro de um comando While, para que o usurio no veja o que est instalado e acabe excluindo indevidamente o arquivo. Shortcuts/Folders A pasta que podemos criar o short cut. Pode escrever o nome da pasta e dentro dessa pasta podemos adicionar os Short Cuts. New Short Cut Os atalhos instalados podem ser especificados de como iro ficar, como vai ser, o nome do atalho. Quando for instalado, no programa vai aparecer o cone de atalho, so os links do software. Registry (Arquivos de registro) Em que local sero registrados. Qual a chave que vai ser colocada. No caso no tem nenhum gerador de chave nesta verso, somente na verso full. ODBC Resources (Driver ODBC) Qual driver ODBC a ser enviado. SE for acessado via Driver Oracle, ento necessrio mandar junto o driver do Oracle. Selecione o Driver e o driver do oracle copiado para instalao. Pode ser criada uma pasta com os drivers e o usurio pode escolher o driver que quer instalar. Pode ser criada uma pasta chamada Driver, colocada no Setup e o usurio escolhe. S vai instalar o driver se o usurio escolher o sistema e se o sistema precisar do driver. Colocamos na pasta Sistema. S quando o usurio instalar o sistema, ele vai e copia o Driver do oracle, caso contrrio no instala o driver. INI File Changes (Arquivo Ini) Se tem um arquivo ini, j mostra o formato de arquivo .ini. Pode ser adicionado um arquivo do formato ini file, especificando o diretrio de destino. File Extensions (Associao de extenso) Vamos supor que o programa abra um arquivo. Se for um AutoCad , abre tudo quanto imagem .bmp. As extenses podem ser registradas. Cada vez que pressionado um cone com extenso .bmp, o sistema abre o programa e roda. Pode ser escolhido o cone do seu sistema. No nosso caso no usaremos isso. No invente de associar bmp no sistema comercial, porque quando for clicado um cone com extenso bmp, o sistema abre a extenso bmp em outro software e da vira uma baguna de software abertos. Environment Variables (Variveis de Ambiente) Disponvel somente na verso Full. Pode ser criado Paths, nmero de arquivos mximos que podem ser abertos com o sistema. Ex: eram 100 e agora necessrio que mude para 200 arquivos. O Path do windows em vez de procurar em C:/ primeiro procura no sistema instalado e depois procura no windows. S para ter uma idia, essas variveis se encontram no Windows na pasta Variveis de

286 Ambiente. O Path quando for salvar, em que pasta ser salva? Quando for salvar algum arquivo, primeiro procura em um caminho e depois num outro alternativo. Importante: Na verso original tome cuidado ao usar essa modalidade. Se tiver o Path do Windows e colocar s o seu sistema dentro desse path, ao iniciar no vai ser achado o seu sistema e o windows j era. Pagina Web Disponvel na verso full. Se tiver uma pgina Web, pode ser instalada no servidor. Customize Setup Disponvel na verso full Opo para colocar caixas de dilogos ao abrir o sistema. Quando aparecer uma caixa de dilogo informando para o usurio se concorda ou no com os termos, selecionamos o runtime e aponta para um arquivo txt. Pode ser colocado um texto ou documento do software, falando sobre as consideraes de seu sistema e a concordncia ou no dos termos. Na hora que fizer o dilogo vai aparecer uma tela, onde pode ser colocada uma imagem, pode ser adicionado um documento de licena, dizendo o que pode ser feito e o que proibido fazer com o software, as suas especificaes, a pasta de destino se pode ser escolhida ou no. Que tipo de setup, se vai ser tpico, personalizado, etc. Os BillBoards So as instalaes que aparecem mensagens de propaganda Disponvel somente na verso full. Automatic Updates somente na verso full. Aes S o que ser feito. Na rotina de instalao vai ser checada a verso do S.O. que pode ser alguma verso que no vai rodar o instalador. Ento escolha a verso certa, ma se for colocada sem verso nenhuma, em qualquer verso do windows vai funcionar. Buid Your Release - Foi selecionado tudo, agora s fazer o Build. Deve ser informado qual o tipo de mdia que vai gerar no sistema. O tamanho especificado da mdia para saber em quantas mdias sero divididas. Se for colocado 1.44, ser dividido em vrios disquetes. Se for colocado 100M, o sistema far arquivos de 100 em 100 megas. Se for colocado tamanho de Cd, o sistema gera cpia em tamanho da capacidade de um Cd. criado um diretrio para ser copiado dentro de um CD ou outro tamanho escolhido. Se for escolhido CDRom e o programa tem 2 Gigas, ento ser dividido em vrios diretrios com 600 Megas cada um. O primeiro tem 600 M, lotou, cria disco 2 e copia o restante, cria o disco 3 at alcanar o tamanho do diretrio total. Gerar arquivo autorum? sim gerar o instalador automtico Distribuir Bild off Setup. Dentro do arquivo de programas na pasta MySetup criou o sistema de vendas. Dentro desta pasta tem o CD.

287 Agora copia tudo dentro de um CD. Copia todos os arquivos para dentro desta pasta e para testar clicar em Setup. Quando clicar aparecer o sistema de vendas, a licena, nome da organizao, tipo de instalao, as opes Disponveis. Em install vai ser gerado.

um tutorial passo a passo, para instalar em windows e tambm em Linux. Este software instala qualquer programa. Toda instalao que gerar, sempre vai gerar dentro da pasta meus documentos. Ele cria a pasta MySetup e para cada projeto, vai ser gerado um disco ou mais. Esta verso no permite fazer o autorum, s na verso full. Compress Para compactar o programa. A instalao fica um pouco mais lenta s que cabe mais arquivos por CD. Para poder colocar DLL criado um diretrio System 32 e copiadas as DLLs. Para saber quais as DLLs que precisam ser copiadas preciso instalar o programa VMWer e tentar rodar o aplicativo, se der erro a DLL necessria tem que ser copiada para depois efetuar a instalao. Neste artigo vimos como criar instalaes para suas aplicaes Delphi usando o Installshield, que acompanha o produto. Como vimos, em alguns minutos, podemos criar instalaes bastante profissionais e completas com essa excelente ferramenta.

C2 Se for inserido uma senha para iniciar o C2 qualquer pessoa pode ter acesso, pode iniciar o C2 sem qualquer dificuldade. Numa fiscalizao o dono da empresa indiciado juntamente com quem fez o software. Porque o desenvolvedor promoveu o meio necessrio para efetuar a fraude. Numa empresa todas as CPUs teoricamente esto interligadas, ento colocada qualquer CPU em lugar no acessvel e plugar um PenDrive. Quando o usurio for efetuar uma venda e no tiver impressora fiscal ligada, o sistema verifica antes se o PenDrive est conectado. Se tiver um PenDrive o sistema grava a venda nele e cancela a venda do item na impressora fiscal e no banco de dados. Se houver algum problema o PenDrive pode ser desconectado e o sistema funciona normalmente. Se a impressora fiscal estiver desligada, antes de cancelar a venda o sistema verifica se existe ou no a coneco com o PenDrive. No tendo o PenDrive o sistema da uma mensagem de erro e cancela a venda.

288 No cdigo fonte feito um tratamento para que o PenDrive seja detectado se a impressora fiscal estiver desligada. A programao: 1- Na tela principal do sistema temos que colocar um componente de DataBase a mais que igual ao do banco de dados do sistema um para o banco do sistema e outro para o PenDrive. Por padro o Connection do componente ser false. 2- Colocar tambm mais dois componentes DataBase ligados na tabela de Pedido 2 e o outro ligado na tabela de Itens 2, ambos ligados ao componente DataBase que faz a coneco. 3- A programao feita com o comando result = 0. Ento iniciando um Try...Result. O comando try uma mensagem de erro para que no se saiba que existe um outro banco de dados. Neste comando fazemos por exemplo: Banco2.Connection:= true. Tentamos fazer a transmisso. Se der certo a transmisso, pegamos a tabela de pedido2.Open abrimos a tabela e gravamos os dados dentro dela e no final colocamos o comando Post. Salvamos todos os dados e no final de tudo no pedido de verdade colocamos o ponto cancel (.Cancel), para que o pedido de verdade no seja gravado, mas s o PenDrive. try banco2.conection:=true; pedido2.open; pedido2.post; pedido.cancel; Por isso a chave do pedido no pode ser o numero de serie da nota e o numero do cupom fiscal, porque com a impressora fiscal desligada, tem temos o nmero de serie da nota e nem o nmero do cupom.

You might also like