Foros Club Delphi

Foros Club Delphi (https://www.clubdelphi.com/foros/index.php)
-   Varios (https://www.clubdelphi.com/foros/forumdisplay.php?f=11)
-   -   Alternar colores en dbgrid (https://www.clubdelphi.com/foros/showthread.php?t=71698)

Casimiro Notevi 04-01-2011 20:23:11

Alternar colores en dbgrid
 
Hola, ya sé que esto es de lo más común, pero no consigo hacer que funcione, así que pregunto a los expertos.

A diferencia de lo habitual, que cambia de color por cada registro, en este caso es por uno de los campos.

Aunque en la imagen aparece ordenado, lo normal es que no esté ordenado por ese campo (asiento), sino por el campo fecha.



He usado una variable para guardar el contenido del último asiento, si el nuevo es distinto... se cambia de color.
No sé si ya estoy encabezonado con esto, pero no consigo que salga bien.

¿Alguna idea?

ecfisa 04-01-2011 20:35:01

Hola Casimiro.

¿ Queres que los registros recién ingresados tengan otro color ?

Edito: ( lo que vió Casimiro :o)
Probá este código:
Código Delphi [-]
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if Odd(DBGrid1.DataSource.DataSet.RecNo) then
    DBGrid1.Canvas.Brush.Color := clMoneyGreen
  else
    DBGrid1.Canvas.Brush.Color := clCream;
  DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;

Saludos.

Casimiro Notevi 04-01-2011 20:37:43

Pero de ese manera va a alternar el color por cada registro y necesito que sea por cada vez que cambia de 'asiento'

Casimiro Notevi 04-01-2011 20:39:01

jajaja... has editado tu respuesta y ahora he contestado a algo inexistente :)

ecfisa 04-01-2011 20:39:21

Si me dí cuenta de mi confusión, pero no fuí tan rápido para modificar ... :)

Ya la agrego para que el hilo sea coherente... :)

Casimiro Notevi 04-01-2011 20:39:58

Es una simple consulta sql, nada más, y quiero que cambie de color cada vez que cambie el valor del campo asiento.

Aleca 04-01-2011 21:23:26

algo asi te puede servir?
Código Delphi [-]
procedure TForm1.DBGDatosDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if State = [] then
  begin
    TDBGrid(Sender).Canvas.Font.Color := clBlack;
    if TblArticulosARTI_BAJA.AsBoolean then
    begin
      TDBGrid(Sender).Canvas.Font.Color := clWhite;
      TDBGrid(Sender).Canvas.Brush.Color := clGreen;
    end;
  end
  else
    TDBGrid(Sender).Canvas.Font.Color := clWhite;
  TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
lo uso para mostrar los articulos dados de baja.

Casimiro Notevi 04-01-2011 21:42:56

Gracias por tu aporte, Aleca.
En este caso no sirve, ten en cuenta que el color debe de cambiar cuando cambie el valor de un campo (asiento) y debe seguir con ese color hasta que cambie el valor ese campo. O sea, no es controlar únicamente el valor de un campo, sino también que no sea distinto (o sí lo sea) del registro anterior.
Teniendo en cuenta que puede estar moviendo el cursor arriba o abajo, claro.

ecfisa 04-01-2011 22:02:08

A ver Casimiro..., proba con este código:
Código Delphi [-]
...
  private
    FCampo: string;
    FCambio: Boolean;
  end;
...
implementation

procedure TForm1.FormShow(Sender: TObject);
begin
  FCampo:= DBGRid1.DataSource.DataSet.FieldByName('CAMPO_ASIENTO').AsString;
  FCambio:= False;
end;

procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if (DBGrid1.SelectedField.FieldName = 'CAMPO_ASIENTO')and
     (DBGrid1.SelectedField.AsString <> FCampo) then
  begin
    FCambio:= not FCambio;
    FCampo:=  DBGrid1.SelectedField.AsString;
  end;
  if FCambio then
    DBGrid1.Canvas.Brush.Color := clCream
  else
    DBGrid1.Canvas.Brush.Color := clMoneyGreen;
  DBGrid1.DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;

Tendrás que hacer algunos cambios y seguro lo puedas mejorar, pero en mis pruebas funcionó...

Un saludo.

fjcg02 04-01-2011 23:18:39

Código Delphi [-]
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if Odd(DBGrid1.DataSource.DataSet.FieldByname('ASIENTO').asInteger) then
    DBGrid1.Canvas.Brush.Color := clMoneyGreen
  else
    DBGrid1.Canvas.Brush.Color := clCream;
  DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;
Y no te vale así ? asientos pares un color, impares otro. En principio, si están ordenados por asiento, y teniendo en cuenta que no puede haber saltos ...

Es igual que el código de ecfisa pero en lugar de usar Recno usas el valor del campo asiento.


Un saludo

Casimiro Notevi 05-01-2011 01:11:04

Cita:

Empezado por ecfisa (Mensaje 386632)
A ver Casimiro..., proba con este código: ]..]

Casi, casi, estoy haciendo unos ajustes... pero vamos por buen camino :)


Cita:

Empezado por fjcg02 (Mensaje 386642)
[..] Y no te vale así ? asientos pares un color, impares otro. En principio, si están ordenados por asiento, y teniendo en cuenta que no puede haber saltos ...
Es igual que el código de ecfisa pero en lugar de usar Recno usas el valor del campo asiento.
Un saludo

No me vale, amigo, los asientos pueden no estar ordenados (aunque en el ejemplo lo esté), normalmente estará ordenado por fecha.

Aleca 05-01-2011 01:31:14

A ver ahora
Código Delphi [-]
....
  private
    { Private declarations }
    nValorAnt: Integer;
    FColor, BColor: TColor;
  public
    { Public declarations }
  end;
var
  Form1: TForm1;
implementation
{$R *.dfm}
procedure TForm1.DBGDatosDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if State = [] then
  begin
    if nValorAnt <> TblArticulosID_GRUPO.AsInteger then
    begin
      nValorAnt := TblArticulosID_GRUPO.AsInteger;
      if BColor = clWhite then
      begin
        FColor := clWhite;
        BColor := clGreen;
      end
      else
      begin
        FColor := clBlack;
        BColor := clWhite;
      end;
    end;
    TDBGrid(Sender).Canvas.Font.Color := FColor;
    TDBGrid(Sender).Canvas.Brush.Color := BColor;
  end
  else
    TDBGrid(Sender).Canvas.Font.Color := clWhite;
  TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  nValorAnt := 0;
  FColor := clWhite;
  BColor := clGreen;
end;
end.

Casimiro Notevi 05-01-2011 02:58:39

Gracias a ambos, las ideas ambos (ecfisa y Aleca) funcionan 'más o menos' bien.

Tienen el inconveniente que a veces se intercambian los colores, normalmente cuando se intercalan asientos de 1 sólo registro o cuando el número de asientos es un número impar.
Más o menos es el problema que tenía yo con las pruebas que estaba haciendo, que no terminaba de "cuadrar".
Bueno, sigo haciendo pruebas...

Delphius 05-01-2011 03:05:44

Hola,

Pues a como lo entiendo para hacer lo que buscas deberías leer el campo en cuestión, y compararlo con el anterior leído. En caso de ser diferente, se altera el color y se pinta con ese. En otro caso sigue pintando por el defecto.

Inicialmente se lee el primer registro y se decide el color inicial y se guarda en una variable auxiliar el valor del campo de este registro. Se pinta el primer registro con el color inicial.

En lo sucesivo se va comparando el valor del campo con el de la variable auxiliar y en caso de ser diferente se guarda en variable auxiliar este valor, se altera el color.

Para lograr la alteración entre dos colores yo tendría algo como esto:

type
ColorDoble = array[boolean] of TColor;

De ese modo tendría los dos colores, por ejemplo:

Código Delphi [-]
var
MiColorDoble: TColorDoble;
...
MiColorDoble[true] := clRed;
MiColorDoble[false] := clBlue;

Y de modo que cuando se cumpla:
Código Delphi [-]
ValorCampo := NombreDataSet.FieldbyName('CAMPO').AsInteger;
if ValorCampo <> ValorAux

Provocar un cambio en el color elegido por pintar, Algo como:

Código Delphi [-]
if ValorCampo <> ValorAux
   then Cambiar := NOT Cambiar; // alterna entre true/false
ColorElegido := MiColorDoble[Cambiar];

DBGrid.Canvas.Brush.Color := ColorElegido;
DefaultDrawColorCell(....)

La idea no es ofrecer el código exacto. No tengo Delphi a mano, pero al menos orientar un poco las cosas.

Saludos,

Casimiro Notevi 05-01-2011 03:50:42

Sí, la idea es esa, Delphius, aunque no termina de quedar bien.
Pienso que el problema puede venir por lo siguiente, pongo un ejemplo:
empezamos pintando en blanco
primer registro (asiento, suelen ser varios registros por asientos)
nuevo registro... pintamos en negro
nuevo registro... pintamos en blanco
Se acabó... se posiciona al principio del dbgrid... y en memoria tenemos el último color, el blanco.
Si ahora movemos el cursor... pintará de negro. O sea, estamos en el primer registro que era blanco y ahora lo pinta de negro, se están intercambiando los colores.
Esto no ocurre cuando el número de asientos es par, acabamos en negro y se posiciona al principio, si movemos el cursor... pintará de blanco, que es el inicial, por lo tanto saldrá bien.
El mismo problema sucede (no sé por qué) cuando hay asientos con un sólo registro, no será nunca habitual porque en contabiildad será siempre como mínimo 2 registros (apuntes) por asiento.
En fin, puede que todo sea ya que estoy cansado de esto y mejor lo dejo para mañana con las ideas más claras :)
Aunque seguiré un rato más :D

Delphius 05-01-2011 04:58:38

¿Te refieres a que eso se descuadra cuando nos desplazamos por los registros, alterando el cursor?

¿No consideraste trabajar con otras dbgrids más especializadas? Quizá en una de esas hay alguna que te facilite la cosa.

Yo también estoy en cero amigo.

Saludos,

Casimiro Notevi 05-01-2011 05:06:13

Sí, los hay, pero cuando me encargaron este proyecto, lo primero que pregunté fue: ¿qué importe tiene presupuestado este proyecto?, y mis jefes se miraron las caras y contestaron: "cero", "nada".

Así que todo lo hago "a mano", lo más algunos componentes libres que los adapto a mis requerimientos.

Luego me meten prisa diciendo que estoy tardando demasiado.

Delphius 05-01-2011 05:23:54

La otra posibilidad que se ocurre es disponer de alguna estructura que almacene la distribución de colores basándose en la posición de los registros.

Por ejemplo:

1 - Blanco
3 - Rojo
10 - Blanco
11 - Rojo
...

De ese modo diríamos que los dos primeros registros van de blanco, desde el 3ro al 9no va de rojo, el 10mo blanco... y así podríamos armar una lista almacenando un "ítem" cada vez que se detecte un cambio.

Lo que se haría es que al lanzar la consulta, llevar un procedimiento que se encargue de analizar el conjunto de datos y genera esta estructura.

Ya con esta estructura de datos se podría pintar los registros sin problemas. Se evaluaría en base al RecNo y de allí determinar el color que le corresponde.

No se si se me entiende.

Cada vez que se desplazace sobre el DBGrid o se repintase se examinaría esta estructura y se pintaría con el color correspondiente ya que tenemos toda la referencia.

Saludos,

Casimiro Notevi 05-01-2011 06:16:41

Sí, te entiendo, aunque tener que llegar a estos extremos para hacer algo así es como se dice normalmente: matar moscas a cañonazos :)
En fin, ya sí me voy a dormir, que son casi las 6am y mañana (dentro de un rato) veré cómo lo hago.
Gracias!!!

fjcg02 05-01-2011 09:13:54

No acabo de entender del todo el problema.
Entiendo perfectamente que puedas ordenar por fecha, pero no entiendo que sea sólo por ese campo. Bien dices que lo normal es que un asiento tenga dos apuntes mínimos, partida y contrapartida. Por lo tanto, bajo mi punto de vista, deberemos ordenar por fecha y asiento, ya que si no ( insisto que es una opinión mía ), la información no tiene sentido ( o lo pierde).

Por lo tanto, si ordenas por FECHA y ASIENTO, las soluciones más simples que se han manejado creo que serían válidas.

Corrigeme si me equivoco, ya que me interesa saber tu opinión.

Saludos

José Luis Garcí 05-01-2011 09:25:26

Casimiro, si me permites mi opinión, por que no usasun sistema de control por asientos, asignando al último digito del asiento, en el grid en el envento OnDrawColumCell... (no recuerdo el nombre exacto), como digo según sea este último digito, se rellene la fila de un color, lo cual te permite 10 colores diferentes del grid, ya sería mucha casualidad, dos asientos con la misma terminación para que sea el mismo color, y a unque esto ocurriese, podrias usar una variable local de 0 a 9, y cada vez que cambiaz de valor el asiento, cambias este valor y asignas color a la fila.

Espero se entienda mi idea.

fjcg02 05-01-2011 09:36:52

Cita:

Empezado por Delphius (Mensaje 386664)

Por ejemplo:

1 - Blanco
3 - Rojo
10 - Blanco
11 - Rojo
...

ATHLETIC DE BILBAO 1 - BARCELONA 0

El ATHLETIC a octavos de final en la copa !!

:D:D:D:D:D:D:D:D:D:D

ElKurgan 05-01-2011 09:44:40

Creo que el problema viene que, cuando pintamos la primera columna y preguntamos si el dato cambia, cambiamos el color (correcto); pero no podemos cambiar la variable que controla dicho cambio, porque entonces, el resto de las columnas volverían a cambiar.

He probado con esto y me ha funcionado:

Código Delphi [-]
 
var
  Dato: string = '';
  Color: TColor = clWindow;
...
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if DBgrid1.DataSource.Dataset.FieldbyName('campo').AsString <> Dato then
  begin
    // sólo debe cambiar de color en la primera columna.
    if Column.Index = 0 then
      if Color = clSkyBlue then
        Color := clWindow
      else
        Color := clSkyBlue;
     Dato := 
       DBgrid1.DataSource.Dataset.FieldbyName('campo').AsString   
  end;
  DBGrid1.Canvas.Brush.Color := Color;
  DBGrid1.DefaultDrawDataCell(Rect, Column.Field, State);
end;

Prueba a ver si te vale
Un saludo

Aleca 05-01-2011 10:36:58

le estuve dando un poco de vuelta al asunto y se armas un campo calculado que lleve el color en que se va a pintar (0-blanco, 1-Verde) y pintas de acuerdo al valor de ese campo.
Código Delphi [-]
....
  private
    { Private declarations }
    nValorAnt, nColor: Integer;
    FColor, BColor: TColor;
...
procedure TForm1.DBGDatosDrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
begin
  if State = [] then
  begin
    if TblArticulosCAMPO_COLOR.AsInteger = 0 then
      begin
        FColor := clWhite;
        BColor := clGreen;
      end
      else
      begin
        FColor := clBlack;
        BColor := clWhite;
      end;
    TDBGrid(Sender).Canvas.Font.Color := FColor;
    TDBGrid(Sender).Canvas.Brush.Color := BColor;
  end
  else
    TDBGrid(Sender).Canvas.Font.Color := clWhite;
  TDBGrid(Sender).DefaultDrawColumnCell(Rect, DataCol, Column, State);
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
  nValorAnt := 0;
  nColor := 0;
  FColor := clWhite;
  BColor := clGreen;
end;

procedure TForm1.TblArticulosCalcFields(DataSet: TDataSet);
begin
  if nValorAnt <> TblArticulosID_GRUPO.AsInteger then
  begin
    nValorAnt := TblArticulosID_GRUPO.AsInteger;
    if nColor = 0 then
      nColor := 1
    else
      nColor := 0;
  end;
  TblArticulosCAMPO_COLOR.AsInteger := nColor;
end;
end.

ahora me lo mantiene estable.
Saludos :)

Aleca 05-01-2011 10:42:53

Cita:

Empezado por Aleca (Mensaje 386673)
le estuve dando un poco de vuelta al asunto y se armas un campo calculado que lleve el color en que se va a pintar (0-blanco, 1-Verde) y pintas de acuerdo al valor de ese campo.

ahora me lo mantiene estable.Saludos :)

umm lo segui revisando y en algun momento lo cambia:mad:

ElKurgan 05-01-2011 10:53:28

Cita:

Empezado por ElKurgan (Mensaje 386672)
Código Delphi [-]
 
  Color: TColor = clWindow;

Mejor cambiar el nombre de la variable, porque a veces puede confundirse con la propiedad Color del Formulario; en algunas ocasiones me la ha interpretado como "Self.Color"

Saludos

fjcg02 05-01-2011 11:56:56

Cita:

Empezado por Aleca (Mensaje 386673)
le estuve dando un poco de vuelta al asunto y se armas un campo calculado que lleve el color en que se va a pintar (0-blanco, 1-Verde) y pintas de acuerdo al valor de ese campo.

Estoy de acuerdo en que si no vale ninguna de las soluciones dadas, la siguiente es en lugar de utilizar una query utilizar un procedimiento almacenado que devuelva una columna adicional, que sea el color a pintar.

Saludos
PD: Cuando Casi vea el revuelo que ha formado igual le da un patatús.

Casimiro Notevi 05-01-2011 13:22:48

jajaja... bueeenooo... ¡¡¡ vaya jaleo !!! :D
Muchísimas gracias a todos :)

Y sí, me piden que esté ordenado por fecha y luego por asiento/apunte, pero como cada asiento son varios apuntes...
No sé, el tema no parece muy complicado, al contrario, pero sin embargo se está complicando.

El asunto es que cada asiento son varios registros (apuntes) y cuando hay un número impar de asientos (y en otros casos que no he detectado el motivo) al terminar de pintar el último se queda con el color igual al primer registro, entonces al posicionarse en el primero e intentar mover el cursor a otro... lo pinta del color que no le corresponde.

Se hace el select y pinta el dbgrid:
asiento 1 apunte 1 azul
asiento 1 apunte 2 azul
asiento 1 apunte 3 azul
asiento 2 apunte 1 rojo
asiento 2 apunte 2 rojo

asiento 3 apunte 1 azul
asiento 3 apunte 2 azul
<-- en memoria queda último color usado: azul

Entonces se posiciona en el primer registro, y si muevo el cursor al siguiente, por ejemplo, al estar en azul... lo pinta e rojo. Alterna los colores.

Cuando el número de asientos es par entonces no hay problema
asiento 1 apunte 1 azul
asiento 1 apunte 2 azul
asiento 1 apunte 3 azul
asiento 2 apunte 1 rojo
asiento 2 apunte 2 rojo

asiento 3 apunte 1 azul
asiento 3 apunte 2 azul

asiento 4 apunte 1 rojo
asiento 4 apunte 2 rojo
<-- en memoria queda último color usado: rojo

Al posicionarse en el primero y movernos, cambia rojo por azul, que es el color correcto.



En fin, que voy a hacerlo de otra forma, ya habéis dado pistas sobre eso, un campo calculado que vaya anotando cada vez que cambia de asiento y listo, luego se pinta del color según ese campo, (true/false ó 0/1).
O cargarlo en un clientdataset o tabla en memoria y hacer lo mismo.

Y de nuevo muchísimas gracias a todos :)
Si se os ocurre una forma "normal" y que funcione... avisáis :)

ElKurgan 05-01-2011 14:19:14

Pues no se, a mi me funciona lo que he probado. Creía que bastaría con adaptarlo un poco a tu programa y ya está

En fin, mi gozo en un pozo

Saludos

Casimiro Notevi 05-01-2011 14:21:59

Cita:

Empezado por ElKurgan (Mensaje 386685)
Pues no se, a mi me funciona lo que he probado. Creía que bastaría con adaptarlo un poco a tu programa y ya está
En fin, mi gozo en un pozo
Saludos

Espera, que todavía no lo he probado todo, déjame un poquito de tiempo :)

ecfisa 05-01-2011 16:11:04

Hola.

Dudo de su aplicabilidad... pero brinda un 'arco iris' de posibilidades... :)
Código Delphi [-]
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  Num,Base: Integer;
begin
  Num:= DBGrid1.DataSource.DataSet.FieldByName('ASIENTO').AsInteger;
  if Odd(Num) then
    Base:=  Integer(clRed)
  else
    Base:=  Integer(clBlue);
  DBGrid1.Canvas.Font.Color:= clWhite;
  DBGrid1.Canvas.Brush.Color:= TColor(Base + Num * 100);
  DBGrid1.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;

Saludos.

duilioisola 05-01-2011 17:22:59

Creo que la solución sería:
  • Poner AutoCalcFields = False;
  • Crear un campo calculado que contenga el color con el que debe pintarse
  • Cuando se abra la tabla, se deberá hacer un FetchAll y dejar que el OnCalcFields calcule el varlor del color.
Código Delphi [-]
var
   ValorAnterior: string;
   Sombra : boolean;

procedure TDataModule.TablaBeforeOpen(DataSet: TDataSet);
begin
   Sombra := False;
   ValorAnterior := '';
end;

procedure TDataModule.TablaOnCalcFields(DataSet: TDataSet);
begin
   if (ValorAnterior<>TablaNRO_ASIENTO.AsString) then
      Sombra := not Sombra;
   TablaCAMPO_CALCULADO_SOMBRA.AsBoolean := Sombra;
end;

Nota: Según la ayuda de Delphi 6:

Cita:

When AutoCalcFields is True (the default), Lookup fields are recalculated and OnCalcFields is triggered when:

The dataset is opened.
The dataset is put into dsEdit state.
Focus moves from one visual control to another, or from one column to another in a data-aware grid and modifications have been made to the record.

When AutoCalcFields is False, Lookup fields are recalculated and the OnCalcFields event occurs only when

The dataset is opened.
The dataset is put into dsEdit state.
A record is retrieved from a database.

pacopenin 05-01-2011 17:27:07

Cita:

Empezado por duilioisola (Mensaje 386700)
Creo que la solución sería:
  • Poner AutoCalcFields = False;
  • Crear un campo calculado que contenga el color con el que debe pintarse
  • Cuando se abra la tabla, se deberá hacer un FetchAll y dejar que el OnCalcFields calcule el varlor del color.
Código Delphi [-]
var    ValorAnterior: string;    
Sombra : boolean;  
procedure TDataModule.TablaBeforeOpen(DataSet: TDataSet); 
begin    
  Sombra := False;    
  ValorAnterior := ''; 
end;  
procedure TDataModule.TablaOnCalcFields(DataSet: TDataSet); 
begin    
 if (ValorAnterior<>TablaNRO_ASIENTO.AsString) then       
  Sombra := not Sombra;    
 TablaCAMPO_CALCULADO_SOMBRA.AsBoolean := Sombra; 
end;

Yo creo que los tiros van por ahí. Solo si tenemos en la tabla un valor que nos defina el color podremos "dibujar" el grid y desplazarnos (saltando) entre registros.

duilioisola 05-01-2011 18:29:49

Al final he hecho lo siguiente:

Código Delphi [-]
{En el Form}
procedure TFCMayor.DBGConsultaDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: integer; Column: TColumn; State: TGridDrawState);
begin
  with TDBGrid(Sender) do
  begin
     if (gdFocused in State) then //If the cell has the focus
     begin
        Canvas.Font.Color := clWhite;
        Canvas.Brush.Color := clHighlight;
     end
     else
        if (DMMayor.xMayorSOMBRA.AsInteger = 1) then
        begin
           Canvas.Font.Color := clBlack;
           Canvas.Brush.Color := clCream;
        end
        else
        begin
           Canvas.Font.Color := clBlack;
           Canvas.Brush.Color := clInfoBk;
        end;
     DefaultDrawColumnCell(Rect, DataCol, Column, State);
  end;
end;

{En el DataModule}
{Pongo xMayor.AutoCalcFields en False}
{Campo calculado xMayorSOMBRA integer}

var
   Sombra : boolean;
   ValorAnterior : string;

procedure TDMMayor.xMayorBeforeOpen(DataSet: TDataSet);
begin
   Sombra := False;
   ValorAnterior := '';
end;

procedure TDMMayor.xMayorCalcFields(DataSet: TDataSet);
begin
   if (ValorAnterior<>xMayorASIENTO.AsString) then
   begin
      Sombra := not Sombra;
      ValorAnterior := xMayorASIENTO.AsString;
   end;
   if (Sombra) then
      xMayorSOMBRA.Value := 1  {<-- Esta asignacion no funciona}
   else
      xMayorSOMBRA.Value := 0; {<-- Esta asignacion no funciona}
end;

El único problema es que la última parte donde asigno al campo sombra un valor, la pasa por alto y siempre es 0.

He probado con AutoCalcFields en False y en True, con el mismo resultado.

Puede ser porque estoy probando con unos componentes que descienden de FreeIB.

Si alguien lo puede probar con otros componentes DataSets que informe si le funciona.

José Luis Garcí 05-01-2011 18:42:16

Casimiro te pongo unas imágenes de lo que te comentaba anteriormente













Ten en cuenta que usado colores a lo loco, deberías usar, un color y derivar luego de este cambiado sólo uno de los valores de la rgb para que fueran tonalidades mas consecutivas.


La parte del código que creo te puede interesar es esta

Código Delphi [-]

function UlDigit(nNumero: integer): Integer;
var
udTama,udResult:Integer;
cNumero:string;
begin
   cNumero:=IntToStr(nNumero);
   udTama:=Length(cNumero);
   if udTama>1 then udResult:=StrToInt(Copy(cNumero,((udTama)),1))
               else udResult:=StrToInt(cNumero);
   Result := udResult;
end;

procedure TForm1.DBGrid2DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var color:TColor;
begin
     case UlDigit(StrToInt(DataSource2.DataSet.FieldByName('LOTE').value)) of
        0:Color:=ColorBox10.Selected;
        1:Color:=ColorBox12.Selected;
        2:Color:=ColorBox13.Selected;
        3:Color:=ColorBox14.Selected;
        4:Color:=ColorBox15.Selected;
        5:Color:=ColorBox16.Selected;
        6:Color:=ColorBox17.Selected;
        7:Color:=ColorBox18.Selected;
        8:Color:=ColorBox19.Selected;
        9:Color:=ColorBox20.Selected;
     end;
     DBGrid2.Canvas.Brush.Color := Color;
     Dbgrid2.Canvas.FillRect(Rect);
     dbGrid2.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;


Como puedes comprobar use mi BD de pruebas y el Campo por el que hago la comprobación es LOTE, en tu caso sería ASIENTO

José Luis Garcí 05-01-2011 19:07:31

Bueno siento ser pesado, pero con unos pequeños cambios os muestro lo que digo.







Código Cambiado

Código Delphi [-]
procedure TForm1.DBGrid2DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
var color:TColor;
begin
//     if odd then
     case UlDigit(StrToInt(DataSource2.DataSet.FieldByName('LOTE').value)) of
        0:Color:=RGB(205,150,10);
        1:Color:=RGB(210,160,40);
        2:Color:=RGB(215,170,70);
        3:Color:=RGB(220,180,100);
        4:Color:=RGB(225,190,130);
        5:Color:=RGB(230,200,160);
        6:Color:=RGB(235,210,190);
        7:Color:=RGB(240,220,210);
        8:Color:=RGB(245,230,240);
        9:Color:=RGB(250,240,255);
//        0:Color:=ColorBox10.Selected;
//        1:Color:=ColorBox12.Selected;
//        2:Color:=ColorBox13.Selected;
//        3:Color:=ColorBox14.Selected;
//        4:Color:=ColorBox15.Selected;
//        5:Color:=ColorBox16.Selected;
//        6:Color:=ColorBox17.Selected;
//        7:Color:=ColorBox18.Selected;
//        8:Color:=ColorBox19.Selected;
//        9:Color:=ColorBox20.Selected;
     end;
     DBGrid2.Canvas.Brush.Color := Color;
     Dbgrid2.Canvas.FillRect(Rect);
     dbGrid2.DefaultDrawColumnCell(Rect,DataCol,Column,State);
end;

Chris 05-01-2011 19:36:24

mmm... comparto la opinión de casimiro, las soluciones presentadas son como cañonazos.

Por mi parte creo que este problema necesita nada más que una especie de switch, o alternador. Una simple variable booleana que controle el color utilizado.

Código Delphi [-]
procedure TForm1.DBGrid1DrawColumnCell(Sender: TObject; const Rect: TRect;
  DataCol: Integer; Column: TColumn; State: TGridDrawState);
const
    background_colors: array[0..1] of TColor = (clBtnFace, clWhite);
begin
if Dataset.FieldByName('asiento').Value <> UltimoValor then
    BoolSwitch := (not BoolSwitch);

TDBGrid(Sender).Canvas.Brush.Color := background_colors[BoolSwitch];
TDBGrid(Sender).DefaultDrawColumnCell( ... );
UltimoValor := Dataset.FieldByName('asiento').Value;
...
end;

BoolSwitch y UltimoValor son variables privadas del formulario.

Creo que con este código se pudiera solucionar el problema. Sino pues creo que de él se puede partir.

Saludos,
Chris

pacopenin 05-01-2011 19:46:01

Estoy siguiendo este hilo con interés. En algún momento voy a verme en la tesitura de implantar algo similar. Y creo que el principal problema no es "pintar" las filas cuando se "cargan" los datos. Eso, con los sistemas de switch que se van comentando es fácil. Yo creo que el principal problema es la navegación, el hacer click en cualquier sitio. Creo que si en el registro de la tabla no hay una información que nos indique si hay que pintar esa celda de un color o de otro, los valores del "switch" no van a ser válidos. Mi opinión en que "debe haber una información en el registro que indique de color hay que pintar esa celda".

Saludos,

Casimiro Notevi 05-01-2011 19:51:21

Cita:

Empezado por pacopenin (Mensaje 386720)
[..] Mi opinión en que "debe haber una información en el registro que indique de color hay que pintar esa celda".
Saludos,

Después de probar las distintas opciones aportadas por los compañeros, debo ecir que no funcionan "totalmente" bien... o yo no he sabido implementarlas, que todo puede ser.

Así que creo que la única opción es la del campo que indique el color o algo así.

Pero todavía se aceptan más propuestas... habrá premio al que obtenga el resultado correcto :)

Delphius 05-01-2011 20:46:07

Pues yo no veo otra salida amigo. Ya sea que se lleve una estructura fuera o en el mismo dbgrid con un campo calculado y el uso de técnicas "flags booleanas" es necesario contar con un artilugio para llevar ese conteo y poder determinar con que color pintar cada registro.

Saludos,


La franja horaria es GMT +2. Ahora son las 15:39:49.

Powered by vBulletin® Version 3.6.8
Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
Traducción al castellano por el equipo de moderadores del Club Delphi