P. 1
Apostila III - Delphi

Apostila III - Delphi

|Views: 2.177|Likes:
Publicado porJoão Batista Fiala

More info:

Published by: João Batista Fiala on Aug 19, 2011
Direitos Autorais:Attribution Non-commercial

Availability:

Read on Scribd mobile: iPhone, iPad and Android.
download as PDF, TXT or read online from Scribd
See more
See less

07/31/2013

pdf

text

original

1

DELPHI APOSTILA III

AUTOMAÇÃO COMERCIAL
AUTORES RENATO BARROS FRANCISCO FERREIRA DA SILVA 2006

2

ÌNDICE
1 2 3 4 4.1 4.2 CONTEÚDO CLASSES TIPOS DE MÉTODOS E CAMPOS COMPONENTES Override A criação 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 criação 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 Programação do componente EdtCpf TEMPLATE 5.1 Um template simples 5.2 Abrindo um novo projeto através do template CÓDIGO DE BARRAS 6.1 Surgimento do código de barras 6.2 Código de barras do tipo UPC 6.3 Os tipos de códigos EAN 6.4 O padrão EAN 6.5 Definição do código 6.6 O funcionamento do código de barras 6.7 A representação dos campos do código EAN 6.8 Duração do código de barras 6.9 Código de barras do tipo EAN-8 6.10 Código ISBN 6.11 Código ESSN 6.12 Código EAN-14 6.13 Código de uso interno 6.14 Localização do código de barras 6.15 Calculo do dígito verificador do EAN-13 6.16 Criação do componente para fazer leitura do código de barras 6.16.1 - Programando as propriedades 6.16.2 - Programação do Procedimento KeyPress 6.16.3 - O tratamento do código EAN-13 para uso interno. 6.17 - Programação da Unit CodigoDeBarras 6.18 - Exercício: 6.19 - Utilizando o código de barras 6.20 - Exemplo de programação de procedimento usando o componente de código de barras

5

6

3 7 – DESINSTALAÇÃO DE COMPONENTES 8 – CRIAÇÃO AUTOMÁTICA DE FORMULÁRIOS. 8.1 - O comando Destroy 9 - DLL 9.1 - Problemas com a DLL 9.2 - Como construir uma DLL 9.3 - Programação das rotinas 9.4 - Gerando a DLL 9.5 - Programação 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 - Programação do botão Divide 9.7 - Como criar formulários dentro da DLL. 9.8 - Programação da Unit U_teste: 9.9 - Criando uma DLL para chamar este formulário. 9.9.1 - Programação das rotinas. 9.10 - Programação da DLL 9.11 - Criando outro Projeto para Teste 9.12 - Programação da Unit Chama tela 9.13 - Exercício: 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 - Relatórios emitidos pela Impressora Fiscal 11.3 - Os Arquivos de Configuração. 11.4 - O emulador. 11.5 - Exemplos de integração 11.6 - Configurando a Impressora 11.7 - A memória de trabalho do emulador. 11.8 - As rotinas 11.9 - PCHAR 11.10 - Possíveis retornos da Função (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 – Lógica 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 – ( ) - Negócio Inteligente 12.2 - A implementação da ferramenta 12.2.1 - Descrição: 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 aplicação 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 – Exercício Trabalho: 13 - CORREIO ELETRÔNICO 13.1 - Email no Delphi 13.2 - Diferença ente servidor ftp e pop3 13.3 - Criando o Formulário 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 programação. 13.4.1 - Botão Anexar 13.4.2 - Botão Enviar 13.5 - Programação completa do aplicativo 14 – CONEXÃO ADO 14.1 - O que é ODBC? 14.2 - A paleta ADO 14.2 .1 - Componentes da Paleta ADO 14.3 - Como criar uma conexão. 14.3 1 - A Porta

5 14.4 - Criação de conexão via ODBC. 14.5 - Caixa de diálogo Instalação 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 – PROGRAMAÇÃO EM TRÊS CAMADAS 15.1 - Introdução 15.2 – As três camadas 15.2.1 - O cliente, o servidor de aplicação e o banco de dados. 15.2.2 - Atualização. 15.2.3 - Desvantagem. 15.2.4 - Performance 15.3 - Antes, um histórico 15.4 - Como o DCOM distribui as tarefas. 15.5 - Criando uma nova Aplicação. 15.5.1 - Projeto Cliente 15.5.2 - Tabela Temporária 15.5.3 - Outro exemplo: 15.6 - Propriedades de Expression (TAggregateField) 15.6.1 - Descrição 15.7 - Colocando um campo Total Parcial. 15.8 - Uma regra de negócio num programa 15.8.1 - Fazendo a configuração 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 programação 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 Três 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 conexão via DCOM 15.9.6 - A propriedade PacketRecords 15.9.7 - Fazendo mais uma exportação. 15.9.8 - Tratamentos 15.9.8.1 - Auto Numeração de Código (ID) 15.9.9 - Programando o evento BeforeUpdataRecord.

9.3 .2 .Fazendo a programação: 17 – INSTALL SHIELD 17.2 .9.2.Instalando o Componente 16.A programação 16.1 .3.3 .1 .2.2 .2 – Melhorando o exemplo: 16.3.6 15.Parity (paridade) 16.2.Stop Bits (Bits de parada) 16.3.1 . .Baud Rate 16.2.1 .Refresh da tela (Atualização) 15.Organização do Setup.2.1 .2.Criando a Instalação.1 . 17.A programação do componente.Descrição da pasta leia-me 16.Um Exemplo 16.2 .1.10 .3 .11 .1.2.2 .Instalação 16.Mais um exemplo: 16. 16.A configuração do DEVICE 16.Programação dos projetos Servidor e Cliente 16 – BALANÇA COMERCIAL 16.2.

Figura 16 – Formulário utilizando o componente criado. Figura 37 – Tela de Cadastro de Clientes. Figura 3 – Preenchimento da caixa de dialogo para instalação de componentes. Figura 30 – Caixa de Instalação de componentes. . Figura 42 – Programação inicial de uma DLL Figura 43 – Compilação da DLL. Figura 23 – Programação do formulário aberto através de um Template. Figura 9 – Registro do componente. Figura 21 – Formulário de Novos Itens Figura 22 – Formulário aberto através de um Template. Figura 39 – Tela de Units de um projeto. Figura 12 – Demonstração da utilização do componente instalado. Figura 4 – Preenchimento das propriedades do novo componente Figura 5 – Modulo de programação do componente. Figura 24 – Exemplo de código EAN-13 Figura 25 – Exemplo de código de barras EAN-13 Figura 26 – Exemplo de código de barras EAN-8 Figura 27 – Caixa de diálogos para criação de novo componente. Figura 34 – Opções de Projetos. Figura 31 – Pacotes de componentes. Figura 7 . Figura 36 – Tela de um projeto.7 FIGURAS Figura 1 – Paletas de Componentes Figura 2 – Caixa de diálogos para instalação de componentes. Figura 35 – Relação de componentes de uma paleta. Figura 32 – Remoção de componentes. Figura 18 – Visualização do formulário Template Figura 19 – Caixa de diálogo para adicionar Template em um repositório. Figura 17 – Formulário compilado e em execução. Figura 13 – Criação do componente TEdtCPF Figura 14 – Reinstalando o componente. Figura 15 – Compilando o componente. Figura 28 – Código de programação do componente CodigoDeBarras. Figura 29 – Procedimento para seleção do evento KeyPress. Figura 40 – Tela de projeto de um sistema. Figura 20 – Confirmação para salvar o Template. Figura 8 – Confirmação da instalação. Figura 11 – Formulário utilizando o novo componente. Figura 38 – Opções de projeto para o sistema. Figura 33 – Caixa de confirmação de remoção de componentes. Figura 41 – Caixa de projetos – Novos itens. Figura 10 – Pacotes de componentes. Figura 6 – Campo protected – criação de procedimentos.Caixa de dialogo para instalação de componentes.

Figura 89 – Formulário para teste de conexão ADO.02 mostrando dados da impressora fiscal.DB no paradox. Figura 70 – Amostra de idade e opcionais. . Figura 90 – Formulário do componente ADOConnection. Figura 65 – Comandos SQL para a tabela do Decision Cube. Figura 82 – Formulário com componente ADO. Figura 64 – Decision Query Editor. Figura 61 – Tabela Vendas. Figura 68 – Amostra de Opcionais vendidos. Figura 80 – Tela para criar nova fonte de dados.Projeto Chama tela compilado.com. Figura 66 – Controle de memória do Decision Cube Editor. Figura 59 – Aspecto do formulário Forma de pagamento para a venda. Figura 62 – Formulário exemplo do Decision Cube. Figura 60 – Componentes da paleta Decision Cube.br. Figura 69 – Gráfico de amostra por idades de clientes.DLL.1.02 Figura 53 – Tela da ajuda da Bemafi32. Figura 56 – Tela de ajuda Bematech – Bematech_FI_AbreCupomMFD. Figura 75 – Object Inspector do componente idSMTP.Instalação do Microsoft ODBC para Oracle. Figura 91 – Propriedade de vinculação de dados. Figura 51 – Tela do site www. Figura 71 – Formulário de email no Delphi. Figura 85 – Fontes de conexão do componente ADO. Figura 50 – Tela aberta através de uma DLL. Figura 76 – Object Inspector do componente LB_Anexos (TlistBox). Figura 86 – Aspecto do formulário de teste para conexão ADO. Figura 63 – Parâmetros do DataBase. Figura 46 – Execução do projeto calculadora com novos parâmetros. Figura 67 – Formatação da Data no Decision Cube. Figura 78 – Clientes e banco de dados.8 Figura 44 – Formulário de uma calculadora simples. Figura 83 – Formulário do componente ADOConnection.bematech. Figura 45 – Projeto calculadora em execução através de uma DLL. Figura 54 – Formulário de teste para Cupom Fiscal. Figura 87 – Configurações e conexão do componente SQLConnection.1. Figura 55 – Funções de inicialização para Impressora Fiscal. Figura 88 – Grid adicionada ao formulário e ligada ao DataSourse. Figura 79 – Administrador de fonte de dados ODBC. Figura 81 . Figura 74 – Object Inspector do componente idMessage. Figura 57 – Teste Impressora em execução Figura 58 – Emulfith vr. Figura 84 – Formulário de propriedades de vinculação de dados. Figura 47 – Formulário para teste Figura 48 – Projeto teste para chamar tela com DLL Figura 49 . Figura 72 – Object Inspector do componente odAnexos (TOopenDialog) Figura 73 – Editor de filtro no Object Inspector do componente odAnexos. Figura 52 – Tela do emulador EMULFITH VR.

Figura 126 – Servidor de Aplicação criado no Serviços de componente. Figura 116 – Tela de diálogo do Data Modulo Figura 117 – Tela de dialogo do DataModuloRemoto. Figura 112 – Formulário de teste Figura 113 – Propriedade de mensagem de erro.9 Figura 92 – Informação de teste de conexão. Figura 100 – Editor de propriedades de componente. Figura 129 – Formulário de Clientes. Figura 119 – Componentes do DataModuloRemoto. Figura 121 – Programação gerada do P_Serv_Tbl. Figura 114 – Mensagem de erro. mostrando o campo TotalGeral. Figura 98 – Editor de propriedades Figura 99 – Formulário de Teste de tabela temporária. Figura 131 – Formulário cliente em execução. Figura 110 – Object Inspector da Tabela de Atividades (Tbl_Atividade) Figura 111 – Mensagem de erro. Figura 128 – Object Inspector do componente Tbl_Ativ (ClientDataSet). Figura 94 – Aspecto do formulário usando exemplo de fonte do Delphi Figura 95 – Representação de cliente ligado ao banco de dados. Figura 122 – Serviços de componentes. Figura 104 – Formulário de Teste de tabela temporária. Figura 102 – Formulário com o campo Total. . Figura 120 – Tela de Units. Figura 115 – Transactional Data Module. Figura 123 – DataModuloRemoto no Install COM. Figura 127 – Object Inspector do componente DCOM_Conexão. Figura 108 – Mensagem de erro mostrando violação de chave. Figura 132 – Object Inspector do componente SQL_Ativ. Figura 133 – Editor SQL. Figura 124 – Nome do Servidor. Figura 93 – String de conexão. Figura 103 – Editor de propriedades de componente. Figura 118 – Tela do Servidor Data Modulo.Paleta ACBr com todos os seus componentes instalados. Figura 134 – Balança Toledo Figura 135 – Conteúdo do pacote ACBr Figura 136 – Mensagem de instalação do pacote ACBr. Figura 101 – Campos do componente Tbl_Teste. Figura 137 – Informações de instalação do pacote ACBr Figura 138 . Figura 125 – Informação de sucesso de registro do ActiveX. Figura 109 – Campos do componente SQLDataSet (Tbl_Atividade). Figura 106 – Aspecto do formulário com duas grids representando dois clientes. Figura 105 – Object Inspector do componente DS_Ativ (DataSetProvider). Figura 97 – Aplicativos COM+ em serviços de componentes. Figura 96 – Tela de visualização de serviços de componentes. Figura 107 – Formulário com dois clientes em execução. Figura 130 – Object Inspetor do componente SQL_Ativ.

Figura 159 – Criação de Shortcuts. Figura 160 . Figura 149 .Informações do Software Figura 156 – Apresentação da Aplicação. Figura 157 – Arquivos para instalação.Tela de boas vindas Figura 152 – Criando um Novo Projeto Figura 153 . Figura 158 – Arquivos Instalados. Figura 154– Atualizações do Software. Figura 161 – Diálogos. Figura 142 – Propriedades do componente ACBrBAL – o Device Figura 143 – Formulário teste Figura 144 – Criação da tabela Produto no Paradox Figura 145 – Preenchimento da tabela Produto no Paradox. Figura 155 . Figura 146 – Preenchimento das propriedades do Database Figura 147 . Figura 151 . Figura 163 – Organização do Setup.Registro do sistema.10 Figura 139 – Formulário do demo BalancaTeste Figura 140 – Propriedades da paleta ACBr Figura 141 – Campo genérico do formulário demo BalancaTeste.Informações da aplicação.Aspecto do formulário depois de executado. Figura 162 – Sumários.Aspecto do formulário depois de pronto Figura 148 .Criando um novo projeto. .Tela de Menu do InstallShield Figura 150 .

11 Delphi – Apostila III AUTOMAÇÃO COMERCIAL 1 – Conteúdo Classes Criação de Componentes Herança Paleta personalizada de componentes Template Código de Barras Implantação de Código de Barras no Sistema Criação de DLL Para que serve Como funciona Como criar uma DLL Como Usar Impressora Fiscal Cupom Fiscal Emissão de Cupom Fiscal Como Cancelar Cupom Fiscal Forma de pagamento Localização de número de Série da Impressora Web dentro do Delphi Desision Cube Instalação de Programas com InstallShield .

Em uma declaração TYPE. além de colocar dados. A definição de um tipo de classe pode ser feita de forma bastante semelhante à de um tipo de variável composta. além de definirmos tipos como código. Um pouco diferente do outro. temos uma estrutura. estamos definindo o tipo para o Delphi. Quando abrimos um formulário dentro do Delphi. É como se fosse criar um novo tipo de variável. Este T é um tipo. End. por exemplo: Calcular o código. A estrutura nós colocamos <Reg1.endereço. procedimentos internos que manipulam esses dados. telefone. Para declarar uma variável denominada Registro do tipo Reg1. telefone. ali ele põe um T antes do NomeDoForm. End_Cli: string. bastando substituir a palavra reservada Record por Class. basta incluir sua declaração após a palavra reservada VAR: Var Registro: Reg1. podemos colocar procedimentos. Em Pascal. endereço. num registro RECORD. Reg1 = Record Cod_Cli:integer. podemos colocar programação. Nome_Cli: string. Exemplos: TEdit. declaramos tudo dentro dessa classe. Para os procedimentos específicos. A letra T antes do nome sempre vai existir. Só existe para aquele dado que definirmos da mesma classe.12 2 – CLASSES A partir de agora faremos literalmente a programação orientada a objeto. estamos definindo uma nova tipagem. TForm TBgrid. A classe é um super-record. estamos criando um tipo chamado TForm1. Vamos definir uma estrutura de dados para ele. --> uma classe é um super-record.Endereço> A idéia de classe é a mesma. podemos definir métodos. Uma classe também tem diversos campos. Isso é uma nomenclatura usada e não é obrigatória. por exemplo: nome. não funciona fora disso. Então criamos esse Form que é uma classe derivada de TForm. definida no campo TYPE.Nome> <Reg1. Da mesma forma que damos um nome a um formulário (Frm_NomeDoForm). . só é colocado para saber que é um tipo.

Exemplo: Como é o filho? Num casamento. de manipulação de Impressora fiscal padrão e as características como escolha de impressora e tipo. porque já foi herdado. Se criarmos uma classe. basta utilizar a notação de ponto. o TForm. mais o que herdar do pai. antes da modificação. O que tem dentro da classe? Quando falamos em classe. Para ter acesso aos campos de um objeto da classe. incluindo a sua declaração após a palavra reservada VAR: Var Registro: Reg1. O filho tem todas as características próprias. minimizar. No formulário do Delphi. Essa classe herda todas as rotinas prontas e só colocaremos o que for preciso a mais. Para atribuir valores aos campos do objeto Registro (da classe Reg1). é idêntico ao Pai. o filho herda características do pai. basta incluir o seguinte trecho de código após a palavra reservada TYPE: Reg1 = Class Cod_Cli:integer. tudo que for definido entre parênteses é herdado. End. . Anteriormente foi criado um tipo de variável e foi declarada uma variável daquele tipo. A vantagem de trabalhar com classe é herdar características. eventos programados que alguém já fez. Se for criado um novo Form é herdada as características do Form principal. cor de fundo. Nome_Cli: string. basta incluir as seguintes linhas de código: Registro. em vez de um tipo de variável composta chamada Reg1 Podemos então declarar um objeto denominado Registro. Este novo formulário criado é igual ao formulário Pai TForm e neste novo formulário podemos fazer as modificações que por padrão. TForm é uma classe criada pelos programadores da Borland para que nós possamos criar outro formulário herdando suas características. Agora temos uma classe denominada Reg1. Da mesma forma que acontece na vida natural. Herdar alguma coisa é pegar as características do objeto Pai. fechar. Agora criamos uma classe e declaramos um objeto daquela classe. tipo de cabelo. Não é necessário programar tudo de novo. End_Cli: string.cod_Cli := 100. Este formulário criado é uma classe chamada TForm. temos as características: borda. com isso economizamos muitas linhas de programação criando classes. por exemplo.13 Se quisermos criar uma classe denominada Reg1 em vez de um tipo composto chamado Reg1. botão maximizar. Podemos construir uma classe. da classe Reg1. podemos ter uma herança desta classe. cor de pele. aqui também.

.Nome_Cli: =„Fulano‟.End_Cli:= „Rua x‟. Registro.14 Registro.

15 .

Essa classe do tipo Tpessoa. private (privados) . Então. conseguimos ver as características de Tpessoa porque é do mesmo tipo. protected (protegidos) . mas seu valor pode ser visualizado no Object Inspector e será visto logo mais na criação de componentes. Criamos uma outra classe chamada Aluno que herda as características de pessoa e que não tem nada no private e nem no public. certamente iria funcionar no Tform1. Se esta definição fosse criada dentro do campo public. porque . Se tivermos outra classe e passamos o mesmo modo. Criamos uma classe chamada Pessoa que tem dentro dela uma única variável que não tem método. Colocamos no formulário um botão.16 3 – TIPOS DE MÉTODOS E CAMPOS Na linguagem Delphi. e qualquer código na mesma unit que a classe podem acessar os membros protected.published – semelhante ao tipo publico. public (públicos) - Alem desses temos ainda os tipos: . Mais precisamente. Como a definição de PintaDeAzul esta dentro do campo private do TForm ela não vai estar disponível para o TForm1 porque é privativa somente para o formulário Pai. já funciona para a classe pessoa. Fazendo um Teste: Abra a programação de um formulário recém criado. Basicamente a classe aluno é igual à classe Pessoa. com uma variável aluno do Tpessoa. e criarmos um TForm1 (que é uma herança) com todas as características do TForm. uma classe pode ter os seguintes tipos de métodos e campos: A diretiva public detona campos e métodos que são livremente acessíveis por qualquer outra porção de uma programa tanto quanto a unit em que estão definidos. Como não foi definido em outro form. subclasses. tem só o código e o nome. qual a diferença da programação entre Private e Public? Se definirmos uma rotina dentro do private no formulário TForm. não conseguimos. Criamos no método private definindo a seguinte variável: A do tipo integer.A diretiva private denota campos e métodos de uma classe que não são acessíveis fora da unit que declara a classe.Automated – tem as mesmas regras de visualização do tipo public e geralmente é usado em classes derivadas da classe TAutoObject (definida na unit OleAuto). e tem mais uma variável TAluno que tem as características Tpessoa. O que acontece? Quando apontamos em TAluno. tem a mesma herança. somente a classe. como uma classe chamada “PintadeAzul”.A diretiva protected é usada para indicar métodos e campos com visibilidade limitada. Somente a classe atual e suas derivadas podem acessar elementos protected.  clique em F12. .

mas se estivesse em Units diferentes. não consegue enxergar se for colocada algum comando de linha no Privat. ele define se é public ou Private. se colocarmos o comando USE UNIT2. Obs. antes de acessar. na mesma Unit. senão não mostra no form. Se no Form2. . Quando fizemos a definição de TAluno. variável aux do tipo integer que só existe no Form2 e foi criado como sendo Private. No caso do componente. no Form2 vamos criar uma característica. por isso é que consegue enxergar. ele mostrou a variável A. Se a classe TPessoa e TAluno tiverem sido definidas em Units diferentes já não conseguiríamos enxergar. Tudo que tiver dentro do Privat na mesma Unit é possível enxergar. Mostrou o A porque estava dentro do formulário. colocarmos a variável Aux no campo Public.17 então está mostrando? Porque esta definido na mesma Unit. então na Unit1 aparecerá o comando Form2. uma Unit que será criada. Agora o comando permitiu mostras a variável Aux porque ela foi colocada no campo Public. No Primeiro exemplo.<qualquercoisa> não mostrará a variável Aux. já não iria aparecer. para verificar se pode ou não acessar. No segundo exemplo. Na Unit1. então não tem privacidade.<qualquercoisa> e a variável será mostrada. em Units diferentes. foi mostrado o acesso a um campo privado porque estava na mesma Unit.: Não esqueça de atribuir algum valor para a variável criada. Em dois formulários. porque está em outro formulário no campo Private. Form1 e Form2.

resize). uma programação que já está feita e quando é herdada já vem tudo pronto (create.Pressionando as Teclas CTRL + SHIFT + C – as linhas deste procedimento é criada logo abaixo com os campos Procedure – begin – end . colocamos no campo public esses procedimentos. estamos disponibilizando vários procedimentos. porque estamos indicando para o Delphi que ele pode ser substituído.Posicionamos o cursor em cima do nome do procedimento. e executa. Se for procurado no Filho e não localizar. então vai ganhar esta característica do PintaDeAzul. No TForm1 se for criada uma classe herdando características do TForm1 não vai existir o procedimento PintaDeAzul. Se tivermos uma classe chamada TForm (formulário) e criamos nossa própria classe chamada TNovoFormulario. no caso “PintaDeAzul” . se o close do Pai ou o close do filho? Neste caso. nele é herdada todas as características automaticamente. se quiser. será executado o evento close do formulário Pai. Esses eventos programados estão no campo public que podem ser modificados. Para isso escrevemos Override (Virtual) após o comando. por padrão. Se não for definido isso. . criamos o nome do procedimento. mas se for herdada do TForm2. herdando características de TForm. mas sim este close que criamos.Para definir esse procedimento. neste formulário gravamos nosso evento Close e não queremos que execute o evento Close do TForm. várias rotinas. Podemos colocar procedimentos e disponibilizar dados.para depois colocarmos a programação dentro deste campo. Ex: No campo public podemos colocar Procedure PintaDeAzul . se existir o procedimento no filho. quando criamos componentes. uma classe herda características de outra classe. este procedimento PintaDeAzul só existe no Tform2. print. Basicamente. . Tem tudo o que o Pai tinha mais a programação que for feita à parte. Esta programação se refere ao Form2 Quando definimos a classe TForm2. Primeiro procura na classe Pai. então executa o do Pai. close. Para criar um procedimento que outros podem acessar. Na herança. no evento do formulário Pai. ele pode. que quando aparecer um ícone. Como fazer para ele saber qual dos closes a executar. sempre vai tentar usar o do filho.18 4 . depois executa do filho. substituir o do Pai. um novo close. Além de dados podemos criar outros procedimentos.COMPONENTES Um componente nada mais é do que uma listagem.

Em vez de usar o create do pai podemos fazer um create especial.1 . Em funções que não podem ser substituídas não colocamos Override. por exemplo. mesmo que for feito este procedimento no Filho. diferente de outros procedimentos. vamos criar um componente Edit que quanto digitarmos letras minúsculas. podendo permitir opcionalmente efetuar sua própria programação.  New component Figura 1 – Paletas de Componentes .1 – Criando o componente Para criar o componente faça:  Clique na paleta Component. habilitar alinhamento não pode ser substituído.2 .2. pintar de alguma cor.A criação do primeiro Componente Para o exemplo. ele transforma tudo em letras maiúsculas.Override Existe um create na classe pai e toda vez que for usado vai executar este create. então o que o novo componente vai ter? Terá tudo o que o Edit1 tem mais a característica de passar tudo para maiúsculo. Então vai ter uma área para digitar.19 4. por exemplo. 4. então este create pode ser substituído. Geralmente na programação do componente ele vem como virtual (Override). Já existe um componente pronto no Delphi. vai ter todas as propriedades do Edit pai mais as propriedades que quisermos definir. deixando uma instrução que é virtual (Override) Em toda programação podemos substituir o método por outra classe que permita que possa colocar uma programação diferente. Para isso defina o método a ser substituído como Override (virtual). O método existe mas pode ser substituído. e na hora que usar. mas podemos fazer o nosso create. vai executar o do Pai. 4.

parecido com quem? Digite o nome TEdit.  Escolha TEdit (StdCtrls). 3). Figura 3 – Preenchimento da caixa de dialogo para instalação de componentes. No ClxAplication – Tudo que for para Linux tem a palavra “Q” na frente e tudo que for para Windows é sem o “Q”. no campo Ancestor type. No caso do nosso exemplo a aplicação é para Windows. Qual o nome a ser dado para o componente? Esse nome é o que vai ser dado para a classe criada. . Qual deles herdar as características? . Ai aparece dois tipos de TEdit – um TEdit (QStdCtrls) e um TEdit (StdCtrls).Tudo que tiver um “Q” na frente é para Linux . componente que deseja herdar as características. (fig. Queremos criar um componente.20 Figura 2 – Caixa de diálogos para instalação de componentes. que mostrará uma listagem dos componentes que o Delphi já tem.

pas Mas se quisermos escolher outro local para criar esse componente é só escolher outro Path. Para gravar essa Unit do componente criada. (fig. 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. 4) Figura 4 – Preenchimento das propriedades do novo componente OBS: Cada vez que criar um componente. ou crie uma exclusiva de novos componentes e salve seus componentes nela. mas escolha uma paleta já criada.  Clique em OK.: Na prova. Para esta pasta pode ser dado o nome de componentes. Obs. ou pode ser criada sua própria paleta. Já criamos uma Unit chamada EditMaiuscula no Path escolhido acima. vai criar um arquivo chamado EdtMaiusculo.pas. Vai ser mostrado o módulo de programação abaixo: (fig 5) . conforme figura abaixo: Palette Page – Nome da paleta a ser criada: O componente pode ser criado dentro de uma paleta que já existe.21  Coloque o nome de TeditMaiusculo no campo Class Name. no diretório Lib. conforme mostrado: c:\arquivos de programas\borland\delphi7\Lib\EdtMaiusculo.  De o nome da paleta de Unilins – escrevendo no campo Palette Page. O local que vai ficar gravada será dentro do Delphi 7. escolha um arquivo existente ou crie seu próprio arquivo no campo Unit file name. não crie um monte de paleta.

protected.22 Figura 5 – Modulo de programação do componente. Private e public já estavam na classe pai. como mostrado o trecho do código abaixo: type TEdtMaiusculo = class(TEdit) Foi definido ainda um procedimento chamado Register que faz uma chamada a outro procedimento denominado RegisterComponents. será derivada por herança da classe TEdit. public e published. end. Este procedimento recebe como parâmetro o nome da categoria da Tool Palette na qual os novos componentes serão inseridos e se a página não existir então será criada. begin RegisterComponents('Unilins'. { TEditMaiusculo } Quando esta classe filha foi criada apareceu na interface os campos private. a transformação do que foi digitado para maiúsculo. Neste arquivo de código a nova classe TEditMaiuscula. type TEditMaiusculo = class(TEdit) private . entre essas características. A classe TEditMaiuscula herda todas as características do TEdit pai mais algumas coisas. procedure Register. [TEditMaiusculo]).

Tudo que tiver como published é o que vai aparecer no Object Inspector.  No campo protected precione as teclas CTRL + barra de espaço (fig. . quando for digitado.2 .23 { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end. 6). isto fará com que o filho herde também as características do pai.Implementando o procedimento KeyPress A nova função do KeyPress neste novo componente. campo T do tipo integer. mas neste campo. Como é protected.2. Se for protected. então pode usar as características herdadas. definimos uma classe Tpessoa. se forem herdadas as características exatas do mesmo pai. Num exemplo. Isto è válido? a: = text. uma classe que tem algo como private = variável “a” do tipo integer. não vai herdar o que esta no campo private de outro formulário. Esta função já foi definida em algum lugar e para verificar a definição.a – isto funciona? Não Considerando que a variável “a” tipo integer não exista. Private – só dentro do próprio formulário temos acesso. veja no campo protected tudo o que pode ser modificado. Mas para fazer com que a classe filha herde as características do pai temos que criar comandos no campo protected. mas em outro formulário. funciona dentro da própria Unit e também fora dela. no campo private não funciona. O que acontece? Fazendo a programação var a: integer. passara todos os caracteres para maiúsculo (UpCase). se for do mesmo tipo do outro. não podemos ter acesso. Se for definida no campo protected. Apesar de herdar todas as características. Published . mesmo herdada as características. sim. 4. se tivermos uma Unit1 e uma Unit2.

também existe. será chamado apenas Keypress. Se for digitado OnKeyPress. aparece mensagem dizendo que é um evento do tipo Keypress. que ao ser selecionado cria um procedimento chamado Override. Tudo que for Published vai aparecer no objecto inspector. o evento usado será então o OnKeyPress. elas serão trocadas para maiúsculas. porque poderá ser substituído/reutilizado se quisermos fazer outro procedimento KeyPress. isto é. OnKeypress é uma propriedade que está armazenada no evento a ser chamado. pode ser substituído. quando for digitadas letras minúsculas. A palavra “on” só é uma propriedade para aparecer no Objecto Inspector. Então se queremos programar um evento do Keypress. No Objecto Inspector tem um evento chamado onKeyPress. todas as funções que podemos escolher para o Edit. Estes comandos (procedures) estão escritos seguidos com a função Override. function. ele cria um evento chamado KeyPress. mas se for digitado KeyPress. dando um duplo clique neste evento. queremos trocar uma letra. OnKeyPress é só o nome da propriedade e nesta propriedade está gravada o evento a ser chamado. A palavra “on” vem antes da propriedade que só armazena o evento a ser chamado. No caso. .24 Figura 6 – Campo protected – criação de procedimentos. Ai aparecerá tudo que poderá ser modificado: procedure. O nome a ser utilizado é o KeyPress. O evento em si não tem esta palavra (on) na frente.

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

Figura 9 – Registro do componente. .  Clique em OK Na caixa de diálogos abaixo pedirá a confirmação da instalação.  Compile clicando no botão Compile. Confirme.26 Figura 7 .  clique em YES  Na caixa de diálogos perguntará se é o componentes EditMaiúsculo que você quer instalar.Caixa de dialogo para instalação de componentes. Figura 8 – Confirmação da instalação.

Public todos tem acesso e Published aparece no Objecto Inspector. No EditMaiusculo. Teremos uma propriedade chamada maiúsculo. chamada maiúsculo local. O programador decide se deseja maiúsculo ou não. se False deixa parecer um Edit Comum. automaticamente as letras digitadas serão transformadas em maiúsculas. Compile e teste. se for colocado True. quanto maiúsculas. se for colocado True. Coloque um Edit comum no formulario e o componentes EditMaiusculo criado. Percorra o campo das paletas e verifique se o componente foi instalado no final. Se quiser criar seu próprio evento ou Propriedade também dá. passa para maiúsculo. Private. crie uma nova aplicação. passa para maiúsculo.  File > New > Apllication. O componente na verdade é o aproveitamento de outro componente que tem muitos procedimentos. Para compartilhar. se False não passa para minúsculo. a programação é colocada no campo Protected se tiver herança entre pai e filho. ninguém acessa. Para criar uma propriedade no Objecto Inspector. No Edit comum podemos digitar letras tanto minúsculas. O sistema mostra mensagem dizendo que o componente foi instalado e registrado. . Criaremos uma propriedade chamada maiúsculo do tipo global.27 Figura 10 – Pacotes de componentes. - Até agora foi criado só um evento. Para verificar a funcionalidade do componente. Você aproveita alguma coisa que alguém já tenha feito e cria novos procedimentos e funções que achar importante.

private { Private declarations } fmaiu: boolean. Essa variável que vamos ter que criar. Então é hora de definir se a permissão é para só gravar. Para permitir a leitura e a gravação. do tipo boolean. Isto é ler uma propriedade. Quando tivermos uma propriedade chamada maiúsculo do tipo boolean .Toda vez que for criada uma propriedade. Por exemplo. está fazendo uma comparação. isto é. se só podemos ler ou também modificar o campo. Atenção . então utilizamos Fmaiu. procure o campo Create public constructor Create(AOwner: TComponent). Se quiser permitir alterar a propriedade é gravação. mas podemos fazer uma propriedade que permita somente leitura e não consegue modificar o valor da propriedade. ler ou ler e gravar. obrigatoriamente deve existir uma variável para atribuir o valor e tem que ser declarado no campo Private. e faz uma leitura.passa para maiúsculo. se tivermos uma variável com o nome “Mai” e outro que vai dentro desta variável do tipo Mai. ele vai pegar a propriedade maiúsculo e armazenar em algum lugar. Só que temos que criar esta variável no campo Private. vamos permitir a modificação. porque o nome maiúsculo não é uma variável. Somente através da propriedade do Objecto Inspector poderá ser mudado o valor. Essa variável tem que ser criada. Passamos para maiúsculo: se o fmaiu for True então passamos para Maiúsculo. If maiúscula = true then (faça alguma coisa). Se precisar gravar. override. na hora que for alterada lá dentro ele vai gravar o valor dentro desta variável chamada EMaiusculo. Neste exemplo. Essa variável vai existir. faz a comparação e executa alguma coisa. porque o valor só pode ser manipulado via Objecto Inspector.28 Importante: Quando definirmos uma propriedade. mas não pode ser vista e nem alterada. Precisamos de uma variável interna para armazenar. Se o valor for verdadeiro. e queremos utilizar aqui dentro. No campo Public precionando as Teclas CTRL + barra de espaço. Foi criada a propriedade maiúscula. podendo consultar o que está lá dentro ou alterar. temos que ter uma variável tipo Read e do tipo Higth. If fmaiu = true then . Geralmente as propriedades do Objecto Inspector são como leitura e gravação. { Public declarations } . temos que especificar se é de leitura ou gravação. mas o nome que vai aparecer no objecto Inspector e o valor do local tem que ser armazenado em algum lugar. grava dentro do Emaiusculo. Quando falamos em propriedade.

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

implementation procedure Register. end. protected procedure KeyPress(var Key: Char). procedure TEditMaiusculo. { TEditMaiusculo } constructor TEditMaiusculo. Do jeito que está como True se for executado e digitando qualquer palavra. override. begin inherited.Create(AOwner: TComponent). procedure Register. end.KeyPress(var Key: Char). feche o que está sendo feito. end. Abra um novo projeto e insira o componente TeditMaiusculo e um Tedit Comum. fmaiu:= true. if fmaiu = true then Key := UpCase(Key). begin RegisterComponents('Unilins'. override. end. { Protected declarations } public constructor Create(AOwner: TComponent). begin inherited. end.  clique no componente TEditMaiusculo. .30 fmaiu: boolean. { Public declarations } published { Published declarations } property Maiusculo: boolean read fmaiu write fmaiu. Para testar. No Objeto inspector verifique se a propriedade Maiúscula está como True – Se estiver como true é porque no método create colocamos a propriedade padrão como True. [TEditMaiusculo]). automaticamente irá transformar para maiúsculo.

ou no OnExit . em minutos. criamos um procedimento checar CPF no evento onKeyPress. herando do Edit – se for true. Figura 12 – Demonstração da utilização do componente instalado. é executada uma rotina. Podemos ter uma propriedade que verifica o CPF válido. um componente que faz a leitura de código de barras. Podemos ter um conjunto de componentes e se for preciso distribuir um componente para alguém entregamos o arquivo criado que será instalado no InstallComponente. quando perder o foco. quando apertar o Enter. as letras não serão convertidas para maiúsculas. A vantagem é que esses componentes criados ficam disponíveis com vários programas. ganhando tempo. Podemos ter uma biblioteca com vários componentes que mais usamos.31 Figura 11 – Formulário utilizando o novo componente. Agora podemos construir componentes com várias funcionalidades. usando herança na construção de componentes e formulários. . Conseguimos fazer um cadastro inteiro. após executar. Um exemplo desse uso é com Código de barras. Voltando na propriedade do Objeto Inspector e mudando para False.

3 . foi salva em uma pasta fora do delphi. no componente Edit: trocar de cor. Para criar um novo componente: Existem muitas coisas a serem trabalhadas. então já deixe gravado no delphi.Mais um exemplo de criação de componentes Quando foi criado o componente anterior. Campos Class Name : TEdtCPF Palette Page: Unilins Unit file name: Escolha o Path Figura 13 – Criação do componente TEdtCPF  Clique em OK .3. filtros com alguma validação (validar um componente que só recebe números ou só recebe letras.1 . mas se o componente for de uso definitivo em seus trabalhos.32 4. A herança é feita através da linha de comando Inherited que faz com que seja executada a programação do componente Pai. 4. por exemplo.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.

end. interface uses SysUtils.xxx-xx.33 A programação da Unit será feita conforme mostrada abaixo: unit EdtCPF. [TEdtCPF]). Vai ser derivada do componente Edit normal. StdCtrls.xxx. procedure Register. onde será feita a programação. Conforme forem digitados os números. O evento onKey Press deverá ser tratado. Esta mascara constituirá dos seguintes campos: xxx. No campo protected precione as Teclas CONTROL+BARRA DE ESPAÇO digite KeyPress e no combo mostrado selecione o procedimento KeyPress . type TEdtCPF = class(TEdit) private { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end. contará quantos caracteres foram digitados e após o terceiro caractere colocará um ponto. end. begin RegisterComponents('Unilins'. Controls. Temos que definir como será feita esta mascara. tratar tanto com o enter e testar todo o calculo e além disso vai ficar procurando toda hora se a quantidade digitada é de zero a nove. Classes. implementation procedure Register. Foi aberta uma nova classe que não tem propriedades e nem eventos . Conforme for digitando vai preenchendo os campos com os pontos e hífen ou digita primeiro todos os campos e depois que apertar o enter aparece a mascara com os zeros também preenchidos.

Se este comando for apagado o procedimento não executará as funções do Pai. end. . Esta programação vem com a linha de comando inherited. if not (key in ['0'.KeyPress(var Key: Char).#13]) then key :=#0. begin inherited. Defina para o procedimento KeyPress as linhas de comando abaixo após a palavra inherited: procedure TEdtCPF. override.'9'. isto significa – faça tudo o que está programado no pai e depois execute as linha de comandos abaixo.#8. Toda programação nestes campos vem seguida do comando Override – isto significa que ela pode ser substituída  Coloque o cursor em cima da palavra Key press e pressione as Teclas CTRL + SHIFT + C Isto fará que o campo da programação abra embaixo. { Protected declarations } public { Public declarations } published { Published declarations } end.KeyPress(var Key: Char). procedure TEdtCPF.34 type TEdtCPF = class(TEdit) private { Private declarations } protected procedure KeyPress(var Key: Char). end. begin inherited..

.35 Primeiro filtro Se a tecla não estiver dentro deste conjunto a tecla Key recebe vazio.  No campo protected . então apaga. quando for perdido o foco. protected { Protected declarations } procedure KeyPress(var Key: Char). Esta programação aceitará todos os caracteres de zero a nove. se quiser é criar uma propriedade e no final.DoExit. Qualquer outra tecla que for digitado e não seja nenhuma destas definidas na programação. override. Qualquer caractere que for digitado e que não esteja dentro do conjunto. podemos fazer com que o campo seja apagado.  digite a palavra Exit e no combo mostrado selecione o evento DoExit. de a mensagem se deu certo ou não. .Se for digitado um número errado. begin inherited. Este evento doExit é o que perde o foco.Temos que saber ainda se na digitação aparecerá os caracteres da esquerda para a direita ou vice-versa. Segundo filtro Se for Enter gera mascara O evento doExit Na hora que o Edit perder o foco gera a mascara. . se conseguir aplicar a mascara colocamos true. dando uma mensagem na . Neste campo temos que ter um número mínimo a ser digitado. colocamos false. Se for digitado uma letra qualquer será apagado. end.  Coloque o cursor em cima da palavra DoExit e pressione as telas CTRL+SHIFT+C para formar o campo de programação do evento. procedure TEdtCPF. procedure DoExit.precione CTRL + barra de espaço para aparecer os procedimentos. então apaga. override. O que pode ser feito. Se perdeu o foco porque foi digitado errado. Conforme digitamos o valor. OBS: Não de mensagens para o usuário porque não podemos saber como está o nosso componente. o backspace.Temos que saber qual o número de caracteres para depois clicar em OK.

Podemos usar a propriedade Length de no máximo 11 posições. O CPF pode ter no mínimo 8 até no máximo 11 caracteres e não podemos deixar que o numero digitado tenha mais de 11 caracteres. ou. podemos somente ler o valor e ela não aparece no Object Inspector porque não é de gravação. primeiro temos que verificar a quantidade de dígitos colocados. No evento onKeyPresss. não tem como atribuir nenhum valor. Geralmente temos que trabalhar com outro nome bem diferente. Internamente temos que trabalhar com outra variável. 2. Duas formas de fazer: 1. colocamos uma mensagem que não foi possível aplicar a mascara. Se criarmos uma propriedade somente leitura. só vai deixar de digitar até dar 11 caracteres e se tentar digitar mais. usando a propriedade Length. . implementamos até o máximo de 11 caracteres. porque não tem sentido aparecer no Object inspector uma propriedade que não podemos mudar.Digita-se o número e quando perder o foco exibe a mascara com 8 até 11 posições.Conforme for digitando. É o nome que aparece no object inspector internamente.36 tela. porque não podemos correr o risco de alguém tentar mudar alguma propriedade.  Crie a variável fvalido tipo boolean dentro do campos private Criamos então essa variável interna dentro do campo private. Ao sair. READ – É o que define o tipo de leitura e gravação do nome que aparecerá no Object Inspector. A vantagem é que o usuário não tem acesso direto à programação. não podemos trabalhar com a mesma. porque nunca sabemos como o usuário quer tratar a interface. Com esta variável é possível fazer o tratamento que quiser. O campo Protected é o que aparece no Object Inspector. Se acontecer de ser digitado mais de 11 caracteres. apaga tudo. desde que seja de leitura e gravação. private { Private declarations } //colocar a propriedade fvalido em private para não ser modificada fvalido : boolean.

com isso estamos limitando o máximo de caracteres que podem ser digitados. Se Length (tamanho) dessa variável for menor que 8 caracteres.<método> . apaga. end. não recebe nada. procedure TEdtCPF. No caso do componente. Ele assume que o Edit é o próprio componente. já coloque direto a palavra text. Se não tem o caractere ainda e for efetuando um KeyPress o evento é chamado antes de aparecer o caractere.text que vai executar o comando (text) depois do ponto. Se o tamanho for >= 11 já tem 11 dígitos e entra com mais um. end. if (Length(text) >= 11) and (key <> #8) and (Key <> #13) then Key := #0.KeyPress(var Key: Char). No procedimento doExit. begin inherited. if (Length (text) < 8) then fvalido := false else begin fvalido := true. então apaga. a variável fvalido recebe false e não conseguimos converter. então consegue converter. pode até funcionar no componente.. usamos por exemplo Edt_valor. Se o caractere é length o KeyPress não está contando ainda. var aux : string. if not (key in ['0'. Mesmo que tiver alguns caracteres. se colocarmos o mesmo comando descrito. só que . o caractere que estiver sendo pressionado não conta neste ponto (o caractere atual) Se o tamanho estiver completo no 12 digito. end. e não foi contado ainda. dentro do Delphi. Em uma propriedade normal qualquer. begin inherited.#13]) then key :=#0. senão fvalido recebe true (o número de caracteres é legal).#8. Se o tamanho for maior que 11 ou diferente que o Backspace ou Enter então apaga. procedure TEdtCPF.DoExit.'9'.37 OBS: Em qualquer propriedade ou método não coloque o nome da propriedade.

para o botão o nome é btn_sair. if length (text) = 8 then text := '0'+ text. end. então assume que é o próprio componente. Criamos uma variável auxiliar para armazenar o valor e depois atribui-la para o campo text de Edit. A primeira posição é a posição zero.A Máscara Tem 8 ou 11 caracteres. Uma string em Pascal permite até 256 caracteres. Esse código verifica se as posições vai de 1 até 11 caracteres. i: integer. preenche com zeros até completar onze caracteres.38 depois que usuário cria um componente e muda o nome (herdando os valores). por exemplo para btn_sair. - aux – variável auxiliar para armazenar os valores digitados. end. dentro do componente não coloque o nome. 4. if (Length (text) < 8) then fvalido := false else begin fvalido := true. o que acontece? Mudamos o nome de programação e quando for executado o código. {montando a mascara} for i := 1 to length do begin if i = 3 aux := aux + text[i]. var aux : string. .2 . begin inherited.3. Para evitar esse problema. procedure TEdtCPF.DoExit. não existe um Edt_valor. Toda vez que o delphi achar essa propriedade e não tem o nome na frente. depois em diante é a seqüência determinada pela variável. mas se o CPF tiver 8 caracteres. O comando Length verifica quantos caracteres existem. Em pascal o primeiro caractere guarda o número de caracteres que tem a string. end. Da posição 1 até a 11 colocamos um comando for variando de 1 até Length. só coloque a propriedade direto. Se for 11 começamos com um número válido. O Delphi verifica que não tem o btn_sair.

4. - 4.3)+'.2).3 . Neste comando colocamos a string que queremos entre parentes. OBS: Se não usarmos o comando IF. Agora jogamos aux para ser mostrada no campo Edit. {montando a mascara} aux:= copy(text. então colocamos uma condição if para cada múltiplo de 3 (if i=3).Aux: . .'+ copy(text.3)+'.Guarda a String completa.3)+'-'+ copy(text.3)+'-'+ (a partir da sétima posição.3) copiamos os três primeiros caracteres e após concatenamos um ponto. var aux : string. Uma linha de comando que não usa o for. Aux:= aux + text[i] . .3.1. depois é só copiar para a variável auxiliar de 3 em 3 caracteres.1. copiamos mais três campos e somamos (concatena) mais um ponto).DoExit. if length (text) = 8 then text := '0'+ text. copy(text.SCRCOPY Comando copy. if (Length (text) < 8) then fvalido := false else begin fvalido := true.7.'+ (a partir da quarta posição. copy(text. (a partir da décima posição. begin inherited. text:= aux. No exemplo copy(text. text:= aux.2). copiamos mais dois campos). mas não é isso que queremos.10.3)+'. copiamos mais três campos e somamos (concatena) um traço).10. copy(text.4.'+ copy(text. então não precisamos da variável “i”.'+ (a partir da primeira posição. procedure TEdtCPF. Neste comando podemos copiar de três em três blocos concatenando os pontos e o traço final. copy(text.do jeito que esta o comando coloca toda a string do aux e coloca no outro. Podemos fazer uma única linha de comando sem usar o for. mas esta condição não coloca ponto e nem traço.39 Text:= „0‟+text – este código completa com zeros se o cpf tiver 8 caracteres (concatena) até 11 caracteres.1. copiamos três campos e somamos (concatena) um ponto). end.3)+'.7.

40  Reinstale o componente para atualiza-lo.  Clique em ok Figura 15 – Compilando o componente.  Install component.3. Figura 14 – Reinstalando o componente. 4.4 – Testando o Componente Dentro de um novo form.  Clique em Compile para instalar. coloque um Edit comum e o EdtCPF que acabamos de criar. .

4. Se tentarmos digitar letras este componente não aceita.Programação do Componente EdtCPF unit EdtCPF. StdCtrls. Após digitar os números e teclar enter (perder o foco ) ele executa a mascara. type TEdtCPF = class(TEdit) private { Private declarations } // colocar a propriedade fvalido em private para não ser modificada fvalido : boolean.5 . Figura 17 – Formulário compilado e em execução. Classes. colocando pontos e traço. OBS: Só podemos fazer componentes se estivermos logados como administrador.41 Figura 16 – Formulário utilizando o componente criado. protected . interface uses SysUtils. porque temos que escrever na pasta do delphi.3.  Compile e teste seu componente. Controls.

end.DoExit.42 { Protected declarations } //precionar CTRL + barra de espaço para aparecer os procedimentos procedure KeyPress(var Key: Char). var aux : string. {Ao perder o foco. [TEdtCPF]). { 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. end. begin inherited. procedure Register. implementation procedure Register. end. // forca 11 caracteres. override. override. {montando a mascara} {for i := 1 to length do begin if i = 3 aux := aux + text[i]. begin RegisterComponents('Unilins'. gerar a mascara} if (Length (text) < 8) then fvalido := false else begin fvalido := true. completando com zero if length (text) = 8 then text := '0'+ text. {se fizer com o comando Copy nao eh necessario usar a variavel "i"} //i : integer. public { Public declarations } published { Published declarations } //propriedade criada para verificar se o numero digitado esta correto property cpfvalido: boolean read fvalido.} . procedure DoExit.

apagar e enter. . //primeiro filtro : digitar somente números. {Se não for digitado os algarismos de 0 a 9 ou barra espaço ou enter então aparecera vazio} if not (key in ['0'.KeyPress(var Key: Char). text:= aux.'9'.'+ copy(text.2).4.#8. end.10. // verificar o tamanho maximo (11 caracteres) {os dígitos podem ser colocados ate a posição 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.'+ copy(text. begin inherited. end.3)+'.3)+'. end.1.3)+'-'+ copy(text.#13]) then key :=#0. end.43 aux:= copy(text.. procedure TEdtCPF.7.

) para que possa ser completado nos formulários criados a partir deste. Então salvamos dentro do delphi numa pasta chamada Template ou outro nome que você quiser. não podemos depois mudar o nome.Um template simples.TEMPLATE È uma maneira de copiarmos toda uma programação sem usar uma única linha de código. Qualquer componente que colocarmos na tela do template. Dentro do Delphi criamos um arquivo chamado U_Cadastro (nosso formulário de cadastro padrão). para Btn_Primeiro. Btn_Anterior e Btn_Proximo em caption.  Coloque o nome da table – Tbl_Máster.  No caption coloque um nome genérico (Cadastro de.  Nome do DataSourse associado – Ds_Máster. – então salve na pasta alunos  Trocamos o nome do formulário para Frm_CadPad.44 5 . tabelas tem que serem genéricos 5. Na tabela. Um DataSourse e uma Table  Mude o nome do Botões. Uma automatização de tarefas.  Associe a Tbl_Máster ao DS_Máster.  Coloque três botões com o nome primeiro. O nome que forem colocados para os botões. anterior e próximo com desenhos. A propriedade Name vai ser fixa.1 .. o importante é estar salvo par evitar que se perca.  Salve o formulário em uma pasta qualquer. A tela ficará com o aspecto mostrado abaixo: . Podemos fazer um formulário com alguns componentes e programa-los como um form padrao.. não foi preenchido o Databasename e nem o TableName – então não está funcionando.

procedure TFrm_CadPad. end. no exemplo: Cadastro . begin tbl_master. end.duplo clique em cada botão para entrar no modulo de programação.First.Btn_ProximoClick(Sender: TObject). begin tbl_master. begin tbl_master.Prior. end.Btn_AnteriorClick(Sender: TObject). procedure TFrm_CadPad. procedure TFrm_CadPad.Next.  Salve o formulário  Para salvar o formulário como template clicamos o botão direito do mouse em cima do formulário e em Add to Repository  Em Title coloque o nome do formulário que vai aparecer.45 Figura 18 – Visualização do formulário Template Programando os botões  Programe o botão .Btn_primeiroClick(Sender: TObject).

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 diálogo para adicionar Template em um repositório.  Clique em OK

Figura 20 – Confirmação para salvar o Template.  Confirme.  A partir de agora este template está gravado no sistema.

5.2 – Abrindo um novo projeto através do template
Para abrir um novo projeto e usarmos esta aplicação para completar um cadastro:  File > New > Other > procure a paleta chamada Unilins criada – o formulário criado deve estar lá dentro

47

Figura 21 – Formulário de Novos Itens Para criar outro cadastro coloque a opção de inherit (faça uma herança) e clique em OK. Foi criado um novo formulário com o nome de Frm_CadPad2, herdando as características do form Frm_CadPad.

Figura 22 – Formulário aberto através de um Template.

48

Figura 23 – Programação do formulário aberto através de um Template. Não foi programado nada no formulário, pois ele já herda toda a programação do formulário pai. Neste formulário é efetuada uma herança, isto é, executa a programação que tinha no formulário padrão – Observe a palavra inherited. A partir da criação do novo formulário selecionamos uma tabela na Tbl_Master, podemos criar outros botões, adicionar procedimentos. Para adicionar outros componentes em todos os formulários, podemos abrir o template e acionar no formulário padrão que vai aparecer em todos os formulários criados a partir deste. Isto é útil num sistema que tem muitos formulários, podemos efetuar no template uma alteração de programação que fará com que todos os formulários que herdam suas características também façam esta programação. A vantagem é que se tivermos um template de cadastro, podemos fazer um cadastro completo em alguns minutos usando a herança.

49

6 – CÓDIGO DE BARRAS
Na aula anterior foram construídos componentes para serem testados. Não foi incluído algoritmos para não ficarem pesados. A intenção foi só para testar componente, porque daqui para frente teremos que criar um componente novo, quer seja componente para trabalhar com código de barras, para impressora fiscal, etc. A idéia da disciplina é que saibamos o que é um componente. A cada componente teremos que colocar peculiaridades novas.

6.1 - Surgimento do código de barras
A idéia do código de barras é velha, é de 1973/75. A necessidade do código de barras foi devido ao crescimento das vendas. Antes os produtos eram vendidos digitando um código e o preço. Era um tipo de código interno e para um novo produto, era gerado um novo código interno e este fixado no produto. Cada vez que tinha um novo produto, era necessário incluí-lo no cadastro. Esses produtos eram únicos, não existia uma uniformidade de dados. Ao passar pelo caixa, era preciso digitar o código e o preço. O problema e as conseqüências eram filas longas e a demora e muitas vezes o código e o preço poderiam ser digitados errados.

6.2 - Código de barras do tipo UPC
O Código de Produto Universal (UPC) foi a primeira simbologia de código de barras adotada para comércio. Foi criado em 3 de abril de 1973, nos Estados Unidos, quando a indústria de carnes instituiu oficialmente o código UPC como o código de barras padrão para marcar seus produtos. Interesses estrangeiros no código UPC levaram ao desenvolvimento e à adoção de um código similar, o código EAN, em dezembro de 1976. O código UPC Americano é composto de 12 dígitos. Usado nos Estados Unidos e no Canadá. Somente são usados os campos código da empresa e o código do produto, não tem o código do país. A partir de 1977, surgiu a Empresa EAN, um grupo que fez a padronização dos códigos de barra. Essa padronização não é nova. O inicio foi dado pelos Estados Unidos em 1973. Após 1977, a EAN difundiu sua padronização para o mundo inteiro e o padrão mundial hoje é ditado por ela. A empresa EAN foi criada na Europa e estabeleceu o padrão utilizado no mundo todo. A Associação Brasileira de Automação Comercial foi criada em 1994 e atualmente utiliza o nome EAN Brasil. Como os Estados Unidos já tinha seu padrão UPC, a EAN difundiu seu código para o restante do mundo, mas hoje os produtos dos Estados Unidos já usam códigos EAN.

50

6.3 - Os tipos de códigos EAN
Existem vários tipos de codificação EAN, as principais delas são EAN8, EAN13 e AN14, que são usadas no front de caixa. Outros códigos como o EAN12, EAN128, não são usados no front de caixa. A maioria dos leitores de código de barras não consegue ler o EAN12 e EAN128, é necessário um leitor especifico. O código EAN128 exige um leitor a laser. O leitor padrão é 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 é necessário encostar o bocal do leitor no código de barras. Essa luz é então refletida por um conjunto de lentes até um circuito integrado sensível à luz, semelhante a células fotoelétricas, que capta a imagem do código de barras. Os leitores a laser requerem uma certa distancia da barra, como é o caso dos leitores usados em supermercados. Para os códigos EAN128 existem aparelhos específicos para fazer a leitura porque o alcance tem que ser maior. O EAN128 geralmente é usado em grandes volumes. O leitor de código de barras normalmente é usado em conjunto com o teclado. Não há diferença na programação, seja para os leitores de códigos comuns (front de caixa) e leitores a laser que requerem uma distância para efetuar leitura. Os hardwares são usados para a mesma função - ler códigos de barras. Quando passamos o leitor em cima do código de barras é a mesma coisa que digitar o valor no teclado.

6.4 - O Padrão EAN
EAN-8 EAN-13 EAN-14 EAN-128  tem 9 dígitos.  tem 13 dígitos.  tem 14 dígitos.  é um caso particular

O EAN-8 é usado para embalagens pequenas mas este código em relação ao preço é muito caro em termos de custos. O padrão utilizado na grande maioria dos produtos expostos à venda é o EAN-13.(fig 24).

6.5 - Definição do código
O código EAN é definido da seguinte forma: - uma margem branca para começar o código a partir dele - uma margem sem nenhuma numeração.

Figura 24 – Exemplo de código EAN-13

tinha que ser alterado na gôndola o preço das etiquetas. filiar-se à empresa e obter o código. por exemplo o Brasil é o 789 e cada país tem um número codificado. Utilizadas para gerenciamento do controle de Estoque.um código de início. pagamento de bancos. o 2 de 5 e o 3 de 9 A leitura das barras é feita da direita para a esquerda. tudo que for branco ou refletir luz será interpretado como digito “1” e as barras que não emitirem luz serão interpretadas como digito “0”. EAN-13.6 . Ao utilizar o código de barras não é necessária a etiquetação de produto a produto. principalmente quando se tem um volume muito grande de dados. 6. o UPC americano. mas sim durante à noite. Os próximos quatro ou cinco dígitos representam o código da empresa. Quando a luz incide no código. Geralmente não se troca o preço no período de funcionamento de uma empresa. 6. Neste caso existem dois tipos de código de barras . na parte de caixa. Os padrões mais importantes são: EAN-8.7 . Com isso podemos saber a origem de determinado produto. Após isso localiza o primeiro código que é o numero “6”. Antes eram usados o código do produto e o preço e muitas vezes quando o preço do produto era alterado.um de 4 e outro de 5 dígitos que representam a empresa. Exemplo: uma empresa como a Nestlé que tem uma linha de produtos muito grande registrou no Brasil com o código 789 (do país). Depende muito da variação do espaçamento para produzir um código diferente. mas sim registrado.O funcionamento do código de barra O código de barras é um símbolo composto de barras paralelas de largura e espaçamento variáveis. Quatro dígitos para representar a empresa e . No meio do código tem outro número “6” e no final tem outro numero para finalizar a String e saber que foi feita a leitura inteira do código. Quanto à compra de um código de barras é necessário entrar em contado com a EAN Brasil. EAN-128.A representação dos campos do código EAN Os três primeiros dígitos do código EAN representa o pais. Esta codificação é feita em bit.51 . OBS: O código do país necessariamente não indica que a origem do produto seja daquele país. Na utilização do código de barras podemos controlar qualquer alteração de preço diretamente no caixa. O taxa de uso é paga anualmente e mais a filiação pela primeira vez. EAN-14. Este numero indica o inicio da leitura e não está representado numericamente para não confundir na digitalização. No sistema financeiro.

Se tiver uma margem escura ou um quadro antes de começar as barras. permitimos que o código do produto vá até 9.000 produtos). Para cada produto. O código que usa somente quatro dígitos para o código da empresa é o mais caro e geralmente começa com o número “1”. Por último. o digito verificador e por último o caractere de guarda que ao final indica que terminou o código de barras. Se o código de barras conter 5 dígitos para a empresa. aqueles são interpretados como se fizessem parte do código. Se o código começa com um (1) então é uma das empresa que pode ir até 99. o caractere central. seqüencial para cada produto.52 cinco dígitos para representar o produto (numa representação de até 100.999 códigos para representar os produtos. permitimos para o código do produto uma faixa de até 9. Ao comprar um código de barras com 5 dígitos para a empresa.000 produtos) que são começados pelo “0” até 99. Margem de Silêncio .999 unidades. caractere que representa o início (seis caracteres para codificar tabela A ou B.999 unidades (10. 4 ou 5 caracteres que representam o código do produto.a margem de silencio. A compra do código de barras é fornecida com o código do país e o código da empresa.É o espaço em branco antes de começar o código que contém os dados. As combinações de corres. Margem clara. um novo código. Os Códigos de Barras tem que ter as combinações de corres corretas: Barra Preto Azul Escuro Marrom Verde Escuro Fundo Branco Amarelo Vermelho Rosa e e e e Não funcionam as combinações de cores de código fora do padrão especificado pela EAN. As barras das extremidades e central são iguais e obrigatórias em todos os códigos. o código da empresa representada por 4 ou 5 caracteres.999 unidades. . O ideal para um código de barras é a impressão de barras pretas em fundo branco. a numeração correspondente ao produto é gerada pela própria empresa. temos o digito verificador que confirma se o número da barra foi lido corretamente. Se ocupar mais espaço para o código da empresa sobra menos espaço para o código do produto. então para evitar isso é necessário um espaço em branco antes de começar o código .

terá que manter o código da empresa comprada (o código de barras) porque ainda existem produtos dessa empresa expostos à venda em estabelecimentos comerciais que ainda não foram vendidos ao consumidor final. caixa de fósforos. pelo menos cinco anos. Neste formato não existe o código do fabricante.53 Se uma empresa comprar outra empresa. Para os produtos não comestíveis. terá que ser gerado um novo número. lápis. não pode ser reutilizado para outro produto. O código de barras de um produto que teve sua fabricação suspensa. A diferença para o EAN13 está no método de codificação e no menor número de caracteres de dados. canetas. porque não está sendo cobrado esse conteúdo a mais. Se tiver um produto que foi modificado. podemos reutilizar o código mas é necessário informar às empresas consumidoras que o produto referente àquele código não existe mais e foi reutilizado para outro produto. 6. etc.9 . etc. assim essas empresas podem atualizar o cadastro referente a esse código de barras em seu sistema (banco de dados). por exemplo a fórmula. Quando terminar o período. como cigarros.Brasil código do fabricante código do produto dígito verificador .Duração do Código de barras. O prazo de cinco anos é necessário para manter durante esse tempo um arquivo fiscal de tudo que foi vendido na empresa.Código de barras do tipo EAN8 O código de barras do tipo EAN8 foi desenvolvido a partir do EAN13. então não é necessário trocar o código do produto. só tem o código do país. Na verdade ele é uma versão compacta do EAN13 visando embalagens pequenas.8 . conteúdo. embalagem. o código do produto e o digito verificador. Pode acontecer de ser colocado uma quantidade a mais e grátis numa embalagem. Exemplo: A reutilização do código de barras para produtos comestíveis é em media de um a dois anos para permitir que o estoque à venda seja esgotado. Veja no exemplo abaixo como o código de barras EAN8 é bem menor que o EAN13: Exemplo: Para o EAN13 tem o seguinte código: 789 4401 00004 1 Figura 25 – Exemplo de código de barras EAN-13 7894401000041 789 4401 00004 1      é o código completo código do país . 6.

000 códigos disponíveis pela EAN que verificará antes de tudo se não é possível colocar um código EAN-13.Código ISBN (International Standard Book Number) – impressos em livros. . Com isto o código utilizado fica com oito dígitos em vez de treze.54 Para codificar a mesma fita utilizando o código EAN8.Ex: 1 – Embalagem com 6 unidades.11 . 6. Não precisa fazer o controle de qual o país. individualmente. Os 13 dígitos é do próprio código e o dígito a mais representa de que forma esta sendo vendido o produto.10 . Quando for necessário usar o código EAN-8.12 . 6. Exemplo abaixo: 789 0004 1 Figura 26 – Exemplo de código de barras EAN-8 789 0004 1 789 0004 1     é o código completo código do país . 6.Código EAN-14 Usado para serem usados em embalagem que contém mais de uma unidade. O símbolo gerado fica mais compacto.Código ESSN Código serial para publicações de periódicos – Começa com 977 e depois o número do periódico. Só existem 10. O EAN-14 é o mesmo EAN-13 com um dígito a mais no início. Esse código permite vender produtos em lote com até 9 tipos de quantidade. seguido da numeração ISBN (nove dígitos) e o dígito de verificação. 3 – Embalagem com 24 unidades. o símbolo gerado ficaria bem mais compacto. Sua localização padrão geralmente em embalagem de plástico é em cima desta embalagem.Brasil código do produto dígito verificador O código que identifica o fabricante é omitido e o código do produto fica com quatro casas em vez de cinco. É um padrão de 13 dígitos também. Tornou-se padrão na identificação internacional de livros. representa a quantidade no lote. com três dígitos iniciais identificando que o produto se trata de um livro (978 ou 979). 2 – Embalagem com 12 unidades. compra-se um único código.

O próximo dígito indica o tipo de cobrança a ser feito – se por peso ou por preço. Se um produto muda muito o preço.Sempre começa com 2 – uso interno reservado. o processo é o mesmo. O calculo do dígito verificador é feito da seguinte forma neste código: Numere cada caractere do código. Quando o produto é vendido por peso.55 6.Código de uso interno Para venda de produtos. por exemplo.Depois o código do produto com 5 dígitos para especificar o produto. por exemplo hortifrutigranjeiros e açougues. porque é só alterar no sistema o peso e não é preciso remarcar o código de barras. 6. Geralmente os açougues trabalham com preço. . Produtos que não são vendidos com facilidade podem ter seu código de barras colocados por preço.999 gramas (100 quilos). da esquerda para a direita. . . Todo código de uso interno também tem 13 dígitos. Por exemplo: “0” para peso e “1” para preço. A diferença está no primeiro dígito: .000 produtos porque pode ser que um ou mais produtos saiam de linha e não é permitido usar esses códigos enquanto não vencer o prazo estabelecido em Lei. Se for vendido por preço.14 . geralmente usamos colocar o peso.Calculo do digito verificador no EAN-13. o peso máximo que podemos vender é 99.99 reais. .Produtos na promoção: Se for vendida duas unidades na promoção é necessário embala-las numa única unidade para colocar outro código de barras. O valor máximo que podemos representar é R$ 999.13 .  representa o fabricante  representa o produto Obs: O número 22009. para que as barras das unidades não fiquem expostas com o risco de serem lidas ao passar pelo caixa.Localização do Código de barras A etiqueta ou impressão do código de barras é colocada de preferência e seguindo uma padronização no canto esquerdo ou direito inferior.15 .Mais cinco dígitos para representar a quantidade ou o peso.E o digito verificador.000 produtos disponíveis. Como calcular o último número que analisa se o código esta certo ou errado? Vamos tomar por base o código de número: 7 8 9 1 0 1 0 2 2 0 0 9 789 1010 22009  número que representa o Brasil. produtos importados. o que muda é o segundo dígito que representa o preço. . . Para o código do produto – 100. não significa que tem 22. 6.

Nos Estados Unidos temos um microship em teste para ser usado no lugar do código de barras. Dentro de pouco tempo.Soma-se o valor do passo 1 (18) com o valor do numero obtido no passo 3 (63): 18 + 63 = 81 5) . No código EAN 128 pode ser codificadas letras que permita colocar a descrição do produto.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) . Permite. por exemplo.Soma-se todas as posições pares: 9 + 0 + 2 + 1 + 1 + 8 = 21 3) . O código de barras representa os dígitos binários 0 e 1. de pizzas congeladas e refrigerantes a CDs e televisores. esta tecnologia será tão familiar quanto o próprio carrinho de supermercado. Já existem componentes que geram o código de barras. determinados pela espessura das barras.Obtenha o múltiplo de 10 maior que o número do passo 4 (81) Múltiplo de 10 > 81 = 90 6) . A RFID.81 = 9  O numero 9 é o dígito verificador do código acima. A invenção atende pelo nome de Radio Frequency Identification (RFID). estará presente em uma infinidade de produtos. se caracteriza por um microcircuito eletrônico que armazena informações sobre todos os tipos de objetos. que está cada vez mais difundida. Cada barra preta ou branca representa um único dígito. e até de animais. Além disso. que em português significa "Identificação por Radiofreqüência". além .Faça a subtração do numero obtido (90) do numero do passo 4 (81): 90 .Soma-se todos os números que estão nas posições ímpares a partir da posição 3: 0 + 2 + 0 + 0 + 9 + 7 = 18 2) .O número que foi obtido no passo 2 (pares) deve ser multiplicado por 3: 21 X 3 = 63 4) . A impressão ideal de código de barras é feita em impressora laser.

Figura 27 – Caixa de diálogos para criação de novo componente.  Após criado > clique em OK Depois de criado aparecerá o código da unit abaixo: (fig. 6. e a transmissão de seus dados a um dispositivo receptor situado a poucos metros ou a vários quilômetros de distância. Em Unit file name: Coloque o diretório a ser salvo. 28) . Geralmente no diretório por você criado ou se for usa-lo definitivamente pode deixar na pasta LIB. Em Palette Page – coloque Unilins.Criação de componente para fazer leitura do código 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.16 . a localização destes em poucos segundos.57 disso.

(fig.58 Figura 28 – Código de programação do componente CodigoDeBarras.  Dentro do evento protected – clique em CTRL + Barra de espaço para abrir a caixa de diálogos abaixo > selecione o evento KeyPress.29).Programando as propriedades A primeira propriedade a ser feita é o evento OnKeyPress. Vai aparecer o procedimento KeyPress abaixo com a declaração override: . Figura 29 – Procedimento para seleção do evento KeyPress.16. Classe TcodigoDeBarras derivado de TEdit 6.1 .

 Coloque o cursor em cima de KeyPress e pressione as teclas CTRL+SHIFT+C que criará o procedimento na ultima linha da unit. Como são todas de uso interno do componente. conforme mostra abaixo: procedure TCodigoDeBarras. outra que retorna se deu certo ou não e qual o tipo de código se EAN-13. {codigo lido} Esta propriedade não pode ser do tipo inteiro porque o numero é muito grande e o inteiro só vai até 32. EAN-14. end. end. pode ser inteiro e trabalhamos todas as medidas em gramas property peso:real read fpeso .KeyPress(var Key: Char).  Agora precisamos criar as variáveis. begin inherited.  No campo published criamos três propriedades Published { Published declarations } property codigo:string read fcod. {EAN13. todas elas somente de leitura. {peso do produto} property preco:real read fpreco . override. {peso(true) ou preço(false)} Se for colocado o preço por quilo.EAN14. etc.59 protected { Protected declarations } procedure KeyPress(var Key: Char). criamos no campo private: . Precisamos de três propriedades. {valido ou nao} Esta propriedade indica de deu certo ou não – é também de leitura property gtipo:integer read ftipo. Colocamos mais três propriedades: property medida:boolean read fmed. interno. Além do evento KeyPress temos que criar uma propriedade que retorna o código. {preco do produto} end.8 OU ITERNO} Esta propriedade retorna o tipo.000 O nome da variável interna vai se chamar fcod property valido:boolean read fval.

var i:integer. principalmente porque ele o usuário nem tem acesso a esse Edit. fval:boolen. fval:boolean.  Coloque o cursor em cima da palavra verifica e pressione CRTL+SHIFT+C: function TCodigoDeBarras. . Para não ficar repetindo os mesmos comandos.verifica(cod: string): boolean. {verifica o dv} Esta funcão retorna se foi lido o código corretamente. fpeso:real. function verifica(cod:string):boolean. fmed:boolean. begin end. fpeso:real. vpar. Não colocaremos o comando overhide porque teoricamente não permitiremos que o usuário modifique os comandos. fpreco:real. ftipo:integer.vtot:integer. ftipo:integer.60 { Private declarations } fcod:string. fmed:boolean. fpreco:real.vimpar. Entramos com o valor de uma string e esta rotina verifica se esta correto ou não:  Esta rotina será criada no campo private para que não se tenha acesso a ela. EAN13. Temos que efetuar três tratamentos: Digito verificador. Private { Private declarations } fcod:string.EAN14 e se é de uso Interno ou Externo. criamos uma rotina extra para fazer o calculo do dígito verificador. tipo de código se EAN-8.

vimpar e vtot.vtot:integer. begin {par} vpar:=vpar+strtoint(cod[i]). end. . end else {impar} begin vimpar:=vimpar+strtoint(cod[i]). 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. Se o valor for impar o mesmo procedimento acima é realizado. a variável vpar recebe o próprio valor do campo mais o caractere daquela posição (cód(i)). vimpar:=0. begin {1 soma as posiçoes impares 2 soma as pares 3 multiplica as por 3 4 soma a multiplicaçao com as pares 5 subtrai do proximo multiplo de 10 } Zerar as variaveis vpar. vpar. vtot:=0.61 O algoritmo: {1 soma as posições impares 2 soma as pares 3 multiplica-as por 3 4 soma o resultado da multiplicação com a soma das pares 5 subtrai o total do próximo múltiplo de 10 } function TCodigoDeBarras. então fora do laço ganha um pouco de desempenho. Detalhe: Tanto faz se for feita a multiplicação por 3 da variável vpar antes ou depois do laço.verifica(cod: string): boolean. vtot:=vpar*3 + vimpar. para cada laço que for realizado é efetuada a multiplicação.vimpar. Se for colocada a multiplicação dentro do laço. vpar:=0. var i:integer.

. if (10 -(vtot mod 10)mod 10)=strtoint(cod[length(cod)]) then Se o digito verificador for correto então retorna a rotina verifica = true.. então convertemos... end. Se for enter então inicia toda a investigação if not (Key in[‗0‘. verifica recebe true. end. {verifica o tipo} Para verificar se o tipo é válido ou não. A função Verifica é só para confirmar o digito verificador. Necessitamos realizar o tratamento do:} . Temos duas opções de calculo: Ou procuramos até achar o múltiplo que queremos.‘9‘.KeyPress(var Key: Char). temos que usar a propriedade chamada valido que retorna true ou .tipo de código se é 14.Programação do Procedimento KeyPress procedure TCodigoBarras. caso contrário retorna false. falta descobrir o múltiplo de dez maior que o vtot. {tratamento do código de barras. if Key = #13 then begin {verificar se é valido} Primeiro temos que verificar se o dígito é válido ou não Fval:= verifica (text). Retorna True ou False com a função de validar o código de barras . Se os códigos forem iguais. verifica:=true else Se deu errado retorna a rotina verifica = false verifica:=false. Esta função é de uso interno. Já temos o tratamento do código verificador.digito verificador .2 .16. Depois comparamos se é igual ao digito verificador.13.62 Já temos o total.#8) and (key<>#13]) then Key:= #0. begin inherited.8 etc. O código é uma string e queremos comparar dois números inteiros. declarada no campo private para o usuário não ter acesso a ela. if(length(text) >= 4) and (key <> #8) and (key <> #13) then Key:= #0. ou pegamos o numero da variável vtot e calculamos o mod 10.se é interno ou externo} Este if verifica se foi pressionada a tecla ENTER. 6.

14. {apos verificar o primeiro digito e descobrir que é de uso interno. 13. end. temos que verificar se o calculo será realizado por peso ou por preço. passando a string digitada e verifica se é falso ou não. case Length(text) of 14: ftipo:= 14. Depois verifica o tipo do código Caso Length (tamanho) for do tamanho do tipo 14. end else ftipo:= 13. A propriedade chamada ftipo se for 14 – ftipo recebe 14. {copiar o código do produto} Fcod := Copy(text.63 false. end. end else begin fpreco:= strtofloat(Copy(text.3. Para tal.8. 8: ftipo:= 8.8. Isto só é possível se a empresa utilizar o EAN13 e o código de barras iniciar com 2} if text[1]= '2' then begin {uso interno} ftipo:= 2. end.5))/1000. end. 13: begin {verifica se é um código de uso interno. Pode ser usada o comando Case para cada tipo independente se é do tipo 13.8 então fara alguma coisa. end.5))/100. etc.5). A propriedade fval recebe a função verifica. . basta olhar o conteúdo do 2 digito} {0 = preço ou 1 = peso} Fmed:= ('1' = text[2]).. { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text.

6. Determinar se é um digito válido ou não – verificação do tipo. Para verificar se o código é de uso interno temos que certificar se o código é o EAN-13 e o código de barras inicia com 2. if text[1]= '2' then begin Se o caractere na primeira posição for o 2 então é de uso interno então ftipo recebe 2. ftipo:= 2. Primeiro temos que saber se começa com o número 2. porque não da para tratar o uso interno de outros códigos (nem do EAN-8 e nem do EAN-14). Há duas maneiras de estabelecer esta condição: . 8 ou de uso interno. Apos verificar o primeiro digito e descobrir que é de uso interno. temos que verificar se o calculo será realizado por peso ou por preço. Esta validação é feita através da rotina verifica e passamos como parâmetro a String digitada que será valida ou não. Para verificar se o código é por preço ou por peso. Para verificar o tipo de código usamos o Length (tamanho). Só podemos usar internamente o código EAN-13 legalmente que começa com 2. se é 14. Existe uma propriedade que define se é por preço ou por peso.16. temos que determinar se a tecla pressionada é o enter através do comando if. temos que ler o segundo digito.3 . Fazemos o tratamento do código só quando for o EAN-13. Antes.O tratamento do código EAN-13 para uso interno. basta olhar o conteúdo do segundo digito: 0 = preço 1 = peso Esta definição de preço ou peso não tem padronização. if text[1]= '2' then begin {uso interno} ftipo:= 2. 13. Se for pressionado enter entra no comando case if Key = #13 then begin end.64 Agora vamos ver qual o código que está sendo usado. Fval:= verifica (text). Para tal.

Se for por peso (fmed:= true). Depois temos que copiar o valor . Nota: Não precisamos colocar (se for = true) porque é um código booleano e retorna true ou false.convertendo em dinheiro). 14. interno. o código do produto será o mesmo. Isso vai dar 10. Se de uso interno começa pelo numero 2. caso contrario atribui false. a medida é por peso. Fcod foi copiado para dentro do campo.200g. O preço terá duas casas decimais representando os centavos.Para copiar o valor comparamos o fmed. .: Se tivermos 10 K e 200g – podemos copiar o numero 10 e concatenar com 200. Estamos comparando se o conteúdo na posição 2 for igual a 1(que é por peso) então atribuímos true para fmed. {copiar o código do produto} Fcod := Copy(text. 0 ou 1 3 Código Produto 4 Preço ou Peso 5 Dig. Ex.3. Se for por peso temos que transformar em valor. Verificador Posições: 1 – Se de uso interno ou não.se 1 for igual a text na posição 2 – estabelece a condição direto. (strtofloat . O peso terá três casas decimais representando a medida de peso em gramas. Ao salvar transformamos em float. 3 – Código do Produto. O EAN 13 é composto de: 1 Tipo 2 Cód.5). Se fmed for true. 2 – Se a segunda posição for igual a 1 fmed recebe true senão fmed recebe false – esta condição ficará como comentário na programação mas também funciona. Nós temos 4 tipos de códigos e temos que descobrir qual o tipo se EAN8. 2 – Código 0 ou 1 – se por preço ou por peso. 5 – Digito Verificador. Fazemos a cópia do código através do comando Copy.65 1 – por peso (fmed:= true) .. 4 – Preço ou peso do produto. 13. Tanto faz se o campo 4 for por preço ou peso.

temos que destrinchar o código. Ela começa na oitava posição e copia cinco caracteres.200g. Se for por preço – dividimos por 100. Então quando efetuamos uma busca.8.200) e dividimos por 1000 que dará os 10. Após transformar em número dividimos por 1000.66 Ou Fazemos a leitura de todos os dígitos de uma única vez (10. dividimos por 100 Se for por peso – dividimos por 1000.5))/1000. if text[1]= '2' then begin {uso interno} ftipo:= 2. o fpeso recebe a string que acabamos de copiar. Se aparecer o campo 2 de uso interno – lê o próximo campo Nota: Quando o código é de uso externo fazemos a busca pelo código inteiro. . mas quando é de uso interno. não passamos o text como parâmetro. Para o preço. Então quando for feito um comando LooKup. { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text. end Com isso conseguimos transformar o peso em gramas else begin fpreco:= strtofloat(Copy(text.5))/100.8. como é utilizado com duas casas decimais. Como é string temos que transformar em numero (strtofloat). Se é por peso. O código: Exemplo (2 0 08100 00071 4) – como é de uso interno vai armazenar os cinco dígitos do código do produto (08100). mas sim o código do produto (o campo especifico do código). end. este comando para o código e localiza o produto especifico daquele código.

colocamos Fcod recebe text (Fcod = text). ftipo:integer. por exemplo. depois 5 digitos do código do produto (12345) e cinco dígitos que indica o valor (55532). por padrão. O código de barras está pronto. no caso do 13 está faltando atribuir qual o tipo. Estamos atribuindo à variável Fcod o valor de text para depois descartar quando não mais precisar. calcula o digito verificador. . Se for por preço será R$ 555.32. vamos pegar todos os dígitos com exeção quando for de uso interno. O tipo já está sendo atribuído. function verifica(cod:string):boolean. Controls.67 A propriedade código (property codigo) que retorna o código de barras tem que ser atribuído no começo no campo published porque independente de qual seja. StdCtrls. que será substituído. interface uses SysUtils. fpeso:real. o que foi digitado. Se for por peso será 55 quilos e 532 gramas. Então se for digitado 789101000001 8. Então por padrão o código é igual ao text (Fcod = text) Quando for de uso interno começo com o número “2” depois 0 ou 1 (dependendo se é por preço ou peso). 6. o código de barras é o que está na propriedade teste. fval:boolean. override. fmed:boolean. Se é valido ou não. fpreco:real. por padrão . 13. esta linha é um “text” que será atribuído por padrão. Classes.Programação da Unit CodigoDeBarras unit CodigoDeBarras. {verifica o dv} protected { Protected declarations } procedure KeyPress(var Key: Char). type TCodigoDeBarras = class(TEdit) private { Private declarations } fcod:string. Como para todos os códigos 12.17 . 14 tanto faz. Para um deles é atribuído o tipo. E por último o dígito verificador. Para esse código que será feita busca no banco de dados.

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

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

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

end else ftipo:= 13. if(Length(text)<1) then fvalido:=false else begin fvalido:= true.8 etc.8.3. if (length(text)>=4)and(key<>#8)and(key<>#13) then Key:= #0. end. {verifica o tipo} case Length(text) of 14: ftipo:= 14.5). begin inherited. if length(text) = 1 then text:= '0'+text. . basta olhar o conteudo do 2 digito} {0 = preco 1 = peso} Fmed:= ('1' = text[2]).5))/1000.13. Para tal. procedure TEdtCodigoBarras. end. { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text. 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.DoExit. end..5))/100. begin inherited.#13])then Key:= #0. {copiar o codigo do produto} Fcod := Copy(text.KeyPress(var Key: Char).. end else begin fpreco:= strtofloat(Copy(text. // se é interno ou não if not (key in['0'.'9'. {apos verificar o primeiro digito e descobrir que e de uso interno. 13: begin {verifica se e um codigo de uso interno. temos que verificar se o calculo sera realizado por peso ou por preco.71 procedure TEdtCodigoBarras. {tratamento do codigo de barras} //digito verificador //tipo de codigo se é 14. if Key = #13 then begin {verificar se e valido} Fval:= verifica (text).8..#8. end.

end. inttot:= intpar * 3 + intimpar. end. if(10-(inttot mod 10)mod 10)= StrToInt(cod[length(cod)]) then {se o digito verificador for correto então retorna a rotina verifica = true} verifica:= true else {se deu errado retorna a rotina verifica = false} verifica:= false. Quando for digitado o valor e apertar enter. Após isso criar um sistema de vendas usando esse componente que realiza a busca do produto e calcule o valor a pagar. inttot:= 0. já lê o código. intimpar:= 0. terá que ser feita a validade. preenche o código do produto. intimpar. independente se o código for por preço ou por peso de uso interno ou externo Detalhe: quando digitar o código de barra e apertar enter. {1 soma as posiçoes impares 2 soma as pares 3 multiplica as por 3 4 soma a mulptiplicaçao com as pares 5 subtrai do proximo multiplo de 10 } begin intpar:= 0.18 . end else //impar {se o valor for ompar o mesmo procedimento acima e realizado} begin intimpar:= intimpar + StrToInt(cod[i]). faz a busca. 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. 16. inttot: integer. faz o insert na tabela de itens.Exercício: Faça um componente que na propriedade código retorne o valor a ser localizado no banco de dados. end. por padrão será o 1 do item 2 abaixo. verifica o código. end. intpar. a variavel intpar recebe o proprio valor do cmpo mais o caractere daquela posicao(cod[i])} begin //par intpar:= intpar + StrToInt(cod[i]). var i:integer. function TEdtCodigoBarras.verifica(cod: string): boolean. end. .72 8: ftipo:= 8. end. end.

Quando for escolhido o tipo 13 que é o Enter confirmando.Utilizando o código de barras  Abrir componente > install component Selecione o código de barras – não esqueça de salvar. Será digitado o valor e o código de barras está com Enter automático.19 .73 preenche a descrição. 4 – Cinco dígitos que indica o valor.Quando for de uso interno fazer a verificação. 2 – Se for por preço ou peso. preenche a quantidade. quando o tipo for igual a 13. 1 . 1 digito 1 digito 5 digitos 5 digitos 1 digito Para uso externo só verifica se o código esta correto através do digito verificador. 6. 3 – Cinco dígitos que indica o código do produto. O sistema dá um aviso que o valor Vtotal não é usado e isso não tem nenhum problema para o exemplo. fazer na tabela de itens. Abra um novo sistema.5 e a tabela foi criada como tipo inteiro no campo quantidade.código 0 ou 1. faz o calculo do valor se for por peso e calcula o total. o componente é inserido e comandado um Free depois. – depois manda instalar. Para fazer a busca no banco de dados. Coloque o componente de código de barras no sistema. O componente está no código de barras. o valor e a quantidade. Por padrão a quantidade será 1(um). cada vez que for chamado.  Recompile para alterar o que já existia. Neste sistema não dá para vender por peso porque não dá para fazer abaixo de 1. Neste sistema o usuário seleciona um novo item (produto) pela descrição. No evento OnKeyPress será executado todo o tratamento quando for digitado o Enter. Em cada tela. Se tipo for igual a 13 então verifica de é de uso interno. pode ser usado um já criado em aulas anteriores – um sistema de vendas para mostrar como utilizar o componente. 5 – O digito verificador. .

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

por exemplo 789010010 depois o código 345. A programação é a mesma para fazer o exercício. já faz todo o tratamento.2. só que não foi mostrado nenhum valor. Gerar código de barras não é preocupação. Esses números são comprados. digitamos um produto que já existe. da insert na tabela. dá Locate para aquele código que esta digitado. preenche todos os dados.3. se tentar localizar do jeito que está o componente. depois que inserir o valor limpa o campo código de barras. fazer o Locate no banco de dados. o número do tipo necessário. Primeiro vai executar aquela programação do código de barras e no final ele acha o número (a herança) e executa essa herança. Vamos imaginar que o usuário digita o “2” e tecla enter (deu violação de chave) Vai mostrar na tabela o valor escolhido (código de barras). não localiza nada.75 Vá novamente no código de barras. É o jeito de usar o código de barras. Esta é a parte final da criação de componentes. Agora é só digitar o código. produto 1. Teoricamente se for digitado o código de barras. Cada vez que passar o item. tem o código de barras. da Locate e pega os demais dados do sistema. Quando comprar uma numeração.) e mais o dígito verificador. e já terá um valor la dentro. Verificando como fica agora. deveria procurar pelo mesmo na tabela de produtos. Não funcionou o código. O leitor de códigos leu o código 2 e apertou enter. Se fosse 13 dígitos iria fazer a mesma coisa. está vazio. então o usuário vai digitar um numero qualquer e clica enter.. 0003. O código vai estar pronto. provavelmente terá uma numeração 789 que o código do pais. Toda vez que pressionar enter é executado os comandos do código de barras. já tem cinco dígitos. 0002. existem muitas ferramentas para isso. mas se primeiro tiver que fazer uma programação antes de executar aquele rotina temos que colocar ele antes. insere. após adquirir o código da empresa por exemplo a empresa 1010. Talvez não funcione. os demais números são gerados seqüencialmente (0001. Toda vez que tiver que executar o código do cliente. Então vai ficar rodando sem parar até terminar a venda. porque no mínimo é oito. só que nesta tabela não tem um campo chamado código de barras. etc. digitando o código de barras. limpa e da um SetFocus. . Somente para exemplificar. Primeiro ele faz a verificação para depois trazer o valor. ele tem que encontrar esse código. Então. colocamos o comando “If”.

Esse Edit por padrão tem o numero um. //valida dados do banco ListaItem:TListItem.00).SetFocus.codbarra1KeyPress(Sender: TObject.00 reais.codigo. Existem muitos componentes prontos na internet para gerar etiquetas com códigos de barras. Break – esse comando para uma rotina e desconsidera as linhas de baixo. O leitor lê e já da o comando Insert. salva o dez no banco de dados e o Edit volta para a posição “1”. //Validando se o produto está cadastrado no banco de dados if (cod_barra <> '')and (codbarra1. Supomos que a laranja seja vendida por quilo a R$ 10. //contém o número do código de barra valor:real. var Key: Char). var cod_barra:string.Exemplo de programação de procedimento usando o componente de código de barras procedure TForm1. No trabalho é permitido deletar itens. o usuário colocou um item na compra e o cliente não quer mais o produto. Vamos supor que o zero seja para preço. if key =#13 then begin libera_valor:=true. 6. //contém o valor do produto achou:string. O cliente compra meio quilo. o tipo (0 ou 1) depois o código do produto armazenado no banco de dados (ex: 00012). Edit2. limpa e posiciona novamente para a próxima leitura. vai no Edit. Se quiser pode opcionalmente colocar um Edit com o número 1 (um). begin if key = 'q' then begin key:=#0. então divide-se o peso comprado pelo peso que é 1 quilo e multiplica-se pelo valor (0. Na geração do código de barras vai completar com zeros (00500) e por ultimo o digito verificador que será calculado pelo sistema gerando supostamente o código 20001200500-7.20 . então é permitido excluir o item. end.Text:=''.76 O número de uso interno é gerado colocando-se o código de uso interno (2). Post. cod_barra:=codbarra1.00 = R$ 5. mas se quiser passar 10 itens. O sistema multiplica pele quantidade 10. O preço é obtido no cadastro de produtos (por unidade ou kilo). coloca o valor 10 e faz a leitura do código de barras.5 * 10. codbarra1. //contém uma lista de itens comprados total:real.valido=true) then . achou:=''.

77 begin try tbl_produto. //Busca o último código inserido num_cupom:=aux1. //Contador de itens inseridos conta:=conta+1.DataSet.Text='' then Edit2.medida = True) then begin tbl_busca_val.AsFloat.AsInteger+1. tbl_pedido.CommandText:='select * from produtos where prod_cod = '+cod_barra.FieldByName('prod_valor'). end. cod_barra:=''+cod_barra+''. tbl_pedido.DataSet. tbl_pedido. tbl_pedido.Open. achou:=tbl_produto.Text:='1'.Insert.Active:=false.Active:=true. aux1:=tbl_codigoMAX.AsInteger:=aux1.Close.FieldByName('ped_cod').Active:=true.Active:=false.gtipo=2) then begin if (codbarra1. if (achou <> '') then //Produto localizado no Banco. begin // qtd automatica se o usuario nao digitar nada if Edit2. // calculo do valor do produto por peso ou preço if (codbarra1. controle:=false. tbl_produto. valor:=codbarra1. end. tbl_busca_val. // controla o insert na tbl_pedido if controle then begin tbl_codigo. tbl_busca_val.fieldByName('prod_cod').ApplyUpdates(0).peso*tbl_busca_val. . tbl_produto. if aux1=0 then //Controle se não houver pedidos no banco aux1:=1.SetFocus. tbl_pedido. end else ShowMessage('CÓDIGO DE BARRA INVÁLIDO!!!!!'). tbl_pedido.post.Active:=true.CommandText:='select prod_valor from produtos where prod_cod = '+achou.AsString. vl_tot:=0. except codbarra1.

tbl_itens.SubItems. end.add(codbarra1.78 libera_valor:=false.ApplyUpdates(0).AsString:=achou. tbl_busca_val. tbl_itens.AsFloat:= strtoint(Edit2.SubItems. codbarra1.Text:=floattostr(vl_tot). ListaItem.FieldByName('ped_cod').FieldByName('prod_cod').Add(edt_descricao.preco.Add.SubItems.Insert. ListaItem.FieldByName('prod_valor'). tbl_itens.Items. end. ListaItem.Text).text)*valor)). end else begin libera_valor:=false. tbl_itens.DataSet. valor:=codbarra1. //===================== layout da lista de itens =========================== //Montando a nota fiscal no ListView ListaItem:= ListViewNota. ListaItem.AsFloat:=strtofloat(Edit2.Text). tbl_itens.Caption:=inttostr(conta).AsFloat.Text). // salva na tbl_itens tbl_itens.AsFloat. edt_total.FieldByName('conta').Post.text)*valor. ListaItem.SubItems.SubItems. //grava dados na tabela de itens de acordo com o pedido tbl_itens. . tbl_itens. //============================================================================= end else begin ShowMessage('PRODUTO NÃO LOCALIZADO!!!!!!'). // controle da busca do valor produto se o mesmo ja não foi localizado acima if libera_valor=true then begin // busca valor do produto tbl_busca_val.Text).Active:=false. end.AsInteger:=aux1. tbl_busca_val. tbl_itens.Open.FieldByName('qtd'). codbarra1.Active:=true.Add(Floattostr(strtoint(Edit2.Text:=''.Text:=''.CommandText:='select prod_valor from produtos where prod_cod = '+achou.Add(edt_valor. tbl_itensIT_VALOR.AsInteger:=conta. total:=tbl_itensIT_VALOR.Close. ListaItem. end. end. end. valor:=tbl_busca_val.Add(Edit2.Text). vl_tot:=vl_tot+total.

Por exemplo: temos um componente de Código de Barras que não funciona corretamente e queremos desinstalar.  Clique Component > Install Component Figura 30 – Caixa de Instalação de componentes. . Figura 31 – Pacotes de componentes. É necessário dar um nome <qualquer.pás> só para aparecer a tela abaixo: Essa tela é necessária para que possamos retirar o componente desejado. no exemplo o CódigoDeBarras.79 7 – DESINSTALAÇÃO DE COMPONENTES As vezes deparamos com um componente que foi instalado e esse componente não funciona corretamente ou queremos substitui-lo.

Não tendo mais o componente CodigoDeBarras instalado. Para isso vá no Install Pakage e se tiver um dos pacotes que esteja dando problemas. . isso remove a paleta inteira. geralmente vai estar em Package – (pacotes). Se for instalada uma paleta no Delphi e não foi você que criou. O sistema pergunta se quer remover o arquivo Figura 33 – Caixa de confirmação de remoção de componentes. Selecione novamente o arquivo e clique em Ok. O pacote também pode ser removido.32). pode ser selecionado para remover. conforme mostrado abaixo: Figura 32 – Remoção de componentes. mande compilar e note que o componente já sumiu da paleta. (fig.31) e clique no botão Remove.  Clique em YES.80  Selecione o arquivo que vai ser removido (fig. é de terceiros. portanto tome cuidado para não remover outros componentes. Isso é para as paletas que o usuário criar. essa paleta também é apagada. Se remover os componentes existentes dentro de uma paleta.  Selecione o componente CodigoDeBarras e clique em OK.

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

82 Figura 35 – Relação de componentes de uma paleta. portanto não invente de ocultar um componente. se escolher essa opção. . será difícil achar o conponente oculto. Atenção: Se ocultar algum componente.

As telas estão no sistema. Muitas vezes. clicando no menu Cadastro e depois no sub-menu Clientes. imagine que um sistema tem 100 telas diferentes e ao executar esse projeto. executando o comando: Frm_Cad_Cli.83 8 – CRIAÇÃO AUTOMÁTICA DE FORMULÁRIOS. . essas 100 telas serão criadas na memória do seu computador e não serão todas usadas. Para exemplificar.Showmodal. fazendo que ocupe um espaço muito grande. Então vamos supor que temos 100 telas neste sistema. abra um projeto qualquer no sistema. o formulário foi salvo como tela de cadastro de clientes (U_Cad_Cli). Figura 36 – Tela de um projeto. Frm_Cad_Cli (não importam os nomes). em grandes projetos. A tela acima abre outra tela (formulário) para cadastrar o cliente. Temos um formulário qualquer e queremos mostrar esse formulário.

84 Figura 37 – Tela de Cadastro de Clientes... mesmo que a tela não seja usada nenhuma vez. . relacionando no campo Auto_create forms as telas que serão criadas automaticamente.. .esta tela e as outras do sistema estarão como sendo AutoCreate.  Clique em Project > Options O sistema abre a tela abaixo. Se abrirmos a tela Project Options for. AutoCreate – significa que as telas serão criadas na memória quando mandar executar.

tudo que estiver nesta lista é alocada espaço na memória e deixa pronto. podemos fazer algumas funções:  Clique em Control + F12 . Como ela está como Auto-create. Esse PC não vai executar esse sistema podendo aparecer a mensagem: “Feche um ou mais aplicativo e tente novamente”. Quando o sistema é executado. a criação das telas é rápida. só que o sistema demora mais para dar But porque primeiro tem que criar todos aqueles arquivos na memória para depois rodar ocupando espaço. vai ser criada na memória e vai ocupar espaço e toda vez que rodar o executável. Para evitar esse tipo de problema. Por exemplo: podemos ter uma tela básica como configuração do sistema que só o administrador tem acesso. por padrão ele não vai estar no menu para abertura da tela. é um problema.85 Figura 38 – Opções de projeto para o sistema. principalmente para um PC muito simples que tem pouca memória. Isso não é bom para um sistema muito grande. mas só dentro do sistema.

Aparece a listagem de tudo o que tem disponível.. Figura 40 – Tela de projeto de um sistema. Quando esse arquivo é aberto. ocupando memória entre o espaço begin. e um deles é o projeto.  Abrindo o arquivo de projeto PSistema no exemplo. é mostrada uma listagem de todos os formulários que serão criados.86 Figura 39 – Tela de Units de um projeto... por exemplo PSistema. todos os formulários...end.. .

Clientes1Click(Sender: TObject). frmClientes. Ao fazer isso. frmClientes). então fica pior ainda.CreateForm(TfrmClientes. o sistema cria na memória a tela e se chamar essa tela dez vezes.CreateForm(TfrmClientes. frmClientes). chamamos a tela. Para criar o formulário na memória: Application. end. esse formulário não vai ser criado na memória. Se deixar do jeito que está. mande criar o formulário através da linha de comando que foi tirada do arquivo de projeto. begin Application.ShowModal. dez vezes ela será criada na memória.CreateForm(TfrmClientes. Só que agora se o comando Showmodal for executado do jeito que está na programação. geralmente o nome e o tipo são iguais. frmClientes. end. Colocamos o nome do aplicativo que queremos rodar. procedure TFrmPrincipal. Criamos o formulário que é mostrado na tela e depois libera (limpa a memória). O único jeito de liberar a tela da memória é colocar o comando Free na seguinte linha de comando: procedure TFrmPrincipal. begin Application. antes chama o formulário e cria na memória. Para resolver tal situação. só usa o “T” na frente no tipo.87 Para que um formulário não ocupe a memória.  Após selecionar clique em Control + X. Cada vez que for chamar a tela. a linha de comando Application. por exemplo o cadastro de clientes do sistema. Então é o tipo e depois indicamos o nome da variável que queremos abrir. frmClientes. pelo menos não na hora que o sistema estiver rodando. selecione esse formulário. na hora que for executado o comando Show. .ShowModal. frmClientes). O sistema vai rodar sem criar o formulário.CreateForm (que é o formulário que está criando na ela) depois passa qual o tipo de formulário (TfrmClientes) e o nome (frmClientes). dará erro tentando abrir um formulário que não existe na memória. antes de dar ShowModal.Clientes1Click(Sender: TObject). o formulário não existe na memória porque foi tirada a criação dele e na hora que for clicado para chamar .Free.

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

Só que o que pode estar dentro desse bloco pode ser um pedaço do Windows. da aplicação.89 Em resumo Dentro do Principal. não são usadas todas as telas. Se executar um Destroy esse comando acha um pedaço de bloco de memória do mesmo tamanho e apaga o que tiver lá dentro. A diferença entre o comando free e Destroy é a seguinte: Free: antes de apagar ele verifica se existe o arquivo na memória.O comando Destroy Se fizermos um teste substituindo o caFree pelo comando Destroy. Esses comandos são interessantes nas aplicações porque gasta pouca memória.Free> se for Modal. então libera. Simplesmente apaga e não pergunta se está sendo usado o aplicativo. Destroy: Acha um bloco de memória do mesmo tamanho. Se não for modal. aquela programação da linha do formulário do sistema que você não quer. 8. aparentemente fará a mesma coisa. não verifica e apaga. Obs: Use o comando CTRL + X para cortar a linha de programação e CTRL + C para colar essa linha no local desejado. do Delphi. Isso evita de errar ao digitar a linha de programação. ao criar as telas também abre os bancos de dados. Na maioria dos sistemas. A própria Borland recomenda não usar o Destroy. na execução. O Free foi construído em cima do Destroy que é a classe pai. <nome do formulário. Vamos supor que existe o comando Free.1 . coloca um Show comum e no evento OnClose do formulário faça com que Action receba caFree. Nos PCs antigos a capacidade de memória é o equivalente a todas as telas abertas ao mesmo tempo. coloca ela antes do ShowModal. Em sistemas quando tem muitos banco de dados. . então vai apagar da memória o arquivo solicitado. ficando um monte de conexões abertas ligadas a bancos e o sistema fica carregado e lento.

essa rotina se duplicará ocupando espaço nesta memória. um sistema com telas. teoricamente fecharia e apagaria a DLL da memória. para isso podemos deixar dentro de uma DLL a origem da compactação. O primeiro sistema que chamar a DLL. uma rotina. Ao ativar uma DLL. VB. enxerga a DLL. roda e quando terminar de usar. Em uma DLL. Quando uma rotina é carregada na memória ao ser chamada pelos dois programas. Se um programa já tiver chamado a DLL e outro sistema também chamar essa mesma DLL (rodando em paralelo). mas o form não tem nada parecido para fazer compactação de dados. diferentes. chamamos essa tela. formulários. quando um dos programas terminar a execução. imprimir.DLL DLL (Dynamic Link Libraries) – Bibliotecas de vinculação dinâmica. Cada vez que for necessário. Todo sistema de programação que trabalha com Windows. num primeiro momento ela não fica na memória. Ex: Temos dois programas na memória. um programa feito em Delphi e outro em “C” e precisamos comunicar um com o outro. só que o Windows verificando que a DLL ainda está sendo usada. um monte de procedimentos e funções que pode ser compartilhada com outros procedimentos do sistema. O que fazer? Colocamos essa rotina inteira dentro da DLL. O programa “A” poderia ser feito em Delphi e o programa “B” em linguagem “C”. carrega-a na memória ( por isso que é dinâmica) . vai criar uma única cópia na memória comunicando-se com vários sistemas. ai então tira a DLL da memória. As vezes algumas rotinas são comuns para os dois programas: abrir arquivo. executa. etc. . O ideal é criar uma única cópia da rotina na memória e quando for chamada por outro programa. Pode-se então perder um tempo maior. faz o que precisa e volta para o sistema que a chamou. Vamos supor que temos um sistema para fazer a conversão de imagens. sai da memória não ocupando espaço. rodando a mesma rotina – uma rotina que serve para qualquer sistema de desenvolvimento. Dentro de uma DLL vamos encontrar um monte de rotinas. não vai criar uma segunda cópia. Através dos Forms um programa em cada. podemos ter rotinas. Vamos supor que temos um bom componente que faz a compactação. podemos usar uma DLL para fazer essa comunicação desses processos ou acessar uma rotina que às vezes a linguagem não permite. não é carregada.90 9 . pode ser programado um sistema inteiro. A grande vantagem da DLL é o fato dela compartilhar dados. espera o outro programa terminar. Uma DLL é um arquivo executável com várias rotinas. seria igual a uma Unit. Outro exemplo: Temos um programa “A” e um programa “B”. calculo de uma função matemática. desenvolver todas as rotinas que são mais usadas e deixar dentro de uma DLL e quando utilizada.

A vantagem é a manutenção depois. Tanto o programa em pascal. imprimir.91 A DLL é compilada num arquivo exe e na hora da compilação. etc). essa atualização é feita somente dentro da DLL. O Windows procura primeiro a DLL no diretório do executável (onde fica o arquivo exe) e se não achar então procura dentro das pastas do Windows. um programa que calcula o código de barras. por exemplo: se tiver um sistema em Visual Basic e outro em Delphi e queremos comunicar os dois sistemas de alguma forma. Para dois sistemas diferentes que utiliza essa DLL é só fazer a manutenção dentro da DLL que os dois sistemas ficam atualizados. a programação é igual. O sistema fica incompleto. mas tabela é complicado. . dentro é a mesma coisa. Se estiver sendo executadas na mesma memória. porque tem várias rotinas. quanto o programa em form (do oracle) também vai usar. uma maneira de comunicação. pode ser feito via DLL. editar. tem alguma rotina que faz um calculo complexo e é muito utilizada.A DLL fica armazenada ou no diretório que fica o executável (exe) ou no diretório System do Windows (System32). Cada vez que precisar de duas aplicações diferentes. separada uma da outra. Não é recomendável colocar um banco de dados dentro de uma DLL. chamando só a rotina que deseja (inserir. colocamos um valor nessa DLL e depois pedimos para carregar para Leitura. Não há diferença entre uma DLL e um exe. enfim um sistema inteiro dentro de uma DLL. Podemos colocar essa rotina dentro de uma DLL. Em vez de criar um componente. e aparece uma mensagem de DLL não encontrada.1 . Cada vez que abrir uma instancia da tabela. gera um executável. a DLL tem que procurar as rotinas. o sistema não funciona. Toda a programação fica dentro da DLL. Podemos ter uma DLL com as principais rotinas que queremos trabalhar. ele compartilha dados com outro. a tabela é aberta localmente. . um feito em oracle e outro feito em Delphi. Se necessário fazer uma atualização no sistema. Pode compartilhar dados com o valor de uma variável. 9. Se precisar compartilhar um código em uma empresa que usa dois sistemas.Problemas com a DLL 1 2 – Se apagar a DLL. O exe. Vamos supor que em sistema. para o sistema seria como duas tabelas independentes. a diferença é o cabeçalho quando o exe indica que será executado do começo ao fim seqüencialmente. programação de uma calculadora. podemos usar uma DLL. na primeira linha já executa. podemos programar dentro de uma DLL. O calculo do banco de dados é um calculo externo. Quando abre. A DLL não faz isso. então é complicado compartilhar dados pela tabela. Cada vez que precisar passar um parâmetro.

. Acessa uma porta da máquina. Se tiver rodando em rede e tiver que atualizar o sistema. Para programar uma DLL é preciso algumas regras: . desde que o outro compilador a entenda (como cdecl. Também pode ser usada outra convenção de chamada. uma DLL que roda em rede. Essa DLL é alocada num servidor e quando é chamada. . Isto torna a rotina visível para o mundo exterior.Outros tipos de parâmetros de uma DLL devem ser os tipos-padrão do Windows (em sua maior parte tipos de dados compatíveis com a linguagem C). Funciona como multiplataforma do mesmo jeito de uma DLL comum. a menos que pretenda usar a biblioteca apenas em outros programas em Delphi. 9. o que é necessário é a conexão com o servidor.As funções exportadas também devem estar declaradas como stdcall para usar a técnica de passagem de parâmetros padrão do Win32 em vez de passagem de parâmetros de registro otimizado (que é o padrão do Delphi.Ela precisa estar listada na clausula exports da DLL. Sempre que um aplicativo carrega uma DLL.Uma DLL pode usar dados globais que não serão compartilhados pelos aplicativos que estão fazendo a chamada.92 3 – A DLL só roda dentro da própria máquina. chama a rotina e executa dentro da DLL.Como construir uma DLL Execute o seguinte procedimento:  File > New > Other > DLL Wizard . ela armazena os dados globais da DLL em seu próprio espaço de endereçamento. A vantagem é a manutenção que pode ser feita uma única vez no servidor e o desempenho depende da rede. Para solucionar esse problema é usada o Web Service. terá que ser atualizada em todas as máquinas. Ele cria um servidor e só fornece serviços. . que é o padrão em compiladores C).As biblioteclas do Delphi devem capturar todas as exceções internas. O Web Service roda em cima de um módulo chamado Swap. sua execução ocorre dentro desse servidor.2 . . um protocolo.

93 Figura 41 – Caixa de projetos – Novos itens.  Clique em OK Aparecerá o Form mostrado abaixo: Figura 42 – Programação inicial de uma DLL A primeira coisa a ser feita após abrir o formulário da DLL é salvar:  Crie uma pasta com o nome DLL dentro da pasta alunos – Dentro da pasta DLL crie outra chamada DllOperações. .

Pode ter 100 rotinas mas se for especificada 5.res) colocamos os procedimentos usados na programação. Queremos disponibilizar outra forma e colocamos o comando stdcall na frente da função: STDCALL . begin soma := (A+B).usa a técnica de passagem de parâmetros padrão do Win32 em vez de passagem de parâmetros de registro otimizado. No DLL não tem os campos Private. protected ou published e quando não queremos que essa rotina seja visível. stdcall. vamos construir uma DLL para fazer as operações de soma e dividir. declaramos no campo Public. para deixar uma rotina visível . 9.B:real):real. No começo do programa a DLL e as rotinas tem que serem especificadas para utilização e liberadas no sistema. Atenção: A rotina criada em uma DLL é diferente. Temos que definir se queremos deixar ou não esta rotina visível para o mundo externo. .O project é aquele que gera um executável. Agora é necessário colocar os procedimentos (as rotinas compartilhadas). essa rotina não é visível para o exterior. só essas cinco serão liberadas. public. mas se quisermos que a rotina seja vista externamente temos que acrescentar um commando chamado Export e se esse comando não for colocado à frente da declaração.Programação das rotinas Como exemplo. e Casesensitive no nome da rotina porque herda da linguagem “C” e grava no formato C de programação. . Antes do símbolo ($R *.94 Salve o projeto  File > Save as  Pasta DLL > Pasta DllOperações > nome DllOperaçoes Note que não esta sendo colocada a extensão no nome do arquivo e se reparar o formato da DLL é Project e não uma UNIT. Após a declaração USES e antes do símbolo ($R *. export.3 .res) coloque as seguintes linhas de comando para a função soma: function soma(A. a DLL na verdade é um executável especial. declaramos no campo Private. Quando trabalhamos com componentes. Passamos para essa rotina dois parâmetros A e B e essa função vai retornar em real. Neste espaço teremos as rotinas compartilhadas.

end. depois de terminada a rotina antes do ultimo begin. end. begin divisao := A/B.B:real):real.Após salva a programação da DLL. Este comando exports colocado no final da programação é diferente do comando exports anterior – Algumas linguagens de programação mais antigas. o delphi lê direto pelo nome da rotina não usando esse índice. exports divisao index 1: begin end. Por questão de compatibilidade.95 end. mas ela ainda não existe fisicamente .. comparando se o segundo elemento é igual a zero. podemos fazer um tratamento. acessar função “1”. stdcall. end. Altere as linhas de comando da function divisão: function divisao (A.. Na linguagem que for feita em Delphi. então temos que criar um index para que seja possível achar esse caminho.B:real):real. Esse índice é só para compatibilidade de aplicativos mais antigos. não trabalham com o nome da rotina. 9. begin if (B=0) then divisao := 0 else divisao := A/B. Para que não fique só dividindo um numero pelo outro. export.Gerando a DLL Até agora só foi feita a programação dessa DLL. export. stdcall.: acessar função “0”. mas sim com o numero da função: Ex. {$R *.4 . faça o seguinte: Deve ser gerada uma função Export + nome da rotina + índice.res} exports soma index 0. vá pelo seguinte caminho:  Project > Buid DllOperacoes . Agora criamos a rotina para a divisão: function divisao (A. então a divisão recebe zero. Se B for igual a zero.

This applies to all strings passed to and from your DLL--even those that are nested in records and classes. Ao clicar no Buid DllOperações e se tudo estiver certo. //rotinas usadas nos aplicativos function soma(A. Classes. ShareMem is the interface unit to the BORLNDMM.96 Observação: Este projeto não é executável.DLL shared memory manager. } uses SysUtils. verificaremos que no diretório que foi salvo existe um arquivo compilado e que foi gerado a DLL. é por isso que temos que usar essa opção. 9.5 . { 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. To avoid using BORLNDMM. Figura 43 – Compilação da DLL. which must be deployed along with your DLL. pass string information using PChar or ShortString parameters. export. é só um aviso. no caso do Delphi não é.Programação da DLL library DllOperacoes.DLL.B:real):real. stdcall. Se a DLL for gerada. . é compilado e mostra que o símbolo Index é especifico para a plataforma.

três Labes e dois botões. 9. end. 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 .  Crie uma nova pasta dentro da pasta DLL com o nome de formulários. begin end. stdcall. function divisao (A.res} exports soma index 0.B:real):real. begin if (B=0) then divisao := 0 else divisao := A/B.6 . {$R *.97 begin soma := (A+B) * 1.Fazendo um aplicativo para testar a DLL Feche a programação da DLL depois de salvar.10. Crie uma nova aplicação:  File > New > Application Coloque no form três Edits. end. export. exports divisao index 1. Nossa aplicação é uma calculadora bem simples para poder acessar a DLL.

 File > Save Project as > C:\Alunos\DLL\DllOperacoes – nome P_Calculadora. então podemos copiar nossa DLL neste arquivo (Windows Sys32) que também funciona 9. Só tem dois campos que podem estar: ou dentro da pasta do executável ou dentro da pasta do Windows (Windows Sys32 onde estão as DLLs).Para usar a DLL Na programação temos que declarar as rotinas. Da pasta da DLL da implementação. porque na hora que fizermos a implementação. Salve o Formulário na pasta formulários:  File > Save as > C:\Alunos\DLL\Formulários – nome: Frm_Calc.6.98 Figura 44 – Formulário de uma calculadora simples.1 . então tem que estar ambos na mesma pasta. Para usar uma DLL o arquivo do projeto criado tem que estar salvo na mesma pasta que foi gerada a DLL. o sistema não localiza sozinho. Se quiser por exemplo salvar em outra pasta então copiamos o arquivo através de um Path e copiamos a DLL na pasta que vai ficar o executável do sistema. Salve o projeto na mesma pasta da DllOperacoes. . porque o arquivo DLL vai gerar um executável. vamos disponibilizar as rotinas (aquelas com os mesmos nomes que foram colocadas na DLL.

stdcall. 2. A Pilha: Cada vez que chamamos uma rotina. agora é só utilizar. guarda numa pilha. Z := soma(X. Podemos armazenar primeiro o nome da rotina e depois os parâmetros. Y := StrToFloat(Edt_Op2.Btn_SomaClick(Sender: TObject).Z:real. begin X := StrToFloat(Edt_Op1. Podemos no mesmo sistema chamar várias DLLs. porque na hora que digitar a rotina o sistema pode entender errado. verifica o estado atual do sistema.Se tivermos a fonte. ou primeiro os parâmetros e depois as rotinas. Coloque as seguintes linhas de comando na programação do botão soma. Para obter o caminho que queremos existe três formas: 1. Edt_Tot.  Clique em F12 para abrir o modulo de programação do form. o sistema empilha a Dll chamada e recusa a rotina e quando terminar a rotina atual.Text).Y). no caso de uma DLL mostra o cabeçalho da DLL.Pela Internet baixamos o software de visualização da DLL. Então. 3.  De duplo clique no botão soma.stdcall. Cada vez que chama uma rotina. Depois de definirmos a rotina.99 Ao invés de escrever export. Atenção: Se a rotina for digitada errada (porque é casesensitive) não vai funcionar. temos que dizer que é da DLL é que virá os dados. Coloque as seguintes linhas de comandos: function soma(A. Quando for clicado o botão de soma.Text := FloatToStr(Z): end. procedure TFrm_Calc.Text). então abrimos e olhamos o caminho.external 'DllOperacoes.dll'. o sistema executa um shunt (desvio).B:real):real. Colocamos então a chamada external. function divisao(A. desempilha e volta ao estado original do sistema.Y. . pega os dois valores e atribua dentro da soma.B:real):real. A diferença é como o armazenamento é feito. com as rotinas disponíveis. a ordem muda de uma linguagem para outra. Esse software. Estamos padronizando a entrada.dll'. como não vamos exportar nada e estamos trabalhando com o caminho de fora. var X.Pela documentação do fabricante da DLL. depois executa a rotina.external 'DllOperacoes.

Essa rotina é parecida com a anterior. o resultado é “0” (zero). através das linhas de comando abaixo: Z := soma(X.Btn_DivideClick(Sender: TObject). temos que converter de float para string e atribuir dentro do Edit.6.Y).2.Text := FloatToStr(Z): O que esta sendo feito: Estamos chamando uma rotina que não programamos em nosso projeto calculadora. passamos os valores dos parâmetros. Faça o mesmo para o botão Dividir.Text := FloatToStr(divisao(StrToFloat(Edt_Op1. . o sistema já reconhece a rotina que foi declarada na DLL. a única diferença é que foi passado o primeiro e o segundo parâmetro (Edt_Op1 e Edt_Op2) convertidos para uma string. 9.Programação do botão Divide procedure TFrm_Calc. O comando é o mesmo. são convertidos e o resultado é mostrado no Edt_Tot. 9.6. Se for divisão por zero e como foi efetuado um tratamento. o segundo operador. será feita em uma única linha. Na hora que o projeto precisar acessar a rotina dentro da DLL e executar. begin Edt_Tot.100 Como os tipos são diferentes fazemos a conversão de String para Float.(StrToFloat(Edt_Op2. Os dois valores entram na rotina. end.2 . Na programação chamamos a rotina da DLL para fazer o calculo da soma para mostrar o valor no sistema.Text)))).A rotina Divide.  Salve o projeto e compile para executar. A rotina divide passa como parâmetro o primeiro operador.1 . Teste colocando os valores nos operadores. a única diferença é que não vai ser criada um bando de aliases.Text). Edt_Tot. Se a declaração do caminho foi feita corretamente. Clique no botão soma e verifique.

begin soma := (A+B) * 1.B:real):real. . Altere a programação da DllOperações.10. function soma(A. cobrar 10% a mais em cima do calculo efetuado. Atenção: Não é necessário recompilar de novo o Projeto Calculadora. Salve e execute novamente o sistema da calculadora. stdcall. por exemplo. end.101 Figura 45 – Projeto calculadora em execução através de uma DLL. export. Se vários programas executassem a mesma rotina e precisasse ser feito uma mudança na programação. Figura 46 – Execução do projeto calculadora com novos parâmetros. Qualquer alteração feita na DLL não precisa recompilar o projeto vinculado. esta mudança é realizada uma única vez na DLL utilizada pelos forms.

 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 aplicação. Coloque no Form os seguinte componente: um Label. Vamos colocar dentro da DLL esse formulário inteiro para poder chamar a aplicação.Como criar formulários dentro da DLL. Podemos colocar componentes visuais dentro de uma DLL. Queremos chamar esse formulário dentro de uma DLL. Fazemos a manutenção ou alterações dentro da DLL. Assim podemos separar o sistema em várias DLLs e só mandamos a DLL que foi modificada.102 Desse jeito podemos ter todas as rotinas dentro de um sistema e colocamos dentro de uma DLL. Propriedades: Caption Teste Name Frm_Teste Lb_Nome Form1 Label1 Figura 47 – Formulário para teste Dentro desse formulário passaremos um parâmetro para ser exibido neste form  Salve o formulário no diretório C:\Alunos\DLL\FormTeste\Formulários com o nome de U_Teste Não salvaremos o projeto ainda que será explicado do porque logo mais.7 . isso ajudaria na manutenção. Exemplo: Num formulário colocamos um Label e vamos chamar esse Form. 9. .

Messages. interface uses Windows. que fizesse cálculos complexos que o Force Reporte não tem e queremos disponibilizar essa tela no aplicativo.Criando uma DLL para chamar este formulário. Salvamos o formulário e fechamos a aplicação. StdCtrls.Programação da Unit U_teste: unit U_Teste. 9. type TFrm_Teste = class(TForm) Lb_Nome: TLabel. SysUtils. var Frm_Teste: TFrm_Teste.8 . implementation {$R *. Ele não tem as tabelas e faz de conta que a Label fosse uma coisa do outro mundo. Variants.  File > New > Other > DLL Wizard > OK Após abrir o formulário da DLL salve no diretório da pasta FormTeste.  File > Save as > C:\Alunos\DLL\FormTeste com o nome de FormTeste .  File > Close. Passamos como parâmetro o nome que será exibido no Form. private { Private declarations } public { Public declarations } end. Forms.103 Por exemplo: Vamos supor que queremos chamar a DLL dentro do Force Reporte. 9.dfm} end. Graphics.9 . Classes. Dialogs. Controls.

frm_teste.Lb_nome. O path tem que ser colocado inteiro porque esse formulário não está no mesmo diretório da tela que foi chamado. No exemplo estamos forçando o sistema encontrar o path (caminho) de onde queremos compilar. uses SysUtils. var frm_teste:Tfrm_teste.104 9. Teremos um procedimento protegido chamado procedure ChamaTela procedure chamatela(nome:string).createform(TFrm_teste. begin application.Programação das rotinas. como não foi criado na memória.Caption:= nome. então é necessário criar um formulário para chamar o Frm_teste.pas'.1 . Como essa rotina esta dentro de um diretório colocamos o caminho: u_teste in 'C:\Alunos\DLL\FormTeste\Formularios\u_teste. Cada vez que for chamado o procedimento ChamaTela passamos como parâmetro o nome que queremos mostrar na String frm_teste. export. Para chamar o formulário. Para chamar esse formulário. Agora temos que criar na memória este formulário. usamos o comando Uses com o nome da Unit. stdcall. Este criação é feita com os comandos: . criamos uma variável chamada Frm_teste do tipo Tform_Teste: var frm_teste:Tfrm_teste.Showmodal. frm_teste. Se tivesse os dois no mesmo diretório era só colocar u_teste que os dados serão encontrados.Lb_nome.pas'. No caso Uses U_Teste. Classes.frm_teste). Para chamar uma rotina que foi declarada em outro local. na hora da compilação.free.forms. vai dar erro.showmodal. u_teste in 'C:\Alunos\DLL\FormTeste\Formularios\u_teste. end.9. frm_teste.Caption:= nome. se fizermos o comando Frm_teste.

Se não temos uma aplicação para ser criada na memória.res}colocamos o comando: exports chamatela index 0. para chamar o formulário que geralmente se encontra fora da pasta.10 . which must be deployed along with your DLL. então criamos a variável. Esse comando não é obrigatório. ShareMem is the interface unit to the BORLNDMM.forms. pass string information using Pchar or ShortString parameters. { 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.DLL shared memory manager. u_teste in ‗C:\Alunos\DLL\FormTeste\Formularios\u_teste. porque o sistema quer que compile o projeto testes para gerar o arquivo DCU. É somente para alguns programas que usam Windows.105 application.DLL. Depois de criado e mostrado o formulário na tela temos que colocar o comando Free para liberar esse formulário após executado. Logo abaixo da programação após o símbolo {$R *. Classes. stdcall. chamamos o formulário e depois liberamos esse formulário. Para sanar isso abra uma nova tela e compile para que o sistema gera a DCU. O que foi feito: Foi criada uma variável.  Project > Build FormTeste Neste ponto dará um erro. procedure chamatela(nome:string). To avoid using BORLNDMM. } uses SysUtils. frm_teste.createform(TFrm_teste.showmodal. 9. var frm_teste:Tfrm_teste. Compile o programa. export. . This applies to all strings passed to and from your DLL—even those that are nested in records and classes.Programação da DLL library FormTeste.pas‘.  Adicione ao projeto essa tela: C:\Alunos\DLL\FormTeste\Formulários Agora volte à DLL e compile.frm_teste).

Este sistema vai chamar o outro formulário. end.11 . . {$R *.res} exports chamatela index 0. Quando clicar no botão.free.  C:\Alunos\DLL\FormTeste\Formulários\U_ChamaTela.showmodal. 9. frm_teste.106 begin application.Criando outro Projeto para Teste Agora temos que criar um outro formulário com um botão: 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 aplicação criada primeiro temos que salvar dentro do mesmo diretório.frm_teste). frm_teste.Lb_nome.Caption:= nome. vai chamar a nova tela através da DLL. frm_teste. begin end.createform(TFrm_teste.  File > Save as > salve dentro do diretório onde está a DLL.

stdcall. Chamamos a outra tela.Projeto Chama tela compilado.  Salve > Compile e execute. Então criamos um procedimento chamatela que passamos um nome que queremos que apareça no Label do form. procedure TFrm_ChamaTela.Btn_TelaClick(Sender: TObject). nome etc. a DLL chama a tela abaixo: Figura 50 – Tela aberta através de uma DLL. end. procedure chamatela(nome:string). Figura 49 . passando como parâmetro o nome que queremos que apareça na tela – pode colocar qualquer mensagem.dll'. Ao clicar no botão acima. external 'formteste. O que acontece: .107 Para chamar a tela colocamos na programação completando a palavra external o nome da DLL. begin chamatela('MENSAGEM').

que poderíamos passar como parâmetro o nome da tabela. Dialogs. 9. var Frm_ChamaTela: TFrm_ChamaTela. end. stdcall. Messages. implementation procedure chamatela(nome:string).108 Estamos mudando um formulário com Showmodal como se estivesse usando o aplicativo. SysUtils. . Graphics. Geralmente em uma DLL tem várias telas.dfm} procedure TFrm_ChamaTela. No formulário criado poderia ter uma table. end. Forms. faz uma consulta e mostra o valor. Classes. neste caso o sistema busca a tabela.12 .Btn_TelaClick(Sender: TObject). {$R *. procedure Btn_TelaClick(Sender: TObject). A única diferença que esse form interno esta dentro de uma DLL. private { Private declarations } public { Public declarations } end. StdCtrls. Podemos fazer uma tela de cadastro padrão e passamos como parâmetro o tableName da mesma forma que passamos o nome como parâmetro. Variants. external 'formteste. begin chamatela('MENSAGEM').dll'. procedure FormCreate(Sender: TObject). type TFrm_ChamaTela = class(TForm) Btn_Tela: TButton. Controls.Programação da Unit Chama tela unit U_ChamaTela. interface uses Windows.

Na hora que clicar em cima do campo. por exemplo: Nome gerar essa tabela de busca. No LooKup digita o nome e manda buscar. Essa DLL deve conter uma tela de busca em uma tabela qualquer. Clicando na tela (no campo) passa como parâmetro a tabela que deseja carregar.Exercício: Faça um sistema que contenha uma DLL. Nessa DLL vai ter uma tela inteira que tem a propriedade como status e botão de busca. na hora que clicar no registro retorna a posição do registro lido. Na busca aparece uma grid que exibe os dados.109 9.13 . Num campo. A tela não pertence ao sistema. A função retorna a posição da tela. retorna o código lido. . Vai chamar a DLL através de uma Function e passa como parâmetro a tabela desejada.

A estrutura é vista abaixo: . TIBtable (interbase) ou TSimpleDataSet (ibexpress)) e modifique este componente de tal forma que ao salvar (após aplicar um post) algum dado ele execute automaticamente um ApplyUpdates no banco. pesquisar o código na tabela indicada e retornar o valor do produto (aplicando a taxa_de_ganho). Pesos: Componente de banco de dados Dll Se achar necessário .PROVAS APLICADAS 10. Caso seja um numero. a tabela a ser pesquisada e a taxa. A taxa de ganho é um percentual sobre o valor do produto que o usuário irá informar.Prova B Tempo: 60 minutos. grava o produto(código).Banco: Cod_Prod Valor_Prod Descr_Prod QTD_PROD N N A[30] N 3. 1) Crie um componente derivado do componente DBedit que ao colocar no sistema e pressionar a tecla enter. recebe false.5 3. ela cria o seu próprio código de 13 dígitos: inicia com 2 (interno). iremos passar o código do produto. Além disso. Se tudo der certo. o componente deve contar o numero de vogais do texto e setar a propriedade vogais com o numero delas.2 .1 . ele verifique se o conteúdo é uma string e deve colocar a propriedade tipo para string. tipo recebe num. quantidade (comprada) e valor . O sistema irá chamar a rotina. Só que em vez de usar o padrão.Prova A Tempo: 60 minutos. 2) Imaginemos que uma empresa deseja implantar código de barras interno. a propriedade salvo recebe true. Se der errado.110 10 . 1) Crie um componente descendente de um banco de dados (por exemplo.5 2) 10. Nesta dll. Criar uma dll com uma rotina de calculo do valor de venda (valor_prod * (1+ taxa_de_ganho)).

Se o usuário realizar um click sobre o componente.5 . retornar o valor da compra Não esqueça de criar o programa para demonstrar o uso da dll. Caso contrário deve ficar com false.Prova C 3) Crie um componente descendente de um SpeedButton e modifique este componente de tal forma que ele possua uma propriedade chamada apertou. 4) Pesos: Componente de banco de dados Dll 3.5 10. Além disso. por padrão o botão deve ser do tipo flat e as figuras devem ser colocadas no topo do botão. Criar uma dll com uma rotina de calculo do digito verificador para o código EAN 13. esta propriedade deve ficar com true. Também deverá ser criada a tela para entrada do código a ser gerado o digito (dentro de uma dll também). Pede-se: Criar uma rotina em DLL.5 3.111 2 ___ ___ __ ___ _ onde Digito verificador com 1 digito Código do produto com 3 dígitos Quantidade com 3 dígitos Valor com 5 dígitos Ex: 2 034 003 00500 3 indica: Comprou 3 unidades do produto 034. Você deve informar o código de barras e ela retorna true ou false se deu certo ou não. que dado o código de barras.5 3.3 . Pesos: Componente de banco de dados Dll 3. a um valor de 5 reais por unidade.

5 . a um valor de 5 reais por unidade. isto é. fica vermelho.112 10. 2) Imaginemos que uma empresa deseja implantar código de barras interno.5 3. se estiver com preto. Se estiver vermelho. Criar uma rotina que dado o código do produto. A estrutura é vista abaixo: 2 ___ ___ __ ___ _ onde Digito verificador com 1 digito Código do produto com 3 dígitos Quantidade com 3 dígitos Valor com 5 dígitos Para a prova. ela deve gerar o código de barras com 13 dígitos e retornar este código. A seqüência de ver preto ou vermelho. ele deve trocar a cor da fonte do texto. quantidade e valor. Pesos: Componente de banco de dados Dll 3. Assumir um valor fixo para este campo (por exemplo. não é necessário gerar o digito verificador.4 . vai para o preto.Prova D componente e a propriedade cores estiver com true. todos através de parâmetros. Só que ela deseja gerar o código. Parâmetros: Código do produto (inteiro) Quantidade (inteiro) Valor (real) Não esqueça de criar o programa para demonstrar o uso da dll. o valor 7) Ex: 2 034 003 00500 7 indica: Comprou 3 unidades do produto 034.

. A maioria das impressoras fiscais tem o mecanismo de impressão por agulhas (sistema matricial). 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. .Contador de Ordem de Operações (COO) e Contador Geral de Comprovante Não Fiscal (GNF). Se uma impressora for comprada de terceiros. A comunicação da impressora fiscal com o micro é através da porta serial RS232 e utiliza o protocolo RTS/CTS. embora existam outros fabricantes. O padrão de impressora que utilizaremos neste estudo é da Bematech.A identificação do cliente é opcional. 2ª Seção – Corpo do cupom No corpo do cupom fiscal que consta os itens da venda é subdividida em outros segmentos: . que utiliza papel de impressão especial e tem apenas uma via. deve estar lacrada.113 11 – IMPRESSORA FISCAL O emissor de cupom fiscal (ECF). o representante que vendeu a impressora. . A primeira parte que veremos é a instalação de uma impressora fiscal. 11. endereço. mas já existe no mercado a impressora térmica. para que a receita possa liberar a impressora zerada e com os dados acima. endereço. Toda impressora fiscal deve ser lacrada pela Receita Federal.1 . CNPJ e Inscrição Estadual do Estabelecimento Comercial.Numero do item (3 dígitos).Razão Social. Para evitar sonegação. CNPJ. levada até um posto da Receita Federal para que seja zerada e substituído os dados da empresa anterior e receber um novo lacre. configuração e zeramento da impressora. Quando for adquirida uma impressora fiscal temos que fornecer para a Receita Federal ao dados tais como: Razão Social. . a Receita Federal exige a impressora fiscal para quem trabalha com vendas. conhecido como Impressora Fiscal é um equipamento de impressão de cupons que substitui a Nota fiscal ao consumidor final que deve atender ao convenio ICMS 156/94 bem como suas atualizações.Data e hora do inicio da impressão do cupom.Cabeçalho .Cupom Fiscal O cupom fiscal é composto das seguintes seções: 1ª Seção .

.Troco se houver e mensagem. uma terceira linha é impressa contendo o valor do desconto.Esta operação bloqueia o ECF. Situação tributária Valor total.2 .Logotipo BR.Data e hora do término da impressão.Número da versão do software do EPROM. mas quando emitido. .114 Código do produto ou serviço (13 dígitos).Informações do subtotal.O Grande Total (GT) criptografado. 11.Impresso nome do fabricante da impressora fiscal. . . . . .Relatórios emitidos pela Impressora Fiscal Leitura X. grava as informações do Grande Total na memória fiscal. imposto a ser pago(IPI.No final do dia ou quando for fechado o caixa é retirada a redução Z. Quantidade (inteira ou fração). por isso é tirada uma única vez no dia porque sua liberação só acontecerá quando da virada da meia noite. Descrição do produto ou serviço (29 caracteres). Valor unitário (duas ou três casas decimais).Modelo da impressora.Descontos ou acréscimos.Contém informações do movimento diário. 3º Seção – Fechamento Na terceira seção é impresso o fechamento: .Impresso no inicio do dia de trabalho e quando for trocada a bobina. . Redução Z.Número de série do ECF.Valor total.Número da loja e do equipamento. . Desconto – se houver desconto. . 4º Seção – Final . . ICMS) – é um resumo gerencial.Forma de pagamento . .A Leitura X pode ser feita várias vezes por dia. .Parecido com a Leitura X. . Resumo de tudo que foi vendido no dia: quanto que foi vendido do produto. . . .

a Redução Z será gerada automaticamente. Se não for efetuada nenhuma venda no dia a Redução Z não será emitida.Os Arquivos de Configuração. clique no link produtos -> impressora fiscal. Figura 51 – Tela do site www.  Manual > Drivers de outros arquivos > selecionar Windows.3 . entre no site do fabricante Bematech (www. 11.com.br.115 Se a Redução Z não for feita após o término do trabalho e for desligada e ligada apenas após a virada da meia noite. - A bobina da impressora matricial é em duas vias. sendo a primeira via entregue ao cliente e a segunda é rebobinada na própria impressora. A impressora térmica. Para serem baixados os arquivos de configuração.bematech.bematech. .com. trava a emissão de novos cupons e destrava logo em seguida continuando o trabalho normalmente.br/desenvolvedores). Dentro da impressora fiscal podemos escolher o modelo da impressora.  Em drivers > Downloads. no caso vamos escolher o modelo MP-20FI II. só tem uma via. como foi dito anteriormente.

br Arquivo txt baixado do site da Bematech: ========== LEIAME.ini -> BemaMFD.Exemplos de integração Baixe o exemplo de integração Delphi 5 completo com código fonte que será utilizado no projeto do site www.dll -> BemaFI32. Se for Windows 95.116  Efetuar o Dowload da biblioteca BEMAFI32. Se for Windows 2000.dll No diretório de sistema de seu Windows.tlb -> DAO350. NT ou XP salve em "\WinNT\System32" Caso você utilize a função Bematech_FI_RelatorioSintegraMFD. Consiste de um software que roda em ambiente gráfico windows e executa as operações de uma Impressora real que deve ser utilizado somente na fase de desenvolvimento do projeto.dll -> MSJET32. escolhendo o sistema operacional windows. 11.O emulador. execute: REGSVR32 /S DAO350.5 . Após o download faça o instalação do emulador. NT ou XP). é necessário que os arquivos DAO350.bematech. Para isso.com. 98 ou ME salve em "\Windows\System".DLL .4 .dll -> DAO2535. 11. A aplicação precisa chamar essas funções com os devidos parâmetros e a DLL se encarrega de enviar os comandos corretos para a impressora.DLL e MSJET35.DLL sejam registrados. Baixe o aplicativo no site da Bematech clicando no link desenvolvedores > downloads e drivers. Esse arquivo deve ser baixado e gravado na pasta C:\windows\system(para windows 95/98/ME) ou C:\winNT\system32 (para windows 2000.DLL REGSVR32 /S MSJET35.DLL. que gera os registros do Sintegra nas impressoras fiscais MFD MP-2000 TH FI e MP-6000 TH FI (somente). Ferramenta desenvolvida pela Bematech e gratuita.TXT ========== Salve os arquivos: -> BemaFI32.

. . . . .----------------------------------------------------------------------------. Basta dar um duplo-clique para abri-lo. BEMAFI32. .br ------------------------------------------------BEMATECH .Mar/2006 . . Neste arquivo. Ver 5. você poderá entrar em contato com o nosso suporte técnico no telefone: 0800 644 2362 ou por e-mail: suporte@bematech. . além de exemplos em Visual Basic e Delphi. MP-50 FI da Bematech e Y-8000 e Y-8500 da Yanco . MP-40 FI II. Para esclarecer suas dúvidas em relação ao uso da DLL.com. [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] . MP-25 FI. .0.117 O arquivo BEMAFI32. você encontrará todas as explicações referente as funções da DLL.0. . que será fiscalizado pela receita .DLL.INI . MP-6000 FI TH. MP-20 FI II. . . Arquivo de inicializacao da dll BemaFI32 para as impressoras fiscais .com.CHM é o arquivo de ajuda da BEMAFI32. MP-2000 FI TH. .br Dentro da impressora fiscal existe uma memória EPROM que guarda todos os dados que gera o cupom fiscal.----------------------------------------------------------------------------.0 .bematech.NOSSO NEGÓCIO É AUTOMAÇÃO COMERCIAL!!! Fonte: www.

Tudo isso é opcional. assim teríamos um monte de cópias espalhadas no sistema. Só que Jose da Silva me é o BAR DO ZÉ. qual a porta a ser utilizada. ele abrirá um bloco de notas que representa toda a configuração da Impressora fiscal (o path. etc. nome da cidade. porque para acessar a DLL. Abrir a pasta BEMAFI32.DLL). Por Exemplo: O nome da empresa é José da Silva ME.coluna do valor numerico . Ela só trás gravado o nome da empresa registrada e seus dados.coluna extenso 1 . Esta pasta armazena todas as DLLs do sistema.DLL – Copiar todos os arquivos com exceção do arquivo Bemath 32. | +---------------------------------.DLL e REGSVR32 /S MSJET35. esta tem que estar no mesmo diretório do executável ou na pasta SYSTEM32. descompactar as três pastas (Exemplo Delphi 5 completo. Estes comandos registram os arquivos Bematech. Este arquivo é o arquivo de Quando der duplo clique em cima deste arquivo. se tem gaveta ou não.INI configuração da Impressora fiscal. Após copiar os arquivos na pasta System32 registre os arquivos clicando em cima dos arquivos REGSVR32 /S DAO350.118 Favorecido= Cidade= [Formato] .Configurando a Impressora Agora falta configurar o arquivo BEMAFI32. vamos ter mais um programa trabalhando. quando efetuado o lacre pela Receita Federal. para evitar isso colocamos direto na pasta Win32 onde qualquer sistema pode acessar.bematech. +------------------------------------.br Após baixados os arquivos necessários.6 . Para aparecer o nome de fantasia BAR DO ZÉ no cupom. 11. . para a pasta System32 (C:\windows\system32). Para que isso? – Porque a Impressora Fiscal não tem esses dados gravados dentro do EPROM.txt.). cidade: LINS SP.HTML (Ajuda) e o Leiame.coluna extenso 2 - Fonte: www. No caso da impressora fiscal.DLL que registram arquivos em lotes do MS-DOS – aparecerá uma tela do MS-DOS e fecha em seguida. Emulador Emulfith e BemaFI32. Parâmetros „EmulMFD = 0 ou 1‟ . então colocamos como favorecido: BAR DO ZÉ. | | +------------------------------.com. escrever o nome do favorecido da nota.

. quando da execução do projeto.Com o emulador . usamos o “0”. Aparece o emulador .br A área esquerda representa o painel da impressora. representa o papel da impressora.1. Para imprimir em uma Impressora Fiscal real. então colocamos como parâmetro o numero “1” .  Clique no ícone do emulador.Com Impressora Fiscal – EmulFMD = 0. conforme figura abaixo: Figura 52 – Tela do emulador EMULFITH VR. deve aparecer o ícone Bematech Emulfith no Desktop. OBS: Já existe uma nova versão do emulador no site www. Atenção .O emulador é só para ser usado na etapa do desenvolvimento. porque ocupa muita memória e o computador fica lento. então não deixe este emulador rodando na máquina o tempo todo.02 A parte direita em branco. . para substituir a Impressora Fiscal física. Se o emulador Emulfith já estiver instalado. Só ative-o quando for fazer um teste.com.bematech.EmulFMD = 1.119 Se formos utilizar o emulador (Emulfth). .

mas se estiver usando a impressora fiscal.  Abra a pasta . pressione a tecla PAPER 5 vezes para colocar o equipamento em operação.120 Quando a Impressora fiscal for ligada. aparecerá a mensagem que o horário avançou mais de 30 dias em relação ao último documento armazenado. Para limpar a mensagem do emulador. a fim de usar o emulador. Enquanto não aparecer a mensagem de Impressora desbloqueada.A memória de trabalho do emulador. ISS.Ajuda da BEMAFI32. neste ponto é emitida a Leitura X e o equipamento está pronto para ser utilizado. este arquivo só é acessível para a Receita Federal. É a memória física – o que interessa à Receita Federal.DLL . não tributados.7 . Na Impressora fiscal. existe um botão (LIMPAR). aparecerá mensagem de que o ECF esta desbloqueado. regulagem da hora. Esta memória é bem grande e quando não tiver mais espaço. quanto tem de ICMS. instalado na pasta Windows\System32. altere o campo EmulMFD para “1”. Isto é feito tanto na impressora real . Após efetuado este processo.INI. Assim a impressora fica preparada para efetuar a operação. Se o horário estiver correto. não altere. como se fosse destacar o papel impresso. o que não é permitido na Impressora Fiscal. não dá para ser usada. No emulador pode-se configurar a porta serial. a impressora deve ser levada na Receita Federal para ser efetuada a leitura e zerada. para poder avançar o papel pressionando o botão PAPER 11. No arquivo BEMATFI32. OBS: O arquivo de Helph da Bematech(que tem uma interrogação). Podemos deixar a impressora em OFF-LINE. OBS: De hora em hora a Impressora Fiscal emite uma barra indicando que ela esta ligada e ativa. vai ser usado para fazer o projeto. quanto no emulador.

Propriedades: Name Frm_TesteImpressora Btn_GerarCupom Caption Teste Impressora Cupom Fiscal Form TButton .     Abra este arquivo e minimize. Crie uma nova aplicação. File > New > Application Coloque um botão: Figura 54 – Formulário de teste para Cupom Fiscal. Abra o Delphi.DLL.121 Figura 53 – Tela da ajuda da Bemafi32.

Clicando em declarando a DLL. colocamos variáveis e jogamos valores fixos nestas variáveis para mandar imprimir esses valores.  Selecione toda a programação – copie e cole depois da palavra implementation {$R *. endereço. temos que saber o nome de cada procedimento. depois substituiremos os valores dessa variáveis pelos campos do banco de dados. campos fixos que não podemos alterar. Note que tem o comando stdcall e external.) > escolha na versão em Delph. Nesta DLL tem os parâmetros declarando a DLL. temos várias linguagens (Visual Basic. Estas rotinas mudam de acordo com a versão DLL que for baixada.  Pressione F12 para abrir o módulo de programação. Abrirá todas as rotinas nesta linguagem..122  Salve a Unit e o projeto Como ainda não temos um banco de dados por ser o primeiro exemplo. No arquivo de Help. Delphi. .. A primeira coisa que fazemos num cupom fiscal é imprimir o cabeçalho que contém o nome da empresa.dfm} Figura 55 – Funções de inicialização para Impressora Fiscal. Para chamar a rotina de dentro da DLL. tem a DLL BEMAFI32. CNPJ.

pchar( cNome ). . cEndereco := 'R. 1000'.123 Após este campo aparecerá a impressão para quem estamos vendendo . 11. Esta rotina explica o funcionamento e os parâmetros necessários (CPF.123.154-98'.As rotinas A primeira rotina é chamada Bematech_FI_AbreCupomMFD. cNome := 'Fulano de Tal'.DLL > clique em DLL BemaFI32 > Funções da DLL > Cupom Fiscal > Bematech_FI_AbreCupomMFD.  Selecione esta rotina – copie e cole na programação do botão Btn_GeraCupom. Sem Fim.Opcional.  Na ajuda da BEMAFI32. nome. iRetorno := Bematech_FI_AbreCupomMFD( pchar( cCPF ). pchar( cEndereco ) ).8 . // // Exemplo em Delphi cCPF := '10. Figura 56 – Tela de ajuda Bematech – Bematech_FI_AbreCupomMFD. endereço do cliente e embaixo quem vendeu).

BTn_GeraCupomClick(Sender: TObject). Para gravar uma P A L A V R A . .PCHAR Dentro desses parâmetros tem o pchar – Numa string em Pascal. que é o símbolo que indica que terminou a string. cNome: string. depois vem a posição. Na Ajuda é possível ver qual o tipo de cada variável já definida. O maior tamanho de uma string em Pascal é 255 (o caractere 255 da tabela ASCII). procedure TFrm_TesteImpressora.. end. o caractere que representa esta posição é colocado no campo zero indicando que foram usadas 7 posições da string. cCPF. tem muitas variáveis que podem também serem usadas. a posição zero guarda o tamanho. A posição zero inibe o tamanho total da posição.9 . pchar( '' ) ). Neste tipo de string podemos ter quantos caracteres quisermos. Na tabela ASCII. 1. begin // Abre o Cupom Fiscal cCPF := '1234567890'. iRetorno := Bematech_FI_AbreCupomMFD( pchar( cCPF ). var iRetorno: integer. cNome := 'Fulano de Tal'. Também podem ser passados em branco. Na linguagem “C” a string é diferente. pchar( cNome ). 11.4.2. na Ajuda. Podemos colocar a expressão “Venda ao Consumidor” – Todos esses parâmetros são opcionais. P 1 A 2 L 3 A 4 V 5 R 6 A 7 0 Estamos usando até a posição 7. O nome e o endereço podem ser colocados no cupom fiscal. A função Pchar transforma uma string em Pascal para um string em “C”. Acima.124 Os nomes das variáveis podem ser mudadas de acordo com a programação desejada.3.. Podemos escrever PALAVRA e no final colocamos “\0”.

mas este retorno só é habilitado pela função Bematech_FI_HabilitaDesabilitaRetornoEstendidoMFD. que significam o estado atual após o envio. Esse erro pode ser: papel atolado. etc). –(O sistema não sabe se vai jogar para o emulador ou para a impressora. .0. Nosso programa esta pegando esta função e jogando para um retorno e por enquanto não vamos usa-lo. // iRetorno := Bematech_FI_RetornoImpressora( iACK. iST2.Comandos Retorno da Impressora retirado do arquivo Ajuda BEMAFI32. – (foi esquecido de plugar a impressora fiscal).ini não foi encontrado no diretório de sistema do Windows. Quando der esse erro temos que chamar outra rotina para mostrar o erro que ocorreu. -27: Status da impressora diferente de 6. 1: OK.Possíveis retornos da Função (INTEIRO): 0: Erro de comunicação. Essa rotina tem o retorno do erro. -4: O arquivo de inicialização BemaFI32.Nas impressoras fiscais Matriciais. executadas na impressora. mas podemos fazer um comando “if” (if retorno <> 1 then showmessage “Erro: Verifique a Impressora”) – é apenas uma das funções que poderia ser usada com a resposta do retorno.11 . –(uma série de erros. NAK (15h ou 21d) : Byte indicativo de recebimento incorreto. chamamos a rotina AbreCupomMFD e passamos como parâmetro o CPF. onde informações mais detalhadas podem ser obtidas. possuem bytes de retorno.125 Então para o nosso exemplo. ST1 e ST2). -5: Erro ao abrir a porta de comunicação. ST1 e ST2. impressora desligada. pelos bytes ACK. sem papel. o nome e o endereço. Vamos supor que desse o erro “-27”. apenas. ST1 e ST2 : Bytes de estado da impressora. retorna um valor: 11. existe um outro retorno chamado ST3 (retorno estendido). Cada byte é tratado da seguinte maneira: ACK (06h ou 6d) : Byte indicativo de recebimento correto. que é exatamente o que está escrito no exemplo das rotinas. Observação: . em resumo. não está instalada a impressora fiscal). os retornos de execução são obtidos. Quando for executada esta rotina que é uma função.Nas impressoras fiscal MFD (somente). .0 (ACK. conforme mostra nos comandos de retorno da impressora abaixo: 11.10 .DLL Todos as funções. iST1. então chamaríamos a próxima rotina (retornoImpressora). iST3 ). -2: Parâmetro inválido na função.

32 sMsg = "Erro no Relógio" End If If St1 >= 16 Then // bit 4 St1 = St1 .64 sMsg = "Pouco Papel" End If If St1 >= 32 Then // bit 5 St1 = St1 . As linhas abaixo são uma forma de você desenvolver um pedaço de código para saber quais bits estão "setados": Codificando o ST1 If St1 >= 128 Then // bit 7 St1 = St1 .4 sMsg = "Comando Inexistente" End If If St1 >= 2 Then // bit 1 .2 .16 sMsg = "Impressora em Erro" End If If St1 >= 8 Then // bit 3 St1 = St1 . tem um valor.11. conforme a tabela acima: O valor recebido da impressora para ST1 e/ou ST2 deve ser comparado com cada bit. Cada bit. dentro do byte.Estados de ST2 Bit 7 6 5 4 3 2 1 0 Descrição do estado Tipo de parâmetro do comando inválido Memória fiscal lotada Erro na memória RAM não volátil Alíquota não programada Capacidade de alíquotas programáveis esgotada Cancelamento não permitido CNPJ/IE do proprietário não programados Comando não executado Valor retornado 128 64 32 16 8 4 2 1 11.8 sMsg = "Comando não iniciado com ESC" End If If St1 >= 4 Then // bit 2 St1 = St1 .1 .Estados de ST1 Bit 7 6 5 4 3 2 1 0 Descrição do estado Fim do papel Pouco papel Erro no relógio interno Impressora em erro Primeiro dado do comando não foi caractere ESC (27 em decimal) Comando inexistente Cupom aberto Número de parâmetro do comando inválido Valor retornado 128 64 32 16 8 4 2 1 11.3 – Lógica de tratamento Lógica de Tratamento Cada byte é composto de 8 bits.11.11.126 11.128 sMsg = "Fim de Papel" End If If St1 >= 64 Then // bit 6 St1 = St1 .

32 sMsg = "Erro na Memória RAM" End If If St2 >= 16 Then // bit 4 St2 = St2 . Fonte: www.4 sMsg = "Cancelamento Não Permitido" End If If St2 >= 2 Then // bit 1 St2 = St2 .1 sMsg = "Comando Não Executado" End If Teste o exemplo acima com ST1 = 66. e repare que você terá dois erros.16 sMsg = "Alíquota Não Programada" End If If St2 >= 8 Then // bit 3 St2 = St2 .128 sMsg = "Tipo de Parâmetro de Comando Inválido" End If If St2 >= 64 Then // bit 6 St2 = St2 .2 sMsg = "CNPJ/IE do Proprietário Não Programado" End If If St2 >= 1 Then // bit 0 St2 = St2 . If (ST1 and 128) = 128 then ShowMessage(‗Fim do Papel!‘).2 sMsg = "Cupom Aberto" End If If St1 >= 1 Then // bit 0 St1 = St1 .8 sMsg = "Capacidade de Alíquotas Lotada" End If If St2 >= 4 Then // bit 2 St2 = St2 .com.127 St1 = St1 .1 sMsg = "Número de Parâmetro(s) Inválido(s)" End If Codificando o ST2 If St2 >= 128 Then // bit 7 St2 = St2 .bematech. If (ST1 and 128) = 128 then ShowMessage(‗Fim do Papel!‘). If (ST1 and 64) = 64 then ShowMessage(‗Pouco Papel!‘).br O código abaixo é mais compacto e tem o mesmo efeito e não é necessário efetuar uma subtração dos valores correspondentes a cada estado retornado. .64 sMsg = "Memória Fiscal Lotada" End If If St2 >= 32 Then // bit 5 St2 = St2 . pouco papel (64) e cupom aberto(2).

25'. agora verificaremos o segundo campo – Os itens da nota. cTipoDesconto := '%'. cQtde := '10'.128 If (ST1 and 32) = 32 then ShowMessage(‗Erro no relógio interno!‘). Basicamente até agora só fizemos a impressão do cabeçalho. cAliquota := '1200'.br . If (ST1 and 16) = 16 then ShowMessage(‗Impressora em erro!‘). pchar( cValorDesc ) ). pchar( cAliquota ).DLL > Funções da DLL > Bematech_FI_VendeItem // Exemplo em Delphi cCodigo := '123'. If (ST1 and 4) = 4 then ShowMessage(‗Comando inexistente!‘). If (ST1 and 8) = 8 then ShowMessage(‗Primeiro dado do comando não ESC!‘). pchar( cTipoQtde ). pchar( cDescricao ). Cupom Fiscal > Fonte: www. cValor := '0. If (ST1 and 2) = 2 then ShowMessage(‗Cupom Aberto!‘). pchar( cValor ). A rotina de Impressão dos itens – Bematech_FI_VendeItem  BEMAFI32. iCasasDecimais. 11. If (ST1 and 1) = 1 then ShowMessage(‗Número de parâmetro do comando inválido!‘). cValorDesc := '0000'. pchar( cTipoDesconto ). iCasasDecimais := 2.bematech. cTipoQtde := 'I'. iRetorno := Bematech_FI_VendeItem( pchar( cCodigo ).com. cDescricao := 'Caneta'.12 – Itens – Rotina Vende Item Neste campo temos que fazer um loop (while) para imprimir os itens. pchar( cQtde ).

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

Fonte: www. Na quantidade fracionária são 3 casas decimais. Casas decimais – o número de casas depois da vírgula para o valor unitário. I . . Ex. podendo vender até 9. .descrição – o nome do produto vendido. tipo). o tipo de quantidade (inteira). Descricao: STRING até 29 caracteres com a descrição do produto..Inteira e F .). ValorDesconto: String com até 8 dígitos para desconto por valor (2 casas decimais) e 4 dígitos para desconto percentual. Depois dos produtos vendidos. substituiremos o valor fixo pelos valores do banco de dados.Alíquota – no caso está selecionando a 2ª alíquota cadastrada ou poderíamos ter colocado 18%. só para saber como chamar os dados.130 Parâmetros: Codigo: STRING até 13 caracteres com o código do produto. 18%. com todos os itens.Vamos colocar o tipo de desconto por porcentual e também nada de desconto. a aliquota. Se for o índice da alíquota deve ser 2 caracteres.bematech. . CasasDecimais: INTEIRO indicando o número de casas decimais para o valor unitário (2 ou 3). apenas estamos demonstrando como imprimir valores fixos .Fracionária. Quantidade – 4 dígitos para inteiro.Colocamos a descrição.999 itens ou 7 dígitos quando é fracionária. no sistema. ValorUnitario: STRING até 8 dígitos para valor unitário.br - Temos que passar a alíquota que vamos utilizar (12%. Tipo da quantidade – tipo da quantidade (se inteiro ou fracionário). o número de unidades (valor com duas casas decimais – 10 reais cada unidade) que no total vai dar R$50. descrição. com 3 casas decimais.com.00 para o valor ou 05 para o índice). (18. Tipo do desconto – se tiver desconto (valor fixo ou percentual). . . Exemplo: Vamos vender um item – supondo 13 livros. '$' desconto por valor e '%' desconto percentual. Quantidade: STRING com até 4 dígitos para quantidade inteira e 7 dígitos para quantidade fracionária. Aliquota: STRING com o valor ou o índice da alíquota tributária. TipoDesconto: 1 (um) caracter indicando a forma do desconto. OBS: Por enquanto não temos o banco de dados. temos que fechar o cupom. Se for o valor deve ser informado com o tamanho de 4 caracteres ou 5 com a vírgula. Valor unitário – uma string até 8 dígitos.. TipoQuantidade: 1 (um) caracter indicando o tipo de quantidade. Podemos dar desconto individualmente por item ou na nota inteira. depois . alíquota.00. Chamamos a rotina VendeItem passando todos os parâmetros (código.

cValorDesc := '1000'. "A" para acréscimo. "$" para desconto por valor e "%" para percentual. // Exemplo em Delphi cAcresDesc := 'X'. cDescAcresc := 'A'.com. iRetorno := Bematech_FI_AcrescimoDescontoItemMFD( pchar( cNumeroItem ). iST3 ). Tipo – Se vai ser em percentual ou valor de desconto.. iST1. ValorDesconto: STRING com no máximo 14 dígitos para desconto por valor e 4 dígitos para desconto percentual. Permite acréscimo e desconto no fechamento do cupom. iRetorno := Bematech_FI_IniciaFechamentoCupomMFD( pchar pchar( cTipoAcresDesc ). pchar( cDescAcresc ). cValor := '10. pchar( cValor ) ). Fonte: www.. pchar( cValorAcres ). desconto ou ambos. cTipo := '$'. Podemos dar R$0. "D" para desconto e "X" para acréscimo e desconto.13 . “A” para dar acréscimo e “D” para dar desconto.00 de desconto em cima do valor total do cupom.00 de acréscimo e R$2.bematech. > Bematech_FI_IniciaFechamentoCupomMFD Inicia o fechamento do cupom fiscal.131 11. pchar( cValorDesc ) ). cTipoAcresDesc := '%'. pchar( cTipo ). iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK. TipoAcrescimoDesconto: STRING que indica se o acréscimo ou desconto é por valor ou por percentual.DLL > Outras funções > funções especificas das impressoras fiscais MFD. ValorAcrescimo: STRING com no máximo 14 dígitos para acréscimo por valor e 4 dígitos para acréscimo percentual.Rotina Iniciar Fechamento do Cupom Fiscal  Ajuda da BEMAFI32. iST2. // Dá Acréscimo ou Desconto em Item posterior cNumeroItem := '001'.00'. Esse acréscimo ou desconto é no total geral. ( cAcresDesc).br  Copie e cole na programação Como parâmetro passamos o Acréscimo ou Desconto que vamos dar na nota. cValorAcres := '1200'. . Parâmetros: AcrescimoDesconto: STRING que indica se haverá acréscimo no cupom.

iRetorno := Bematech_FI_CancelaAcrescimoDescontoItemMFD( pchar ( cAcresDesc ). temos que especificar como vai ser pago: A vista. iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK. cValorAcre := '10. iST2. Parâmetros: Flag: STRING com "A" para cancelar o Acréscimo ou "D" para cancelar o Desconto.br // Cancela Acréscimo ou Desconto em Item Vendido Posterior cDescAcresc := 'A'. cNumeroItem := '001'. em cheque.. . // Exemplo em Delphi cAcresDesc := 'A'. // Inicia o Fechamento do Cupom Fiscal com Acréscimo e/ou Desconto cDescAcresc := 'X'.com. iST1.bematech.00 e um acréscimo de R$ 10.132 Bematech_FI_CancelaAcrescimoDescontoItemMFD Cancela a acréscimo ou a desconto dado no item. iRetorno := Bematech_FI_CancelaAcrescimoDescontoItemMFD( pchar( cDescAcresc ). pchar( cNumeroItem ) ). cValorDesc := '05. iST1. pchar( cValorAcre ).  Fazendo um joguinho: podemos dar um desconto em dinheiro no valor de R$5. iST3 ). pchar( cValorDesc ) ). no cartão. iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK. Depois que Iniciamos o Fechamento do Cupom e após o total ser definido. cNumeroItem := '005'.) – esta forma de pagamento é registrada também no cupom fiscal. pchar( cNumeroItem ) ). iST3 ). Fonte: www. cTipo := '$'. etc.00. iST2. iRetorno := Bematech_FI_IniciaFechamentoCupomMFD( pchar( cDescAcresc ).00'.00'. a prazo. pchar( cTipo ).. Item: STRING de até 3 dígitos com o número do item a ser cancelado restrito aos 300 últimos registros efetuados.

Exemplo: // Exemplo em Delphi cFormaPgto := 'Cartão VISA'.bematech.0. Parâmetros: FormaPagamento: STRING com a forma de pagamento com no máximo 16 caracteres. DescricaoFormaPagto: STRING com a descrição da forma de pagamento com no máximo 80 caracteres. Parcelas: STRING numérica entre 1 e 24 com o número de parcelas em que o pagamento será realizado. St2 e St3) Observações: .Ok -2 .Parâmetro inválido.133 11. . cValorPago := '50.0 (Ack. ValorFormaPagamento: STRING com o valor da forma de pagamento com até 14 dígitos.Erro ao abrir a porta de comunicação -24 . cNumeroParcelas := '2'.Erro de comunicação 1 . Se o cliente vai fazer o pagamento da entrada dando uma nota de R$100. Poderá ser emitido um comprovante para cada parcela. Chamamos Efetuar Forma de Pagamento escolhendo o pagamento em 3 vezes.14 – Rotina Bematech FI EfetuarFormaPagamentoMFD  Ajuda da BEMAFI32.00'. iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar ( cFormaPgto ).00.O número de parcelas é utilizado para emissão do comprovante não fiscal vinculado. pchar( cMsg ) ).Forma de Pagamento não programada. Retornos da Função (INTEIRO): 0 . pchar( cValorPago ). temos que devolver-lhe o troco.Status da impressora diferente de 6.Arquivo ini não encontrado ou parâmetro inválido para o nome da porta -5 .br Primeiro a forma de pagamento vai ser feita através de uma TEF (Transferência Eletrônica de Fundos – Cartão) e descrita a forma de pagamento. -4 .A descrição será impressa uma linha após a forma de pagamento. A forma de pagamento vai ser a prazo.com. .DLL > Funções da DLL > Funções Especificas das Impressoras Fiscais MFD > Bematech_FI_EfetuarFormaPagamentoMFD Função Forma de Pagamento Para efetuar a forma de pagamento use esta função Imprime a(s) forma(s) de pagamento e o(s) valor(es) pago(s) nessa forma. pchar( cNumeroParcelas ). -27 . Fonte: www.O fechamento do cupom com formas de pagamento deve ter sido iniciado. Esse valor que o cliente esta dando .0. cMsg := 'Compra parcelada'. St1.

Agora falta fechar o cupom 11. // Programa a Forma de Pagamento cForma := 'A Prazo'. e 320 caracteres (8 linhas X 40 colunas).Escolha da forma de pagamento .Fechamento da nota. . iST1. assim como o numero de parcelas para pagamento a prazo e a descrição da forma de pagamento.Fechamento do Cupom Fiscal. 60 e 90 dias'. para a impressora fiscal MP-20 FI II. cDescForma := 'Compra parcelada em 30. . iST1.Os itens da nota. iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar( cForma ). iST3 ). . iRetorno := Bematech_FI_ProgramaFormaPagamentoMFD( pchar( cForma ). cParcelas := '3'. A rotina que fecha o cupom se chama Termina Fechamento Cupom Fiscal Termina o fechamento do cupom com mensagem promocional. // Efetua Forma de Pagamento cValor := '100.00'. .15 . iST3 ). iST2.Quanto foi dado em dinheiro e se tem troco ou não da primeira parcela. cTEF := '0'. iST2.  Ajuda da BEMAFI32. pchar( cDescForma ) ).Impressão do cabeçalho da nota fiscal. pchar( cValor ).134 e o troco que vai receber estarão registrados no cupom fiscal. pchar( cTEF ) ). Até aqui foram feitos: .Escolheu como pagar. Parâmetro: Mensagem: STRING com a mensagem promocional com até 384 caracteres (8 linhas X 48 colunas). pchar( cParcelas ). . iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK.DLL > Funções da DLL > Cupom Fiscal > Bematech_FI_TerminaFechamentoCupom. iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK. para a impressora fiscal MP-40 FI II.

. iRetorno := Bematech_FI_TerminaFechamentoCupom( pchar( cMensagem ) ).0 (ACK. Para verificar o funcionamento.bematech. -4: O arquivo de inicialização BemaFI32. Cada linha com 46 colunas.br Esta rotina só tem um parâmetro – A Mensagem – Esta mensagem pode ser trocada de acordo com as promoções ou épocas do ano.com. -2: Parâmetro inválido na função. serão impressas 4 linhas de texto. foi criado o cabeçalho. No final foi impressa a mensagem “Obrigado. volte sempre !!!'. -27: Status da impressora diferente de 6.ini não foi encontrado no diretório de sistema do Windows. serão impressas 8 linhas de texto. iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK. Observações: .00 e recebeu R$45. ST1 e ST2).A forma de pagamento deve ter sido efetuada.00 de troco. verifique que no emulador ou na impressora fiscal. iST1. iST3 ). iRetorno := Bematech_FI_TerminaFechamentoCupom( pchar ( cMsgPromocional ) ).135 Possíveis retornos da Função (INTEIRO): 0: Erro de comunicação. // Termina o Fechamento do Cupom Fiscal cMensagem := 'Obrigado. 1: OK. imprimiu o item vendido.Na impressora fiscal BEMATECH. iST2. -5: Erro ao abrir a porta de comunicação. o acréscimo e o desconto foram feitos. Ao clicar no botão imprimir. Exemplo: // Exemplo em Delphi cMsgPromocional := 'Obrigado. -36: Forma de pagamento não finalizada.Na impressora fiscal YANCO.0. volte sempre !!!'. o cliente pagou com uma nota de R$100. deixe ligado o emulador Emulfith. Fonte: www. . volte sempre!!!” . end.  Salve e compile o programa. end. Para que o programa possa rodar. as variáveis tem de ser declaradas. Foi uma conta a prazo.

Brasil CNPJ:82.630-490 Curitiba . de Equip.077/0001-71 IE:10181465-30 UF:PR ------------------------------------------------ .Parana .136 Figura 57 – Teste Impressora em execução Figura 58 – Emulfith vr. ****ECF DESBLOQUEADO**** Bematech Ind.1. Eletronicos S. e Com.02 mostrando dados da impressora fiscal. Estrada de Santa Candida.373.A. 263 82.

60 e 90 dias TROCO R$ 45. conforme mostrado abaixo: program Venda. Nota: No começo da programação do Formulário de vendas.00 A Prazo 100. Abra uma nova aplicação com os seguintes dados: Name Frm_Principal Caption Sistema de Vendas ECF - Form Main Menu IBDataBase IBTransaction  Salvar Como U_Principal.00 TOTAL R$ 55.pas' {FRM_Venda_FormaPAg}.pas‘.00 I1 50.00g desconto -5.16 – Implementando o programa para uso com banco de dados.137 16/04/2006 10:42:27 CCF:000001 COO:000002 -----------------------------------------------CNPJ/CPF consumidor:1234567890 NOME:Fulano de Tal ------------------------------------------------ CUPOM FISCAL ITEM CÓDIGO DESCRIÇÃO QTD. U_Venda_Formapag in 'Formularios\U_Venda_Formapag. U_Principal in 'Formularios\U_Principal.  File > New > Unit . volte sempre !!! 11.00g Acréscimo item 001 +10.00 Compra parcelada em 30.pas' {Frm_Vendas}. U_vendas in 'Formularios\U_vendas.00 acréscimo 10.pas'. no campo uses foi introduzida a linha U_Fiscal in ‗Formularios\U_Fiscal. VL UNITÁRIO( R$) ST VL ITEM( R$) -----------------------------------------------001 1234567890123 Produto de Teste 5 X 10. uses Forms. U_Fiscal in 'Formularios\U_Fiscal.UN.pas' {Frm_Principal}. Crie uma Unit para colocar as rotinas da impressora.00 -----------------------------------------------Obrigado.00g Cancelamento Acréscimo item 001 -10.00 -----------------Subtotal R$ 50.

External 'BEMAFI32. . StdCall.DLL'.DLL'. Largura: Integer. function Bematech_FI_ProgramaAliquota( Aliquota: String. External 'BEMAFI32. Altura: Integer. onde temos os campos Private e Public. uma procedure teste por exemplo. implementation end. unit U_Fiscal. As rotinas da programação da impressora fiscal fica dentro do campo Interface e no final da programação começa o campo Implementation e tudo que for colocado após este campo não é acessível.DLL'.DLL'. function Bematech_FI_CodigoBarrasPDF417MFD( NivelCorrecaoErros: Integer. Colunas: Integer. Todas as rotinas da impressora fiscal foram colocadas numa outra Unit para poder chamar depois. podemos declarar esta função no campo Interface e no campo Implementation colocamos a programação repetindo o mesmo cabeçalho nos dois campos. foi criada a Unit U_Fiscal. External 'BEMAFI32. porque todas as rotinas iriam se misturar no código fonte. StdCall. colocamos o cabeçalho no campo Interface e a programação no campo Implementation. Se precisarmos definir uma rotina dentro dessa Unit. Codigo: String ): Integer. function Bematech_FI_CodigoBarrasPLESSEYMFD( Codigo: String ): Integer. Lembra da Classe. ICMS_ISS: Integer ): Integer. interface // Funções de Inicialização function Bematech_FI_AlteraSimboloMoeda( SimboloMoeda: String ): Integer. Se for necessário criar uma rotina. StdCall. Então colocando dentro do campo Interface é disponível para fora da Unit. Tudo que colocamos numa interface de uma Unit é comparado ao campo Public e tudo que estiver no campo Implementation é Private.138  Salve dentro da pasta Formulários com o nome U_Fiscal. Então para evitar misturar muitas rotinas e facilitar a leitura do código fonte. StdCall. External 'BEMAFI32.

Dentro desta rotina nova venda. ficará em branco. a programação da o Insert na tabela Tbl_Ped. O que acontece no dia a dia da empresa? O usuário (vendedor) clicando em nova venda. colocar a data ou atribuir direto do sistema e escolher o cliente. geramos um novo pedido e abrir // o cupom fiscal. {é possível chamar a rotina de abrir o cupom aqui? R: Não. após abrir o formulário ainda não selecionou quem é o cliente (nome do cliente. pois o cliente ainda não foi escolhido. esta aparecerá nos campos para ser selecionada. Como deixamos as rotinas disponíveis dentro desta DLL.Insert.O primeiro comando abre o cupom passando três parâmetros (CPF. A solução é abrir o cupom ao salvar o pedido} end. . a impressora fiscal não imprimirá esses dados. teremos somente o comando Tbl. neste momento é gerada o cabeçalho. Tbl_Ped.Tbl_PedBeforePost(DataSet: TDataSet). Então não podemos definir o cabeçalho nesta rotina (Nova Venda).Btn_NovaVendaClick(Sender: TObject). Antes de inserir o primeiro item . para que a programação fique ordenada e fácil de fazer uma manutenção.139 Se agora abrir o Unit vendas e chamar esta procedure teste pressionando as teclas CTRL + Barra de Espaço. procedure TFrm_Vendas. e digitando a rotina teste. CPF e endereço). nome e endereço). NumeroCupom: string[6]. salvamos a tabela de Pedido. Todas as rotinas que quisermos chamar em Bemafh disponível nesta DLL é encontrado na mesma hora como se estivesse feito na Unit chamadora. permite ao usuário escolher o numero. begin // Ao abrir uma nova venda. temos que definir em outro local. agora é só chamar na Unit Vendas. . var CPF: String[30]. Se fosse comandado uma impressão para a impressora fiscal sem esses parâmetros no campo nova venda: .Se for pedido uma impressão. procedure TFrm_Vendas. iretorno:integer. Se tivermos alguma rotina para colocar na programação. No evento BeforPost da tabela de pedido fazemos o tratamento do cupom fiscal. só que não temos nenhum dos três porque não foram selecionados ainda. Quando der o Insert na tabela. podemos colocar nesta Unit e chamá-la em outro formulário.Insert. Quando for clicado em nova venda. NumeroSerie : String[15].

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

Na tabela de clientes é selecionado o CPF escolhido e atribuído na variável CPF. se retornar “0”. chamamos de novo a impressora e capturamos o numero do cupom fiscal que foi gerado seqüencialmente ao abrir o cupom fiscal e gravamos em uma variável que vai ser armazenado dentro do banco de dados.fieldbyname('CPF_Cli'). {case} end. {0} Antes de salvar. se retornar “0” . é cancelado o pedido. {Try} end.141 Showmessage(NumeroSerie). Para evitar esse problema. Tratamento especial} try // tratamento Tbl_Ped. executa esta função: Se retornar “1” – deu certo. passando como parâmetro o CPF: iRetorno := Bematech_FI_AbreCupom( ( CPF ) ). O usuário selecionou o cliente e colocou na tabela de pedidos CPF:= Tbl_Cli. { A impressora está liga e imprimiu (abriu) o cupom. . Esta rotina retorna um valor em iRetorno – Cada vez que der erro na impressora fiscal.deu erro (A impressora pode estar desligada. 1: // já salva por padrao. porque se for salvo o pedido e não for impresso o cupom é um problema muito grande. cancelamos a nota. iRetorno := Bematech_FI_AbreCupom( ( CPF ) ). case iretorno of 0 : begin { erro de comunicação com a impressora. logo depois Abre Cupom na rotina abaixo.Cancel. . houve um erro de comunicação) Se a impressora fiscal estiver desligada. end. except showmessage('erro de comunicação com a impressora'). -27 : // realizar o tratamento para cupom em aberto // ou problemas com a impressora. end.AsString. end.

asstring:= NumeroCupom. Na tabela de pedidos. //Tbl_Ped. iRetorno := Bematech_FI_NumeroCupom( NumeroCupom ). //Tbl_Ped. então foi feito um showmessage na tela para não dar erro.FieldByName('NumeroSerie'). no caso fazemos um comando para guardar no banco. // NumeroSerie: Variável string com o tamanho de 15 posições //para receber o número de série. //Tbl_Ped.142 Armazenar o numero do cupom e o numero da impressora antes de salvar.asstring:= NumeroSerie. Isso servirá para que a empresa possa gerenciar seus dados e verificar se um produto foi mesmo vendido em seu estabelecimento comercial. Showmessage(NumeroCupom + 'criar no banco!'). mas tem que ser criado os campos no banco de dados na tabela de pedidos.asstring:= NumeroCupom.FieldByName('numerocupom'). antes da programação . Não foi criado no campo do banco de dados o número de série e o número do cupom. iRetorno := Bematech_FI_NumeroSerie( NumeroSerie ).asstring:= NumeroSerie. {****************************************************************** NAO ESQUECER DE CRIAR OS CAMPOS NUMERO DE SERIE E NUMERO DO CUPOM NA BASE DE PEDIDOS ! ********************************************************************} //Tbl_Ped. end. Showmessage(NumeroSerie). guardamos o numero do cupom. Guardamos os dois campos.FieldByName('NumeroSerie'). } begin //NumeroCupom: Variável string com 6 posições para receber //o número do último cupom. capturamos também o número de série da impressora fiscal. então fica fácil verificar se um produto foi vendido ou não em um estabelecimento comercial. Showmessage(NumeroCupom + 'criar no banco!'). porque identificando o numero de serie e o numero da impressora é fácil listar os itens vendidos. Showmessage(NumeroSerie). Armazenamos os dois campos na tabela de pedido. Logo depois que capturar o número do cupom. No cupom tem o número de série e o numero da impressora.FieldByName('numerocupom').

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

O código do produto da tabela de produtos é armazenada na tabela de itens. valor. Na rotina de ImprimirCupom temos que passar os parâmetros (código.asinteger:= Tbl_Prod. Descr:= Tbl_Prod.FieldByName('cod_prod'). {o valor vem da tabela produto} Tbl_Itens. .00'. Depois de armazenado todos os dados. Alicota:='18. Se for o valor deve ser informado com o tamanho // de 4 caracteres ou 5 com a vírgula. A alíquota foi fixada em 18% para o exemplo e salvamos a alíquota usada (o código 5 representa a alíquota de 18%) //Aliquota: STRING com o valor ou o índice da alíquota // tributária.) Foi salva a descrição da tabela de produtos e armazenada dentro do campo descrição da tabela de itens.asstring.FieldByName('Imposto_Itens'). Ex. descrição. No exemplo poderíamos ter armazenado o valor da alíquota de 18%.asinteger.AsString:='05'.FieldByName('Desc_prod').FieldByName('cod_prod').asinteger). pegamos o código que foi armazenado na tabela de itens e jogamos dentro da variável cód que é a primeira variável porque agora temos que chamar a rotina de imprimir cupom cod := inttostr(Tbl_Itens. etc. porque no dia da compra do item.00 para o valor // ou 05 para o índice). (18. sendo que o código permanece o mesmo. Se for o índice da // alíquota deve ser 2 caracteres.FieldByName('cod_prod'). foi vendido a 18% de alíquota. Se o cliente apresentar uma nota fiscal antiga temos que saber quanto foi cobrada a alíquota no dia da venda. e essa alíquota pode mudar. Em vez de armazenar o código da alíquota podemos armazenar a porcentagem cobrada em virtude de mudança de alíquota que pode ocorrer. Tbl_Itens.144 Colocamos a tabela de Itens em modo de inserção e somamos na variável aux mais um (aux + 1) É preenchido os demais dados – o código do pedido (cód_ped) da tabela de Itens é armazenado na tabela de pedido.

//ValorDesconto: String com até 8 dígitos para desconto por //valor (2 casas decimais) e 4 dígitos para desconto percentual.AsInteger) . Tbl_Itens. { if Tbl_Prod. {O tipo Desconto e o valor do desconto vem da tabela promo Cod_Prod. I .00'. é fracionário.ValorDesc. tQtd:='I'.AsInteger:=1. Se não for por quilo então é unidade (inteiro) // TipoQuantidade: 1 (um) caracter indicando o tipo de // quantidade. // Na quantidade fracionária são 3 casas decimais. // ValorUnitario: STRING até 8 dígitos para valor unitário. Por exemplo. Tbl_Itens. O valor da tabela de Produtos é armazenado na tabela de Itens: // CasasDecimais: INTEIRO indicando o número de casas // decimais para o valor unitário (2 ou 3).Inteira e F .asfloat). // '$' desconto por valor e '%' desconto percentual. Por último. Qtd:= inttostr(Tbl_Itens.fieldbyname('Tipo'). Tbl_Itens. se o tipo for quilo.FieldByName('Valor_Venda'). } Quantidade – Por padrão a quantidade é igual a “1”.asfloat.. := Se existir algum desconto. // Quantidade: STRING com até 4 dígitos para quantidade // inteira e 7 dígitos para quantidade fracionária. // O campo value substitue todos os tipos as. também é armazenado. Decimal:=2.Dataini e Datafim } // TipoDesconto: 1 (um) caracter indicando a forma do desconto. Desconto := '00.Value := TDesc.asstring = 'Kg' then TQtd:='F' else TQtd:='I'. é chamada a rotina Bematech_FI_VendeItem que imprime os itens no cupom .FieldByName('qtde_prod').Fracionária. O número de casas decimais é estabelecido com até quatro dígitos para quantidade inteira e sete dígitos para fracionarias e na quantidade fracionaria é estabelecido três casas decimais.asfloat:= Tbl_Prod.145 TipoQuantidade – se é fracionário ou inteiro. valor floattostr(Tbl_Itens..FieldByName('Valor_Venda').FieldByName('TipoDesc'). no caso não tem desconto. TDes.FieldByName('Valor_Venda').FieldByName('qtde_prod').TDesc:='$'.

( tQtd ).Cancel.Edit. ( TDesc ).( Qtd ). Se deu erro (código zero) – A impressora estava desligada. end. . {try} end. {0} end. é pressionado o botão fechar da venda e escolher a forma de pagamento. FRM_Venda_FormaPAg. Except showmessage('erro de comunicação! Verifique o cabo!').( Desconto ) ).( Valor ). // salvar no banco. {case } Edt_Barra. então a venda é cancelada.Post (salva o item no banco de dados). Após ter concluído uma venda.146 // inserir item na impressora iRetorno := Bematech_FI_VendeItem( ( Cod ). se tentou salvar e deu certo (código 1) – Tbl_Itens. end.Text:=''.BitBtn1Click(Sender: TObject). {if #13} end. 0: // impressora desligada begin try // Tratamento especial Tbl_Itens. end. ( Alicota ). Clicando no botão fechar é mostrada outra tela para escolher a forma de pagamento: procedure TFrm_Vendas.Post. {if locate} end. case iretorno of 1: // salvar no banco begin Tbl_Itens. ( Descr ). begin Tbl_Ped. Lembre-se que a rotina retorna iRetorno. Decimal.showmodal.

cFormaPgto : String[16]. procedure TFRM_Venda_FormaPAg. se vai ser em percentual ou valor Begin // Iniciar o fechamento do pedido (desconto) { **************************** Atenção ************************ Se a empresa trabalha com cartões próprios de desconto ou mantém convênio com outras empresas. var AcreDes: char.Btn_FechaClick(Sender: TObject). valor: String[14]. devemos incluir os campos Desconto e tipo de desconto na forma de pagamento. É apresentado o cupom fiscal dando o desconto se existir. iretorno:integer. Quando pressionada esta tecla tem que ser iniciado o fechamento do cupom dando o desconto se existir. cDescricao : string[80]. cMsgPromocional:string. Quanto foi recebido para efetuar o pagamento e é exibido o troco se existir. Aparece o total do pedido. o cliente escolhe a forma de pagamento. Após selecionado os comandos e pressionada a tecla fechar venda. cValorPago : string[14]. Figura 59 – Aspecto do formulário Forma de pagamento para a venda. Tipo : char. ****************************************************************} // AcrescimoDesconto: Indica se haverá acréscimo ou desconto no cupom. .147 end.

// DescricaoFormaPagto: STRING com a descrição da forma de . pchar( cTEF ) ). no cartão. iST3 ). iST1. cDescForma := 'Compra parcelada em 30. faz o fechamento do cupom mostrando se vai ter desconto ou acréscimo (o tipo e o valor desse acréscimo) e inicia o fechamento. '$' para desconto por valor e '%' para percentual. iRetorno := Bematech_FI_IniciaFechamentoCupom( pchar( AcreDes ). iRetorno := Bematech_FI_ProgramaFormaPagamentoMFD( pchar( cForma ). cTEF := '0'. É feito os cálculos do desconto. pchar( Tipo ). ******************************************************************* } // Escolher a forma de pagamento //Imprime a(s) forma(s) de pagamento e o(s) valor(es) pago(s). iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK. iST2. iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar( cForma ). pchar( cParcelas ).( Valor )). valor:= '0000'. Tipo:= '%'. AcreDes:= 'D'./ // ValorFormaPagamento: STRING com o valor da forma de pagamento // com até 14 dígitos. mostrado no cupom. // Efetua Forma de Pagamento cValor := '100. pchar( cValor ).148 // 'A' para acréscimo e 'D' para desconto. // TipoAcrescimoDesconto: Indica se o acréscimo ou desconto é por valor // ou por percentual. cheque ou boleto bancário e gravar no cupom fiscal // Fazer o tratamento especial { *******************cadastar formas de pagamentos **************** // Programa a Forma de Pagamento cForma := 'A Prazo'. 60 e 90 dias'.00'. pchar( cDescForma ) ). //Permite a impressão de comentários na(s) forma(s) de pagamento // FormaPagamento: STRING com a forma de pagamento com no máximo //16 caracteres. É programada a forma de pagamento se a vista ou a prazo. // ValorAcrescimoDesconto: STRING com no máximo 14 dígitos para //acréscimo // ou desconto por valor e 4 dígitos para acréscimo ou desconto por percentual.cParcelas := '3'.

149 // pagamento com no máximo 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 descrição 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 integração com o cliente. No caso de uma promoção é possível dar 10% de desconto aos clientes que compram entre os períodos A e B, ou que nasceram em uma data especifica. Se o CRM estiver ligado com um sistema CallCenter (telefonia), o próprio sistema liga para o cliente e coloca da base de dados do cliente os funcionários que atenderam esse cliente pela última vez. O sistema CallCenter liga para o cliente verificando qual funcionário que falou com esse cliente pela última vez, então busca outro vendedor ou atendente que não seja o último que falou com o cliente, porque pode ser que o cliente não tenha sido bem atendido pela ultima vez e descarta esse vendedor. Após estabelecer contato com o cliente o funcionário se identifica e com um script pronto na tela, desenvolve um dialogo anotando fatos indispensáveis para um relacionamento mais próximo com o cliente, para quando ligar outra vez vai falar desses fatos, dando a impressão ao cliente que o conhece muito. Para efetuar uma venda, o vendedor informa uma promoção para esse cliente, com forma de pagamento em 60 dias – um diferencial – de uma maneira que obrigue o cliente a comprar, tentando forçar uma venda. Quando efetuamos uma venda com o sistema CRM, no campo de observações, anotamos fatos pessoais do cliente: do que gosta, o que faz – isso para criar um vinculo de relacionamento. Quando terminar uma campanha, através dessa ferramenta é possível saber quanto foi vendido, quantos clientes compraram e quantos não compraram, qual tipo de reclamação foi relatado. Com base nesses dados e outros anotados é possível fazer uma mudança na empresa.

12.1 - BI – (

) - Negócio Inteligente

É uma ferramenta para extração de dados. O funcionamento baseia-se em extrair dados das tabelas de um banco de dados, fazer combinações desses dados para tomada de decisão gerencial. Uma tabela do banco de dados tem vários atributos, por exemplo: código do produto, descrição, valor, nome do cliente, endereço, etc.. Com esses dados, essa ferramenta gera um cubo de decisão, combinando informações e transforma num cubo 3D. Cada combinação gera uma informação diferente que podem ser infinitas. Diferente de uma consulta em SQL, se fizermos um relatório 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 implementação 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 - Descrição: 12.2.1.1 – DecisionCube. Neste componente é efetuada toda a programação que existe – comparado a um componente DataBase da paleta BDE. Acrescente um objeto TdecisionCube a um form ou data module para permitir uma aplicação para representar o cruzamento de dados. TDecisionCube analisa os dados de uma fonte de informações para uma estrutura multidimensional onde cada dimensão corresponde a uma sumarização (um resumo). Alguns dados podem ser usados como fontes de um objeto TDecisionCube, mas é mais fácil trabalhar com TDecisionQuery. TDecisionCube possui propriedades e métodos para formatar dados para um componente TDecisionSource que, por sua vez, disponibilizará para os componentes TDecisionGraph e TDecisionGrid Usualmente, os valores resumidos são calculados para o dataset que é a fonte do decision cubes. Contudo , valores médios podem ser calculados internamente em vez do Decision Cube. Médias 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 métodos que liga uma tabela para fornecer estes dados a um TDecisionSource. Decision grids e Decision graphs não recuperam dados diretamante do decision cube. Eles usam um TDecisionSource, que representam uma configuração da dimensão do TDecisionCube. O componente decision cube, TDecisionCube, suprimento de dados multidimensional que busca estes dados de um dataset (tipicamente uma estrutura especial SQL declarada através de TDecisionQuery ou TQuery). Os dados são armazenados em um formulário que produzem dados fáceis de pivotar (isto é, mudam o sentido em que os dados estão organizados e sumariza) sem necessidade de rodar a query.

152

12.2.1.2 – DecisionQuery. Comparado a uma Query comum, neste componente a programação é 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 dimensões e sumariza para definir diretamento no dataset analisando em um decision control. Então fazemos uma SQL query para providenciar a informação daquele dataset em um formato que pode ser usado pelo decision cube. Decision cubes pode usar outros tipos de datasets, mas a informação pode ser estruturada no mesmo caminho para a saída 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 necessário) dentro do dialeto usado pela fonte de dados da query. Use somente padrão 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 dimensões do decision cube de linhas e colunas. TDecisionSource também fornece métodos para mostrar a dimensão para focar em um sumário um valor simples ou ocultar ou mostrar dimensões no pivô. Todos os controles de decisão que divide uma fonte de desisão mostra o mesmo estado do pivô. Por exemplo, um formulário pode conter uma decision grid e um decision graph lincados com o mesmo decision sourse. Pivotando a dimensão do decision grid fará automaticamente um update da imagem do grafico tratado. Para o display separar em duas projeções da informação 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 manipulação 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 votões que coprrespondem as dimensções ativas de um decision cube e um drop-down list box para escolher o sumario desejado. Pressione os botões de dimensão para abrir ou fechar a dimensão, controlando se o decision source fornece valores para outras dimensões. Clicando o botão do decision pivot é restabelecido um menu que permite usar o controle de estado da dimensão. Exercita o focus da dimensão em um valor simples com a dimensão. Arrastando os botões de um decision pivot reorganizamos as dimensões do decision source dentro de uma nova configuração do pivô.

153 Nota: Não use o Decision pivot para pivô, subtotal, ou exercicio no sumario que não será aditivado. Sumários SUM e COUNT sao aditivados, AVERAGE (a menos que calculado pelo Decision cube), MAX, e MIN não. 12.2.1.5 – DecisionGrid Utilize um TDecisionGrid para adicionar um decision grid no formulário. Decision grids apresenta um sumario simples que é calculado sobre um numero arbitrário de dimensões. As dimensões podem aparecer como linhas ou colunas na grid, com o valor de campo das dimensões listadas como labels ao longo do topo e na borda esquerda da grid. O campo que é sumarizado e os campos (dimensões) que são sumarizados por cima podem ser chamados dinamicamente após rodar para mostrar algumas configurações do sumario e dimensões fechadas para o mapa de dimensões do decision cube. Para chamar as dimensões e sumarios, esta pode ser inicializada pela manipulação direta decision grid, ou usando o objeto TDecisionPivot . TDecisionGrid possui propriedades, eventos e métodos herdados de TcustomDecisionGrid, mas não introduz novos comportamentos. Para apresentar os dados de um gráfico, use TdecisionGraph.. 12.2.1.6 – Decision Graph Utilize TDecisionGraph para colocar um decision graph em um formulário. O gráfico Decision graphs é um sumario simple que é calculado por cima de um número de dimensões. As astes do gráfico correpondem a estas dimensões, que são providenciadas por um objeto decision source. Por padrão a primeira linha da dimensão apresenta-se como o X do eixo e a primeira coluna da dimensão apresenta-se como o Y do eixo. A área que é sumarizada e as áreas (dimensões) que são sumarizadas por cima podem ser mudados dinamicamente para mostrar algumas configurações do sumario escolhendo o dimension map de um decision cube. Mudanças para as dimensões e cumarios podem ser inicializadas usando um objeto TDecisionPivot. TDecisionGraph utiliza muitas das propriedades, eventos e métodos herdando de TCustomDecisionGraph, mas não introduz novos comportamentos. Para apresentar os dados em uma grid, use TDecisionGrid. Dimensões(Dimensions) – Campos usados para as linhas e títulos de uma coluna e que não levam sinal de igual. São os botões que clicamos para abrir no DecisonPivot. Resumos(Summaries) – Todos os campos que tem agregação(sum, count e average). Os campos do banco de dados que iremos usar tem: data do pedido, idade do cliente, categoria, opcionais e valor.

Categoria. percentual. médio.DB no paradox. verificar o valor médio. COUNT( Data_ped ). 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. Idade_Cli. etc. SUM( Valor ) valores.). Temos também uma totalização que podemos somar. . Valor. Opcionais.154 Para o exemplo crie no Paradox a seguinte tabela: Figura 61 – Tabela Vendas. Opcionais.  Salve a tabela como Vendas. Categoria. Idade_Cli. Valor É aqui que são colocados os campos que aparecem em percentual. mínimo.DB Esses campos são os dados que entraram na programação do SQL que queremos buscar. COUNT( * ) COUNTALL FROM vendas v GROUP BY Data_ped. por valor máximo. Esses campos são os que também poderão entrar na programação do SQL SELECT Data_ped. contar.

MÉDIA. . Da Paleta Standard . tem que aparecer dentro do value por SQL. Os campos agrupados tem que serem feitos com o comando Select.3 – Criando uma aplicação exemplo  Crie uma nova aplicação com os seguintes componentes: Da Paleta Win32 . Colocamos na programação SQL só os valores que queremos na consulta. 12.1 Panel Da Paleta BDE . respectivamente. colocaríamos 10 tabelas com clausula “Where” fazendo as ligações dos códigos das tabelas ou valor de uma tabela igual ao valor de outra. só estamos utilizando uma tabela de eventos.1 PageControl com duas abas.  Acrescente o Componente DecisionGraf na Aba Gráfico. mas se tivermos 10 tabelas. O Formulário ficará com o seguinte aspecto: Figura 62 – Formulário exemplo do Decision Cube. No exemplo.155 Como estão agrupados.  Selecione a PageControl e coloque o nome das abas na propriede Caption: Dados e Gráfico. todos os campos que não pertencem a um SUM.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. Vamos fazer um SQL indicando campos normais.

3. Então indicamos quem abre dimensão e quem é sumario. Para acessar a tabela. exemplo: C:\Alunos\software\Dados\) Para acessar a tabela usaremos um comando Select do SQL (Select * from vendas) mostrado logo mais. Escolha para o Driver name: STANDARD  Clique no Defauts da tabela e coloque o nome do diretório após o PATH. . 12. Figura 63 – Parâmetros do DataBase. só colocamos o Path (nome do diretório.156  Ligue o componente DataBase ao banco de dados criado anteriormente.  Na propriedade do componente DecisionQuery indique em DataBaseName o nome do DataBase = teste. Nesta tela aparecem todos os campos.1 .Decision Query  Duplo clique no componente DesisionQuery Abrirá a tela abaixo.  Coloque em Name do DataBase o nome: teste.  Escolha a tabela vendas no campo table que alias é única.  Clique em OK  Nas propriedades do componente DataBase coloque Connected = true.  Desmarque Login prompt.

podendo escolher o número de registros. A soma não arrastamos. COUNT E AVERAGE. Opcionais e Valor.157 Figura 64 – Decision Query Editor. é aquele que aparece no canto e selecionamos os valores que irão aparecer. Clique em SQL Query para verificar: . podemos definir os SUM. Os campos que irão compor a dimensão são aqueles que podemos arrastar de um lado para outro para aparecer na linha ou na coluna da Grid. nas SQLs. Após selecionar os campos dentro da Dimensão e do Sumario o sistema automaticamente gera o SQL. colocamos na Dimensão e tudo que tiver de somatório colocamos no Sumario. a média – é o valor que vai aparecer na Grid como valor de campo. Tudo que tiver campo normal. Nesta tela clicando nos campos da lista da esquerda (List of Available Fields) podemos adicionar para a coluna das dimensões (Dimensions) os campos que desejamos apresentar. a soma. Categoria. como por exemplo: Data_ped. No resumo (Summaries) colocamos os campos que sofrem agregação. podem ser contados e levam sinal de igual. Idade_Cli. por exemplo.

Selecionamos qual SQL da tabela (que é o nome dos campos que vamos mostrar).158 Figura 65 – Comandos SQL para a tabela do Decision Cube. Indicamos o nome da tabela (FROM vendas) e indicamos um GROUP BY em todos os valores que não forem totalizados. 12.  Na propriedade do componente DecisionQuery colocar Active = true. COUNT. temos que colocar no campo (SUM. onde podemos escolher a quantidade de registros que quisermos. É responsável por efetuar a análise dos dados em um dataset e montar a estrutura multidimensional em que cada dimensão corresponde a um campo do dataset sobre as informações que devem ser resumidas. MEDIA) da programação SQL. é o coração do processo.2 . . tipo grade do Ecxel. conforme exemplo do quadro acima.3. Se tiver somatória media. Ao clicar em MemoryControl. aparece o numero de registros. ou contar o número de registros.DecisionCube  De duplo clique no componente DecisionCube DecisionCube é o componente que executa as combinações.

Figura 67 – Formatação da Data no Decision Cube. colocamos dois campos tipo Data (Data1 e Data2). ano. No nosso exemplo utilizamos o agrupamento por ano. . Se quisermos totalizar com duas datas. então podemos saber a venda por mês e por ano. que pode ser por mês. a primeira data chamamos de Data1 que usaria o mesmo campo (Data_ped) da Data2.159 Figura 66 – Controle de memória do Decision Cube Editor. Ao clicar em Dimension Settings. O Data1 podemos totalizar por mês e a outra por Ano. Por padrão no campo Grouping aparece “none” (campos não agrupados). o único que agrupamos é a data. aparece todos os campos na coluna Available Fields. podemos colocar um Label para indicar Data1 e outro para indicar Data2. trimestre. Na programação do SQL colocamos duas datas.

Executando o Aplicativo Com uma base de apenas 20 registros é possível demonstrar a ferramenta num bando de dados de uma revenda de automóveis.  Salve o projeto 12.6 .4 .5 . O banco de dados tem os seguintes campos: Idade do cliente.4 . podemos colocar a janela de gráficos e preenchemos a propriedade DecisionSourse.3.DecisionGrid  A Grid é o componente DecisionGrid – a propriedade a ser preenchida é o DecisionSourse. 12. categoria do veículo.3.160 12.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. o valor de venda do veiculo e a data de compra.Na combinação feita é mostrado que foram vendidos 14 carros com ar e 6 sem ar condicionado num total de 20.DecisionGraph Se quisermos um gráfico. . Figura 68 – Amostra de Opcionais vendidos.4.DecisionPivot  Os botões de comando é o componente DecisionPivot e a única propriedade que preenchemos é o DecisionSourse nas propriedades do componente. 12.Exemplo 1: Podemos saber quantos carros foram vendidos com e sem ar condicionado . 12.3.3 .1 . opcionais que foram vendidos. 12.

Isso pode ser visualizado num gráfico. Então o cliente com mais idade sempre vai comprar um carro que tem ar condicionado? Na maioria dos casos do exemplo.4. se é com ou sem ar condicionado. Porque? Provavelmente está mais estabelecido financeiramente e tem condições de comprar esse opcional. então verificamos que pessoas de 24 a 36 anos tem a tendência de comprar carros que tem ar condicionado. o cliente que tem uma idade entre 18 e 19 anos.Exemplo 2: Se quisermos saber por idade. sim. Se pensarmos. .2 .161 12. está comprando seu primeiro carro – Estamos extraindo informações. a ferramenta mostra para cada idade que tipo de compra é efetuada pelo cliente. Figura 70 – Amostra de idade e opcionais. Figura 69 – Gráfico de amostra por idades de clientes.

12. mas no caso da perua o valor médio subiu muito. a idade e os compradores por tipo.Exemplo 5 Se quisermos descobrir a evolução das vendas por ano. 12. tanto compra um Sport Utilit. pegamos um contador (quantos esportivos foram vendidos na faixa de R$ 30. por categoria.4. De 45 anos é equilibrado. Selecionando a categoria. podemos colocar a Data e o Valor das vendas por ano. Então podemos descobrir por essas combinações as categorias que são adquiridas em determinada faixa de idade.00 12. Podemos saber também quantos carros vendem por cada faixa de preço.. – Verificamos que foram vendidos os carros na faixa de R$ 35. selecionando o campo data de venda por ano.Exemplo 8 Podemos ver a venda só em relação a 2004. Podemos saber que tipo de caro vendemos a cada preço. o valor de venda.6 . colocando o valor e a categoria.00. Nestas combinações podemos ver tanto em formato de dados . Perua é a mesma coisa.4. No exemplo pesquisado verifica-se que carro Esport Utilit praticamente não vende sem ar condicionado. verificamos que na faixa de 24 anos o cliente compra uma perua. em vez de valor. No caso do esportivo é o que mais subiu de preço em relação ao ano anterior. Agora. Um Esport Utilit vende bem mais carro. o Sedam praticamente empata com ou sem ar. As vendas de cada ano podemos comparar com a faixa dos valores dos carros. mas se colocarmos uma perua nova no mercado sem ar condicionado.4 .000. verificamos que são vendidos na faixa de R$ 35.  clique com o botão direito e.4. pelo exemplo não será vendida. como um Sedam.162 12. como mostra na ferramenta. quantos da faixa de R$ 35. Uma perua está na faixa de preço de venda de R$ 36. Então podemos calcular o valor do preço do produto atual.4. Essa pesquisa pode mostrar as categorias que não vendem sem ar condicionado.00) 12.5 . quanto em formato de gráficos.4. provavelmente será vendido.Exemplo 6 Podemos saber quem é o comprador de cada categoria – quem é o comprador de um Sport Utilit..7 -Exemplo 7 Podemos verificar o volume de vendas e o valor médio de cada caro por ano. 12.000. O valor médio no caso do Esport Utilit tem permanecido o mesmo. – Estamos descobrindo padrões. Se for colocado um carro Sedam sem ar no mercado. De 25 o cliente compra um Esportivo. De 36 anos compra-se um Esport Utilit.000.Exemplo 3 Se quisermos saber qual a categoria de carro que mais vende com ar e sem ar condicionado: Pode aparecer no gráfico.00. Se for zero(0) é porque no ano anterior não foi vendido nenhum.3 .8 .4.00.Exemplo 4 Se quisermos saber como tem sido a evolução dos valores desses carros: Exemplificando carros esportivos.000. .000.

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. contendo as seguintes características: a) Impressora Fiscal b) Componente de Código de Barras c) C2 d) Decision Cube (BI) – com relacionamento de 3 tabelas.10 – Exercício Trabalho: Com base no sistema dado em aula (Vendas).163 Ver as vendas só de 2005 ou também em todo o período.Exemplo 9 Por opcionais. Podemos comparar os valores ao longo dos anos ou por mês. 12.9 . . faça a modificação do mesmo. Abrimos a dimensão e fazemos o comparativo do ano de 2004 e 2005.4. podemos saber o valor médio.

Podemos guardar uma String. estaremos usando a caixa postal daquele email para manda para outros endereços. o que mais compra .então colocariamos esse endereço de email (um email retorno). verifique através do outlook e manda baixar seus emails.Funcionamento da ferramenta . Podemos colocar o assunto ou span direto.Diferença ente servidor ftp e pop3 Do lado do cliente.1 . .CORREIO ELETRÔNICO Podemos enviar via email. Abra e verifique se chegou o email teste.Demonstração . Só um endereço de email e a senha.Podemos anexar um ou mais arquivos (um orçamento por exemplo). Se tivermos um servidor de email. depois adicionamos o banco para a consulta e fazemos um span de verdade. Então a ferramenta usa esse email para fazer um Span. Podemos fazer um teste enviando para nós mesmo um email através da ferramenta. etc. verificamos todos os clientes que gosta daquele novo produto e passamos um email. mandando um prospecto do jogo. o produto que mais vende.Email no Delphi . Na pesquisa feita no BI é fácil descobrir qual o perfil do cliente. Não fica no servidor. Neste caso podemos ganhar novos clientes sem precisar efetuar ligações via telefone..Pode ser requisitada uma confirmação do recebimento do email.2 . mas poderia ser colocado de um banco de dados (uma string). dizendo que chegou tal tipo de jogo neste email podemos anexar um arquivo do ofice. através de um comando select (seleciona os clientes e passamos um span para todo mundo). e consultando na base.com. a imagem do jogo.Pode ser enviado para vários endereços de email com cópia. Neste exemplo foi colocado um endereço fixo. uma propaganda de um novo produto ou um novo serviço. . 13. . username e a senha para conectar. .Pode ser definida a prioridade do envio do email (baixa.Abrimos um email em qualquer servidor de email.Quando executamos esse programa aparece o campo onde pode ser colocado vários endereços de emails. acessar essa string posteriormente e colocar no email para envio. . No FMTP temos que enviar: endereço de origem do email (endereço de resposta) a partir da conta que queremos enviar o email e a mensagem ou destinatário.164 13 . média ou alta). Então chega um produto novo. A primeira versão do aplicativo não tem um banco de dados. 13. o protocolo de envio de amail é o FMTP. Vamos supor que uma loja de CD de jogos tem no cadastro de clientes os tipos de jogos preferidos por esses clientes. por exemplo: suporte @unilins. depois achamos o publico alvo e enviamos uma mala direta para esse cliente. Para verificar se o email foi enviado.br . só passa por ele e é enviado para os outros. igual ao endereço do servidor (IP do servidor). o que da para fazer nos jogos. se quisermos enviar um email. pelo BI através da internet. O que é preciso ter .

. o resto é tudo automático: a importação. Tudo isso é automático no banco de dados. gerando um padrão de comunicação com o banco (um arquivo txt. O único trabalho é clicar um botão e importar o arquivo que estamos recebendo do banco. a senha e retornando a mensagem. Todo mês temos que mandar uma chave para o usuário (um número que vale por 30 dias). Precisamos enviar a mensagem indicando o destinatário. importação). Quando o cliente pagar o boleto no banco.Teoricamente o POP3 é bem mais simples que o FMTP. No nosso exemplo não fazemos um programa para email. Para fazer uso. geramos um arquivo (igual contas a pagar e a receber) e mandamos para um banco escolhido. esse retorna para nós um arquivo txt também. porque já tem muitos no mercado. Enviamos esse arquivo de cobrança para o banco.  File > New > Application Acrescente no formulário: 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: .Criando o Formulário  Abra um novo projeto.165 . a origem. Damos a baixa no pagamento e já envia por email a senha para mais 30 dias de uso. O que temos que fazer é enviar os dados para um servidor. Um exemplo de caso peculiar: temos um software e alugamos esse software por mês e todo final do mês ele expira.3 .O protocolo POP3 é o que recebemos mensagem. tipo arquivo de exportação. Todo dia exportamos esse arquivo txt para o banco e quando importar o arquivo txt de volta e sabendo quais os campos. Para executar o teste crie um conta de email para executar o nosso programa 13. Fazemos um algoritmo no programa e depois de 30 dias expira comparando datas criptografadas. Esse arquivo txt é padrão e informa qual o cliente que pagou. Para executar nosso exemplo é necessário ter uma conta de email que consiga abrir no Outlook e um servidor FMTP. vamos no banco de dados para verificar quais são os clientes que pagaram. Vamos fazer nosso sistema para enviar email e não é só para propaganda. a baixa no pagamento e o envio do email ao cliente.

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 formulário ficará com o aspecto mostrado abaixo: .

São três formas de enviar os emails . .3.3.1 .CheckBox Confirmar recebimento  Por padrão checkd = false.  O item padrão será a Alta (Item index = 0). Media e Baixa prioridade. 13.167 Figura 71 – Formulário de email no Delphi.Na propriedae Items do combobox.Memo O memo é parecido com o Edit. No nosso exemplo colocaremos por padrão em Alta Prioridade.2 .Normalmente a prioridade dos emails estará na média que é o normal. 13. Em propriedade Line do memo pode deixar em branco ou deixar uma mensagem. a diferença é que o memo pode ter várias linhas de texto e quanto terminar o quadro do texto gera uma barra de rolagem para continuar escrevendo. no caso: Alta. cadastrar os itens necessários. .

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 disponíveis. É usado para: abrir todos os arquivos (*.*), Documentos(*.Doc), Imagens (*.Jpg, *.Gif, *.bmp) e Executáveis (*.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 parênteses (*.DOC) para saber o que buscar fica melhor, senão aparece só o asterisco e não 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 (Diretório Inicial) - Se não for colocado nada, vai começar a partir do diretório que estava com .exe. Se tiver iniciado com meus documentos, o programa entra no arquivo e começa a abrir esta pasta. - se quiser abrir em outro diretório, por exemplo a partir do disco “C”, então coloque C: - O FileName não é para ser preenchido a não ser que seja preciso salvar o arquivo. Na hora que o usuário 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 é extensão .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 padrão é o meMIME.  Na propriedade from, clique no sinal +.  Crie um email para teste em um provedor

Temos que preencher a Web - Address (o seu endereço de Email para o cliente retornar depois). Name - o nome que queremos que apareça 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 conecção para enviar email. IdsMTP - Esse componente é que vai gerar realmente a conexão 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 máquina ou o nome da máquina. Mais fácil colocar o nome. Ex: smtp.bol.com.br. Propriedade Port: A porta por padrão é a que já mostra, mas tem alguns provedores que mudam essa porta. Propriedade Username - nome do usuário da conta criada. Propriedade Password - A senha para acessar a caixa postal. Propriedade MaxLineLength - Numero de linhas - por padrão, para a mensagem tem 16K (16 mil caracteres). Propriedade Authentication - Se o programa requer alguma autenticação, então selecionamos. Por padrão a maior parte não requer autenticação antes, podemos enviar mensagem com a senha junto. Existem provedores que primeiro faz a autenticação para depois enviar mensagem.

13.4 - A programação.
Temos duas programações - uma no botão anexar e outra no botão enviar 13.4.1 - Botão 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 não foi selecionado nada, então não 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 começar anexar, ao abrir o formulário temos que limpar este ListBox (LB_Anexos) Para limpar  clique em ListBox - eventos - onClick - escolha Btn_LimparClick e faça a programação :

172

Figura 76 – Object Inspector do componente LB_Anexos (TlistBox).  Clique em Btn_LimparClick e acrescente a seguinte linha de programação.  OU Clique direto no botão limpar para abrir o modulo de programação e acresente a programação. procedure TForm1.Btn_LimparClick(Sender: TObject); begin LB_Anexos.Items.Clear; end; Agora temos um botão para anexar e outro para limpar. 13.4.2 - Botão Enviar Programação: procedure TForm1.Btn_EnviarClick(Sender: TObject); var xAnexo : Integer; {numero de anexos} xAnexo: Variável para controlar o número de anexos. begin // Grava os dados da pessoa que ira receber o email IdMessage.Recipients.EMailAddresses := Edt_Para.Text; EmailAddresses: - O endereço para quem vai ser enviado. IdMessage.CCList.EMailAddresses := Edt_Copia.Text; EmailAddresses: A lista de endereços que vai ser enviada cópias. IdMessage.BccList.EMailAddresses := Edt_CopiaOculta.Text;

Text := IdMessage. O conteudo da mensagem: Subject: Assunto.Strings[xAnexo])). A propriedade ReceiptRecipient é a resposta e temos que passar para ele qual o endereço de resposta (o endereço de email) para o destinatário enviar a resposta.From. 1 : IdMessage.create(idmessage. Então temos que indicar para quem vai ser mandado o correio. .Items. não teremos retorno de resposta. Normal ou Baixa) // Trata o assunto e conteudo da mensagem IdMessage.Priority := mpLow.ReceiptRecipient. Se a propriedade estiver em branco. Se a propriedade estiver preenchida já retorna uma resposta automática.MessageParts. 2 : IdMessage.ItemIndex of 0 : IdMessage. //Trata a Prioridade da mensagem case cbxPrioridade. informando que a mensagem foi lida. Nos campos acima é tratada a prioridade das mensagens (Alta. sendo que o usuário terá que clicar em responder.Priority := mpNormal.é o email que será enviado de volta confirmando a leitura pelo destinatário. //Tratando os arquivos anexos for xAnexo := 0 to LB_Anexos. Body (conteúdo da mensagem): são as linhas inseridas no corpo da mensagem.Items. end. Passamos o mesmo endereço de envio.From. // Auto Resposta IdMessage. Este componente é o que vai ser construída a mensagem de texto.Body := mmMensagem. quem vai receber cópia e quem vai receber cópia oculta.Texte: Retorna o nome de usuário e o endereço de Email .Text.Subject := Edt_Assunto.173 EmailAddresses: Lista de endereços com copia oculta.Priority := mpHigh.Text.Lines.Count-1 do TIdAttachment. TFileName(LB_Anexos. if cbxConfirmaLeitura. então automaticamente já está colocado o endereço de resposta. IdMessage.Checked then IdMessage.

Passamos como parâmetro quem vai receber as mensagens (idmessage) e o nome do arquivo a ser enviado (LB_Anexos.String[xAnexos]). IdMessageCoder. anexo numero dois.Items. IdComponent.MessageBox('Email enviado com sucesso!'. IdSMTP. finally IdSMTP. Quando foi clicado em sMTP já foi dado o “use” e entre as classes disponíveis tem a classe TIdAttachment que compacta o arquivo para poder enviar junto. Variants. StdCtrls.O “T” é o tipo . IdMessageClient.estamos chamando uma classe para fazer a compactação.Programação completa do aplicativo unit U_Envia. O MessageBox escreve a confirmação. IdTCPConnection. end. IdMessageCoderMIME. IdSMTP. interface uses Windows. Diferente de Exception o comando finally independente de enviar ou não a mensagem desfaz a conexão. Application. Este comando envia a mensagem passando como parametro a mensagem a ser enviada. MB_ICONINFORMATION + MB_OK). type TForm1 = class(TForm) . Dialogs. Messages.Connect.create . Controls. etc). IdMessage. Será feito um for que varia de zero até o numero de elementos menos um. try IdSMTP.Disconnect. 'Confirmação'. Esta linha faz a conexão. IdTCPClient.Send(IdMessage). Classes. 13.5 . Graphics. Forms. Neste campo indica que o email foi enviado com sucesso. Conecta com o provedor e envia a senha. anexo numero um. (anexo numero zero. end.  Salve > compile e execute o programa.174 TIdAttachment. SysUtils. IdBaseComponent.

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!', 'Confirmação', MB_ICONINFORMATION + MB_OK); end; procedure TForm1.Btn_LimparClick(Sender: TObject); begin LB_Anexos.Items.Clear; end; end.

177

14 – CONEXÃO ADO
ADO (ActiveX Data Objects – Objetos de dados ActiveX) – Uma camada sobre o OLE DB e é referido como uma interface em nível de aplicativo. Tem semelhança com o BDE e tanto um como o outro suportam navegação e manipulação de conjuntos de dados, processamento de transações e atualizações em cache (chamadas atualizações em lote, no ADO). O ADO é de tecnlogia da Microsoft e é muito bom para Bancos da Microsoft, ASP e SQLService. Desde a versão do Delphi 2 já existe a conexão via ADO, é um tipo de conexão antiga que tem permanecido por conta da Microsoft, mas podemos fazer conexões 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 padrão que liga uma aplicação para acessar diferentes fontes de dados. As fontes de códigos de aplicações não devem ser recompiladas para cada data source. Um database driver liga a aplicação para um data source especifico. Um database driver é um dynamic-link library que uma aplicação pode invocar exigindo um acesso para um data source particular. Portando, a aplicação pode acessar algum data source para que um database driver exista. A interface ODBC define o seguinte:
    

Uma função library of ODBC que permite chamar uma aplicação para conexão com um data source, executando SQL statements, e recuperando resultados. Sintaxe SQL baseada na especificação SQL-99. Um conjunto de código de erros padrão. Um caminho padrao para conexão e login com um data source. Uma representação padrão 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 também tem a conexão, 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 página da paleta de Componentes faz a conexão ao database information usando ActiveX Data Objects (ADO): ADOConnection Estabelece uma conexão com um ADO database e fornece suporte para transações. 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 conexão com um componente DataSource. Este é o controle mais genérico 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 conexão com um componente DataSource. Utiliza declarações SQL para recuperar dados de uma tabela de banco física via ADO e permite componentes data-aware para manipular estes dados fazendo conexão com um componente DataSource. Torna possível uma aplicação acessando stored procedures em servidores usando ADO. Gerencia a organização dos dados quando um objeto Recordset é passado de um processo ou maquina para outro. Utilize TRDSConnection quando contruir aplicações multicamadas usando business objects (Application Servers).

ADOTable

ADOQuery

ADOStoredProc

RDSConnection

14.3 - Como criar uma conexão.
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 máquina especifica para isso. Se a base de dados for remota, estiver em outra máquina, temos que salvar os dados remotamente, tendo a concorrência de outras CPUs que também estão salvando os dados no mesmo Banco de Dados. CPU CPU

BD CPU Figura 78 – Clientes e banco de dados. CPU

179

Para fazer a conexão com o Banco de Dados, primeiro temos que criar essa conexão e indicar onde vamos gravar esses dados. No caso do Oracle existe um arquivo no diretório dependendo da instalação : C:/oracle/Net80/Admin. Test Message - De duplo clique neste arquivo. Esse é o arquivo de configuração e indica o local em que se encontra o banco de dados. Esta porta é a porta que o oracle está ouvindo, porque dentro da máquina pode ser instalado além do Oracle, o Interbase, SQLServer, etc... 14.3 1 - A Porta Temos um servidor com endereço 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 formulário chamado SERVICE. Tudo que fazemos em cima desse sistema é através do SERVICE. O sistema faz um chamado. O que é esse chamado? - O usuário pede ao servidor que imprima a página atual. Essa página é impressa e entregue ao cliente. - No email é pedido ao servidor um serviço, é digitada a senha e o serviço busca a mensagem. Basicamente tudo trabalha com serviço da mesma forma que temos serviços em nosso dia a dia. Se o servidor fosse uma cidade e dentro dessa cidade tem vários serviços(de correio, limpeza pública, segurança, educação). Cada serviço tem um endereço, situado em uma rua e um número. O servidor trabalha da mesma forma, todo serviço que ele executa tem um endereço, esse endereço é a porta. Dentro de um servidor tem vários serviços: na porta 80 – internet, na porta 21 – FTP, na porta 1521 – o oracle). Qualquer serviço que se abra tem um número de porta e nunca dois serviços pode estar na mesma porta porque dá conflito de endereço. Quando mandamos um pacote para uma máquina. Se estamos no cliente e mandamos algum pacote de comunicação, esse pacote sai do cliente para o servidor que tem um cabeçalho e vai compor a seguinte escolha: - Qual o IP da máquina de origem, por exemplo 10.2.0.50 -> nesta máquina é a porta 50. - Porta de origem: A porta que esta enviando, supondo que a porta seja 10.20. - Endereço IP da máquina de destino: a porta do servidor que vai receber a mensagem(pacote) na porta 1521. Quando esse pacote chegar no destino, alguém recebe e envia para a porta (endereço) correto. Se for para a porta 1521 do Oracle – ele executa e responde para o endereço IP de origem. Em resumo: Trabalha coma porta de origem e de destino (endereço de origem e endereço de destino). Cada vez que vai mandar mensagem de uma máquina para outra tem que ter o endereço e porta de origem e na hora que mandar o pacote de volta tem que mandar exatamente para o mesmo endereço. Para bloquear o endereço de uma porta é só desabilita-la. O Firewal para bloquear portas faz o seguinte: As portas que não estão sendo utilizadas, não 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 vírus dentro dessa

4 . Para evitar que alguém invada uma máquina mandando um pacote e responder alguma coisa que não deveria. 14. o firewal então desabilita essa porta. Fechamos o arquivo. na máquina. então libera o acesso. Entre os vários serviços que podemos acessar.Criação de conexão via ODBC. Essa conexão vai se chamar ORCL.  Iniciar > Painel de controle > Ferramentas Administrativas > Fonte de Dados ODBC. se pode. Essa é a configuração do Oracle. outras pessoas podem acessar a máquina. quando chegar um pacote. procurando em uma lista. Dentro do oracle. Foi criada uma conexão com o Oracle chamada ORCL e vai se conectar com o banco de dados chamado Oracle. envia para o Oracle. acessamos o banco de dados chamado ORCL. Se na máquina não tiver nenhum Firewal ativo e as portas abertas. . Figura 79 – Administrador de fonte de dados ODBC. As portas que estão ativas são monitoras. copiar um arquivo e etc. acessa o servidor. o sistema verifica se o cliente que enviou pode acessar. Com esse endereço válido(habilitado). vamos acessar o serviço 1521. nesta porta o oracle vai responder.180 porta e se chegar o pacote o programa de vírus pode receber e tomar a iniciativa. Se for mandado um pacote para a porta 80 pedindo alguma coisa para o servidor WEB.

No caso usaremos o Oracle. . Figura 80 – Tela para criar nova fonte de dados. O mesmo procedimento para o Paradox ou qualquer outro banco.181 Para criar uma nova conexão é indicada para essa máquina que qualquer coisa que chegar será mandada para o servidor.  Clique em Concluir.Oracle.  Selecione o banco de dados do oracle – Microsoft ODBC para Oracle Se fosse Interbase então coloque esse banco ao adicionar.  Adicionar (ADD) > Microsoft ODBC. No exemplo o servidor é remoto.

em branco por padrão.Instalação do Microsoft ODBC para Oracle. Contém qualquer qualificador descritivo.Caixa de diálogo Instalação do Microsoft ODBC para Oracle A caixa de diálogo Instalação do Microsoft ODBC para Oracle contém os seguintes controles: Nome da fonte de dados O nome ou identificador usado pelos aplicativos para chamar ou usar esta fonte de dados. (Para obter informações sobre construção de seqüências de caracteres. consulte Atributos da seqüência de conexão. consulte o arquivo de ajuda do Oracle. O nome de usuário para a fonte de dados. O alias de banco de dados criado na SQL*Net Easy Configuration ou uma seqüência de conexão. mas é necessário.) Clique em Selecionar para escolher um conversor de dados carregado. Este campo fica em branco por padrão. Os usuários podem usar qualquer método descritivo para nomear uma fonte de dados. o padrão é No translator (sem conversor).5 . 14.182 Figura 81 . Para obter descrições de seqüências de conexão com banco de dados pessoais e remotos. Descrição Nome de usuário Servidor Conversão .

em bytes. sábado = 7). Este driver recupera informações de coluna mais rapidamente quando este valor não é definido (ou quando o valor é definido como 0). alocado para receber dados buscados. segue o formato de dia de semana do Oracle (segunda = 1. Incluir REMARKS em funções de catálogo especifica que o driver deve retornar colunas de comentários para o conjunto de resultados SQLColumns. o driver retornará 0 para estes tipos de colunas. O driver otimiza a busca de forma que uma busca no servidor Oracle retorne linhas suficientes para preencher um buffer do tamanho especificado. Personalização Impor o padrão DayOfWeek do ODBC define o conjunto de resultados com um determinado formato de dia da semana. Observação As informações detalhadas e programáticas sobre este driver estão localizadas em msdn. que contém uma seção denominada ODBC Drivers (Drivers ODBC). SQLDescribeCol sempre retorna um valor para precisão especifica que a chamada SQLDescribeCol retornará 130 para a precisão quando o Oracle não fornecer esta informação. quando definido como True (1). Os valores maiores tendem a aumentar o desempenho quando se busca muitos dados. essa opção especifica que o conjunto de resultados segue o formato de dia da semana do ODBC (domingo = 1.: abra a página MSDN Library Online (Biblioteca MSDN on-line) e a página Platform SDK (SDK da plataforma). Desmarque esta opção para aumentar o desempenho. Caso contrário. . Para obter mais informações sobre os produtos Oracle.microsoft. onde você encontrará o MDAC SDK (SDK do MDAC).183 Desempenho O Tamanho do buffer especifica o tamanho.3 ou posterior. Se selecionada. Se esta caixa de seleção estiver desmarcada. consulte a documentação Oracle. Visualizações e Sinônimos. uma chamada API SQLColumns() retornará informações de coluna para Tabelas. como colunas numéricas calculadas e colunas definidas como NÚMERO sem precisão ou escala.com. domingo = 7). O Microsoft ODBC Driver para Oracle oferece suporte apenas ao SQL*Net 2. Incluir SYNONYMS em SQLColumns especifica que. Alguns tipos de dados numéricos do Oracle não têm uma precisão fixa.

foi dado um nome para essa conexão de ORCL.Nome da fonte de dados: por exemplo Oracle – esse nome vai ser usado depois na programação (é o Alias). vai buscar o ORCL.Servidor = ORCL Quando criamos uma conexão para ligar na máquina cliente nesse banco de dados. 14.A descrição se tiver pode ser colocada.  Esta criada a conexão. Em todo banco de dados tem um componente para conexão. Figura 82 – Formulário com componente ADO. No exemplo apresentado vamos fazer somente em um formulário só para testar essa conexão. então na hora que ele voltar. .  De duplo clique em cima desse componente.  Clique em OK. .User Name = System . .184 Nesta tela preencha: .Para usar no Delphi Abra o Delphi  Clique na paleta ADO.6 .  Coloque o componente ADOConection. Quando abrir o ORCL vai ter o endereço IP da máquina. Figura 83 – Formulário do componente ADOConnection. Esta máquina já sabe quem é o servidor. a porta que vai conectar e qual o banco de dados que vai acessar.

basta utilizar. mas em geral usamos o editor de strings de conexão. mostrado na figura acima. Se não der certo é porque o arquivo TMF está errado. se souber o que está fazendo. Não é necessário criar a conexão porque já esta pronta.  Clique em Testar conexão.185 Ao abrir procure o botão Build  Clique no botão Build para ir direto ao editor de strings de conexão da Microsoft.  Selecione Permitir salvamento de senha. . No campo Use Connection String escolhemos a conexão oracle. Figura 84 – Formulário de propriedades de vinculação de dados. o ADO usa as strings de conexão. Para indicar o banco de dados. Neste campo é feita a opção UserName e senha. É possível digitar uma string de conexão. Vamos procurar a conexão que vai criar que já está pronta dentro do Conect.

Colocando uma tabela.  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: . agora é só criar as tabelas. Já está feita a conexão com o oracle. Qualquer arquivo que for salvo será gravado no banco oracle no servidor.1 .6.  Adicione um componente ADOTAble e preencha como se fosse uma tabela comum.  Clique em OK e OK novamente.  Em LoginPrompt deixe = false. 14. Em propriedade do componente ADOConection:  Connected = true.186 Figura 85 – Fontes de conexão do componente ADO.

compile e execute o programa. existe no ADOTable a propriedade MasterSourseMasterField.  Clique em OK . não muda nada.187 Figura 86 – Aspecto do formulário de teste para conexão ADO.  Salve. A única preocupação é com o gerador de números. Cada um que for conectar. o sistema pede o número da máquina e isso tem que ser feito por você. Se tiver várias conexões acessando o banco com muitas tabelas com o mesmo nome. A conexão também pode ser feita com outro componente em vez de usar o ADO. tem que ser programado no banco. o sitema fica lento. Essas propriedades são semelhantes a uma Table comum.  Colocar o nome do Banco de Dados = ORCL  Nome Username = System  Password = oracle. por exemplo: Teste_oracle. Se for um banco que não tenha uma monte de tabelas com o mesmo nome. Quando cadastrar algum campo. mas depois da conexão o tempo fica normal. Para fazer a conexão do DBExpress. é dado um duplo clique em cima do componente. pode ser usado o DBExpress. o tempo de acesso é rápido. É normal como qualquer outra. Para ligar uma tabela na outra com MasterSourse e MasterField. O ideal é ter tabelas com nomes completamente diferentes uma da outra. A conexão com o oracle é feita assim. Coloque um componente SQLConnection no form  De duplo clique no componente e adicione uma nova conexão do oracle. manda adicionar uma nova conexão do oracle (nome dessa conexão por exemplo: Teste_oracle).

Ligue a tabela (SimpleDataSet).  Adicionar o componte SimpleDataSet. .  Adicione uma Grid e ligue-a ao DataSourse Figura 88 – Grid adicionada ao formulário e ligada ao DataSourse. Propriedade Connection = SQLConnection1 Banco de dados:  Tabela de produtos > Propriedade Active = true.188 Figura 87 – Configurações e conexão do componente SQLConnection.  Conected = true. Em propriedades do componente:  Login Prompt = false.

Suponha que existe uma StoredProcedure programada no banco. Ser for usado por exemplo o componente DBExpress. na propriedade DataSet > Command Type tem os parâmetros: Table.4 é a ordem que está na StoredProcedure.1.189 Note a diferença de perfonmance entre os componentes Microsoft e Borland.2.(???). Também tem a opção Params que são os parâmetros que serão passados para a history procedure (nome. é tudo igual. mas sim com acesso direto. O que não pode é criar um monte de conexão de um Software. Parâmetro um [1] . Se precisar passar parâmetros. o servidor tem que estar configurado. o componente da Borland (DBExpress) não acessa via ODBC. etc). Para passar os dois parâmetros suponha que uma tabela se chama Tbl Então Tbl. menos com o Paradox. quando for colocado o componente SimpleDataSet. Suponha que a StoredProcedure esteja feita. Para acessar essa StoredProcedure.3. O ideal é ter uma única conexão com o Banco de Dados. incluir. Selecionamos History Procedure e colocamos qual StoredProcedure que queremos. endereço. Para funionar bem. aparecerá a tabela referente à senha do usuário. Se for colocados os parâmetros entre colchetes 0. Passamos os parâmetros e colocamos a tabela em active = true.asString) recebe true. Isso é mandado para o servidor. Query e StoredProcedure. O DBExpress funciona com todos os bancos. etc).  Na opção DataSet selecione ComandType = StoredProcedure  e em ComandText selecione atualize. existe a opção params (parâmetros).  Criar uma tabela com um componente SimpleDataSet Propriedade Name = Tbl_Teste. O nome dela está gravada no banco ou selecionamos direto. Dentro do colchete colocamos o parâmetro zero(0). Enquanto o ADO funciona via ODBC. por isso se torna mais rápido e depende de senha porque se for criada qualquer conexão e criar nome. selecionamos a StoredProcedure que existe neste campo (cadastrar. na propriedade (Data Set) Comand type selecione a StoredProcedure.<algumacoisa>: = 3 e depois coloque active = true. O zero é o primeiro parâmetro (. Interbase ou Paradox. depois na propriedade Comand Test. validar. Não tem diferença em trabalhar com Oracle. Poderia ter sido programada uma historyProcedure no servidor. .Params[0]. e Cliper.

 Coloque um componente ADOConection no form. Figura 89 – Formulário para teste de conexão ADO.Um exemplo prático Vamos usar um arquivo Acces MDB instalado pela Borland com o Delphi em C:\Arquivos de programas\Arquivos comuns\Borland Shared\data\dbdemos.190 14.mdb Abra o Delphi  Clique na paleta ADO. .7 . Ao abrir procure o botão Build  Clique no botão Build para ir direto ao editor de strings de conexão da Microsoft.  De duplo clique em cima desse componente que mostrara o editor abaixo: Figura 90 – Formulário do componente ADOConnection.

mdb.4. Figura 92 – Informação de teste de conexão.  Clique em OK  E OK novamente A string de conexão será mostrada no campo Use connection string : Provider=Microsoft.mdb  Clique em Testar conexão.  No campo 1 Selecione ou insira o nome de um banco de dados do endereço: C:\Arquivos de programas\Arquivos comuns\Borland Shared\data\dbdemos.0. Persist Security Info=False .OLEDB. Data Source=C:\Arquivos de programas\Arquivos comuns\Borland Shared\Data\dbdemos.Jet.191 Figura 91 – Propriedades de vinculação de dados.

192 Figura 93 – String de conexão. .  Em LoginPrompt deixe = false.Colocando uma tabela. Em propriedade do componente ADOConection:  Connected = true. 14. compile e execute o programa.  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 formulário usando exemplo de fonte do Delphi  Salve.  Adicione um componente ADOTAble e preencha como se fosse uma tabela comum.7.1 .

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

pode-se mudar a localização (host). E se for um monte de tabelas? Ou se uma tabela tiver 1 Giga? Fica trafegando pela rede um bocado de informações. isso redundaria numa despesa enorme em licenças de uso. terá que desembolsar além do sistema instalado. executa um comando SQL (select * from tabela). lê o banco de dados. o Firebird ou Postgree.1 . principalmente se tiver muitos usuários conectados. seleciona todos os campos de uma tabela. então não tem problema. Para o programador. utilizamos e colocamos um componente no formulário principal (DataBase) com todos os acessos ao banco ligados nele (connection) e ele ligado ao banco de dados (um intermediário). paga uma conexão como banco de dados (não free).000. Cada máquina que for acessar o servidor. Quando trabalhamos com o interbase ou o oracle. todos os usuários irão acessar o mesmo ponto. cem mil reais só com o banco de dados. O que muda é só o caminho (path) do arquivo de configuração. alem de tornar complexa a programação e de difícil manutenção. Se o sistema tiver 10 clientes acessando diretamente um banco de dados pago. este pode estar na mesma máquina ou rodar remotamente e o software acessando esse banco de dados remotamente. . Observe a figura abaixo: Cliente BD Figura 95 – Representação de cliente ligado ao banco de dados. Se cada conexão custar R$ 1. existem outros associados: Numa conexão de rede. entupindo o trafego por melhor que ela seja. Pode-se colocar localhosto ou colocar o IP da CPU onde o banco de dados está localizado. faz uma cópia e passa pela rede.Introdução 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 máquina ou não. Até ai não tem diferença nenhuma se o banco está localizado na mesma CPU ou está remotamente sendo acessado. tem que ser via rede e quando o sistema busca uma tabela.00 e tiver 100 máquinas instaladas com o software para acessar o servidor. Para evitar isso. não faz diferença é só mudar o path. Para acessar o servidor remoto. ficando lento o sistema. Além desses problemas.194 15 – PROGRAMAÇÃO EM TRÊS CAMADAS 15. Dando duplo clique no componente DBExpress por exemplo. Se tiver usando software livre. o Interbase. Manda esse comando SQL para o servidor.

um servidor de aplicação e um banco de dados. E se for mudado o banco de dados terá que ser mudado também o driver em cada uma das estações para acessar o banco. por exemplo: foi comprado o oracle numa promoção ou usando o racle gratuito de 4 Gigas. Se tiver 20 estações. para acessar o servidor de banco de dados tem que ter instalado o Driver do banco que está utilizando.1 . Então resolvem mudar de 25% para 30% e a partir daí terá que modificar uma constante X:= 25 para X:= 30. Se precisar dar manutenção: No sistema estava programada a seguinte conta: Comissão = 0.Todo mundo continua acessando. Após passar a raiva ele pergunta se não tem outro banco de dados para usar e gratuito. ai vai em todas as estações e muda o arquivo “. não gasta mais com um monte de licenças. daqui a alguns meses ele alcança a capacidade máxima de 4 gigas e o sistema para de funcionar. teremos um cliente. Se estiver utilizando o oracle.195 Se tiver usando oracle para dez estações (clientes). Na hora que o cliente tiver o orçamento dos gastos que irá ter. o servidor de aplicação e o banco de dados. Por exemplo: pode ser especificada 30 linhas. tem que estar instalado o cliente do oracle. porque não foi informado antes. ele vai dar um pulo dessa altura. Se a pasta tem 100 registros. criar conexão. só que em vez de trazer o comando Select * from tabela.Antes tinha que salvar a senha de acesso e a localização para cada estação. Mudou o servidor. Toda estação. Note que só tem problemas. 15. terá que reinstalar 20 vezes. toda a programação que tem no banco. Ele vai no banco. será gasto apenas uma licença porque terá apenas uma conexão. 15. trás a tabela selecionada.O cliente. Com 10 pessoas acessando este servidor de banco de dados. Isso é uma tristeza. . Se quiser um banco oracle. Em oracle é utilizada a linguagem PL SQL que é diferente de SQL. mas só que não trás ela inteira. agora tem um componente de conexão que faz uma única conexão com o banco de dados para todas as estações. o cliente. recompila o sistema e gera um novo executável. . Qual o problema a enfrentar agora? Foi criado todo o StoreProcedure em oracle. então é dito ao cliente que agora ele tem que comprar uma “versão de verdade” e que agora tendo 20 estações ele. máquina por máquina.25 * Venda. Divide em pedaços em quantas linhas que foram especificadas. Pode usar um Firebird. ele seleciona os 30 . vai ter que gastar 20 mil (mil reais por cada acesso).2 – As três camadas Para programação em três camadas. .2. “de raiva”. Em resumo. Achou alguma vantagem usando programação em duas camadas? Basicamente é o que todo mundo faz. terá que ser refeita e praticamente todo o sistema vai ser modificado porque o cliente quer trocar de banco de dadas. um Postgree.Todas as estações irão se conectar através do componente chamado DCOMConnection e não se paga nada para fazer essa conexão. Para corrigir esse “pequeno problema” temos a solução em 3 camadas. e ele então quer passar tudo para o Postgree.ini”.

comunicação entre processos. Se trabalhar com dois servidores e por um acaso um deles ficar off-line. isto aumenta a performance do sistema. Quando não tiver mais espaço no cash o SO elimina os registros mais antigos para dar espaço aos mais novos. quando se tem dois servidores. então o sistema é balanceado. esta regra é mudada só no banco de dados e esta mudança fica pronta para a rede inteira sem a necessidade de recompilar no cliente. automaticamente. não estará programado as StoreProcedures no banco. No banco de dados não tem mais as Triggers e nem as StoredProcedures. mas estará programada no cliente. ele estará no cash enquanto tiver memória determinado pelo SO. mudando alguns clientes para outra máquina. Se for necessário mudar de banco de dados. automaticamente as estações localizam outro servidor para se conectarem e continuar trabalhando. terá que ser alterado no formulário do cliente.2 . além de dar segurança aos dados no caso de um dos servidores falhar. Só que a DLL só funciona dentro da mesma máquina. executa o comando select através de uma busca daquele produto e manda somente ele para o cliente. o sistema divide o mesmo numero de CPUs para os dois servidores. 15.2. Quando trabalhamos com DLL.Desvantagem. manda pedaços dessa base para não congestionar a rede e enquanto tiver memória.3 . Toda estação tem uma lista dos servidores. tínhamos dois programas A e B. Se quiser localizar um produto especifico. 15. Outro detalhe: no balanceamento de carga. Se for necessário alterar um botão (um layout). Se for mudada uma regra de negocio. .4 . vai gerar um cash para quando for necessário acessar o mesmo registro não é preciso buscar de novo no banco.2. Então em vez de mandar a base inteira. 15. Com dois servidores de banco de dados é possível fazer uma sincronização.2. Mas existe uma maneira de fazer uma DLL funcionar pela rede (internet). Essa DLL se chama DCOM. roda a SQL de novo e manda mais 30 registros e assim vai mandando pedaços da base com menos de 1K. Essa comunicação é chamada (Dialog ou COM) ou seja.196 primeiros e manda para o cliente e quanto chegar na ultima linha que é a 30. assim fica fácil trocar um banco de dados por outro. colocando metade da rede acessando um servidor e a outra acessando o outro com duas licenças de banco de dados. A partir de agora temos dois programas para executar: um programa cliente e um programa servidor. Se em uma maquina tem muitos clientes conectados. mas tudo dentro da mesma máquina. Era possível acessar uma máquina cliente e uma tabela na mesma DLL.Atualização.Performance Para uma rede que tem um servidor rodando pode-se instalar outro servidor de aplicação.

faz as contas e depois retorna. acessa um servidor que na verdade tem uma DLL. Nesta DLL estarão os métodos e a visibilidade. a diferença é o fabricante. RMI e (CORBA). então o programa refaz a tela (atualiza) e manda para você e para jogar em rede estará usando o DCOM. DCOM vem junto com a Microsoft – os Windows a partir da versão 98 tem o DCOM.3 . O servidor faz os cálculos. ela roda o programa. A DLL está disputando uma porta (porta 2021. Quem quiser usar. este protocolo. Esse procedimento de acessar os dois lados tem três protocolos para fazer isso: DCOM. um histórico Com um cliente é preciso rodar um programa e para acessar um servidor é preciso executar um comando no servidor para que ele mande uma cópia para o cliente. O que muda com o DCOM Por exemplo: Em programa de jogo existe uma mensagem que manda atualizar a tela. que estaria ligada essa DLL. Então é possível acessar os dois lados. um cliente ligado numa determinada porta. Se tiver um valor avariado dentro da memória do cliente.197 15. É possível visualizar as DLLs do Windows através do seguinte endereço:  Iniciar > painel de controle > ferramentas administrativas > serviços de componentes > computadores > meu computador. CORBA – Também faz a mesma coisa. a posição do mouse neste momento já está definida e você refaz a posição para localizar o alvo. tem que estar instalados na máquina. Se num jogo você vai dar um tiro em um alvo. só que o servidor não tem acesso aos dados do cliente. o servidor não consegue acessar esse valor e dar um boot.Antes. Quando chegar qualquer coisa na porta 211. O padrão de comunicação foi definido e está disponível. . 15. Quando roda um programa com DCOM. Para usar. como se fosse um Driver de Banco de Dados. É uma DLL que vai executar através da Internet. Note que o cliente tem acesso ao servidor. 211. O DCOM é uma DLL. assim como os outros. mas não tem acesso na memória e nem no HD do cliente. Então na hora da programação estará tudo em DLL. etc). Os três fazem a mesma coisa e são de fabricantes diferentes.Como o DCOM distribui as tarefas.4 . é de graça. este protocolo é de padrão internacional – aberto. Então tem uma complicação – se for necessário 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 conteúdo da memória e do HD. RMI – Conhecido como Java. busca esse valor. executa o que precisa e devolve.

Cada vez que for compilar.198 Figura 96 – Tela de visualização de serviços de componentes. desligue o servidor. Se for compilar. Nos serviços de componente instalados na CPU estão todos os aplicativos DCOM Na pasta Aplicativos COM+ estão todos os servidores que estão rodando na máquina. porque na hora que for substituir algum dado. Quando for criado o servidor de aplicação para o exemplo e se quiser colocar o servidor no estado ON-LINE para acesso em rede é só clicar com o botão direito do mouse no servidor criado e mandar iniciar o serviço. pode dar erro. faça a compilação e depois ligue novamente. deve parar o servidor. Figura 97 – Aplicativos COM+ em serviços de componentes. Se quiser parar é só clicar de novo e mandar desativar e ninguém mais acessa. .

Pode ser criada uma tabela. mas uma tabela local. Propriedades do componente ClientDataSet:  name = Tbl_Teste Ao criar uma tabela temos que ligar ao banco de dados. 15. Imagine que será feito um calculo: Temos 100 itens para incluir num pedido e cabe 14 itens por nota. Podemos fazer os cálculos simplesmente com a tabela na memória (uma tabela temporária). clique outra vez com o botão direito do mouse. Não é preciso criar um banco de dados inteiro. Esse exemplo explica como trabalhar com o cliente e o servidor de aplicação.  Da paleta DataAccess > selecione ClienteDataSet e adicione no form.  No editor aberto. a partir de agora nos clientes só vai ter a tabela Cliente DataSet. podemos criar campos no próprio local. não no servidor. não só você terá acesso. IBTable.  No editor de campos. Neste caso não é obrigatório.Tabela Temporária Porque uma tabela temporária? Se for acessada a tabela no servidor de bando de dados. assim como outros usuários alterando os registros a todo momento. como se fosse uma tabela. uma tabela com vários recursos adicionais que nenhuma outra tem.Projeto Cliente  No Delphi > abra um novo projeto.Criando uma nova Aplicação.2 . uma tabela que existe só na memória cash. congestionando a rede. ClienteDataSet é uma tabela muito especial.  De duplo clique no componente. É um novo tipo de tabela. No cliente será criada uma tabela temporária. Em vez de usar uma table.5 .5. 15. É so para mostrar um novo componente que vai ser utilizado. Para evitar isso é criada uma tabela temporária na memória e sem registro físico no HD. Para o exemplo será criada uma tabela temporária. É preciso dividir os itens para caber na nota.1 . conforme especificada abaixo.5. clique em novo campo (New Field) para abrir o editor mostrado na figura abaixo. . é uma table turbo. mas sim pequenas partes que serão armazenadas temporariamente e salvas depois no banco de dados que esta localizado no servidor.199 15.

Para cada campo pode ser trocada na propriedade display label o nome do campo que aparece para o usuário e também modificada outras propriedades depois de selecionado esse campo. Criando o DataSet na memória  Clique com o botão direito do mouse no componente e depois no campo CreateDataSet. um de cada vez: Name Type Size Cod (Código) Integer Nome String 30 Qtde(Quantidade) Integer Data Date Valor Float Field Type Data Data Data Data Data Faça para cada campo adicionando na tabela  Clique em OK. Foram criados os campos como se fosse em uma tabela comum. DataSet: Tbl_Teste . A partir de agora esta tabela já existe.  Da paleta DataAccess – coloque um DataSourse Propriedades: name: DS_Ativ.200 Figura 98 – Editor de propriedades Digite os campos do quadro abaixo.

O Resultado da tela é a mostrada abaixo: Figura 99 – Formulário de Teste de tabela temporária.  Com o componente selecionado (tabela – Tbl_Teste) na propriedade Active – coloque true se ainda não estiver ativa. os dados se perdem. mas é só para teste. A única diferença desta tabela é que na hora que o formulário for fechado. o banco de dados estará só na memória.  Salve o projeto e compile  Rode e coloque alguns dados na tabela.Outro exemplo: Numa tela de pedido. 15. Ao rodar o projeto.201  Da paleta Data Controls – adicione uma Grid. ou programar as linhas de comando a seguir para fazer o calculo do total: Tbl_Pedido:= first.5.  Da paleta DataControls coloque um DBNavigator para testes. quando é feito um pedido.  Na propriedade DataSourse da Grid – selecione DS_Ativ. um campo total pode ser criado com um comando SQL para calcular esse total.3 . O DBNavigator neste caso não é necessário. Propriedade DataSourse: DS_Ativ. While not (Tbl_Pedido EOF) do .

E vai acumulando numa variável para mostrar o valor na tela. Fazendo o campo total.  Clique em OK. após criado o campo agregado. Agora o campo faz os cálculos de total e já mostra no final.  Clique com o botão direito do mouse e depois em New Fild. se tentar arrastar ele não obedece e não aparece na grid. No Editor de campos abaixo. .202 Aux:= aux + valor. 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. Campo agregado é campo de total. Como esse campo é feito agora?  Duplo clique na tabela (Componte ClientDataSet). nome que ele aparece separado porque é um campo especial. Na hora que criar um novo campo.

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

.1 .6.6 . Expression contém uma expressão que inclui um mais operadores sumários conforme mostrados na tabela abaixo: Operador Sum Avg Count Uso Total de valores para um campo numérico ou expressão. Computa o valor average para um campo numérico ou date-time ou expressão. 15. especifica o número de valores (campos preenchidos) para um campo ou expressão. Use count(*) para contar o numero de registros em um dataset ou subgroup.204 Figura 102 – Formulário com o campo Total. Observe que se for alterado algum valor o campo total também será modificado. Sintaxe no Delphi: Tipo da propriedade Expression: string. Nota: Não foi feita nenhuma linha de programação no cliente.Descrição Selecione Expression para indicar como os valores agregados devem ser calculados.Propriedades de Expression (TAggregateField) Especifica a fórmula usada para calcular o valor agregado. 15.

ou sumarizando valores e constantes. .do tipo float Field Type: Calculated. use a propriedade GroupingLevel . numeric. De qualquer modo. ou campo date-time ou expressão. 15. Nome do Campo = Total .Field2 { ilegal – não sumário } { ilegal – expressão de sumário e campo} Nota: Para especificar o jogo de gravações sumarizadas por estas expressões . O operador sumário aciona um valor de campo ou uma expressão embutida no valor de campo usando alguns operadores para criar um filtro. ou campo date-time ou expressão. Podemos criar expressões usando operadores sumarizando valores com outros valores sumarizados (rezumidos).205 Min Max Indica o valor mínimo para uma string.  Clique com o botão direito do mouse e no campo New Field para adicionar um novo campo. Pode ser colocado um campo calculado ( um total parcial).Colocando um campo Total Parcial. não podemos combinar valores sumarizados com valores de campo.7 .Max(Field2) {legal – expressão num sumário } Avg(DiscountRate) * 100{ legal – expressão do sumário e constante } Min(Sum(Field1)) Count(Field1) .) Estas regras são ilustradas nas seguintes expressões: Sum(Qty * Price) {legal – sumario de uma expressão no campo } Max(Field1) . Para colocar um campo do tipo calculado:  Duplo clique no componente ClienteDataSet. porque expressões semelahntes são ambiguas (não há indicação de como mostrar fontes gravadas para o valor de campo. Indica o valor máximo para uma string. numeric. (Não podemos aninhar operadores sumários de qualquer modo).

 Selecione a tabela (componente ClienteDataSet) e no evento OnCalcFields faça a seguinte linha de programação: procedure TForm1. 15. end.  Salve o rode o sistema colocando valores nos campos para verificar o funcionamento Temos um software comercial com uma linha de programação.AsFloat:= qtde * valor.FieldByName('Total'). Como fazer para exportar dados? Para exemplificar coloque um botão no formulário. begin Tbl_Teste. end.Tbl_TesteCalcFields(DataSet: TDataSet). Tem muito mais coisas que esse componente é capaz de fazer.  Reative a tabela para que o campo ―Total‖ apareça na Grid.  Clique em OK.1 .206 Figura 103 – Editor de propriedades de componente.Salvando os dados Para exportar os dados da memória. suponha que esta ligado numa tabela.7. Propriedades: Botão – Name: Btn_Salvar Caption: Salvar .

Pode ser salvo o que foi digitado nos campos da grid. Se for feito um select e tiver 50 registros. end. begin //Esta linha de programação só funciona após criado o arquivo XML //É a linha de importação do arquivo. end.SaveToFile('c:\teste. Seleciona tudo que ainda não foi exportado.dfXML). procedure Tform1. Quando clicar no botão salvar serão exportados os dados. no Explorer ou outro programa porque XML é padrão de exportação de dados.Btn_SalvarClick(Sender: TObject).LoadFromFile('c:\teste.xml'.  Clique no botão para entrar no módulo de programação Coloque as seguintes linhas de programação: procedure TForm1.Savetofile<path> no arquivo X e no formato escolhido. É um padrão que não precisa de Driver para abrir. end. Pode ser feita uma geração de exportação do dia. quando mandar salvar. Tbl_Teste. Do outro lado será aberta esta tabela e atualizada no sistema (banco de dados).FormCreate(Sender: TObject). vai salvar os 50 que entrou.207 Figura 104 – Formulário de Teste de tabela temporária. begin Tbl_Teste. . Tbl_Teste. no caso a exportação será no formato XML que poderá ser aberta no Office. montando uma tabela e envia pela internet.xml').

O arquivo de exportação em formato XML forão gerados. end. . Para carregar esse arquivo.ApplyUpdates(0).<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> . Em resumo: É possível exportar para qualquer lugar.<METADATA> .Tbl_AtivAfterPost(DataSet: TDataSet).  Exporte os dados clicando no botão salvar. begin Tbl_Ativ.0"> .  Clique no componente (table) e no evento AfterPost coloque a seguinte linha de programação: procedure TForm1. A exportação se não for definida será em binário e só o Delphi consegue abrir. Verifique o formato de como este arquivo ficou.0" standalone="yes" ?> . Pode ser aplicado um filtro em ordem crescente ou decrescente ou outro modo qualquer. os campos e os valores para cada campo. conforme mostrado abaixo: <?xml version="1.208 O Funcionamento  Execute o programa colocando alguns dados (campos) para testar.<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> Através do Ecxel é possível importar esses dados.<DATAPACKET Version="2.

Carrega o arquivo faz um comando ApplyUpDate e salva automaticamente no banco de dados.Uma regra de negócio num programa Tudo o que foi feito é para você habituar ao poder do componente ClienteDataSet. Para exportar faça um comando SQL – se for feito Select * from <tabela> no banco de dados também funciona.8 . você executa o comando para carregar na memória e logo em seguida executa o comando ApplyUpDate para salvar no banco de dados.  Da paleta DBExpress coloque o componente SQLDataSet e SQLConnection .209 Cada vez que for ativado e em vez de salvar será carregado de um arquivo. não se perdem mais.  Abra um novo projeto no Delphi.  Da paleta DataAccess coloque os componentes: dois ClienteDataSet e dois ClienteDataSourse. compile e execute o programa Agora se clicar em salvar. Nesta versão será colocado tudo num único formulário – o servidor e o cliente – sem usar o componente DCOM só para ver como funciona a comunicação entre eles e depois será colocado o componente DCOM numa outra versão. a partir de agora. Na empresa que foi exportado os dados para poder carregar. Select * from <tabela> Where (onde por exemplo: flag = “true”) Neste ponto seleciona um bloco e só traz aquele que não está atualizado e efetua o comando para salvar no arquivo. os dados já estarão lá.  Da paleta DataAccess coloque o componente DataSetProvider – o componente que vai gerar a DLL. mesmo que abrir a próxima vez.  Salve. para salvar no banco de dados basta colocar o nome da tabela a ser salva e fazer o comando ApplyUpDate . 15.o que estiver na tabela e não estiver no banco já é exportado na hora. Do jeito que está e quando for carregado o arquivo. Do lado do servidor. Exemplo: Seu amigo mandou um arquivo e você quer salvar num banco de dados. Do lado do cliente.

então é necessário ligar a tabela com o banco.1.CommandText = TAB_ATIVIDADES – do Banco de dados BANCO. Para o exemplo estamos usando o Interbase.SQLConection = Conexao.Componente DataSetProvider A novidade é esse componente.8. ele joga nessa tabela.Componente SQLDataSet Em propriedades do componente: . Connected = true. . .8. joga dentro da tabela e salva dentro do banco de dados através de uma conexão (componente SQLConnection).Name = TBL_Atividade.1 -Componente SQLConnection  Clique no componente SQLConnection e escolha a conexão com o banco de dados colocando o Path no campo DataBase. Quando se conectar vai receber a Tabela de Atividades. Dois clientes acessando o mesmo servidor e o servidor acessando o banco de dados. Nas propriedades do componente DataSetProvider foi selecionado DataSet e tudo que chegar e independente do que chegar.Active = true. Quando chegar algum dado dentro desse componente.8.Fazendo a configuração Para o servidor é tradicional escolher a conexão em propriedades.8.GDB listado logo abaixo.1. O componente DataSetProvider vai ser o provedor de banco de dados. . por exemplo se rodar a base no Interbase: 15. O componente SQLDataSet quando precisar salvar. . vai gravar nesta tabela.2 . 15. por isso foi escolhido DataSet.1.  Clique no componente DataSetProvider. 15. Propriedade do componente: Name = Conexao Login Prompt = false. O componente SQLConnection liga as tabelas ao servidor através de uma única ligação com o banco.1 . 15. Neste ponto foi conectado com o banco de dados do outro lado.3 .210 Nota: Todas as estações que existirem irão se conectar com o DataSetProvider e este componente estará somente no servidor. Se precisar gravar alguma coisa será gravada na Tabela de Atividades. Todo mundo vai se conectar através deste componentee.CommandType = ctTable. .

.DataSet = ClienteDois Na Propriedade Options do componente DataSetProvider coloque como true os campos: Figura 105 – Object Inspector do componente DS_Ativ (DataSetProvider). .ProviderName = DSP_Ativ.Name = DSP_Ativ.DataSet = TAB_ATIVIDADES 15. Essas propriedades estão listadas logo abaixo: .Active = true.ProviderName = DSP_Ativ. o PropagateChanges e o IncFieldProps em true – isso no servidor.Name = ClienteDois .Os dois clientes O primeiro cliente vai se conectar ao componente DataSetProvider (DSP_Ativ). Nas propriedades desse componente coloque por enquanto o AutoRefresh. Componente DataSourse1 . Componente ClienteDataSet1 .8.211 Em propriedades do componente: .Name = ClienteUm . .4 .Active = true. Componente ClienteDataSet2 .1.DataSet = ClienteUm Componente DataSourse2 .

1.  Para cada cliente coloque um DBNavigator ligados ao DataSourse. comandar ApplyUpDate neste exemplo. No caso da importação de dados. para gravar no servidor. Do lado do cliente programe componenteClientDataSet(ClienteUm): clicando no evento AfterPost do . será salvo no servidor.A programação Cada vez que os dados forem salvos.3 mostra uma explicação de cada uma das propriedades dos componentes DataSetProvider (data access) e ClientDataSet (data access) No servidor foram estabelecidas as propriedades AutoRefresh. só serão salvos no banco de dados quando for executado o comando ApplyUpDate que pode ser programado no evento AfterPost da tabela ou no botão Salvar.212 OBS: O item 16. Os dados devem ser mostrados nos dois clientes e cada vez que salvar em um cliente. depois de importar. logo após será salvo no outro. O formulário ficará com o aspecto mostrado abaixo: Figura 106 – Aspecto do formulário com duas grids representando dois clientes. o PropagateChanges e o IncFieldProps. 15.6. se tiver dez registros. cada vez que salvar.5 .8.  Coloque uma grid para cada cliente – só para mostrar os dados – cada uma ligada a um DataSourse.3.

ApplyUpdates(0). end. begin ClienteDois. Quando clicar em salvar. Não tem nenhuma regra programada. salva os dados no Servidor que por enquanto ainda não recebeu nenhuma programação. O outro cliente também tem o código 17 para salvar com a descrição ZZZZ. end.ApplyUpdates(0). Faça o mesmo procedimento para o componente ClientDataSet2(ClienteDois): procedure TForm1. begin ClienteUm. O primeiro foi salvo executando o comando ApplyUpDate e o segundo também executou o mesmo comando.ClienteDoisAfterPost(DataSet: TDataSet). Figura 107 – Formulário com dois clientes em execução. Após atualizar as tabelas executando uma atualização da tela(Refresh) nota-se que o segundo cliente não consegue salvar os dados porque o primeiro já salvou e a mensagem de erro é mostrada. com a descrição AAAA. conforme abaixo: .ClienteUmAfterPost(DataSet: TDataSet). ClienteDois.213 procedure TForm1.Refresh. Se os dois clientes tiverem o mesmo código para salvar? Se o último registro de cada um é o código 16 e um dos clientes salva este registro para depois digitar o código 17.Refresh. ClienteUm.

É necessário que todas as vezes funcione para todo mundo.. Esta restrição está sendo programada no servidor. 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 Descrição) Figura 109 – Campos do componente SQLDataSet (Tbl_Atividade). . Foi campo(CustomConstraints) e foi programada com a restrição acima. Suponha que só é possível colocar códigos maior que zero.then) antes de salvar (BeforPost).Neste campo o numero ID vai ter que ser maior que zero e menor ou igual a cinqüenta (“ID > 0 and ID <= 50”). .214 Figura 108 – Mensagem de erro mostrando violação de chave... Isso tem que ser controlado programando uma Trigger no servidor. Para programar pode ser colocado a condição (if. Ex: Que o valor esteja entre 1 e 50.  Selecione o campo ID Na propriedade CustomConstraints – pode ser criada restrições igual ao banco de dados. . 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..Agora é possível digitar valores no campo ID somente na faixa de 1 a 50.

Para o cliente de baixo deverá mostrar a mesma mensagem. Coloque um valor fora da faixa especificada para testar o programa.  Salve as alterações > compile novamente e rode o programa. Se for colocado um valor valido e você não quer esse valor.6 .Alterando nomes dos campos Para alterar um nome. 15. A programação foi feita uma vez só no servidor que foi compartilhada entre os clientes – a constraints. compile e execute o projeto. como por exemplo o campo “descricao”. então pode excluir para colocar outro numero.1. .215 Figura 110 – Object Inspector da Tabela de Atividades (Tbl_Atividade)  Salve.8. Neste ponto note que o programa não vai obedecer até ser colocado um valor válido devido à constraint. Veja que não foi necessário programar nada nos clientes. 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”. dentro do servidor selecione o campo “descricao” e mude o display label para “Descrição” com inicial maiúscula e acentuação. Figura 111 – Mensagem de erro.

Pode ser colocada uma mensgem se não for digitado nada como do tipo: “Digite um valor”. Agora se precisar que a impressora seja local (no cliente). No cliente só vai ter um botão “Insert” da tabela. Figura 112 – Formulário de teste A programação e alterações são feitas somente no servidor. isso se tiver uma impressora para cada máquina. mas a programação de um botão de salvar ou inserir.  No servidor selecione o campo descrição e crie uma constraint. por exemplo. Para a programação de uma impressora fiscal. Para que o usuário não digite valores de espaço em branco – obrigatoriamente tem que ser digitada a descrição. O que é da impressora fica no cliente e o que é de banco de dados fica no servidor. Se tiver uma única impressora. mas se for uma impressora compatilhada então a programação fica no servidor. . a programação poderá ser feita somente no servidor. está será feita no servidor. será feita no cliente. A descrição tem que ser diferente de vazio: descricao <> “”.216 Note que todas as estações clientes estão atualizadas. parte da programação da impressora terá que estar no cliente.

Figura 114 – Mensagem de erro. mas o que o usuário final vai ver é a mensagem: “Digite a descrição” e enquanto não for digitada ele não sai do campo e nem avança.8. que na verdade não é um erro. mas se quiser. OBS: Ao executar o programa note que um erro aparece porque o Delphi está aberto. é so um aviso igual ao “Tray” e só acontece porque você está usando o Delphi e num executável só aparece a mensagem para o usuário.1.8.DataSetProvider (data access) Constraints -> se as regras de contrantes serão passadas para o clientes DataSet -> a tabela a ser usada . Digite um campo e deixe em branco a descrição e salve. Aparece um erro de exception (um try automático. A programação do cliente se restringe em Refresh e ApplyUpDate.1.8 . pode cancelar.217 Figura 113 – Propriedade de mensagem de erro. 15.Propriedades dos componentes DataSetProvider (data access) e ClientDataSet (data access) 15.  Faça todos os paços já descritos anteriormente para alterar a programação > Salve e execute o programa para testar.7 .

)  poCascadeDeletes-> delete feito em cascata no details. Métodos: procedure TForm1. displayvalues.  poIncFieldProps-> incluir dados sobre as colunas (tamanho da coluna. CurValue) .Apenas as colunas modificadas.(NewValue. serão habilitados).  poDisableDeletes-> se não pode excluir um registro. editmask.DataSetProvider1BeforeUpdateRecord(Sender: TObject. O tipo OwnerData pode passar qualquer informação entre o cliente e o provedor. UpdateMode->  upWhereAll .  poAutoRefresh -> atualizar clientes quando forem aplicadas atualizações.(banco deve ter suporte a "ON DELETE CASCADE")  poCascadeUpdate-> Atualizações no master devem ser feitas no detail. OldValue. Este evento é chamado antes de enviar os dados para o banco de dados. Bom quando duas ou mais pessoas estão atualizando o mesmo registro).DataSetProvider1AfterApplyUpdates(Sender: TObject. valor máximo.  upWhereKeyOnly. formato.218 Options  poFetchDetailsOnDemand -> em ligações master/detail. var Applied: Boolean).  poAllowMultiRecordUpdate-> atualiza vários registros de uma só vez se for necessário (sql com várias tabelas). etc. se for false.Todas as colunas serão usadas como base para localizar um registro (na clausula where .  poDisableInsert-> indica se o cliente pode ou naõ inserir novos registros(pode inserir = false)  poDisableEdit-> indica se o cliente não pode alterar um registro. UpdateKind: TUpdateKind. etc.Usa apenas a chave primária para buscar um registro e atualizar. (é muito rápido). procedure TForm1. begin end.  poReadOnly -> não pode fazer atualizações. não inclue os registros do detail. O DeltaDS são os valores vindo do cliente.  False: Atualizações feitas pelo Provider (TSQLResolver). ResolveToDataset->  True: atualizações de dados do banco serão feitas usando o dataset (BeforePost. DeltaDS: TCustomClientDataSet. SourceDS: TDataSet. var OwnerData: OleVariant).  upWhereChangedOnly . AfterPost. É mais rápido.currency.

FieldDefs-> informações sobre tamanho. é só usar o dataset). Evento chamado antes de enviar os dados para o cliente. DisableStringTrim ->  False: são retirados os espaços em branco.9 . DataSetFields-> representa uma ligação detalhe. etc.(como se os dados do detail estivessem dentro da tabela máster). DataSet: TCustomClientDataSet). AggregatesActive -> campos agregados estarão ativos (sim ou não). Pode ser passado como parâmetro em outros eventos.219 procedure TForm1. Como não sabemos quem é.DataSetProvider1GetData(Sender: TObject. assegurando a integridade. Os dados estão no pacote armazenado em Data. AutoCalcFields-> quando o campo calculado será acionado. FileName -> usado para criar tabelas temporárias em arquivos. sem os valores. onde todo o pacote de dados do máster já vem com os dados do cliente.1. em vez de usar um banco de dados. 15. 0 = só os metadados (SQL.  True. CommandText -> SQL que será enviando do cliente para sobrepor o do provedor. Serão retirados antes de serem salvos. Através do dataset. São parecidos com o campo calculado.  False -> quando o dado é enviando para o banco. PacketRecords = quantos registros serão trazidos por vez para o cliente (para evitar lotar a memória e deixar a rede lenta) (-1 = todos.ClientDataSet (data access) Mantém uma copia dos dados vindos do provedor na memória do cliente. Só terá efeito se a opção poAllowCommandText do provedor for true.  True: é gravado do jeito que está. podemos modificar até os valores a serem enviados para o cliente (o dataset é igual ao nome da tabela de destino. mas tem o expression para definir a expressão. isto é.8. só o nome dos campos)). Filter e Fieltered -> aplica um filtro nos dados (where) FilterOptions-> .> quando o foco for para outro controle. Pode causar perda de desempenho no cliente se usado em demasia. FetchOnDemand -> quando chegar ao final do pacote de dados (PacketRecords). nome. deve buscar outro automaticamente.

decricao varchar(50) ).2). Updatestatus -> Estado das atualizações dos registros. id smallint not null. create table tab_parceiros_cont( id_parc integer. cnpj char(18). 15. . create table tab_parceiros_refer( id_parc integer not null. tp_ref char(1). insc_est char(11) ).8. id smallint not null. com_dt_ult_compra date. RemoteServer -> Nome do servidor de aplicações. Métodos: revertRecord -> desfaz as modificações feitas no registro corrente.  usDelete – registro excluído mas modificação ainda não aplicada. com_vl_prestacao numeric(18. create table tab_parceiros( id_parc integer not null.220  foCaseInsensitive (não diferenciar maiúsculas e minuscular)  foNoPartialCompare (comparação parcial) ProviderName-> nome do provedor que o CDS está associado. email_contato varchar(35) ).  usUnModified – sem atualizações pendentes  usModified – tem modificações a serem aplicadas. mas inserção não aplicada. com_vl_tt_compra numeric(18.2 – Tabelas do banco de dados para teste: create table tab_atividades( id integer not null. nome_contato varchar(50) not null. tel_contato varchar(25). nome_ref varchar(30) not null.  usInserted – Registro inserido. nome varchar(50).2). Podemos usar a propriedade ConnectionBroker para abstrair a conexão do servidor.

. Agora o banco de dados será apenas um repositório porque toda a programação ficará no servidor de aplicação. alter table tab_parceiros_refer add constraint pk_tab_parceiros_refer primary key (id. então vai ser colocado tudo dentro de um Data Modulo. vai rodar sem ninguém saber e como não tem tela não é possível colocar um banco de dados numa tela. Commit. da mesma forma que o oracle ou o interbase roda. fornecendo recursos e que não tem tela de exibição de dados.As Três Camadas de fato Nos tópicos anteriores foram desenvolvidos exemplos de aplicação. O Data Modulo é um formulário invisível. mas apenas com uma camada.nome_ref). só para ter uma noção do que se está trabalhando. não fica nenhuma tela mostrando o que esses bancos estão fazendo. alter table tab_parceiros add constraint pk_tab_parceiros primary key (id_parc). bco_agencia varchar(25). um local em que vai ser feita a programação. alter table tab_atividades add constraint pk_tab_atividades primary key (id). O servidor em si não tem tela. usando um componente de três camadas (ClienteDataSet).221 com_dt_vcto_ult_parc date. alter table tab_parceiros_cont add constraint pk_tab_parceiros_cont primary key (id. bco_dt_abert_conta date. A mesma coisa vai ser aqui. A partir de agora serão criados exemplos em três camadas. Será criado primeiro o servidor e depois o cliente ligados a um banco de dados qualquer. esta alteração se refletirá para toda máquina (cliente) ligado a este servidor. Se for alterada alguma característica no servidor.9 . só que ainda não estão em três camadas.nome_contato). é um serviço de banco de dados. um programa que vai rodar dentro da máquina servidora que vai ficar monitorando. alter table tab_parceiros_refer add constraint fk_1015_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade. 15. Quando trabalhamos com servidor de aplicação em três camadas é importante criar um Data Modulo Remoto. bco_cheque_esp char(1) ). alter table tab_parceiros_cont add constraint fk_1014_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade. da facilidade de programação.

Após clicar em OK aparece a tela de dialogo abaixo: . mas não foi estardado o ActiveX Library.O servidor     Abra o Delphi File > new > Other Em New Itens procure a aba ―Multitier‖. Após feitas as operações acima se aparecer uma tela do ActiveX está sendo adicionado o Transactional Object no projeto. isto significa que a programação em Pascal será transformada em ActiveX e gravada no servidor. Clique no Icone ―Transactional Data Module‖ Figura 115 – Transactional Data Module. Este serviço terá que ser iniciado (start) para fazer a conversão clicando em OK.1 . Quando trabalha com DCOM.  Clique OK Multitier – Multitarefa. Roda várias coisas ao mesmo tempo. toda programação vai ser ActivX.9. um servidor com a linguagem da Microsoft.222 15. É um Data Modulo que vai fornecer dados para várias pessoas ao mesmo tempo.

.  Clique em ―Requires a New Transaction‖. Figura 117 – Tela de dialogo do DataModuloRemoto. Apartment e Both. Apartment ou Both vai poder suportar.223 Figura 116 – Tela de diálogo do Data Modulo Qual o nome do servidor?  No campo CoClassName(?) coloque o nome do servidor: No exemplo – ―DataModuloRemoto‖ – tudo junto. No caso vamos colocar Both (ambos). Modelo de transação (Transaction Model) – Toda vez que for modelo de transação sempre carrega uma nova transação e cada pessoa que se conecta ao servidor é gerado uma transação para ele.  Tipo de modelo de Thead: ―Theading Model – teremos os campos Single.  Clique em OK. – Tanto Single.

Vai ocupar um pouco mais de memória no servidor só que em compensação o acesso dos clientes se torna mais rápido. Isso habilita um cash para atender aos clientes. create table tab_parceiros( id_parc integer not null.224 Pronto foi criado o Data Modulo. isto é. Se não tiver as pastas. o Servidor. A prioridade são os clientes. A intenção é que o acesso dos clientes seja rápida e não o servidor. Faça no Interbase o banco de dados abaixo para utilizar no exemplo: Tabela para teste: create table tab_atividades( id integer not null. Falta fazer a ligação com o banco. por isso que não foi criada a pasta formulários. cria um Pool. Nota: o DataModulo não é uma tela. Figura 118 – Tela do Servidor Data Modulo.  Antes de mais nada. insc_est char(11) ). na propriedade Pooled – coloque true. uma class para quando vários clientes tiverem acessado. cnpj char(18). . decricao varchar(50) ).  File > Save as > C:/3Camadas/Servidor/DataModulo.  Salve o projeto com o Nome P_Serv.  Salve o servidor. ele torna um pouco mais rápido. nome varchar(50). crie.

nome_contato varchar(50) not null. . então será usado o DBExpress que é mais fácil de trocar de banco de dados.nome_contato). alter table tab_parceiros_cont add constraint fk_1014_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade.2). bco_cheque_esp char(1) ). alter table tab_parceiros_refer add constraint pk_tab_parceiros_refer primary key (id. com_dt_vcto_ult_parc date. bco_agencia varchar(25). Propriedade Name = conexão. bco_dt_abert_conta date. 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. SQLConection é o componente que vai se conectar com o banco de dados. email_contato varchar(35) ). nome_ref varchar(30) not null. create table tab_parceiros_refer( id_parc integer not null.  Coloque no formulário (DataModuloRemoto) os componentes SQLConection e SQLDataSet da paleta DBExpress. alter table tab_parceiros_refer add constraint fk_1015_1013 foreign key (id_parc) references tab_parceiros(id_parc) on delete cascade. com_vl_tt_compra numeric(18. tel_contato varchar(25). id smallint not null. id smallint not null. com_dt_ult_compra date.2). tp_ref char(1). com_vl_prestacao numeric(18.nome_ref). O componente ADO é muito lento.225 create table tab_parceiros_cont( id_parc integer. alter table tab_atividades add constraint pk_tab_atividades primary key (id). No DataModuloRemoto pode ser colocado o banco de dados que quiser. Commit.

 Da Paleta DBExpress coloque mais um componente SQLDataSet. Propriedade do componente SQLDataSet Name = SQL_Geral SQLConnection = Conexao  Após criada a conexão – coloque Active = true na tabela e LoginPrompt = false.9. Propriedades do DataSetProvider: Name = DSP_Ativ. O DataSetProvider será ligado a uma tabela.  Selecione o componente DSP_Ativ e ligue a propriedade DataSet com a tabela (Tbl_Ativ) que antes não tinha.SQLConnection = conexão . . 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. todas as tabelas estarão no servidor. agora será DataSetProvider e Tabela. Vai ser a tabela. A propriedade DataSet do componente DataSetProvider é a tabela que vai ser gravada que por enquanto não colocamos ainda mas essa propriedade determina em qual tabela será gravada quando for necessário gravar alguma coisa. é ele que compartilha os serviços. Quando o(s) cliente(s) for(em) conectado(s) no servidor. portanto daremos um nome de programação para ele. O DataSetProvider é o fornecedor de recursos. É ele que vai fornecer os recursos.2 . esta tabela será a ligação.226 Procure o banco de dados para efetuar a conexão. componente DataSetProvider.CommandType = table . 15. Preencher as propriedades do SQLDataSet2 > .Name = Tbl_Ativ . todos irão se conectar primeiro no componente DataSetProvider.Active = true. Da mesma forma que funcionava a dupla DataSourse e Tabela.Command text = (TAB_ATIVIDADES) .Fornecedor de recursos O fornecedor de recursos está na paleta DataAccess. para cada vez que precisar de efetuar alguma ligação. Em três camadas.  Adicione o componente DataSetProvider da paleta DataAccess.

 poReadOnly -> não pode fazer atualizações. Detalhe importante: Clique Control + F12 – Verifique P_Serv_PLB .  poIncFieldProps-> incluir dados sobre as colunas (tamanho da coluna. editmask. currency. se for false. praticamente já está pronto o servidor.  poAllowMultiRecordUpdate-> atualiza vários registros de uma só vez se for necessário (sql com varias tabelas). valor máximo.  poAutoRefresh -> atualizar clientes quando forem aplicadas atualizações.  poDisableDeletes-> se não pode excluir um registro. No Data Modulo foram colocadas a tabela e a conexão.  Na propriedade Options de DSP_Ativ.(banco deve ter suporte a "ON DELETE CASCADE")  poCascadeUpdate-> Atualizações no master devem ser feitas no detail. formato. etc. não inclue os registros do detail. componente DataSetProvider coloque true nas opções FetchDetailsOnDemand. IncFieldProps. A propriedade Options tem várias opções que estão descritas abaixo: Options  poFetchDetailsOnDemand -> em ligações master/detail.227 Figura 119 – Componentes do DataModuloRemoto.)  poCascadeDeletes-> delete feito em cascata no details. PropagateChanges e AutoRefresh.  poDisableInsert-> indica se o cliente pode ou não inserir novos registros(pode inserir = false)  poDisableEdit-> indica se o cliente não pode alterar um registro. displayvalues.

Cada servidor gera automaticamente um número único que não pode ser apagado ou modificado. mas só conhece números.228 Figura 120 – Tela de Units. Internamente não trabalha com servidor de aplicação. tudo internamente é tratado com um número. Antes criava só o provedor que foi salvo . O que mostra é uma tela de configuração. gera um número para trabalhar. Selecione o arquivo que foi criado e pressione F12. O número (GUID: {981439C8-2642-49E5-B1D8-8E91EBF6CBB3}) do exemplo indica que toda vez que for trabalhar a partir de agora com comandos ou com aplicações DCOM. A tela gerada é a mostrada abaixo: Figura 121 – Programação gerada do P_Serv_Tbl. .o Data Modulo e foi criado também o arquivo P_Serv_TLB.

229 Esta tela tem um campo chamado Interface. Interface é para declarar as rotinas mas não tem programação e Implemantation é para fazer a programação. Quando criamos a DLL. Neste caso é a mesma coisa. é uma tela gráfica que depois será criada a rotina que como antes pode ser pressionado com o botão direito do mouse e criar métodos e propriedades. Veja que por enquanto não tem o servidor do exemplo instalado ainda.  Feche as janelas abertas.  Volte ao Data Modulo 15. Algumas rotinas serão feitas depois.9.3 – Montando o Servidor  Iniciar > painel de controle > ferramentas administrativas > serviços de componentes > computadores > meu computador > aplicativos COM+.  No Delphi Clique em RUN > InstallCOM+ Objects. Agora execute a instalação. especificando que tipo de parâmetros deverá ser usado. tinha os campos chamados Interface e Implementation. Figura 122 – Serviços de componentes. Aqui pode ser criada várias propriedades. .

No campo Description pode ser descrito para que serve o novo servidor.  Coloque o nome: Servidor de aplicação.230 Figura 123 – DataModuloRemoto no Install COM.  Selecione DataModuloRemoto para abrir a próxima tela  Clique no campo: Install into new Application para instalar um novo servidor Figura 124 – Nome do Servidor. poderia escolher qual deles queira colocar (instalar). porque não queremos que todos os Data Módulos sejam instalados. . Suponha que tem vários Data Módulos. OBS: Se a aplicação já existir. Nesta tela digitamos o nome do servidor. selecione o Data Modulo a ser instalado escolhendo o campo install into existing Application. Esse é o nome do Servidor para o exemplo. O sistema pergunta onde vamos criar. Será instalado dentro de um servidor.

Agora vamos colocar tudo dentro do Servidor de aplicação.  Iniciar > painel de controle > ferramentas administrativas > serviços de componentes > computadores > meu computador > aplicativos COM+.  Clique em OK. Figura 126 – Servidor de Aplicação criado no Serviços de componente. . Após executado os passos anteriores.  Após criar clique em OK e OK novamente.  Clique em RUN > Register ActiveX Server Note que após executado o registro é criada uma DLL. verifique no Arquivo de ferramentas Administrativas. serviço de componentes a criação do Servidor de Aplicação. Figura 125 – Informação de sucesso de registro do ActiveX.231 Nota: Estamos criando dentro de uma nova aplicação porque podemos colocar quantos serviços quiser dentro de um servidor mas o ideal é ter serviços separados porque na hora que parar o servidor não para os outros serviços que estão sendo executados.

Como no exemplo que está sendo feito. Colocar objetos tudo como Pooling.Os Clientes Inicie uma nova aplicação que vai acessar o servidor criado. ele inicializa sozinho. terá que parar o serviço. 15.5 . Está pronto o servidor e pode ser executado. 15. Selecione o COM+ (Objeto COM). O sistema salva as modificações automaticamente ao fechar. se for feita alguma alteração no Delphi e tentar instalar novamente o ActiveX não será possível fazer a alteração.232 O Servidor de aplicação está inativo. Propriedades: . Propriedades name = Tbl_Ativ.  Pode fechar.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 máquina. A partir do momento que começa a rodar. Se for solicitado algum serviço ao servidor. o servidor está na própria máquina e se não sabemos o nome da máquina.9.9. Então como conectar com o banco de dados?  Da Paleta DataSnap coloque o componente DCOMConnection que fará a conexão. compilar e iniciar novamente.  Salve a aplicação. . crie também um Cash para ficar mais rápido o plugin.  Da paleta DataAccess coloque o componente ClienteDataSet. A partir de agora tudo que vai ser utilizado estará na paleta DataAccess ou DataControls A tabela vai ser sempre o ClienteDataSet. colocamos ―localhost‖.  Coloque o nome do Servidor. então toda vez que necessitar compilar novamente o servidor. Para ativa-lo clique com o botão direito do mouse em cima dele e inicialize o serviço.4 . Mande que faça uma sincronização de objetos. Para cada vez que criar um objeto.Primeira forma de conexão via DCOM Para conectar a base de dados não podemos usar o componente SQLConnection porque este componente já esta no DataModulo – é uma conexão só com o banco.

Agora a tabela já está conectada. Note que quando foi colocado o nome. Use o nome do Servidor de Aplicação ―P_Server‖.233 Propriedade SeverName Pode ser colocado o ServerGUID que é o número gerado na aplicação anterior do servidor.  Coloque a propriedade Active = true. O Provider – No DSPDataSetProvider será indicada qual o ProviderName. No componente ClientDataSet ( Tbl_Ativ).  Na propriedade RemoteServer coloque DCOM_Conexao. Figura 127 – Object Inspector do componente DCOM_Conexão.  Coloque a propriedade Conected = true. Só que provavelmente esse número não foi memorizado. o número gerado na aplicação anterior também aparece. então é mais fácil instalar pelo ServerName. determine em que tabela será ligada. O DSPAtividade já aparece. Coloque o nome da tabela.  Na propriedade ProviderName selecione DSP_Ativ. qual a tabela. .

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

será incluído somente na memória e só vai salvar no banco do servidor quando for aplicado um comando Post (Salvar). o único problema é faltar energia ou ter alguma falha na máquina cliente.235  Da paleta DataControl coloque uma Grid e um DBNavigator.  Clique no ClienteDataSet > Eventos > After Post para abrir o modulo de programação.ApplyUpdates(0).  Lique a Grid e o DBNavigator ao DataSourse. begin Tbl_Ativ. Se deixar para fazer isso no final de um dia? Imagine se for feita 50 vendas e de vez em quando efetua um Post. Toda vez que executar um Post(salvar) atualiza no servidor. Tbl_Ativ. cada vez que salvar já atualiza no servidor. perde-se todos os dados porque esses dados estarão numa tabela temporária (cash). Detalhe: Quando mandar incluir um dado.  Salve a aplicação com o nome camadas/clientes/U_CadAtiv.  Salve o projeto com o nome de P_Cliente. Após salvar pega a tabela e atualiza. O formulário ficará com o aspecto mostrado abaixo: U_CadAtiv em C:/Alunos/3 . Se os dados não estiverem sendo mostrados verifique se o DataSourse está ligado ou se a tabela está ativa (Active = true). end. automaricamente. Assim por segurança.Tbl_AtivAfterPost(DataSet: TDataSet).Refresh. somente para mostrar os dados. Programação: procedure TForm1.

 Selecione o campo ID.  Duplo clique na tabela.236 Figura 129 – Formulário de Clientes. . No editor com o botão direito do mouse clique novamente e adicione todos os campos > Add AllField.  Feche o aplicativo cliente. o aplicativo permite e salva um código negativo. Faça uma restrição. ou programamos em cada estação cliente. Para fazer com que o sistema não permita cadastro de número (código) negativo terá que sr feito um tratamento. o código ID só pode ser positivo.  Abra o Servidor. Para colocar somente números maiores que zero. Se cadastrar o código (-6). Na propriedade CustonConstraint indique que o campo ID será maior ou igual a zero: ID >=0 Pode ser colocada uma mensagem para o usuário de no caso digitar um valor negativo:  Na propriedade ConstraintErro coloque a mensagem: ―Digite números maiores que zero‖. ou programamos uma trigger no banco de dados. Nota: Em duas camadas.  Execute a aplicação. Agora temos uma aplicação com muitas tabelas e uma única conexão também no formulário principal usando o componente DCOM. temos muitas tabelas e uma única conexão no formulário principal.

No cliente não vai ser modificado nada. Selecione o campo descricao e na propriedade Display Label – Digite ―Descrição‖ com todos os acentos. Nos campos ID e Descrição será feito um exemplo de modificação de campo manipulando somente o Servidor.7 .237 Figura 130 – Object Inspetor do componente SQL_Ativ.Fazendo mais uma exportação. Selecione o campo ID e na propriedade Display Label – Digite ―Código‖.     Abra o Servidor.  Ative novamente o Servidor. .  Pare o servidor e compile novamente  Registre novamente o servidor e ative de novo o serviço. pare o serviço do Banco de Dados.  Volte no servidor > clique em RUN > registre novamente > Register ActiveX Server. 15.9.  Salve as alterações efetuadas. Duplo clique na Tabela (SQL_Ativ).  Execute o aplicativo cliente. Só quando parar o Servidor é possível atualizar os dados. Para recompilar .

Neste ponto será mostrada a mensagem de erro: “Descrição deve ter valor”. Note que os campos ID e Descrição da Grid foram atualizadas.  Rode o aplicativo cliente para testar.Tratamentos Campos em branco (sem preenchimento) – Para que não seja permitido campo sem digitação.  Selecione o campo descrição e na propriedade Constraint será determinado que o campo chamado Descrição será diferente de vazio (descricao <> ‗ ‗). será refletido no cliente. . Digite o código e deixe em branco a descrição.238 Figura 131 – Formulário cliente em execução. Qualquer propriedade que for modificada. 15.  Pare o Servidor e compile novamente.  Duplo clique na tabela SQL_Ativ da aplicação do Servidor. tamanho.9. será criada uma constraint. Figura 132 – Object Inspector do componente SQL_Ativ.8 . como por exemplo a descrição. etc.  Para a mensagem coloque ―Descrição deve ter valor‖. Display Label.  Registre o servidor e ative de novo.

Auto Numeração de Código (ID)  Abra o Servidor. No evento BeforeUpDataRecord. pega um valor anterior e soma mais um. um pacote com todos os dados. Uma Tabela que só tem um registro acumulado no cliente.239 15. mas pode ser criada uma variável para armazenar o último número existente. Antes de salvar. um cadastra o nome João e outro cadastra o nome José e serão salvos no mesmo servidor de aplicação. só que os dados provem do cliente. em DeltaS vai ter um comando SQL para pegar o último registro. será feito um comando SQL para efetuar uma consulta no servidor. vai executar o que está ali dentro e é neste ponto que vai ser feita a auto numeração para depois salvar. Por exemplo: para alterar o código – DeltaDS. Aquele que chegar primeiro executa o evento BeforeUpdataRecord.  Selecione DBExpress – Coloque um componente SQLDataSet no DataModulo da aplicação Servidor. se quiser trocar (colocar um comando new). esse numero vai ser descartado. Para fazer uma atualização. mesmo que seja por milionésimos de segundos. numerar e colocar automaticamente. O primeiro e o segundo executam o comando que nunca. Ele é como se fosse uma tabela. No DataSetProvider (DSP_Ativ) será feita a maioria da programação porque entre os eventos tem um chamado BeforeUpdataRecord. O evento BeforeUpdataRecord é um dos eventos mais importantes do projeto.NewField) := <NovoValor>. antes de salvar no banco. Propriedades: Name = SQL_Geral .9. Não importando o numero de código que foi digitado. Esses dados serão colocados numa fila de execução. Este exemplo é para treinamento de comandos no banco de dados. atualizando no banco BeforeUpdataRecord DeltaDS – são os dados que são originados do cliente. Quando for executado esse comando. um valor que tinha anteriormente na tabela. Exemplo: se temos um numero(old) já registrado. Então temos um oldt(antigo) e um new(novo) que pode ser colocado no lugar do antigo.FieldByName(ID.1 .8. altere. Se duas pessoas começarem a cadastrar dados na tabela Cliente. mas nunca serão exatamente no mesmo instante. gerando um novo número para o primeiro registro da fila e manda atualizar. salvando no banco de dados e após isso gera um numero consecutivo para o segundo registro. verificar o último número e retornar.

9. Figura 133 – Editor SQL. Quando executar o evento. O campo vai se chamar Maior. vai pegar a tabela SQL_Geral e colocar true na programação: SQL_Geral. 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. .Programando o evento BeforeUpdataRecord.Active := true.  Selecione o componente DataSetProvider (DSP_Ativ) para programar o evento BeforeUpdataRecord.AsInteger. Deixe a tabela em Active = false. 15. substituindo o valor: DSDelta. Quando colocar a tabela em Active = true e não der erro é porque o código está certo.NewValue:= SQL_Geral.fieldByName(„maior‟). O FieldByName vai se chamar Maior.FieldByName(„ID‟). Vai ser ativado o SQL.240 SQL_Connectio = conexão CommandType = ctQuery CommandText = clique nas reticencias para abrir o editor de SQL.  Teste o aplicativo.9 . O Select vai pegar o maior valor do campo ID e somar mais um.

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

Ao digitar qualquer valor. Como o banco do aplicativo é pequeno. só que vai fazer a atualização (Refresh) quando estiver em Browser (navegando). OU Desabilite o campo colocando true. edição ou busca.9. begin if Tbl_Ativ. end.FieldByName('id').  Clique com o botão direito no editor e adicione todos os campos. Pode também ser colocada uma mensagem de retorno para saber se foi atualizado ou não. end. A atualização de tela deve ser feita mais vezes no caso de uma tabela de produto ou cliente. Nota: A atualização só vai ser feita quando o sistema não estiver executando nenhum comando.  Salve e execute o programa colocando um novo registro.  Da paleta System coloque o componente Timer  No eveno BeforPost do componente ClienteDataSet ( Tbl_Ativ) faça a seguinte linha de programação: procedure TForm1. Vai executar Time. Se estiver em inserção.asinteger:=0. . 15. este valor será substituído por zero e esse zero será descartado na atualização colocando um novo valor auto-numerado.  Pare o servidor.242 begin Tbl_Ativ.  Salve o aplicativo. não fará atualização nenhuma.Timer1Timer(Sender: TObject). não ficará executando atualizações da tela a todo momento porque no pedido só vai ser mostrado só o atual e não tem sentido atualizar a tela a todo instante.State = dsBrowse then Tbl_Ativ.  Duplo clique da Grid. no caso por exemplo de um outro banco que tem uma tabela de pedido.10 .Refresh da tela (Atualização) Quando salvar nos clientes automaticamente atualiza a tela.  Registre o servidor e ative novamente o serviço..  Selecione o campo ID e na propriedade ReadOnly coloque true.Refresh.

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

SourceDS: TDataSet. end else begin DisableSocketTransport(ClassID).244 if Register then begin inherited UpdateRegistry(Register. Forms.AsInteger. initialization TComponentFactory. Variants. begin Sql_geral. // showmessage(inttostr(SQL_Geral. Controls. ciMultiInstance. ProgID). DBCtrls. interface uses Windows. ClassID.AsInteger)). Class_DM_ServidorRemoto. Graphics. SysUtils. inherited UpdateRegistry(Register.FieldByName('id'). . EnableSocketTransport(ClassID).Active:=true. Grids. DeltaDS: TCustomClientDataSet. MConnect.Active:=false. ClassID. DB. ExtCtrls. TDM_ServidorRemoto. Messages. UpdateKind: TUpdateKind. var Applied: Boolean). Unit U_CadAtiv. SQL_Geral.DSP_AtivBeforeUpdateRecord (Sender: TObject. DBClient.NewValue:= SQL_Geral. end.fieldbyname('maior'). DisableWebTransport(ClassID).Prepared:=true. Applied:=FALSE. end. type TForm1 = class(TForm) Tbl_Ativ: TClientDataSet. Classes. EnableWebTransport(ClassID). DeltaDS. SQL_Geral. end. Dialogs.fieldbyname('maior').Create(ComServer. tmBoth). DBGrids. ProgID). procedure TDM_ServidorRemoto. end.

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

Com isso o grupo CBR implementou através do protocolo de comunicação que essa balança emite dentro de um componente e também as funções de uma DLL. basta pegar direto o componente e dentro dele tem diversos demos. salve dento de uma pasta de sua preferência. em www. o componente gera um executável e o protocolo de comunicação vai estar tudo lá dentro.net primeiro lugar vamos baixar o componente do site Na área de pesquisa.Balança Comercial Figura 134 – Balança Toledo As balanças tem um parâmetro de comunicação. por exemplo: Alunos/<nomesubpasta> . 16. A balança Toledo não envia o protocolo. A vantagem é que quando colocamos o componente não é necessário instalar a DLL. Há um protocolo que deve existir quando compramos uma balança. nem a DLL. digite ACBr e clique em Search e ao visualizar o componente faça o download.246 16 . Há várias pastas no download.Instalando o Componente Para implementar.1 .sourceforge. Após feito o download.

licença. Impressoras de Cheque.4b | | | | Biblioteca multiplataforma de componentes Delphi para | | interação com equipamentos de Automação Comercial | | utilizados no Brasil | | | | http://acbr. descompacte o arquivo em uma pasta que ninguém possa apagar. Como executar os Demos.1 . Entre esses equipamentos podemos citar: Impressoras Fiscais. Como posso ajudar no projeto 9. Tarefas que ainda precisam ser iniciadas.sourceforge. crie uma pasta chamada componente e coloque o arquivo lá dentro.Descrição da pasta leia-me +---------------------------------------------------------------------+ | | | Projeto: Componentes ACBr Versao 0. 5. Transferência Eletrônica . Autores e Colaboradores 8. Componentes 7. Compatibilidade 4. isso se for na sua máquina. Vários fabricantes vem disponibilizando vários equipamentos para permitir a criação de Programas de Ponto de Venda.net | | | +---------------------------------------------------------------------+ INDICE 1. Gavetas de Dinheiro. No arquivo leia-me é explicado a instalação que mostra a descrição.247 Agora é só instalar o componente. etc. Instalação 6. por exemplo dentro da pasta do Delphi. Vantagens e Desvantagens 10. Histórico do desenvolvimento -------------------------------------------------------------------------------1. Licença 3. Descrição 2. compatibilidade.1. Para instalar o componente. 16. Dentro do Delphi.8. melhoradas ou completadas 11. DESCRIÇÃO O mercado de automação comercial Brasileiro está em franca expansão.

também serei beneficiado. Porque o projeto é OpenSource ? É realmente muito difícil fazer um projeto desse tamanho sozinho. para acesso aos equipamentos em Linux.. que permita acesso direto a esses equipamentos. entretanto para uma aplicação de Automação Comercial acessar vários equipamentos são necessárias várias DLL's. O objetivo desse projeto é desenvolver uma Paleta de Componentes para a Linguagem Delphi com versões VCL e CLX. LICENÇA Esta biblioteca é software livre. sem DLL's. Conseguir acesso a diversos equipamentos para testes. Kylix 3. ou (a seu critério) qualquer versão posterior. ajuda nos testes. Por isso acho que compartilhando minhas informações com a comunidade. Monitor de Bombas de Combustível. Além de permitir a programadores da Linguagem Kylix. -------------------------------------------------------------------------------2.1 da Licença. acesso direto a esses equipamentos em Linux. em diferentes sistemas operacionais e configurações de máquinas. SEM NENHUMA GARANTIA. tanto a versão 2. porém ainda não foi testado. interagindo com eles direto na porta serial (ou outra porta a qual eles sejam ligados). e até mesmo com a colaboração de outros desenvolvedores. ou ainda criar uma modificação dessa Biblioteca. nem mesmo a garantia implícita de COMERCIABILIDADE OU ADEQUAÇÃO A UMA FINALIDADE ESPECÍFICA. etc. (Arquivo LICENÇA. seja com sugestões.. Quase todos os fabricantes disponibilizam DLL's para acesso a seus equipamentos.TXT) Por favor leia pelo menos a Introdução do arquivo LICENÇA. você pode redistribuí-la e/ou modificá-la sob os termos da Licença Pública Geral Menor do GNU conforme publicada pela Free Software Foundation. 7..TXT ou LICENSE. -------------------------------------------------------------------------------3. 6.. Consulte a Licença Pública Geral Menor do GNU para mais detalhes.TXT. COMPATIBILIDADE Compatível com Delphi 5. se você deseja usar essa biblioteca em algum Programa Comercial. porém. . Esta biblioteca é distribuída na expectativa de que seja útil.248 de Fundos (TEF). Outro problema é a não disponibilização de SO's. por parte dos Fabricantes. Display de Mensagens.o que dificulta a instalação e manutenção dos Programas. e futuramene Lazarus (FreePascal) Pode haver compatibilidade com versões inferiores ao Delphi 5.

9-qt2. Na IDE do Delphi acione "File.Windows 98 SE Delphi 7 Professional .DPK (para versão VCL) ACBr\Source\Pascal\ACBr_D5.Windows XP Home SP2 Delphi 7 Professional . Na IDE do Delphi acione "Tools. Clique em "Compile" e em seguida em "Install".Conectiva 10 Kylix 3 Patchs não oficiais para CLX DEVEM SER APLICADOS ( http://unvclx.ZIP na pasta de sua preferência. 2. (não há 4.DPK (para versão CLX) ou ACBr\Source\Pascal\ACBr_VCL. Adicione o diretório " ACBr\Source\Pascal " no "Library Path".3. Feche o arquivo DPK necessidade de salvar).sourceforge. Open" Localize o arquivo ACBr\Source\Pascal\ACBr_CLX. A melhor maneira de aprender como usar os componentes ACBr é observar o código dos Programas de demonstração.sf.DPK para a versão desejada.net ) -------------------------------------------------------------------------------4. COMO EXECUTAR OS DEMOS Atualmente o ACBr ainda não possui um Manual de Ajuda ou qualquer outra documentação. Se você instalou a versão CLX da ACBr abra apenas os programas de demos da pasta ACBr\Source\Pascal\Demos\CLX. Compile e Instale a Biblioteca. Durante o desenvolvimento foi usada a seguinte Plataforma: . Se você não possui o Kylix instalado. Abra o arquivo .DPK (para Delphi 5) 3. Descompacte o arquivo . copie a biblioteca acima para o diretório /usr/lib. INSTALAÇÃO 1. as bibliotecas de run-time podem ser achadas em: http://kylixlibs. Enviroment Options" selecione a guia "Library".so) disponível no Kylix (/usr/local/kylix/bin). use os demos da pasta Os Demos Linux precisam da biblioteca QT/Borland (libborqt-6.249 Por enquanto não é possível intalar a versão VCL e CLX da Biblioteca simultaneamente. clique .net -------------------------------------------------------------------------------5. Para rodar os demos em uma máquina que não possua o Kylix instalado. Se você instalou a versao ACBr\Source\Pascal\Demos\VCL VCL da ACBr...

Ao iniciar um NOVO projeto em CLX adicione a clausula "VisualCLX" ou "CLX" em "Conditional Defines".. alguns relases ocorrerão sem os devidos testes em alguns modelos de equipamentos. com a vantagem imediata de tornar o seu código compatível a todas os Modelos de Impressoras suportadas pelo ACBrECF.. Schalter. 5. e em "Add". Com suporte a gavetas ligadas a Porta Serial... -------------------------------------------------------------------------------6. antes de "Compile" e "Install". A idéia é substituir os comandos da DLL por chamadas aos métodos do componente ACBrECF.. Mecaf (e compatíveis) ACBrGaveta .Clique na aba "Directories/Conditionals" ...".. Ficaremos muito gratos com a sua participação no projeto. Build ACBr. Se você já instalou uma versão (VCL ou CLX) e pretende instalar a outra versão. É necessário clicar em "Project..) de "Library Path". Antes de cada release...Para se comunicar com Impressoras Fiscais (ECF)..Clique em "Project".. Inicialmente suportando os seguintes modelos: Menno. ou diretamente ao ECF ou ainda ligadas a Impressoras não Fiscais (paralela ou serial). SEJA VOCÊ TAMBÉM UM COLABORADOR.. pois algums arquivos são compartilhados entre as duas versões. Isso irá gerar corretamente os arquivos DCU para a nova versão.. Se você possui acesso a algum equipamento que é do escopo do projeto ACBr. Muitos fabricantes gentilmente nos ajudaram nos testes. clique em "OK". Inicialmente imaginamos desenvolver os seguintes componentes ACBrECF . A paleta ACBr será criada com os componentes da Biblioteca ACBr. COMPONENTES * IMPORTANTE * Durante a fase Beta do Projeto. Isso por causa da dificuldade de conseguir Hardware disponível para testes.. Daruma. clique no botão elíptico (.) à frente da caixa de texto.Digite VisualCLX em "Conditional Defines" e clique em OK. apenas escolha o modelo e pronto..250 no botão elíptico (. Click em "OK" para finalizar. Sweda. Gerbô.Para acionamento de Gavetas de dinheiro.. Nota para o uso das versões VCL / CLX. localize a pasta " ACBr\Source\Pascal " no diretório de instalação da Biblioteca. contactando Colaboradores ou Fabricantes. fazemos o maior esforço possível para testar o maior número de modelos. outros nem tanto. "Options" ou SHIFT-CTRL-F11 . . Inicialmente suportando os seguintes modelos: Bematech. . ***** Nota IMPORTANTE sobre a Versão CLX ***** .

(Nenhuma experiência do autor).Monitor de Bombas de Combustível. Desenvolvimento . um Memo simulando a fita (permitindo salvar) ACBrUtil . e todos ECF's 2 estações suportados por ACBrECF ACBrDisplayCliente .Componente para formatar informações no LayOut do Sintegra. Bematech. suportando os registros da serie 50 e 60 ACBrTEF .Leitor de código CMC7 de Cheques.Display de Mensagens de 2 linhas acoplado a teclados reduzidos.)..Unit contendo diversos procedimentos e funções úteis para aplicações comerciais: ValidaCNPJ. (Experiência apenas com TEF Discado) ACBrCalculadora . ACBrLeCMC7 ..Andre Ferreira de Moraes WebMaster. ACBrSintegra .Projeto Jedi Diversas rotinas e o arquivo ACBr. como por exemplo. Modelo suportado: CompanyTec ACBrLeBarras . Arquivos de ajuda . mas com algumas frescuras a mais.Para impressão de Cheques.. Modelos: Gertec ACBrBombas . A impressora de cheques pode ser avulsa ou conjugada ao ECF (ECF 2 estações). comunicando pela porta AT.Componente para facilitar a criação dos arquivos de troca entre a Aplicação Comercial e os programas das Operadoras. Documentação..Display de Mensagens de 2 linhas para o Cliente (fica voltado para o Cliente e exibe informações sobre a venda.251 ACBrCheque . Extenso.Daniel Simões de Almeida Administração do Projeto. lendo os abastecimentos gerados. Inicialmente com suporte as Impressoras de Cheque Chronos. ValidaCPF.inc foram baseados no código da JCL e JVCL -------------------------------------------------------------------------------- . Inicialmente suportando o Gertec ACBrDisplayOperador .Alexandre Rocha Lima e Marcondes Administração do Projeto e Suporte . ValidaINSCEST.Mais uma calculadora. etc -------------------------------------------------------------------------------7. alterando os preços das Bombas. AUTORES E COLABORADORES .Permitindo acesso a informação lida por Leitores de código de Barra ligados a porta serial.

Doações podem motivar os desenvolvedores a destinar mais tempo para o andamento do projeto. porém em uma versão antiga (causando Bugs no seu programa) ... .Multiplataforma: Linux / Windows . ficaremos muito contente com a sua ajuda.....Programação Limpa e Clara: Basta inserir um componente ACBrECF no seu projeto e configurar o Modelo.-) -------------------------------------------------------------------------------9. Por favor nós envie-nos um e-mail com os seus testes. entre em contato antes) * Emprestando Equipamentos: Nem sempre temos acesso aos Equipamentos para testes e melhorias.. Se você é um fabricante ou possui um equipamento disponível para emprestimo. * Testando os Componentes: Fizemos o possível para eliminar os bugs mais óbvios. até mesmo os programadores precisam comer.Facil distribuição: Não precisa distribuir e instalar nenhuma DLL ... (Quando o usuário instala outro programa que usa a mesma DLL que você usa...) .... Se o equipamento que você deseja não consta na relação de Equipamentos a compatíveis você pode estudar os Fontes e tentar implementar uma nova Classe para o seu Equipamento (Por favor.. COMO POSSO AJUDAR NO PROJETO Se você possui experiencia em Automação comercial e deseja ajudar. entre em contato Em breve estarei relacionando os equipamentos que necessitam de testes.. mas em ambientes diferente bugs novos podem aparecer. * Divulgando o ACBr: Quanto maior o uso da biblioteca mais usuários podem ajudar. sem se preocupar com implementações específicas de cada Modelo.Livre-se do Inferno das DLL's.. sabe o que eu quero dizer. * Efetuando Doaçoes: Atualmente a Biblioteca é desenvolvida no tempo livre disponível dos Desenvolvedores. VANTAGENS E DESVANTAGENS Vantagens: .Total controle da Aplicação: Já vi DLL's que simplesmente param o processamento do programa (Quem já homologou TEF discado.252 8. junte-se a nós. .. Se a biblioteca for bem conhecida e utilizada os Fabricantes de equipamentos de Automação Comercial terão maior interesse em ajudar no desenvolvimento. * Desenvolvendo Componentes: Alguns componentes como o ACBrECF deverão ser implementados para vários modelos de equipamento.. Mesmo que tudo dê certo ainda sim gostariamos da sua opnião. O Codigo fonte sempre irá se referir a esse componente... pois é.

.-) -------------------------------------------------------------------------------11. MELHORADAS OU COMPLETADAS Na versão atual existe tanto a fazer e programar que essa seção seria muito grande. .. TAREFAS QUE AINDA PRECISAM SER INICIADAS.DPK (para versão VCL) ACBr\Source\Pascal\ACBr_D5. vai abrir o Delphi..DPK para a versão desejada. Na IDE do Delphi acione "File. . Open" Localize o arquivo ACBr\Source\Pascal\ACBr_CLX.. ou até mesmo de um modelo do equipamento para testes.1. Ao abrir o Delphi.Instalação  Descompacte o arquivo .  Abra o arquivo . Aqui teremos que implementar um novo filho das classes Basicas para cada Hardware novo (somente se o novo hardware não for compatível com o antigo) -------------------------------------------------------------------------------10. ficamos dependendo de novas informações do fabricante.DPK (para versão CLX) ou ACBr\Source\Pascal\ACBr_VCL.Se o hardware mudar.. HISTÓRICO DO DESENVOLVIMENTO Por favor leia o arquivo: " ACBr-change-log..Geralmente as DLL's incorporam novos Hardwares do mesmo fabricante. conforme mostrado abaixo: .DPK (para Delphi 5) Dando duplo clique neste arquivo.TXT " 16. aparecerá o pacote para instalação e compilação do componente ACBr..ZIP na pasta de sua preferência.2 .253 ) Desvantagens: ..

Feche o arquivo DPK necessidade de salvar).  Clique em OK. Figura 137 – Informações de instalação do pacote ACBr .254 Figura 135 – Conteúdo do pacote ACBr  Compile e Instale a Biblioteca. (não há Figura 136 – Mensagem de instalação do pacote ACBr. O quadro abaixo informa que a compilação foi bem sucedida. Clique em "Compile" e em seguida em "Install".

ACBr VCL é um pacote para o Delphi... Click em "OK" para finalizar.2 .  Na IDE do Delphi acione "Tools. Enviroment Options" selecione a guia "Library".) de "Library Path".  Clique em File/Open  Localize o arquivo na pasta ACBr/Sourse/Pascal/Demo/VCL e abra o projeto BalançaTeste.  Abra o Delphi.) à frente da caixa de texto.  A paleta ACBr será criada com os componentes da Biblioteca ACBr.Paleta ACBr com todos os seus componentes instalados.  Não salve o projeto. Figura 138 . clique no botão elíptico (. O sistema de comunicação com a balança será aberto.  Rode o Demo . clique no botão elíptico (.Um Exemplo Para exemplificar ganhando tempo.255  Adicione o diretório " ACBr\Source\Pascal " no "Library Path".. e em "Add". vamos pegar um projeto demo pronto que já está dentro do arquivo ACBr.. clique em "OK". uma paleta inteira não compilada 16. localize a pasta " ACBr\Source\Pascal " no diretório de instalação da Biblioteca.

256 Figura 139 – Formulário do demo BalancaTeste  Selecione a balança.A programação do componente.2. esta ligada e conectada – agora faremos a leitura de peso colocando um peso qualquer na balança. No exemplo deu 172 gramas que é o peso que foi colocado na balança. mas isso é só para exemplificar. mandamos fazer a leitura. A resposta que a balança mandou. A porta de comunicação estará ligada na própria Com da máquina (COM1 ou COM2) . Não será necessário modificar nada. Foi feita a leitura. No exemplo usaremos a balança Toledo. O símbolo #3 no final é para indicar que terminou a leitura do sistema. o numero 2.1 . Está enviando peso que é 00 99999 gramas – lógico que essa balança não agüenta 99 quilos. Se fosse 1200 gramas então mostraria o 1 (um) e embaixo 200.  Após a escolha mande ativar. indicando que é peso. o máximo que essa balança agüenta é 15 quilos.  Escolha a porta de comunicação que no caso é o COM mesmo. A única escolha a ser feita é a balança que no caso é da marca Toledo. 16.

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 genérico do formulário demo BalancaTeste. .

2 . é mostrada uma mensagem de erro no campo Mensagem.A configuração do DEVICE Se quiser configurar a velocidade de resposta da balança na porta serial essa configuração é feita em Device que por padrão tem um valor já configurado (9600 (Baud).1 .2.2. uma é teste e a outra um outro tipo. No caso foi deixado como nenhum para ser genérico. Se Filizola ou Toledo. para servi em qualquer um. Se no mesmo estabelecimento tem que ter a balança e a impressora fiscal. não modifica nada. Temos uma máquina 1 e maquina 2. 8 bits (Data).Baud Rate Como funciona uma porta serial.2. Então já vem previamente configurado o valor da porta serial porque na porta serial da nossa máquina não está préconfigurada para 9600. enviado por 1 e . sem paridade – none (Parity). com um cabo ligado entre as duas. temos que selecionar a porta. teremos que ter duas portas seriais. Esta sendo enviada dados de um lado para outro. o nome de programação que estamos trabalhando que no caso é o próprio nome. uma para a balança e a outra para a impressora. 16. Se a balança não responder dentro de 2 segundos. em propriedades. 16. OBS: Se for usado o emulador essa configuração terá que ser mudada para 4800 em Baud. O intervalo mostrado é o tempo (o número 200 dá aproximadamente 2 segundos) para que a balança lê a cada 2 segundos.258 Essa parte que ele colocou aqui é só para ter a opção de trocar – o exemplo pode ser genérico. Selecionando o componente. Figura 142 – Propriedades do componente ACBrBAL – o Device Por último o modelo da balança que vai trabalhar. bits de parara = 1 (Stop)).

na hora que for descarregar o caminhão. tem outros configurados com 128000 e a porta serial das máquinas dificilmente estão em 9600.2. Mas porque? Não é sempre oito? Não. as duas portas tem que estar na mesma velocidade. Quando chegar todos os números no destino. as duas máquinas tem que rodar na mesma velocidade. só que é uma palavra da tabela ASC e não de ASCII. Só que para funcionar. É enviado o primeiro digito “1”. cai 9600 laranjas em cima da cabeça de alguém. só consegue receber a 9600Kbps.259 recebido por 2. já vem configurado com 56000. então sai de baixo porque as laranjas vão te atropelar literalmente. será enviado sete caracteres por vez. envia o próximo dígito. Os dois pontos tem que estar conectados na mesma velocidade e essa configuração é feita no Device onde é fixada a velocidade da porta. Se deixar com essa configuração a balança é literalmente atropelada. ela só funciona a 9600.2. Agora imagine se não tivermos a mesma situação. Sete bits é igual a uma letra. A balança trabalha com caracteres especiais e se nós trabalharmos com 7 bits não será feita a comunicação. fazendo isso um por um. Não adianta descarregar um caminhão de laranjas e não ter um recipiente para receber as laranjas. O normal é 8 bits. porque será mandado tantos dados que ela não consegue ler nem ¼ do que foi enviado. Alguns sistemas trabalham com sete caracteres. eles serão reunidos novamente. Se o caminhão tem a capacidade de descarregar 9600 laranjas e você pode pegar somente meia dúzia por vez.2 . então não perderá nada na descarga. 16. que é representada pelo número binário 1000001 da tabela ASCII. não importando a velocidade configurada. Porque temos que saber isso? Os PCs de hoje em dia. Para evitar perdas de valores. Não 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 também as 10 letras por minuto. porque se um dado se perder no meio do caminho será possível descobrir o valor Se a soma dos dados der um número . É necessário baixar a velocidade para a balança conseguir fazer a comunicação. Para caracteres só de letras podemos usar a tabela ASC. um caminhão cheio de laranjas descarrega 9600 laranjas num único segundo e se tiver um recipiente que receba essas 9600 laranjas. Para enviar a letra “A” para o outro lado. Dividindo por 8 verificamos que ela consegue receber 1200 letras por segundo. depois que chegar do outro lado. um pouco mais que 1K. Se tivermos uma esteira de transporte de laranjas e estamos trabalhando com uma velocidade de 9600 laranjas por segundo. A cada segundo é transferido um 1kb de dados. No caso dessa balança. é enviado também um bit a mais para informar se a soma dos caracteres é par ou impar. vai trabalhar a 9600 Kbps. Cada vez que enviar uma letra. Oito bits é da tabela ASCII que são 255 possíveis caracteres.Parity (paridade) – Cada vez que um dado é enviado.

isso é para verificar se existe ou não a balança. Ou é fixado no componente o valor configurado ou colocamos nos campos criados e na hora que ativar preenchemos os campos depois.Se for “0” escreve “'Coloque o produto sobre a Balança!' porque leu zero – não tem nada. A leitura é (lerPeso) e passamos o tempo de espera de resposta. só que se esquecer de por o . Essa propriedade teste é o valor que podemos inserir. ele copiava só os dados. Neste caso no ativar. Se a balança manda um número negativo. faz a formatação porque o peso tem um valor sem formatação nenhuma. então basta dar o comando ativar e depois fazer a leitura.260 par.2. Não tem fluxo de paridade porque a balança não controla isso. gravava dentro da paridade. Ai chama a rotina que lê o último peso lido que retorna um número. O comando ativar manda o caractere #5 para a balança. . estando genérico é possível altera se quiser de acordo com a balança escolhida. Isso é feito se caso houver falha no envio de algum dado. será possível saber qual o numero que faltou. Porque pode ser que ela esteja quebrada. Aqui ele pega o valor do tempo em txt da propriedade teste. Esse outro lePeso trás o último lePeso lido e a resposta. Esse 200 são 2000 milisegundos que corresponde a 2 segundos. que é o tempo de resposta que a balança dará depois da leitura do peso.Se for “-1” quer dizer que o peso está instável. “-2” =‟peso negativo‟ – foi calibrada a balança para –50 gramas. . A função lePeso trás um resultado do peso lido – é 00. gravado dentro do modelo. desligada ou sem energia.Stop Bits (Bits de parada) – bit para identificar que terminou. Todo peso que é lido teoricamente é positivo. mas podemos deixar fixo no sistema colocando por exemplo 2000. quando fazia o ativar na balança. por exemplo: 1 + 1 + ? = 2. É só colocar 2000. Por exemplo: num restaurante é calibrada a balança para ler –50 gramas ( o peso do prato) e na hora que for colocado um prato cheio é lido só o conteúdo. Quando mandamos o comando para a balança ela começa a fazer a leitura serial com o micro. portanto no momento que mandamos o comando para verificar sua funcionalidade. a balança retorna true ou false como resposta. o terceiro número só pode ser zero porque a soma já é dois. basicamente preenchendo o valor das propriedades.3 . Converte o valor do peso lido. algum problema ocorreu.2. Essa configuração do lado não seria necessário porque podemos deixar fixo no componente. o que é escolhido. Poderíamos ter feito esse comando em propriedades que funcionária igual. como o negócio é genérico. Após chama outra função. O comando ativar fará a leitura da configuração que tiver sido feita. Depois que estiver pronto pressionamos o botão ativar. um número que vai ter que ser dividido em pedaços. não consegue ler nenhum número. Então faz a formatação aplicando uma mascara. chamando a rotina lePeso e passa o peso que ele trouxe. 16.

dará peso negativo. case valid of 0 : Memo1. Então podemos controlar a carga de um caminhão que chega ou que sai.Text := 'Leitura OK !' else begin valid := Trunc(ACBrBAL1. begin sttPeso. Agora é possível ver qual a diferença de peso. podemos controlar produto vendido dentro de um supermercado. if Peso > 0 then Memo1.  Em propriedades do componente especifique no Modelo a balança Toledo . mas esqueceu de por o prato na balança.UltimoPesoLido).Caption := Converte( Resposta ) . O processo de funcionamento entre uma balança e outra é o mesmo. por exemplo pesou 162 T e esse valor fica armazenado dentro do banco de dados. a diferença é o produto que foi descarregado.Lines.Lines.  Coloque o componente ACBrBal no form. 10 Sobre peso – Se for colocado um peso a mais do que a balança pode suportar. sttResposta.Lines. end . porque mandou ler. var valid : integer. O caminhão é descarregado e volta para a balança para ler um novo peso. end. -10 : Memo1.Text := 'Peso Negativo !' . O Código da explicação é o mostrado abaixo: procedure TForm1. Peso ). Resposta: String). a diferença está na ordem dos valores. por exemplo mais de 15 Kg.Caption := formatFloat('##0.261 prato antes de fazer a leitura. E uma balança para pesar caminhão? O caminhão carregado passa pela balança e você manda fazer a leitura. -2 : Memo1.Mais um exemplo:  Abra uma nova aplicação. Primeiro coloca o prato.Text := 'Peso Instavel ! ' +sLineBreak+ 'Tente Nova Leitura' .Lines. por exemplo 131 T. depois faz a leitura.000'. um peso pequeno ou um peso gigantesco. -1 : Memo1.3 .Lines.ACBrBAL1LePeso(Peso: Double.Text := 'Sobrepeso !' . 16.Text := 'TimeOut !'+sLineBreak+ 'Coloque o produto sobre a Balança!' . end.

Crie uma variável do tipo double.ativar.1 . para que não fique amarrada a resposta no infinito. end.lepeso(2000). faz a leitura e fecha. e se é uma função retorna tipo float com número inteiro. var aux :double. Se for colocado uma espera de 3 horas.desativar.A programação programação do botão var aux :double. acbrbal1.desativar. 16.lePeso e por padrão passamos o tempos que vai demorar para fazer a leitura. acbrbal1. begin acbrbal1. Mande ativar. aux:=acbrbal1.lepeso(2000). Quando mandar um comando para a balança. Essas linhas é para receber a leitura da balança ativando-a. . fica travada.262  Coloque um botão para fazer a leitura. aux:=acbrbal1. vai mostrar um número tipo 00262. por exemplo AUX:= valor E por último desativa o componente ACBr.  Insira um Edit para ver a leitura na tela. edt_peso. Quando clicar no botão já é feita a comunicação.text:= floattostr(aux). Logo depois faça a leitura do peso. espera até dois segundos para ela responder.  Coloque um componente para ver o valor a partir da tela.ativar. A rotina que faz a leitura é ACBrBAL1. Note que é uma função. Coloque dentro de uma variável. enquanto não receber resposta. armazenando o valor lido e desativar a balança. acbrbal1. no caso vamos colocar dois segundos.3. Se for colocado 262.

text:= floattostr(aux). FormatFloat -> o valor desejado com formato de 3 casas após a vírgula depois o valor que queremos mostrar. 16. Pode ser colocada a leitura num formato melhor passando uma string com 3 casas depois da virgula. A leitura inicial é zero.263 Agora mostramos o valor da leitura: edt_peso.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.3. Aumente o tamanho da fonte. Porque FloattoStr – porque mandamos converter float para str. O formatFloat pega o valor e vai colocar obrigatoriamente 3 casas após a virgula. Figura 143 – Formulário teste Rode o programa e faça uma leitura. Crie uma tabela no Paradox  Abra o Database Desktop no Paradox e crie a seguinte tabela: .

Abra o banco de dados e digite os valores: Figura 145 – Preenchimento da tabela Produto no Paradox. .  Feche o banco.264 Figura 144 – Criação da tabela Produto no Paradox Salve a base de dados.

 Driver Name = STANDARD  Clique em Defauts e prencha o PATH com o endereço do banco criado anteriormente.265  Da paleta BDE coloque um componente Database  De duplo clique no componente e preencha as propriedades: Propriedades:  Name = Banco.  Active = True Para fazer a venda:  da paleta DataControl coloque uma grid para mostrar os dados do produto.  Coloque um componente Table da paleta BDE no form.  da paleta DataAcces coloque um componente DataSourse Propriedades do DataSourse: DataSet = Tbl_Prod .db  Name = Tbl_Prod.  Desmarque Login prompt e clique em OK.  TableName = Produto. Figura 146 – Preenchimento das propriedades do Database  Connected = true. Propriedades da table:  DataBaseName = Banco.

Text:= FloatToStr(aux). var aux.  Coloque mais um Edit para ver o valor total da conta. Edt_Total. Edt_Peso. Para calcular o valor do produto.  Propriedade: Name = Edt_Total. ele é retirado da tabela Produto.3 .Fazendo a programação: Com o sistema ligado na tabela fazemos a programação procedure TForm1.aux. acbrbal1.desativar.FieldByName('Qtd_Prod'). Tbl_Prod.Post. begin acbrbal1. end.AsFloat.Button1Click(Sender: TObject). 16.FieldByName('valor_prod'). Edt_Total.Edit.valor :double. aux:=acbrbal1. Tbl_Prod.AsFloat.266 Propriedades da Grid: DataSourse = DataSourse1 Basicamente o usuário clica no produto que ele quer e depois em Ler Peso.FieldByName('Qtd_Prod'). var aux. end.valor :double. Depois armazenar em uma variável o valor do produto para fazer o calculo do valor total (valor * qtde) Cria a variável valor do tipo double. Tbl_Prod.lepeso(2000). valor:= tbl_prod.3. Vai multiplicar o valor lido pelo valor do produto cadastrado.AsFloat .ativar.FieldByName('valor_prod').Text:= FloatToStr(aux * valor).AsFloat:= Tbl_Prod. .Text:= floattostr(aux * valor). valor:= tbl_prod. que seria a leitura da balança.

A quantidade vai receber a própria quantidade menos o que foi lido. Por último.FieldByName('Qtd_Prod').aux.AsFloat .AsFloat:= Tbl_Prod.Edit.267 Agora temos dentro do Edt_Lido o valor que foi lido e o valor dado para pagamento Para calcular o total: Edt_Total. Então o sistema coloca na tela. mostra o total e por último atualiza o bando de dados. multiplica o valor. salve a tabela Tbl_Prod.Text:= FloatToStr(aux * valor).Aspecto do formulário depois de pronto Execute o sistema. O que foi feito Feita a leitura na balança. mostra os dados e altera o que vai sobrar no banco (atualiza o BD) Figura 147 .Post.FieldByName('Qtd_Prod'). Coloque a tabela em modo de Edição: Tbl_Prod. . Tbl_Prod.

deste a mais simples até a maior balança que faz lê peso de caminhão é o mesmo. O padrão de comunicação da Toledo. não dá para . Coloque o produto sobre a balança) Se der uma mensagem diferente temos uma tabela de erros: por exemplo: 0 : 'Coloque o produto sobre a Balança!' . se for rodado para fazer a leitura. -2 : 'Peso Negativo !' . Para o produto limão.. Cada vez que for feita uma venda. Enquanto a doméstica lê peso em grama a outra pode ter uma variação de tolerância em quilos a mais ou a menos. tinha uma quantidade de 100Kg. -1 : 'Peso Instavel ! ' + 'Tente Nova Leitura' . procurou o valor e trouxe zero que é a propriedade da balança. então mostra a mensagem (Se o retorno for zero then. temos a baixa no estoque. A única diferença é a variação do peso em gramas. Basicamente a programação se resume em poucas linhas. -10 :'Sobrepeso !' .Aspecto do formulário depois de executado. Na escolha do produto limão a quantidade era 100 e quando clicar para fazer a leitura. Se for “0” escreve “'Coloque o produto sobre a Balança!' porque leu zero – não tem nada. continua tendo 100 Kg.268 Figura 148 .. porque já imaginou um caminhão carregado de gado se mexendo. Porque mostra a mensagem ―'Coloque o produto sobre a Balança!' Foi no banco de dados. faz a leitura do peso e multiplica esse valor pelo preço que foi colocado no produto e já faz a baixa no estoque.

O emulador para balança Toledo A pessoa digita o valor que quer e manda enviar para a porta. tem que ter um limite de tolerância a mais ou a menor para poder fazer a leitura. . uma máquina para simular a balança e a outra para fazer a leitura. não esquecendo de configurar a porta de entrada. A idéia para isso funcionar é ter uma máquina com esse programa e a outra com outro sistema.269 o peso se estabilizar. uma para instalar o programa da balança e a outra para o sistema fazer a leitura. São necessárias duas máquinas.

clicando pasta por pasta. Compacta tudo. tanto faz. O que ele faz? Recompila de novo os arquivos modificados e gera um novo software. Pode ser através de Project Wizard ou Blank Setup Project tanto faz selecionar um ou outro. foi feita simulação.1 . mas com ela conseguimos criar instalações bastante completas e profissionais para nossos sistemas desenvolvidos em Delphi.Criando a Instalação {Supondo que você fez um sistema. O software já foi instalado e testado em uma máquina virtual e já se sabe quais os arquivos necessários para fazer funcionar esse software Tudo bem. da empresa InstallShield Software Corporation. um software precisa ser instalado e se for modificado um arquivo é só abrir o arquivo de projeto e mandar recompilar. O InstallShield. agora é preciso vender para o usuário.270 17 – INSTALL SHIELD Um software que pode fazer a instalação do sistema desenvolvido e que vem junto com o CD de instalação do Delph. A diferença que um é em caixas de diálogos e o outro é só preencher os dados do lado. que está no diretório C:\Arquivos de Programas\Borland\Delphi7\Demos\Db\CtrlGrid. tem que ser criado um executável para instalação que pode ser através de um Wizard ou de um formulário em branco. foi feita a brincadeira completa. 17. Temos que selecionar qual tipo de projeto que vamos fazer. Para cada projeto criado. Com o InstallShield aberto: Na primeira tela. foi criada rede. É necessário gerar agora o arquivo de instalação. como se fosse o arquivo do Delphi. Tudo foi testado antes. Fazendo pelo Wizard nota-se que o outro jeito aparece do lado e vai ser a mesma coisa. é preciso levar o software para instalação. Então cada vez que for feito um software. É uma versão mais simples (Express Borland Limited Edition) do que a versão full. escolha a opção Create a new project . temos tudo isso. Tem que ser selecionada a localização que vai ser salvo o sistema a ser instalado.

271 Figura 149 .Criando um novo projeto. .Tela de Menu do InstallShield Após 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 .

Tela de boas vindas Será aberto um Wizard para auxiliar nos passos iniciais de criação da instalação Vai criar um novo projeto? Qual vai ser o nome do projeto? .272 A próxima tela é de boas vindas – clique em Avançar Figura 151 .

Grid Demos do Delphi)  O idioma – no caso só tem dois – escolha o inglês.  Clique em avançar. .273 Figura 152 – Criando um Novo Projeto  Selecione a opção Create a New Project  No campo escreva o nome que quer dar em seu Projeto (Ex. A verão Full é mais completa.

Para cada vez que for mudada a versão por motivos de correções.2. Ex. Application Version: Digite o número da Versão da aplicação – no caso versão 1.0. Temos então a Versão.1 e na segunda correção será 1. a Sub-versão e a compilação. Grid Demos Delphi. Qual o nome da aplicação? Nos campos: Application Name: Digite o nome da aplicação. a numeração é alterada. .0. Default Destination Folder: [ArquivoProgramaFolder]Nome da sua Empresa\Nome do seu produto Se tiver uma correção na versão.274 Figura 153 . Podemos compilar 9.999 vezes antes de mudar de sub-versão.Informações da aplicação. a nova versão será 1.  Clique em avançar.0.

Ativar para receber atualização via InstallShield UpDataService – Isso não resolve nada. . Podendo deixar ativo ou não. porque não faz diferença. É só atualização do instalador.  Clique em Avançar.275 Figura 154 – Atualizações do Software.

276 Figura 155 .  Telefone: <CodigoPais> + <CodigoRegião> + <Telefone> Se tiver um Site pode ser colocado o Site da empresa. Coloque um numero de telefone para que o usuário final possa entrar em contato com o suporte técnico.unilins.Informações do Software  Nome da companhia: <NomeCompanhia>. exemplo: www. É basicamente a mesma coisa para a maioria dos casos. .edu.br.

um arquivo . . Os outros arquivos. Imagens. Quando fazemos a instalação do Office. Relatórios) o usuário não é obrigado instalar na mesma máquina. Na documentação pode ser escolhido o que vai ser copiado lá dentro. São os arquivos básicos – uma DLL. O diretório escolhido para instalação também instala os arquivos colocados neste campo. etc? Sim. Faturamento. vários pacotes diferentes. aparece os campos para instalação de outros arquivos e você vai clicando (marcando) os arquivos que quer instalar. Campo Alwayas Install – O que é isso? Quando for instalar pode ser dividido em pacotes.INI. Poderia criar um pacote de vendas. por exemplo: Num grupo de arquivos que devem ser instalados. Tipo de compra. O pacote que tiver no Alwayas Install sempre será instalado. Sempre vai ter que copiar a DLL – procura a DLL independente da versão de escolha assim como o banco de dados. vai ser instalado. Se ele faz vendas. poderia. independente da versão. mas alguns deles sempre terá que ser instalado para o perfeito funcionamento (uma DLL por exemplo). independentes da instalação dos arquivos escolhidos irão ser copiados porque são essenciais para o funcionamento. um sistema de vendas que foi dividido em vários módulos (Tipo de venda. Todos os pacotes usam essa DLL.  Alwayas Install – o que vai ser instalado. Os arquivos que forem colocados neste campo. Então podemos ter vários tipos de instalação.277 Figura 156 – Apresentação da Aplicação. esses tipos de coisas. instala só o módulo de vendas. compras.

não esquecendo de DLLs ou outros (como arquivo de help. *. Figura 157 – Arquivos para instalação. Descrição Programa Executável Ajuda do Sistema Arquivos de Dados Extensão *.gdb Tabela. vai instalar. Em qualquer documentação vai instalar algum arquivo.mdb. Application Features. No nosso caso. *. vamos adicionar o mesmo arquivo. *. Veja um exemplo na Tabela abaixo.278 Na tela seguinte. por exemplo. . Na tela Application Files adicionamos todos os arquivos que deverão ser instalados na máquina do usuário para o sistema funcionar. O sistema por padrão.fbd. podemos definir itens que poderão ser selecionados para instalação pelo usuário. *.exe *.ib.db. isso não é necessário e.) se esse for o seu caso. Se for colocado em avançada. vendas junto com os arquivos que vão fazer parte dessa instalação lembrando que tudo que tiver no campo Alwayas Install vai ser instalado. *. Para quando for documentação padrão queremos que mande um determinado arquivo.xml. Depois se for escolhida a documentação na documentação padrão. *. *. Para adicionar clique em Add Files e selecione os arquivos necessários para o funcionamento do sistema. Arquivos que devem ser adicionados na instalação. arquivos INI etc.hlp *. Cada opção escolhida é o arquivo que vai ser gravado (instalado). portanto vamos oferecer somente o item Always Install.dbf.  Clique em Add Files para adicionar os arquivos a serem instalados.

279 Figura 158 – Arquivos Instalados. Clique com o botão direito do mouse em cima de Programs Menu e escolha New Folder.  Clique em Avançar Na tela Create Shorcuts configura-se os atalhos dos arquivos da instalação. . Digite o nome do sistema para a pasta e aperte Enter.

etc. Depois de escolhido o tipo de instalação pode ser instalado os aplicativos desejados. ele executa. Dentro da documentação pode ser colocado vários subtipos: Documentação Padrão. etc.  Crie algumas pastas para subtipos e clique em avançar. o dia da instalação e a configuração – é um arquivo de registro (Reg File). pode ter um arquivo de registro anexado para cada um deles porque no Windows quando instalamos alguma coisa. Temos duas telas: uma que tem os campos Típico. Podemos adicionar informações neste registro basta ser colocado um arquivo neste campo. Então este jogo de aplicativos que queremos é a tela mostrada abaixo: Pode ser especificado o diretório para a instalação do pacote.280 Figura 159 – Criação de Shortcuts. Só que é necessário saber qual o arquivo que vai ser executado. . etc. Esse arquivo serve para registrar o software. Padrão. Podemos criar um arquivo. Pode ser criada várias partes ali dentro em subtipos. o diretório de banco de dados. Uma espécie de TXT que ele executa. Agora para cada uma das instalações avançadas. para deixar o Pet bem visualizado. personalizada. para criar um ícone.. Custon.  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. apontar o arquivo e dependendo da instalação que for feita. existe um arquivo que controla toda a versão que foi feito quando foi instalado. Documentação Avançada.

conforme for escolhido.INI.281 Agora para cada tipo de instalação vai dizer que é avançada.  Clique em Avançar. podemos ter um arquivo de registro. aparece a mensagem “Registrando seu Software” – é a hora que executa o arquivo de registro. . Para cada tipo de instalação. é igual a um arquivo . vai registrando o que for necessário. No final da instalação de um software. Figura 160 .Registro do sistema. nada mais que um arquivo TXT cheio de comandos.

 Clique em Avançar Figura 162 – Sumários.282 Figura 161 – Diálogos. .

Organização do Setup. Aqui temos toda a organização: informação geral sobre o software (qual a versão do produto. É possível modificar esses dados. o tipo). ela é colocada no campo General Information com o campo YES preenchido. A descrição – Quando for clicada na documentação. O local.283  Clique em Concluir 17. Pode ser personalizada cada uma das instalações. a letra. General Information Se for criado algum pacote que o usuário não pode mexer e é obrigatória a sua instalação. Figura 163 – Organização do Setup. O tipo de instalação para cada arquivo.2 . vai aparecer os documentos explicativos do sistema gerado. . O nome da empresa.

arquivos comuns. Dentro do Progress Files. onde será posto o arquivo. podendo-se mudar cada um desses nomes alterando o nome das pastas. só na versão full. o próprio sistema já esta configurado para instalação automática. Poderia criar alguns outros. Para cada tipo de instalação.Se no tipo vai ter só o sistema escolha só o sistema. Custom . Todas as pastas do Windows. Se é uma DLL que precisa estar dentro da pasta System 32. não vai ter nada nem o sistema. Poderia mostrar qual das pastas. Se for preciso criar uma pasta dentro da pasta Progress File então adicionamos ali dentro.Quando for mínimo. É a instalação que vai ser personalizada e vai ser escolhidos os arquivos na instalação avançada. é selecionada esta pasta e copiamos a DLL dentro dela. podemos usar a que já existe ou criar outra. Esses procedimentos estão sendo feito com Wizard. as outras pastas que forem adicionadas dentro desse diretório terão que ter permissão. Foram escolhidos os arquivos para instalação que aparecem na listagem para confirmação e checar como vai ficar a instalação. Pode ser criado um arquivo de documentação. Para cada uma das instalações podemos indicar o que vai ser instalado.284 Setup Types Typical . o usuário pode escolher. Pré-definido o diretório de instalação. se está dentro do Windows no Systen 32. então arrasta para a pasta. Pode ser feita a listagem das pastas que queremos que copie. A estrutura que for criada é a estrutura que quando o usuário escolher em avançada é a que vai ser mostrada. no nome da empresa será criada uma pasta com o nome do produto que será adicionada. Por exemplo: é preciso mandar o DCOM e o ADO juntos para efetuar conexão com o Banco de . O ideal é fazer com a versão full que tem mais opções. mas não é obrigatório. que grupo de coisas vai ser instalado. se não está faltando nada. Upgrad Paths . Specify Application Data (Especificações dos arquivos) File – Uma cópia de cada arquivo. Então se fosse uma DLL é dentro do Windows – essa é a “Destination”. Será mostrada uma listagem para confirmar se está tudo certo. Recomendado para usuários experientes. Em cada uma das instalações podemos escolher os arquivos. Podemos adicionar as pastas conforme for a necessidade.neste caso não tem porque não está neste versão. Quando for feita a instalação é copiada para a pasta System 32 tudo o que for direcionada para ela. Redistributables (Redistribuição) – O que precisa mandar junto no seu sistema. colocando as pastas escolhidas. Exemplo: Dentro da pasta Systen será colocada uma DLL. Meus Documentos. Pasta Pessoal. O Path pode ser especificado para cada um dos arquivos. Temos um padrão de compilação para copiar DLL e pode ser instalada ou não uma imagem. Minimal . é a pasta que vai ser colocada.Quando clicar em Custon. é um tipo de bloco que vamos ter disponível. O sistema deixa escolher o local de instalação mas se não for escolhida.

O Path do windows em vez de procurar em C:/ primeiro procura no sistema instalado e depois procura no windows. o sistema abre a extensão bmp em outro software e daí vira uma bagunça de software abertos.bmp. File Extensions (Associação de extensão) – Vamos supor que o programa abra um arquivo. Se tiver algum serviço do windows instalado na máquina e quer aproveitar e mandar junto. Selecione o Driver e o driver do oracle é copiado para instalação. como vai ser. um script. Pode ser criada uma pasta chamada Driver. caso contrário não instala o driver. a não ser que seja colocada dentro de um comando While. Cada vez que pressionado um ícone com extensão . algumas DLLs. Não invente de associar bmp no sistema comercial. Do jeito que está. No nosso caso não usaremos isso. Pode ser adicionado um arquivo do formato ini file. Se for um AutoCad . número de arquivos máximos que podem ser abertos com o sistema. colocada no Setup e o usuário escolhe. abre tudo quanto é imagem . porque quando for clicado um ícone com extensão bmp. então é necessário mandar junto o driver do Oracle. Só vai instalar o driver se o usuário escolher o sistema e se o sistema precisar do driver.ini. DXB. Shortcuts/Folders – A pasta que podemos criar o short cut. Isso tudo vai para a instalação padrão e pode ser escolhido o que é necessário. System. pode ser feito também. Environment Variables (Variáveis de Ambiente) – Disponível somente na versão Full. Colocamos na pasta Sistema. Pode escrever o nome da pasta e dentro dessa pasta podemos adicionar os Short Cuts. Pode ser criado Paths. Pode ser criada uma pasta com os drivers e o usuário pode escolher o driver que quer instalar. Quando for instalado. No caso não tem nenhum gerador de chave nesta versão. o sistema abre o programa e roda.285 Dados. Só para ter uma idéia. Ex: eram 100 e agora é necessário que mude para 200 arquivos. Só quando o usuário instalar o sistema. ODBC Resources (Driver ODBC) – Qual driver ODBC a ser enviado. já mostra o formato de arquivo . As extensões podem ser registradas. são os links do software. assim como mandar um banco de dados. para que o usuário não veja o que está instalado e acabe excluindo indevidamente o arquivo. Dependencies (Dependência) – Só na versão Full que pode ser colocado OCX. ele vai e copia o Driver do oracle. INI File Changes (Arquivo Ini) – Se tem um arquivo ini. essas variáveis se encontram no Windows na pasta Variáveis de .bmp. SE for acessado via Driver Oracle. especificando o diretório de destino. Qual a chave que vai ser colocada. Registry (Arquivos de registro) – Em que local serão registrados.  New Short Cut Os atalhos instalados podem ser especificados de como irão ficar. Pode ser escolhido o ícone do seu sistema. etc. no programa vai aparecer o ícone de atalho. o nome do atalho. somente na versão full.

o sistema gera cópia em tamanho da capacidade de um Cd. selecionamos o runtime e aponta para um arquivo txt.286 Ambiente. Buid Your Release . falando sobre as considerações de seu sistema e a concordância ou não dos termos. cria disco 2 e copia o restante. ma se for colocada sem versão nenhuma. pode ser adicionado um documento de licença. Os BillBoards – São as instalações que aparecem mensagens de propaganda – Disponível somente na versão full. Se for colocado 100M. as suas especificações. Gerar arquivo autorum?  sim  gerar o instalador automático  Distribuir  Bild off Setup. pode ser instalada no servidor. O Path quando for salvar. O primeiro tem 600 M. Se for escolhido CDRom e o programa tem 2 Gigas. Customize Setup – Disponível na versão full – Opção para colocar caixas de diálogos ao abrir o sistema. Quando aparecer uma caixa de diálogo informando para o usuário se concorda ou não com os termos. será dividido em vários disquetes. Na hora que fizer o diálogo vai aparecer uma tela. etc. Pagina Web – Disponível na versão full. Na rotina de instalação vai ser checada a versão do S. cria o disco 3 até alcançar o tamanho do diretório total. Dentro do arquivo de programas na pasta MySetup criou o sistema de vendas. lotou. se vai ser típico. Deve ser informado qual o tipo de mídia que vai gerar no sistema. Então escolha a versão certa. primeiro procura em um caminho e depois num outro alternativo. ao iniciar não vai ser achado o seu sistema e o windows já era. em qualquer versão do windows vai funcionar. personalizado. que pode ser alguma versão que não vai rodar o instalador. Automatic Updates – somente na versão full. Se tiver uma página Web. Se for colocado 1. Importante: Na versão original tome cuidado ao usar essa modalidade. Dentro desta pasta tem o CD. então será dividido em vários diretórios com 600 Megas cada um. a pasta de destino se pode ser escolhida ou não.Foi selecionado tudo. Pode ser colocado um texto ou documento do software. Que tipo de setup. o sistema fará arquivos de 100 em 100 megas. É criado um diretório para ser copiado dentro de um CD ou outro tamanho escolhido. O tamanho especificado da mídia é para saber em quantas mídias serão divididas.44. dizendo o que pode ser feito e o que é proibido fazer com o software. Se tiver o Path do Windows e colocar só o seu sistema dentro desse path. agora é só fazer o Build. onde pode ser colocada uma imagem.O. em que pasta será salva? Quando for salvar algum arquivo. . Ações – Só o que será feito. Se for colocado tamanho de Cd.

então é colocada qualquer CPU em lugar não acessível e plugar um PenDrive. sempre vai gerar dentro da pasta meus documentos. A instalação fica um pouco mais lenta só que cabe mais arquivos por CD. Se a impressora fiscal estiver desligada. Quando clicar aparecerá o sistema de vendas. Toda instalação que gerar. 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. Esta versão não permite fazer o autorum. pode iniciar o C2 sem qualquer dificuldade. Numa empresa todas as CPUs teoricamente estão interligadas. . as opções Disponíveis. Neste artigo vimos como criar instalações para suas aplicações Delphi usando o Installshield. vai ser gerado um disco ou mais. Este software instala qualquer programa. podemos criar instalações bastante profissionais e completas com essa excelente ferramenta.287 Agora copia tudo dentro de um CD. se der erro a DLL necessária tem que ser copiada para depois efetuar a instalação. C2 Se for inserido uma senha para iniciar o C2 qualquer pessoa pode ter acesso. Se houver algum problema o PenDrive pode ser desconectado e o sistema funciona normalmente. antes de cancelar a venda o sistema verifica se existe ou não a conecção com o PenDrive. Não tendo o PenDrive o sistema da uma mensagem de erro e cancela a venda. Para poder colocar DLL é criado um diretório System 32 e copiadas as DLLs. a licença. Ele cria a pasta MySetup e para cada projeto. nome da organização. Copia todos os arquivos para dentro desta pasta e para testar clicar em Setup. Em install vai ser gerado. só na versão full. Porque o desenvolvedor promoveu o meio necessário para efetuar a fraude. É um tutorial passo a passo. para instalar em windows e também em Linux. Compress – Para compactar o programa. Como vimos. que acompanha o produto. tipo de instalação. Quando o usuário for efetuar uma venda e não tiver impressora fiscal ligada. Numa fiscalização o dono da empresa é indiciado juntamente com quem fez o software. Para saber quais as DLLs que precisam ser copiadas é preciso instalar o programa VMWer e tentar rodar o aplicativo. em alguns minutos.

Por isso a chave do pedido não pode ser o numero de serie da nota e o numero do cupom fiscal. tem temos o número de serie da nota e nem o número do cupom. pegamos a tabela de pedido2.Cancel). ambos ligados ao componente DataBase que faz a conecção. 2.post. Então iniciando um Try.cancel. pedido. Se der certo a transmissão. A programação: 1.conection:=true. 3.A programação é feita com o comando result = 0.Connection:= true.. porque com a impressora fiscal desligada. mas só o PenDrive. O comando try é uma mensagem de erro para que não se saiba que existe um outro banco de dados. Salvamos todos os dados e no final de tudo no pedido de verdade colocamos o ponto cancel (. try banco2.288 No código fonte é feito um tratamento para que o PenDrive seja detectado se a impressora fiscal estiver desligada.. Neste comando fazemos por exemplo: Banco2.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. .Open – abrimos a tabela e gravamos os dados dentro dela e no final colocamos o comando Post. para que o pedido de verdade não seja gravado.open. pedido2. Tentamos fazer a transmissão.Result.Colocar também mais dois componentes DataBase ligados na tabela de Pedido 2 e o outro ligado na tabela de Itens 2. Por padrão o Connection do componente será false. pedido2.

You're Reading a Free Preview

Descarregar
scribd
/*********** DO NOT ALTER ANYTHING BELOW THIS LINE ! ************/ var s_code=s.t();if(s_code)document.write(s_code)//-->