Dicas sobre o componente DBGrid do Delphi
O TDBGrid talvez seja um dos componentes mais utilizados no dia a dia de um desenvolvedor Delphi.
Resolvi juntar algumas dicas simples e práticas para melhorar a utilização deste componente. Para melhor demonstrar os resultados dos exemplos, criei um projeto teste com dados fictícios em um ClienteDataSet, porem, os exemplos que fiz são quase que 100% independentes do tipo de DataSet utilizado.
Fazer linha zebrada :Temos que verificar se o numero do registro atual do DataSet é impar ou par, nos dataSet temos a propriedade RecNo que consiste no numero do registro ativo no dataSet e para saber se esse numero é impar ou par, basta usar o método Odd que retornar true se um numero é impar e false se esse for par. Para implementar essa rotina, iremos utilizar o evento OnDrawColumnCell do TDbGrid que consiste no evento em que os dados são “desenhados” no grid.
procedure TForm1.dbGridTesteDrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if Odd(ClientDataSet1.RecNo) then
dbGridTeste.Canvas.Brush.Color := clWindow
else
dbGridTeste.Canvas.Brush.Color := clMoneyGreen;
dbGridTeste.Canvas.FillRect(Rect);
dbGridTeste.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
Utilizamos a propriedade Canvas, dentro de canvas a propriedade Brush, que é utilizada para pintar o fundo de uma linha no grid. O resultado deste exemplo ficaria desta forma.
Destacar linhas: Nesse exemplo vamos destacar as linhas com da fonte vermelha e em negrito nos que tiverem o salario menor de 1900,00.
procedure TFSistema.dbGridTesteDrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if ClientDataSet.FieldByName('VALOR').AsFloat <= 1900 then begin
if (gdSelected in State) then
dbGridTeste.Canvas.Brush.Color := clRed
else begin
dbGridTeste.Canvas.Font.Style := [fsBold];
dbGridTeste.Canvas.Font.Color := clRed;
end;
dbGridTeste.Canvas.FillRect(Rect);
dbGridTeste.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;
end;
Agora estamos utilizando "gdSelected in State", se resultar true significa que esta posicionado na linha do TDBGrid.
Destacar uma célula e uma coluna: Agora vamos fazer por célula, quando o valor for menor que 1900,00 a célula vai ficar vermelha e a letra branca e se maior a célula ficara verde. Algo semelhante ao exemplo anterior
procedure TFSistema.dbGridTesteDrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
if Column.FieldName = 'VALOR' then begin
if Column.Field.AsFloat <= 1900 then begin
dbGridTeste.Canvas.Brush.Color := clRed;
dbGridTeste.Canvas.Font.Color := clWhite;
end else
dbGridTeste.Canvas.Brush.Color := clTeal;
dbGridTeste.Canvas.FillRect(Rect);
dbGridTeste.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;
end;
Inserir um checkbox em um coluna:Já fiz um post com apenas esse exemplo, e um dos que mais utilizo. Vamos inserir o checkBox com isso vamos usar um campo integer o SEL e nele vamos jogar 1 ou 0 em caso de 0 esta desmarcado e 1 marcado, conseguimos fazer isto através da variável Check.
procedure TFSistema.dbGridTesteDrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
R: TRect;
Check: integer;
begin
if (Column.Index = 0) then begin
if (ClientDataSet.FieldByName('SEL').Value = 0) then
Check := DFCS_BUTTONCHECK or DFCS_CHECKED
else
Check := DFCS_BUTTONCHECK;
dbGridTeste.Canvas.FillRect(Rect);
R := Rect;
InflateRect(R, -2, -2);
DrawFrameControl(dbGridTeste.Canvas.Handle, R, DFC_BUTTON, Check);
end;
end;
Para deixar um pouco mais prático o uso do checkBox no DBgrid, podemos fazer uma rotina para marcar ou desmarcar o componente quando a célula que ele está seja clicada
Já no TDBGrid vai o código abaixo:
procedure TFSistema.dbGridTesteDblClick(Sender: TObject);
begin
ClientDataSet.Edit;
ClientDataSetSEL.Value := IfThen(ClientDataSetSEL.Value = 1, 0, 1);
ClientDataSet.Post;
end;
Inserir uma imagem em uma coluna:Vamos utilizar o componente TImageList para poder armazenar as imagens. Com a mesma ideia do marcar e desmarcar do CheckBox.
Já no TDBGrid vai o código abaixo:
procedure TFSistema.dbGridTesteDrawColumnCell(Sender: TObject; const Rect: TRect;
DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
lIcon: TBitmap;
begin
if (Column.Index = 0) then begin
lIcon := TBitmap.Create;
lIcon.Transparent := True;
ImageList1.GetBitmap(ifthen(ClientDataSetSEL.Value = 1, 1, 0), lIcon);
try
dbGridTeste.Canvas.FillRect(Rect);
dbGridTeste.Canvas.Draw(Round((Rect.Left + Rect.Right - lIcon.Width) / 2), Rect.Top, lIcon);
finally
FreeAndNIl(lIcon);
end;
end;
end;
Utilizar um ComboBox em uma coluna: Dentro dasColumns do Dbgrid existe a propriedade PickList que tem o objeto do tipo TStrings e é utilizado exatamente para dar esse efeito do combo dentro de uma célula do grid. Então para demonstrar a utilização desta propriedade, dentro do método de carregar os dados, vamos colocar o seguinte trecho de código:
procedure TFSistema.DoCreate;
begin
with dbGridTeste.Columns[2].PickList do begin
Clear;
Add('GERENTE');
Add('REPRESENTANTE');
Add('ENCANADOR');
Add('VENDEDOR');
end;
end;
Ordenar dinamicamente pela coluna clicada pelo usuário: Vamos fazer uma ordenação que o usuário escolha por qual campo ele quer fazer a ordenação, clicando no titulo de uma coluna no DBgrid. Utilizaremos o IndexFieldNamesque .
Exemplo: Download do exemplo
Ana, boa tarde
ResponderExcluirPoderia me ajudar em uma duvida?
Tenho uma NF e preciso cadastrar esta NF e seus itens para que apareça em um DBGrid, segue um exemplo abaixo
NF DESCRIÇÃO DO PRODUTO VALOR UNITARIO QUANTIDADE VALOR TOTAL
1234 PARAFUSO DE AÇO R$ 0,50 10 R$ 5,00
1234 TUBO DE SILICONE 100 ML R$ 5,00 5 R$ 25,00
Como devo proceder neste caso? Teria algum exemplo fisico?
Uso AdoQuery, AdoConexion, Banco de Dados Access.
Parabens pelo Blog!!!
No aguardo,
Cristiano
Acredito que seja um dbgrid normal consiga exibir esses dados.
ExcluirSe não é bem isso ha como passar mais detalhes de como quer? Obrigada
Bom dia, Ana. Tenho uma dúvida, talvez você possa esclarecê-la. Tenho um DBGrid, no qual necessito " navegar entre as colunas " --- tem de ser através de um botão --- a fim de inserir dados nos diversos campos . Eu tenho de usar botões simulando as setas ( para cima, para baixo --- essas eu consigo com " prior e next " porém as setas para esquerda e direita eu não consigo codificar.Obrigado pela sua atenção.
ResponderExcluirOla Boa tarde.
ExcluirPara navegar entre colunas tem a tecla de atalho Tab para prosseguir e shift + tab para volta então seria apenas colocar em botões a simulação de cliques nessas teclas.
Exemplo:
Direita
{ Pressiona Tab }
keybd_event(VK_TAB, 0, 0, 0);
Esquerda
{ Pressiona Shift}
keybd_event(VK_SHIFT, 0, KEYEVENTF_EXTENDEDKEY or 0, 0);
{Preciona Tab}
keybd_event(VK_TAB, 0, 0, 0);
{ Libera (solta) Shift }
keybd_event(VK_SHIFT, $45, KEYEVENTF_EXTENDEDKEY or KEYEVENTF_KEYUP, 0);
Responde ai se isso ajudou
Boa tarde Ana, Cara gostei muito de suas dicas. Estou com um problema aki e talves vc possa me ajudar,Eu tenho um DBGrid para mostrar a lista de itens de um pedido. Quero saber se é possivel eu apenas digitar o codigo ou o nome do produto em uma das coluna do DBGrid, e as outras colunas serem preenchidas com as informações restante do produto.
ResponderExcluirex: ____________________________________________________________________
| código | Descrição | Ref. | Valor_Unid | Quantidade | Valor_Total |
Dentro do DBGrid, eu digitaria apenas o "código" do produto... e ele me retornaria com as informações das outras colunas restantes. "Descrição" "Ref." "Valor_Unid" "Quantidade" "Valor_Total".
Isso é possivel ?
Eu uso Delphi 7, DBxpress ( SQLDataSet, ClientDataSet...), Firebird 2.5
Ola boa tarde Marcos, porque não utiliza a propriedade "OnChange" do campo "código" na tabela ClientDataSet, se no seu caso não houvesse restrição acredito que seria a melhor maneira sem precisar alterar o TDBGrid. Responde ai se isso ajudou.
ExcluirBoa tarde Ana, gostei muito do seu post, já ajudou um bocado, mas ainda enfrento um problema. tenho uma dbgrid de um contas a receber com checkbox e gostaria que ao marcar o checkbox ele somasse um valor de um determinado campo. pelo exemplo que vc deu, não estou conseguindo marcar o checkbox, já que o tratamento que vc deu já vem de um capo booleano existente na tabela. Fico agradecido pela atenção.abraços.
ResponderExcluir