Desenvolvimento de Aplicações com Lazarus
Desenvolvimento de Aplicações com Lazarus
LAZARUS
1 – INTRODUÇÃO
Diferente da primeira apostila do Lazarus, embora tenha sido trabalhado com progra-
mação orientada a objeto, e que o objetivo da disciplina era familiarizá-lo com o ambiente
Lazarus, trabalhando com eventos, mostrando o que são eventos, propriedades, tratamento de
erros, banco de dados, criando um cadastro, manipulando imagens, etc... O objetivo da segun-
da apostila de Lazarus (Lazarus II) é o Desenvolvimento de Aplicações, criando um aplicativo
comercial que funcione. Então o que orienta essa disciplina?
A maioria das pessoas que estão fazendo o curso serão programadores. Essa disciplina
é a base para o desenvolvimento para montar um Sistema Comercial. O tipo de sistema que
permita fazer pedidos, fazer baixa em estoques, fazer créditos, fazer débitos, gerar relatórios
comerciais, tudo automaticamente pelo computador.
2 – BANCO DE DADOS
2.1– Introdução
Neste curso será relembrado como criar as tabelas no Interbase6, que serão acessadas
através da aplicação LCL Forms. Será utilizado o Interbase6 como sistema de gerenciamento
pelo fato dele acompanhar o pacote de instalação do Delphi. Em nosso caso o InterBase não
vem incluso ao Lazarus, sendo assim será necessário fazer o download ou adquirir através do
CD incluso na apostila.
Porque usar o Interbase e não usar outra ferramenta qualquer? O Custo dos Bancos de
Dados como o Axis e o Oracle são muito elevados, e neste caso será utilizado um sistema
gatuito.
Um exemplo de sistema gratuito é o Firebird que é uma cópia do Interbase e pode ser
usado em múltiplas máquinas e não se paga nada por isso, outro sistema é o Interbase que já
vem incorporado no Delphi ou mesmo baixando apenas o aplicativo Interbase.
Se você sabe trabalhar com o Interbase, sabe também trabalhar com o Oracle e outros
bancos de dados. Nesse curso vai ser mostrado como colocar qualquer outro Banco de Dados.
Paradox
Axis
SQL
Interbase
Firebird
Oracle
DBII
SQLServer
3
O Interbase tem que estar instalado e rodando no sistema e, para saber se ele está ins-
talado verifique:
O Interbase trabalha com um único arquivo e dentro desse arquivo estão às tabelas a-
cessando um único arquivo pelo DOS. Se for verificado pelo Windows e olhar a pasta dados,
você verá um único arquivo e dentro dele são armazenados os dados criados. É um gerencia-
dor de Banco de Dados da mesma forma que o Oracle e o SQL. Cria uma única área e cons-
trói tudo lá dentro.
Dentro desse arquivo estarão as tabelas e se existir alguma trigger, ou alguma outra
programação, também estará armazenada neste arquivo, assim como os dados, permissões e
restrições vão estar dentro de um único arquivo.
Na area Server Information deixe selecionada a opção Local Server e na área Login
Information, nos campos coloque:
UserName: SYSDBA
Password: masterkey
2.5 – DataBase
O DataBase não é a tabela mas sim o espaço onde tudo será gravado. O espaço onde
será guardada a tabela, o usuário, a programação, os dados. Então tem que criar esse espaço,
que por enquanto não existe ainda, e geralmente esse arquivo contem 500 Kbytes.
Clique com o botão direito no mouse em cima de DataBases e escolha a opção Create
Database...
6
2.6 - O Alias
É o que vai aparecer no IBConsole quando clicar no DataBase. Vai aparecer vários
bancos porque o InterBase não precisa estar restrito a um único Banco de Dados, mas pode
gerenciar vários bancos. Poderia mais tarde colocar uma CPU em outro local com o Banco de
Dados de sistema de Vendas, outro banco com sistema de Impostos, um outro com sistema
7
de contabilidade fiscal, isto é, vários bancos de dados instalados numa única máquina em ou-
tro local e acessar remotamente.
O nome que ira colocar no banco de dados é o mesmo que vai aparecer no arquivo.
Tem que ser um nome Único, não pode existir dois arquivos com o mesmo Alias, não é um
arquivo físico, mas sim um nome lógico, é o nome que vai aparecer na Listagem.
O espaço Físico tem que indicar o local que será criado o Banco de Dados. Tem que
ser digitado o nome do Arquivo no campo FileName(s) na caixa de diálogos
No campo FileName(s), no primeiro quadrado coloque o caminho para onde vai ser
salvo e o nome do banco com sua extensão, por exemplo: C:\Vendas\Dados\Vendas.gdb.
O nome para o banco no exemplo é \Vendas.gdb ou colocar qualquer outro nome, co-
mo por exemplo BASEDADOS. Ficando da seguinte maneira:
Foi criado o Banco Vendas e também uma pasta chamada Table onde foram criadas as
tabelas.
Fisicamente o HD é como se fosse um CD com uma cabeça de leitura que faz o traba-
lho de busca, chamado de tempo de acesso, quanto menor esse tempo melhor o desempenho
do micro.
No caso de uma Table no Paradox, como não há reserva de espaço, os arquivos são
praticamente colocados em diversos pontos do HD. Na desfragmentação, os arquivos do
mesmo tipo são juntados. Tudo que era por exemplo Clientes, é colocado um próximo do ou-
tro. Os arquivos do Word podem ser colocados próximos, mas em um outro campo do HD. O
sistema não sabe que os tipos de arquivos fazem parte do arquivo de um Banco de Dados.
Um arquivo cliente pode estar no começo do HD e o arquivo fornecedor pode estar no final.
Quando o sistema precisar fazer uma consulta em SQL, primeiramente faz uma leitura, depois
faz a busca, vai para outro ponto no HD, para continuar. Mesmo fazendo a desfragmentação,
ele junta tudo que era cliente num campo e tudo que era fornecedor em outro lugar, mas não
juntou a pasta dados num único espaço.
Com as configurações prontas, basta clicar no botão SQL no menu rápido ou atraves
do menu TOOL > INTERACTIVE SQL.
);
Se o código sumir, significa que a programação esta certa, caso contrário aparecerá
uma mensagem de que não pode ser executado, e na onde esta o erro, corrija e execute nova-
mente.
Na estrutura do DataBase, de um duplo clique na tabela de clientes, para que possa ver
os campos criados na tabela:
Figura 12 – Tb_clientes
Ao fazer isso, o Interbase retorna uma janela na qual disponibiliza ao usuário escolher
uma das tabelas salva no banco, e navegar nas abas de Properties, Metadata, Permissions,
Data, Dependencies.
Também foi criado uma tabela simples de clientes com os campos código, nome
cidade e UF, sendo colocado poucos dados porque a idéia e que você faça depois de acordo
com o projeto escolhido para testes.
16
Será apresentada duas tecnologias para a conexão com o banco. A paleta SQLdb e a
paleta Zeos Access
Essa paleta é responsável para acessar bancos de dados no Lazarus. Com essa paleta
pode-se conectar ao PostgreSQL, Oracle, MySQL, Firebird ou Interbase, SQLite e ODBC.
Para cada um desses existe um componente TXXXConnection. Para conectar ao Interbase, por
exemplo, existe o componente TIBConnection. Para executar as operações sobre tabelas existe
o componente TSQLQuery e o TSQLTransaction.
TSQLQuery Usada para executar comandos SQL no servidor. Os dados podem ser
obtidos atribuindo-se à propriedade SQL algum comando SELECT e
chamando o método Open. Também é possível manipular os dados
executando-se comandos INSERT, DELETE ou UPDATE. No último
caso, não deve ser usado o método Open, mas sim o método
ExecSQL.
TSQLTransaction A SQLTransaction é necessária por motivos internos de
gerenciamento (corresponde ao conceito de transação em banco de
dados). A SQLTransaction é automaticamente ativada quando um
banco de dados é aberto através dela. Para fechar a SQLConnection,
no entanto, certifique-se de que a SQLTransaction não está ativa.
TXXXConnection Responsável pela conexão entre o Projeto e o arquivo físico que esta
no HD. É usada para armazenar parâmetros de conexão ao servidor de
banco de dados. Os componentes são:
TIBConnection (Conectar ao Interbase e Firebird)
TODBCConnection (Conectar ao bando MsAcess)
TOracleConnection (Conectar ao banco Oracle)
TMySQL50Connection(Conectar ao banco MySql)
sação que está editando os dados pode ter acesso aos mesmos. Isto
também previne, num ambiente multi-usuário, que outro usuário te-
nha acesso aos dados que estão sendo editados. Como este TIL é
muito restritivo no que se refere ao acesso dr dados que estão sendo
editados, deve ser aplicado comcautela.
tiNone Nenhum TIL é usado para isolar a transação
tiReadUncommitted O TIL tiReadUncommitted não é suportado pelo Firebird. Se este
TIL for usado, um erro será disparado e a transação não será isolada
(de uso semelhante ao TIL tiNone).
TZQuery É recomendado o uso do TZQuery no modo RequestLive associado
com o componente TZUpdateSQL. Se um conjunto de dados for atua-
lizado, então RequestLive deve ser setado como True e usado com o
componente TZUpdateSQL, a fim de se usar os comandos SQL de
ação (update, insert, delete). Para retornar um conjunto de dados de-
ve-se chamar o método Open. Caso queira executar uma Query de
ação (que não retorna um recordset) chame o método ExecSQL, para
os comandos update, delete, insert.
TZTable O componente TZTable deve ser utilizado apenas em aplicações cli-
ente-servidor que manipulam pequenas tabelas, uma vez que todos
os registros da tabela serão transferidos para a memória da máquina
cliente. É equivalente ao comando SQL “SELECT * FROM
TB_CLIENTES”.
TZStoredProc O componente TZStoredProc fornece a possibilidade de executar um
procedimento armazenado (stored procedure) de um banco de dados.
Existem dois tipos de procedimentos armazenados. O que retorna um
conjunto de dados e o outro que não retorna. Não é necessário cha-
mar o método Prepare antes de executar o método ExecProc.
TZReadOnlyQuery Este componente é similar ao TZQuery, porém com a diferença de
que recordset retornado é somente leitura. Conseqüentemente não é
possível o uso associado do TZUpdateSQL.
TZUpdateSQL O TZUpdateSQL fornece comandos SQL de atualização (update,
insert, delete) para um conjunto de dados, recuperados por um TZ-
Query.
ZQuery1.Sql:
UpdateSQL1.InsertSql:
UpdateSQL1.ModifySql:
UPDATE Tb_clientes
SET nome_cli = :nome_cli
WHERE cod_cli = :cod_cli
UpdateSQL1.DeleteSql:
Protocol (Protocolo) Esta propriedade define qual o banco de dados a ser acessado.
4 – INICIANDO A CONEXÃO
http://www.jpsoft.com.br/downloads/ZEOSDBO-6.6.5-stable.zip
Clique no botão Compilar e aguarde até que a compilação seja feita, logo em seguida
clique no botão Instalar, ira aparecer à seguinte mensagem:
.
24
É criada uma pasta raiz em um local adequado com o nome de Vendas e dentro desta
pasta crie quatro pastas com os nomes: formularios, imagens, relatorios, dados.
Abra o Lazarus crie um novo PROJETO(caso não esteja ) e salve a unit dentro da pas-
ta formulários com o nome u_principal, e o projeto com o nome de p_vendas dentro da pasta
raiz (pasta Vendas).
Name Caption
Frm_principal Vendas
Adicione o componente TZConnection que esta dentro da paleta Zeos Access no for-
mulário principal e mude suas propriedades para:
A conexão foi criada, falta agora criar outro formulário para adicionar o componente
ZTable
Name Caption
Frm_cadcli Cadastro de Clien-
tes
implemation
uses u_cadcli;
Name DataSet
DS_Cli Tbl_cadcli
Adicione também Label e DBEdits para cada campo da tabela(cod_cli, nome_cli, en-
der_cli, cidade_cli, UF_cli) e mude as propriedades do componente DBEdit para:
DataSourse DataField
DS_Cli <Nome do campo>
DataSourse
DS_Cli
Tbl_cadcli.open;
26
Frm_cadprod.showmodal;
Name Caption
Frm_cadprod Cadastro de Produtos
implemation
uses u_cadcli, u_cadprod;
Name DataSet
DS_Prod Tbl_cadprod
DataSourse DataField
DS_Prod <Nome do campo>
DataSourse
DS_Prod
Tbl_cadprod.open;
Frm_cadprod.showmodal;
6 – Canais
Programar todos os botões na unha usando comandos na programação SQL. Para cada
um dos botões teria que ser programado o SQL.
Name
Up_prod
UpdateObject
Up_prod
UpdateObject: Quando for preciso fazer uma atualização, incluir um novo elemento
ou salvar, o UPDateObject vai gerar o SQL automaticamente.
Clicando na aba SQL, é verificado os tipos de SQL (Modify, Insert e Delet) se estão
todos em branco, como mostra um dos tipos abaixo, então como fazer para programá-los?
Clique na aba Options e logo em seguida na área KEY FIELD selecione o campo
COD_PROD e na área UPDATE FIELD selecione todos os campos e clique no botão Gene-
rate SQL.
Execute o programa e chame a tela. Observe que o botão insert (+) está ativo, então o
sistema poderá inserir e salvar quando executado essa função.
É criada uma pasta raiz em um local adequado com o nome de Vendas2 e dentro desta
pasta crie quatro pastas com os nomes: formularios, imagens, relatorios, dados.
Abra o Lazarus crie um novo PROJETO(caso não esteja ) e salve a unit dentro da pas-
ta formulários com o nome u_principal, e o projeto com o nome de p_vendas dentro da pasta
raiz (pasta Vendas2).
Name Caption
Frm_principal Vendas 2.0
Adicione o componente TZConnection que esta dentro da paleta Zeos Access no for-
mulário principal e mude suas propriedades para:
Name Caption
Frm_cadcli Cadastro de Clien-
tes
implemation
uses u_cadcli, u_cadprod;
Adicione também o componente DataSource que esta na aba Data Access com as se-
guinte propriedades:
Name DataSet
DS_Cli Tbl_cadcli
DataSourse DataField
DS_Cli <Nome do campo>
DataSourse
DS_Cli
Tbl_cadcli.open;
Frm_cadcli.showmodal;
Entre o formulário e o Banco de Dados, quando se utiliza o TZQuery, ele cria uma
cópia do banco e guarda no Cash. Quando está digitando os dados, na verdade, não esta
guardando no banco de dados, mas sim guardando no Cash. Quando clicar em Post, os dados
digitados são salvos no Cash. Isso é executado para diminuir o trafego de dados na rede.
Se fosse uma rotina muito grande dentro do banco de dados, poderia ficar
manipulando os dados. Quando a resposta estiver pronta, pode guardá-la no servidor, porque
por enquanto não foi feita a transação. Na hora que começa a fazer a leitura, inicia a
transação, mas não finaliza. Se você fechar do jeito que está à transação não tendo sido
confirmada, volta tudo como estava antes, então perdeu tudo.
Figura 32 – AfterApplyUPDate
CachedUpdates
TRUE
Agora acesse o guia Events e de um duplo clique no evento AfterPost para abrir o seu
modulo de programação.
Para trabalhar com essa transação coloque um comando Try , após comandar o
ApplyUpdates, se tudo der certo, salva. Se der Exeption, coloque uma mensagem para o
usuário.
sistema ou no próprio computador antes de efetuar o UPData, acaba perdendo tudo, porque
não foi feito o evento After Post o comando ApplyUpData.
Se existem duas máquinas, cada uma com seu Cash, se nessas duas máquinas forem
ao mesmo tempo cadastrados dois clientes com o mesmo número. O primeiro que salvar com
o AfterPost, conseguirá êxito, o segundo dará erro, porque já existe o código, então terá que
efetuar o tratamento com o comando Try...Exeption, para dizer que já existe o código.
Se for feito um tratamento pelo Lazarus, não tem como o sistema saber quantas
máquinas acessa o bando de dados. O Ideal é fazer o tratamento no local que for salvar. Cada
vez que for salvar, gera uma chave. Essa programação (generation) é feita no banco de
dados.
Trabalhando com tabelas do tipo mostrado abaixo, ligada uma com a outra, delas
nascendo um relacionamento N para N – uma tabela intermediaria. Por exemplo: um cliente
pode fazer N pedidos. Um pedido pode ter vários produtos e um produto pode pertencer a
vários pedidos. Nesta tabela N para N nasce uma intermediaria “ITENS”.
1 N N N
CLIENTE PEDIDO TEM PRODUTO
1 N 1 N N 1
CLIENTE PEDIDO ITENS PRODUTO
8.1.1 – DbLookupComboBox
Ligação do tipo consulta. São exemplos os componentes do tipo combo, onde tem
várias opções para escolher, mas não pode cadastrar.
O produto é a mesma coisa, já está previamente cadastrado e você seleciona, faz uma
consulta. Então toda ligação que faz uma escolha vai ser a tabela com um
DbLooKupComboBox.
Para as ligações do tipo Combobox – O Master será quem tem N e o Detail quem tem
o 1.
40
8.1.2 - MasterSource/MasterField
MasterFieds: Essa propriedade é declarada como uma variável do tipo String que
define os campos que farão a ligação entre duas tabelas. Os nomes devem ser separados por
ponto-e-vírgula.
Teoricamente o cliente só pode ser consultado, porque já existe uma tabela especifica
para cadastrar clientes. Ex: O cliente CLEITON é o cliente que aparece para comprar
pequenos itens, quando vai ao supermercado. Pode ser cadastrado como cliente 999- venda ao
consumidor. Mas o cliente que sempre compra, geralmente tem um cadastro já feito e tem seu
próprio código, como o cliente de uma farmácia que paga mensalmente.
Código Nome
1 Cleiton
2 Anderson
Imagine se não houvesse uma modelagem, então como deveríamos guardar esses
dados. Seria necessário guardar todos os dados no pedido. Exemplo:
Se o cliente quiser mais um item, teoricamente teria referência de tudo que for comum.
Esses dados se repetem para cada item colocado, então se deve aplicar a normalização (1FN,
2FN, 3FN). Reparem que essa parte tem uma coisa comum, linhas que se repetem várias
vezes.
Tudo que se repete no banco de dados, exclua e coloque numa tabela separada. Tem
que dividir a tabela em duas partes. Uma que se repete várias vezes e a outra que é diferente
nos seus campos. Divida em duas Tabelas Uma com o nome Pedido e outra com o nome
Itens.
A tabela de pedido vai ter uma única vez os campos: n_pedido, data, nome, rua, etc.
Na outra tabela Itens vai ficar com os seguintes campos: cod_item, descrição, valor,
qtde, total. Exemplo:
PEDIDO ITENS
Numero Data Nome Cliente Endereço Cód.Item Descricao Valor
01 23/08/05 Cleiton Rua Antonio 01 Mouse 15,50
01 23/08/05 Cleiton Rua Antonio 02 WebCam 40,00
Se o banco de dados ficar exatamente assim, se for inserido um outro pedido, esse
outro pedido pode também comprar o caderno. A chave sendo só o código do item ou o
código do caderno daria para descobrir qual pedido ele pertence? Não.
Então tem que fazer uma ligação entre uma tabela e outra. Um pedido pode ter N itens
e um produto podem estar em N itens. A chave migra do lugar que tem 1 para o lugar que tem
N. A chave do pedido vai para itens. Se não for feita essa migração, você não saberá de que
pedido pertence o item.
42
A idéia é não repetir os dados muitas vezes, essa repetição foi substituída pelo código.
Tudo que se repete várias vezes foi separado em outra tabela.
PEDIDO ITENS
Numero Data Nome Cliente Endereço Cód.Item Descricao Valor
01 23/08/05 Cleiton Rua Antonio 01 Mouse 15,50
01 23/08/05 Cleiton Rua Antonio 02 Webcam 40,00
ITENS
Código Pedido Código Itens Descrição Valor Qtde Total
01 01 Mouse 15,50 02 31,00
01 02 Webcam 40,00 03 121,00
Existe informação gravada em outra tabela. Por exemplo: o nome Cleiton. Cada vez
que o Cleiton fizesse um pedido, seria preciso digitar o nome e o endereço do Cleiton. Se
fizesse muitos pedidos, seria preciso armazenar muitas vezes o nome e o endereço, ou pode
digitar uma única vez um código pré-cadastrado quando quiser buscar um campo. Esse código
(do cliente) sai de uma classe e vai para outra classe (a chave estrangeira). No diagrama, a
chave sai da classe que tem 1 e vai para a classe que tem N. A chave do código do cliente sai
da classe cliente e vai para a classe pedido. A chave substitui todos os campos que seriam
preenchidos e que são repetidos.
O item Mouse vem da tabela produto. Se a pessoa digitar o item errado ou pode
vender o item como se fosse outro produto, na verdade não pode permitir que o usuário digite
o nome do produto. A descrição pode ser importada da tabela produto, então não é necessário
um banco de dados, essa descrição pode vir da tabela de produtos, colocando apenas o código.
Exemplo:
Veja o Diagrama. A chave da classe produtos (1) vai para a classe itens (N) – código
do produto vai para a classe itens.
1 N 1 N N 1
CLIENTE PEDIDO ITENS PRODUTO
43
O que está sendo feito? Sendo minimizados os dados que tem na tabela, ao invés de
guardar a descrição repetida vezes, assim podendo acessar dados repetidos através de chaves.
ITENS
Código Pedido Código Produto Qtde Total
01 01 2 15,50
01 02 3 40,00
Todos os campos que são calculados podem ser retirados da tabela. Ex. Num pedido
pode ter o total desse pedido somando todos os itens. Se a chave for Foreign Key ele vai da
tabela que tem 1 para a tabela que tem N.
Na tabela de pedido tem que ser guardado o valor, porque o valor de um item, hoje
pode ser um preço, amanhã pode subir, e se o cliente quiser devolver um produto, o valor da
compra tem que estar armazenado (o valor do dia da venda).
1 N 1 N N 1
CLIENTE PEDIDO ITENS PRODUTO
Detail Master Detail
Na tabela de Pedidos, quem manda é quem tem N, sendo assim o Master vai
continuar sendo pedidos e o Detail vai ser o cliente. Se a ligação for do tipo combobox, quem
manda é quem tem o N, quem tem bastante é o Máster. Quem tem pouco é o Detail – é
mandado.
No caso do campo entre produtos e itens, quem vai mandar é o itens (vai ser o
Master) e o produto vai ser o Detail.
45
9 - CRIANDO AS TABELAS
Tabela de Funcionarios
Tabela de Pedido
A forma normal pede que todo campo calculado deva ser retirado do banco, mas em
uma grande empresa faz-se muitos cálculos para saber, por exemplo, quanto foi vendido do
final do ano, no mês. Na normalização, para cada pedido, abre a tabela e soma todos, um por
um, isso perde muito tempo quando existe muitos relatórios desse tipo. O ideal é colocar o
total no mesmo banco, para não precisar fazer o calculo de novo, isso agiliza a busca em SQL.
Então quando não obedecer a 3FN? Quando precisar otimizar, isto é, de muita
velocidade no banco, faz-se o calculo e deixa gravado no próprio banco.
Se tivesse um cadastro de funcionários. Exemplo: foi feita uma venda e foi cobrado
um preço errado, tem que cobrar de alguém, o código do funcionário que efetuou a venda
estará registrado. Para isso tem que ser criada a tabela de funcionários.
A chave primária é o código do pedido, só ela é NOT NULL, mas se for obrigatório o
código do cliente, então acrescente também NOT NULL nesse código. Quando o código do
cliente for obrigatório, tem que selecionar primeiro o cliente para depois inserir os itens.
Status do Pedido – Se está fazendo uma venda, vai chegar num ponto em que cada vez
que passar por um setor da empresa, essa venda muda de status. Exemplo: Pedido não
concluído, pedido encaminhado para o setor de crédito, pedido aprovado, pedido sem emissão
de nota fiscal, pedido entregue.
Para que é necessário este Status? Para saber a situação atual da sua venda até a
entrega e conclusão definitiva da venda.
Tabela de itens
No IbConsole
Alter table tb_pedido Add foreign key (cod_cli) references tb_clientes (cod_cli);
Alter table tb_itens Add foreign key (cod_ped) references tb_pedido (cod_ped);
Alter table tb_itens Add foreign key (cod_prod) references tb_produto (cod_prod);
Quanto às chaves.
1 - A chave primaria migra da tabela que tem 1 para a tabela que tem N.
Para as ligações do tipo Combobox o Master será quem tem N e o Detail quem tem 1
Quais as ligações?
Entre a tabela de pedido e a tabela do cliente foi criado uma referência entre código do
cliente e código do pedido, porque se a pessoa deletar o pedido não deleta também o cliente.
Exemplo: Se estiver no pedido e deletar esse pedido, quando for consultado o cliente, este
não existirá mais, então o sistema não deixa apagar se tiver alguma referência.
Porque não foi criado os Foreign Key quando foram criadas as tabelas?
Se fizer referências na criação das tabelas, pode haver alguma tabela ainda não criada.
Exemplo: Você criou a tabela de itens, mas ainda não criou a tabela de produtos, se tentar
colocar um Foreign Key, vai dar erro, porque a tabela de produtos ainda não existe.
10.1 – Introdução
Name Caption
Frm_vendas Venda de Produtos
1 N 1 N N 1
CLIENTE PEDIDO ITENS PRODUTO
Detail Master Detail
Combobox Máster Combobox
Máster Detail
50
10.3.1 - A Chave
A chave então vai da classe que tem 1 para a classe que tem N.
Quando a ligação é do tipo Combobox, no lugar que tem 1 é o Detail e onde tem N é o
Master.
Para poder pegar os dados que estão no bando de dados através da TABLE é
necessário declarar no Form principal.
implementation
uses u_cadcli, u_prod, u_func u_vendas;
O pedido tem a própria tabela de pedido, os itens, os produtos e para quem está
vendendo (o cliente), além disso, você pode ter opcionalmente algumas tabelas do tipo:
funcionário, forma de pagamento, porque na venda pode ser escolhido a forma de pagamento,
se é a prazo ou à vista e outras tabelas que podem ser agregadas depois, como: contas a
pagar, a receber, fornecedores, etc.
Insira varias TZTABLE que se encontra na paleta Zeos Access com as seguintes
propriedades:
TABELA CLIENTES
TABELA PRODUTOS
TABELA PEDIDO
TABELA ITENS
TABELA CLIENTES
Name DataSet
DS_cli Tbl_cli
TABELA PRODUTOS
Name DataSet
DS_prod Tbl_prod
TABELA PEDIDO
Name DataSet
DS_ped Tbl_ped
TABELA ITENS
Name DataSet
DS_itens Tbl_itens
Antes, cadastrar alguns dados na tabela pedido do Interbase, só para verificar como
funciona. No interbase na tabela de pedidos – cadastrar dois pedidos para exemplo para o
mesmo cliente. Clicar em Commit para salvar.
O pedido 1 tem um item, o pedido 2 tem dois itens. Salve clicando Commit e volte
para o Lazarus.
O que está acontecendo? A pessoa está mostrando o pedido número um na tela, mas
estão sendo exibidos os itens do pedido um e também do 2.
Neste sistema, se você vai comprar algum produto, quando exibido o pedido na tela,
você consegue ver a lista de compras do ultimo cliente.
O Ideal é quando estiver na tela o pedido 1, seja mostrados os itens somente deste
pedido. Se do pedido 2, somente devem ser mostrados os itens do pedido 2.
Ex: Se for uma compra num supermercado, aparecerá todos os itens comprados por
esse cliente, tudo que estiver registrado.
56
Veja o que acontece agora. Para o pedido numero 1 mostra is itens respectivos, assim
como para o pedido numero 2 mostra os itens do pedido 2.
Tudo que for permitir inclusão na mesma tela você liga através de
MasterSourse/MasterFields. Tudo que for para consultar DBLookupcombobox.
57
A tela de clientes com pedidos é ComboBox. A tabela que você foi quando estava
fazendo o Master-Detail entre as tabelas de pedido e itens, foi no Itens (Detail) e indicou
que o Master é o pedido, isso para ligação Master Detail.
O tipo desta conexão vai inverter-se. Agora você vai no Master para informar quem é
o Detail.
Clique com o botão direito em qualquer parte da janela(Edit Field) e escolha a opção
NEW, aparecerá a caixa de diálogos (New Field) abaixo:
Crie um novo campo na tabela de cliente: Quando a tabela for aberta, como exemplo
aparecerá o nome do cliente. Diferente do Delphi, não é preciso especificar o Name, Type e
Size, pois o Lazarus pega o nome, tipo e tamanho do próprio campo da tabela.
Selecione a opção Lookup na área Fild Type na área Lokup Definition preencha os
campos:
Remova a Primeira Grid e adicione 5 DBEdit que se encontra dentro da paleta Data
Controls, com as seguintes propriedades:
Agora para cada DBEdit adicione os Label(Paleta Standart) que esta no formulario
Campo(DBEdit) Caption
1 Código do Produto
2 Data
3 Código do Funcionario
61
4 Status do Pedido
5 Nome do Cliente
Quando for escolher um pedido, geralmente quer que os demais dados sejam
apresentados, porque pode ter dois clientes com mesmo nome residindo em locais diferentes.
Da tabela de cliente, coloque os demais campos que estão faltando tipo: endereço,
cidade e Unidade Federativa.
E para cada campo adicione um Label que se encontra dentro da paleta Standart:
Campo(DBEdit) Campo
1 Endereço
2 Cidade
3 UF
Ligue todas as tabelas novamente (Active = TRUE) e veja como ficou a tela do
formulário:
Para indicar que os campos da tabela de clientes não estão ativos, coloque outra cor
para destacá-los.
Com a tecla Shift pressionada clique nos campos da tabela de clientes: Endereço,
Cidade e UF.
Color ReadOnly
Escolha a cor TRUE
ReadOnly: Isto quer dizer que os campos estão desabilitados. Mesmo que o usuário
clicar em cima de qualquer destes campos, não vai modificar, é só para consultar.
Quando fizer a busca sem usar o mouse, se digitar o J, por exemplo, mostra o nome
começado com J em ordem alfabética. Se pressionar outra letra inicial, o sistema busca o
nome começado com aquela letra. O sistema já está com busca de Locate ativada por padrão.
Nas propriedades:
Definições:
Foi ligado o Código do Produto com Código do Produto. Um da tabela de Itens e outro
da tabela de Produto. No resultado mostra a descrição: DESC_PROD.
Na execução do sistema, se o cliente não quiser a pilha, clicando uma vez no canto da
descrição, o sistema abre um Lookup e você pode escolher outro produto. Por enquanto foi
colocado um lookup cliente, colocamos os demais campos da tabela cliente que eram
necessários, foi criado lookup da tabela itens, foram colocados os campos na ordem certa
com um lookup nos itens.
Duplo clique na Tabela de Itens > New - para criar o campo total
Name Type
Total Float
68
Clique no botão OK
Events > OnCalcfields > duplo clique para entrar no modo de programação.
69
10.10 - Programação:
Evento OnCalcFields: Ao ter um campo calculado. Toda vez que tiver um campo do
tipo calculado a programação é feita neste evento.
70
Tbl_itens.FieldByName('total').asfloat:=
Tbl_itens.FieldByName('valor_prod').asfloat*
Tbl_itens.FieldByName('qtd_prod').asinteger;
end;
end.
De duplo clique novamente na tabela de Itens para colocar o tipo dos campos Valor e
Total como moeda e duas casas decimais.
O que falta: Programar todos os botões de inclusão e fazer todo o tratamento, porque
quando incluir o número do pedido, o sistema vai ter que gerar este número automaticamente.
Falta o tratamento dos campos. Fazer o tratamento do campo valor do produto para aparecer
automaticamente, quando escolher o produto. Não foi feita a baixa de estoque.
71
O pedido ainda não está trazendo o valor do produto automaticamente, não está
numerando os itens.
Existem duas formas de fazer: através de uma Store Procedure no Banco de Dados
ou através de programação. A melhor é a Store Procedure. Como ainda não foi vista a Store
Procedure, vamos executar a programação no Lazarus.
Para inserir um novo pedido, temos que gerar um código automaticamente. Como
fazer? Quando for clicado no botão inserir novo item, é chamado o evento Insert da tabela.
Só que antes de inserir é necessário efetuar um cálculo.
O Evento Insert
Para implementar é necessário criar uma variável. Crie a variável aux do tipo inteiro.
Criando a variável.
var
frm_vendas: Tfrm_vendas;
implementation
{ Tfrm_vendas }
Programação:
end;
O que está sendo feito: O último valor do código do pedido da Tabela de Pedido é
armazenado dentro da variável aux.
Não só o código do sistema, mas também a data deve ser colocada automaticamente.
A hora do sistema – a única diferença é que não precisa de conversão, porque o tipo dele já é
tipo DataTime.
Programação:
{adicionar a data}
Tbl_ped.FieldByName('data_ped').asdatetime:= now;
end;
A execução do sistema.
Para adicionar um novo item no banco, só é possível inserir um registro se existir uma
chave estrangeira (Foreign Key). Se adicionar os dados e enquanto não for executado um
„Post’, os dados não são salvos porque a programação Aplly UpDates está no evento After
Post. Se não clicar em Post para salvar e mandar inserir um item, vai dar erro.
Se não tem pedido, não dá para incluir um item. Não existindo a chave estrangeira (do
pedido), não da para inserir item nenhum. Então para clicar e inserir um novo item, é
necessário verificar se o pedido já foi salvo, se não, salve primeiro e depois aplique o Inserir.
Programação
TbL_itens.Cancel;
end;
{para incluir um novo item, devemos verificar se já
não existe um item que ainda não foi salvo.
Se existir, devemos salva-lo antes}
if tbl_ped.state in [dsInsert] then
try
tbl_itens.Post;
except
showmessage('verifique os dados do item da venda!');
end;
end;
O comando Try...Exeption – Pode ser que tenha algum campo obrigatório que foi
esquecido de preencher. Se der algum problema na tabela, enviar mensagem para verificar os
dados do Pedido e cancelar a inclusão através do comando TbL_itens.Cancel;, porque se
deixar incluir e der erro é porque algum campo está faltando na tabela de Pedido.
Na tela – Pode ter um botão para incluir um novo item e um botão para cancelar. Nos
Itens – Pode ser permitido digitar os dados, escolher o produto. No Lookup tem a seta para
escolher o produto.
Cada vez que inserir um novo item, é necessário verificar se o item anterior já foi
salvo, se não foi, então salva.
CAMPO FIELDNAME
0 – Title COD_PROD
1 – Title DESC_PROD
2 – Title QTD_PROD
3 - Title VALOR_PROD
4 – Title Total
Programação:
Na tabela de Pedido > OI > Eventos > AfterScroll
end.
Na execução, após clicar com o mouse sobre a descrição do produto para incluir um
novo item, só de passar a seta em cima da descrição, o valor do produto aparece do lado.
Os itens gravados no Pedido, ainda não estão sendo salvos. Para gravar tem que ser
efetuado o comando AplyUpdate.
Programação:
Tbl_Itens. ApplyUpdates;
Se não for colocado ApplyUpDate, o sistema não salva diretamente no banco, fica só
na memória, e na hora que for encerrado o aplicativo os dados se perdem.
Programação:
aux:= Tbl_Ped.fieldbyname('cod_ped').asinteger;
end;
Na execução do programa.
Até agora já foi tratado o total, o valor do produto que tem que aparecer
automaticamente, o código auto-incremental do pedido que gerava o ultimo código + 1, já
preenche automaticamente a data e traz automaticamente os dados do cliente. O que falta?
Substituir o Navigator por botões
Retirar o Navigator
80
begin
{deve chamar o evento de inserir pedido}
Tbl_Ped.Insert;
end;
A melhor maneira seria alterar o status do pedido para cancelado, para empresa
estimar o numero de pedidos cancelados.
A programação ficaria – Tbl_Ped.Edit; - Porque Edit? Você vai alterar o valor do
campo, se a tabela não estiver em modo de edição, vai dar erro. Aqui nós temos um campo
que armazena o Status. Procure o campo Status_Ped que é do tipo inteiro para fazer o
restante da programação.
Porem neste caso, será apenas deletado o pedido e seus respectivos itens.
procedure TFrm_Venda.Btn_CancelaPedidoClick(Sender: TObject);
begin
{Deletando o pedido junto aos seus itens
Posiciona a tabela no primeiro item
Enquanto a tabela não está no ultimo arquivo
Apaga o registro da tabela de item
Apaga o registro da tabela de pedido}
tbl_itens.First;
While not (tbl_itens.Eof) do
Tbl_itens.delete;
Tbl_pedido.delete;
end;
Até neste ponto terminou na verdade o pedido. A única coisa que ainda não ficou
pronto é o total que será feita depois. Conseguimos Inserir, Excluir. Na hora que busca o
produto, já aparece o valor, já calcula o total parcial. Se clicar para inserir um novo pedido, o
sistema verifica se ainda não salvou e salva para abrir um novo. Se digitar dado invalido, com
o Try...Except, o sistema avisa para digitar novamente. Está tudo filtrado.
Falta imprimir nota e gerar contas a receber. No Interbase ainda não tem a base de
notas e contas a receber.
Salve o Programa.
As parcelas:
Imagine que o cliente escolha pagar em 3 vezes do tipo 30, 60 e 90 dias ou 60, 90 e
120 dias. As duas formas. A primeira forma com numero de 3 parcelas. Para calcular a data
da primeira parcela, a partir do dia de hoje a primeira data é somada mais trinta dias. A
segunda data soma sessenta dias a partir de hoje. Isso é um intervalo entre as parcelas. Entre
uma parcela e outra são trinta dias. Em cima disso tem os juros. Quanto de juros vai calcular
(a taxa de juros multiplicado pelo total e dividindo depois pelo numero de parcelas). Então o
que é necessário armazenar? Não é a data. A data da primeira parcela é o numero para guardar
a referencia. O intervalo é uma data que gravamos para saber o quanto vai colocar a mais em
cada uma das parcelas, e por último os juros.
Tem que fazer mais duas tabelas uma de Nota Fiscal e outra de Itens de Nota Fiscal.
O pedido não é nota. O pedido pode ser cancelado. Nota fiscal paga imposto e para cancelar
tem que ter a nota original.
CFOP – código fiscal de operação - toda operação fiscal tem um código (código de
entrada, código de transferência, etc.). Código que a receita cria, para fiscalização. Por
exemplo: se quiser transferir um estoque para outro lugar, tem-se que gerar uma nota de
transferência.
Existem mais campos na nota, quem vai transportar, a placa do carro que vai
transportar, a pessoa responsável pelo transporte, só que tem que gerar mais tabelas. Para o
exemplo é suficiente.
Quando usar uma impressora fiscal, temos que colocar um campo item, e na tabela de
produtos e tabela de nota fiscal, teremos que guardar o numero de serie da impressora fiscal e
o numero de nota, porque para cada impressora tem um numero de nota. É lacrado pela
receita inserindo o numero da nota. A chave quando se usa mais de uma impressora fiscal
é numero da nota mais o numero de série da impressora.
Como nosso exemplo só tem uma impressora então não usaremos o numero de serie
da impressora.
Temos a tabela de Nota Fiscal, mas esta faltando Gerar Contas a Receber, que no
momento não será criada, porque a prioridade é fazer a Nota Fiscal.
Foi feita a parte de salvar o Pedido e salvar Itens. Falta gerar a Nota, depois gerar
Contas a receber.
Pegamos todos os dados da tabela de pedido e copiamos esses dados numa Nota
Fiscal. Para isso é preciso ter os componentes SimpleDataSet (as Tbls Form_Pag, ItensNota e
Nota).
Name DataSet
DS_nota Tbl_nota
DS_ItensNota Tbl_itens_nota
DS_form_pag Tbl_form_pag
87
tbl_nota.open;
tbl_itens_nota.open;
tbl_form_pag.open;
end;
Fazendo com que as tabelas sejam carregadas quando o formulário for chamado.
Ligar a tabela de Nota com a Tabela Itens da Nota. Da mesma forma que pedidos foi
ligado com itens do pedido, faremos aqui a mesma ligação Master/Detail.
88
A Nota também tem os Itens da Nota, é como se fosse um pedido. A tabela Nota é a
Máster.
Essa ligação é feita através da Tabela de Pedido para adicionar o LookUp...da Tabela
de Forma de Pagamento.
89
De duplo clique na Tabela de Pedidos depois clique com o botão direito do mouse e
escolha a opção New. Na janela que surgi escolha a opção lookup e de as seguintes
propriedades:
Clique em Ok.
- Agora temos que transportar os dados do pedido e copiar para a Nota e do itens da
Nota.
12.4 – Programação
var
auxnota: integer;
Comentario
{inicia o processo para gerar a nota.
Basicamente, temos que copiar os dados da tabela de pedido e gravar na nota.
Algoritmo:
Posicionar no ultimo item da nota gravar o numero em um aux cria um novo re-
gistro para a nota gravar os dados gravar os items (atraves de um laco semelhante a
baixa)}
Imagine como ficaria um banco com cem mil registros. Toda vês que for inserir um
novo pedido, o algoritmo indicaria que tem que posicionar no último número para depois
incluir o próximo. Então, toda vez seria percorrida toda a tabela para inserir um novo pedido.
Por enquanto esta sendo usando o algoritmo por facilidade, mas ira ser criado uma
tabela de configuração, uma tabela que indicará os últimos números usados. Cada vez que
precisarmos de um número, iremos pesquisar nessa tabela para saber qual foi o último número
criado e indicar o próximo. O comentário acima é para esse propósito.
Criar uma variável chamada auxnota dentro do procedimento. Note que essa variável
é do tipo local, só funciona dentro desse procedimento para não ficar ocupando memória.
Tbl_Nota.Last;
auxnota:=Tbl_Nota.fieldbyname('num_nota').AsInteger;
Tbl_Nota.Insert; {Tbl_nota.Append;}
Tbl_Nota.FieldByName('num_nota').Asinteger:=auxnota + 1;
Tbl_Nota.FieldByName('serie_nota').Asstring:='A1';
Tbl_Nota.FieldByName('numero_ped').AsInteger:=
Tbl_Nota.fieldByname('ncod_ped').AsInteger;
Tbl_Nota.FieldByName('dat_emi_nota').AsDateTime:= now;
Tbl_Nota.FieldByName('data_saida_nota').AsDateTime:=now;
91
Tbl_Nota.FieldByName('cfop_nota').AsInteger:= 512;
{falta obs e total nota}
Tbl_Nota.Post;
Tbl_Itens.First;
while not (TBL_Itens.Eof) do
begin
{não existe a necessidade do locate do produto, pois
como as tabelas de itens e produto estão conectadas
por um dblookupcombobox, isto é feito automaticamente}
Tbl_ItemNota.Append;
Tbl_ItemNota.FieldByName('Num_Nota').asinteger:=
Tbl_Nota.FieldByName('num_nota').AsInteger;
TBL_ItemNota.FieldByName('serie_nota').asstring:=
TBL_Nota.FieldByName('serie_nota').asstring;
Tbl_ItemNota.FieldByName('Cod_Prod').asinteger:=
Tbl_Nota.FieldByName('Cod_Prod').AsInteger;
TBL_ItemNota.FieldByName('qtd_item').asinteger:=
TBL_Nota.FieldByName('qtd_prod').asinteger;
Tbl_ItemNota.FieldByName('Valor_item').asfloat:=
Tbl_Nota.FieldByName('valor_prod').Asfloat;
Tbl_itemnota.Post;
TBL_itens.Next;
end;
Tbl_Nota.ApplyUpdates;
Tbl_ItemNota.ApplyUpdates;
end;
Foi posicionada a tabela no último elemento, foi guardado numa variável o último
número da nota ,armazenando esse valor no número da nota. Um auto-incremental.
Tbl_Nota.Last;
auxnota:=Tbl_Nota.fieldbyname('num_nota').AsInteger;
Tbl_Nota.Insert; {Tbl_nota.Append;}
Tbl_Nota.FieldByName('num_nota').Asinteger:=auxnota + 1;
Por enquanto não está sendo feito no banco mas feito direto na programação do
Delphi.
Depois é armazenado o Número de Série da nota, que por enquanto não temos campo
de configuração.
Tbl_Nota.FieldByName('serie_nota').Asstring:='A1';
92
Tbl_Nota.FieldByName('numero_ped').AsInteger:=
Tbl_Nota.fieldByname('ncod_ped').AsInteger;
Temos que preencher a data emissão e a data de saída. Esse preenchimento é feito com
a data atual.
Tbl_Nota.FieldByName('dat_emi_nota').AsDateTime:= now;
Tbl_Nota.FieldByName('data_saida_nota').AsDateTime:=now;
Depois o código cfop que é o código do serviço que está sendo feito é armazenado no
campo cfop_nota da Tbl_Nota.
Tbl_Nota.FieldByName('cfop_nota').AsInteger:= 512;
Salva a nota.
Tbl_Nota.Post;
Salvar cada Item. Posicione a tabela de Itens no Inicio. Enquanto não for final da
tabela de Itens. Coloque Append. Esse Append é igual ao Insert – a única diferença é que
insere no final da tabela, para não ter que ficar percorrendo a tabela toda hora. O ideal para
fazer um sistema com velocidade é usar o Append e não o Insert.
Tbl_Itens.First;
while not (TBL_Itens.Eof) do
begin
Tbl_ItemNota.Append;
Tbl_ItemNota.FieldByName('Num_Nota').asinteger:=
Tbl_Nota.FieldByName('num_nota').AsInteger;
TBL_ItemNota.FieldByName('serie_nota').asstring:=
TBL_Nota.FieldByName('serie_nota').asstring;
Tbl_ItemNota.FieldByName('Cod_Prod').asinteger:=
Tbl_Nota.FieldByName('Cod_Prod').AsInteger;
TBL_ItemNota.FieldByName('qtd_item').asinteger:=
TBL_Nota.FieldByName('qtd_prod').asinteger;
Tbl_ItemNota.FieldByName('Valor_item').asfloat:=
Tbl_Nota.FieldByName('valor_prod').Asfloat;
Tbl_itemnota.Post;
TBL_itens.Next;
Tbl_Nota.ApplyUpdates;
Tbl_ItemNota.ApplyUpdates;
end;
Package > Open package file (.lpk)... > Abrindo em seguida uma janela para se
localizar o componente.
94
Tendo como base que a instalação do programa foi feita no Windows e sem a
alteração dos parâmetros de diretórios, para localizar o componente “lazreport.lpk”, segue se
o caminho:
Após clicar no botão abrir será apresentado essa outra janela, que é a janela de
instalação de componentes do Lazarus.
FROM
tb_itemnota, tb_produtos
WHERE
tb_itemnota.cod_prod = tb_produtos.cod_prod
Name DataSet
DS_Rqped ROQ_ped
frDBDataSet
Name DataSource
DBD_ped DS_Rqped
frReport
Name DataSet
Rel_ped DBD_ped
Agora de um duplo clique sobre o componente frReport para abrir o seu editor.
97
Adicione uma banda e escolha a opção Page Header. Nessa banda adicione o texto
como mostra abaixo, atravez do botão Insert Retangle Object (Poderá digitar qualquer coisa
nessa banda):
Insira nova banda e escolha o tipo Master Data. Ele vai abrir uma janela solicitando a
escolha de um DataSource. Escolha a opção DBD_ped como mostra a figura abaixo e clique
em OK.
98
Agora insira os texto Nome Endereço e Numero Nota, clicando no botão Insert Re-
tangle Object.
Quando cliclar, no botão Insert Retangle Object ira aparecer a seguinte janela
Clique no botão DB Field e escolha a opção tbl_cli, para que possa pegar todos os
componentes da tabela cliente
99
Agora para campo Numero da Nota clique no botão Insert Retangle Object logo em
seguida clique no botão DB Field, na área Available DB’s escolha a opção ROQ_ped e no
campo de baixo escolha a opção Num_Nota. Ficando da seguinte maneira
Insira uma banda e escolha o tipo Detail Data. Escolha o DataSource DBD_ped.
100
Insira nova banda e selecione o tipo Detail Footer. Escreva o texto Total Venda
e logo na frente insira um texto e na janela que surgiu clique em FUNCTION
Clique em OK.
102
Para poder formatar o campo valor Total, em estilo moeda basta completar a formula
como a seguir
[SUM([tbl_itens"TOTAL"]) #N##,##0.00]
Tbl_Nota.DataSet.ParamByName('nota').AsInteger:=
Tbl_Nota.fieldbyname('num_nota').AsInteger;
Tbl_Nota.DataSet.ParamByName('serie').Asstring:=
Tbl_Nota.fieldbyname('serie_nota').Asstring;
Tbl_Nota.Active:=true;
Tbl_ItensNota.Active:=true;
REl_ped.ShowReport; {qr_nota.Print}
end;
Essa programação ira carregar o relatório toda vez que abrir o formulário vendas
105
Pelo fato de estar filtrando o relatório por uma única nota especifica, essa listagem
imprime uma única nota.
Quando impressa uma nota fiscal, seu visual tem que ser de outra forma, teria que ter
neste visual só alguns campos, porque uma nota fiscal é pré-impressa – então na impressão,
vai preencher só os valores.
Como dividir igualmente os Itens em mais de uma nota fiscal quando a quantidade de
itens for maior que o campo? No programa do Lazarus tem que fazer uma modificação. Se no
pedido tiver dezesseis itens e na nota fiscal couberem somente treze itens, temos que dividir
essa nota fiscal em duas, senão o programa imprimirá os restantes dos itens fora da área. O
ideal nesta divisão da nota é ter metade dos itens em cada nota. Para implementar essa
condição, verifique o RecordCount (contador de itens) .
Se esse valor for maior que o tamanho do formulário. Ex.: No formulário cabendo no
máximo treze itens, se esse valor for maior que 13, dividimos em mais de uma nota.
Para descobrir quantas notas são necessárias para impressão dos itens, temos que
dividir o total de itens da nota pelo campo (espaço da nota). Se a nota tem 13 espaços e os
itens são 20, dividimos 20 por 13 e descobrimos quantos formulários serão necessários.
Algoritmo:
Se o numero de itens do pedido for maior que o espaço da nota, então: Numero
necessário de Formulários = Numero de Itens dividido pelo espaço (Arredondando para o
numero inteiro abaixo).
Se após esses campos for colocado o comando Itens.First dentro do laço, nunca vai
terminar a primeira nota, então colocamos esse comando antes do laço for.
Agora temos que descobrir quantos itens serão colocados por nota. A condição para
impressão não vai ser feita enquanto não for final dos itens, mas sim até o final do numero de
106
notas. Se fosse um algoritmo que não dividisse nada então a nota seria impressa ate que os
itens fossem iguais a treze.
Quando for impressa uma nota fiscal precisamos lembrar que nem sempre é possível
colocar todos os itens da nota, se isso acontecer temos que gerar mais de uma nota.
Antes de sair imprimindo a nota, temos que lembrar que nem sempre é
possível colocar todos os itens na nota. Se isto acontecer temos que gerar
mais de uma notafiscal}
TBL_itens.First;
{NIN - numero de itens por nota}
NIN:= round(tbl_itens.RecordCount/(round(tbl_itens.RecordCount/13)));
Para os campos abaixo será feito um for variando de um até a quantidade de notas
necessárias. Os valores como data, código, pedido, serão os mesmos, mas os itens não podem
ser reinicializados, senão vai ser impressa duas notas com os mesmos itens – o Comando
Tbl_Itens.First tem que ser colocado antes do laço for.
{dividir em N notas}
for i:=1 to round(Tbl_itens.RecordCount/13) do
begin
Tbl_config.open;
Tbl_config.Edit;
Tbl_Config.Fieldbyname('numnota').Asinteger:=
Tbl_config.Fieldbyname('numnota').asinteger+1;
tbl_config.post;
Tbl_config.ApplyUpdates;
Tbl_Nota.Append;
Tbl_Nota.fieldbyname('num_nota').AsInteger:=
Tbl_config.Fieldbyname('numnota').asinteger;
Tbl_Nota.fieldbyname('serie_nota').Asstring:=
107
Tbl_config.fieldbyname('numserie').Asstring;
Tbl_config.close;
Tbl_Nota.fieldbyname('numero_ped').Asinteger:=
Tbl_ped.fieldbyname('cod_ped').AsInteger;
Tbl_Nota.fieldbyname('data_saida_nota').Asdatetime:=now;
Tbl_Nota.fieldbyname('cfop_nota').Asinteger:=512;
{falta obs e total nota}
Tbl_Nota.Post;
O comando While abaixo não vai ser executado até chegar o final de arquivo, mas
vamos ter que imprimir até chegar na metade dos itens.
Se tiver por exemplo quinze itens teria dois algoritmos possíveis: itens divididos
igualmente em mais de um formulário e outro quando chegar no final de campo, começa
outro formulário (nota).
Explicação:
Para um formulário para 13 itens. Como implementar a impressão para dividir meio a
meio? Temos que saber quantos itens serão impressos por nota. Pode-se criar uma variável
NIN(número de itens por nota).
O NIN (Numero de itens por nota) é o total de itens dividido pelo campo desta nota,
arredondado para um numero inteiro)
Tbl_Itens.First;
J=0;
NIN:= round(Tbl_Itens.RecordCount/(round(Tbl_Itens.RecordCount/13))),
-
-
-
While J mod NIN <> 0
a) quando for 8 itnes – 1 nota.
J mod Nim <> 0 8/13 = 0.62 8 mod 13 = 1
b) 9 itens – 1 nota
c) 13 itens – 1 nota
d) 16 itens – 2 notas tendo 8 itens cada
e) 17 itens – 2 notas – uma com 9 e outra com 8 itens.
J mod NIN <> 0 17/13 = 1,31 duas notas
NIN:= round(Tbl_Itens.RecordCount/(round(Tbl_Itens.RecordCount/13))),
A primeira ficará com nove itens e depois fara um tratamento para a segunda.
J Mod NIN <> 0 9 mod 9 <> 0 – não é verdadeiro, então o comando não ira ser
executado e o item 9 não será incluído.
109
Se for deixada essa condição, na hora que imprimir o oitavo item, fecha a nota, ai co-
meça a próxima começando do 10º item até o 17, imprime até o 16º item e fecha a segunda
nota – Faltou um item.
Neste algoritmo falta fazer com que o NIN vá até o décimo item - ao invés do laço
comparar com o nono item, irá ser comparado com o décimo, então o item 9 será impresso.
While J mod (NIN + 1) <> 0 Para contar até 9 quando os itens forem 13.
Na hora que chegar no décimo item, faz a comparação e sai do laço, começando tudo
de novo a partir do décimo item. O valor de J neste ponto é 10.
Na primeira nota a impressão for normal, mas no momento que entra no laço nova-
mente e faz a comparação com 10 – sendo a condição falsa – não imprimirá a segunda nota.
Criamos outro problema.
A conclusão é que o comando While para este caso não funciona, não é a solução.
Tbl_Itens.First;
J = 0;
NIN:= round(Tbl_Itens.record.count/(round(Tbl_Itens.recordcount/13)))
-
-
-
for j:= 1 to NIN do
if not (Tbl_Itens.Eof) then
Begin
Tbl_Nota.Item.Insert;
-
-
Tbl_Nota.Item.Post;
Tbl_Itens.Next;
End;
End;
Antes do laço, a tabela Tbl_Itens foi colocada em sua primeira posição. Após o ultimo
laço executado, os itens não serão impressos de novo. Isso dará a condição de ser impressa a
segunda nota continuando dos itens ainda não impressos na nota.
110
begin
{não existe a necessidade do locate do produto, pois como as tabelas
de itens e produto
estão conectadas por um dblookupcombobox, isto é feito
automaticamente}
Tbl_ItensNota.Append;
Tbl_ItensNota.FieldByName('Num_Nota').asinteger:=
Tbl_Nota.FieldbyName('num_nota').AsInteger;
Tbl_ItensNota.FieldByName('serie_nota').asstring:=
Tbl_Nota.fieldbyname('serie_nota').Asstring;
Tbl_ItensNota.FieldByName('Cod_Prod').asinteger:=
Tbl_Itens.FieldByName('Cod_Prod').asinteger;
Tbl_ItensNota.FieldByName('Qtd_item').asinteger:=
Tbl_Itens.FieldByName('Qtd_Prod').asinteger;
Tbl_ItensNota.FieldByName('valor_Item').asfloat:=
Tbl_Itens.FieldByName('valor_prod').asfloat;
TBL_itensnota.Post;
TBL_itens.Next;
end;
Depois que foram copiados os valores, salva esses valores, o comando ApplyUpdates,
continua na mesma posição. Depois que são geradas as notas, elas são salvas no Banco.
Tbl_ItensNota.ApplyUpdates(0);
Depois essas notas são impressas. A diferença agora é que a impressão era feita depois
que tinham sido gerada as duas notas. Agora tem um end no final. Esse end é do primeiro
comando for (que da a condição de verificar a quantidade de notas que são necessárias). É
gerada a primeira nota e impressa, depois gera a segunda nota, depois imprime.
Tbl_Nota.DataSet.ParamByName('nota').AsInteger:=
Tbl_Nota.fieldbyname('num_nota').AsInteger;
Tbl_Nota.DataSet.ParamByName('serie').Asstring:=
Tbl_Nota.fieldbyname('serie_nota').Asstring;
Tbl_Nota.Active:=true;
111
Tbl_ItensNota.Active:=true;
Rel_ped.ShowReport;
end;
A vantagem é se tivermos que mudar uma numeração de nota, entra-se neste arquivo e
muda-se, não tendo que alterar o programa fonte inteiro. Se tiver uma impressora fiscal,
moeda, alguma configuração do sistema (por exemplo: numero de páginas de nota fiscal)
pode-se colocar nesta tabela. O próprio Path do arquivo poderia estar dentro desta tabela.
Note que não tem chave primaria, porque esse arquivo de configuração só tem uma
única linha
Programação:
Tbl_config.open;
Tbl_config.Edit;
Tbl_Config.Fieldbyname('numnota').Asinteger:=
Tbl_config.Fieldbyname('numnota').asinteger+1;
tbl_config.post;
Tbl_config.ApplyUpdates;
Tbl_Nota.Append;
Tbl_Nota.fieldbyname('num_nota').AsInteger:=
Tbl_config.Fieldbyname('numnota').asinteger;
Tbl_Nota.fieldbyname('serie_nota').Asstring:=
Tbl_config.fieldbyname('numserie').Asstring;
Tbl_config.close;
Abrindo a tabela – sempre vai estar posicionada no ultimo registro que existe.
Tbl_config.open;
Antes de mais nada, somar no último número da nota mais um, para já incrementar o
valor da nota.
Tbl_Config.Fieldbyname('numnota').Asinteger:=
Tbl_Config.Fieldbyname('numnota').asinteger+1;
Tbl_Config.post;
Tbl_Config.ApplyUpdates;
Insere o numero da nota, copia o valor, copia o numero de série depois fecha a tabela.
Tbl_Nota.fieldbyname('num_nota').AsInteger:=
Tbl_config.Fieldbyname('numnota').asinteger;
Tbl_Nota.fieldbyname('serie_nota').Asstring:=
Tbl_config.fieldbyname('numserie').Asstring;
Tbl_config.close;
Cada vez que o programa for executado o sistema abre a tabela, porque enquanto
estiver rodando a primeira nota, outra pessoa pode imprimir outra nota também. Gerar uma
após a outra.
Em nenhum lugar esta armazenando a forma de pagamento, então tem que criar um
formulário (tela) forma de pagamento. O Banco já existe, então crie o Formulário.
Name Caption
Frm_formpag Forma de Pagamento
Para cada campo do banco de dados insira um DBEdit como feito nos projetos
anteriores e também adicione os Labels para poder especificar cada campo
Pedido. Este campo é um Combo porque só vai fazer consultas na Tela Forma de Pagamento.
A Forma de Pagamento foi criada em outra tela.
Depois que gerar a nota, falta gerar contas a receber. O próximo passo é fazer um
comando for ou While variando de 1 até o número de parcelas. O numero de parcelas está
cadastrado na tabela Forma de Pagamento, então para fazer um comando for ou While
variando de um até o numero de parcelas, pegamos o total da nota e dividi pelo numero de
parcelas.
Primeiramente é precisso criar algumas rotinas auxiliares, pois se não poderá dar
alguns problemas.
É preciso fazer uma função que some um centavo na primeira nota, se houver esse
centavo. Quando for R$ 99,00 dividido por 3 parcelas, dará R$ 33,00 em cada parcela. Mas se
for R$ 100,00 dividido por 3 parcelas, terá que gerar uma parcela de R$ 33,34 e as demais
parcelas de R$ 33,33, então sempre terá que arredondar esse um centavo em alguma das
parcelas.
12.10 - A Programação
busco o produto
qtd_prod = qtd_prod - qtd_itens
ir para o proximo item
fim enquanto}
TBL_itens.First;
{quando executamos o first na tabela de itens, estamos posicionando
o ponteiro no primeiro item deste pedido (e não da tabela inteira)
devido ao relacionamento master/detail }
while not (TBL_itens.Eof) do
begin
{não existe a necessidade do locate do produto, pois
como as tabelas de itens e produto estão conectadas
por um dblookupcombobox, isto é feito automaticamente}
Tbl_Prod.Edit;
TBL_Prod.FieldByName('qtd_prod').asinteger :=
TBL_Prod.FieldByName('qtd_prod').asinteger -
TBL_itens.FieldByName('qtd_prod').asinteger ;
Tbl_Prod.Post;
TBL_itens.Next;
end;
{inicia o processo para gerar a nota.
Basicamente, temos que copiar os dados da tabela de pedido e gravar na
nota.
Algoritmo:
{- antes de sair imprimindo a nota, temos que lembrar que nem sempre é
possivel colocar todos os itens na nota.Se isto acontecer temos que gerar
mais de uma nota fiscal}
TBL_itens.First;
{NIN - numero de itens por nota}
NIN:= round(tbl_itens.RecordCount/
(round(tbl_itens.RecordCount/13)));
{dividir em N notas}
for i:=1 to round(Tbl_itens.RecordCount/13) do
begin
Tbl_Config.open;
Tbl_Config.Edit;
Tbl_Config.Fieldbyname('numnota').Asinteger:=
Tbl_Config.Fieldbyname('numnota').asinteger+1;
Tbl_Config.post;
Tbl_Config.ApplyUpdates;
Tbl_Nota.Append;
Tbl_Nota.fieldbyname('num_nota').AsInteger:=
Tbl_Config.Fieldbyname('numnota').asinteger;
Tbl_Nota.fieldbyname('serie_nota').Asstring:=
Tbl_Config.fieldbyname('numserie').Asstring;
Tbl_config.close;
116
Tbl_Nota.fieldbyname('numero_ped').Asinteger:=
Tbl_ped.fieldbyname('cod_ped').AsInteger;
Tbl_Nota.fieldbyname('data_saida_nota').Asdatetime:=now;
Tbl_Nota.fieldbyname('cfop_nota').Asinteger:=512;
{falta obs e total nota}
Tbl_Nota.Post;
Tbl_ItensNota.FieldByName('serie_nota').asstring:=
Tbl_Nota.fieldbyname('serie_nota').Asstring;
Tbl_ItensNota.FieldByName('Cod_Prod').asinteger:=
Tbl_Itens.FieldByName('Cod_Prod').asinteger;
Tbl_ItensNota.FieldByName('Qtd_item').asinteger:=
Tbl_Itens.FieldByName('Qtd_Prod').asinteger;
Tbl_ItensNota.FieldByName('valor_Item').asfloat:=
Tbl_Itens.FieldByName('valor_prod').asfloat;
TBL_itensnota.Post;
TBL_itens.Next;
end;
Tbl_Nota.ApplyUpdates(0);
Tbl_ItensNota.ApplyUpdates(0);
Tbl_Nota.DataSet.ParamByName('nota').AsInteger:=
Tbl_Nota.fieldbyname('num_nota').AsInteger;
Tbl_Nota.DataSet.ParamByName('serie').Asstring:=
Tbl_Nota.fieldbyname('serie_nota').Asstring;
Tbl_Nota.Active:=true;
Tbl_ItensNota.Active:=true;
Rel_ped.Showreport;
end; {for i - o primeiro for}
end;
117
Antes de gerar contas a receber tem que programar o total, para quando for inserindo
itens já aparece o total na conta do cliente.
Caption
Total
Primeira solução:
No evento AfterPost da tabela de Itens - Cada vez que um item for inserido e salvo -
após o post (salvar) fazemos um for do primeiro até o último item (for i variando de 1 até
recordcount) O total recebe qtde X valor n vezes até descobrir o total geral. Para fazer essa
forma só podemos usar um Edit comum para atribuir o valor.
Segunda Solução:
Ou criar mais uma tabela com SQL e toda vez que for feita alguma coisa, vamos nesta
tabela e fazemos um Refresh nesta tabela e teremos o total na hora.
Para testar será utilizado os dois tipos de programações e depois é so escolher uma.
A primeira Solução:
Caption
119
Total
A segunda Solução
13.2 - Programação:
Clique na Tabela de Itens e no Obect Inspector > Eventos > After Post.
Após um Post. Após salvar um item fazemos a contagem do total. Porque após um Post?
Porque tem que ter certeza que o item já foi salvo. Se fizer a programação no evento before
post (antes de salvar) o programa fará a conta mas não tem o item ainda salvo. Então essa
conta ficará errada. Só pode fazer a conta depois de salvar
.
Depois que o pedido foi feito, o item foi salvo, foi percorrido toda a tabela e gravamos no
total.
120
Declare a variavel aux do tipo local, para não ficar ocupando espaço na memória, ela
será usada na programação.
Depois que estiver no primeiro registro, já foi possionado no primeiro item. Imagine
que uma tabela tenha dez mil itens e existe um pedido com dez itens e é o décimo produto que
esta sendo passado, após salvar, volta no primeiro item, percorre a tabela inteira dos dez itens
gravados e totaliza numa variável auxiliar e no final, apresenta o valor da variável auxiliar no
Edit Total da tela.
Esse algoritmo lembra o algoritmo da baixa em estoque, portanto são todos parecidos.
Não é necessário fazer aux receber o zero. Quando foi criado a variavel aux, por
padrão no Pascal, é criada uma variável zerada, quando numeric e string. Na linguagem C
tería que fazer obrigatoriamente uma variável zerada, porque vem lixo dentro.
aux:=0;
TBL_itens.First; {o First vai para o primeiro registro}
Existe uma lista de pedido, então posiciona no primeiro registro, enquanto não for
final de arquivo, vai somando no total. Se tiver um pedido com muitos itens seria usado o
método com SQL que é mais rápido. Enquanto não chegar no final de arquivo na tabela de
itens, carrega o auxiliar aux. Aux recebe aux + valor do total.
Esta pegando o total e armazenando na variável aux. No final do comando While, note
que esta fazendo a programação fora do laço se faz a programação abaixo:
edt_total.Text:=formatfloat('R$ #,##0.00',aux);
end;
{ou}
{ Tbl_Itens.ApplyUpdates;
Tbl_Total.Close;
Tbl_Total.Open;
}
end;
O Calcula está sendo executado corretamente, mas só depois que alteramos algum
valor ou inserimos um novo item. Para alterar isso, tem que fazer a mesma programação
quando for mostrar o sistema.
A programação em si, funciona, mas falta mais um local para programar, quando abre
o formulário, quando aparece o pedido.O evento depois que o pedido aparece é o evento After
Scroll (após navegar). Após o pedido aparecer usa-se a tabela de pedidos.
Esse propriedade vai executar a mesma coisa antes de chegar no final. A vantagem é
que se for feita a programação uma única vez e se precisar efetuar alguma alteração é feita
nesta propriedade e essa alteração também é efetuada nos dois eventos.
Coloque essa observação no começo da programação acima após o begin:
Se ao tentar executar o programa e der uma mensagem de erro , dizendo que não se
pode executar uma operação com o banco de dados fechado, faça o seguinte:
Fazendo uma linha do tempo tem o primeiro evento Open da Tabela de pedido. Esse
evento abre a tabela de pedido, depois abre a Tabela de Itens e assim por diante. O que
acontece? Quando abrir a tabela, antes de tudo, posicione no primeiro registro, fazendo o
123
evento Scroll. O que acontece é que temos o comando Tbl_itens.First, só que a tabela de
itens no tempo ainda não foi aberta. Por isso dá o erro de tabela fechada.
Para corrigir esse problema, tem que efetuar um tratamento para verificar se a tabela
de itens foi aberta ou não. Só pode executar esse algoritmo se a tabela de itens estiver aberta.
Para verificar se a tabela já está aberta coloca a linha de comando abaixo, antes de colocar a
tabela de itens no primeiro registro.
A tabela não estando em modo Insert, se não tiver nenhum desses status a tabela não
está aberta, não esta navegando, nem inserindo e nem editando, quer dizer que ela esta ou
inativa ou ainda está abrindo. Pode-se usa-la só depois que estiver aberta. Então pode tentar
estes três valores ou colocar um “not” (se a tabela não está abrindo ou inativa). É mais fácil
colocar: Se o status estiver em navegando (dsBrowser), editando(dsEdit) ou
inserindo(dsInsert), então o sistema fará alguma coisa.
Teste o programa!
Porque não mostrou o item se foi feita a programação? Porque não chamou esse
evento. Quando abriu a tabela o sistema posicionou no primeiro registro e não navegou para o
último. Então quando a tabela abriu, posicionou-se no primeiro registro e a tabela e a tabela
de itens não estava aberta ainda. Só que não foi para o último registro porque não tem
comando para fazer isso.
124
- Na hora que ligou, foi conferida a tabela, estava engatada? Ainda não, então não anda.
Em algum lugar oi mencionado que tinha que engatar a primeira, trocar de marcha, fa-
zer um force ou retry na tabela.
- Em nenhum momento foi engatada a marcha, foi dada a partida, não mandamos a ta-
bela para nenhum registro (não engatamos a marcha) então não da para sair andando.
- Falta algum passo para sais andando. Se o carro vai andar, temos que dar partida e de-
pois engatar. O que é engatar? É selecionar o que queremos fazer, sair na primeira,
engatar a segunda, terceira, quarta...
- O que isso representa em nosso exemplo? Os registros, temos que mandar a execução
para algum registro, para o primeiro, anterior ou próximo.
No caso de uma venda, quando abrirmos o sistema, o registro iria para a última venda.
Ao trazer o formulário, deveria mostrar a última venda, a partir dali, conseguimos colocar
novas vendas.
Não adianta mostrar a primeira venda. O interessante é mostrar a última venda. Então
ao abrir o formulário posicione na última venda.
Programação:
Quando mostrar o formulário na tela, jogo a tabela no último registro.
tbl_cli.open;
tbl_prod.Open;
tbl_ped.Open;
tbl_itens.Open;
tbl_nota.open;
tbl_itens_nota.open;
tbl_form_pag.open;
end;
125
Execute o programa.
Name
Edt_total
Na propriedade procure o EditMask e clique nos três pontinhos para entrar no Modulo de
Editor e deixe como mostra a figura abaixo:
edt_total.Text:=formatfloat('R$ #,##0.00',aux);
126
Lazarus: não é possível executar o projeto antes de salvar, primeiramente tem que sal-
var o projeto para que possa ser executado,
Lazarus: Quando for salvo as units em pasta diferente é necessário especificar o diretó-
rio dessas units
Lazarus: É mais complicado, pois suas propriedades são feitas atravez do objectoIns-
pector e precisa-se de um outro compoenente (Transaction) para fazer a comunicação entre o
projeto e arquivo fisico
Delphi: Apenas um componente basta para fazer a ligação entre o projeto e o arquivo
físico;
Lazarus: não existe a opção de selecionar todos os campos da tabela e arrastar para
dentro do formulário, adicionando assim todos os campos da tabela no formulário, o único
modo é fazer um a um.
Delphi: Precisa-se de dois componente, o primeiro (CoolBar) que cria o espaço onde a
barra d e ferramentas ira ficar, o segundo (ToolBar) é a barra de ferramenta;
Lazarus: Para que se possa chamar uma outra tela, é necessário programar no próprio
código fonte, tornando assim um pouco mais complexo.
Lazarus: Muito mas fácil, pois tudo que será utilizado na criação de relatório esta em
um único lugar
Delphi: Torna-se mais complicado, pois cada componente que precisa-se esta em luga-
res diferentes, fazendo assim que sua atenção redobre;
Lazarus: É possível criar um gráfico, mas muito complicado, pois todas as suas pro-
priedades tem que ser programada no ObjectInspector
Lazarus: Apesar do EXE ser maior que o do Delphi, não precisa de outras bibliotecas
instalado na maquina que vai rodar o EXE.
15 - REFERÊNCIAS BIBLIOGRÁFICAS
Sites:
http://blog.silvioprog.com.br/
DATA: Ultimo acesso em novembrode 2010
http://dicas4lazarus.blogspot.com/2010/03/fortes-report-for-lazarus-vs-0358.html
DATA: Ultimo acesso em novembro de 2010
http://lazarusbrasil.forumeiros.com/
DATA: Ultimo acesso em novembrode 2010
http://professorcarlos.blogspot.com/2010/02/lazarus-acessando-banco-de-dados-
com.html
DATA: Ultimo acesso em outubro de 2010
http://wiki.freepascal.org/SQLdb_Package
DATA: Ultimo acesso em outubro de 2010
http://www.baixaki.com.br/download/lazarus.htm
DATA: Ultimo acesso em outubro de 2010
Apostila:
Apostila Delphi 2 - DESENVOLVIMENTO DE APLICAÇÕES COMERCIAIS
130
16 - CONCLUSÃO
De acordo o conteúdo apresentado neste projeto, fica claro que o Lazarus pode ser
considerado uma poderosa ferramenta de desenvolvimento, e que através dele, é possível
executar a matéria implementada pelo professor Renato Barros na disciplina de Programação
Visual que utiliza o Delphi como ferramenta. E fica comprovado que o projeto apresentado
em Lazarus se equivale com a matéria apresentada em Delphi, mesmo existindo algumas
diferenças, nas quais foram resolvidas com estudo e auxilio do professor.
131
17 - CRONOGRAMA
AGOSTO
SETEMBRO
OUTUBRO
NOVEMBRO
DEZEMBRO