Feldbreiten des DBGrid an Textbreite anpassen

Für Themen zu Datenbanken und Zugriff auf diese. Auch für Datenbankkomponenten.
Antworten
aldicek
Beiträge: 37
Registriert: Do 6. Mär 2008, 12:48
OS, Lazarus, FPC: WinXP/Mint13KDE (Lazarus 1.0.8 FPC 2.6.2)
CPU-Target: 64 Bit
Wohnort: Halle (Saale)

Feldbreiten des DBGrid an Textbreite anpassen

Beitrag von aldicek »

Hallo, liebe Forumteilnehmer!

Ich möchte in meinem DBGrid mittels einer Prozedur die Spaltenbreiten an den längsten Text jeder Spalte anpassen. Habe schon jede Menge in Google gesucht, bin aber leider bisher nicht fündig geworden. Mein Ansatz ist, durch mein Grid (ist immer nur ein kleines mit einer überschaubaren Anzahl Spalten (5) u. Zeilen (9..20)) spaltenweise durch alle Zeilen zu gehen und die maximale Textbreite respektive -weite zu ermitteln und mit dieser die Spaltenbreite neu zu setzen. Folgende Frage: Wie ermittle ich die Breite des Textes (TextWidth(...)?)? Ist diese in Punkten zu lesen? Setze ich die neue Breite mit DBGrid.Columns.Items[Col].Width := ...? Oder muss ich da etwas umrechen?
Wäre für jeden Hinweis dankbar!

Gruß
Aldi

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Canvas.TextExtend('Meintext').x

Gibt dir die Breite eines Textes in Pixeln an.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

...Und das müsstest du direkt der oben genannten Eigenschaft zuweisen können.
Johannes

aldicek
Beiträge: 37
Registriert: Do 6. Mär 2008, 12:48
OS, Lazarus, FPC: WinXP/Mint13KDE (Lazarus 1.0.8 FPC 2.6.2)
CPU-Target: 64 Bit
Wohnort: Halle (Saale)

Beitrag von aldicek »

Hallo und vielen Dank für die schnellen Antworten!

Mein Problem ist momentan noch, dass ich einfach nicht weiss, wie ich an den Text einer durch Spalte, Zeile definierten Zelle heran komme. Das für mich Wichtige: Canvas.TextExtend(DBGrid.DataSource.DataSet.undwaskommtjetzt?) Oder gibt es noch einen einfacheren Weg? (Sorry für die für viele von euch sicher doofe Frage, aber es ist schon eine Zeit her, dass mich mich zuletzt damit beschäftigt habe und man vergißt wirklich verdammt schnell verdammt viel.)

Gruß
Aldi

monta
Lazarusforum e. V.
Beiträge: 2809
Registriert: Sa 9. Sep 2006, 18:05
OS, Lazarus, FPC: Linux (L trunk FPC trunk)
CPU-Target: 64Bit
Wohnort: Dresden
Kontaktdaten:

Beitrag von monta »

DBGrid.Datasource.DataSet.RecNo(Integer) >> setzt aktiven Datensatz (also letztlich die Zeile)

...DataSet.FieldByName('Feldname').AsString >> gibt den String-Wert der mit Feldnamen angegebenen Spalte der oben gesetzten Zeile zurück, also eine konkrette Zelle.

Mit Dataset.First und Next kannst du in ner Schleife auch alle Datensätze durchgehen, bspw:

Code: Alles auswählen

var: MaxBreite: integer;
 
DataSet.First;
MaxBreite := 0;
while not Dataset.EOF do
begin
  if Canvas.TextExtend(DataSet.FieldByName('Spalte1').AsString > MaxBreite; then
    MaxBreite := Canvas.TextExtend(DataSet.FieldByName('Spalte1').AsString;
  DataSet.Next;
end;
//Und dann Zuweisung an entsprechende Spalte:
DBGrid.Columns.Items[Spalte1].Width := MaxBreite;
Johannes

Benutzeravatar
theo
Beiträge: 10862
Registriert: Mo 11. Sep 2006, 19:01

Beitrag von theo »

Also ich versteh zwar nicht viel von DB unter Lazarus, aber ich würde das
OnPrepareCanvas Ereignis nehmen.
Das sollte eigentlich immer auf dem aktuellen Datensatz stehen und mit DataCol kann man das Feld abholen und gleich Column.Width setzen.
Es heisst übrigens TextExtenT, aber TextWidth würde reichen.
Ich stelle mir das so vor, das müsste das Problem eigentlich lösen ohne viel Geeiere (nicht getestet)

Code: Alles auswählen

procedure TForm1.DBGrid1PrepareCanvas(sender: TObject; DataCol: Integer;
  Column: TColumn; AState: TGridDrawState);
var Wid:Integer;
begin
 Wid:=Canvas.TextWidth(TDBGrid(Sender).DataSource.DataSet.Fields[DataCol].AsString);
 if Column.Width<Wid then Column.Width:=Wid;
end;

Christian
Beiträge: 6079
Registriert: Do 21. Sep 2006, 07:51
OS, Lazarus, FPC: iWinux (L 1.x.xy FPC 2.y.z)
CPU-Target: AVR,ARM,x86(-64)
Wohnort: Dessau
Kontaktdaten:

Beitrag von Christian »

Warnung recNo dürfe nicht bei allen TDataSet abkömmlingen Funktionieren. In SQL Tabellen hat man schlichtweg in 90% der Fälle keine Recordnumber. geht ja auch nicht weil die Abfrage ja stark variieren kann.

Am effizientesten wäre das in Grid zu machen du könntest dir einen Nachfahren vom DBGrid ableiten und das über den Buffer des DataSets machen. Das wäre viel schneller als tatsächlich die datensätze durchzugehn. problem ist dabei das beim scrollen die Spaltenbreite springen dürfte.
W.m.k.A.h.e.m.F.h. -> http://www.gidf.de/

Benutzeravatar
af0815
Lazarusforum e. V.
Beiträge: 6766
Registriert: So 7. Jan 2007, 10:20
OS, Lazarus, FPC: FPC fixes Lazarus fixes per fpcupdeluxe (win,linux,raspi)
CPU-Target: 32Bit (64Bit)
Wohnort: Burgenland
Kontaktdaten:

Beitrag von af0815 »

Ich meine, der schnellste Ansatz ist (mit einer Unschärfe):

Unmittelbar nach der Abfrage aus der Datenbank, so wie von Monta gebracht, durch die Datenmenge gehen, nur dort den längsten String speichern.
Dann erst mittels TextExtend die Länge bestimmen und die Spalte des Grids setzen.
Dann erst die Datenmenge an das Grid hängen.

Warum: Wird bei der kleinen Anwendung nicht so spürbar sein, sind aber viele Datensätze und Spalten vorhanden, so kosten das ausrechen der Breite mehr. Bei der Stringlänge kann es nur vorkommen, das das Feld nicht zu 100% genau definiert wird, weil bei einigen Zeichen (i etc.) Platz eingespart wird. Ich verwende zur Errechnung der Feldbreite einen breiten Buchstaben als Muster.
Blöd kann man ruhig sein, nur zu Helfen muss man sich wissen (oder nachsehen in LazInfos/LazSnippets).

aldicek
Beiträge: 37
Registriert: Do 6. Mär 2008, 12:48
OS, Lazarus, FPC: WinXP/Mint13KDE (Lazarus 1.0.8 FPC 2.6.2)
CPU-Target: 64 Bit
Wohnort: Halle (Saale)

Beitrag von aldicek »

Vielen Dank, Leute!

Es hat wirklich geklappt, prima!

Gruß
Aldi

Antworten