
Color de fila dbgrid diferente para cada registro con un campo distinto
#1
Posted 25 January 2011 - 12:34 AM
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?
#3
Posted 25 January 2011 - 08:02 PM
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.
#4
Posted 25 January 2011 - 09:17 PM
Prueba este código:
procedure TGridForm.DBGridDrawColumnCell( Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState) ; var grid : TDBGrid; row : integer; begin grid := sender as TDBGrid; row := grid.DataSource.DataSet.RecNo; if Odd(row) then grid.Canvas.Brush.Color := clSilver else grid.Canvas.Brush.Color := clDkGray; grid.DefaultDrawColumnCell(Rect, DataCol, Column, State) ; end; (* DBGrid OnDrawColumnCell *)
Fuente
#5
Posted 25 January 2011 - 09:47 PM
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:
// Evaluamos si pintamos con el color anterior o con uno nuevo if ValorCampoCuenta <> ValorAnterior then begin Color := ElegirColor(ValorCampoCuenta); ValorAnterior := ValorCampoCuenta; end; ... // Indicamos el nuevo color con que pintar DBGrid.Canvas.Brush.Color := Color; // Pintamos 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,
#6
Posted 25 January 2011 - 10:04 PM
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
#7
Posted 25 January 2011 - 10:18 PM
Hago esta aclaracion por si de algo sirve en la busqueda de la solucion de este asunto.
#8
Posted 25 January 2011 - 10:31 PM
unit Unit1; interface uses Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms, Dialogs, ExtCtrls, DBCtrls, Grids, DBGrids, DB, ADODB; type TForm1 = class(TForm) ADOConnection1: TADOConnection; tb: TADOTable; DataSource1: TDataSource; DBGrid1: TDBGrid; DBNavigator1: TDBNavigator; procedure DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); private { Private declarations } public { Public declarations } end; var Form1: TForm1; implementation {$R *.dfm} procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState); begin with Sender as TDBGrid do begin case tb['num'] of // tb es Dataset y num es el campo que comparo, en este caso es un entero 1: begin Canvas.Font.Color := clRed; canvas.Brush.Color := ClBlack; DefaultDrawColumnCell(Rect, DataCol, Column, State); end; 2: begin Canvas.Font.Color := clWhite; canvas.Brush.Color := ClGreen; DefaultDrawColumnCell(Rect, DataCol, Column, State); end; 3: begin Canvas.Font.Color := clBlack; canvas.Brush.Color := ClYellow; DefaultDrawColumnCell(Rect, DataCol, Column, State); end; end; end; end; end.
#9
Posted 25 January 2011 - 10:36 PM
Attached Files
#10
Posted 25 January 2011 - 10:54 PM
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?
#11
Posted 25 January 2011 - 10:57 PM
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.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.
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,
#12
Posted 25 January 2011 - 11:03 PM
Como puedo poner el array en el case?
Array de que tipo?
#13
Posted 25 January 2011 - 11:43 PM
#14
Posted 26 January 2011 - 12:34 AM
fue puesto por ecfisa moderador y aunque el mismo dudaba de su funcionalidad, pues a mi me funciona:
PROCEDURE TFRMactivasred.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: INTEGER; COLUMN: TColumn; State: TGridDrawState); var Num,Base: INTEGER; BEGIN Num:= DBGrid1.DataSource.DataSet.FieldByName('CSID').AsInteger; IF Odd(Num) THEN Base:= INTEGER(clblue) ELSE Base:= INTEGER(clyellow); DBGrid1.Canvas.Font.Color:= clwhite; DBGrid1.Canvas.Brush.Color:= TColor(Base + Num * 100); DBGrid1.DefaultDrawColumnCell(Rect,DataCol,COLUMN,State); 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.

Talvez no sea la solucion final, pero es un avance muy bueno. voy a seguir probando.
#15
Posted 26 January 2011 - 12:40 AM
PROCEDURE TFRMactivasred.DBGrid1KeyDown(Sender: TObject; var KEY: Word; Shift: TShiftState); BEGIN IF (KEY = VK_DOWN) THEN BEGIN DMmonitorenred.ZQactivas.DisableControls; DMmonitorenred.zqactivas.NEXT; IF DMmonitorenred.ZQactivas.EOF THEN KEY := 0 ELSE DMmonitorenred.ZQactivas.Prior; DMmonitorenred.ZQactivas.EnableControls; END ; END;
codigo para no pasarme de la ultima fila. Sacado de trucomania.
#16
Posted 26 January 2011 - 12:49 AM
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?
#17
Posted 26 January 2011 - 12:55 AM
if DMmonitorenred.ZQactivasCSID.AsString<>'' then Num:= DBGrid1.DataSource.DataSet.FieldByName('CSID').AsInteger else num:=1;
#18
Posted 26 January 2011 - 06:32 AM
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.



#19
Posted 26 January 2011 - 06:50 AM
PD: Recuerda que solo son posibles algo mas que 16 millones de colores, por si tu DB crece mucho.
![]()
![]()
![]()
No te preocupes que he ensayado hasta con este número tan grande y da un hermoso azul.
Form1.Color := TColor(TColor((Integer(clblue) + 100000000000000 * 100)));
#20
Posted 26 January 2011 - 07:01 AM
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.