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.

2 .1 .Descrição da pasta leia-me 16.2.2.Baud Rate 16.Organização do Setup.Stop Bits (Bits de parada) 16.2 .1.2.Refresh da tela (Atualização) 15.1 . .10 .1.1 .11 .A programação do componente.9.2 .Parity (paridade) 16.Um Exemplo 16.Instalando o Componente 16.Criando a Instalação.2.3.Programação dos projetos Servidor e Cliente 16 – BALANÇA COMERCIAL 16.3.1 . 17.Fazendo a programação: 17 – INSTALL SHIELD 17.A programação 16.2.Instalação 16.9.2 .3 .1 .1 .3 .2.6 15. 16.2 .Mais um exemplo: 16.3 .2 – Melhorando o exemplo: 16.A configuração do DEVICE 16.3.2.2.

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

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

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

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

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 .

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

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

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

15 .

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

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

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

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

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

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

{ TEditMaiusculo } Quando esta classe filha foi criada apareceu na interface os campos private.22 Figura 5 – Modulo de programação do componente. 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. [TEditMaiusculo]). 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. a transformação do que foi digitado para maiúsculo. public e published. A classe TEditMaiuscula herda todas as características do TEdit pai mais algumas coisas. Private e public já estavam na classe pai. begin RegisterComponents('Unilins'. entre essas características. type TEditMaiusculo = class(TEdit) private . Neste arquivo de código a nova classe TEditMaiuscula. end. será derivada por herança da classe TEdit. protected. procedure Register.

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

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

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

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

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

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

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

protected procedure KeyPress(var Key: Char). begin inherited. Para testar. feche o que está sendo feito. automaticamente irá transformar para maiúsculo. Abra um novo projeto e insira o componente TeditMaiusculo e um Tedit Comum. end.Create(AOwner: TComponent). override. begin RegisterComponents('Unilins'. [TEditMaiusculo]). . override. procedure TEditMaiusculo. Do jeito que está como True se for executado e digitando qualquer palavra.KeyPress(var Key: Char). { TEditMaiusculo } constructor TEditMaiusculo. fmaiu:= true. 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. end. end. if fmaiu = true then Key := UpCase(Key). end. begin inherited. { Protected declarations } public constructor Create(AOwner: TComponent). end. implementation procedure Register.30 fmaiu: boolean. procedure Register.  clique no componente TEditMaiusculo. { Public declarations } published { Published declarations } property Maiusculo: boolean read fmaiu write fmaiu.

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

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

xxx-xx. end. 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. contará quantos caracteres foram digitados e após o terceiro caractere colocará um ponto. Vai ser derivada do componente Edit normal. begin RegisterComponents('Unilins'. interface uses SysUtils. Classes. Conforme forem digitados os números. O evento onKey Press deverá ser tratado. end. [TEdtCPF]). No campo protected precione as Teclas CONTROL+BARRA DE ESPAÇO digite KeyPress e no combo mostrado selecione o procedimento KeyPress . StdCtrls.xxx. Esta mascara constituirá dos seguintes campos: xxx. implementation procedure Register. type TEdtCPF = class(TEdit) private { Private declarations } protected { Protected declarations } public { Public declarations } published { Published declarations } end. Temos que definir como será feita esta mascara. Foi aberta uma nova classe que não tem propriedades e nem eventos . Controls. onde será feita a programação. procedure Register. 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.33 A programação da Unit será feita conforme mostrada abaixo: unit EdtCPF.

end. 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. isto significa – faça tudo o que está programado no pai e depois execute as linha de comandos abaixo.#13]) then key :=#0.#8.KeyPress(var Key: Char). Defina para o procedimento KeyPress as linhas de comando abaixo após a palavra inherited: procedure TEdtCPF. begin inherited.'9'. . Se este comando for apagado o procedimento não executará as funções do Pai. end. if not (key in ['0'. procedure TEdtCPF..34 type TEdtCPF = class(TEdit) private { Private declarations } protected procedure KeyPress(var Key: Char).KeyPress(var Key: Char). begin inherited. override. { Protected declarations } public { Public declarations } published { Published declarations } end. Esta programação vem com a linha de comando inherited.

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

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

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

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

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

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

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

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

end. . {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'.3)+'.43 aux:= copy(text. end.#13]) then key :=#0.#8. apagar e enter.3)+'.KeyPress(var Key: Char). text:= aux. //primeiro filtro : digitar somente números.2).7.3)+'-'+ copy(text.'+ copy(text. end. procedure TEdtCPF. // 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.10.'9'.'+ copy(text.4.1. begin inherited.. end.

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

Btn_primeiroClick(Sender: TObject). procedure TFrm_CadPad.45 Figura 18 – Visualização do formulário Template Programando os botões  Programe o botão . procedure TFrm_CadPad.First.Btn_AnteriorClick(Sender: TObject). end. end. begin tbl_master.Prior. procedure TFrm_CadPad. begin tbl_master.Btn_ProximoClick(Sender: TObject). end. begin tbl_master. no exemplo: Cadastro .duplo clique em cada botão para entrar no modulo de programação.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.

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

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

um novo código.É o espaço em branco antes de começar o código que contém os dados. o digito verificador e por último o caractere de guarda que ao final indica que terminou o código de barras. 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. seqüencial para cada produto.999 códigos para representar os produtos. Margem clara. permitimos para o código do produto uma faixa de até 9. o código da empresa representada por 4 ou 5 caracteres. 4 ou 5 caracteres que representam o código do produto. Margem de Silêncio . Se ocupar mais espaço para o código da empresa sobra menos espaço para o código do produto.52 cinco dígitos para representar o produto (numa representação de até 100. permitimos que o código do produto vá até 9. O ideal para um código de barras é a impressão de barras pretas em fundo branco. As combinações de corres. As barras das extremidades e central são iguais e obrigatórias em todos os códigos. a numeração correspondente ao produto é gerada pela própria empresa.a margem de silencio. Se o código de barras conter 5 dígitos para a empresa.999 unidades. caractere que representa o início (seis caracteres para codificar tabela A ou B. então para evitar isso é necessário um espaço em branco antes de começar o código .999 unidades. o caractere central. Se tiver uma margem escura ou um quadro antes de começar as barras. Se o código começa com um (1) então é uma das empresa que pode ir até 99. 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”. . temos o digito verificador que confirma se o número da barra foi lido corretamente. Ao comprar um código de barras com 5 dígitos para a empresa. Por último. aqueles são interpretados como se fizessem parte do código. Para cada produto. A compra do código de barras é fornecida com o código do país e o código da empresa.000 produtos).000 produtos) que são começados pelo “0” até 99.999 unidades (10.

8 . Neste formato não existe o código do fabricante. terá que ser gerado um novo número. como cigarros. conteúdo.53 Se uma empresa comprar outra empresa. etc.Brasil código do fabricante código do produto dígito verificador . assim essas empresas podem atualizar o cadastro referente a esse código de barras em seu sistema (banco de dados). pelo menos cinco anos. Pode acontecer de ser colocado uma quantidade a mais e grátis numa embalagem.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. 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 .9 . embalagem. porque não está sendo cobrado esse conteúdo a mais. lápis. não pode ser reutilizado para outro produto. 6. caixa de fósforos. só tem o código do país. Para os produtos não comestíveis. O prazo de cinco anos é necessário para manter durante esse tempo um arquivo fiscal de tudo que foi vendido na empresa. 6. o código do produto e o digito verificador. 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. A diferença para o EAN13 está no método de codificação e no menor número de caracteres de dados. Na verdade ele é uma versão compacta do EAN13 visando embalagens pequenas. 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. por exemplo a fórmula. canetas.Duração do Código de barras. 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. O código de barras de um produto que teve sua fabricação suspensa. etc. Quando terminar o período.

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

O próximo dígito indica o tipo de cobrança a ser feito – se por peso ou por preço. Produtos que não são vendidos com facilidade podem ter seu código de barras colocados por preço.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. O calculo do dígito verificador é feito da seguinte forma neste código: Numere cada caractere do código. Se um produto muda muito o preço. Por exemplo: “0” para peso e “1” para preço.Sempre começa com 2 – uso interno reservado. porque é só alterar no sistema o peso e não é preciso remarcar o código de barras. para que as barras das unidades não fiquem expostas com o risco de serem lidas ao passar pelo caixa. .15 .E o digito verificador.Depois o código do produto com 5 dígitos para especificar o produto. Todo código de uso interno também tem 13 dígitos. Quando o produto é vendido por peso. . o que muda é o segundo dígito que representa o preço.  representa o fabricante  representa o produto Obs: O número 22009. produtos importados. Para o código do produto – 100. A diferença está no primeiro dígito: .Calculo do digito verificador no EAN-13.999 gramas (100 quilos). 6. . o processo é o mesmo. 6. . não significa que tem 22. por exemplo hortifrutigranjeiros e açougues.Código de uso interno Para venda de produtos. . 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.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.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. geralmente usamos colocar o peso. Se for vendido por preço.000 produtos disponíveis.Mais cinco dígitos para representar a quantidade ou o peso.55 6.13 .14 . O valor máximo que podemos representar é R$ 999. Geralmente os açougues trabalham com preço. por exemplo. o peso máximo que podemos vender é 99. . da esquerda para a direita.

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

57 disso. Em Unit file name: Coloque o diretório a ser salvo.16 .  Após criado > clique em OK Depois de criado aparecerá o código da unit abaixo: (fig.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. 28) . Geralmente no diretório por você criado ou se for usa-lo definitivamente pode deixar na pasta LIB. 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 Palette Page – coloque Unilins. Figura 27 – Caixa de diálogos para criação de novo componente. a localização destes em poucos segundos.

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

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

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

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. vtot:=vpar*3 + vimpar. então fora do laço ganha um pouco de desempenho. a variável vpar recebe o próprio valor do campo mais o caractere daquela posição (cód(i)). vimpar e vtot. Se for colocada a multiplicação dentro do laço. begin {par} vpar:=vpar+strtoint(cod[i]). vpar:=0.vimpar. var i:integer. . vimpar:=0. vtot:=0. end. Detalhe: Tanto faz se for feita a multiplicação por 3 da variável vpar antes ou depois do laço. vpar. Se o valor for impar o mesmo procedimento acima é realizado.verifica(cod: string): boolean. para cada laço que for realizado é efetuada a multiplicação.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.vtot:integer. 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. end else {impar} begin vimpar:=vimpar+strtoint(cod[i]).

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

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

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

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

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).8.200) e dividimos por 1000 que dará os 10. temos que destrinchar o código. dividimos por 100 Se for por peso – dividimos por 1000. Após transformar em número dividimos por 1000. . Então quando efetuamos uma busca. end Com isso conseguimos transformar o peso em gramas else begin fpreco:= strtofloat(Copy(text. Então quando for feito um comando LooKup.5))/1000.200g.8. este comando para o código e localiza o produto especifico daquele código. mas sim o código do produto (o campo especifico do código). Se for por preço – dividimos por 100. não passamos o text como parâmetro. if text[1]= '2' then begin {uso interno} ftipo:= 2. { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text. Ela começa na oitava posição e copia cinco caracteres.5))/100. mas quando é de uso interno. o fpeso recebe a string que acabamos de copiar. Como é string temos que transformar em numero (strtofloat).66 Ou Fazemos a leitura de todos os dígitos de uma única vez (10. como é utilizado com duas casas decimais. Para o preço. end. 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.

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

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

end. end.5))/100. { copiar o valor} if fmed then begin fpeso:= strtofloat(Copy(text.vimpar. 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.3. end. end else begin fpreco:= strtofloat(Copy(text. vimpar:=0.verifica(cod: string): boolean. for i:=length(cod)-1 downto 1 do begin if (i mod 2)=0 then begin {par} vpar:=vpar+strtoint(cod[i]). end.69 {copiar o código do produto} Fcod := Copy(text. end. end else {impar} begin vimpar:=vimpar+strtoint(cod[i]). {realiza o calculo do dv verificador} function TCodigoDeBarras. vtot:=vpar*3 + vimpar. end. end. end else ftipo:= 13.vtot:integer.5).8. end. . end.8. 8: ftipo:= 8. vtot:=0.5))/1000. vpar. if (10 -(vtot mod 10)mod 10)=strtoint(cod[length(cod)]) then verifica:=true else verifica:=false. var i:integer.

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

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

faz a busca.72 8: ftipo:= 8. inttot:= intpar * 3 + intimpar. por padrão será o 1 do item 2 abaixo. end. end.Exercício: Faça um componente que na propriedade código retorne o valor a ser localizado no banco de dados. Após isso criar um sistema de vendas usando esse componente que realiza a busca do produto e calcule o valor a pagar. verifica o código. end. já lê o código. function TEdtCodigoBarras. terá que ser feita a validade. intpar. 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. preenche o código do produto. 16. intimpar:= 0. faz o insert na tabela de itens. intimpar. . end. a variavel intpar recebe o proprio valor do cmpo mais o caractere daquela posicao(cod[i])} begin //par intpar:= intpar + StrToInt(cod[i]). inttot: integer.verifica(cod: string): boolean.18 . inttot:= 0. Quando for digitado o valor e apertar enter. end. var i:integer. end. 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. end else //impar {se o valor for ompar o mesmo procedimento acima e realizado} begin intimpar:= intimpar + StrToInt(cod[i]). 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.

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

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

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

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

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

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

Figura 31 – Pacotes de componentes.  Clique Component > Install Component Figura 30 – Caixa de Instalação de componentes. Por exemplo: temos um componente de Código de Barras que não funciona corretamente e queremos desinstalar.pás> só para aparecer a tela abaixo: Essa tela é necessária para que possamos retirar o componente desejado. É necessário dar um nome <qualquer.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. . no exemplo o CódigoDeBarras.

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

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

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

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

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

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

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

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

Se colocar só o comando Show em vez de Showmodal. colocamos o comando Free logo em seguida porque só vai executar o comando free quando fechar a tela. 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. var Action: TCloseAction). Qual a diferença? Se for usado ShowModal. Mas se quiser colocar o comando Show.show. begin Application. begin action:=caFree. será executado a linha de baixo: o comando Free.Clientes1Click(Sender: TObject). . procedure TFrmClientes.88 Esse jeito funciona no cadastro de clientes do exemplo. 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. Primeira forma: colocamos o Free na programação mostrado acima. 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. Cada vez que for fechar o formulário libera automaticamente a memória. Se usar Show. 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. obrigatoriamente temos que colocar na condição de quando for fechar o formulário recebe action := caFree.FormClose(Sender: TObject. end. end. fechou e libera.CreateForm(TfrmClientes. quer dizer que o comando vai ser executado. terminou. formulário mostrado na tela e só quando for fechado. ai ele executa a linha de baixo. frmClientes. Neste evento informe que a ação será free (Action recebe caFree). OnClose do formulário tem um parâmetro chamado Action (ação). frmClientes). fica executando e só vai para a próxima linha quando fechar o form. Modal – chama o formulário.

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

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

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

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

.  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.93 Figura 41 – Caixa de projetos – Novos itens.

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

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

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

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

98 Figura 44 – Formulário de uma calculadora simples. 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. porque na hora que fizermos a implementação.1 . vamos disponibilizar as rotinas (aquelas com os mesmos nomes que foram colocadas na DLL.  File > Save Project as > C:\Alunos\DLL\DllOperacoes – nome P_Calculadora. Salve o projeto na mesma pasta da DllOperacoes. Salve o Formulário na pasta formulários:  File > Save as > C:\Alunos\DLL\Formulários – nome: Frm_Calc. o sistema não localiza sozinho. 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). então podemos copiar nossa DLL neste arquivo (Windows Sys32) que também funciona 9. Para usar uma DLL o arquivo do projeto criado tem que estar salvo na mesma pasta que foi gerada a DLL.Para usar a DLL Na programação temos que declarar as rotinas. então tem que estar ambos na mesma pasta. Da pasta da DLL da implementação.6. . porque o arquivo DLL vai gerar um executável.

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

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

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

isso ajudaria na manutenção. 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. Vamos colocar dentro da DLL esse formulário inteiro para poder chamar a aplicação. .  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.102 Desse jeito podemos ter todas as rotinas dentro de um sistema e colocamos dentro de uma DLL. Assim podemos separar o sistema em várias DLLs e só mandamos a DLL que foi modificada. 9. Podemos colocar componentes visuais dentro de uma DLL. Fazemos a manutenção ou alterações dentro da DLL. Coloque no Form os seguinte componente: um Label. Queremos chamar esse formulário dentro de uma DLL.7 . Exemplo: Num formulário colocamos um Label e vamos chamar esse Form.Como criar formulários dentro da DLL.

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

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

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

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

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

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

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

A estrutura é vista abaixo: . Pesos: Componente de banco de dados Dll Se achar necessário . 2) Imaginemos que uma empresa deseja implantar código de barras interno. Só que em vez de usar o padrão. Se der errado. Caso seja um numero. recebe false.Prova A Tempo: 60 minutos. pesquisar o código na tabela indicada e retornar o valor do produto (aplicando a taxa_de_ganho). Nesta dll. 1) Crie um componente descendente de um banco de dados (por exemplo. grava o produto(código). Além disso. ele verifique se o conteúdo é uma string e deve colocar a propriedade tipo para string.PROVAS APLICADAS 10.5 3. A taxa de ganho é um percentual sobre o valor do produto que o usuário irá informar. a tabela a ser pesquisada e a taxa.Prova B Tempo: 60 minutos. O sistema irá chamar a rotina. Criar uma dll com uma rotina de calculo do valor de venda (valor_prod * (1+ taxa_de_ganho)).5 2) 10. tipo recebe num.1 .110 10 . Se tudo der certo. 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. ela cria o seu próprio código de 13 dígitos: inicia com 2 (interno). iremos passar o código do produto. o componente deve contar o numero de vogais do texto e setar a propriedade vogais com o numero delas. a propriedade salvo recebe true. quantidade (comprada) e valor .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.2 .

Pede-se: Criar uma rotina em DLL. Caso contrário deve ficar com false. por padrão o botão deve ser do tipo flat e as figuras devem ser colocadas no topo do botão.5 . que dado o código de barras. 4) Pesos: Componente de banco de dados Dll 3. Também deverá ser criada a tela para entrada do código a ser gerado o digito (dentro de uma dll também). Você deve informar o código de barras e ela retorna true ou false se deu certo ou não.3 . Se o usuário realizar um click sobre o componente. Pesos: Componente de banco de dados Dll 3. Criar uma dll com uma rotina de calculo do digito verificador para o código EAN 13.5 3.5 3. a um valor de 5 reais por unidade. Além disso.5 10.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.Prova C 3) Crie um componente descendente de um SpeedButton e modifique este componente de tal forma que ele possua uma propriedade chamada apertou. esta propriedade deve ficar com true. retornar o valor da compra 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. Pesos: Componente de banco de dados Dll 3.5 . quantidade e valor. Assumir um valor fixo para este campo (por exemplo. não é necessário gerar o digito verificador. se estiver com preto. ela deve gerar o código de barras com 13 dígitos e retornar este código. isto é. ele deve trocar a cor da fonte do texto.4 . todos através de parâmetros. 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.5 3. Se estiver vermelho.Prova D componente e a propriedade cores estiver com true. A seqüência de ver preto ou vermelho.112 10. Só que ela deseja gerar o código. fica vermelho. a um valor de 5 reais por unidade. 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. Criar uma rotina que dado o código do produto. vai para o preto. 2) Imaginemos que uma empresa deseja implantar código de barras interno.

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

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

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

dll -> DAO2535.TXT ========== Salve os arquivos: -> BemaFI32. é necessário que os arquivos DAO350.ini -> BemaMFD. Baixe o aplicativo no site da Bematech clicando no link desenvolvedores > downloads e drivers.DLL REGSVR32 /S MSJET35.com.116  Efetuar o Dowload da biblioteca BEMAFI32.dll No diretório de sistema de seu Windows.dll -> MSJET32.DLL . Esse arquivo deve ser baixado e gravado na pasta C:\windows\system(para windows 95/98/ME) ou C:\winNT\system32 (para windows 2000. 98 ou ME salve em "\Windows\System".DLL e MSJET35.DLL sejam registrados. Para isso. Se for Windows 2000. Se for Windows 95. NT ou XP). que gera os registros do Sintegra nas impressoras fiscais MFD MP-2000 TH FI e MP-6000 TH FI (somente). 11. NT ou XP salve em "\WinNT\System32" Caso você utilize a função Bematech_FI_RelatorioSintegraMFD. 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. 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. escolhendo o sistema operacional windows.bematech.5 .dll -> BemaFI32. execute: REGSVR32 /S DAO350.O emulador. 11.tlb -> DAO350. Ferramenta desenvolvida pela Bematech e gratuita.br Arquivo txt baixado do site da Bematech: ========== LEIAME.DLL.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.4 . Após o download faça o instalação do emulador.

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

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

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

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

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

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

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

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

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

11.11. 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 .3 – Lógica de tratamento Lógica de Tratamento Cada byte é composto de 8 bits.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 . dentro do byte. conforme a tabela acima: O valor recebido da impressora para ST1 e/ou ST2 deve ser comparado com cada bit. tem um valor.11.128 sMsg = "Fim de Papel" End If If St1 >= 64 Then // bit 6 St1 = St1 .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.126 11.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.8 sMsg = "Comando não iniciado com ESC" End If If St1 >= 4 Then // bit 2 St1 = St1 .1 .64 sMsg = "Pouco Papel" End If If St1 >= 32 Then // bit 5 St1 = St1 . Cada bit.32 sMsg = "Erro no Relógio" End If If St1 >= 16 Then // bit 4 St1 = St1 .

Fonte: www. If (ST1 and 64) = 64 then ShowMessage(‗Pouco Papel!‘).127 St1 = St1 . pouco papel (64) e cupom aberto(2). If (ST1 and 128) = 128 then ShowMessage(‗Fim do Papel!‘).32 sMsg = "Erro na Memória RAM" End If If St2 >= 16 Then // bit 4 St2 = St2 .2 sMsg = "Cupom Aberto" End If If St1 >= 1 Then // bit 0 St1 = St1 .4 sMsg = "Cancelamento Não Permitido" End If If St2 >= 2 Then // bit 1 St2 = St2 .2 sMsg = "CNPJ/IE do Proprietário Não Programado" End If If St2 >= 1 Then // bit 0 St2 = St2 .1 sMsg = "Comando Não Executado" End If Teste o exemplo acima com ST1 = 66. .8 sMsg = "Capacidade de Alíquotas Lotada" End If If St2 >= 4 Then // bit 2 St2 = St2 .com.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.1 sMsg = "Número de Parâmetro(s) Inválido(s)" End If Codificando o ST2 If St2 >= 128 Then // bit 7 St2 = St2 .64 sMsg = "Memória Fiscal Lotada" End If If St2 >= 32 Then // bit 5 St2 = St2 . e repare que você terá dois erros.bematech. If (ST1 and 128) = 128 then ShowMessage(‗Fim do Papel!‘).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 .

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

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

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

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

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

133 11. pchar( cNumeroParcelas ). cMsg := 'Compra parcelada'. pchar( cValorPago ).00.Erro de comunicação 1 . Parcelas: STRING numérica entre 1 e 24 com o número de parcelas em que o pagamento será realizado. Fonte: www. Chamamos Efetuar Forma de Pagamento escolhendo o pagamento em 3 vezes. Retornos da Função (INTEIRO): 0 . DescricaoFormaPagto: STRING com a descrição da forma de pagamento com no máximo 80 caracteres. temos que devolver-lhe o troco. -27 . iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar ( cFormaPgto ).A descrição será impressa uma linha após a forma de pagamento.Status da impressora diferente de 6. St2 e St3) Observações: . pchar( cMsg ) ).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.14 – Rotina Bematech FI EfetuarFormaPagamentoMFD  Ajuda da BEMAFI32.0 (Ack.O fechamento do cupom com formas de pagamento deve ter sido iniciado.0. -4 . Poderá ser emitido um comprovante para cada parcela. .O número de parcelas é utilizado para emissão do comprovante não fiscal vinculado. Esse valor que o cliente esta dando .0. Se o cliente vai fazer o pagamento da entrada dando uma nota de R$100.Forma de Pagamento não programada. Parâmetros: FormaPagamento: STRING com a forma de pagamento com no máximo 16 caracteres.com. cNumeroParcelas := '2'. A forma de pagamento vai ser a prazo. ValorFormaPagamento: STRING com o valor da forma de pagamento com até 14 dígitos.00'. St1.bematech.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.Ok -2 . cValorPago := '50. . Exemplo: // Exemplo em Delphi cFormaPgto := 'Cartão VISA'.Parâmetro inválido.Erro ao abrir a porta de comunicação -24 .

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

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

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

U_vendas in 'Formularios\U_vendas.pas' {Frm_Principal}.00 -----------------------------------------------Obrigado.  File > New > Unit .00g desconto -5.pas‘. Nota: No começo da programação do Formulário de vendas.00 acréscimo 10.00 TOTAL R$ 55.00 I1 50. uses Forms.UN.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.00g Cancelamento Acréscimo item 001 -10.00 Compra parcelada em 30. U_Venda_Formapag in 'Formularios\U_Venda_Formapag. 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. U_Fiscal in 'Formularios\U_Fiscal.00 -----------------Subtotal R$ 50. U_Principal in 'Formularios\U_Principal. 60 e 90 dias TROCO R$ 45. no campo uses foi introduzida a linha U_Fiscal in ‗Formularios\U_Fiscal. Crie uma Unit para colocar as rotinas da impressora.pas' {Frm_Vendas}. volte sempre !!! 11.00 A Prazo 100.16 – Implementando o programa para uso com banco de dados. VL UNITÁRIO( R$) ST VL ITEM( R$) -----------------------------------------------001 1234567890123 Produto de Teste 5 X 10.pas' {FRM_Venda_FormaPAg}.00g Acréscimo item 001 +10.pas'. conforme mostrado abaixo: program Venda.

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

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

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

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

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

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

Se for o índice da // alíquota deve ser 2 caracteres. . descrição.00 para o valor // ou 05 para o índice). valor.asinteger). Depois de armazenado todos os dados. Alicota:='18. 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.FieldByName('Imposto_Itens'). Se for o valor deve ser informado com o tamanho // de 4 caracteres ou 5 com a vírgula. No exemplo poderíamos ter armazenado o valor da alíquota de 18%.asstring. foi vendido a 18% de alíquota. porque no dia da compra do item. sendo que o código permanece o mesmo.FieldByName('cod_prod'). e essa alíquota pode mudar.asinteger.00'. Na rotina de ImprimirCupom temos que passar os parâmetros (código.asinteger:= Tbl_Prod. 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. Se o cliente apresentar uma nota fiscal antiga temos que saber quanto foi cobrada a alíquota no dia da venda. Ex.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.FieldByName('Desc_prod'). etc.FieldByName('cod_prod'). Descr:= Tbl_Prod. O código do produto da tabela de produtos é armazenada na tabela de itens.AsString:='05'. {o valor vem da tabela produto} Tbl_Itens. Tbl_Itens.FieldByName('cod_prod').) Foi salva a descrição da tabela de produtos e armazenada dentro do campo descrição da tabela de itens. 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. (18.

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

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

Quando pressionada esta tecla tem que ser iniciado o fechamento do cupom dando o desconto se existir. Aparece o total do pedido. É apresentado o cupom fiscal dando o desconto se existir. cMsgPromocional:string. cDescricao : string[80].147 end. Tipo : char. Quanto foi recebido para efetuar o pagamento e é exibido o troco se existir. Figura 59 – Aspecto do formulário Forma de pagamento para a venda. 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. procedure TFRM_Venda_FormaPAg. ****************************************************************} // AcrescimoDesconto: Indica se haverá acréscimo ou desconto no cupom. var AcreDes: char. iretorno:integer. valor: String[14]. Após selecionado os comandos e pressionada a tecla fechar venda. devemos incluir os campos Desconto e tipo de desconto na forma de pagamento. cFormaPgto : String[16]. . cValorPago : string[14]. o cliente escolhe a forma de pagamento.Btn_FechaClick(Sender: TObject).

( Valor )). // 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. pchar( cTEF ) ). no cartão. AcreDes:= 'D'. 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. iST2. mostrado no cupom.00'. iST1. É programada a forma de pagamento se a vista ou a prazo. iRetorno := Bematech_FI_RetornoImpressoraMFD( iACK. iRetorno := Bematech_FI_IniciaFechamentoCupom( pchar( AcreDes ). cDescForma := 'Compra parcelada em 30. pchar( cParcelas ). //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. // TipoAcrescimoDesconto: Indica se o acréscimo ou desconto é por valor // ou por percentual. 60 e 90 dias'. ******************************************************************* } // Escolher a forma de pagamento //Imprime a(s) forma(s) de pagamento e o(s) valor(es) pago(s). iST3 ). pchar( cDescForma ) ). cTEF := '0'. valor:= '0000'. pchar( cValor ).148 // 'A' para acréscimo e 'D' para desconto. iRetorno := Bematech_FI_ProgramaFormaPagamentoMFD( pchar( cForma ). 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'. Tipo:= '%'. // Efetua Forma de Pagamento cValor := '100. iRetorno := Bematech_FI_EfetuaFormaPagamentoMFD( pchar( cForma ). É feito os cálculos do desconto./ // ValorFormaPagamento: STRING com o valor da forma de pagamento // com até 14 dígitos.cParcelas := '3'. // DescricaoFormaPagto: STRING com a descrição da forma de . '$' para desconto por valor e '%' para percentual. pchar( Tipo ).

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.

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

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

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

a média – é o valor que vai aparecer na Grid como valor de campo. podemos definir os SUM.157 Figura 64 – Decision Query Editor. como por exemplo: Data_ped. A soma não arrastamos. podendo escolher o número de registros. é aquele que aparece no canto e selecionamos os valores que irão aparecer. Após selecionar os campos dentro da Dimensão e do Sumario o sistema automaticamente gera o SQL. Idade_Cli. por exemplo. COUNT E AVERAGE. Categoria. 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. nas SQLs. a soma. Clique em SQL Query para verificar: . Tudo que tiver campo normal. colocamos na Dimensão e tudo que tiver de somatório colocamos no Sumario. Opcionais e Valor. No resumo (Summaries) colocamos os campos que sofrem agregação. 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. podem ser contados e levam sinal de igual.

3. Indicamos o nome da tabela (FROM vendas) e indicamos um GROUP BY em todos os valores que não forem totalizados. ou contar o número de registros.  Na propriedade do componente DecisionQuery colocar Active = true.2 . Selecionamos qual SQL da tabela (que é o nome dos campos que vamos mostrar). aparece o numero de registros. Se tiver somatória media. MEDIA) da programação SQL. COUNT. conforme exemplo do quadro acima. É 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. Ao clicar em MemoryControl. tipo grade do Ecxel. onde podemos escolher a quantidade de registros que quisermos.DecisionCube  De duplo clique no componente DecisionCube DecisionCube é o componente que executa as combinações. temos que colocar no campo (SUM. 12. .158 Figura 65 – Comandos SQL para a tabela do Decision Cube. é o coração do processo.

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

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

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

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

4.163 Ver as vendas só de 2005 ou também em todo o período. faça a modificação do mesmo.9 . 12. 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. Abrimos a dimensão e fazemos o comparativo do ano de 2004 e 2005.4.10 – Exercício Trabalho: Com base no sistema dado em aula (Vendas). 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.Exemplo 9 Por opcionais. Podemos comparar os valores ao longo dos anos ou por mês. podemos saber o valor médio. .

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

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

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: .

no caso: Alta. São três formas de enviar os emails .1 . .Memo O memo é parecido com o Edit. .3.2 .CheckBox Confirmar recebimento  Por padrão checkd = false. 13. No nosso exemplo colocaremos por padrão em Alta Prioridade.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. Media e Baixa prioridade. cadastrar os itens necessários.Na propriedae Items do combobox.3.  O item padrão será a Alta (Item index = 0).167 Figura 71 – Formulário de email no Delphi.

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;

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

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

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

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

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

consulte Atributos da seqüência de conexão. Descrição Nome de usuário Servidor Conversão . (Para obter informações sobre construção de seqüências de caracteres. Os usuários podem usar qualquer método descritivo para nomear uma fonte de dados. O nome de usuário para a fonte de dados.182 Figura 81 . consulte o arquivo de ajuda do Oracle.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. O alias de banco de dados criado na SQL*Net Easy Configuration ou uma seqüência de conexão. Este campo fica em branco por padrão. o padrão é No translator (sem conversor). em branco por padrão. Para obter descrições de seqüências de conexão com banco de dados pessoais e remotos.Instalação do Microsoft ODBC para Oracle. mas é necessário.) Clique em Selecionar para escolher um conversor de dados carregado. Contém qualquer qualificador descritivo. 14.5 .

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

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

Figura 84 – Formulário de propriedades de vinculação de dados. o ADO usa as strings de conexão. Vamos procurar a conexão que vai criar que já está pronta dentro do Conect. Não é necessário criar a conexão porque já esta pronta. . É possível digitar uma string de conexão. Para indicar o banco de dados.  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. Se não der certo é porque o arquivo TMF está errado. se souber o que está fazendo. mostrado na figura acima. basta utilizar. No campo Use Connection String escolhemos a conexão oracle.  Selecione Permitir salvamento de senha. Neste campo é feita a opção UserName e senha. mas em geral usamos o editor de strings de conexão.

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

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

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

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

 De duplo clique em cima desse componente que mostrara o editor abaixo: Figura 90 – Formulário do componente ADOConnection. Ao abrir procure o botão Build  Clique no botão Build para ir direto ao editor de strings de conexão da Microsoft.  Coloque um componente ADOConection no form.7 .mdb Abra o Delphi  Clique na paleta ADO. Figura 89 – Formulário para teste de conexão ADO.190 14. .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.

 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. Figura 92 – Informação de teste de conexão.OLEDB.4.Jet.191 Figura 91 – Propriedades de vinculação de dados.0.  Clique em OK  E OK novamente A string de conexão será mostrada no campo Use connection string : Provider=Microsoft. Data Source=C:\Arquivos de programas\Arquivos comuns\Borland Shared\Data\dbdemos. Persist Security Info=False .mdb.mdb  Clique em Testar conexão.

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

testes e compilação.O componente TDCOMConnection Quando usar DCOM para comunicar com o servidor de aplicação. inclua no cliente de aplicação o componente TDCOMConnection para conexão com o servidor de aplicação. 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 .193 14. 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.8 .. 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. Se você não fornecer o registro do sistema para o servidor de aplicação no cliente quando estiver usando DCOM. podemos usar a propriedade ObjectBroker instalada para especificar um valor para o nome do computador ( ComputerName). Este deve ser especificado para ser útil durante o desenvolvimento. . o componente DCOM connection criará um exception na tentativa de abrir uma conexão. podemos especificar o nome do computador para ordenar esta entrada. O componente TDCOMConnection usa a propriedade ComputerName para identificar a máquina que está o servidor. Quando a propriedade ComputerName estiver em branco. você deve indicar o ComputerName.

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

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

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

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

Se quiser parar é só clicar de novo e mandar desativar e ninguém mais acessa. desligue o servidor. Cada vez que for compilar. porque na hora que for substituir algum dado. faça a compilação e depois ligue novamente.198 Figura 96 – Tela de visualização de serviços de componentes. deve parar o servidor. . 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. pode dar erro. Figura 97 – Aplicativos COM+ em serviços de componentes. Se for compilar. 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.

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

 Da paleta DataAccess – coloque um DataSourse Propriedades: name: DS_Ativ. A partir de agora esta tabela já existe. 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. Foram criados os campos como se fosse em uma tabela comum. DataSet: Tbl_Teste .200 Figura 98 – Editor de propriedades Digite os campos do quadro abaixo. 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. Criando o DataSet na memória  Clique com o botão direito do mouse no componente e depois no campo CreateDataSet.

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

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

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

Computa o valor average para um campo numérico ou date-time ou expressão. . Observe que se for alterado algum valor o campo total também será modificado.204 Figura 102 – Formulário com o campo Total. 15.6 . Use count(*) para contar o numero de registros em um dataset ou subgroup. especifica o número de valores (campos preenchidos) para um campo ou expressão. 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. 15.Propriedades de Expression (TAggregateField) Especifica a fórmula usada para calcular o valor agregado. Sintaxe no Delphi: Tipo da propriedade Expression: string. 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.1 .6.

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

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

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

begin Tbl_Ativ.208 O Funcionamento  Execute o programa colocando alguns dados (campos) para testar. Em resumo: É possível exportar para qualquer lugar.<DATAPACKET Version="2. end. Pode ser aplicado um filtro em ordem crescente ou decrescente ou outro modo qualquer. Verifique o formato de como este arquivo ficou. .<FIELDS> <FIELD attrname="Cod" fieldtype="i4" /> <FIELD attrname="Nome" fieldtype="string" WIDTH="30" /> <FIELD attrname="Qtde" fieldtype="i4" /> <FIELD attrname="Data" fieldtype="date" /> <FIELD attrname="Valor" fieldtype="r8" /> </FIELDS> <PARAMS CHANGE_LOG="1 0 4 2 0 4 3 0 4" /> </METADATA> .<ROWDATA> <ROW RowState="4" Cod="1" Nome="Nome um" Qtde="1" Data="20060601" Valor="10" /> <ROW RowState="4" Cod="2" Nome="Nome dois" Qtde="2" Data="20060602" Valor="20" /> <ROW RowState="4" Cod="3" Nome="Nome tres" Qtde="3" Data="20060603" Valor="30" /> </ROWDATA> </DATAPACKET> Através do Ecxel é possível importar esses dados.<METADATA> .0" standalone="yes" ?> . os campos e os valores para cada campo.ApplyUpdates(0).  Exporte os dados clicando no botão salvar.Tbl_AtivAfterPost(DataSet: TDataSet). A exportação se não for definida será em binário e só o Delphi consegue abrir. Para carregar esse arquivo. conforme mostrado abaixo: <?xml version="1. O arquivo de exportação em formato XML forão gerados.0"> .  Clique no componente (table) e no evento AfterPost coloque a seguinte linha de programação: procedure TForm1.

não se perdem mais.Uma regra de negócio num programa Tudo o que foi feito é para você habituar ao poder do componente ClienteDataSet. Carrega o arquivo faz um comando ApplyUpDate e salva automaticamente no banco de dados.o que estiver na tabela e não estiver no banco já é exportado na hora.  Da paleta DataAccess coloque os componentes: dois ClienteDataSet e dois ClienteDataSourse. compile e execute o programa Agora se clicar em salvar. os dados já estarão lá. a partir de agora.209 Cada vez que for ativado e em vez de salvar será carregado de um arquivo. Do lado do servidor. Do jeito que está e quando for carregado o arquivo.  Salve.  Da paleta DataAccess coloque o componente DataSetProvider – o componente que vai gerar a DLL. Exemplo: Seu amigo mandou um arquivo e você quer salvar num banco de dados.8 . para salvar no banco de dados basta colocar o nome da tabela a ser salva e fazer o comando ApplyUpDate . Na empresa que foi exportado os dados para poder carregar. você executa o comando para carregar na memória e logo em seguida executa o comando ApplyUpDate para salvar no banco de dados. Para exportar faça um comando SQL – se for feito Select * from <tabela> no banco de dados também funciona.  Da paleta DBExpress coloque o componente SQLDataSet e SQLConnection . mesmo que abrir a próxima vez. 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.  Abra um novo projeto no Delphi. 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. 15. Do lado do cliente.

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

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

Os dados devem ser mostrados nos dois clientes e cada vez que salvar em um cliente.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. se tiver dez registros. O formulário ficará com o aspecto mostrado abaixo: Figura 106 – Aspecto do formulário com duas grids representando dois clientes.5 . logo após será salvo no outro. 15.212 OBS: O item 16. para gravar no servidor.A programação Cada vez que os dados forem salvos. o PropagateChanges e o IncFieldProps. No caso da importação de dados.  Coloque uma grid para cada cliente – só para mostrar os dados – cada uma ligada a um DataSourse.  Para cada cliente coloque um DBNavigator ligados ao DataSourse. será salvo no servidor.6. Do lado do cliente programe componenteClientDataSet(ClienteUm): clicando no evento AfterPost do . depois de importar. comandar ApplyUpDate neste exemplo.8.3. 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. cada vez que salvar.1.

O primeiro foi salvo executando o comando ApplyUpDate e o segundo também executou o mesmo comando.ApplyUpdates(0). conforme abaixo: . salva os dados no Servidor que por enquanto ainda não recebeu nenhuma programação. Quando clicar em salvar.Refresh. begin ClienteDois. 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. end. ClienteUm.213 procedure TForm1.Refresh.ClienteUmAfterPost(DataSet: TDataSet). O outro cliente também tem o código 17 para salvar com a descrição ZZZZ. Figura 107 – Formulário com dois clientes em execução. Não tem nenhuma regra programada. end. 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.ClienteDoisAfterPost(DataSet: TDataSet). com a descrição AAAA. Faça o mesmo procedimento para o componente ClientDataSet2(ClienteDois): procedure TForm1.ApplyUpdates(0). begin ClienteUm. ClienteDois.

Para programar pode ser colocado a condição (if. Isso tem que ser controlado programando uma Trigger no servidor. Suponha que só é possível colocar códigos maior que zero. . Ex: Que o valor esteja entre 1 e 50. ..Agora é possível digitar valores no campo ID somente na faixa de 1 a 50. . É necessário que todas as vezes funcione para todo mundo.. Foi campo(CustomConstraints) e foi programada com a restrição acima... 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). Esta restrição está sendo programada no servidor. pode ser colocada a mensagem: “Digite um valor entre 1 e 50” no campo ConstraintErrorMessage. escolhido um Se for digitado um valor errado (fora da faixa). Tudo que for geral é programado no lado do servidor e automaticamente já transfere para todos os clientes.214 Figura 108 – Mensagem de erro mostrando violação de chave.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”).  Selecione o campo ID Na propriedade CustomConstraints – pode ser criada restrições igual ao banco de dados.

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

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

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.1.  Faça todos os paços já descritos anteriormente para alterar a programação > Salve e execute o programa para testar. que na verdade não é um erro. Aparece um erro de exception (um try automático. A programação do cliente se restringe em Refresh e ApplyUpDate.8. pode cancelar. mas se quiser. é 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. 15.8 .217 Figura 113 – Propriedade de mensagem de erro. Figura 114 – Mensagem de erro.DataSetProvider (data access) Constraints -> se as regras de contrantes serão passadas para o clientes DataSet -> a tabela a ser usada .1.Propriedades dos componentes DataSetProvider (data access) e ClientDataSet (data access) 15.8. Digite um campo e deixe em branco a descrição e salve.7 . OBS: Ao executar o programa note que um erro aparece porque o Delphi está aberto.

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

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

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

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

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

 Clique em ―Requires a New Transaction‖.  Clique em OK. Figura 117 – Tela de dialogo do DataModuloRemoto.  Tipo de modelo de Thead: ―Theading Model – teremos os campos Single. Apartment e Both. No caso vamos colocar Both (ambos). – Tanto Single. . Apartment ou Both vai poder suportar. 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.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.

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

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

para cada vez que precisar de efetuar alguma ligação. portanto daremos um nome de programação para ele. agora será DataSetProvider e Tabela. Propriedades do DataSetProvider: Name = DSP_Ativ. É ele que vai fornecer os recursos. todas as tabelas estarão no servidor.  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.SQLConnection = conexão . é ele que compartilha os serviços. .CommandType = table . Vai ser a tabela. O DataSetProvider é o fornecedor de recursos.2 . Em três camadas. componente DataSetProvider.  Adicione o componente DataSetProvider da paleta DataAccess.9.226 Procure o banco de dados para efetuar a conexão. 15.Name = Tbl_Ativ .Fornecedor de recursos O fornecedor de recursos está na paleta DataAccess. todos irão se conectar primeiro no componente DataSetProvider. Preencher as propriedades do SQLDataSet2 > . Da mesma forma que funcionava a dupla DataSourse e Tabela. esta tabela será a ligação. O DataSetProvider será ligado a uma 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. Quando o(s) cliente(s) for(em) conectado(s) no servidor.Active = true.Command text = (TAB_ATIVIDADES) .  Selecione o componente DSP_Ativ e ligue a propriedade DataSet com a tabela (Tbl_Ativ) que antes não tinha. 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.

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

o Data Modulo e foi criado também o arquivo P_Serv_TLB.228 Figura 120 – Tela de Units. Selecione o arquivo que foi criado e pressione F12. A tela gerada é a mostrada abaixo: Figura 121 – Programação gerada do P_Serv_Tbl. O que mostra é uma tela de configuração. mas só conhece números. Internamente não trabalha com servidor de aplicação. Cada servidor gera automaticamente um número único que não pode ser apagado ou modificado. Antes criava só o provedor que foi salvo . 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. . gera um número para trabalhar. tudo internamente é tratado com um número.

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

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

 Após criar clique em OK e OK novamente. Após executado os passos anteriores. Figura 125 – Informação de sucesso de registro do ActiveX.  Clique em RUN > Register ActiveX Server Note que após executado o registro é criada uma DLL. Figura 126 – Servidor de Aplicação criado no Serviços de componente. verifique no Arquivo de ferramentas Administrativas. serviço de componentes a criação do Servidor de Aplicação.  Iniciar > painel de controle > ferramentas administrativas > serviços de componentes > computadores > meu computador > aplicativos COM+.  Clique em OK. Agora vamos colocar tudo dentro do Servidor de aplicação.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. .

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

 Clique em OK.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. Figura 137 – Informações de instalação do pacote ACBr . Clique em "Compile" e em seguida em "Install". Feche o arquivo DPK necessidade de salvar). O quadro abaixo informa que a compilação foi bem sucedida.

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

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

O que temos que verificar nele? Figura 141 – Campo genérico do formulário demo BalancaTeste.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 nome de programação que estamos trabalhando que no caso é o próprio nome. 16. Se no mesmo estabelecimento tem que ter a balança e a impressora fiscal. Esta sendo enviada dados de um lado para outro. Figura 142 – Propriedades do componente ACBrBAL – o Device Por último o modelo da balança que vai trabalhar. Temos uma máquina 1 e maquina 2.258 Essa parte que ele colocou aqui é só para ter a opção de trocar – o exemplo pode ser genérico. Selecionando o componente.2. O intervalo mostrado é o tempo (o número 200 dá aproximadamente 2 segundos) para que a balança lê a cada 2 segundos. Se Filizola ou Toledo. para servi em qualquer um.Baud Rate Como funciona uma porta serial. enviado por 1 e . com um cabo ligado entre as duas. 16.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). Se a balança não responder dentro de 2 segundos. uma é teste e a outra um outro tipo. em propriedades. 8 bits (Data). não modifica nada.1 . teremos que ter duas portas seriais. sem paridade – none (Parity).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.2.2. uma para a balança e a outra para a impressora. temos que selecionar a porta. bits de parara = 1 (Stop)). é mostrada uma mensagem de erro no campo Mensagem. No caso foi deixado como nenhum para ser genérico. OBS: Se for usado o emulador essa configuração terá que ser mudada para 4800 em Baud.

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

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

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

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

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

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

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

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

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

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

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

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

na caixa Project Type clique no ícone Project Wizard e depois em Create Figura 150 .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). .271 Figura 149 .Criando um novo projeto.

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.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.  Clique em avançar. . A verão Full é mais completa.

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

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

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

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

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

279 Figura 158 – Arquivos Instalados. Digite o nome do sistema para a pasta e aperte Enter. 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.

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

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

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

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

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

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

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

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

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

Sign up to vote on this title
UsefulNot useful