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


La franja horaria es GMT +2. Ahora son las 08:02:23.

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