| Últimas 20 atualizações de Cicero Tadeu Pereira Lima França |
|
|
Esta série de artigos irá mostrar com usar nosseus softwares o middleware LUCAS-GABRIEL, que tem a finalidade deaumentar a escalabilidade do SGBD através da distribuição horizontal dos dados. Apresentação Sistemas que entram em produção tendem a perderdesempenho após um determinado tempo. Algumas vezes essa perda de desempenho estárelacionada com consultas de dados mal elaboradas, mas na maioria das vezes oproblema está relacionado a sobrecarga que os servidores de dados sofrem com oaumento dos dados armazenados. Na tentativa de resolver este problema aCASSIC está desenvolvendo o middleware LUCAS-GABRIEL. Este middlewareefetua a distribuição horizontal dos dados entre instâncias distintas deSGBDRs, mas sem interferir diretamente sobre o processamento dos SGBDRs. 
Figura 1 – Arquitetura do LUCAS-GABRIEL Esta solução impacta diretamente sobre acomunidade de programadores e softhouses, pois o LUCAS-GABRIEL tem a pretensãode ser independente do banco de dados e da linguagem de programação utilizada,o que diminui significativamente a curva para a interoperabilidade entresistemas feitos em linguagens distintas e banco de dados heterogêneos, cenáriocomum nas empresas da atualidade. Existem outras soluções para este problema,mas diferentemente do LUCAS-GABRIEL, elas são direcionadas para um banco dedados ou linguagem de programação especifica. Já foram feitos teste iniciais emlaboratório e alguns teste em ambiente de produção controlado, nos dois casosforam obtidos bons rendimentos. Agora estamos colocando ele a disposição dacomunidade para que todos avaliem e dêem feedbacks. A intenção da CASSIC édesenvolver um middleware que seja GRATUITO e CONFIÁVEL. Com a finalidade de apresentar e divulgar acomunidade, será apresentado uma série de artigos mostrando as funcionalidadesdo LUCAS-GABRIEL em conjunto com o Delphi. Esperamos que apreciem e dêem seusfeedbacks sobre o produto. Preparando os Bancos de Dados Foi dito anteriormente que o LUCAS-GABRIEL “tema pretensão de ser independente do banco de dados”, mas para efetuar osprimeiros testes e avaliarmos melhor o desempenho do banco de dados, nestaprimeira versão beta só foi implementada a conexão com o Firebird. Colocadaesta explicação, vamos a construção do banco de dados. Abaixo seguem os comandos DDLs para acriação das tabelas que serão usadas para mostrar as funcionalidades do LUCAS-GABRIEL.
create table Cliente(
ID integer not null primary key,
Nome varchar(50),
Limite_Credito numeric(15,2)
);
create table Produto(
ID integer not null primary key,
Descricao varchar(50),
Vr_Venda numeric(15,2)
);
create table PDV(
ID integer not null primary key,
Dt_Venda date,
ID_Cliente integer,
foreign key(ID_Cliente) references Cliente(ID)
);
create table PDV_Item(
ID integer not null primary key,
Quant numeric(15,3),
Vr_Unit numeric(15,2),
ID_PDV integer,
ID_Produto integer,
foreign key(ID_PDV) references PDV(ID),
foreign key(ID_Produto) references Produto(ID)
);
Devido o LUCAS-GABRIEL efetua a distribuiçãohorizontal, estes mesmos comandos DDLs devem ser repetidos para cadainstância do SGBD. Se desejar, pode efetuar a cópia de todo o banco de dadospara as máquinas onde os SGBDs estão instanciados. É importante ter em menteque na distribuição horizontal, as mesmas tabelas e colunasexistentes numa instância do SGBD devem existir nas outras instâncias. Instalação do LUCAS-GABRIEL Os arquivos necessários para usar oLUCAS-GABRIEL podem ser baixados de http://www.cassic.com.br/carregar/produtos/lucas_gabriel. Observação:Osistema que vai ser desenvolvido para testar o LUCAS-GABRIEL será citado desteponto por diante como Sistema Cliente. Na máquina onde ficará Sistema Clientenão é instalado nenhum driver de conexão com o SGBD, nela deve-secolocar apenas o arquivo “LUCAS.dll” que está dentro do arquivo baixado. Numa máquina entre o Sistema Clientee os SGBDs deve ser instalado o aplicativo GABRIEL junto com o arquivo“Midas.dll”. Nesta máquina também devem ser instalados os drivers clientedo SGBDs, pois o aplicativo GABRIEL é visto pelos SGBDs com um sistema clientecomum. Configuração do LUCAS-GABRIEL O arquivo “LUCAS.dll” será configuradodentro do Sistema Cliente. Mas o aplicativo GABRIEL requer configuraçõesmanuais. A figura 2 mostra a aparência do aplicativoGABRIEL quando ele for inicializado pela primeira. 
Figura 2 – Aplicativo GABRIEL nãoconfigurado Para configura o aplicativo GABRIEL siga ospassos abaixo: 1. Na“Caixa de edição Porta” informe a porta e na seqüência clique no “BotãoSetPorta”. Nossa configuração usou a porta “1010”, mas a sua porta pode serdiferente. 2. Na“Caixa de edição Servidor” informe o nome do servidor, na “Caixa deedição Endereço” informe o endereço do banco de dados, em seguida clique nobotão “Botão SetServidor”, repita este processo para todos osservidores. A nossa configuração usou 3 servidores de banco dedados e ficou como mostrado abaixo, ela serve de exemplo para a suaconfiguração: a. Servidor: Servidor_01 Endereço: 192.168.56.20:\Documents andSettings\Windows-VB\Desktop\BancoDados_1.FDB b. Servidor: Servidor_02 Endereço: 192.168.56.30:\Documents andSettings\Windows-VB\Desktop\BancoDados_2.FDB c. Servidor: Servidor_03 Endereço: 192.168.56.40:\Documents andSettings\Windows-VB\Desktop\BancoDados_3.FDB 3. Na“Caixa de edição Tabela” informe o nome da tabela que será distribuídaentre os bancos de dados, na “Caixa de edição Chave” informe o nome doatributo da tabela que deve ser tratada como chave primária, e na “Caixa deedição Gerador” informe o número que será usado como valor de inicializaçãoda chave primária. Na seqüência clique no “Botão SetTabela”, repitaeste processo para todas as tabelas. Para seguir os exemplos desteartigo, a sua configuração deve ficar igual a nossa: a. Tabela: Cliente Chave:ID Gerador: 0 b. Tabela: Produto Chave:ID Gerador: 0 c. Tabela: PDV Chave:ID Gerador: 0 d. Tabela: PDV_Item Chave:ID Gerador: 0 
Figura 3 – Aplicativo GABRIEL configurado Criando o Formulário Principal do Projeto SistemaCliente Crie um novo projeto, modifique apropriedade Name do formulário para FPrincipal. Insirana seção interface da Unit o código que estádestacado com a cor vermelha.
interface
uses
Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
Dialogs;
type
TFPrincipal = class(TForm)
private
{ Private declarations }
public
{ Public declarations }
ArqResposta: string;
end;
procedure LUCAS_SetAtivarSoquete(Ativar: Boolean);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetPorta(Porta: Integer);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetMediador(Endereco: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetResposta(Endereco: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetConfiguracao(Porta: Integer; EnderecoMediador,
EnderecoResposta: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetTabela(Tabela: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetChaveEstrangeira(Tabela, Campo: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetDados(Campo, Valor: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_Clear;
stdcall; external 'LUCAS.dll';
procedure LUCAS_ClearChaveEstrangeiraTudo;
stdcall; external 'LUCAS.dll';
procedure LUCAS_ClearChaveEstrangeira(Tabela, Campo: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_ClearDadosTudo;
stdcall; external 'LUCAS.dll';
procedure LUCAS_ClearDados(Campo: string);
stdcall; external 'LUCAS.dll';
function LUCAS_GetSocketAtivo: Boolean;
stdcall; external 'LUCAS.dll';
function LUCAS_GetSocketAtivar: Boolean;
stdcall; external 'LUCAS.dll';
function LUCAS_GetPorta: Integer;
stdcall; external 'LUCAS.dll';
function LUCAS_GetMediador: string;
stdcall; external 'LUCAS.dll';
function LUCAS_GetResposta: string;
stdcall; external 'LUCAS.dll';
function LUCAS_GetTabela: string;
stdcall; external 'LUCAS.dll';
function LUCAS_GetChaveEstrangeira: string;
stdcall; external 'LUCAS.dll';
function LUCAS_GetDados: string;
stdcall; external 'LUCAS.dll';
function LUCAS_GetPendente: Integer;
stdcall; external 'LUCAS.dll';
function LUCAS_GetStatusDescr(var Status: string): Integer;
stdcall; external 'LUCAS.dll';
function LUCAS_GetStatus: Integer;
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetIncluir(Requisitar: Boolean);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetAlterar(Condicao: string; Requisitar: Boolean);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetExcluir(Condicao: string; Requisitar: Boolean);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetConsultar(Condicao: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetConsultarSQL(ComandoSelect: string);
stdcall; external 'LUCAS.dll';
procedure LUCAS_SetRequisitar;
stdcall; external 'LUCAS.dll';
var
FPrincipal: TFPrincipal;
No evento OnShow do FPrincipalentre com o código abaixo:
procedure TFPrincipal.FormShow(Sender: TObject);
begin
// Desativando conexão com o GABRIEL
LUCAS_SetAtivarSoquete(False);
// Configurando endereço do mediador
// Este endereço foi usado no nosso projeto, mas o seu pode ser diferente
LUCAS_SetMediador('192.168.56.10');
// Configurando porta de comunicação
// Esta porta foi a configura na “Caixa de edição Porta”
// do aplicativo GABRIEL, mas a sua pode ser diferente
LUCAS_SetPorta(1010);
// Ativando conexão com o GABRIEL
LUCAS_SetAtivarSoquete(True);
// Nome do arquivo de retorno
// Este nome é padrão e pode ficar numa constante do sistema
ArqResposta := 'Consulta.xml';
// Configurando endereço do arquivo com retorno da consulta
LUCAS_SetResposta( ExtractFilePath(Application.Exename) );
end;
Coloque no formulário um componente TMainMenue configure-o como mostrado na figura 4. 
Figura 4 – Menu do Sistema Cliente Observação:A construção do Sistema Clientefocará o uso do middleware LUCAS-GABRIEL, logo nem sempre serão usadas as boaspráticas da programação por questões didáticas. Salve o formulário com o nome de UPrincipale o projeto com o nome de SistemaCliente. Criando o Formulário FClienteInc Crie um formulário e configure e coloque oscomponentes solicitados:
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real – Parte 2g
Continuação da Parte 2f.
Para finalizar a classe de integração TCASSICNFe, os métodos InutilizarNFe e Enviar_eMailNFe são apresentado na listagem abaixo.
|
// Método para gerar o arquivo de solicitação de inutilização de NF-e |
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real – Parte 2f
Continuação da Parte 2e.
Para finalizar a classe de integração TCASSICNFe, o métodos ImprimirDANFE e CancelarNFe são apresentado na listagem abaixo.
|
// Método para gerar o arquivo de solicitação de impressão do DANFE |
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real – Parte 2e
Continuação da Parte 2d.
Na listagem seguinte é mostrado o método responsável por integrar o ERP com o middleware (MercuryMD). Ele cópia para a pasta de solicitação o arquivo gerado pelos métodos GerarNFe (Parte 2b), ImprimirDANFE (Parte 2f), CancelarNFe (Parte 2f), InutilizarNFe (Parte 2g) e Enviar_eMailNFe (Parte 2g). Na seqüência o método fica aguardando o arquivo de retorno gerado pelo middleware para poder processar a resposta.
|
// Método que integra o ERP ao Mercury-MD |
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real – Parte 2d
Continuação da Parte 2c.
Continuação do método que gera o arquivo de solicitação para emissão da NF-e (GerarNFe).
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real – Parte 2c
Continuação da Parte 2b.
Continuação do método que gera o arquivo de solicitação para emissão da NF-e (GerarNFe).
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real – Parte 2b
Continuação da Parte 2a.
Na listagem seguinte é apresentada a primeira parte do método que gera o arquivo de solicitação para emissão da NF-e (GerarNFe). Embora o método seja grande, ele é simples, pois basicamente ele captura os dados da nota fiscal persistida no ERP e formata o arquivo de solicitação no mesmo local do aplicativo.
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real – Parte 2a
Após apresentar o middleware que criamos para integrar ERPs com NF-e (Nota Fiscal Eletrônica – Um caso real) recebi alguns e-mails pedindo ajuda na integração. De uma maneira geral a integração é simples, mas para os que haviam pedido ajuda lhes enviei uma classe de integração criada no Delphi, o que reduz ainda mais a curva de integração entre o nosso middleware e o ERP.
A classe que será apresentada é utilizada pelos nossos ERPs para fazer a emissão de NF-e via middleware. Embora o arquivo da classe seja grande, ela é bem simples e auto-explicativa. Mas caso exista alguma dúvida, por favor, nos comunique.
Na listagem abaixo é apresentado a declaração da classe TCASSICNFe e das constantes PathNFeIn e PathNFeOut. Estas duas constantes informam a classes TCASSICNFe onde colocar o arquivo de solicitação que será consumido pelo middleware (PathNFeIn) e onde o middleware irá colocar a reposta da solicitação feita (PathNFeOut).
Na mesma listagem é apresentado o construtor da classe (Create), o método que buscará o ID do município que será usado na geração da NF-e (MunicID) e o método que retorna a descrição do status da solicitação feita ao middleware (StatusNFe).
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Nota Fiscal Eletrônica – Um caso real
Nossa empresa estar inserida numa
região que comporta o terceiro pólo calçadista do país. No final de 2009 inicio
de 2010 várias indústrias precisaram inserir nos seus ERPs a emissão da NF-e.
Entre essas empresas estavam alguns clientes nossos. Além das indústrias de
calçado outros clientes atacadistas e varejistas também precisavam emitir NF-e.
Com mais de um sistema para ser
integrado com a NF-e passamos por um questionamento:
- Como
minimizar o trabalho de manutenção dos ERPs para integrá-los a NF-e?
A resposta que encontramos foi a
criação de um middleware que faça todo o processo de integração da NF-e com o
mínimo de alteração em sistemas legados.
O middleware foi pensado e
construído visando nos nossos sistemas legados em Delphi, e já preparado para,
se preciso, integrá-lo com nossos sistemas legados feitos em outras linguagens.
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Transferência de dados através de arquivos .txt - Parte VII
Projeto para receber os dados (cont.)
Código para receber o arquivo de
transferência
Vamos colocar
o código necessário para receber e gravar os dados que estão no arquivo de
transferência. No evento OnShow do formulário coloque a Listagem
6, depois dê um clique duplo no BtnRec
insira a Listagem 7 no evento OnClick.
|
procedure
TFRec.FormShow(Sender: TObject);
begin
PnlStatus.Caption := 'Status : Sem Processo';
end;
|
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Transferência de dados através de arquivos .txt - Parte VI
Projeto para receber os dados
Agora devemos criar um projeto para
receber o arquivo que foi gerado. Assim
como o projeto anterior deixaremos ele simples, para que possa, caso deseje,
colocar essa rotina em um projeto seu com poucas alterações.
No novo
projeto mude as seguintes propriedades do formulário:
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Transferência de dados através de arquivos
.txt - Parte V
Iniciando um novo projeto para
transmitir os dados (cont.)
Entrando com código para gerar o arquivo de
transferência (cont.) Para
formatar
a data e a hora de acordo com o layout usamos a função FormatDateTime
do próprio Delphi, como vista na Listagem 1 é bem simples, ela requer
dois parâmetros, o primeiro parâmetro é formato de saída desejado e o
segundo
parâmetro é a Data e/ou Hora
que será formatado.
Já
para
remover o separador decimal dos valores numéricos e fixar os tamanhos
desejados
para alfanuméricos e numéricos criamos duas funções com os respectivos
nomes de
RemoverChar e PreencherStr. Essa função tem que ser declaradas no Private
declarations do
formulário (Listagem 2).
|
Type
TFTransf = class(TForm)
BtnGerar: TBitBtn;
PBarGerar: TProgressBar;
SQLConnec: TSQLConnection;
SQLQuery: TSQLQuery;
DataSetProv: TDataSetProvider;
ClientDataSet: TClientDataSet;
procedure
BtnGerarClick(Sender: TObject);
private
{ Private declarations }
// Declare as duas
funções criadas para esse exemplo aqui
function PreencherStr(StrEntrada: string;
CharPreencher: Char;
TamRetorno: Integer;
LeftPreencher:
Boolean): string;
function
RemoverChar(StrEntrada: string;
CharRemover: Char): string;
public
{
Public
declarations }
end;
|
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Transferência de dados através de arquivos .txt - Parte IV
Iniciando um novo projeto para transmitir os dados (cont.)Entrando com código para gerar o arquivo de transferência Agora para concluir o programa de transferência de dados devemos entrar com o código que irá gerar o arquivo desejado de acordo com o layout proposto. Dê um clique duplo no BtnGerar para criar o evento OnClick. Dentro do evento coloque a Listagem 1. * Todo o código está comentado para melhor compreensão.
|
procedure TFTransf.BtnGerarClick(Sender: TObject);
var
// Variável do tipo arquivo
ArqTransf: TextFile;
Cont, Lin, Reg1,
Reg2: Integer;
begin
/////////////////////////////////////////////////////////////
//
//
// Lembrete : Serão adotados os
formatos preestabelecidos //
//
no layout
//
// //
// Obs. : Para identificar que dados
estamos informando //
//
colocaremos apenas os nomes dos campos informados no //
//
layout criado //
// //
/////////////////////////////////////////////////////////////
// Inicializando os contadores
Lin := 0;
Reg1 := 0;
Reg2 := 0;
// Informando a variável ArqTransf o
// nome do arquivo que será gerado
AssignFile(ArqTransf, 'Transf.txt');
// Inicializando o arquivo de transferência
Rewrite(ArqTransf);
// Incrementando o contador de linhas
Inc(Lin);
// Incluindo uma nova linha no arquivo de
transferência
// Registro Tipo 0
WriteLn(ArqTransf,
// Tipo
'0' +
// DtGera
FormatDateTime('yyyyymmdd', Now) +
// HsGera
FormatDateTime('hhmmss', Now) +
// Versão
'1.0.0' +
// Brancos
PreencherStr(' ',
' ', 170,
False) +
// Linha
PreencherStr(IntToStr(Lin), '0', 5, True ));
// Abrindo a conexão com a base de dados
SQLConnec.Connected := True;
///////////////////////////////////////
// //
// Inicio da transferência dos dados //
// //
///////////////////////////////////////
// Quando a variável "Cont" for
igual a 1 estaremos utilizando a
// tabela "Cliente". Quando o seu valor for 2 passaremos a usar
// a tabela "Produto"
// Cont = 1 --> Tabela Cliente
// Cont = 2 --> Tabela Produto
for
Cont := 1 to 2 do
begin
// Abrindo tabela de cliente
SQLQuery.SQL.Clear;
case Cont of
// Utilizando a
tabela "Cliente"
1:SQLQuery.SQL.Add('select * from Cliente');
// Utilizando a tabela
"Produto"
2:SQLQuery.SQL.Add('select * from Produto');
end;
// Para melhor compreenção não
utilizarei o "with ClientDataSet do"
ClientDataSet.Active := False;
ClientDataSet.Active := True;
// Preparando o TProgressBar para mostrar
o progresso
// da transferência dos dados
PBarGerar.Position := 0;
PBarGerar.Max :=
ClientDataSet.RecordCount;
// Entra no loop dos registros da
tabela atual
// até chegar no fim do arquivo - Eof
(End of file)
while not(ClientDataSet.Eof)
do
begin
// Incrementando
o contador de linhas
Inc(Lin);
case Cont of
// Utilizando a tabela
"Cliente"
1:begin
// Incrementando o contador
do Registro Tipo 1
Inc(Reg1);
// Incluindo uma nova linha
no arquivo de transferência
// Registro Tipo 1
WriteLn(ArqTransf,
// Tipo
'1'
+
// Codigo
PreencherStr(ClientDataSet.FieldByName('Codigo').AsString,
'0', 5, True) +
// CPF
PreencherStr(ClientDataSet.FieldByName('CPF').AsString,
' ', 14, False) +
// Nome
PreencherStr(ClientDataSet.FieldByName('Nome').AsString,
' ', 50, False) +
// Endereço
PreencherStr(ClientDataSet.FieldByName('Ender').AsString,
' ', 50, False) +
// Bairro
PreencherStr(ClientDataSet.FieldByName('Bairro').AsString,
'
', 30, False) +
// Cidade
PreencherStr(ClientDataSet.FieldByName('Cidade').AsString,
' ', 30, False) +
// UF
PreencherStr(ClientDataSet.FieldByName('UF').AsString,
' ', 2, False) +
// DtNasc
FormatDateTime('yyyyymmdd',
ClientDataSet.FieldByName('DtNasc').AsDateTime)+
// Linha
PreencherStr(IntToStr(Lin),
'0', 5, True));
end;
// Utilizando a
tabela "Produto"
2:begin
// Incrementando o contador do Registro Tipo
2
Inc(Reg2);
// Incluindo uma nova linha
no arquivo de transferência
// Registro Tipo 1
WriteLn(ArqTransf,
// Tipo
'2' +
// Codigo
PreencherStr(ClientDataSet.FieldByName('Codigo').AsString,
'
', 13, False) +
// Descr
PreencherStr(ClientDataSet.FieldByName('Descr').AsString,
'
', 50, False) +
// Valor
PreencherStr(RemoverChar(Format('%1.2f', [
ClientDataSet.FieldByName('Valor').AsCurrency]),
DecimalSeparator), '0', 15, True) +
// Brancos
PreencherStr(' ', ' ', 111, False) +
// Linha
PreencherStr(IntToStr(Lin),
'0', 5, True));
end;
end;
// Pula para o
próximo registro da tabela atual
ClientDataSet.Next;
//
Incrementa o TProgressBar
PBarGerar.Position :=
PBarGerar.Position + 1;
// Delay apenas
para mostrar a evolução do TProgressBar
// pois os arquivos são muito
pequenos e sem ele não veriamos
// essa evolução. Sua remoção não causará efeito algum
// ao resultado final do arquivo de
transferência
Sleep(100);
end;
end;
// Incrementando o contador de linhas
Inc(Lin);
// Incluindo uma nova linha no arquivo de
transferência
// Registro Tipo 9
WriteLn(ArqTransf,
// Tipo
'9' +
// Reg1
PreencherStr(IntToStr(Reg1), '0', 5, True) +
// Reg2
PreencherStr(IntToStr(Reg2),
'0', 5, True)
+
// Brancos
PreencherStr(' ',
' ', 179,
False) +
// Linha
PreencherStr(IntToStr(Lin), '0', 5, True));
// Fechando o arquivo de transferência
CloseFile(ArqTransf);
ShowMessage('Arquivo
gerado');
end;
|
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Transferência de dados através de
arquivos .txt - Parte III
Iniciando um novo projeto para
transmitir os dados
Criaremos um novo projeto para a
geração do arquivo de transferência, será um programa bem simples, pois ficará
mais fácil a colocação da rotina de geração dentro de um projeto, fazendo-se apenas
algumas poucas modificações.
Crie um
projeto no Delphi, no formulário mude as propriedades:
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Transferência de dados através de
arquivos .txt - Parte II
Layout
Agora que já
temos informações a serem transferidas, é necessária a elaboração de algumas
regras para gerar o arquivo texto. Essas
regras, que de agora por diante chamaremos apenas de layout, tem que ser compreendida pelos dois aplicativos(o que gerou
o arquivo e que irá receber).
Sendo assim
vamos criar nosso layout.
1.
Regras de formatação de campos
1.1.
Campos numéricos (Tipo N) fracionados deverão
ser preenchidos por completo, sem nenhum tipo de sinal, sem vírgula e pontos,
alinhado a direita e com suas posições a esquerda preenchidas por zeros:
Ex1: R$ 1.050,55 com
tamanho 15,2(13 caracteres da parte inteira e 2 da decimal) no layout deverá
aparecer 000000000105055
Ex2: R$ 78,00 com tamanho
15,2(13 caracteres da parte inteira e 2 da decimal) no layout deverá aparecer 000000000007800
1.2.
Campos inteiros (Tipo I) serão similares aos
campos numéricos fracionados, apenas não utilizando as casas decimais.
1.3.
Campos com datas (Tipo D) tem que estar no
formato AAAAMMDD:
Ex1: 31/12/2005 tem que ser
informado 20051231
Ex2: 01/02/2006 tem que ser
informado 20060201
1.4.
Campos com tempo (Tipo T) tem que estar no
formato HHMMSS:
Ex1: 10:30h tem que ser informado
103000
Ex2: 13:25:55h tem que ser
informado 132555
1.5.
Campos alfanuméricos (Tipo A) serão alinhados a
esquerda com espaço em branco a direita até ser atingido seu tamanho máximo:
Ex1: José da Silva com
tamanho 50 deverá “José da Silva ” – sem as
aspas
Ex2: Celular XR-60 com
tamanho 50 deverá aparecer “Celular XR-60 ” – sem as
aspas
2.
Regras para tipos de registros
2.1.
Todos os registros deverão ter obrigatoriamente 195
posições.
2.2.
O primeiro dígito indicará o tipo de registro que
contém na linha e o cinco últimos a posição do registro no arquivo.
Ex1: “100001111.111.111-11Jose da
Silva
Rua da Flores, 123 Romeirao Juazeiro do Norte CE1970123100002” – O primeiro dígito
é o número 1 o que indica que é um Registro Tipo 1, os cinco últimos números
são 00002 informando que o registro está na segunda linha do arquivo
Ex2: “21234567890123Telefone
XT-72 000000000008399
00006” - O primeiro dígito é o
número 2 indicando que é um Registro Tipo 2, os cinco últimos números
são 00006 informando que o registro está na sexta linha do arquivo
2.3.
O registro deverá ser finalizado com carriage return/line feed (CR/LF).
2.4.
O arquivo deverá iniciar obrigatoriamente com o Registro
Tipo 0 e ser finalizado com o Registro Tipo 9.
2.5.
O arquivo só poderá ter apenas um Registro Tipo 0
e um Registro Tipo 9, os Registro Tipo 1 e Registro Tipo 2
pode aparece nenhuma ou varias vezes por arquivo.
3.
Descritiva dos registros
3.1.
Registro Tipo 0
3.1.1. Ocorre
uma vez no arquivo, deve ser o primeira registro. Inicialização do arquivo. Registro obrigatório.
|
Campo
|
Descritiva
|
Tamanho
|
Tipo
|
Pos. Inic.
|
Pos. Final
|
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Transferência de dados através de arquivos .txt - Parte I
Introdução
Um
problema encontrado por desenvolvedores é a transferência de dados entre
empresas parceiras (Ex.: Pedidos, tabelas de preço, cadastro de cliente, etc)
ou entre empresas comerciais e bancos (Ex.: Arquivos de remessa e retorno de
valores).
Embora os
arquivos XML sejam utilizados pelos sistemas atuais (Ex.: SNGPC/ANVISA, NF-e) para
resolver este problema, existem sistemas legados (Ex.: CNAB/FEBRABAN) que ainda
utilizam a geração de arquivos texto seguindo um layout pré-definido por uma ou
ambas as partes.
Este artigo
não tem a intenção de definir qual a melhor solução, e sim, mostrar como
podemos trabalhar com arquivos texto neste contexto.
Tabelas utilizadas neste artigo para Transmissão
e Recebimentos
Crie um banco
de dados com o nome ClubeDelphi_Transf.fdb.
Neste artigo foi utilizado o Firebrid 2.0, mas fique a vontade para utilizada o
SGBD da sua preferência.
Tabela Cliente
Criando o gerador utilizado
pela tabela cliente
create generator Gen_Cliente;
Obs1:
Criamos esse gerador para acumular o último código usado pelo “Trigger”(Veja mais a frente) no momento
de incluir um novo cliente.
Criando a tabela cliente
create table Cliente(
Codigo integer not null,
CPF char(14) not null,
Nome
varchar(50) not null,
Ender varchar(50),
Bairro varchar(30),
Cidade varchar(30),
UF char(2),
DtNasc date
);
Obs2:
Usamos dois campos para alfanumérico, o varchar
e o char. A diferença entre os dois é
bem simples. Um campo varchar(50) está indicando a quantidade
máxima de caracteres, mas caso você use apenas um caractere, as outras quarenta
e nove posições serão “desprezadas”. Já
um campo char(14) quer dizer que se
você incluir apenas um caractere, as outras trezes posições serão preenchidas com
espaço.
Obs3:
Após a definição do tipo dos três primeiros campos aparece “not null”. Essa instrução informa ao Firebird que é
obrigatório entrar com um valor nos mesmos para cada registro informado, ou
seja, não é permitido deixá-los em branco.
Criando a chave primaria da
tabela cliente
alter table Cliente
add primary
key(Codigo);
Obs4:
Nesse exemplo criamos uma chave primaria simples. Caso fossemos criar uma chave composta
usando, por exemplo, os campo Codigo e CPF bastaríamos, na linha, ter escrito “primary key(Codigo, CPF)”.
Obs5:
Embora seja permitido criar a chave primeira junto com a criação da tabela,
nesse exemplo criamos a chave primeira depois de termos criado a tabela. Para criarmos junto com a tabela só seria
preciso colocar uma virgula após a definição do campo “DtNasc” e incluir “primary
key(Codigo)” como mostrado abaixo:
create table
Cliente(
Codigo integer not null,
CPF char(14) not null,
Nome
varchar(50) not null,
Ender
varchar(50),
Bairro
varchar(30),
Cidade
varchar(30),
UF char(2),
DtNasc date,
primary key (Codigo)
);
Criando o trigger utilizado
pela tabela cliente
set term^;
create trigger
TCliente for Cliente
active before insert
position 0
as begin
new.Codigo = gen_id(Gen_Cliente, 1);
end;
Obs6:
O Firebird não possui um campo do tipo Autoincremente, mas podemos driblar isso
com o uso do “Trigger” como mostrado
acima.
Obs7:
A linha “create trigger TCliente for
Cliente” manda o SGBD criar um “Trigger”
com o nome “TCliente” para a tabela “Cliente”.
Obs8:
A linha “active before insert” pede
que esse “Trigger” seja acionado
antes de se inserir um novo registro. O
comando “position 0” informa que caso
exista mais de um “active before insert”,
esse será o primeiro a ser executado. Caso
existisse um segundo “active before
insert” o comando irá aparecer “position
1”.
Obs9:
O “begin... end” informa o inicio e o
fim de um bloco de código.
Obs10:
A linha “new.Codigo = gen_id(Gen_Cliente,
1);” utilize a função “gen_id( )”
para incrementar em 1(um) o gerador “Gen_Cliente”(criado
anteriormente) e jogar esse valor no campo “Codigo”
do novo registro.
Tabela Produto
Criando a tabela produto
create table Produto(
Codigo varchar(13) not
null,
Descr varchar(50) not null,
Valor numeric(15, 2) not null
);
Criando a chave primaria da
tabela produto
alter table Produto
add primary
key(Codigo);
Após
ter criado as tabelas, trigger e generators, faça uma cópia da base e renomeia
para ClubeDelphi_Rec.fdb, essa base
será usada para receber os dados gerados.
Vale ressaltar que embora a base de recebimento seja igual a de
transferência(nome das tabelas, campos, tipos e tamanhos), nem sempre isso
acontece na vida real.
Incluindo Dados na Base de Transmissão
Vamos
agora alimentar a base ClubeDelphi_Transf.fdb
com alguns registros como mostrado a seguir:
Incluindo registros na tabela
cliente
insert into Cliente(CPF, Nome, Ender, Bairro, Cidade, UF, DtNasc)
values ('111.111.111-11', 'Jose da Silva', 'Rua da Flores, 123',
'Romeirao', 'Juazeiro do Norte', 'CE', '12/31/1970');
commit;
insert into Cliente(CPF, Nome, Ender, Bairro, Cidade, UF, DtNasc)
values ('222.222.222-22', 'Maria da Silva', 'Rua Sao Pedro, 234',
'Centro', 'Juazeiro do Norte', 'CE', '02/28/1975');
commit;
insert into Cliente(CPF, Nome, Ender, Bairro, Cidade, UF, DtNasc)
values ('333.333.333-33', 'Joao Carvalho', 'Rua Sao Jose, 345',
'Salesianos', 'Juazeiro do Norte', 'CE', '10/01/1980');
commit;
insert into Cliente(CPF, Nome, Ender, Bairro, Cidade, UF, DtNasc)
values ('444.444.444-44', 'Joana Alencar', 'Rua Padre Cicero, 456',
'Matriz', 'Juazeiro do Norte', 'CE', '01/10/1985');
commit;
Obs11:
Não foi informado o campo “Codigo” pois o mesmo será gerado pelo trigger da tabela.
Obs12:
Note que a data está no formato MM/DD/AAAA, este é o formato aceito pelo
comando insert para data quando se
utiliza a barra “/”.
Obs13:
Como esses dados são apenas para questões didáticas, os CPF informados são
inválidos.
Incluindo registros na tabela
produto
insert into Produto(Codigo, Descr, Valor)
values ('1234567890123', 'Telefone XT-72', 83.99);
commit;
insert into Produto(Codigo, Descr, Valor)
values
('2345678901234', 'Celular RM-50', 390.5);
commit;
insert into Produto(Codigo, Descr, Valor)
values ('3456789012345', 'Carregador para celular MP-65', 78);
commit;
insert into Produto(Codigo, Descr, Valor)
values ('4567890123456', 'Bateria para celular FL-900', 102.05);
commit;
insert into Produto(Codigo, Descr, Valor)
values ('5678901234567', 'Celular XR-60', 1050.55);
commit;
Obs14:
Verifique que usamos o sinal de ponto no lugar da vírgula como símbolo decimal e
que o símbolo de agrupamento de dígitos inexiste.
|
Artigo criado por http://www.cassic.com.br/
|
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Introdução ao comando SELECT da SQL - Parte III
Para Programadores
Função avg
Retorna
a
média aritmética da coluna informada.
Sintaxe
:
select avg(Coluna)
[as New_Coluna] from Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna
[as New_Coluna] Nome
da coluna de retorno [Opcional]
Exemplo
:
select
avg(Salario)
as Media from Funcion
Resultado
Media
1071,42
Função max
Retorna
o
maior valor da coluna informada.
Sintaxe
:
select max(Coluna)
[as New_Coluna] from Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna
[as New_Coluna] Nome
da coluna de retorno [Opcional]
Exemplo
:
select
max(Codigo)
as Maior_Codigo from Funcion
Resultado
Maior_Codigo
7
Função min
Retorna
o
menor valor da coluna informada.
Sintaxe
:
select min(Coluna)
[as New_Coluna] from Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna
[as New_Coluna] Nome
da coluna de retorno [Opcional]
Exemplo
:
select
min(Codigo)
as Menor_Codigo from Funcion
Resultado
Menor_Codigo
1
Função sum
Retorna
o
somatório da coluna informada.
Sintaxe
:
select sum(Coluna)
[as New_Coluna] from Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna
[as New_Coluna] Nome
da coluna de retorno [Opcional]
Exemplo
:
select
sum(Salario)
as Total from Funcion
Resultado
Total
7500
Função count
Retorna
a
quantidade de registros existentes.
Sintaxe :
select count(Coluna) [as
New_Coluna] from Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna – Pode ser substituído pelo “*” (asterisco)
[as
New_Coluna] Nome
da coluna de retorno [Opcional]
Exemplo
:
select count(Codigo) as QtTotal from
Funcion
Resultado
QtTotal
7
Função distinct
Usamos
distinct para evitar que um determinado
valor seja repetido em uma consulta.
Sintaxe
:
select distinct(Coluna)
from Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna
Exemplo
:
select distinct(Cliente) from Pedido
Resultado
Cliente
2
4
5
Cláusula group by
Quando
queremos
agrupar o resultado de uma ou mais funções com os dados de uma ou mais
colunas devemos usar o group by.
Sintaxe
:
select Função,
Coluna from Tabela
group
by Coluna
Tabela
Nome
da tabela
Função
Função
a ser unida com a coluna
Coluna
Nome
de uma coluna
Exemplo
:
select
sum(Valor)
as Soma, Cliente from Pedido
group
by
Cliente
Resultado
Soma Cliente
3500 2
2000 4
2500 5
Cláusula having
Having é utilizada para filtrar o
resultado de uma função de agrupamento juntamente com a cláusula group by.
Sintaxe
:
select Função,
Coluna from Tabela
group
by Coluna
having
Condição
Tabela Nome
da
tabela
Função Função
a
ser unida com a coluna
Coluna Nome
de
uma coluna
Condição Cria
condição
para filtrar o resultado da função.
Exemplo
:
select
sum(Valor)
as Soma, Cliente from Pedido
group
by
Cliente
having
sum(Valor)
>= 2500
Resultado
Soma Cliente
3500 2
2500 5
Operador de concatenação ( || )
Para
combinar
cadeias de caracteres utilizamos o operador ||.
Sintaxe
:
select Coluna
|| [String ||] Coluna [as
New_Coluna]
from Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna
String
String
para separar as colunas [Opcional]
[as New_Coluna] Nome
da coluna de retorno [Opcional]
Exemplo
:
select
Nome ||
' ' || Sobrenome as Nome_Completo from Cliente
Resultado
Nome_Completo
Francisco
Silva
José Lima
Maria Silva
Adriana
Ferreira
João Oliveira
Eduarda Souza
Operadores aritméticos
Podemos
fazer
cálculos com operações aritméticas em qualquer declaração de cláusula
SQL, com
exceção para a cláusula from.
Sintaxe
:
select Coluna,
Operação_Aritmética [as New_Coluna] from
Tabela
Tabela
Nome
da tabela
Coluna
Nome
de uma coluna
Operação_Aritmética Operação
aritmética desejada
[as New_Coluna] Nome
da coluna de retorno [Opcional]
Operadores aritméticos “+” (Adição)
Exemplo
:
select
Nome,
(Salario + 200) as Salario_Atual from Funcion
Resultado
Nome Salario_Atual
Tadeu 1700
Ylane 1400
Julian 1200
Ewerton 1200
João 1000
Geraldo 1700
Maria 700
Operadores aritméticos “-” (Subtração)
Exemplo
:
select
Nome,
(Salario - 200) as Salario_Atual from Funcion
Resultado
Nome Salario_Atual
Tadeu 1300
Ylane 1000
Julian 800
Ewerton
800
João 600
Geraldo 1300
Maria 300
Operadores aritméticos “*” (Multiplicação)
Exemplo
:
select
Nome,
(Salario * 1.5) as Salario_Atual from Funcion
Resultado
Nome Salario_Atual
Tadeu 2250
Ylane 1800
Julian 1500
Ewerton 1500
João 1200
Geraldo 2250
Maria 750
Operadores aritméticos “/” (Divisão)
Exemplo
:
select
Nome,
(Salario / 2) as Salario_Quinzena from Funcion
Resultado
Nome Salario_Quinzena
Tadeu 750
Ylane 600
Julian 500
Ewerton 500
João 400
Geraldo 750
Maria 250
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Recursos
do Code Editor
O Code Editor além das sintaxes coloridas oferece outros recursos
tais como:
- Class
Completion : Após declarar um método, usamos esse recurso para fornecer
a definição do mesmo na seção Implementation
da Unit, o inverso também pode ser
feito, ou seja, após definir o método na seção Implementation o Class
Completion cria a declaração. Outra
opção fornecida por esse recurso é o complemento da definição de uma
propriedade.
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Conteúdo dos arquivos PAS, DFM e DPR
Conteúdo do arquivo UPrincipal.pas
|
Declaração
da unit
|
unit UPrincipal;
|
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
|
Padrões
de Codificação
Por que usar um padrão de codificação?
A organização do código fonte
facilita os processos de desenvolvimento, retirada de bugs, atividades de
validação e manutenção. O uso de um
padrão de codificação também aumenta a produtividade num projeto, uma vez que a
comunicação dentro da equipe de desenvolvimento fica mais fácil, mas vale ressaltar que partes desses padrões são
vistas, algumas vezes, como sugestões por empresas que adotam seus próprios
padrões.
-
Comentários : Usamos as chaves - { }- para iniciar e terminar um
comentário com mais de uma linha, esse tipo de comentário é comum para se
informar dados gerais e específicos de Unit
e métodos, vindo no seu inicio. Dentro
dos comentários com chaves não devemos usar asteriscos, símbolos ou caracteres
especiais. Outro tipo de comentário usado
é a barra de data digitada duplamente - // - neste caso o comentário se ressume
a uma linha, devendo ser dado um espaço após a segunda barra para começar o
texto desejado.
- Indentação
: Ato de separar os níveis de codificação por espaços em branco. No caso da Linguagem Delphi a indentação deve ter dois espaços, não se podendo
usar tabulação.
...
Exibição do post interrompida. Para ler conteúdo completo, clique aqui
|
|
|
| |
|