AGB  ·  Datenschutz  ·  Impressum  







Anmelden
Nützliche Links
Registrieren
Zurück Delphi-PRAXiS Programmierung allgemein Programmieren allgemein Delphi Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

Ein Thema von NicoleWagner · begonnen am 25. Nov 2021 · letzter Beitrag vom 26. Nov 2021
Antwort Antwort
NicoleWagner

Registriert seit: 6. Jul 2010
167 Beiträge
 
Delphi XE3 Professional
 
#1

AW: Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

  Alt 25. Nov 2021, 18:41
Danke für Deine Mühe und Geduld!!!


//************************************************** ****************************
implementation
uses .........

Var monat_temp, woche_temp: integer; // benötigt für das Farbschema
farbe: TColor= $00E7F2FF; // fürs Einfärben des Grids
Monatswechsel: Boolean = false;

Wochengewinn: integer = 0;
Monatsgewinn: integer = 0;
myKontostand: integer = 0; // fürs Draw Ereignis

=======================================

// malt die Monateszeilen der Trades je nach Monat bunt und rechnet sie auch, als "Calc"-Ereignis missbraucht
procedure TFrame_Konto.DBGrid_TradesDrawColumnCell(Sender: TObject;
const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);

Var s_cell: string;
d: double;
i: integer;
dat_: TDateTime;
monat_, woche_: integer;
Kapital, Gewinn: integer;


begin
// wird jede Zelle aufgerufen, dabei liegen dieParameter so:
/// Query.RecNo 1 1 1 1 => DataSource_TradesListen.DataSet.RecNo
/// 2 2 2 2
/// column.index 0 1 2 3
/// 0 1 2 3
/// 0 1 2 3
/// columns 0 1 2 3
/// 0 1 2 3
/// 0 1 2 3
/// hier passiert nur das ZEICHNEN, der Inhalt hängt davon nicht ab
/// ACHTUNG Namen der Felder sind case sensitive!
///
///

with (Sender as TDBGrid) do begin


if Column.Field <> nil then s_cell:=Column.Field.AsString; // hier wird einmal alles generell in ein eintragbares String gespeichert
// ganz unten wird dieser String über den neuen Hintergrund geschrieben

// für andere Werte überschreibe ich das String, um es anders zu formatieren.

//________________ diese Block färbt alternierende Zeilen, wenn NICHT nach Datum sortiert wird
if RadioGroup_Sortiere.ItemIndex <> 5 then begin
i:=DataSource_TradesListen.DataSet.RecNo;
if Odd(i) then Canvas.Brush.Color :=$00E7F2FF;
Canvas.FillRect(Rect); // steht das vor dem Block "Schriftfarbe", wird nur hinter-dem-Anfüllen-aufgerufen sichtbar
Canvas.TextOut(Rect.Left + 2, Rect.Top + 1,s_cell); // Text wird neu geschrieben
exit; // Sortierung der Query UNGLEICH Datum, daher macht das Einfärben oder Rechnen keinen Sinn
end;


//__________alles weitere bis hinunter, WENN nach Datum sortiert wird
// die Spalte Datum wird ausgelesen und für diese Zeile verarbeitet
dat_:=DataSource_TradesListen.DataSet.FindField('E ntry_Date').AsDateTime;
monat_ := MonthOf(dat_);
woche_:= WeekOf(dat_);

myKontostand:=DB_Konto.ReadSQL_Kontostand_ausTBGel d(dat_); //findet in tbgeld den Kontostand zu einem bestimmten Datum vom in RadioGroup gewähltem Konto

// _________________jedes neue Monat wird erkannt
if monat_ <> monat_temp then begin
monat_temp:=monat_;
Monatswechsel:=true;
Monatsgewinn:=0;
end;

if Monatswechsel and (DataSource_TradesListen.DataSet.RecNo > 1) then begin // das zeichnet den oberen Rand einer einzelnen Zelle, außer ganz oben
Canvas.Pen.Color := $00243C79; // $005180F5; // Linienfarbe für die Monatstrennung
Canvas.Pen.Width := 5; // Stärke der Linie, erzeugt einen Ballon am Zeilenbeginn
Canvas.MoveTo(Rect.Left,Rect.Top);
Canvas.LineTo(Rect.Right,Rect.Top); // zeichnet eine rote Linie an die Oberkante und damit unter das alte Monat
end;

i:=Columns.Count; // Columns.Count nimmt er, doch "interner Fehler", er scheint falsch zu zählen.
if (DataCol > 12) // das funktioniert jetzt, doch nur für > 12?! ich lasse das einmal so, weil es nicht lohnt. d.h. die Striche sind lang, doch nicht bis zum Ende
then Monatswechsel:=false;
//_______________________ Ende zur Monaterkennung: Es wird das Monat als Zelle erkannt und die Info bis zum Zeilenfortschritt auf Zelle 12 beibehalten, danach alte Farbe/Dicke


// _________________jede neue Woche wird erkannt

if woche_ <> woche_temp then begin
woche_temp:=woche_;
If farbe = clwhite then farbe := $00E7F2FF // wechselt mit der als neu erkannten Woche
else farbe := clWhite;
Wochengewinn:=0; // Der Wochengeweinn wird zurückgeetzt
end;
Canvas.Brush.Color := farbe; // Hintergrundfarbe wird zugewiesen, bewirkt, dass die Hingrundfarbe orange bleibt, bis zum nächsten Wochenwechsel
//_____________ Ende der Wochenbearbeitung


// überschreibt string für die PL wieder, um die PL besser zu formatieren
if (Column.FieldName='PL') then begin // klappt auch: if (dataCol=1).....
d:=DataSource_TradesListen.DataSet.FindField('PL') .AsFloat;
s_cell:=FloatToStrF(d,ffNumber,5,2);
end;

// adddiert die Tradeergenisse zum Periodenfangskapital, rechnet Performance
if (Column.FieldName='ERGEBNIS') then begin // das ist case sensitive !!!
i:=DataSource_TradesListen.DataSet.FindField('ERGE BNIS').AsInteger;
if i < 0 then Canvas.Font.Color := clRed
else Canvas.Font.Color := clGreen;
myKontostand:= myKontostand + i;
Monatsgewinn:=Monatsgewinn + i;
Wochengewinn:=Wochengewinn + i;
end;

if (Column.FieldName='KAPITAL') then
s_cell:=FloatToStrF(myKontostand,ffNumber,5,2);

if (Column.FieldName='Wochengewinn') then begin
s_cell:=FloatToStrF(Wochengewinn,ffNumber,5,2);
if Wochengewinn < 0 then Canvas.Font.Color := clRed
else Canvas.Font.Color := clGreen;
end;

if (Column.FieldName='WoG_Prozent') then begin
if myKontostand = 0 then d:=0
else d:=(Wochengewinn / myKontostand) * 100;
s_cell:=FloatToStrF(d,ffNumber,5,2) + ' %';
if d < 0 then Canvas.Font.Color := clRed
else Canvas.Font.Color := clGreen;
end;

if (Column.FieldName='Monatsgewinn') then begin
s_cell:=FloatToStrF(Monatsgewinn,ffNumber,5,2);
if Monatsgewinn < 0 then Canvas.Font.Color := clRed
else Canvas.Font.Color := clGreen;
end;

if (Column.FieldName='MoG_Prozent') then begin
if myKontostand = 0 then d:=0
else d:=(Monatsgewinn / myKontostand) * 100;
s_cell:=FloatToStrF(d,ffNumber,5,2) + ' %';
if d < 0 then Canvas.Font.Color := clRed
else Canvas.Font.Color := clGreen;
end;
//__________________ Ende Performancerechnungen


// die übermalte Schrift wird wieder eingetragen
Canvas.FillRect(Rect); // steht das vor dem Block "Schriftfarbe", wird nur hinter-dem-Anfüllen-aufgerufen sichtbar
Canvas.TextOut(Rect.Left + 2, Rect.Top + 1,s_cell); // Text wird neu geschrieben


// ShowMessage(IntTostr(Datacol)+ ' ');


end; // zu (Sender as TDBGrid)

end;
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.605 Beiträge
 
Delphi 7 Professional
 
#2

AW: Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

  Alt 25. Nov 2021, 19:00
Probiere bitte mal folgendes:

Statt
Delphi-Quellcode:
i := Columns.Count; // Columns.Count nimmt er, doch "interner Fehler", er scheint falsch zu zählen.
if (DataCol > 12) // das funktioniert jetzt, doch nur für > 12?! ich lasse das einmal so, weil es nicht lohnt. d.h. die Striche sind lang, doch nicht bis zum Ende
then Monatswechsel := false;
bitte
Delphi-Quellcode:
i := DBGrid1.DataSource.DataSet.FieldCount; // Anzahl der Spalten im DataSet.
if (DataCol >= i) then Monatswechsel := false;
Klappt es damit?
  Mit Zitat antworten Zitat
NicoleWagner

Registriert seit: 6. Jul 2010
167 Beiträge
 
Delphi XE3 Professional
 
#3

AW: Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

  Alt 26. Nov 2021, 10:48
danke für die Idee!
Nein, es geht nicht, doch was nicht geht, muss man eben tragen.

und zwar habe ich diese Zwischenergebnisse

i:=DataSource_TradesListen.DataSet.Fields.Count - 1; // 28
i:=DataSource.DataSet.FieldCount; // Anzahl der Spalten im DataSet // 28?!
i:=Column.Field.FieldNo - 1; // 7

Doch der Hund ist vermutlich tiefer begraben:

if (DataCol >= i) then Monatswechsel := false;

Denn dieses "DataCol" hat bei mir nur die Werte von 0 bis 13. Daher muss die Abfrage > 28 stets false sein
Allerdings wie frage ich die Feldnummer statt DataCol ab?
Mit den Verdächtigen oben klappte es nicht.
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.605 Beiträge
 
Delphi 7 Professional
 
#4

AW: Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

  Alt 26. Nov 2021, 11:20
Das wird jetzt echt kompliziert

Was ich wissen möchte:

Wieviele Spalten liefert die Query, wenn Du die manuell im Selectstatement nachzählst. Ebenfalls 28, mehr oder weniger?

Die Spalten des DBGrids sind im Spalteneditor definiert. Wieviele sind das? Stimmt die Reihenfolge mit der im Select überein?
Wenn nein, wäre es möglich, dass Select so umzuschreiben, dass die Spaltenreihenfolge des Selects mit der Spaltenreihenfolge des DBGrids übereinstimmt?

Column.Field.FieldNo gibt an, an welcher Position sich das zur Spalte Column gehörende Feld in der Datenmenge befindet und nicht die Position in der Spaltenreihenfolge im DBGrid. Hier ist das - 1 vermutlich falsch. Hier würde ich eher vermuten, dass das Feld der Spalte, bei der Du i := Column.Field.FieldNo - 1; // 7 ermittelt hast, das achte Feld in der Datenmenge ist. Sollte es sich hierbei um das "letzte" Feld, also die rechts Spalte im DBGrid handeln, dann ändere doch bitte mal die Abfrage auf Monatsende auf if (Column.Field.FieldNo = 8) then Monatswechsel := false; Zugegeben, das ist jetzt auch nur reine Spekulation, aber man weiß ja nie

Eventuell könnte aber auch eine Abfrage auf if (Column.Index = DBGRid1.Columns.Count - 1) then Monatswechsel := false; zum Ziel führen oder alternativ "festverdrahtet": if (Column.Index = 28) then Monatswechsel := false;
  Mit Zitat antworten Zitat
NicoleWagner

Registriert seit: 6. Jul 2010
167 Beiträge
 
Delphi XE3 Professional
 
#5

AW: Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

  Alt 26. Nov 2021, 15:23
Die Query im Feldeditor ebenso wie die DBGrid im Spalteneditor haben jeweils 28 Felder.
Wobei alle Felder im Query-Feldeditor in den DBGrid Spalteneditor hinzugefügt sind.
d.h. die beiden entsprechen einander von der Anzahl her und ihrer Art und Benennung.
Die Reihenfolge im Spalteneditor des DBGrids hingegen stimmt mit der Reihenfolge im Query-Feldeditor in vielen Fällen NICHT überein.

Spannend wird die Query im "Query-Editor" bzw. in der SQL-Formulierung, die ihm entspricht:
Ob die stets 28 Abfragelemente hat, dessen bin ich nicht ganz sicher. Eher ja.
Denn es wird die Query erst zur Laufzeit erstellt: Der Nutzer kann aus 4 umfangreichen Radio-Boxen wählen, was er jeweils abfragen will. Die Kombinationsmöglichkeiten sind so zahlreich, dass ich nicht so leicht sagen kann, wieviele es sind.

D.h. ich hoffe, dass es stets 28 Felder sind.
An das select-statement zur Laufzeit komme ich daher nicht so leicht ran. Es sind wohl hunderte Varianten möglich.
Allerdings arbeite ich zur Zeit nur mit einer Einstellung, die ich nicht verändern möchte, bis die Sache steht.
So das gilt: 28.

Das Select kann daher nicht so umgeschrieben werden, dass die Reihenfolge übereinstimmt.
Abgesehen davon, dass die "calculated" Felder nicht in der query aufscheinen, weil sie erst danach aus den Abfrageergebnissen berechnet werden.
  Mit Zitat antworten Zitat
Delphi.Narium

Registriert seit: 27. Nov 2017
2.605 Beiträge
 
Delphi 7 Professional
 
#6

AW: Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

  Alt 26. Nov 2021, 16:16
Also kurz und knapp:

Das Ganze ist hoch dynamisch.

Momentan hab' ich da keine Idee.

Es scheint wohl so zu sein, dass man nicht davon ausgehen kann, dass alle Zellen von oben links beginnend nach rechts und schön zeilenweise gezeichnet werden, sondern so, wie es das DBGrid für richtig hält bzw. nur jeweils die Zellen, deren Neuzeichnen tatsächlich erforderlich ist. Also z. B. nur der sichtbare Bereich oder die Zellen, die nach dem Wegklicken eines ShowMessagesdialoges wieder sichtbar werden. Dies würde dann auch die nicht nachvollziehbaren Werte für DataCol, ... erklären.

Eventuell gibt es ja noch eine andere Möglichkeit, wenn auch jetzt sehr aus dem Bauch heraus und ungetestet:
Delphi-Quellcode:
// Beispiel von weiter oben etwas abgewandelt:
procedure TForm1.dbgDrawColumnCell(Sender: TObject; const Rect: TRect; DataCol: Integer; Column: TColumn; State: TGridDrawState);
var
  Monat : Integer;
  Monatswechsel : Boolean;
begin
  // Den Monat des aktuellen Datensatzes holen.
  Monat := dbg.DataSource.DataSet.FieldByName('Monat').AsInteger;
  // Den mit dem gemerkten Monat vergleichen.
  Monatswechsel := fMonatOld <> Monat;
  // Hat ein Monatswechsel stattgefunden?
  if Monatswechsel then begin
    // Wenn ja, Linie zeichnen.
    dbg.Canvas.Pen.Color := $00243C79; // $005180F5; // Linienfarbe für die Monatstrennung
    dbg.Canvas.Pen.Width := 5; // Stärke der Linie, erzeugt einen Ballon am Zeilenbeginn
    // Der linke Rand des DBGrids:
    dbg.Canvas.MoveTo(0,Rect.Top);
    // Linie über die Breite des DBGrids:
    dbg.Canvas.LineTo(dbg.Width,Rect.Top);
    fMonatOld := Monat;
  end;
end
Hoffe, dass damit egal ist, welche Spalte zuerst und welche zuletzt gezeichnet wird, da die Linie (hoffentlich) über die gesamte Breite des DBGrids gezogen wird.
  Mit Zitat antworten Zitat
NicoleWagner

Registriert seit: 6. Jul 2010
167 Beiträge
 
Delphi XE3 Professional
 
#7

AW: Wie ziehe ich eine farbige Linie in einem DBGrid / DrawColumnsCell-Event?

  Alt 26. Nov 2021, 16:40
Danke für die Zeit und Mühe und Ideen!

Ich habe viel dabei gelernt über Spalten und Methoden und das DBGrid.

Ich glaube, ich akzeptiere mal die kürzere Linie.
Die "optimale Optik" lasse ich fallen. Denn mein Programm wird bereits sichtbar langsamer.

Was ich mittlerweile noch herausgefunden habe, solltest Du Dich je damit herumschlagen:
Die "calculated" Felder werden an vielen Stellen als "leer" betrachtet, wo sie es eigentlich nicht sein sollten.

Zum Glück habe ich die Query-Ergebnisse noch in ein Array geschrieben, das ich mit Steinzeit-Delphi-Werkzeugen bearbeiten kann und nicht auf das wackelige DataSet Zeug zurückgreifen muss.

Sollte hier jemand eines fernen Tages nachschlagen:
Ich verwende FireDAC und den Typ TADQuery, der viele Vorteile hat, doch so richtig reibungsfrei nicht mit DBGrids interagiert.
Ob Interbase und seine Verwandten besser sind, weiß ich nicht.
Delphi XE3 ist jedenfalls richtig buggy. Die IDE schieße ich zur Zeit mehrmals täglich mit dem Taskmanager ab, weil sie mir den Arbeitsspeicher so zumüllt, dass er auf 99% ansteht und nichts mehr geht.
Hätte ich nicht Angst, dass alles noch viel schlimmer werden könnte, würde ich ein Update nehmen.
  Mit Zitat antworten Zitat
Antwort Antwort

Themen-Optionen Thema durchsuchen
Thema durchsuchen:

Erweiterte Suche
Ansicht

Forumregeln

Es ist dir nicht erlaubt, neue Themen zu verfassen.
Es ist dir nicht erlaubt, auf Beiträge zu antworten.
Es ist dir nicht erlaubt, Anhänge hochzuladen.
Es ist dir nicht erlaubt, deine Beiträge zu bearbeiten.

BB-Code ist an.
Smileys sind an.
[IMG] Code ist an.
HTML-Code ist aus.
Trackbacks are an
Pingbacks are an
Refbacks are aus

Gehe zu:

Impressum · AGB · Datenschutz · Nach oben
Alle Zeitangaben in WEZ +1. Es ist jetzt 05:09 Uhr.
Powered by vBulletin® Copyright ©2000 - 2025, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024-2025 by Thomas Breitkreuz