sábado, 30 de abril de 2011

Lendo e gravando arquivos de texto

Existem vários métodos em Delphi para gravar arquivos texto a partir de informações gravadas em bases de dados ou para ler arquivos texto e armazená-los em bases de dados. Esta dica apresenta um destes métodos: o uso de TextFiles.

TextFile é um tipo de dado pré-definido no Delphi e corresponde ao tipo Text do Turbo Pascal e do Object Pascal.

Inicialmente para acessar um arquivo de texto, você precisa definir uma variável tipo TextFile, no local que você achar mais apropriado, da seguinte forma:

var arq: TextFile;
Vamos precisar também de uma variável tipo string para armazenar cada linha lida do arquivo:

var linha: String;
Antes de se iniciar a leitura do arquivo, precisamos associar a variavel TextFile com um arquivo fisicamente armazenado no disco:

AssignFile ( arq, 'C:\AUTOEXEC.BAT' );
Reset ( arq );
A rotina AssignFile faz a associação enquanto Reset abre efetivamente o arquivo para leitura. AssignFile corresponde à Assign do Turbo Pascal. Em seguida é necessário fazer uma leitura ao arquivo, para isto utilizaremos a procedure ReadLn:

ReadLn ( arq, linha );
O comando acima lê apenas uma linha de cada vez, assim precisamos de um loop para efetuar várias leituras até que o arquivo acabe. Para verificar o fim do arquivo, utilizaremos a função Eof:

while not Eof ( arq ) do
Agora uma rotina quase completa para fazer a leitura de um arquivo texto. Esta rotina recebe como parâmetro o nome do arquivo que será lido:

procedure percorreArquivoTexto ( nomeDoArquivo: String );
var arq: TextFile;
linha: String;
begin
AssignFile ( arq, nomeDoArquivo );
Reset ( arq );
ReadLn ( arq, linha );
while not Eof ( arq ) do
begin
{ Processe a linha lida aqui. }
{ Para particionar a linha lida em pedaços, use a função Copy. }
ReadLn ( arq, linha );
end;
CloseFile ( arq );
end;
E também uma rotina quase completa para gravação de um arquivo texto. Esta rotina recebe como parâmetro o nome do arquivo que será gravado e uma tabela (TTable) de onde os dados serão lidos:

procedure gravaArquivoTexto ( nomeDoArquivo: String; tabela: TTable );
var arq: TextFile;
linha: String;
begin
AssignFile ( arq, nomeDoArquivo );
Rewrite ( arq );
tabela.First;
while not tabela.Eof do
begin
Write ( arq, AjustaStr ( tabela.FieldByName ( 'Nome' ).AsString, 30 ) );
Write ( arq, FormatFloat ( '00000000.00', tabela.FieldByName ( 'Salario' ).AsFloat ) );
WriteLn ( arq );
tabela.Next;
end;
CloseFile ( arq );
end;
Note nesta segunda rotina, a substituição de Reset por Rewrite logo após o AssignFile. Rewrite abre o arquivo para escrita, destruindo tudo que houver lá anteriormente .

Note também o uso de Write e WriteLn para gravar dados no arquivo texto.

Finalmente note o uso de AjustaStr e FormatFloat para garantir que campos string e numericos sejam gravados com um número fixo de caracteres. FormatFloat é uma rotina do próprio Delphi enquanto AjustaStr está definida abaixo:

function AjustaStr ( str: String; tam: Integer ): String;
begin
while Length ( str ) < tam do
str := str + ' ';
if Length ( str ) > tam then
str := Copy ( str, 1, tam );
Result := str;
end;
O uso da função AjustaStr é fundamental quando você estiver gravando arquivos texto com registros de tamanho fixo a partir de bases de dados Paradox que usualmente não preenchem campos string com espaços no final.

Exibindo as propriedades do arquivo

A dica abaixo apresenta o código de implementação para exibir na tela uma janela padrão Windows de propriedades do arquivo.

Para implementar este procedimento é necessário acrescentar a unit ShellAPI.As propriedades do arquivo são armazenadas numa estrutura chamada TShellExecuteInfo, que corresponde a um registro com os campos: tamanho do arquivo (cbSize), atributos (fMask), nome (lpFile) , shell (lpVerb) e modo de apresentação da janela (nShow).O primeiro passo do procedimento é zerar todas a propriedades da Shell ( FillChar(S,SizeOf(S),0) ), segundo passo é atualizar estas propriedades (With S do ) em relação ao arquivo indicado (Arq :String) e o terceiro passo é abrir a janela de propriedades com os valores atualizados (ShellExecuteEx(@S)).

Código Completo:

Procedure Propriedades(Arq:String);
Var
s:TShellExecuteInfo;
Begin
FillChar(S,SizeOf(S),0);
With S do Begin
cbSize := SizeOf(S);
fMask := SEE_MASK_FLAG_NO_UI or SEE_MASK_INVOKEIDLIST or SEE_MASK_NOCLOSEPROCESS;
wnd := Handle;
lpVerb := 'properties';
lpFile := Pchar(Arq);
nShow := sw_ShowNormal;
End;
ShellExecuteEx(@S);
End;

Criando um diretório

Para criar um diretório você precisa usar a função ForceDirectories, o exemplo a baixo testa se não existe um diretório e cria o diretório apartir de uma variável string testando se o diretório já existe

Unit
 
FileCtrl
 
procedure TForm1.Button1Click(Sender: TObject);
var
  Dir: string;
begin
Dir := 'C:\APPS\SALES\LOCAL';
 
if not DirectoryExists(Dir) then
  ForceDirectories(Dir);
  Label1.Caption := Dir + ' foi criado';
end;

terça-feira, 26 de abril de 2011

Colocar uma barra de progresso na inicialização do sistema

É bem simples, trata-se de abrir por código todas as tabelas na entrada do programa, portanto deixe todas as tabelas fechadas no datamodule.

procedure DataModule.OnCreate;
var Tabela, i: Integer;
begin
  Tabela := 0;
  for I := 0 to ComponentCount -1 do
    if Components[I] is TTable then
      with TTable(Components[I]) do
        if (Tag = 9) and not Active then  // Tag = 9 identifica as tabelas à serem abertas
         try
           Inc(Tabela);  // contador das tabelas q já foram abertas.
           lblInfo.Caption := Format('Abrindo as Tabelas (%d/%d)', [Tabela, Total]);
           {aqui, informo à uma label o andamento do processo, usei o formato totalTabelasAbertas/TotalàAbrir, pode-se trocar para porcentagem ou até usar o ProgressBar.}
           lblInfo.Refresh; // vital para atualizar a tela durante o processo.
           Application.ProcessMessages;
           Open;
        except
   Raise; // quem estiver a fim, pode-se colocar aqui uma verificação, se deu zebra e a zebra é indice corrompido, rodar rotina de recriação de indice da tabela.
end;

Alternando Bitmaps no Fundo de um Form.

Um leitor perguntou recentemente sobre imagens de fundo em Forms.... Apesar de já se ter escrito diversos artigos sobre este tópico, sua questão tinhas algumas novidades. Primeiramente, ele desejava que o fundo se alternasse periodicamente.
Essencialmente, a solução para isto seria a aplicação de outros artigos similares. Em primeiro lugar, para resolver a questão de se ter diversas imagens, os bitmaps devem ser carregados em um array quando o Form for criado. A mudança periódica da imagem s
Finalmente, para tratar do assunto "não leia as imagens do disco", recorremos aos resources. Um arquivo de resource é apenas um caminho para empacotar muito bem qualquer tipo de dados que será anexado ao executável durante o processo de Linkedição. Para o
BITMAP1 BITMAP IMAGE1.BMP
BITMAP2 BITMAP IMAGE2.BMP
BITMAP3 BITMAP IMAGE3.BMP
BITMAP4 BITMAP IMAGE4.BMP
BITMAP5 BITMAP IMAGE5.BMP
A primeira parte de cada linha é o identificador que você utilizará no código para capturar uma imagem em particular. A segunda parte é o tipo de resource (neste caso, bitmap). E a última parte é o nome do arquivo que deve ser utilizado para a imagem. Ist
{$R MYBMPS.RES}
Quando o executável está sendo linkeditado (um passo antes da compilação), o resource será automaticamente anexado ao executável. Para carregar as imagens do resource no array de bitmaps no programa, fiz simplesmente:
    for a := 1 to NumBmps do
    begin
       Bmps[a] := TBitmap.Create;
       Bmps[a].LoadFromResourceName(hInstance,'BITMAP'+IntToStr(a));
    end;
É basicamente isto... A seguir a listagem da Unit principal:
unit Unit1a;
interface
uses
    Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs,
    ExtCtrls, StdCtrls;
const
    NumBmps = 5;
type
    TForm1 = class(TForm)
        Timer1: TTimer;
        Edit1: TEdit;
        CheckBox1: TCheckBox;
        ListBox1: TListBox;
        procedure FormCreate(Sender: TObject);
        procedure FormDestroy(Sender: TObject);
        procedure FormPaint(Sender: TObject);
        procedure Timer1Timer(Sender: TObject);
    private
       Bmps : Array[1..NumBmps] of TBitmap;
       SelectedBmp : Integer;
    public
    { Public declarations }
    end;
var
    Form1: TForm1;
implementation
{$R *.DFM}
{$R MYBMPS.RES}
procedure TForm1.FormCreate(Sender: TObject);
var
    a : Integer;
begin
    for a := 1 to NumBmps do
    begin
        Bmps[a] := TBitmap.Create;
        Bmps[a].LoadFromResourceName(hInstance,'BITMAP'+IntToStr(a));
    end;
    SelectedBmp := 1;
end;
procedure TForm1.FormDestroy(Sender: TObject);
var
    a : Integer;
begin
    for a := 1 to NumBmps do Bmps[a].Free;
end;
procedure TForm1.FormPaint(Sender: TObject);
var
    x,y,w,h : Integer;
begin
    w := Bmps[SelectedBmp].Width;
    h := Bmps[SelectedBmp].Height;
    for x := 0 to (Width div w) do
        for y := 0 to (Height div h) do
            Canvas.Draw(x*w,y*h,Bmps[SelectedBmp]);
end;
procedure TForm1.Timer1Timer(Sender: TObject);
begin
    Inc(SelectedBmp);
    if SelectedBmp > NumBmps then SelectedBmp := 1;
    Paint;
end;end.

Técnicas de depuração em Delphi e Prevenção de Bug


Muitas vezes pegamos um sistema legado de outro programador para realizarmos implementação de novas funcionalidades ou corrigir eventuais "bugs". Neste caso você vai precisar depurá-lo para encontrar os "bugs". O Delphi oferece ótimas ferramentas de depuração e quando você sabe como usá-las, você vai economizar muito tempo para corrigir o "bug" e chegar no resultado desejado
Neste caso quero indicar um tutorial que encontrei e ajudou quando o assunto era depuração de programas.
Aqui está o conteúdo:

Project options - antes que você possa começar a utilizar as ferramentas depurador do Delphi, você tem que certificar-se de todas as configurações necessárias são definidas opções depurador .

Breakpoints - Quando pressionar a tecla F5 ou clicando na barra esquerda do seu editor você pode adicionar uma linha vermelha para a sua fonte. Esta linha de origem terão um ponto de interrupção. Ao executar o programa, a execução irá parar quando ele passa a linha de origem. Agora você pode seguir em sua origem, usando algumas teclas de função.

Call stack - a janela Call Stack exibe as chamadas de função que o trouxe para a sua localização atual no programa e os argumentos passados para cada chamada de função.

Local variables - essa janela vai mostrar todas as variáveis locais e o seu valor atual no atual função ou procedimento.

Watches - você adicionar um Watches para controlar os valores das variáveis do programa ou expressões como você passar por cima ou em código de rastreamento.

Idéias para criar os seus próprios recursos de depuração Prevenção Bug Try-Finally Gotchas Try-Except Gotchas

domingo, 17 de abril de 2011

Adicionando o sistema no menu de contexto do Windows Explorer


Aqui vai uma dica para adicionar um item ao menu de contexto do Windows Explorer, exibido ao clicarmos com o botão direito do mouse sobre uma pasta.

Quando o usuário clica com o botão direito sobre uma pasta no Windows Explorer (ou em um componente TShellTreeView) um menu de contexto é exibido. Entre os itens padrões é possível adicionar um para a sua própria aplicação. Quando o usuário clicar neste seu item, o programa será iniciado e o caminho daquele diretório será passado como parâmetro.

A procedure a seguir adiciona uma entrada no registro do Windows para "registrar o programa" como um comando válido no menu de contexto:

procedure EnsureShellFolderPopupItem(const itemName: string);
begin
  with TRegistry.Create do
  try
    RootKey := HKEY_CLASSES_ROOT;
    if OpenKey('Directory\shell', true) then
    begin
      if OpenKey(itemName+'\command', true) then
        WriteString('', '"'+Application.ExeName+'" "%1"');
    end;
  finally
    Free;
  end;
end;

Este código fará a adição de uma chave na seguinte forma:

HKEY_CLASSES_ROOT\Directory\shell\itemName

Onde itemName será passado por parâmetro à função (vide código abaixo) e que na verdade será o texto de exibição no menu de contexto. Seu valor será o caminho do programa e o %1, para indicar que a pasta clicada será enviada por parâmetro à aplicação:

;@="c:\...\Project1.exe" "%1" - Onde "c:\...\Project1.exe" é o local do seu executável.

Agora no evento onCreate do Form, façamos:

procedure TForm1.FormCreate(Sender: TObject);
begin
  //certifica que nosso item está no menu de contexto de diretórios
  //não é necessário chamar sempre, mas para testes está ok!
  EnsureShellFolderPopupItem('Processar com Meu Programa');

  //exibe qual a pasta que foi selecionada para processamento
  if ParamCount > 0 then
    ShowMessage('Pasta selecionada: ' + ParamStr(1))
  else
    ShowMessage('Sistema iniciado diretamente');
end;

Para testar, rode o programa pelo Delphi para que seja processada a procedure EnsureShellFolderPopupItem. Você receberá a mensagem "Sistema iniciado diretamente". Em seguida, feche o programa e clique com o botão direito sobre qualquer diretório no seu computador.

quinta-feira, 14 de abril de 2011

Conhecendo a classe Exception

Fonte: www.activedelphi.com.br

Durante a execução de uma aplicação é muito comum ocorrer erros que acabam atrapalhando sua execução, tais erros são denominados exceções. Por exemplo, temos uma função responsável em dividir dois valores, exemplificada abaixo:
function Divisao(Valor1,Valor2: Double): Double;
begin
  Result := Valor1/Valor2;
end;

Se atribuirmos ao parâmetro Valor2 o numero 0, irá ocorrer uma exceção e uma mensagem será exibida.

A mensagem nos informa que ocorreu uma exceção do tipo "EZeroDivide" com a mensagem "Floating point division by zero" (Divisão de ponto flutuante por zero), ou seja, tentamos dividir um valor por zero, o que na matemática é uma operação indeterminada.

O problema é que na maioria das vezes tais exceções provocam o encerramento da aplicação de forma brusca, que é muito desagradável, principalmente quando seu programa exige que determinadas informações sejam atualizadas, como salvar alterações feitas em bancos de dados. Para resolver este problema podemos utilizar a classe Exception, através das cláusulas try...except...end, de acordo com a sintaxe abaixo:
try
  //Insira aqui o bloco de comandos
except
  //Insira aqui o bloco de comandos que deverá ser executado caso ocorra alguma
  //exceção no código acima
end;
Você também pode usar o bloco try...finally...end:

try
  //Insira aqui o bloco de comandos
finally
  //De forma análoga, insira aqui o bloco de comandos que deverá ser executado caso
  //ocorra alguma exceção ou interrupção (exit / abort) no código acima
end;
Antes de prosseguirmos vamos conhecer um pouco mais a classe Exception.

A classe Exception é codificada na Unit SysUtils, é derivada da classe TObject e compõe a classe-base para todas as outras que manipulam exceções. Uma curiosidade é que a classe não segue o padrão do Delphi, onde o nome das classes deve ser precedido pela letra "T". Ela possui dois campos internos:

- um deles é o FMessage, um campo do tipo string(texto) que define a mensagem que será exibido na caixa de diálogo quando a exceção é gerada.
- o outro é o FHelpContext, do tipo integer(inteiro) que guarda o índice que identifica o tópico do arquivo help on-line associado a essa classe.

Voltando a nossa função "divisao", podemos tratá-la da seguinte forma:
function Divisao(Valor1,Valor2: Double): Double;
begin
  try
    Result := Valor1/Valor2;
  except
    ShowMessage('Valores incorretos!');
  end;
end;
Também podemos verificar qual o tipo de exceção foi gerado, usando o comando:

  on < tipo de exceção> do
Dessa forma é possível definir um bloco de comandos para cada exceção que sua aplicação possa gerar, permitindo um tratamento individual. Poderíamos redefinir a função como abaixo:

function Divisao(Valor1,Valor2: Double): Double;
begin
  try
    Result := Valor1/Valor2;
  except
    on EZeroDivide do
      ShowMessage('Divisão por zero!');
  end;
end;
Abaixo segue uma tabela com algumas exceções, claro que existe um número muito maior e é impossível lista-las. O objetivo desse artigo foi introduzir os conceitos referentes à classe Exception para quem nunca teve contato com ela.

Exceção
Significado
EZeroDivide
Divisão de um número real por zero
EDivByZero
Divisão de um número inteiro por zero
ERangeError
O limite de um número inteiro foi excedido
EIntOverFlow
O limite do resultado de uma operação com número inteiro foi excedido
EOverFlow
O limite do resultado de uma operação com numero real foi excedido
EInvalideOp
Operação inválida
EAccessViolation
Acesso violado
EDataBaseError
Erro genérico no banco de dados
EDBEngineError
Problema com a BDE
EOutOfMemory
Memória insuficiente


Você pode conferir mais sobre o uso dos comandos Try..Except e Try..Finally nesta série de artigos feita pelo João Marcos:
Try..Except..Finally - Parte 01 
Try..Except..Finally - Parte 02 
Try..Except..Finally - Final

quarta-feira, 13 de abril de 2011

Validando Número do Título Eleitoral


Veja nesta dica como incrementar seu sistema acrescentando a validação do número eleitoral, com uma simples função desenvolvida baseando-se no Resolução do TSE.

Para entender como funciona o esquema de validação do título de eleitor devemos primeiro dar uma olhada na Resolução, de Nº 20.132 do dia 19/03/1998. Vejamos o que diz o artigo de número 10:

    Art. 10 - Os Tribunais Regionais Eleitorais farão distribuir, observada a seqüência numérica fornecida pela Secretaria de Informática, às Zonas Eleitorais da respectiva Circunscrição, séries de números de inscrição eleitoral, a serem utilizados na forma deste artigo.
    Parágrafo único - O número de inscrição compor-se-á de até 12 (doze) algarismos, por Unidade da Federação, assim discriminados:
    a) os 8 (oito) primeiros algarismos serão seqüenciados, desprezando-se, na emissão, os zeros à esquerda;
    b) os 2 (dois) algarismos seguintes serão representativos da Unidade da Federação de origem da inscrição, conforme códigos constantes da seguinte tabela:
    01 - São Paulo
    02 - Minas Gerais
    03 - Rio de Janeiro
    04 - Rio Grande do Sul
    05 - Bahia
    06 - Paraná
    07 - Ceará
    08 - Pernambuco
    09 - Santa Catarina
    10 - Goiás
    11 - Maranhão
    12 - Paraíba
    13 - Pará
    14 - Espírito Santo
    15 - Piauí
    16 - Rio Grande do Norte
    17 - Alagoas
    18 - Mato Grosso
    19 - Mato Grosso do Sul
    20 - Distrito Federal
    21 - Sergipe
    22 - Amazonas
    23 - Rondônia
    24 - Acre
    25 - Amapá
    26 - Roraima
    27 - Tocantins
    28 - Exterior (ZZ)
    c) os 2 (dois) últimos algarismos constituirão dígitos verificadores, determinados com base no módulo 11 (onze), sendo o primeiro calculado sobre o número seqüencial e o último sobre o código da Unidade da Federação seguido do primeiro dígito verificador.

Resumindo: Os dígitos verificadores são calculados em duas etapas. Na primeira, calcula-se o módulo 11 sobre os 8 primeiros dígitos. Os estados de SP e MG possuem títulos com 13 dígitos, sendo assim, nestes casos devemos considerar os 9 primeiros algarismos. Na segunda etapa calculamos o módulo 11 sobre o código da UF + o primeiro dígito verificador.

Vejamos agora a função implementada:

function TForm2.valida_titulo(numero: String): Boolean;
var
  intInd1,intInd2,intLimite    : Integer;
  intSoma,intDigito            : Integer;
  strDVc,strSequencial         : String;
  strUF,strDV1,strDV2          : String;
begin
  numero := Trim(numero);
  while (Length(numero) < 13) do  numero := '0' + numero;
  intInd1 := 0; intInd2 := 0; strDVc := '';
  strSequencial := Copy(numero,1,9);
  strUF  := Copy(numero,10,2);
  strDV1 := Copy(numero,12,1);
  strDV2 := Copy(numero,13,1);
  {Verifca se a UF estiver entre os código possíveis, de 1(SP) até 28(ZZ-Exterior)}
  if ((StrToInt(strUF) >  0) and (StrToInt(strUF) < 29)) then
  begin
   intLimite := 9;
   {Loop para calcular os 2 dígitos verificadores}
   for intInd1 := 1 to 2 do
   begin
     intSoma := 0;
     {Calcula a soma para submeter ao módulo 11}
     for intInd2 := 1 to intLimite do
     begin
      intSoma := intSoma + StrToInt(Copy(strSequencial,intInd2,1)) * (intLimite + 2 - intInd2);
     end;
     {Pega o resto da dívisão, o módulo, por 11}
     intDigito := intSoma mod 11;
     { Se a UF for SP ou MG}
     if  (StrToInt(strUF) in [1,2]) then
     begin
       if (intDigito = 1) then  intDigito := 0
       else if (intDigito = 0) then intDigito := 1
       else intDigito := 11 - intDigito;
     end
     { Outros UF e Exterior}
     else begin
       if ((intDigito = 1) or (intDigito = 0)) then intDigito := 0
       else intDigito := 11 - intDigito;
     end;
     {Atribui à variavel strDVc o dígito calculado}
     strDVc := strDVc + IntToStr(intDigito);
     {Muda o valor de intLimite para o cáculo do segundo dígito}
     intLimite:= 3;
     {O cálculo do segundo dígito será sobre o código da UF + primeiro dígito verificador}
     strSequencial:= strUF + IntToStr(intDigito);
   end;
  end;

  result := (strDV1+strDV2 = strDVc);
end;

Para usá-la é bastante simples. Adicione ao seu form um Edit e um Button. No evento onClick deste Button, faça:

procedure TForm2.Button1Click(Sender: TObject);
begin
  if valida_titulo(Edit1.Text) then
    MessageDlg('Título Válido', mtInformation, [mbOk], 0)
  else
    MessageDlg('Título Inválido', mtWarning, [mbOk], 0);
end;

Pronto! Agora basta rodar o aplicativo, informar um número qualquer de título eleitoral que você verá a mensagem "Título Válido", a menos que o número informado esteja incorreto! :-)

terça-feira, 12 de abril de 2011

Instalando a Biblioteca Zeoslib no Delphi 7


Neste exemplo utilizei a versão Zeos 6.5.1 – Alpha.

1) Descompacte o arquivo em uma pasta de sua preferência. Utilizei a pasta C:\Zeos;
Copie os arquivos libmysql.dll, libpq.dll e libpq721.dll da pasta Componentes, (onde foram descompactados os arquivos do Zeos) para a pasta C:\Windows\System. Caso não aparecer estes arquivos na pasta Componentes, abra o Windows Explorer clique no menu Exibir, Opções de Pasta e ative a opção “Mostrar todos os Arquivos”. (Assim serão mostrados todos os arquivos com extensão dll para que você possa copiar para a pasta C:\Windows\System32 ( Windows XP) .

2) Abra o Delphi, clique no Menu Tools, Environment Options e clique na aba Library e após no botão Library Path, na janela Directories, clique no botão do combo Greyed items denote invalid path, selecione a pasta C:\Zeos\SCR\ZCore e clique no botão Add. Faça o mesmo procedimento para as pastas abaixo, nesta mesma ordem.
• ZCore
• ZParseSql
• ZPlain
• ZDbc
• Zcomponent

3) No Delphi, Clique no Menu File, Open , selecione o arquivo C:\Zeos\packages\Delphi7\Zeosdbo, e clique no botão Abrir , será aberta a janela de instalação de componentes. Clique no componente ZCore.bpl e com o botão direito do mouse , selecione a opção compile e depois Install. Faça o mesmo procedimento para os outros arquivos, observando a ordem abaixo :
ZCore.bpl
ZParseSql.bpl
ZPlain
ZDbc.bpl
ZComponent.bpl.

Pronto! Esta instalada a biblioteca Zeoslib.

20 motivos para você adotar o Firebird em sua empresa!

1 DBA não requerido

O Firebird é feito idealmente para desenvolvedores de aplicações que querem um banco de dados realmente encaixado. A pequena footprint e pouca necessidade de manutenção (O DBA não é requerido) do Firebird te dão a tranquilidade de que seus clientes mal notarão que ele está lá.

2 Alta performance tanto em aplicações críticas como em aplicações menores

O Firebird provê uma funcionalidade de alta performance que suporta operações críticas de negócios em áreas como comércio de mercadorias (ações, apólices), farmacêutica, aerospacial e gerenciamento de rede, enquanto se mantém com preço acessível (IB6 ser;a free) e fácil de usar para desenvolvedores de aplicações menores.

3 Versioning

O servidor Firebird é construído em uma arquitetura multi-geracional(MGA). O MGA provê um dispositivo versionig único que assegura alta disponibilidade para usuários que suportam decisões (support-decision). Servidores de banco de dados suportam tradicionalmente o modelo de interação de banco de dados On-Line Transaction Procesing (OLTP), caracterizado por um grande volume de transações simples e curtas. Enquanto o dispositivo versioning do Firebird suporta essas transações curtas, do tipo OLTP, o Firebird supera a competição em aplicações reais porque também gerencia ao mesmo tempo transações de longa duração do tipo support-decision.

4 Arquitetura SuperServer

A arquitetura SuperServer aumenta a performance e otimiza o uso de recursos de sistemas, especialmente por um grande número de usuários. Isto te permite ter mais clientes no seu servidor, e ainda aumentar a velocidade de suas repostas. Este é um servidor multi-threaded compartilhado, que provê a melhor performance já vista.

5 Instalação em minutos

O Firebird é instalado facilmente com um único comando. Ele tem uma pequena footprint, então você não precisa se preocupar em ter bastante espaço livre em disco e não precisará estabelecr centenas de parâmetros de sintonia. O Firebird foi preparado para requerer pouca manutenção, portanto ele otimiza suas transações pra você.

6 Sinalizadores de Eventos

Sinalizadores de eventos tornam possível a existência de um banco de dados ativo, avisando automaticamente as "partes interessadas" quando certas mudanças acontecem. Tudo isso é feito sem polling constante no banco de dados, portanto isto não limita os recursos do sitema.

7 Funções Definidas pelo Usuário (UDFs)

UDFs provêem meios de aumentar as capacidades analíticas do Firebird através da criação de funções habituais de negócios. UDFs são um código reutilizável e asseguram a integridade e confiabilidade dos dados. Da mesma maneira, UDFs podem ser usadas para chmar aplicações externas ao banco de dados

8 BLOBs - Binary Large Objects

O Firebird estabeleceu o padrão industrial com o lançamento de seu primeiro produto em 1986, quando armazenou som, imagem, gráficos e informações binárias diretamente no banco de dados usando os seus tipos de dados BLOB.

9 Arrays Multidimensionais

O Firebird também suporta os arrays multidimensionais usados extensivamente em aplicações financeiras e científicas. Armazenando arrays multidimensionais com até 16 dimensões em um único campo no banco de dados o Firebird simplifica o design da aplicação e aumenta a performance..

10 Banco de dados distribuídos para flexibilidade da aplicação

Quando você precisar mover a sua solução desktop de banco de dados para uma configuração client/server ou aumentar as suas aplicações de grupo de trabalho para servir a um ou mais departamentos, o Firebird é ideal, pois é feito para ambientes de banco de dados distribuídos.

11 Junção de múltiplos bancos de dados

O Firebird é um verdadeiro servidor de bancos de dados distribuídos SQL que permite que cada query do sistema de banco de dados retorne a informação para qualquer outro servidor Firebird

12 Commit em duas fases

O Firebird também gerencia transações com servidores múltiplos de maneira rápida e fácil. Ele inclui o processamento de transações com commit em duas fases, o que assegura que as atualizações sejam feitas sem intervenção da aplicação. Toda vez que uma transação abrange dois ou mais servidores de banco de dados o Firebird primeiro investiga os servidores participantes para assegurar de que eles estejam em atividade e rodando, então envia o comando commit para completar a transação.

13 Recuperação distribuída de Commit em duas fases

O Firebird leva o processo de commit em duas fases um passo além. Ele foi o primeiro produto de banco de dados a prover recuperação distribuída para um commit em duas fases. Isto assegura a recuperação completa sem o risco de um único ponto de falha, pois a coordenação da submissão é distribuída entre todos os servidores, reduzindo assim a necessidade de administração dos dados. No evento em que a transação não possa ser submetida em todos os servidores, a transação inteira é automaticamente tolled back em todos os servidores.

14 ANSI SQL-92

Para soluções em aplicações de missão crítica, o Firebird oferece total compatibilidade com SQL-92.

15 Sistema de travamento otimista

O Firebird utiliza tecnologia de travamento otimista para proporcionar grande taxa de uso de operações de banco de dados para clientes. O Firebird implementa travamentos a nível de linha reais para restringir mudanças somente nos registros do banco de dados que um cliente modifica. Diferente de travamentos a nível de página, que restringe qualquer dado arbitrário que estiver armazenado fisicamente próximo no banco de dados. Travamentos a nível de linha permitem múltiplos clientes atualizarem dados em uma mesma tabela sem conflito, resultando em menor serialização das operações de bancos de dados.

16 Usuários de peso

Vejam quem está utilizando o Firebird: NASA,Motorola, Nokia, MCI, Northen Telecom, Philadelphia Stock Exchange, Bear Stearns, First National Bank of Chicago, Money Store, US Army, NASA, Boeing, IBM (Brasil).

17 Flexibilidade de plataformas Windows, Linux, Unix, Solaris, NetWare...

Você escolhe qual usar,não ficando obrigado a certos sistemas operacionais.

18 Internet Explorer?

Você sabia que para o SQL Server 7 funcionar você precisa do Internet Explorer instalado em sua máquina?.

19 Firebird 6 tem distribuição livre

A versão 6 do Firebird é open-source e free, o que significa que o custo de seu projeto cairá! Consequentemente seus clientes ficarão bem satisfeitos.

20 O Firebird pode crescer com você Com produtos Firebird,

você não tem somente uma melhor performance nas mais populares plataformas UNIX e Windows, mas também uma melhor performance adaptada às necessidades de sua empresa. O Firebird é uma família de produtos que atravessa o espectro de um único usuário e servidores de pequenos grupos até grandes negócios. Com o recém-adicionado InterClient JDBC, você também tem a flexibilidade que precisa. Então, enquanto você cresce o Firebird pode crescer com você.

segunda-feira, 11 de abril de 2011

Alterando a cor de fundo de um hint

Basta colocar o código abaixo no evento OnCreate de um form, ou em qualquer outro objeto que você desejar.

Application.HintColor := clAqua; 

Aí está "clAqua" mas pode ser a cor de você quiser, só precisa saber os nomes das cores em delphi.

Ou se não, basta você colocar um dialogo (ColorDialog) de cores, e coloque o código abaixo, para você ver que você poderá escolher a cor do fundo do hint em tempo real.

procedure TForm1.Button1Click(Sender: TObject);
begin
  If colordialog1.Execute then begin 
     Application.HintColor := colordialog1.Color;  {opera a cor que      você optou no dialogo}
  end;
end;
end.

Conectado banco firebird pelo arquivo ini

Dica de como se conectar no banco interbase ou firebird, através de configurações de um arquivo ini.

var
vArqIni:TIniFile;
Caminho:string;
begin
   Caminho:='C:Automacao ComercialBancoAUTOMACAO.FDB';
   DataModulo.conexao.Close;
   if not( fileexists(extractfilepath(ParamStr(0))+'Automacao.ini') ) then begin
      ShowMessage('Arquivo de Configurações do Banco de Dados Não Encontrado!');
      vArqIni := TIniFile.Create(extractfilepath(ParamStr(0))+'Automacao.ini');
      try
        conexao.ConnectionName:='BANCO';
        vArqIni.WriteString('BANCO','database',Caminho);
        conexao.Params.Values['DataBase'] :=Caminho;
      finally
        vArqIni.Free;
      end;
   end;

   try
     vArqIni := TIniFile.Create(extractfilepath(ParamStr(0))+'Automacao.ini');
     conexao.ConnectionName:='BANCO';
     Caminho :=vArqIni.ReadString('BANCO','database',Caminho);
     conexao.Params.Values['DataBase'] :=Caminho;
   finally
     vArqIni.Free;
   end;

   try
     DataModulo.conexao.Connected:=True;
     DataModulo.VChamada:=0;
     DataModulo.spsusuarios.Close;
     DataModulo.spsusuarios.Open;
     DataModulo.UserControl.Execute;
   except
     Application.MessageBox( 'Não foi possivel se conectar com o banco de dados.' + #13 +
     'verifique se o arquivo de configuração está configurado, ' + #13 +
     'ou se o servidor firebird está instalado em seu sistema.' + #13 +
     'Verifique tambem se o Usuario secundario esta cadastrado.' + #13 +
     'Entre em contato com suporte para esclarecer qualquer dúvida.',
     'Error Interno', mb_ok + mb_IconError );

   Application.Terminate;
end;

Testa conectividade com internet

Essa Rotina verifica se o computador está conectado a internet usando a API do Windows. Para usar essa funcionalidade, é preciso declarar a uses WinInet.

var
flags : DWORD;
begin

   if not InternetGetConnectedState(@flags, 0) then
      MessageBox(handle, 'Você não está conectado a internet! ', mb_Ok + mb_IconWarning);
   
end;

Adicionar SQL em rotina Delphi

Atenção pessoal que está iniciando na programação Delphi com Interbase ou Outro banco. Para adicionar consulta tipo:

DataModule.Tabela.SQL.add('Texto '+variavel+'Texto'+variavel)
Onde a variável é alfa tem que ser feito conforme a seguir:
DataModule.Tabela.SQL.add('Select * from Table '''+variavel+'''Texto'''+variavel)
Perceberam as tres aspas? Muita gente já arrancou os cabelos antes de descobrir isso.

sábado, 9 de abril de 2011

Nomes dos arquivos que estão sendo executados:

É comum e até relativamente fácil encontrarmos rotinas para listar todas as janelas abertas. Mas muitas vezes não é apenas o caption das janelas que queremos listar e sim o nome do arquivo executável.

Veja então uma rotina que cria uma lista de strings com esses nomes:

uses TLHelp32; // não esqueça de incluir esta unit
procedure ListProcess(List: TStrings);
var
  ProcEntry: TProcessEntry32;
  Hnd: THandle;
  Fnd: Boolean;
begin
  List.Clear;
  Hnd := CreateToolhelp32Snapshot(TH32CS_SNAPALL, 0);
  if Hnd <> -1 then
  begin
  ProcEntry.dwSize := SizeOf(TProcessEntry32);
  Fnd := Process32First(Hnd, ProcEntry);
  while Fnd do
  begin
  List.Add(ProcEntry.szExeFile);
  Fnd := Process32Next(Hnd, ProcEntry);
  end;
  CloseHandle(Hnd);
  end;
end;
E para utilizar esta rotina é muito simples, veja:
procedure TForm1.Button1Click(Sender: TObject);
begin
  ListProcess(ListBox1.Items);
end;

Programar meu aplicativo para abrir arquivos a partir do Windows Explorer

Inclua na seção uses: Registry

Problema:
Criei um editor de textos no Delphi. Agora gostaria que o Windows Explorer usasse este editor para abrir arquivos com a extensão .dpg e .dan. Como fazer?

Solução:
Para fazer isto será necessária a criação de algumas chaves no Registro do Windows. O exemplo abaixo cria todas as chaves necessárias.

- Coloque um TButton e no evento OnClick dele coloque o código abaixo:

procedure TForm1.Button1Click(Sender: TObject);
var
  Reg: TRegistry;
begin
  Reg := TRegistry.Create;
  try
  Reg.RootKey := HKEY_CLASSES_ROOT;
  Reg.LazyWrite := false;
  { Define o nome interno (ArquivoDaniel) e uma legenda que aparecerá no Windows Explorer (Arquivo do Daniel) }
  Reg.OpenKey('ArquivoDaniel', true);
  Reg.WriteString('', 'Arquivo do Daniel');
  Reg.CloseKey;
{ Define o comando a ser executado quando abrir um arquivo pelo Windows Explorer (NomeDoExe %1). O símbolo %1 indica que o arquivo a ser aberto será passado como primeiro parâmetro para o aplicativo - ParamStr(1). }
  Reg.OpenKey('ArquivoDaniel\shell\open\command', true);
  Reg.WriteString('', ParamStr(0) + ' %1'); { NomeDoExe %1 }
  Reg.CloseKey;
  { Define o ícone a ser usado no Windows Explorer:
  0 - primeiro ícone do EXE
  1 - segundo ícone do EXE, etc }
  Reg.OpenKey('ArquivoDaniel\DefaultIcon', true);
  Reg.WriteString('', ParamStr(0) + ',0'); { 0 = primeiro ícone }
  Reg.CloseKey;
  { Define as extensões de arquivos que serão abertos pelo meu aplicativo }
  { *.dpg }
  Reg.OpenKey('.dpg', true);
  Reg.WriteString('', 'ArquivoDaniel');
  Reg.CloseKey;
  { *.dan }
  Reg.OpenKey('.dan', true);
  Reg.WriteString('', 'ArquivoDaniel');
  Reg.CloseKey;
  finally
  Reg.Free;
  end;
end;
- Coloque um TMemo;

- No evento OnShow do Form coloque o código abaixo:

procedure TForm1.FormShow(Sender: TObject);
begin
  { Se o primeiro parâmetro for um nome de arquivo existente... }
  if FileExists(ParamStr(1)) then
  { Carrega o conteúdo do arquivo no memo }
  Memo1.Lines.LoadFromFile(ParamStr(1));
end;
*** Para testar ***

- Execute este programa;

- Clique no botão para criar as chaves no Registro do Windows;

- Feche o programa;

- Crie alguns arquivos com as extensões .dpg e .dan;

- Vá ao Windows Explorer e procure pelos arquivos criados;

- Experimente dar um duplo-clique sobre qualquer dos arquivos com uma das extensões acima.

Observações

Existem outros recursos que poderão ser configurados. Porém, para começar, este já é um bom exemplo.  

terça-feira, 5 de abril de 2011

Formatando a visualização do tamanho de um arquivo

Fonte: www.activedelphi.com.br

Quando se trabalha com arquivos no Delphi pode ser necessário exibir o tamanho de um arquivo, como é feito no Explorer, onde o valor não é mostrado em bytes, mas sim de acordo com o seu tamanho atual. Para a maioria, "45.678.123 Bytes" é confuso, mas "43,56 MB" não!
A seguir, temos uma função chamada FormatByteSize, que converte um valor em bytes para uma String que representa o número expressado em Bytes, Kilobytes Megabytes ou Gigabytes, dependendo do seu tamanho:

//Formata o tamanho de um arquivo
function FormatByteSize(const bytes: Longint): string;
const
  B = 1; //byte
  KB = 1024 * B; //kilobyte
  MB = 1024 * KB; //megabyte
  GB = 1024 * MB; //gigabyte
begin
  if bytes > GB then
    result := FormatFloat('#.## GB', bytes / GB)
  else
    if bytes > MB then
      result := FormatFloat('#.## MB', bytes / MB)
    else
      if bytes > KB then
        result := FormatFloat('#.## KB', bytes / KB)
      else
        result := FormatFloat('#.## bytes', bytes) ;
end;
Para usá-la, basta fazer no evento onClick de um button, por exemplo:

procedure TForm1.Button1Click(Sender: TObject);
var
  TamanhoEmBytes: Longint;
begin
  with TFileStream.Create(
    'C:\Windows\System32\calc.exe',
    fmOpenRead or fmShareExclusive)
  do try
    TamanhoEmBytes := Size;
  finally
    Free;
  end;

  ShowMessage( FormatByteSize(TamanhoEmBytes) );
end;

domingo, 3 de abril de 2011

Verificando as impressoras pela rede e sabendo se elas estão online


Como verificar quais são as impressoras da rede e se elas estão On-line Com essa dica eu ajudei no fórum esta semana o Ronaldo, mas creio que como artigo, devo conseguir ajudar mais. Em vários projetos, saber se a impressão será efetuada com sucesso, e se a impressora estiver em rede e o computador que ela estiver ligada estiver sendo reiniciado, por exemplo, ou houver algum problema com a rede, talvez seja melhor dar um aviso ao usuário e esperar que ele regularize a situação antes de efetuar a impressão...
Com esta rotina abaixo, você consegue efetivamente tanto em Windows 98 quanto em Xp, obter uma resposta confiável da impressora. 

function VerImpressoraONLINE: Cardinal;
var
  hPrinter  : THandle;
  pInfo:  PPrinterInfo2;
  bytesNeeded: DWORD;
begin
  hprinter := GetCurrentPrinterHandle;
  try
    Winspool.GetPrinter( hPrinter, 2, Nil, 0, @bytesNeeded );
    pInfo := AllocMem( bytesNeeded );
    try
      Winspool.GetPrinter( hPrinter, 2, pInfo, bytesNeeded, @bytesNeeded );
       Result := pInfo^.Status;
    finally
      FreeMem( pInfo );
    end;
  finally
    ClosePrinter( hPrinter );
  end;
end;


se o resultado for > 0 então a impressora tem algum tipo de problema.
If VerImpressoraONLINE > 0
   then ShowMessage('A Impressora está OFFLINE, impressão ficará no aguardo' + #13 +  'Chame o Suporte Técnico para verificar a Impressora' );
 Para verificar quais são as impressoras da sua rede, teste da seguinte forma:
 var  ts : TStrings;
      J, K, I : Integer;
begin
    TS := Printer.Printers;
    K := Printer.PrinterIndex;
           J := -1;
           For I := 0 to TS.Count -1
               do If uppercase(copy(TS.Strings[I],1,7)) = 'EPSON'
                     then J := I;
           If J = -1
              then begin
                     ShowMessage('Impressora do estoque não configurada');
                     Exit;
              end
              else begin
                     Printer.PrinterIndex := J;
                     If VerImpressoraONLINE > 0
                        then ShowMessage('A Impressora EPSON está OFFLINE, impressão ficará no aguardo' + #13 +  'Chame o Suporte Técnico para verificar a Impressora' );
           end;

Como Consultar entre Datas no Delphi/Interbase.


Bom, estou aqui novamente para esclarecer algumas coisas sobre o artigo que escrevi anteriormente, após o artigo “Como Trabalhar com Data e Moeda no Delphi/Interbase”, recebi vários email´s e conheci muitas pessoas no MSN, por isso estou aqui novamente para dar mais uma pequena contribuição à comunidade Delphi e lembrando que é para iniciantes, programadores avançados talvez achem até sem importância para eles mas para mim foi crucial e deve ser também para outras pessoas.
Eu sei que esse assunto é no mínimo chato, mas mesmo assim vamos lá. Dessa vez vou abordar apenas datas que dão uma grande dor de cabeça no Interbase, acabo de desenvolver dois programas, um de controle de membros e colaboradores de uma Igreja e o outro para Tabelionato de Notas, apesar de serem completamente diferentes, consegui ao desenvolver os dois tirar muitas dúvidas sobre datas, por exemplo, Cartórios de Notas, todas as autenticações e demais atos que são feitos são recolhidos para o Estado (SecFaz, IPESP, etc.) e isso gera uma guia conhecida como GARE, que o cartório é obrigado a preencher diariamente, e para isso é preciso contar todos os atos realizados no dia, pegar o valor correspondente e multiplicar, além disso, escrever todo o conteúdo no campo de descrição da guia.

Com o software que eu desenvolvi, isso ficou muito fácil, pois todos esses dados estão em apenas uma tabela, é só dar um select, jogar os valores encontrados em campos pré-definidos (tipo EditQAut.text, EditvlAut.text) ou também em variáveis do tipo double fazendo as contas usando as velhas equações de 1º e 2º grau, aí é só pegar os dados encontrados e jogados nos edits correspondentes e mandar escrever em um campo qualquer:


Exemplo:


Na tabela DIARIO, existem os campos: Q_Aut Integer, Vl_Aut Numeric(9,2) e Data Date: (o campo “Q_aut”, serve para guardar a quantidade total de autenticações realizadas no dia; o campo “Vl_Aut”, para guardar a multiplicação dessas autenticações pelo preço unitário, que por sua vez é armazenado em uma outra tabela que chamei de CUSTAS, mas não vem ao caso, e o campo Data para guardar o dia que foi realizado as autenticações).

Em tempo: esses valores são encontrados previamente pelo cliente através de cálculos e opções fornecidas pelo software, entenda que estamos trabalhando já com o valor final, e não unitário tipo PDV que registra um-a-um, é como se já se tivesse fechado o caixa e estivesse querendo gerar um relatório com os dados finais.

Primeiro passo, dar um select para saber os dados do dia:


Var

C:string;
begin
C:=('select * from Diario where (Data = '#39+editdata.text+#39')');
IBQuery1.SQL.clear;
IBQuery1.sql.add(c);
IBQuery1.Open;
while IBQuery1.Eof = false do
begin
EditQAut.text:= IBQuery1.fieldbyname('Q_Aut').AsString;
EditVlAut.text:= IBQuery1.fieldbyname('Vl_Aut').AsString;
end;
end;

A declaração da variável “C: string” poderia ser de modo global, para não se repetir esse comando, dessa forma, o programa iria exibir nos edits em questão os valores contidos na tabela DIARIO. Aí logo após eu precisei escrever esses dados por extenso em um memo chamado “Mdescricao” e ficou desta forma:


MDescricao.text:= 'Hoje tiveram '+EditQAut.text+' Autenticações, que no total somou R$ '+EditvlAut.text;


Resolvi meu primeiro problema facilmente, bem simples, pois esta tudo na tabela chamada DIARIO, a Data, a Quantidade total do dia e o Valor Total, o “X” da questão foi quando me disseram que a guia que é gerada para instituição chamada IPESP não é diária, é semanal. Putz, como fazer um select entre duas datas e ainda por cima somando quantidades inteiras e valores monetários?????. Lí um e-mail que me fizeram essa mesma pergunta só que utilizando Acces, já havia lido vários artigos e dicas pela net e percebi que a resposta já estava lá, apenas precisava ser mais bem trabalhada, então achei uma solução:


Primeiro eu tinha que informar o dia inicial e o dia final, pois não encontrei funções para que o Interbase descobrisse isso pra mim, então adicionei ao form dois Maskedit´s (EditDataInicial.text e EditDataFinal.text), que serviram para informar no caso a Segunda-Feira e Sexta-Feira respectivamente, isso se não tiver feriado é claro, a partir daí criei um select com aquela função SUM, que serve para somar valores direto na base de dados, não esquecendo também de criar duas variáveis do tipo Tdate para armazenar as datas no formato americano ( D_inicial, D_Final).


Var

D_Inicial, D_Final : Tdate;
begin
{Guardar as datas nas variáveis}
D_Inicial:= StrtoDate(EditDataInicial.text);
D_Final:= StrtoDate(EditDataFinal.text);
{formatar para o formato americano}
ShorDateFormat:= ‘mm/dd/aaaa’;
{jogar as datas de volta nos Maskedits já formatadas}
EditDataInicial.text:= DatetoStr(D_Inicial);
EditDataFinal.text:= DatetoStr(D_Final);

C:=('select Sum(Q_Aut) AS Tot_Aut from Diario where (data >= '#39+EditDataInicial.Text+#39') and (data <= '#39+EditDataFinal.Text+#39')');

IBQuery1.SQL.clear;
IBQuery1.sql.add(c);
IBQuery1.Open;
while IBQuery1.Eof = false do
begin
EditTotal.text:= IBQuery1.fieldbyname('Tot_Aut').AsString;
{retornar para o formato brasileiro}
ShorDateFormat:= ‘dd/mm/aaaa’;
{joga o valor das datas novamente nos edits só que no formato dd/mm/aaaa}
EditDataInicial.text:= DatetoStr(D_Inicial);
EditDataFinal.text:= DatetoStr(D_Final);
end;
end;

Assim descobri a quantidade total de autenticações da semana, para descobrir a soma dos valores é só mudar o campo “Q_Aut” por “Vl_Aut”, assim ele irá somar os valores e não as quantidades. Claro que tudo isso pode ser feito em apenas um Select com declarações compostas utilizando aquela opção de Select-dentro-de-Select (SubSelect), aí é só quebrar a cabeça e resolver. Existem outras formas de fazer isso tudo que eu fiz diminuindo consideravelmente à quantidade de linhas de comandos, mas expliquei desse jeito passo-a-passo para entendermos melhor como funciona o Interbase com relação a datas.


Explicando o código:


Primeiro eu declarei duas variáveis do tipo “Tdate” [D_Inicial, D_Final] para armazenar as datas informadas nos MaskEdits [EditDataInicial.text e EditDataFinal.text], o que acontece, quando digitamos 13/12/2004 e 17/12/2004 respectivamente, isso é de Segunda a Sexta, ele vai pegar e alterar 13/12/2004 e 17/12/2004 por 12/13/2004 e 12/17/2004 respectivamente e jogar de volta no Maskedit, ai ele faz a comparação na base de dados já no formato que o Interbase entende mm/dd/aaaa (Mês/Dia/Ano), após isso é feito o select somando a quantidade encontrada [SUM(Q_Aut)] verificando as datas e retornando somente os registros que forem maiores ou iguais que 12/13/2004 e menores ou igual que 12/17/2004 [where (Data >= '#39+EditDataInicial.text+#39') and (Data <= '#39+EditDataFinal.text+#39'], assim ele vai verificar todos e trazer para os edits indicados, após isso, mudei novamente o formato da data para o formato brasileiro [ShorDateFormat:= ‘dd/mm/aaaa’] e mandei jogar os valores das respectivas datas nos Maskedits de novo, aí ele desfaz 12/13/2004 e 12/17/2004 por 13/12/2004 e 17/12/2004 respectivamente, ou seja, assim o delphi faz todo o trabalho de conversão para você sem maiores preocupações com o formato que foi digitado Dia/Mês/Ano, ou seja, o cliente digita Dia/Mês/Ano, o programa muda para Mês/Dia/Ano, faz todo o trabalho de recuperação dos dados e depois muda de novo para Dia/Mês/Ano.

Alguns devem pensar, pô.....engraçado, o cara do artigo fala que o formato da data é alterada pelo Interbase mas quando eu abro o IBConsole e dou um select * from Nome_da_Tabela, a data [campo do tipo Tdate] vem no formato dd/mm/aaaa, e não como ele diz que é...... Simples, é que ao fazer esse select no IBConsole, o Interbase verifica as configurações regionais do Windows e já retorna no formato correto, só que se você colocar um dbgrid no seu aplicativo para testar e der o mesmo select, irá ver que a data virá invertida, da forma que eu estou dizendo.