Ir al contenido


Foto

Color de fila dbgrid diferente para cada registro con un campo distinto


  • Por favor identifícate para responder
32 respuestas en este tema

#1 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 25 enero 2011 - 12:34

Me gustaria saber como puedo ponerle un color diferente a cada fila segun el valor de un campo especifico.
Es decir si tengo:

cuenta  evento
0001    ba01
0001    ba02
0003    ba01
0005    ba08
0100    ma12

que me ponga esto:

cuenta  evento
0001    ba01
0001    ba02
0003    ba01

0005    ba08
0100    ma12


En este caso la comparacion se haria por el campo cuenta.
Alguna idea?

  • 0

#2 escafandra

escafandra

    Advanced Member

  • Administrador
  • 4.107 mensajes
  • LocationMadrid - España

Escrito 25 enero 2011 - 01:12

Quizás esto te de alguna idea.

Saludos.
  • 0

#3 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 25 enero 2011 - 08:02

Gracias Escafandra por responder.

Pues en el hilo que me indicas se habla de un stringrid y del evento ondrawcell. En mi caso quiero hacerlo en un dbgrid y el evento ondrawcolumncell no tiene esas variables. La verdad es que no se por donde empezar para hacer lo que quiero.

Si me dan un empujon, que no sea muy fuerte porque va y me caigo.
  • 0

#4 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 25 enero 2011 - 09:17

Saludos.

Prueba este código:


delphi
  1. procedure TGridForm.DBGridDrawColumnCell(
  2.   Sender: TObject;
  3.   const Rect: TRect;
  4.   DataCol: Integer;
  5.   Column: TColumn;
  6.   State: TGridDrawState) ;
  7. var
  8.   grid : TDBGrid;
  9.   row : integer;
  10. begin
  11.   grid := sender as TDBGrid;
  12.  
  13.   row := grid.DataSource.DataSet.RecNo;
  14.  
  15.   if Odd(row) then
  16.     grid.Canvas.Brush.Color := clSilver
  17.   else
  18.     grid.Canvas.Brush.Color := clDkGray;
  19.  
  20.   grid.DefaultDrawColumnCell(Rect, DataCol, Column, State) ;
  21.  
  22. end; (* DBGrid OnDrawColumnCell *)



Fuente
  • 0

#5 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 25 enero 2011 - 09:47

Si se tuviese que alternar entre dos colores únicamente cada fila no habría problema con el ejemplo que te han pasado. El asunto es que el coloreado de cada registro depende del valor que tenga un campo, y además (que es donde está el principal problema de encararlo) el color está relacionado o depende del registro anterior... o mejor dicho del "grupo" anterior.

Tu caso es bastante similar a uno que se ha discutido en Clubdelphi hace unos cuantos días. Puedes tomar como base lo analizado allí.

La idea es que se vaya pintando cada registro con el nuevo color cuando se detecte una nueva cuenta. Alterando un "poco" el ejemplo de Rolphy básicamente la idea sería que tuvieras algo como:



delphi
  1. // Evaluamos si pintamos con el color anterior o con uno nuevo
  2. if ValorCampoCuenta <> ValorAnterior
  3.   then begin
  4.         Color := ElegirColor(ValorCampoCuenta);
  5.         ValorAnterior := ValorCampoCuenta;
  6.         end;
  7. ...
  8. // Indicamos el nuevo color con que pintar
  9. DBGrid.Canvas.Brush.Color := Color;
  10. // Pintamos
  11. DBGrid.DefaultDrawColumnCell(Rect, DataCol, Column, State);



El problema, es que si uno se desplaza por el DBGrid, se impieza a repintar de nuevo el DBGrid y se descompajina todo... Es necesario disponer de una especie de lista o tabla que recuerde y asocie a cada registro del DBGrid con un color.

La hipotética ElegirColor hace ese proceso. La lista tiene la correspondencia de cada cuenta con el color. De ese modo simplemente busca el número de cuenta y regresa el color correspondiente.
Naturalmente, para que funcione adecuadamente esta lista debe generarse previamente.

Saludos,
  • 0

#6 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 25 enero 2011 - 10:04

Gracias Rolphy, Delphius por responder.
Delphius tiene razon y su logica como siempre es valida. El problema es implementarlo.

Voy a estudiar el hilo que me indica delphius y veremos que sale.

Gracias de nuevo


  • 0

#7 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 25 enero 2011 - 10:18

Quiero aclarar que el dbgrid en cuestion tiene todos los campos readonly. El usuario no va a editar, ni insertar nada directamente en el dbgrid. Hay  botones cbsEllipsis en dos campos. Estos botones abren formularios en donde el usuario modifica y manipula en este caso el query o dataset asociado al dbgrid.

Hago esta aclaracion por si de algo sirve en la busqueda de la solucion de este asunto. 
  • 0

#8 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 25 enero 2011 - 10:31

En el  un siguiente Post te adjunto un ejemplo que funciona perfectamente así:



delphi
  1. unit Unit1;
  2.  
  3. interface
  4.  
  5. uses
  6.   Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  7.   Dialogs, ExtCtrls, DBCtrls, Grids, DBGrids, DB, ADODB;
  8.  
  9. type
  10.   TForm1 = class(TForm)
  11.     ADOConnection1: TADOConnection;
  12.     tb: TADOTable;
  13.     DataSource1: TDataSource;
  14.     DBGrid1: TDBGrid;
  15.     DBNavigator1: TDBNavigator;
  16.     procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  17.       DataCol: Integer; Column: TColumn; State: TGridDrawState);
  18.   private
  19.     { Private declarations }
  20.   public
  21.     { Public declarations }
  22.   end;
  23.  
  24. var
  25.   Form1: TForm1;
  26.  
  27. implementation
  28.  
  29. {$R *.dfm}
  30.  
  31. procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  32.   DataCol: Integer; Column: TColumn; State: TGridDrawState);
  33. begin
  34.   with Sender as TDBGrid do
  35.   begin
  36.     case tb['num'] of // tb es Dataset y num es el campo que comparo, en este caso es un entero
  37.   1:  begin
  38.       Canvas.Font.Color := clRed;
  39.       canvas.Brush.Color := ClBlack;
  40.       DefaultDrawColumnCell(Rect, DataCol, Column, State);
  41.       end;
  42.   2:  begin
  43.       Canvas.Font.Color := clWhite;
  44.       canvas.Brush.Color := ClGreen;
  45.       DefaultDrawColumnCell(Rect, DataCol, Column, State);
  46.       end;
  47.   3:  begin
  48.       Canvas.Font.Color := clBlack;
  49.       canvas.Brush.Color := ClYellow;
  50.       DefaultDrawColumnCell(Rect, DataCol, Column, State);
  51.       end;
  52.   end;
  53. end;
  54. end;
  55.  
  56. end.


  • 0

#9 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 25 enero 2011 - 10:36

Aqui te adjunto el ejemplo, solo debes arreglar la ruta de la DB en el componente de conexión.

Archivos adjuntos


  • 0

#10 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 25 enero 2011 - 10:54

Gracias Wilson por responder.

Esta es un aproximacion interesante a una solucion, pero el problema es que el valor del campo a vericar puede ser de 0001 hasta 1000000 o mas, aunque en este caso especifico solo llegaria a 1500.  Pero podria poner la opcion que si del 1 al 100 que le de tal color, que del 101 al 200 le de otro color.  Obviamente eso no resuelve el problema de que la cuenta 0001 y 0002 no tengan el mismo color. No obstante esto es algo con lo que puedo ir trabajando.

Como puedo poner el array en el case?


  • 0

#11 Delphius

Delphius

    Advanced Member

  • Administrador
  • 6.295 mensajes
  • LocationArgentina

Escrito 25 enero 2011 - 10:57

Quiero aclarar que el dbgrid en cuestion tiene todos los campos readonly. El usuario no va a editar, ni insertar nada directamente en el dbgrid. Hay  botones cbsEllipsis en dos campos. Estos botones abren formularios en donde el usuario modifica y manipula en este caso el query o dataset asociado al dbgrid.

Hago esta aclaracion por si de algo sirve en la busqueda de la solucion de este asunto. 

Pues por más que no pueda editar, se puede mover y desplazar por los registros por lo que de todas formas se debe contar con esa "lista" que comentaba en el hilo de CD.

Ya sea que esa "lista" sea un campo "ficticio" devuelto por un SP, o la implementes en el cliente con un vector, TList o lo que fuese es necesaria porque de esa lista es donde se obtiene el color que se debe pintar el registro.

Saludos,
  • 0

#12 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 25 enero 2011 - 11:03


Como puedo poner el array en el case?


Array de que tipo?


  • 0

#13 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 25 enero 2011 - 11:43

wilson me refiero a poner que si el valor es de 1 a 100  de 201 a 200 y asi sucesivamente
  • 0

#14 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 26 enero 2011 - 12:34

Pues este codigo lo encontre en el hilo de Club Dephi que me indicó Delphius
fue puesto por ecfisa  moderador y aunque el mismo dudaba de su funcionalidad, pues a mi me funciona:


sql
  1. PROCEDURE TFRMactivasred.DBGrid1DrawColumnCell(Sender: TObject;
  2.   const Rect: TRect; DataCol: INTEGER; COLUMN: TColumn;
  3.   State: TGridDrawState);
  4. var
  5.   Num,Base: INTEGER;
  6. BEGIN
  7.   Num:= DBGrid1.DataSource.DataSet.FieldByName(&#39;CSID&#39;).AsInteger;
  8.   IF Odd(Num) THEN
  9.     Base:=  INTEGER(clblue)
  10.   ELSE
  11.     Base:=  INTEGER(clyellow);
  12.   DBGrid1.Canvas.Font.Color:= clwhite;
  13.   DBGrid1.Canvas.Brush.Color:= TColor(Base + Num * 100);
  14.   DBGrid1.DefaultDrawColumnCell(Rect,DataCol,COLUMN,State);
  15. END;



Le cambie los colores, pero la esencia es la misma.
El unico problema que tengo es que al convertir a integer el campo CSID, cuando me paso del ultimo registro me lanza un error. Se que controlar que no se pueda pasar del ultimo registro visible en el dbgrid es facil, pero no recuerdo como se hace. Dejenme investigar para corregir este detallito.

Imagen Enviada

Talvez no sea la solucion final, pero es un avance muy bueno. voy a seguir probando.

  • 0

#15 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 26 enero 2011 - 12:40



sql
  1. PROCEDURE TFRMactivasred.DBGrid1KeyDown(Sender: TObject; var KEY: Word;
  2.   Shift: TShiftState);
  3. BEGIN
  4. IF (KEY = VK_DOWN) THEN
  5.         BEGIN
  6.         DMmonitorenred.ZQactivas.DisableControls;
  7.           DMmonitorenred.zqactivas.NEXT;
  8.           IF DMmonitorenred.ZQactivas.EOF THEN
  9.             KEY := 0
  10.           ELSE
  11.             DMmonitorenred.ZQactivas.Prior;
  12.           DMmonitorenred.ZQactivas.EnableControls;
  13.         END ;
  14.  
  15. END;



codigo para no pasarme de la ultima fila. Sacado de trucomania.
  • 0

#16 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 26 enero 2011 - 12:49



delphi
  1. Num:= DBGrid1.DataSource.DataSet.FieldByName('CSID').AsInteger;


me da un error en esta linea al iniciar el programa con el dbgrid vacio o si cuando se pone en blanco en dbgrid.  Como puedo corregir esto?
  • 0

#17 luk2009

luk2009

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.040 mensajes
  • LocationSanto Domingo

Escrito 26 enero 2011 - 12:55

Lo cambie por este codigo y funciona.



delphi
  1. if  DMmonitorenred.ZQactivasCSID.AsString<>'' then
  2.   Num:= DBGrid1.DataSource.DataSet.FieldByName('CSID').AsInteger
  3.   else
  4.   num:=1;



  • 0

#18 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 26 enero 2011 - 06:32

Me alegra que hayas dado con la solución para tu problema.

Gracias Wilson por responder.

Esta es un aproximacion interesante a una solucion, pero el problema es que el valor del campo a vericar puede ser de 0001 hasta 1000000 o mas, aunque en este caso especifico solo llegaria a 1500.


No sabía que necesitabas hacer esto con tantos registros, es evidente que la solucón que te propuse no era viable en este caso.

Saludos.

PD: Recuerda que solo son posibles algo mas que 16 millones de colores, por si tu DB crece mucho.  :D :D :D
  • 0

#19 Wilson

Wilson

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.137 mensajes

Escrito 26 enero 2011 - 06:50

PD: Recuerda que solo son posibles algo mas que 16 millones de colores, por si tu DB crece mucho.  :D :D :D


No te preocupes que he ensayado hasta con este número tan grande y da  un hermoso azul.



delphi
  1. Form1.Color := TColor(TColor((Integer(clblue) + 100000000000000 * 100)));


  • 0

#20 Rolphy Reyes

Rolphy Reyes

    Advanced Member

  • Moderadores
  • PipPipPip
  • 2.092 mensajes
  • LocationRepública Dominicana

Escrito 26 enero 2011 - 07:01

Saludos.

Aún no entiendo lo que andas buscando, osea si es necesario por algún motivo especial colorear esas filas.

En el trabajo usamos el Grid de los JEDI que tiene la propiedad AlternateRowColor y AlternateRowFontColor con estas propiedades se logra que se pinte filas alternadas.  Osea fila 1 color negro, fila 2 color rojo, fila 3 color negro y así sucesivamente, para una cuestión de estética.
  • 0




IP.Board spam blocked by CleanTalk.