Saudações, leitores! Há algum tempo, tive de implementar uma funcionalidade que exibe uma imagem na célula de uma coluna do componente DBGrid. Enquanto pesquisava na internet, encontrei vários exemplos, no entanto, muitos deles estavam incompletos. Por conta disso, decidi reunir não só essa, mas também outras dicas desse componente neste artigo. Confira!
O componente TDBGrid
é utilizado em praticamente todas aplicações para exibir dados na tela. No artigo, apresentarei 10 dicas para incrementar as funcionalidades desse componente e trazer uma melhor usabilidade para o usuário.
Sem mais delongas, mãos à obra!
1) Imagem dentro de uma célula
Considere que, na coluna “Ativo” de uma DBGrid, seja necessário exibir um Ãcone para “Sim” e outro para “Não”.
Em primeiro lugar, é necessário utilizar um componente TImageList
(paleta Win32) e adicionar 2 imagens, cada uma representando um estado da coluna “Ativo”, conforme ilustrado abaixo:
Em seguida, basta implementar o seguinte código no evento OnDrawColumnCell
da DBGrid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var lIndiceImagem: byte; begin if UpperCase(Column.Field.FieldName) = 'ATIVO' then begin DBGrid.Canvas.FillRect(Rect); if Column.Field.AsString = 'N' then lIndiceImagem := 0 else lIndiceImagem := 1; // desenha a imagem conforme a condição acima ImageList.Draw(DBGrid.Canvas, Rect.Left + 24, Rect.Top + 1, lIndiceImagem); end; end; |
2) Checkbox dentro de uma célula
Essa dica é bem semelhante ao código acima, salvo algumas exceções. Não precisamos do TImageList
neste caso, portanto, somente o código abaixo é necessário para desenhar o CheckBox:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
var lMarcar: word; lRetangulo: TRect; begin if UpperCase(Column.FieldName) = 'ATIVO' then begin DBGrid.Canvas.FillRect(Rect); if Column.Field.AsString = 'S' then lMarcar := DFCS_CHECKED else lMarcar := DFCS_BUTTONCHECK; // ajusta o tamanho do CheckBox lRetangulo := Rect; InflateRect(lRetangulo, -2, -2); // desenha o CheckBox conforme a condição acima DrawFrameControl(DBGrid.Canvas.Handle, lRetangulo, DFC_BUTTON, lMarcar); end; end; |
Porém, se você executar este código, irá observar que, quando clicamos na célula, ao invés de marcar ou desmarcar o CheckBox, aparecerá a letra “S” ou “N”. Para evitar isso, são 2 passos. Primeiro, vamos manter a coluna “Ativo” como somente leitura, adicionando o código abaixo no evento OnColEnter
da DBGrid:
1 2 3 4 |
if UpperCase(DBGrid.SelectedField.FieldName) = 'ATIVO' then DBGrid.Options := DBGrid.Options - [dgEditing] else DBGrid.Options := DBGrid.Options + [dgEditing]; |
Em seguida, precisamos “esconder” os valores “S” e “N” na célula através do evento OnGetText
do campo (Field) “Ativo” no DataSet:
1 |
Text := EmptyStr; |
Por útimo, claro, é necessário alterar os valores quando o usuário clicar no CheckBox. Para isso, implemente o seguinte código no evento OnCellClick
da DBGrid:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
var lValorColunaAtivo: string; begin if UpperCase(Column.FieldName) = 'ATIVO' then begin if ClientDataSet.FieldByName('Ativo').AsString = 'S' then lValorColunaAtivo := 'N' else lValorColunaAtivo := 'S'; // edita o DataSet, inverte o status e grava os dados ClientDataSet.Edit; ClientDataSet.FieldByName('Ativo').AsString := lValorColunaAtivo; ClientDataSet.Post; end; end; |
3) ComboBox dentro de uma célula
Para disponibilizar múltiplas opções para o usuário em forma de ComboBox, trabalharemos com a propriedade PickList
da classe TColumn
. No evento OnCreate
ou OnShow
do formulário, preencha essa propriedade com as opções que devem ser exibidas na coluna. No exemplo abaixo, ao clicar na coluna “Cidade”, a DBGrid apresenta as alternativas adicionadas:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
var lIndiceColunaCidade: smallint; begin // encontra o Ãndice da coluna "Cidade" lIndiceColunaCidade := ClientDataSet.FieldByName('Cidade').Index - 1; // preenche as opções DBGrid.Columns[lIndiceColunaCidade].PickList.Add('São Paulo'); DBGrid.Columns[lIndiceColunaCidade].PickList.Add('Maringá'); DBGrid.Columns[lIndiceColunaCidade].PickList.Add('Florianópolis'); DBGrid.Columns[lIndiceColunaCidade].PickList.Add('Rio de Janeiro'); DBGrid.Columns[lIndiceColunaCidade].PickList.Add('Rondonópolis'); DBGrid.Columns[lIndiceColunaCidade].PickList.Add('Porto Alegre'); end; |
Legal, porém, há um problema: o ComboBox só é exibido quando clicamos duas vezes na coluna, prejudicando a usabilidade. Como alternativa, utilize o evento OnColEnter
da DBGrid e habilite a propriedade EditorMode para essa coluna:
1 2 |
if UpperCase(DBGrid.SelectedField.FieldName) = 'CIDADE' then DBGrid.EditorMode := True; |
Faça o mesmo para o evento OnCellClick
para permitir a exibição do ComboBox ao alterar de linha:
1 2 |
if AnsiUpperCase(Column.FieldName) = 'CIDADE' then DBGrid.EditorMode := True; |
4) Ordenar os registros ao clicar no tÃtulo da coluna
Essa dica é uma boa, hein? E melhor, é fácil!
Para essa funcionalidade, devemos utilizar o evento OnTitleClick
da DBGrid, inserindo o código a seguir:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 |
var lIndexName: string; lOrdenacao: TIndexOptions; i: smallint; begin // retira a formatação em negrito de todas as colunas for i := 0 to DBGrid.Columns.Count - 1 do DBGrid.Columns[i].Title.Font.Style := []; // configura a ordenação ascendente ou descendente if ClientDataSet.IndexName = Column.FieldName + '_ASC' then begin lIndexName := Column.FieldName + '_DESC'; lOrdenacao := [ixDescending]; end else begin lIndexName := Column.FieldName + '_ASC'; lOrdenacao := []; end; // adiciona a ordenação no DataSet, caso não exista if ClientDataSet.IndexDefs.IndexOf(lIndexName) < 0 then ClientDataSet.AddIndex(lIndexName, Column.FieldName, lOrdenacao); ClientDataSet.IndexDefs.Update; // formata o tÃtulo da coluna em negrito Column.Title.Font.Style := [fsBold]; // atribui a ordenação selecionada ClientDataSet.IndexName := lIndexName; ClientDataSet.First; end; |
Observe que, ao clicar na tÃtulo das colunas, uma linha vertical aparece temporariamente na DBGrid. Isso ocorre em função da propriedade Options
> dgColumnResize
, que permite o redimensionamento das colunas com o mouse. Caso essa função não seja conveniente, desative-a para evitar esse efeito.
5) Alterar a fonte das linhas
Algumas vezes, é necessário formatar a fonte de algumas linhas para destacar o estado do registro. Utilizando o mesmo exemplo da coluna “Ativo”, suponha que os registros que estiverem inativos (“N”) devem ser marcados em vermelho e itálico. Essa funcionalidade também deve ser adicionada no evento OnDrawColumnCell
:
1 2 3 4 5 6 7 8 9 10 |
// verifica se o registro está inativo if ClientDataSet.FieldByName('Ativo').AsString = 'N' then begin // formata a linha em vermelho e itálico DBGrid.Canvas.Font.Style := [fsItalic]; DBGrid.Canvas.Font.Color := clRed; // pinta a linha DBGrid.DefaultDrawColumnCell(Rect, DataCol, Column, State); end; |
6) Linhas zebradas
Aproveitando a dica anterior, confira também como deixar a DBGrid “zebrada” no evento OnDrawColumnCell
, ou seja, alternar as cores de cada registro para aprimorar a visibilidade.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
var lLinha: integer; begin // obtém o número do registro (linha) lLinha := DBGrid.DataSource.DataSet.RecNo; // verifica se o número da linha é par ou Ãmpar, aplicando as cores if Odd(lLinha) then DBGrid.Canvas.Brush.Color := clMenu else DBGrid.Canvas.Brush.Color := clMoneyGreen; // pinta a linha DBGrid.DefaultDrawColumnCell(Rect, DataCol, Column, State); end; |
7) Mover a posição da linha junto com a barra de rolagem
Quando o usuário move a barra de rolagem vertical na DBGrid, já notou que posição do registro não acompanha essa movimentação? Procurei alguma explicação na documentação do Delphi, mas não obtive sucesso. Mesmo assim, há uma forma de contornar esse comportamento, embora seja um pouco complexo. Primeiramente, é preciso herdar um componente da classe TDBGrid
para que possamos declarar o método que responde à mensagem de Scroll:
1 2 3 4 5 |
type TDBGrid = class(Vcl.DBGrids.TDBGrid) private procedure WMVScroll(var Message: TWMVScroll); message WM_VSCROLL; end; |
Em seguida, implementamos a função com o código abaixo:
1 2 3 4 5 6 7 |
procedure TDBGrid.WMVScroll(var Message: TWMVScroll); begin if Message.ScrollCode = SB_THUMBTRACK then Message.ScrollCode := SB_THUMBPOSITION; inherited; end; |
Agora, execute a aplicação, mova a barra de rolagem vertical e observe que a posição do DataSet acompanha automaticamente a movimentação  da barra.
8) Obrigar letras maiúsculas nas células
Como as células da DBGrid não possuem a propriedade CharCase
para configurar a digitação em maiúsculas, podemos implementar esse comportamento no evento OnKeyPress
:
1 |
Key := AnsiUpperCase(Key)[1]; |
9) Exibir “Sim” para o valor “S” e “Não” para o valor “N”
Se a intenção é converter os valores “S” e “N” para “Sim” e “Não”, respectivamente, basta utilizar o evento OnGetText
do campo (Field) do DataSet. No exemplo abaixo, faço essa conversão com uma coluna que armazena estes valores:
1 2 3 4 |
if Sender.AsString = 'S' then Text := 'SIM' else Text := 'NÃO'; |
10) Navegar entre as células com as teclas de seta, mantendo o efeito de linha selecionada (dgRowSelect)
Quando ativamos a propriedade dgRowSelect
, a DBGrid impede a navegação entre as células com as teclas de seta. Lembro-me que um dos usuários da minha aplicação reportou uma queixa desse comportamento. Para solucioná-lo, deasativei a opção dgRowSelect
da propriedade Options
da DBGrid e implementei o código abaixo no evento OnDrawColumnCell
:
1 2 3 4 5 6 7 |
if Rect.Top = TStringGrid(DBGrid).CellRect(0, TStringGrid(DBGrid).Row).Top then begin DBGrid.Canvas.FillRect(Rect); DBGrid.Canvas.Font.Color := clWhite; DBGrid.Canvas.Brush.Color := clHighlight; DBGrid.DefaultDrawDataCell(Rect, Column.Field, State) end; |
Pessoal, e agora vem a melhor parte: desenvolvi um pequeno exemplo com todas as dicas mencionadas acima! Baixe-o neste link.
Um grande abraço a todos!
Fantástico André … eu não fazia ideia que poderia inserir imagem na DBGRID essa matéria já me deu algumas ideias legais para implementar no meu sistema, porem fica uma duvida como alterar apenas a cor de uma coluna ? Ex: na dbgrid aparece a coluna código, cliente e data de vencimento como fazer a células da data de vencimento ficarem de cores diferentes em casa de atraso? eu sei com fazer a linha inteira mas só uma célula não . Muito Obrigado por toda ajuda e continue com esse excelente trabalho .
Opa, André, tudo certo?
Para alterar a cor apenas de uma coluna é preciso envolver o código de pintura em uma função IF que indique essa coluna.
Utilizando o cenário que você mencionou, sobre a data de vencimento, este seria a codificação no evento OnDrawColumnCell:
if AnsiUpperCase(Column.FieldName) = 'DATAVENCIMENTO' then
begin
// se o cliente estiver atrasado
if ClientDataSet.FieldByName('Situacao').AsString = 'A' then
begin
// formata a linha em vermelho
DBGrid2.Canvas.Font.Color := clRed;
DBGrid2.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
end;
Abraço!
André,
Gostaria de parabeniza-lo, pela clareza e funcionalidade das dicas encontradas em seu Blog. Nunca tinha visto dicas tão fáceis de implementar, e tão bem explicadas quanto as suas.
Eu sou um programador das antigas (DBase, Clipper, etc) e estou começando a me aventurar no mundo do Delphi. Fiz um Curso de Delphi, e tenho assistidos vários tutoriais…
Gostei muito das suas dicas, e o mais legal.. os Códigos Fonte dos exemplos que baixei do seu site, realmente Funcionaram de primeira. Coisa rara, pelo que percebi em vários outros sites por ai…
Eles estão me dando excelente dicas para alguns projetos que estou tentando desenvolver.
Um grande abraço.
Olá, André, tudo bem?
Agradeço fortemente pelo seu comentário e pelo reconhecimento! Sempre comento com a minha noiva que são comentários como o seu que me mantém motivado para continuar o trabalho no blog.
Fico contente que os artigos e os exemplos lhe ajudaram! Espero continuar contribuindo com a comunidade Delphi e apoiando cada vez mais programadores!
Conte comigo para o que precisar nessa nova empreitada com o Delphi.
Obrigado novamente!
Grande abraço!
André,
Percebi que você é cara bastante experiente em Delphi, então vou te pedir uma ajuda. Eu já li seu artigo sobre os erros de Access Violation, e me ajudou muito. Mas estou com um erro destes que está me deixando de “cabelos brancos”.
O erro está descrito neste Forum do DevMedia no seguinte link: http://www.devmedia.com.br/forum/access-violation-at-adress-0057943a/530850
Se você conseguir me ajudar eu te agradeço muito.
André
Olá, André! Já nos falamos por e-mail e aparentemente o problema foi resolvido, certo?
Abraço!
Fala André,
Parabéns pelo artigo, ficou muito bem explicado todas as 10 dicas e foram muito úteis.
Gostaria de saber se existe uma maneira de aumentar a altura das linhas do TDBGrid, eu tentei com THackGrid(DBGrid1).DefaultRowHeight mas não funcionou.
Muito obrigado e parabéns mais uma vez.
Olá, Robson, tudo certo?
Que estranho, o código que você informou deveria funcionar. Fiz um teste no projeto do artigo e a altura mudou de tamanho.
Vou entrar em contato com você, ok?
Abraço!
Robson e Batera, bom dia. Deu certo alterar a altura da linha do dbgrid?
Estou utilizando desta forma, porém sem sucesso.:
depois da sessão uses e antes da declaração type do form
type
THackDBGrid = class (TDBGrid)
procedure AllRows (DBGrid: TDBGrid; NewHeight: Word);
end;
Após a diretiva {$R *.dfm}:
procedure THackDBGrid.AllRows (DBGrid: TDBGrid; NewHeight: Word);
var
i: DWord;
begin
for i := 0 to THackDBGrid (DBGrid).RowCount – 1 do
THackDBGrid (DBGrid).RowHeights [i] := NewHeight;
end;
E chamo assim:
Se quiser alterar a altura de todas as linhas use:
THackDBGrid(DBGrid1).AllRows (DBGrid1, 40);
Se quiser alterar a linha de apenas uma linha use:
THackDBGrid(DBGrid1).RowHeights[0] := 40;
Fala, Ivan, tudo certo?!
Eu e o Robson trocamos alguns e-mails sobre esse comportamento. Vou encaminhá-los para você.
Abraço!
Fala batera, blz companheiro?
Eu consegui o resultado que precisava da seguinte forma:
No Object Inspector, nas propriedades do DBGrid, deu defini o fonte size como 16, por exemplo;
No evento OnDrawColumnCell do DBGrid eu modifico o font.size para um tamanho menor, e utilizo o DefaultDrawColumnCell para definir a altura levando em conta a font.size que esta definido lá nas propriedades.
DBGrid1.Canvas.Font.Size := 10;
DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
Funciona que é uma maravilha, não consegui ainda centralizar o texto na vertical.
Muito obrigado pela contribuição, Ivan!
Pesquisei bastante, mas essa solução nem me passou pela cabeça, rsrs.
Mais um problema resolvido! 🙂
Grande abraço!
nao funcionou comigo essa ideia de aumentar o tamanho e diminuir DrawColumnCell.. Visualmente funciona, mas basta clicar que fica duas escrita o tamanho GRANDE e o tamanho 10
Olá, Daniel, tudo certo?
Depois de alguns testes, observamos que essa solução realmente não é eficiente.
A ideia que sugeri para o Robson, na época, era utilizar uma Grid de terceiros que já tenha essa funcionalidade ou criar a própria Grid, embora essa última opção exija um pouco mais de pesquisa e conhecimento da VCL do Delphi.
Abraço!
Olá Andre! Boas dicas e muito úteis. Obrigado. Veja se pode ajudar-me nesta questão: queria inverter o dbgrid, colocar as colunas como linhas e as linhas como colunas. Se souberes e puder ajudar-me, agradeço desde já. Valeu. Abçs… Flavio
Olá, Flávio, tudo certo?
Rapaz, acredito que esse tipo de inversão só pode ser feito com componentes de terceiro. Uma vez fui informado que o componente InfoPower TwwDBGrid trazia essa funcionalidade, mas nunca tive a oportunidade de utilizá-lo. Se eu souber de algo, entro em contato.
Abraço!
Existe um componente pago da DevExpress que faz isso, se chama PivotGrid.
Olha aÃ! O Artur deu uma boa dica!
Muito obrigado, Artur!
Bom dia André,
Faço minhas as palavras do André Marsola, achei o conteúdo fantástico.
Estou usando a dica: 1) Imagem dentro de uma célula
Mas não consegui identificar a parte referente a “OnGetText” no meu caso o tipo de dados é booleano, mas pelo o que eu vi é indiferente, não consegui achar o evento citado no dataset.
Estou usando o RAID STUDIO XE7 com o FireDAC, mais especificamente o FDQuery.
Será que poderia me ajudar?
Desde já muito obrigado e parabéns, serei um leitor assÃduo.
Olá, Luiz, tudo certo?
Muito obrigado pelo feedback! 🙂
O evento “OnGetText”, na verdade, é do componente TField, e não do DataSet. No caso do TFDQuery, clique com o botão direito no componente e depois em Fields Editor. A janela que for exibida exibirá todos os campos (Fields) existentes na Query. São nesses campos que o evento “OnGetText” é disponibilizado!
Espero ter ajudado!
Abraço!
Olá,
muito boa suas dicas. Tenho uma pergunta, terias algumas dicas para agilizar o carregamento de dados no dbgrid? Por exemplo, usar o DisableControls antes de dar o CommandText e depois EnableControls acelera o carregamento do dataset para o dbgrid?
Agradeço desde já.
Olá, Artur, tudo bem?
Obrigado pelo feedback!
Como já me questionaram algo semelhante, ao invés de responder a sua pergunta, eu vou elaborar um artigo, pode ser?
Vou postá-lo essa semana ou na semana que vem!
Abraço!
Tem como fazer celula multilinha?
Olá, Eddie, tudo bem?
Fiz algumas pesquisas na internet e não obtive muito sucesso. Pelo que notei, esse recurso é mais fácil com a TStringGrid.
Mesmo assim, dê uma olhada no link abaixo:
http://www.scriptbrasil.com.br/forum/topic/150114-resolvido%C2%A0alterar-altura-da-linha-do-dbgrid-automaticamente/
O autor do tópico menciona o componente TJvDBGrid da biblioteca Jedi. Talvez possa ser a solução para você! 🙂
Abraço!
Tem como colorir apenas uma célula? por exemplo colorir apenas a célula onde fica um valor de apenas determinada linha.
Olá, Jackson!
Sim, é possÃvel. Basta controlar as condições no evento OnDrawColumnCell. Veja o exemplo abaixo:
Abraço!
André, primeiramente parabéns pelos codigos.
Muito bem explicados e totalmente praticos e funcionais.
Mas to com uma dúvida…
Gostaria de que ao maximizar a tela, ou fazer um resize qualquer… eu escolher uma coluna para acompanhar o resize, ou então todas as colunas se encaixem ao layout da tela.
Já vi vários codigos na intenet mas ta dificil algum que realmente funcione.
Isso é para eliminar o espaço em branco que fica quando as colunas estão fixas.
Agradeço desde já;
Olá, Lucas, tudo bem?
Obrigado pelo feedback sobre os artigos! 🙂
Já existe um tutorial no DevMedia sobre o redimensionamento automático de colunas:
http://www.devmedia.com.br/redimensionar-colunas-dbgrid-delphi/18076
Usei essa implementação uma vez e funcionou!
Abraço!
Bom dia Andre, desde ja fica aqui o meu agradecimento, tenho lido os seus tutorias e eles tem me ajudado bastante, estou com dois problemas queria saber se pode me ajudar.
1º – Tenho uma estrutura de Tabelas assim: Um tabela de atendimento, o qual o campo cliente dessa tabela atendimento puxa esse dado cliente de outra tabela, no meu DBGrid, mostra o código do cliente invés do nome, como poderia fazer para mostrar o nome invés do código?? (Minha base dados e conectada com os componentes dbexpress e base firebird).
Olá, Felipe, tudo bem?
Para exibir o nome na consulta, você precisará trabalhar com comandos JOINs na sua instrução SQL. Esses comandos fazem junções entre 2 ou mais tabelas, trazendo valores relacionados.
Por exemplo, considere a consulta abaixo na tabela de Atendimentos:
Essa consulta irá retornar apenas o código do cliente, certo? Para trazer o nome, é necessário unir as tabelas de Atendimentos e Clientes através de um INNER JOIN:
Quando possÃvel, confira o link abaixo para aprender melhor estes comandos:
http://thomaslarock.com/2012/04/real-world-sql-join-examples/
Abraço!
Boa Tarde, obrigado pela atenção e pela resposta. Vamos la, eu acho que pelo jeito que estou fazendo aqui esse comando não ira funcionar. Quando estou no meu aplicativo (na tabela atendimento) vou preenchendo os campos, quando chego no campo cliente, esse campo é um DBLookupCombobox que esta ligado em outra tabela cliente, nessa tabela já tem vários clientes cadastrados. No meu DBGrid aparece o código desse cliente invés de ser o nome.
Olá, Felipe!
Aparentemente é uma configuração incorreta do campo Lookup no DataSet.
Para exibir o nome, você deve criar o campo Lookup com as seguintes propriedades:
KeyField: Campo que está ligado à outra tabela (Código do Cliente da tabela de Atendimento)
DataSet: DataSet de origem (DataSet de Clientes)
LookupKeys: Campo do DataSet de origem (Código do Cliente da tabela de Clientes)
Result Field: Campo de nome do cliente (Nome do cliente da tabela de Clientes)
Dessa forma, quando você informar o código do cliente no cadastro do atendimento, o campo Lookup (Nome) exibirá automaticamente o nome do cliente.
Abraço!
Nos componentes DBEdit, Lookup, estao exibindo corretamente os nomes e os codigos, porem no DBGrid que aparace os códigos, e quero os nomes.
Certo, Felipe. Então você deve adicionar o Field Lookup (que traz o nome) na DBGrid também. Para isso, acesse o Columns Editor da DBGrid e adicione uma nova coluna, indicando o campo Lookup na propriedade FieldName.
Abraço!
Sim, todos estão inseridos por esse meio, porem aparace o código invés de ser o nome.
Vou lhe enviar um exemplo, Felipe.
Abraço!
Você pode enviar novamente? Obrigado, pela ajuda Andre e me desculpe a insistência, muito obrigado mesmo, ainda bem que existe pessoas como você. Obrigado
Enviei, Felipe!
Olá andré estou com uma duvida no dbgrid, pois eu preciso criar uma nova coluna que não esta vinculado no meu data set, para que o usuário digite nessa nova coluna um valor direto pelo dbgrid, mas o dbgrid não permiti ele digitar, e se eu tento forçar pelo codigo ele da um erro de acces violation, você pode me informar se é possÃvel eu fazer tal alteração pelo dbgrid em uma coluna nova que não está vinculada ao dataset e como posso fazer isso?
Boa noite, Renan!
Vou entrar em contato com você. Abraço!
Olá Andre, tudo blz?
Sou Anderbelluno do Active.
Estou seguindo suas dicas, me veio uma duvida aqui,
teria como usar o IBDataSet no lugar o ClientDataSet?
Estou tentando modificar, mas estou com um pouco de dificuldades.
Teria como vc me dar uma força?
Obrigado.
Opa, tudo certo, Anderson?
Vou entrar em contato por e-mail, ok?
Abraço!
Bom dia! Eu segui a dica do Ivan Juste para aumentar a altura da linha. Funcionou mas, os dados não ficam alinhados verticalmente (o texto fica no alto da célula). Haveria algum jeito de centralizar na vertical. Agradeço.
Olá, Luis, tudo bem?
Encontrei um método no site ScriptBrasil (e fiz algumas adaptações) que talvez poderá ajudá-lo:
Basta chamá-lo no evento OnDrawColumnCell, após redefinir o tamanho da fonte:
Espero ter ajudado. Abraço!
Funcionou perfeitamente! O problema é que a gente sempre quer tudo ao mesmo tempo, agora! kkkk
Meu DBGrid é zebrado, tem Ãcones e quando seleciono a linha ela muda de cor. Quando eu coloco estas firulas, o alinhamento vertical não acontece. O Rect é mudado. O que eu poderia alterar para que fosse centralizado? Outra pergunta: É possÃvel que a linha selecionada aparecesse mesmo quando se movimentasse o Scroll. No meu código ela some. Agradeço
procedure TformPrincipal.DBGrid2DrawColumnCell(Sender: TObject;
const [Ref] Rect: TRect; DataCol: Integer; Column: TColumn;
State: TGridDrawState);
var
nLinha: integer;
image_1: TImage;
begin
image_1 := TImage.Create(Self);
image_1.Picture.LoadFromFile(‘C:\SGE\imagens\Trash-32.png’);
DBGrid2.Canvas.Font.Size := 10;
AlinharVertical(Column.Field.AsString, Rect, Column.Alignment);
nLinha := DBGrid2.DataSource.DataSet.RecNo;
if Odd(nLinha) then
DBGrid2.Canvas.Brush.Color := clWhite
else
DBGrid2.Canvas.Brush.Color := $00F4E6D9;
DBGrid2.DefaultDrawColumnCell(Rect, DataCol, Column, State);
if Rect.Top = TStringGrid(DBGrid2).CellRect(0, TStringGrid(DBGrid2).Row).Top then
begin
DBGrid2.Canvas.FillRect(Rect);
DBGrid2.Canvas.Font.Color := clWhite;
DBGrid2.Canvas.Brush.Color := clHighlight;
DBGrid2.DefaultDrawDataCell(Rect, Column.Field, State);
image_1.Picture.LoadFromFile(‘C:\SGE\imagens\Cancel2-32.png’);
end;
if Column.Field.FieldName = ‘VISUALIZAR’ then
begin
DBGrid2.Canvas.Draw(Rect.Left + 15, Rect.Top + 5,image_1.Picture.Graphic);
end;
image_1.Free;
end;
Olá, Luis!
Bom, já que você tem outros tratamentos no mesmo evento, devemos tomar cuidado para que um comportamento não anule o outro, que é o que provavelmente está acontecendo. Como a sua necessidade é um pouco mais complexa, eu vou conversar com você por e-mail, ok?
Abraço!
Olá André ! Cara, parabéns pelo seu artigo. Show de bola. Minha dificuldade: Não uso ClientDataSet, estou usando firedac, TFDQuery. Para ordernar a coluna, da erro, pois os parametros são outros. Vc ja fez ordenação usando um dataset do firedac ? se tive, tem como mandar o código ? Vlw !!!
Olá, Romeu, tudo bem?
Realmente, para o componente TFDQuery, o código é um pouco diferente. Confira:
Espero ter ajudado. Abraço!
Retornando o problema.
Em todos os seus exemplos você usa o ClientDataSet, mas como sempre usei os componentes ZEOS, nunca utilizei o ClientDataSet e nem sei o que ele realmente faz.
Com isso todos os exemplos exigem alterações, e como não sei bem o que o ClientDataSet faz não sei o que alterar.
Poderia me dar uma dica de como alterar de ClientDataSet para somente o DataSource e zTable?
Olá, Roberto, boa noite.
Como você já usa o zTable, não é necessário utilizar o ClientDataSet. No artigo, este componente foi utilizado apenas como exemplo de um DataSet com dados.
Infelizmente não tenho conhecimento com os componentes do Zeos, mas acredito que apenas algumas alterações mÃnimas sejam necessárias.
Abraço!
Muito obrigado André !!! Perfeito.
Ah, André, sou cristão, e o que vou dizer, não é apologia. Mas hoje vi esta frase, e creio que ela se aplica a você com toda certeza: “Grandeza não é se destacar acima dos pequenos, mas ajudar os pequenos a se destacarem acima dos grandes”. Cara, parabéns e muto obrigado pela sua “disponibilidade” em nos fazer crescer. Vlw mesmo.
Boa tarde, Romeu!
Fiquei muito feliz com as suas palavras! Receber um feedback como o seu é o combustÃvel que me motiva a continuar ajudando a comunidade de programadores Delphi.
Muito obrigado e que Deus lhe abençoe!
Bom dia Andre, tudo bem?
Preciso que na coluna da grid apareça a imagem ou um texto qualquer.
Estou utilizando o imagelist, apenas para uma condição deve-se aparecer a imagem, para as demais mostrar o próprio texto que estiver retornando.
Isso é possÃvel?
Olá, Michel!
Sim, é possÃvel. Basta codificar a condição no evento OnDrawColumnCell conforme o 2º exemplo do artigo:
Para exibir a imagem dentro da DBGrid, siga as orientações do link abaixo:
http://delphi.help-me-please.com/tipsandtrick/drawing-an-image-in-a-cell-of-a-delphi-dbgrid/
Espero que lhe ajude.
Abraço!
Dica Perfeita, foi muito útil !! Obrigada!
Sinto-me grato por ter ajudado!
Obrigado pelo comentário!
Oi André! Os seus exemplo foram muito úteis para mim, funcionou perfeitamente. Estou agora com uma dúvida. Não sei se o que preciso é possÃvel fazer… eu criei o check para um valor no banco de dados que pode ser T ou F. Eu precisaria que quando fosse F este valor, a célula do lado pudesse estar habilitada, e quando fosse T, a célula do lado estar desabilitada para edição. Se eu fizer por exemplo,
GridMov.Columns[11].ReadOnly := True vai estar desabilitado para todas as células daquela coluna… não sei se isso é possÃvel fazer….
Olá, Natana, tudo bem?
A sua dúvida parece ser um pouco complexa. Vou entrar em contato por e-mail!
Bom dia! Apenas para dar um feedback sobre o que o André me retornou e resolveu meu problema!
No evento OnCellClick da célula que será habilitada/desabilitada.
Se o valor for “T”, a coluna fica ReadOnly.
Mais uma vez obrigada André pela sua ajuda!
Muito obrigado por ter dedicado um tempo para voltar ao blog e postar esse comentário, Natana!
Fico feliz em ter ajudado! 🙂
fiz a dica 2 tudo certinho ta tudo blz, só falta uma coisa: Salvar no Banco de Dados
ja tentei colocar um botão com o ApplyUpdates(0); mas sem sucesso
Olá, Elias.
Não consigo orientá-lo com precisão sem analisar o código, mas experimente utilizar o evento OnReconcileError do DataSet. Por algum motivo, está ocorrendo algum erro na gravação do registro ou o DataSet não está incrementando o ChangeCount após a alteração.
Abraço!
Fala André, bacana teu artigo. Já fiz uma implementação usando um dos seus exemplos. Obrigado pelo artigo.
Estou à procura de uma solução para um DBGrid que está com a propriedade MultiSelected marcada. Preciso que quando teclar ESPAÇO ele deixa aquela linha marcada.
Só esta marcando quando teclo CONTRO+CLIQUE na linha. Tem alguma dica, man? Abraço.
Olá, Cleiton, tudo bem?
É possÃvel configurar esse comportamento na TDBGrid, sim!
Para isso, é necessário trabalhar com o evento OnKeyDown, adicionando o seguinte código:
Tranquilo, né? 🙂
O detalhe está na primeira condição, que verifica se a tecla pressionada pelo usuário é a barra de espaço. O código dentro da condição alterna o valor entre ‘S’ e ‘N’ para marcar/desmarcar o checkbox.
Abraço!
Boa tarde,
Tudo bem ?
Veja se pode me ajudar. Estou com a seguinte dificuldade.
Tenho a classe abaixo, e precisava popular os campos no DBGrdi com RTTi
como devo fazer ? Obrigado.
TColumn = class(TCustomAttribute)
{ Mapeia um campo de uma tabela do banco de dados }
private
FName: String;
FCaption: String;
FLength: Integer;
FLocalDisplay: TLocalDisplayColumn;
FTransiente: Boolean;
public
[TableName(‘TELEFONES’)]
TTelefones = class(TPersistent)
private
public
published
[TColumn(‘FONE’, ‘Fone’, 35,[ldGrid, ldLookup, ldComboBox], False)]
property TELEFONE: string read FTELEFONE write setTELEFONE;
end;
Olá, Alexandre!
Já estamos nos falando por e-mail! 🙂
Abraço!
e ai ANDRE, conseguiu uma solução para este último problema RTTI? Tambem estou eperando pela resposta, obrigado.
Olá, Wilton!
No caso do Alexandre, que postou o comentário anterior, o problema estava relacionado com o tutorial que ele acompanhou para desenvolver o projeto.
Como este assunto é bem especÃfico, envie a dúvida com o máximo de detalhes para “[email protected]”.
Abraço!
Gostaria de uma pesquisa de codigo dentro do dbgrid(coluna,)
Poderia dar um exemplo?
Olá, Luis, já estamos nos falando pela página do Facebook.
Abraço!
Olá André, parabéns pelo seus artigos, me ajudou muito e melhorou muito meus códigos, pois conseguia fazer muita coisa, mas ficava uns códigos meio complicado de entender e extenso. Obrigado. Espero que continue compartilhando de seu conhecimento com a comunidade DELPHI.
Obrigado!
Olá, Cristiano, tudo bem?
Agradeço pelo feedback e também pelos elogios!
Fiquei feliz ao saber que o artigo melhorou a qualidade do seu código. Continue acompanhando!
Abraço!
Boa Noite andré, parabéns pelo seu artigo, sou mais um que estou precisando do seu conhecimento, tenho um dbgrid que listo os produtos vendidos, gostaria de pegar todos
os produtos de um determinado campo, por exemplo: no dbgrid tem o campos ‘produto’ , ‘tipo’, valor….ok logo no exemplo esta listado no campo produtos os seguistes itens : ‘calça’, ‘blusa’, ‘cinto’, … ok … entao gostaria de pegar todos os produtos { ‘calça’, ‘blusa’, ‘cinto ‘ } e coloca em um Edit. deste ja agrateço
Boa noite, saezo, tudo bem?
Este comportamento pode ser feito de uma forma bem simples. Primeiro, sabemos que o DBGrid está conectado a um DataSet, certo? Podemos percorrer esse DataSet e concatenar o valor do campo “Produto” em uma variável. Depois, basta atribuir essa variável no componente TEdit. Veja o exemplo:
Espero ter ajudado.
Abraço!
Bom dia! André, acompanho seus posts e exemplos e já consegui utilizar vários deles. O que queria perguntar é se vc teria um exemplo ou mesmo uma dica de como retirar valores de um CheckListBox1 com vários itens, por exemplo: 237,001,444, pegar os que estão marcados (237, 444), e usar num Query1 da paleta BDE, onde seria esse SQL: Select * from cobranca where codigo in (‘237′,’444’). Não consegui preencher corretamente. Desde já agradeço.
Olá, Márcio!
Tente usar o código abaixo como base:
Espero que lhe ajude!
Abraço!
Olá André,
Parabéns pelo conteúdo. Muito bom.
Encontrei ele, pois, estava buscando uma forma de inserir imagem no dbgrid, foi então que usei como base a dica 1 deste post.
O que ocorre é que quando seleciono a célula, o texto da Field aparece por baixo da imagem.
Essa é uma tela de consulta dinâmica, então pode ser que em algum momento o tamanho da coluna mude, de forma que não dá para definir um tamanho fixo para a imagem, escondendo assim o texto.
Tem alguma forma de resolver isso?
Já tentei usar da outra forma que está em um link acima e também não rolou.
Muito obrigado.
Olá, Marcelo, obrigado!
Vou pedir para que você siga o que está na dica 2 para manipular o evento OnGetText do Field:
Dessa forma, no evento para ler o valor efetivo do campo, atribuÃmos uma string vazia, evitando que ele apareça por baixo da imagem.
Abraço!
Foi isso mesmo que fiz. Achei que existia uma outra forma, pois, como disse, esse procedimento estou usando em um form de pesquisa que uso para várias query. Mas como uso todas as querys de pesquisa em apenas um DM, facilitou.
Muito obrigado e parabéns novamente pelo blog.
Que bom que funcionou, Marcelo.
Boa sorte no projeto!
Abraço!
Oi André, tudo certo? Como sempre, paro no seu blog para aprender um pouco mais. Agora já virou professor André.
Eu estou com dificuldade de implementar uma ideia e talvez você possa me ajudar.
Eu quero que algumas colunas do meu dbGrid aceitem fórmula, igual o EXCEL. [:o]
Imagine a tabela de itens do pedido de vidraçaria
CODIGOPRODUTO INT
PRECO Numeric
AREA Numeric
PrecoFinal
Eu gostaria muito que o usuário pudesse digitar a seguinte string na coluna AREA:
“= 120*240” ou até mesmo “=120×240”
Fica convencionado que toda vez que a string começar com “=” (sinal de igual) então eu vou tentar resolver a fórmula
Estou utilizando a classe TParser da biblioteca JEDI para resolver a equação e gravar a Area do item na tabela
Qual seria o melhor evento para validar esta fórmula?
Eu posso utilizar isso nos eventos onSetText ou onValidate do ClientDataset?
Grande abraço.
Boa noite, Ricardo! Bem interessante essa funcionalidade!
Bom, para este contexto, eu recomendo a utilização de uma TStringGrid ao invés de uma TDBGrid. O componente TStringGrid possui caracterÃsticas e propriedades que permitem simular melhor uma planilha do Excel.
Acredito que a parte mais difÃcil dessa codificação será a interpretação da fórmula dentro das células. Talvez você terá que codificar um Interpretador (opcionalmente utilizando o Design Pattern Interpreter) para traduzir cada expressão da fórmula, considerando possÃveis erros de digitação e caracteres inválidos.
Infelizmente não conheço o TParser do Jedi. Mesmo assim, se este componente já dispor a inteligência de interpretar fórmulas, já é meio caminho andado!
Abraço!
Boa noite, André. Tudo bem ?
Surgiu uma dúvida com relação ao DBGrid que no meu caso não está funcionando. Bom, para alterar a apresentação de dados em uma coluna se usa o evento OnGetText, correto ? Porém, para isso, eu tenho que tornar os campos persistentes através do Fields Editor. O meu caso é que eu estou utilizando um TFDQuery e as instruções SQL variam. Eu tenho um campo em uma tabela de banco SQLite do tipo inteiro para guardar valores Boolean. Em vez de mostrar valores 0 e 1 eu queria mostrar “Não” ou “Sim”. Escrevi o código abaixo:
E está apresentando o seguinte erro: os dados são mudados corretamente nas linhas que não estão selecionadas no DBGrid (onde é 0 aparece Não e onde é 1 aparece Sim). Porém, na linha selecionada, ele apresenta as duas informações sobrepostas (dá para ver pedaços dos números atrás dos textos).
Você sabe onde estou errando ?
Grande abraço.
Olá, Adalberto, como vai?
Para utilizar o evento OnGetText, você não precisa necessariamente criar Fields persistentes. A atribuição deste evento pode ser feita em tempo de execução, como, por exemplo, no evento OnAfterOpen do DataSet.
Dessa forma não será necessário trabalhar com o Canvas da DBGrid.
Abraço!
Maravilha André… Aprendi mais uma.
Muito obrigado e abração.
Boa tarde, André Celestino!
Cara, fiz o Download do seu exemplo, perfeito!
Por gentileza André, poderia me ajudar?
Como faço para que meu DBGrid faça a soma, por ex: da coluna “vendas” e me retorne o “valor Total:” no final da coluna?
Olá, Julio!
Infelizmente o componente
TDBGrid
nativo do Delphi não traz um recurso para adicionar um “rodapé” na parte inferior com as somas das colunas. Alguns componentes de terceiros possuem essa funcionalidade, como oTdxGrid
da DevExpress.Uma alternativa é criar um campo agregado (Aggregate) no DataSet informando a expressão de soma e exibir o valor desse campo em um componente
TLabel
. Outra alternativa é trazer este valor somado já na consulta SQL, dispensando a codificação do lado Delphi.Obrigado pelo comentário. Abraço!
Muito bom, aprendi bastante. Eu só queria saber como é que eu faço para usar estas dicas em um form Base onde os outros que herdam dele? Tentei fazer um TypeCast mas não deu certo.
Uso os componente de acesso a dados do FireDac, no caso o TFDQuery. Na dica de ordenação de colunas não deu certo essas linhas.
Como usar isso tudo na ordenação sendo com o TFDQuery?
Olá, Jeová, como vai?
No caso do FireDAC, há algumas alterações nesse código de ordenação:
1) Use
TFDSortOptions
ao invés deTIndexOptions
na variável de ordenação;2) Use
[soDescending]
ao invés de[ixDescending]
ao definir o Ãndice em ordem descendente;3) Modifique o código que adiciona o Ãndice na Query para:
O resto continua igual! 😉
Abraço!
Obrigado pela dica André, dei uma olhada no componente.
Você me indicaria um material bom (Livros, PDF) que eu possa estar adquirindo?
Olá, Julierme, tudo bem?
Bom, acredito que você está se referindo a algum material sobre o uso do componente
TDBGrid
, certo?Se este for o caso, eu recomendo os cursos sobre FireDAC, que abrange a tecnologia mais recente de conexão com banco de dados do RAD Studio e também algumas técnicas com o
TDBGrid
.Mas fique tranquilo, Julierme. Trabalhar com a o componente
TDBGrid
é bem fácil. Reserve um tempo para explorar as propriedades desse componente. Garanto que você vai descobrir muita coisa! 🙂Abraço!
André, boa tarde!
Estou precisando muito de uma dica, e notei que vc realmente tenta ajudar. Em um grid eu preciso agrupar as colunas em seções.
Exemplo: uma coluna acima Genéricos e abaixo as colunas dos laboratórios, depois vai ter uma outra seção Similares e abaixo dessa seção as colunas dos laboratórios. Não sei se me fiz entender, mas posso te mandar um print de um exemplo. Eu consigo fazer isso com os componentes nativos do Delphi?
Olá, Marcelo, boa noite!
Notei que você já entrou em contato comigo por e-mail.
Vamos conversar por lá, ok?
Abraço!
Boa noite amigo, tudo bem?
Estou desesperado para entregar um projeto no qual necessito de dois “subtÃtulos” no tÃtulo da coluna do DBGrid, como nesse exemplo: http://docwiki.embarcadero.com/images/RADStudio/Tokyo/e/9/94/Obj_grid.jpg
O que pega é que eu estou trabalhando com os campos ‘ADT’, vinculando, porém não obtive resultados, e não há material nenhum na internet além dessa foto… Poderia me ajudar por favor? Estou com prazo e desesperado… Desde já agradeço muito!!!!
Olá, Márcio!
Já estamos nos falando por e-mail! 😉
Boa tarde André L. Celestino,
Tenho pesquisado na internet, como fazer meu componente FDConcection, da paleta FireDac, conectar minha aplicação pela REDE.
Desenvolvi uma aplicação para minha igreja Assembléia de Deus, para melhorar a organização das informações.
E minha aplicação funciona perfeitamente Local, mas quando configuro o meu arquivo INI para acessar via rede o banco de dados no servidor não consigo conectar minha aplicação.
Gostaria muito de receber uma ajuda técnica para ter a solução.
Estou usando o Delphi XE8 e IBExpert para trabalhar no banco de dados com Firebird 2.5.
Olá, Ronaldo.
Para que eu possa ajudá-lo com mais assertividade, preciso analisar a mensagem de erro.
Vou entrar em contato com você. Abraço!
Bom dia, André.
Estou com a seguinte situação:
Tenho uma função onde passo como parâmetro um ClientDataSet, que por sua vez está ligado a um DBGrid através de um DataSource.
Na função manipulo o ClientDataSet e no final gostaria de posicionar o foco da DBGrid na segunda coluna (1).
Com tantas dicas de manipulação do DBGrid legais, me animei a escrever para ti para fazer a seguinte pergunta:
É possÃvel fazer algum tipo TYPECAST como:
Para poder obter o resultado que pretendo??? Todas as minhas tentativas até agora foram infrutÃferas.
Abraços. 🙂
Olá, Ricardo, como vai?
O typecast que você mencionou resultaria em um Access Violation, já que
TDBGrid
eTDataSource
são tipos diferentes.Se a sua intenção é focar uma coluna especÃfica na DBGrid, use a propriedade SelectedField informando o Field do DataSet no qual deve receber o foco. Por exemplo, para focar a coluna “Descricao”, basta preencher dessa forma:
Abraço!
André, boa tarde, tudo bem?
Primeiramente parabéns pelos ensinamento que passa a todos.
Estou com o seguinte problema:
No evento DrawColumnCell da dbgrid.
Até ai tudo bem, estava funcionando perfeitamente, porém, ativei os temas q o Delphi oferece e a partir dai, a linha selecionada aparece embaixo do valor em negrito o valor normal… um sobreposto ao outro.
quando saio da linha o valor volta a ficar certinho, com a formatação negrito e a cor certinha também.
Tem ideia do pq disso?
Olá, Felipe, boa noite! Excelente pergunta.
Este efeito ocorre quando se utiliza cores fixas no sistema. No seu caso, clBlue e clGreen. Ao alternar o tema da aplicação, essas cores realmente tendem a sobrepor ou divergir das cores do tema.
Para evitar este problema, recomendo a utilização de cores dinâmicas, como, por exemplo, clActiveCaption. Faça um teste: adicione um componente TEdit no formulário e o configure com essa cor. Em seguida, alterne os temas da aplicação e observe que a cor do componente é alterada conforme o tema selecionado. 🙂
Abraço!
André, boa noite.
Quando ajusto as colunas do DBGrid com o mouse, aumentando ou diminuindo a sua largura, tem algum evento informando o seu tamanho? ex. dbgrid.columns[0].width
Obrigado.
Olá, Auriston, tudo bem? Ótimo comentário.
Infelizmente não existe um evento published para capturar o redimensionamento de colunas. Para que isso seja possÃvel, você terá que criar um novo componente herdado de TDBGrid e incluir este novo evento, que será chamado pelo método protected “ColWidthsChanged”. Veja o exemplo:
Ao adicionar este componente no formulário, o evento OnColResize será exibido na lista de eventos. Basta implementá-lo como qualquer outro evento do componente TDBGrid.
Grande abraço!
Andre, bom dia, para colocar o checkbox o código abaixo eu coloco dentro do OnDrawColumnCell?
Exatamente, José! 🙂
Professor beleza? Preciso alterar vários dados de uma coluna da dbgrid, tenho que fazer uma estrutura de repetição, mas não estou conseguindo validar este código. O senhor poderia me ajudar?
Na hora que eu clicar no botão quero alterar todos os dados de uma coluna do dbgrid de ‘S’ para ‘N’, são 7.000 registros.
Olá, José!
Certo, vou apresentar o código com comentários:
Isso aÃ!
Abraço!
Boa noite. Gostaria muito de uma ajuda no projeto q estou fazendo. Tenho 2 DBGrid num form, onde no primeiro tenho uma lista de XMLs com algumas colunas, no 2º DBGrid tenho uma lista de pagamentos q foram importadas do excel. Gostaria de validar todas as linhas do DBG2 com um valor de todas as linhas do DBG1 e se o valor bater pintar a linha do DBG2. Uso 2 ClientDataSet temporarios para montar as informações dos DBG. Tentei fazer varredura nos 2 CDS no DrawColumnCell, mas parece q não tem fim a atualização do DBG e trava a aplicação
Olá, Mardson, tudo bem?
Vou entrar em contato para ajudá-lo melhor, ok?
Abraço!
Olá André, Boa Noite!
No Firemonkey como faço para substituir os valores por imagem? Exemplo.
Na minha tabela tenho um campo “A”-Aberto “I”-Iniciado “F”-Finalizado. Queria substituir esses valores por imagens, da seguinte forma, A=img1 I=img2 e F=img3.
Desde já agradeço!
Olá, Dirceu, tudo bem?
Infelizmente possuo pouco experiência com Firemonkey.
Você pode encaminhar as dúvidas sobre FMX para o Landerson Gomes ([email protected]). Ele também é MVP da Embarcadero e é especialista em Firemonkey!
Grande abraço!
Boa tarde André!
Você sabe me dizer um jeito de não mostrar a barra de rolagem? Eu achei um exemplo na internet que até tira a barra de rolagem, mas sempre que clico em outro registro do Grid ele foca no primeiro registro.
Se você souber de algum jeito, ou outro componente que eu possa usar, agradeço muito.
O exemplo que achei é esse:
Desde já agradeço!
Olá, Thais, tudo bem?
Esse código que você me enviou remove a barra de rolagem vertical do DBGrid de forma permanente. Inclusive reproduzi o teste no meu Delphi e funcionou normalmente.
Talvez o fato de você clicar em um registro e o DBGrid focar o primeiro registro esteja sendo causado por outro código no formulário. Veja se existem outros eventos implementados no DBGrid e, em caso positivo, remova-os temporariamente para fazer o teste.
De qualquer forma, este código do
ShowScrollBar
, em si, não traz nenhum impacto na navegação de registros do DBGrid. Este problema provavelmente está relacionado com outra codificação.Abraço!
André, sabe dizer se é possÃvel adicionar um checkbox no tÃtulo da coluna?
Dessa formar ao checar o tÃtulo da coluna, marcaria todos os registros como checado.
Abraço.
Olá, Guilherme! Desculpe-me pela demora.
Acredito que é possÃvel, mas a codificação não é simples. Será necessário criar de um novo componente (herdado de
TDBGrid
) para implementar essa funcionalidade, trabalhando com o Canvas do componente.Por outro lado, já que é algo complexo, uma alternativa é disponibilizar essa função (marcar todos) como menu suspenso do
TDBGrid
.Outra alternativa – nada elegante, eu admito – é inserir um componente
TCheckBox
por cima do tÃtulo doTDBGrid
, de forma que, visualmente, este componente “faça parte” da coluna. Em seguida, implementar a ação doTCheckBox
para marcar/desmarcar a coluna noTDBGrid
.Espero ter ajudado.
Abraço!
Opa, tudo bem? Estou com uma dúvida, gostaria de que quando eu estivesse na última linha em um célula do Grid eu coloque o foco em um Edit.
Não sei se entendeu mas qualquer coisa me avisa que te mando o exemplo que to fazendo.
Obrigado pela ajuda.
Grande abraço.
Olá, Fernando.
Vou pedir mais detalhes por e-mail, ok?
Abraço!
Bom dia André, Obrigado pelas dicas, tem me ajudado muito. Uma outra necessidade que surgiu: como eu edito um campo do tipo BLOB na célula do DBGrid, vc pode me ajudar por favor.
Obrigado,
Abraço
Olá, Claudir, boa tarde!
Por padrão, campos do tipo BLOB não são exibidos como editáveis nas células do DBGrid por conta do tamanho do conteúdo que este campo pode armazenar. Imagine, por exemplo, um texto de 5.000 caracteres sendo exibido em uma célula do DBGrid. É praticamente impossÃvel ler o conteúdo, certo? Além disso, trazer campos BLOB em uma consulta de dados que serão exibidos no DBGrid prejudica a performance da aplicação.
Por este motivo, a recomendação é exibir um Ãcone nessa célula, indicando que um “atalho” para o conteúdo do campo. Ao clicar neste Ãcone, é exibida uma nova janela apresentando o conteúdo do campo BLOB e pode ser editado pelo usuário.
Abraço!
Boa tarde, André! Parabens pelas dicas. Vai me ajudar muito nos meus estudos com o Delphi.
Estou com um probleminha que, embora seja simples, está me dando uma dor de cabeça incrÃvel. Vou explicar:
Uso o Firebird 2.3 e tenho duas tabelas, a CONTA_CORRENTE e a MOVIMENTO_CONTA_CORRENTE.
A CONTA_CORRENTE tem os principais campos: ID_CONTA_CORRENTE; DESCRICAO; SALDO_INICIAL.
A MOVIMENTO_CONTA_CORRENTE tem : ID_MOVI_CCORRENTE; ID_CCORRENTE; DATA; DOCUMENTO; VALOR; CED_DEB.
Uso a estrutura FDQuery / DataSetProvider / ClientDataSet.
A Grid da tabela de movimento da conta corrente que quero montar exibe: Data; Documento; C/D; Valor; Saldo; onde Saldo é um Field Calculated que recebe valores da seguinte Forma:
onde FSaldoLinha eu inicializo no Create do formulário como saldo inicial da conta corrente e atualizo toda vez que seleciono outra conta corrente.
Ele monta direitinho a grid. O problema é que quando eu movimento a grid através da barra de rolagem, eu não consigo ajustar o FSaldoLinha para a linha correspondente anterior ao registro que a Grid vaio atualizar.
Tem alguma outra forma de elaboração desta Grid?
Talvez no evento
OnDrawColumnCell
?Já tentei de várias formas mas não consegui.
Agradeço desde já por qualquer ajuda.
Forte abraço!
Olá, Samyr, como vai?
Já tentou utilizar o evento
OnAfterScroll
do DataSet? Este evento é disparado todas as vezes que há uma movimentação no cursor do DataSet. Talvez poderá atender a sua necessidade.Abraço!
Muito bom!! Parabéns
Obrigado, Icaro!
Bom dia Andre!
Estou iniciando os estudos em Delphi e estou com algumas dificuldades, poderia me orientar?
Tenho um dbgrid onde devo preencher o código do produto, e o valor deve ser preenchido automaticamente.
Fiz o seguinte código no evento OnChange do código do produto:
Mas não funciona. Preciso fazer mais alguma coisa?
Obrigada
Olá, Elisete.
Vou entrar em contato!
Excelentes dicas, André!
Me ajudou demais.
Parabéns!
Que bom que lhe ajudou, Wesley!
Obrigado pelo comentário. Abraço!
Boa tarde!
Estou fazendo um sistema de vendas (pdv), e os produtos que estão sendo comprados vão sendo inseridos no dbgrid, o que acontece é que, ao inserir o 3° produto ele muda a ordem dos itens ficando
2
3
1
e o correto seria
3
2
1
Já verifiquei algumas formas de ordenar, mas não posso clicar em botão ou no na coluna para ordenar, preciso que fique com a ordem que foi cadastrado o produto pois pretendo imprimir o cupom.
Estou utilizando clientDataSet.
Poderia me ajudar?
Olá, Elisete, bom dia.
Você pode utilizar a propriedade
IndexFieldNames
do componenteTClientDataSet
.Preencha essa propriedade com a coluna que você deseja ordenar.
Abraço!
Olá André, está me ajudando muito compartilhando seu conhecimento !
Tenho a seguinte dúvida, faço a importação de um XML de uma nota fiscal e os itens da nota ficam numa TcxGrid por exemplo, minha idéia seria comparar esses produtos com o cadastro, seja código de barras ou referência, para saber quais estão cadastrados ou não. Nesse caso mudando a cor da fonte para diferenciar e partir disso chamar o formulário para cadastrar aqueles que não estão no banco.
Posso utilizar o evento da Grid para colorir a linha usando o Locate para fazer essa verificação, qual sua dica para esse cenário?
Obrigado !
Ederson, boa noite!
Você pode usar a dica 5 do artigo (“Alterar a fonte das linhas”). Para facilitar a implementação, eu sugiro que você crie uma coluna virtual no DataSet (por exemplo, chamada “ProdutoEstaCadastrado”), preenchendo-a durante a importação do XML. Em seguida, utilizá-la como condição para altera a cor da fonte:
Espero ter ajudado. Abraço!
Boa tarde André !
Sua sugestão da coluna virtual ajudou demais.
Obrigado !
Boa tarde André!
Usei o seu exemplo do item 4 “Ordenar os registros ao clicar no tÃtulo da coluna” e me retornou um erro.
Segue:
“o provedor atual não oferece suporte para a interface necessária a funcionalidade Ãndice”
Estou saundo query e banco Microsoft Access.
Se puder me ajudar ficarei grato.
Olá, Mailson!
Acredito que você esteja utilizando os componentes ADO, certo?
A implementação de ordenação de registros com ADO realmente é diferente, assim como também é diferente com FireDAC.
Veja o terceiro tópico deste artigo:
https://www.andrecelestino.com/perguntas-respostas-comentarios-blog-faq/
Espero que ajude.
Abraço!
Olá André!
Legal essas dicas, obrigado
Andei lendo acima sobre como aumentar a altura da linha. Como ficou? Poderia enviar? Não estou querendo usar componente de terceiros. Grato.
Olá, Samuel!
Encontramos uma solução “parcial” para essa necessidade. Conseguimos aumentar o número da linha, mas não conseguimos centralizar o texto (verticalmente).
Se mesmo assim atender a sua necessidade, segue a instrução:
No Object Inspector, nas propriedades do DBGrid, defina o
Font Size
como 16, por exemplo.No evento
OnDrawColumnCell
do DBGrid, modifique oFont.Size
para um tamanho menor, e utilize oDefaultDrawColumnCell
para definir a altura levando em conta oFont.Size
que está definido nas propriedades.Abraço!
Bom dia.
Estou com um projeto para facilitar minhas atividades na empresa em que trabalho, mas como parei de programar há mais de 10 anos e estou voltando agora, além de esquecer muita coisa, o Delphi mudou muito.
Minha dúvida é; criei uma tabela do Access, e estou manipulando com uma ADOTable. Eu devo criar o primeiro registro e depois clicar em um botão para que o sistema gere [n] linhas de acordo com a quantidade de Paletes e com o número dos Paletes em Incremento. Até ai tudo bem, mas na última linha normalmente teremos menos volumes que nas demais e eu não estou conseguindo tratar este caso, como inserir a quantidade a menos na última linha?
[código removido por motivo de privacidade]
Olá, Huemerson!
Vou entrar em contato com você!
Abraço!
André, obrigado pelas dicas. Eu utilizei o checkbox mas quando eu tento mudar a cor da linha:
o checkbox desaparece. Existe alguma forma de isso não acontecer?
Olá, André, tudo certo?
Pelo que entendi, você desejar aplicar duas customizações no TDBGrid: exibir o checkbox e alterar a cor da linha, certo?
Essas duas customizações devem ser feitas no mesmo evento, chamado OnDrawColumnCell.
Eu não consigo me recordar se existe uma “sequência”, ou seja, se você deve primeiro pintar a linha e depois desenhar o checkbox, ou vice-versa.
Tente começar por aÃ, invertendo a sequência. Talvez já seja a solução!
Abraço!
Sim, obrigado pela dica, mas acabei resolvendo.
Estamos em 2022 e esse post me ajudou infinitamente a esclarecer algumas coisas sobre DbGrids, muito obrigado, excelente conteúdo, Parabéns!
Opa, Carlos!
Eu que agradeço pelo comentário!
Fico feliz por saber que o artigo lhe ajudou.
Abração!
Olá.
Tenho várias colunas na GRID (codigo, descricao, qtde, …) quando passo o leitor no código de barras e gostaria que ela fosse para o campo quantidade, ou abrisse uma nova linha. focado no campo codigo, como posso fazer isso?
Olá, William.
Bom, eu teria que analisar melhor o seu projeto, mas você pode focar colunas na Grid usando a propriedade SelectedIndex.
Clique aqui para ver um exemplo no StackOverflow.
Abraço!
Primeiro parabéns pelo conteúdo, no DBGrid preciso saber exatamente o conteúdo em uma célula quando digitado, como o conteudo popula o data set somente após mudar de celula, eu estou pegando o Keypress e somando letra a letra digitada e subtraindo quando dado backspace, o problema é quando o usuario cola algo na célula, selecionada alguns caracteres e apaga ou etc
Olá, Fabiano, tudo bem?
A única forma de capturar o valor atual de um célular (sem sair dela), é fazer um “hack” da classe TDBGrid para acessar a propriedade InplaceEditor.
Na seção “type” do seu formulário, adicione a seguinte linha:
type
TGridHack = class(TDBGrid);
Em seguida, utilize o evento OnKeyUp para capturar o texto à medida em que ele é digitado:
procedure TForm1.DBGrid1KeyUp(Sender: TObject; var Key: Word; Shift: TShiftState);
begin
if Key <> VK_RETURN then
ShowMessage(TGridHack(DBGrid1).InplaceEditor.EditText);
end;
Espero que atenda a sua necessidade.
Abraço!
André, parabéns e desde já obrigado por todas as dicas.
Eu gostaria de saber se teria como adicionar uma imagem na coluna do dgindicator, ou seja a coluna que fica mais a esquerda usada para exibir a posição do data set.
Eu preciso colocar uma imagem no topo para os usuários clicarem e abrir um pop-up para selecionar quais colunas serão exibidas na grid.
Olá, Juarez!
Rapaz, boa pergunta. Eu sei que existe uma forma, tanto é que componentes de terceiros, como DevExpess e Jedi, possui essa função. Porém, acho que não é tão trivial. Para desenhar uma imagem no tÃtulo da coluna do indicador, é necessário trabalhar com Canvas. Até pesquisei algo na internet, mas não obtive sucesso. Pelo que pude entender, não existe uma forma “nativa” de implementar essa funcionalidade. Talvez você terá que estender a classe TDBGrid e aplicar algumas customizações.
Alternativmente, você pode disponibilizar essa função no botão direito do mouse. Ou seja, ao clicar com o botão direito no tÃtulo da DBGrid, é disponibilizada uma lista com as colunas que podem ser exibidas ou escondidas.
Abraço!
Olá André, como sempre seus artigos são excelentes, estou com um problema que não estou conseguindo resolver, fiz uma grid, preenchi tudo em design, poucas alterações em modo de execução e apenas uma vez os campos vieram em modo edição, agora apenas um campo permite alterar e os demais estão como leitura, revisei, removi e adicionei novamente, mas o problema persiste, o campo data preciso alterar e não permite.
Olá, John.
Primeiramente, obrigado pelo feedback!
Bom, o atributo de somente leitura (propriedade ReadOnly) pode ser habilitado tanto no field do DataSet quando na coluna da Grid. Veja se está como False nos dois.
Verifique também se a propriedade “AutoEdit” do TDataSource está como True.
Por último, verifique se a propriedade “FieldKind” dos fields do DataSet foram criados como fkData. Se estiverem diferentes disso, a edição fica bloqueada.
Se mesmo assim não resolver, envie um email para “[email protected]”.
Abraço!
Parabéns pelo trabalho de excelência sempre!!!
Gostaria de saber como resolver uma questão. Seguinte, sempre que um usuário vai descendo os registros de um dbgrid pela seta do teclado, quando chega no último registro e ele tenta descer mais um, internamente a tabela fica em EOF, o usuário visualmente entende que está no último registro, mas se tentar editar, por exemplo, não irá conseguir pq está em EOF… Tenho esse problema a muito tempo!! Teria como solucionar isso André? De já Obg!
Olá, Gleickson.
Que estranho. Ao atingir o EOF, o cursor do DataSet deveria voltar para o último registro, de forma que possibilitasse a edição.
Vou entrar em contato com você.
Abraço!
Boa tarde André
sobre essa explicação: 7) Mover a posição da linha junto com a barra de rolagem
tentei de todos as formas, mas não consegui…teria como ter um pouco de paciência, e desculpar minha ignorância… baixei o código e não da certo… uso Delphi7
Olá, Marcos, desculpe pela demora.
Vou entrar em contato com você.
Muito bom, obrigado pelas dicas. Ajuda muito!
Muito obrigado, Rosandro!
Bom dia André, esse com certeza é uma das melhores dicas da internet sobre o DBGrid. Sobre a dica 10 tem dois pontos que quero ver contigo a solução. 1 – Coluna com o Checkbox da dica 2 some; 2 – Coluna com os dados alinhados ao centro vão para a esquerda. tem solução para isso? Obrigado
Opa, Leandro, desculpe pela demora.
Pois é, as dicas 2 e 10 conflitam. Exibir um checkbox pode impactar na navegação com as setas.
A minha recomendação é colocar o código da dica 2 logo no inÃcio do evento OnDrawColumnCell.
Dessa forma, o código do checkbox será executado ANTES do código do RowSelect (dica 10).
Você pode fazer o teste e reportar se funcionou?
Obrigado!