domingo, 24 de julho de 2011

Criando um Calendário Simples

Veja nesta dica como criar um calendário bastante simples, explorando o componente TMonthCalendar

    Crie um novo formulário em sua ara de trabalho(file > new > form).
    Altere suas propriedades de acordo com a tabela seguinte:

Propriedade         Valor

BordeStyle          bsDialog
Caption             Calendário
Color               clBtnFace
Font.Name           Arial
Font.Size           7
FormStyle           fsNormal
Height              437
Name                Calendario
Position            poScreenCenter
Width               703

    Insira no formulário do calendário um componente monthcalendar localizado na paleta win32.
    Ajuste suas propriedades para:

Propriedade         Valor
Aling               alClient
WeekNumbers         True (exibe o numero das semanas)

    Caso seja necessario, ajuste a altura e largura da janela até que o calendário apresente os 12 meses.

    O componente MonthCalendar possui a propriedade chamada Date, cuja função é definir a data a ser exibida. O problema é que esta propriedade fica ancorada com a data de criação do componente, ou seja, se você o inserir em um form em 16/12/08, sua data ficará fixada em 16/12/08, independente de qual seja a data em que você estiver executando o programa. Para resolver este problema, insira no evento onActivate da janela calendário:

procedure TCalendario.FormActive(Sender: TObject);
begin
  MONTHCALENDAR1.DATE := DATE;
end;

    Pressione F9 e veja o resultado.

Você também pode personalizar seu calendário através da propriedade CalColors. Se puder usar um form com uma maior extensão para visualização, sugiro a fonte arial 8 em negrito. Fica perfeito.

terça-feira, 19 de julho de 2011

Criação de DLL - Dynamic Link Libraries


Vou explicar em breves palavras como criar um sistema com a utilização de arquivos dll’s.
1º Regras para escrever uma DLL no Delphi : As funções e/ou procedimentos de DLL devem seguir estas regras:
- Precisam estar listados na cláusula exports da DLL. Isso possibilita que no momento de chamar a funções e/ou procedimentos, seja aceito pelo programa principal.
- As funções exportadas precisam ser declaradas como stdcall;
- Os tipos de parâmetros de uma DLL devem ser de tipos padrão do Windows, pelo menos se você quiser usar a DLL dentro de outros ambientes de desenvolvimento, como por exemplo, C++.
- Uma DLL pode usar dados globais que não serão compartilhadas pelos programas base. Sempre que uma aplicação carrega uma DLL, ele armazena os dados globais da DLL em seu próprio espaço de endereço
 
2º Neste passo vamos tirar a dúvida a uma pergunta muita frequente; “Como criar uma DLL?”.
Dando início ao desenvolvimento de DLLs no Delphi, vou mostrar a vocês uma biblioteca muito simples. O principal objetivo desse exemplo é mostrar a sintaxe utilizada para definir uma DLL no Delphi.
Para começar, selecione o comando File/New, escolha a opção DLL na página New do Object Repository. Isso cria um Codigo-Fonte muito simples.
Aqui está código fonte da nossa primeira DLL:
 
Library MINHADLL.DLL;
uses SysUtils,
Classes;
{$R *.res}
function Triple(N: Integer): Integer; stdcall;
begin
  Result := N * 3;
end;
function Double (N: Integer): Integer; stdcall;
begin Result := N * 2;
end;
exports Triple, Double;
end.

3ª E agora por fim vamos incluir a dll num projecto Win32.

Para fazer um formulário usando nossa DLL vamos abrir o Delphi e criar uma nova aplicação.
Colocar dois Edits e dois Buttons, no evento OnClick dos botões faremos as chamadas das funções. Para chamar um função de uma DLL é preciso apenas declarar as funções de forma igual a declarada na dll, ou seja, nome, parâmetros e tipos.
Aqui fica um exemplo:

unit Unit1;
  interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls;
  type TForm1 = class(TForm)
    Button1: TButton;
    Button2: TButton;
    Edit1: TEdit;
    Edit2: TEdit;
  procedure Button1Click(Sender: TObject);
  procedure Button2Click(Sender: TObject);
  private { Private declarations }
  public { Public declarations }
end;
var Form1: TForm1;
implementation
{$R *.dfm}
 
{funções da DLL Delphi}
  function Double (N: Integer): Integer; stdcall; external 'MINHADLL.DLL';
  function Triple (N: Integer): Integer; stdcall; external 'MINHADLL.DLL';
  procedure TForm1.Button1Click(Sender: TObject);
  var x, y: integer;
  begin
    x := StrToInt(Edit1.Text);
    y := Double(x);
    Edit1.Text := IntToStr(y);
  end;
 
  procedure TForm1.Button2Click(Sender: TObject);
  var x, y: integer;
  begin
    x := StrToInt(Edit2.Text);
    y := Triple(x);
    Edit2.Text := IntToStr(y);
  end;
end.

domingo, 10 de julho de 2011

Guia Inicial Rápido Para Otimização de Índices


Veja neste artigo a tradução de um post feito por Paul Beach em seu blog, que foi mencionado pelo site firebirdnews.org, mas cujos conceitos se aplicam a praticamente todos os SGBDs.

Abaixo, é apresentado um rápido guia inicial com cinco (na verdade seis) pontos para a otimização de índices, cortesia de Pavel Cisar.

1. Sempre defina TODAS as regras (constraints) de integridade: chaves primárias, estrangeiras e índices únicos. Isto será automaticamente utilizado na otimização de junções (joins).

2. Defina índices separados para CADA COLUNA que será utilizada em regras adicionais de suas consultas (ex: filtros em cláusulas WHERE), que não fazem parte do primeiro ponto (pk's, fk's e uniques).

3. Atualize as estatísticas de seus índices regularmente, visto que dados são inseridos / modificados / excluídos em sua base de dados. Uma boa regra geral é atualizar as estatísticas dentro de suas rotinas de manutenção (quando fizer backup, sweep, etc.), e/ou sempre que você inserir / alterar um quarto de todos os registros, uma vez que a tabela possua mais de 10.000 registros.

4. Uma vez tendo dados representativos do mundo real em seu banco de dados, você pode avaliar a usabilidade dos índices para eliminar aqueles que não ajudam suas instruções SQL (um índice insignificante apenas tornará lento seus inserts e updates!) e adicionar novos índices compostos ou de expressões, que aumentem a performance de instruções específicas.

5. Índices inúteis são normalmente aqueles com baixa seletividade (poucos valores distintos). Execute algumas consultas com filtros condicionais em colunas com baixa cardinalidade e verifique quando o otimizador usa o índice ou não. Se o índice de baixa seletividade é sempre ou frequentemente usado em outras condições de filtro, você pode melhorar a sua seletividade e consequentemente a sua usabilidade, criando um índice composto com as colunas que são usadas nestes outros filtros, ao invés de usar índices independentes em cada coluna.

6. Se você sempre / frequentemente usa um grupo de colunas para filtros, um índice composto nestas colunas pode melhorar a performance do comando, mas faça isso apenas se não estiver satisfeito com a performance que os índices em colunas individuais provêem.

De Enum para String e de String para Enum


Há algum tempo atrás precisei criar um enumerado e depois carregar este enumerado em um ComboBox. Toda vez que surgia essa necessidade eu criava o enum e criava um array de string com todas as opções do enum, aí com um loop no array eu populava o ComoboBox. Só que toda vez que precisava acrescentar um nova opção no enum eu tinha que atualizar o array.

Isso começou me incomodar! Foi aí que lembrei que quando desenvolvemos componentes e criamos uma property do tipo de um enum na seção published, o Delphi exibe esse enum no ObjectInspector com um ComboBox, e ele faz isso automaticamente! Aí pensei: “isso deve ser possível” já que o Delphi faz. Então entrei em contato com um amigo meu muito fera em Delphi, “Adriano Santos”, e ele conseguiu a solução que eu gostaria de publicar.

Vamos lá, vou dar o exemplo referente a minha necessidade na época que estava desenvolvendo uma comunicação com uma balança através da porta COM.

Criando o enum:

type
  TPorta = (COM1, COM2, COM3, COM4, COM5, COM6, COM7, COM8, COM9);

Criando a property do tipo do enum:

  private
    FPort: TPort;
  public
    property Port: TPort read FPort write FPort;
  end;

Criando um método que vai popular uma lista do Tipo TStrings, assim, com esse método posso popular objetos como: TComboBox, TMemo, TListBox ou até mesmo uma variável do Tipo TStrings. Primeiro deve ser declarado na seção uses a unit: TypInfo.

class procedure TSerialComunication.PopulateListPort(AList: TStrings);
var
  i: Integer;
Begin
  for i := Ord(Low(TPort)) to Ord(High(TPort)) do
    AList.Add(GetEnumName(TypeInfo(TPort), i));
end;

Agora basta chamar o método e popular o ComboBox:

procedure TfrmPrincipal.btnPopulatePortClick(Sender: TObject);
Begin
  TSerialComunication.PopulateListPort(cbbPort.Items);
end;

Essa foi a solução que meu amigão Adriano Santos meu passou, achei genial.

Agora imagina se precisar pegar um item do ComboBox que é uma string e passar pra uma variável do tipo do Enum? Antigamente eu usaria um case pra saber qual foi o item selecionado e passar a opção do enum correta, mas agora posso usar a mesma idéia e converter automaticamente enum para string ou vice-versa! Então criei dois overload de um método Convert:

class function TSerialComunication.Convert(const APort: string): TPort;
begin
  Result := TPort(GetEnumValue(TypeInfo(TPort), APort)) ;
end;

class function TSerialComunication.Convert(const APort: TPort): string;
begin
  Result := GetEnumName(TypeInfo(TPort), Integer(APort)) ;
end;

Agora ficou facil, basta chamar os métodos de conversão!

Convertendo o item do combobox para o enum:

procedure TfrmPrincipal.btnStringToEnumClick(Sender: TObject);
var
  vPort: TPort;
begin
  vPort := TSerialComunication.Convert(cbbPort.Text);
end;

Convertendo de Enum para uma string:

procedure TfrmPrincipal.btnEnumToStringClick(Sender: TObject);
var
  vPort: TPort;
begin
  vPort := COM1;
  ShowMessage(TSerialComunication.Convert(vPort));
end;

terça-feira, 5 de julho de 2011

Repositório do Delphi


O repositório do Delphi é um local para armazenamento de objetos, como formulários e projetos, que facilita o compartilhamento desses objetos por vários projetos. Quando você clica em File|New... para criar um novo objeto, você pode escolher um dos itens do repositório.
Acrescentando um formulário ao repositório
    
Abra um projeto DPR, e dentro dele o formulário "Form" (Form1.pas). Esse formulário está sendo compartilhado dentro do mesmo projeto, mas se você quiser reutilizá-lo em outros projetos, pode acrescentá-lo ao repositório. 
     Para isso, clique com o botão direito e em Add to Repository. Você deve informar o título do item, uma descrição e qual a página onde ele será inserido (se você digitar um nome de página que não existe, uma nova será criada), além do seu nome para indicar qual o autor desse item. Opcionalmente você pode escolher um ícone que será usado para representar o item. Para o exemplo digite o seguinte: 

   Title: Formulário para uma tabela
   Description: Formulário de banco de dados para uma tabela
   Page: Forms (default)
   Author: seu nome 

     O botão "Browse" permite você procurar um ícone , para representar sua classe de formulário, caso não informe ele irá mostrar o seguinte ícone . Clique Ok. O novo item será adicionado ao repositório. Agora crie um novo projeto com File|New Application e veremos como o item pode ser reutilizado.
     Formas de criar novos objetos
    
Se você clicar em File|New... e na página "Forms", você verá que o novo item ("Formulário para uma tabela") está dentro do repositório. Agora ele está disponível em qualquer projeto, permitindo criar novos formulários a partir dele.
     Existem três opções para criar novos objetos a partir do repositório: copiar [copy] o item, herdar [inherit] do item (criar uma nova classe derivada) ou usar [use] o item diretamente.
Se você marcar a opção "Copy" e clicar Ok, o Delphi cria uma cópia separada do objeto original que está no repositório. Qualquer alteração no original posteriormente não vai afetar essa cópia e qualquer alteração na cópia é independente do que está no repositório. Note que a unidade do formulário não foi salva e está em memória como "Unit2". Isso permite você salvar com um nome qualquer.
     A opção "Inherit" (herdar) faz diferente: faz uma referência ao original (ou seja, acrescenta o formulário original dentro do projeto) e cria uma nova classe derivada da original, TForm1. O novo formulário será chamado de 'FormBase1', com a classe 'TFormBase1'. A unidade do formulário não foi salva ainda. Nesse caso, qualquer alteração no original, que está no repositório, será herdada pela classe derivada.
     A opção "Use" não copia o objeto original, mas compartilha com o projeto atual. Nesse caso, alterações feitas no item dentro do projeto afetam o item no repositório e vice-versa. Se vários projetos usarem o mesmo item, todos eles compartilham o mesmo item.
     Adicionando um projeto ao repositório
    
Para reutilizar um projeto inteiro, você pode acrescentá-lo ao repositório com o menu Project|Add to Repository... e informar a descrição do item como antes.
     Gerenciando o repositório
    
Para gerenciar as páginas do repositório e os itens de cada página, você pode clicar em   Tools|Repository. Na caixa de diálogo você pode criar, renomear ou excluir uma página do repositório (você só pode excluir se ela estiver vazia). É possível também mudar a ordem das páginas.
     Você pode mover os itens entre páginas arrastando o item da lista da esquerda e soltando sobre a página desejada. Também é possível renomear ou alterar características de um item ou excluir o item.
     Compartilhando o repositório numa equipe
    
Quando uma equipe de desenvolvedores trabalha em conjunto, é importante que eles possam compartilhar o repositório, de forma que novos itens adicionados a ele estejam disponíveis para toda a equipe.
     Para compartilhar o repositório, você deve usar um diretório na rede que seja acessível a todos os desenvolvedores. Por exemplo, se G: é uma letra de drive que aponta para a rede, você pode usar G:\REPOS. Você deve também copiar os arquivos do repositório do Delphi para esse diretório.
     Os arquivos do repositório do Delphi são armazenados num subdiretório OBJREPOS, abaixo do diretório onde o Delphi foi instalado (geralmente C:\Arquivos de Programas\Borland\Delphi6). Além desses arquivos, o Delphi usa um arquivo de texto chamado DELPHI32.DRO, localizado no subdiretório BIN do Delphi.
     Para compartilhar o repositório na rede, faça o seguinte: 
     • Crie um diretório compartilhado (e.g. G:\REPOS). Verifique que todos os desenvolvedores têm acesso a ele e usam a mesma letra de drive; 
     • Copie o repositório de um computador para o diretório compartilhado (G:\REPOS), ou seja, todos os arquivos do subdiretório OBJREPOS do Delphi, mais DELPHI32.DRO, do subdiretório BIN; 
     • Em cada um dos computadores, no Delphi, clique em Tools|Environment Options. Na página Preferences Em "Shared Repository", digite o caminho do diretório compartilhado. 
Agora lembre-se que qualquer alteração ou acréscimo feito por um desenvolvedor afeta todos os outros. É importante também notar que quando você quiser compartilhar um objeto, ele deve ser salvo num diretório compartilhado também, acessível a todos (por exemplo, G:\BIBLIOTECAS).

Como instalar componentes no delphi


Existe a possibilidade de instalar componentes através de três tipos de extensões de arquivos: *.pas, *.dcu, *.dpk.
Explicando um por um:
1 - Para arquivos que necessitam de um Package (normalmente componentes que possuem somente o *.PAS), execute o Delphi e feche o projeto, acesse o menu 'Component' e clique na opção 'install component'. Na janela que se apresenta, acesse a aba ' Into New Packages', clique no botão 'Browse' ao lado da caixa de texto 'Unit File Name' abra o arquivo com extensão *.pas, dê ok e logo após 'Compile' e 'Install' e o arquivo criará uma aba na barra de componentes com um nome para a sua localização.

2 - Para instalar pacotes de componentes (Packages, arquivos com a extensão *.DPK), execute o Delphi e feche o projeto, acesse o menu 'File' e clique na opção 'Open', abra o arquivo que contém os componentes. Dê Ok e depois é só clicar en 'install'. Pronto seu pacote de componentes será instalado.


3 - Para arquivos com a extensão *.dcu, é um pouco mais complicado. Acesse o menu 'Component' e clique na opção 'install package'. Verifique se na lista 'Design packages' existe a opção 'Borland user component', se sim, clique no botão 'edit', abrirá uma caixa de mensagens, clique no botão 'yes'. Na janela que aparece clique no botão 'add', na janela que se abrirá clique no botão 'browse' da caixa de texto 'unit file name'. Na caixa de combinação 'files of type' escolha 'Delphi compiled unit(*.dcu)', depois na caixa de texto 'File name' direcione o arquivo a ser instalado, clique no botão 'open'. Clique no botão 'ok' na janela que aparece e clique no botão install. Pronto o seu componente será instalado.


Obs:Se na lista 'Design packages' não tiver a opção 'Borland user component' você deverá primeiro instalar componentes que estão em arquivos com extensão *.pas.

terça-feira, 28 de junho de 2011

Stored Procedure para saber os aniversariantes por dia/mês


Administrador Essa procedure lhe retorna todos os aniversariantes de um determinado período de dia e mês. Foi feita originalmente para Firebird, mas pode ser facilmente adaptada para qualquer outro banco que suporte Stored Procedures

Observação: este artigo é uma alternativa ao material enviado pelo amigo cruzeirense, pois em sua dica, exige-se que o ano de nascimento também seja informado como parâmetro da procedure. Seu material pode ser visto neste link:

No exemplo, utilizarei uma tabela chamada FUNCIONARIO, conforme pode ser visto abaixo:

/* Estrutura da tabela FUNCIONARIO
CREATE TABLE FUNCIONARIO (
    ID               INTEGER,
    NOME             VARCHAR(50),
    SALARIO          NUMERIC(15,2),
    DATA_NASCIMENTO  TIMESTAMP
);
*/

SET TERM ^ ;

CREATE PROCEDURE ANIVERSARIANTES (
    strdta_ini varchar(5),
    strdta_fim varchar(5))
returns (
    nome varchar(50),
    salario numeric(15,2),
    dta_nasc timestamp)
as
declare variable dta_ini timestamp;
declare variable dta_fim timestamp;
BEGIN
    SELECT CAST(:STRDTA_INI||'.'||CAST(EXTRACT(YEAR FROM
        MAX(DATA_NASCIMENTO)) AS VARCHAR(10)) AS TIMESTAMP) AS B
        FROM FUNCIONARIO INTO DTA_INI;
    SELECT CAST(:STRDTA_FIM||'.'||CAST(EXTRACT(YEAR FROM
        MAX(DATA_NASCIMENTO)) AS VARCHAR(10)) AS TIMESTAMP) AS B
        FROM FUNCIONARIO INTO DTA_FIM;
    WHILE (DTA_INI <= DTA_FIM) DO
    BEGIN
        FOR SELECT NOME, SALARIO, DATA_NASCIMENTO FROM FUNCIONARIO WHERE
        EXTRACT(DAY FROM DATA_NASCIMENTO) = EXTRACT(DAY FROM :DTA_INI) AND
        EXTRACT(MONTH FROM DATA_NASCIMENTO) = EXTRACT(MONTH FROM :DTA_INI)
        ORDER BY NOME, DATA_NASCIMENTO INTO :NOME, :SALARIO, :DTA_NASC DO
            SUSPEND;
        DTA_INI = DTA_INI + 1;
    END
END^

SET TERM ; ^

Agora é só fazer um select como o abaixo e pronto! ;-)

SELECT * FROM ANIVERSARIANTES('01/01', '31/01');

Curso de Delphi: 7.Consultas SQL