Delphi-PRAXiS
Seite 1 von 3  1 23      

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Sonstige Fragen zu Delphi (https://www.delphipraxis.net/19-sonstige-fragen-zu-delphi/)
-   -   Delphi TStringGrid OnDrawCell - Bestimmte Felder makieren (https://www.delphipraxis.net/172239-tstringgrid-ondrawcell-bestimmte-felder-makieren.html)

Mazen 20. Dez 2012 08:22

TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Hallo Leute,
ich möchte euch erstmal kurz schildern worum es geht und wozu ich es überhaupt brauche.

Es geht darum eine Übersicht der Ausgaben zu erhalten die in einem auswählbaren Zeitraum von einer auswählbaren Kostenstelle angefallen sind. Diese Daten bekomme ich aus einer Datenbank.

Bisher wurde das mit Excel gelöst. Die Anzeige der Informationen in Excel ist schon ziemlich optimal, allerdings nicht leicht zu pfelgen, bzw. zu aufwendig. Da alle Rechnungen sowieso archiviert werden und in der Datenbank landen wäre es also sinnvoll das auch zu nutzen.

Da die Ansicht wie gesagt in Excel beibehalten werden soll, bzw. auch (noch) kein Ausdruck benötigt wird habe ich gedacht das das TStringGrid recht nah an die Optik von Excel rankommt was Spalten und Zeilen angeht. Nur leider enden da scheinbar auch schon die Gemeinsamkeiten.

An dieser Stelle schonmal der Hinweis: Wenn jemand eine leichtere/bessere Idee hat wie das zu lösen ist bin ich dafür gerne offen ;)
Hab auch überlegt ob es nicht möglich wäre mit Excel auf die Datenbank zuzugreifen, doch das gehört nicht hier ins Delphi Forum ;)

Im Moment häng ich also an dem Problem das bestimmte Zellen entweder Fett, Farbig oder Unterstrichen dargestellt werden müssen um die Lesbarkeit zu erhöhen.
Diese Zellen sind natürlich nicht immer die gleichen da sie dynamisch zur Laufzeit gefüllt werden. Daher kann ich in OnDrawCell Ereignis nicht einfach nach ACol und ARow abfragen.

Ich müsste also beim füllen der Zellen eine Art Kennzeichen setzen die dem Ereignis mitteilt wie diese formatiert werden soll.
Da habe ich nun schon 2 Ansätze verfolgt, leider ohne gewünschtes Ergebnis:

1) Ich erstelle mir 3 Arrays ála "arrBold Array of Array of Integer" in dem ich die Koordinaten der Zellen speicher die fett werden soll und dann beim OnDrawCell Ereignis dieses Array durchlaufe. Leider komme ich damit aber nicht zum Ergebnis.

2) Da ich dachte das das Ereignis nach jedem Eintrag aufgerufen wird hab ich auch versucht mit Booleans zu arbeiten. Heißt also wenn ich eine Zelle fülle die fett werden muss setze ich vorher "makeBold = true" und frage das in der Methode ab. Leider ebenfalls ohne Erfolg.

Leider habe ich die Codeschnippsel nicht mehr da ich in der Zeit weiter rumprobiert habe.
Mit folgendem Code versuch ich die Formatierung zu ändern:

Code:
StringGrid1.Canvas.Brush.Color := StringGrid1.Color;
StringGrid1.Canvas.FillRect(Rect);
StringGrid1.Canvas.Font := StringGrid1.Font;
StringGrid1.Canvas.Font.Style := [fsBold];
StringGrid1.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 2,
StringGrid1.Cells[ACol, ARow]);
Da ich nicht genau weiß wie OnDrawCell arbeitet bzw. wann dieses aufgerufen wird kanns auch sein das meine Ansätze oben totaler Unsinn sind.

Vielleicht könnt ihr mir dabei helfen ;)

DeddyH 20. Dez 2012 08:30

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Es steht doch recht verständlich in der Hilfe: OnDrawCell wird aufgerufen, wenn eine Zelle neu gezeichnet werden muss. Du bekommst das Grid, die aktuelle Spalte und Zeile sowie das Rechteck und den Status der aktuellen Zelle übergeben. Mit diesen Angaben sollte sich doch auswerten lassen, wie die Zelle nun zu zeichnen ist (das wird vermutlich auch von deren Inhalt abhängen, oder?). Beispiele sollten sich reichlich im Forum finden lassen.

Bummi 20. Dez 2012 08:31

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Wenn die Daten aus einer Datenbank kommen, bestünde dann die Möglichkeit eine datengebundenes Grid zu verwenden (z.B. DBGrid) und die Informationen über die gewünschte Darstellung aus der Datenmenge zu ziehen?

Mazen 20. Dez 2012 08:47

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Geht leider nicht weil ich in die Tabelle noch Überschriften, Summen, Differenzen etc. einfügen muss.
Sachen wie "negative Werte sollen rot makiert werden" sind kein Problem. Nur lässt sich vom Tabelleninhalt eben nicht immer ableiten wie ein Feld formatiert werden muss.
Das müsste ich manuell machen können.

Ich werd nochmal was probieren und meinen Versuch dann hier posten, vielleicht kann man mir dann besser helfen ;)

Edit: Das muss jetzt der Vorführeffekt sein :/
Habs nochmal so gemacht wie ich es schonmal hatte. Aber jetzt funktionierts :shock:
Ich denke das ist nicht die einfachste und beste Methode das zu lösen, aber es funktioniert...

Wenn eine Zelle fett soll speicher ich die Koordinaten in einer TStringList. (Ich finde damit ist einfacher zu arbeiten als mit einem Array. Ich teile beide Koordinaten mit einem Strich:

Code:
listBold.Add(IntToStr(x)+'|'+IntToStr(y));
Meine OnDrawCell-Methode sieht dann so aus:

Code:
if listBold.Count > 0 then
begin
  for i:=0 to listBold.Count-1 do
  begin
    if (ACol = StrToInt(AnsiLeftStr(listBold[i],AnsiPos('|',listBold[i])-1))) AND (ARow = StrToInt(AnsiRightStr(listBold[i],Length(listBold[i])-AnsiPos('|',listBold[i])))) then
    begin
      StringGrid1.Canvas.Brush.Color := StringGrid1.Color;
      StringGrid1.Canvas.FillRect(Rect);
      StringGrid1.Canvas.Font := StringGrid1.Font;
      StringGrid1.Canvas.Font.Style := [fsBold];
      StringGrid1.Canvas.TextRect(Rect, Rect.Left + 2, Rect.Top + 2,
      StringGrid1.Cells[ACol, ARow]);
    end;
  end;
end;

Volker Z. 20. Dez 2012 12:20

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Hallo,

wie wäre es mit der Eigenschaft TStringGrid.Objects?

Du könntest Dir eine Klasse (z. B. TFormat) bauen, die Deine Zellenformatierung speichert und jeweils eine Instanz dieser Klasse jeder zu formatierenden Zelle zuordnen.

Dann könntest Du in OnDrawCell
Delphi-Quellcode:
var
  f : TFormat;
begin
  f := TFormat (StringGrid1.Objects [ACol, ARow]);
  if Assigned (f) then
    begin
      StringGrid1.Canvas.Font.Color := f.Color;
      StringGrid1.Canvas.Font.Style := f.Style;
      // usw.
    end
end;

die Zellen entsprechend formatiert ausgeben.

Du darfst natürlich nicht vergessen den belegten Speicher beim "Aufräumen" wieder freizugeben.

Gruß

Mazen 20. Dez 2012 12:25

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Der Ansatz gefällt mir. Scheint übersichtlicher und auch was die Performance angeht besser zu sein.

Allerdings hab ich noch ein paar Fragen.

Delphi-Quellcode:
var
  f : TFormat;
begin
  f := TFormat (StringGrid1.Objects [ACol, ARow]); *1
  if Assigned (f) then
    begin
      StringGrid1.Canvas.Font.Color := f.Color;
      StringGrid1.Canvas.Font.Style := f.Style;
      // usw.
    end
end;
*1 Du erzeugst hier doch erst eine neue Instanz der Klasse TFormat oder nicht? Dementsprechend wären die Werte f.Color und f.Style doch immer dieselben, und zwar die, die im Konstruktor vergeben wurden? Oder nicht?

DeddyH 20. Dez 2012 12:31

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Nö, das ist ein harter Typecast.

Mazen 20. Dez 2012 12:33

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Nach längerem überlegen hab ichs glaub ich.
Ich muss im Vorfeld also ein Objekt der Klasse TFormat erzeugen und die dem Objekt-Array das Stringgrids zuweisen.
Und das kann ich dann wie oben auswerten?!
Ich werds so einfach mal probieren.

DeddyH 20. Dez 2012 12:34

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
So isses. Da Objects ja nun einmal TObject enthält, musst Du auf TFormat casten, wenn Du an dessen Properties und Methoden herankommen willst.

Volker Z. 20. Dez 2012 12:36

AW: TStringGrid OnDrawCell - Bestimmte Felder makieren
 
Zitat:

*1 Du erzeugst hier doch erst eine neue Instanz der Klasse TFormat oder nicht? Dementsprechend wären die Werte f.Color und f.Style doch immer dieselben, und zwar die, die im Konstruktor vergeben wurden? Oder nicht?
Nein. Die Instanz der Formatklasse legst Du beim "Füllen" Deines Grids an.

Delphi-Quellcode:
f := TFormat.Create;
f.Color := clRed;
f.Style := [fsBold];

StringGrid1.Cells[1, 1]   := 'Testdaten';
StringGrid1.Objects [1, 1] := f;
So sollte es tun.

Im Destructor dann noch über alle Zeilen, Spalten laufen Assigned (StringGrid1.Object[i, j]) testen und ggf. freigeben.

Gruß


Alle Zeitangaben in WEZ +1. Es ist jetzt 10:41 Uhr.
Seite 1 von 3  1 23      

Powered by vBulletin® Copyright ©2000 - 2024, Jelsoft Enterprises Ltd.
LinkBacks Enabled by vBSEO © 2011, Crawlability, Inc.
Delphi-PRAXiS (c) 2002 - 2023 by Daniel R. Wolf, 2024 by Thomas Breitkreuz