sexta-feira, 26 de fevereiro de 2016

Imagem no Quickreport a Partir de Um Arquivo

Há pouco tempo precisei configurar um sistema de uma outra pessoa para alterar as logos que existiam nos relatórios. As logos do sistema eram todas fixas, sem configuração em nenhum lugar. A maneira mais fácil que encontrei foi de deixar um arquivo de imagem com tamanho e nome padrão, e alterar todos relatórios para que pegassem esta imagem na pasta do executável.
Esta operação é bastante simples:
No evento "Before Print" do quickreport é só adicionar a linha:

 // Carrega a imagem
 if FileExists(ExtractFilePath(ParamStr(0))+'logo.jpg') then
 begin
   QRImage2.Picture.LoadFromFile(ExtractFilePath(ParamStr(0))+'logo.jpg');
 end;
 


Basicamente verifico se existe o arquivo "logo.jpg" na pasta em que está o executável "ExtractFilePath(ParamStr(0))". Se o arquivo não existir, nada acontece.
 Isto é muito útil, veja que pode ser colocada uma logo padrão na pasta do executável, apenas trocando a logo, ficam todos os relatórios no padrão.

quarta-feira, 8 de setembro de 2010

Lendo Configurações de Conexão a Partir de Arquivo Texto

Na verdade isso é mais uma dica do que um artigo. Vamos abrir um arquivo texto com configurações, ler estas configurações e aproveitá-las para a conexão com o banco.
Existem também componentes prontos para isso, porém eu tento sempre usar o mínimo de componentes externos nos meus sistemas. Outra coisa também que se utiliza é o registro do Windows ao invés de arquivo texto, mas eu ainda prefiro a simplicidade de abrir um arquivo texto.
O código fonte é bastante simples e fácil de entender, eu sempre deixo esse código no evendo Before Connect do componente de conexão com o banco.
procedure TFrmPrincipal.ConexaoBeforeConnect(Sender: TObject);
var f:TextFile;
    h,p,base:String;
begin
  // Verifica se o arquivo com
  // host do db existe
  AssignFile(f,'conexao.ini');
  if not FileExists('conexao.ini') then
  begin
    { Se o arquivo de configuração não existir, o
      sistema vai criá-lo com o servidor 192.168.0.1,
      porta 5432-porta padrão do PostgreSQL e com o banco
      chamado database1
    }
    try
      Rewrite(f);
      WriteLn(f,'host=192.168.0.1'); 
      WriteLn(f,'porta=5432');
      WriteLn(f,'base=database1');
    finally
      CloseFile(f);
    end;
  end;
  try
    Reset(f);  // Abre o arquivo
    { Aqui o sistema está lendo linha por linha,
      a primeira linha fica o hostname ou ip do servidor,
      na segunda a porta e na última o nome da base. 
      No arquivo esses dados têm que estar exatamente 
      nesta ordem.
      O nome do meu componente de conexão é "Conexao"
      e estou usando o Zeos. 
      Outra coisa importante, os dados são lidos 
      considerando que estão na posição de coluna 
      correta, ex.: o host na coluna 6
    }
    Readln(f, h);
    Conexao.HostName:=Copy(h,6,Length(h)-5);
    Readln(f, p);
    Conexao.Port:=StrToInt(Copy(p,7,Length(p)-6));
    Readln(f, base);
    Conexao.Database:=Copy(base,6,Length(base)-5);
    CloseFile(f);
  except
    on e: Exception do
    begin
      { Caso não consiga abrir o arquivo, dá a mensagem 
        de erro e fecha o sistema}
      ShowMessage('Erro ao abrir arquivo de '+
                  'configuração. Erro:'+#10+#13+
                   e.Message);
      Application.Terminate;
    end;
  end;
end;

quarta-feira, 31 de março de 2010

Lendo uma NFE - Nota Fiscal Eletrônica (XML) no Delphi 2006.

Este é um artigo que gostei muito de fazer. O Delphi 2006 tem algumas facilidades para mexer com arquivos XML que tornam o trabalho muito fácil, e porque não dizer, divertido. Coloquei no título NFE, mas serve para qualquer XML que você queira importar.
Agora com a demanda de arquivos XML rodando por aí, seja na área fiscal, contábil, e até na área de saúde, ter uma opção para abrir e mapear arquivos XML é imprescindível.
Eu vou mostrar como mapear e abrir um XML no Delphi como se fosse um DataSet. Ou seja, você poderá navegar no arquivo, ver ele em DBEdit e em DBGrid. Depois disso a importação é brincadeira de criança.
O Delphi 2006, e posteriores (não sei exatamente em que versão saiu) possui uma ferramenta chamada XML Mapper, que fica em Tools / XML Mapper.Veja na imagem:

Clique na opção File / Open e abra um arquivo XML, no meu caso abri uma nota fiscal eletrônica. A estrutura do XML vai aparecer no lado esquerdo, clique com o botão direito em algum elemento do XML e use a opção Select All. No grid do meio vão aparecer os elementos do XML. Depois no menu, vá na opção Create / Datapacket from XML. Isso irá preencher o lado direito com as tags do XML e seus respectivos tipos.

Clique no botão “Create and Test Transformation”. O programa abrirá uma DBGrid, com os dados do arquivo XML, tendo como campos as Tags. Isso dá uma prévia do que teremos como resultado final. Feche a tela de teste e clique com o botão direito na tela do meio, e use a opção “Save Transformation”. Isso vai gerar um arquivo XTR, que funciona como um “mapa” para o Delphi abrir um XML como dados.

Para finalizar, vamos fazer isso funcionar. Crie um novo projeto no Delphi, e adicione ao Form1, um TDataSource, um TClientDataSet, um TXMLTransformProvider e um TDBGrid para vermos os dados. Na propriedade DataSet do DataSource1, coloque o ClientDataSet1. Na propriedade ProviderName do ClientDataSet1, coloque XMLTransformProvider1. Na propriedade DataSource do DBGrid1, coloque DataSource1. Clique no + da propriedade TransformRead, do XMLTransformProvider1, e depois em TransformationFile, escolha o arquivo XTR que você criou anteriormente. E em XMLDataFile escolha um arquivo XML, que no casso desse exemplo é uma nota eletrônica. No ClientDataSet mude Active para True e os dados devem aparecer no grid, conforme a figura.

Concluindo, existe uma facilidade muito grande em se trabalhar com arquivos XML no Delphi. E isso vai se tornando cada vez mais útil visto o aumento de uso desse tipo de comunicação.


sexta-feira, 26 de março de 2010

Delphi e Lazarus

Venho acompanhando o Lazarus desde que o projeto surgiu, há muitos anos atrás. Sempre fui entusiasta do software livre, e como programador Clipper, que depois migrou pro Delphi, não podia deixar de procurar algo "livre" para fazer meus projetos.
O Lazarus surgiu como uma esperança para isso, porém lá no começo, onde não tinha quase nada de componentes, a IDE completamente instável, era totalmente impossível fazer qualquer programa no Lazarus, a não ser que fosse muito simples. De tempos em tempos me lembro do Lazarus e baixo ele para ver como está e vejo que está em constante evolução.
Ontem baixei o Lazarus e vi que está bem mais estável, a IDE entra rápido e tem uma gama de componentes considerável. A comparação com o Delphi é inevitável. Eu uso o Delphi 2006, mas eu teria que comparar o Lazarus com o Delphi 5 ou 6, pelo número de recursos. Uma coisa que ainda me chateia no Lazarus desde o começo é o fato dos executáveis ficarem gigantes. Um form mais um grid e conexão com firebird fizeram um executável de 21MB. Enquanto isso no Delphi, mesmo sendo 2006, normalmente não chega a 1MB.
Um ponto muito importante me chamou a atenção no Lazarus, que não tinha antes: herança visual. Isso era uma das coisas mais importantes que me impedia de migrar para o Lazarus. Apesar de tudo, me decepcionei quando vi que a herança não chega a ser igual a do Delphi, um form herdado, até fica com o mesmo visual e componentes do seu antecessor, mas se você muda algo na IDE, não altera direto no form filho. Depois que fechei o projeto e abri novamente aí sim foi efetivada a alteração.
Concluindo, achei o Lazarus muito mais maduro do que um dia já foi, mas ainda vou ter que continuar com o meu Delphi, um dia espero que possa pegar todos os meus projetos Delphi e compilá-los no Lazarus sem complicações. Mas esse é o meu caso em específico, pra quem vai começar um projeto do zero, acredito que seja uma ótima idéia avaliar com carinho essa ótima ferramenta de desenvolvimento que é o Lazarus!

quarta-feira, 18 de novembro de 2009

Abrindo uma planilha excel como dataset

Apesar de parecer não muito sensato usar excel como tabela, esse artigo é muito útil. No dia a dia, diversas vezes recebi planilhas excel enviadas por clientes e fornecedores da empresa, com dados que precisavam ser conciliados ou comparados com informações do banco.
Mas então, o que fazer ? Eu criava uma tabela no banco e importava a planilha,. Isso não é tão demorado, mas as vezes é complicado, você não quer ficar criando tabelas no teu banco, principalmente se precisa de poucas informações pra cruzar com a planilha.
Outro fato importante, é poder automatizar isso para o usuário, ele mesmo abre a planilha, e com alguns ajustes poderia cruzar informações com o seu sistema.
Fiz o projeto no delphi 2006 mas provavelmente funciona nas outras versões. Este projeto vai ter um único form principal, onde você poderá abrir uma planilha excel e ver e alterar os dados, também terá um combo box para você navegar entre as planilhas do arquivo.
Então mãos a obra:
1. Crie um novo projeto VCL Forms
2. Adicione ao Form1:
- TPanel
Dentro do Panel1:
- TADOConnection
- DataSource
- TADOQuery
- TButton
- TOpenDialog
- TComboBox
Fora do Panel1
- TDBGrid

Deixe o Panel1 com align=alTop
Deixe o DBGrid1 com align=alClient
No TADOConnection1, mude LoginPrompt para: False
e a propriedade provider para: Microsoft.Jet.OLEDB.4.0
Na propriedade DataSource do DBGrid1 coloque: DataSource1
Na propriedade DataSet do DataSource1 coloque: ADOQuery1
e no ADOQuery1 coloque na propriedade Connection: ADOConnection1

Ficará como na figura abaixo:



Vamos criar a procedure que abre o dataset e faz o tamanho das colunas ficar com o tamanho máximo de 450:
No código fonte, na parte das declarações, adicione uma linha em public, com a declaração da procedure:

procedure AbrePlan(Plan:String);

Vai ficar assim:Agora o código da procedure:

procedure TForm1.AbrePlan(Plan:String);
var i:Integer;
begin
ADOQuery1.SQL.Clear;
ADOQuery1.SQL.Add('SELECT * FROM ['+Plan+'];');
ADOQuery1.Open;
for i := 0 to DBGrid1.Columns.Count - 1 do
begin
if DBGrid1.Columns[i].Width>450 then
DBGrid1.Columns[i].Width:=450
end;
end;



Agora, clique duas vezes no Button1 e cole o código abaixo:

if OpenDialog1.Execute then
begin
ADOQuery1.Close;
AdoConnection1.Connected:=False;
AdoConnection1.ConnectionString:=
'Provider=Microsoft.Jet.OLEDB.4.0;'+
'Data Source='+OpenDialog1.FileName+ ';'+
'Extended Properties=Excel 8.0;';
AdoConnection1.Open;
AdoConnection1.GetTableNames(ComboBox1.Items,True);
ComboBox1.ItemIndex:=0;
AbrePlan(ComboBox1.Text);
end;
E por fim, no evento OnChange do ComboBox1:

AbrePlan(ComboBox1.Text);

Pronto, esse programa basicamente abre a planilha, deixa todas as colunas com o tamanho máximo de 450 e o combo box escolhe em qual pasta você vai trabalhar. Dá pra inclusive fazer atualização de dados. Até a próxima.