![]() |
Spaltenbreite DBGrid automatisch anpassen
Hallo,
ich suche für das DBGrid (oder vllt. generell für Grids) die Möglichkeit die Spaltenbreite automatisch anzupassen, so wie die bei Excel das Autofit. Hintergrund ist, dass viele Spalten des Grid einfach viel zu breit sind. Stellt es z.B. ein DB-Feld dar, das ein CHAR(250) Feld ist, so ist die entsprechende Spalte einfach sehr breit, um halt die theor. 250 Zeichen anzuzeigen. Der größte tatsächliche Feldinhalt ist aber z.B. nur 50 Zeichen. Dann könnte die Breite viel kleiner sein. Hinzukommt, dass wenn die Spaltenbreite sehr groß ist (größer als z.B. die Bildschirmbreite) ist es sehr mühselig, wenn nicht unmöglich, das per Hand klein zu ziehen. Mein Workarround in solchen Fällen ist es, alle SPaltenbreiten erstmal auf 50 zu setzen und dann so groß zu ziehen, wie ich sie brauche. Das ist aber auch nicht elegant. Drum die Frage, gibt es bei Grids so eine Eigenschaft? Falls nicht wie baut man das ein, bzw. hat jemand schonmal was diesbezüglich gemacht? |
AW: Spaltenbreite DBGrid automatisch anpassen
Hallo,
eine "dumme" Idee für die Schnelle: Ermittle die maximale Länge des Spalteninhaltes. Nimm den längsten Text und weise diesen der Caption eines Labels zu. Das Label muss AutoSize = True haben. Es bekommt damit die entsprechende Breite des zugewiesenen Textes. Nun nimmst Du den Wert der Eigenschaft Width des Labels rechnest noch 8 (oder so) für ein bisserl Rand dazu und weist diesen Wert als Breite der (DB)Gridspalte zu. Und damit ist das "AutoFit" vorhanden. Das Label kannst Du entweder unsichtbar irgendwo auf das Formular legen oder zur Laufzeit erstellen. Eine entsprechende Routine dem TitleClick der Grids zuweisen und Du hast fast den Effekt von Excel. Ob man bei einem Grid auch eine Ereignisroutine für einen Doppelklick auf die Trennlinie zwischen zwei Spaltenköpfen legen kann, weiß ich nicht. |
AW: Spaltenbreite DBGrid automatisch anpassen
Dazu muss aber auch die gesamte Datenmenge durchlaufen werden, was ggf. schon ein wenig dauern kann.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Und wenn man trotzdem den Weg von naphets gehen will, dann könnte man sich das Label sparen und stattdessen mit TCanvas.TextWidth arbeiten.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Jepp, aber dabei nicht vergessen, dass man auch den richtigen Font zuweisen muss, sonst rechnet man mit falschen Werten.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Zitat:
Z.B. TADOQuery q:
Delphi-Quellcode:
q.SQL.Text:= 'SELECT Max(Length(Feld1)) as F1, Max(Length(Feld2))as F2,... from MyTable';
q.Open; for i:=0 to q.RecordCount-1 do Grid.Columns[i].Width:=q.Fields[i].AsSingle * KonstanterFaktor; |
AW: Spaltenbreite DBGrid automatisch anpassen
So wie gezeigt wird es wohl nicht gehen, Du brauchst ja keine Maximalwerte, sondern die Metadaten. Wenn Du die ausgelesen hast könnte das schon funktionieren, zumindest für Datentypen, deren "Ausgabelänge" sich konkret ermitteln lässt.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Hallo,
Zitat:
Code:
geht doch bestimmt auch und muss einmal beim Programmstart aufgerufen werden. Änderungen zur Programmlaufzeit wollen wir hier mal geflissentlich ignorieren.
Select max(length(Spalte1)) as a, max(length(Spalte2)) as b, ... from Tabelle
Natürlich müssen die Fonts übereinstimmen, da ich immer die gleiche Schrift nutze, tritt das Problem nicht auf. Edit: @Jumpy: Die Idee hatte ich auch, nur leider zu spät ;-) |
AW: Spaltenbreite DBGrid automatisch anpassen
Das klappt aber auch nur bei fixed Fonts, die Länge des enthalteten Strings kann also auch kein eindeutiges Kriterium sein. In Arial sind 10 'X' breiter als 20 'i'. Also entweder doch jeden einzelnen Datensatz anfassen oder eben wie gesagt Metadaten auslesen und Breite auf die größtmögliche stellen. Oder halt einen fixed Font verwenden.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Zitat:
Das mit "Max(Length(Feld1)) as F1" macht natürlich nur bei String-Feldern Sinn, aber die sind es auch, die den meisten Ärger verursachen. Datum und Zahl-Felder sind meist nicht so übertrieben breit. Ich werd mal versuchen ein Beispiel-Unit zu bauen und hochzuladen. |
AW: Spaltenbreite DBGrid automatisch anpassen
Wenn Du mit MAX die Maximalbreite ermitteln kannst, kannst Du auch mit AVG die Durchschnittsbreite ermitteln ;). Multiplizierst Du das dann mit einem "breiten" Buchstaben wie dem angegebenen 'W' ist das zwar nicht der Weisheit letzter Schluss, aber IMO ein akzeptabler Kompromiss, wenn es nicht auf einzelne Pixel ankommt.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Praktische Breite bei variabler Schrift ist
Code:
Damit bin ich in der Regel gut zurechtgekommen.
maximale Buchstabenanzahl
in W * 75% Bei Datum und Zahlen kann man ebenfalls die maximale Länge bestimmen und als Zeichen die 0 statt das W nehmen. |
AW: Spaltenbreite DBGrid automatisch anpassen
Hab ich mal von irgendwo aus dem Netz kopiert und noch etwas überarbeitet
Delphi-Quellcode:
unit uGridColumnWidth;
interface uses DBGrids; procedure SetGridColumnWidths( AGrid : TDBGrid ); implementation uses DB, SysUtils; procedure SetGridColumnWidths( AGrid : TDBGrid ); const DEFBORDER = 10; var temp, idx, bcidx : integer; lmax : array of integer; bm : TBookmark; begin with AGrid do begin SetLength( lmax, Columns.Count ); if dgTitles in AGrid.Options then begin // Measure Title Canvas.Font := AGrid.TitleFont; for idx := 0 to Columns.Count - 1 do if Columns[ idx ].Visible then lmax[ idx ] := Canvas.TextWidth( Columns[ idx ].Title.Caption ) + DEFBORDER; end; // Measure Data Canvas.Font := AGrid.Font; // Anzeige abschalten DataSource.DataSet.DisableControls; try // Aktuellen Datensatz merken bm := DataSource.DataSet.GetBookmark; // Zum ersten Datensatz springen DataSource.DataSet.First; // Alle Datensätze durchwandern while not DataSource.DataSet.EOF and ( DataSource.DataSet.RecNo < DataSource.DataSet.RecordCount ) do begin // Alle Spalten durchwandern for idx := 0 to Columns.Count - 1 do // Ist die Spalte sichtbar? if Columns[ idx ].Visible then begin // Breite des Inhalts ermitteln temp := Canvas.TextWidth ( trim( Columns[ idx ].Field.DisplayText ) ) + DEFBORDER; // nur die maximale Breite merken if temp > lmax[ idx ] then lmax[ idx ] := temp; end; // Nächster Datensatz DataSource.DataSet.Next; end; // Zum Datensatz zurückspringen, der eingangs gewählt war if DataSource.DataSet.BookmarkValid( bm ) then DataSource.DataSet.GotoBookmark( bm ) else DataSource.DataSet.First; finally // Anzeige einschalten DataSource.DataSet.EnableControls; end; // Spaltenbreiten ändern for idx := 0 to Columns.Count - 1 do if Columns[ idx ].Visible then if lmax[ idx ] > 0 then Columns[ idx ].Width := lmax[ idx ]; end; end; { SetGridColumnWidths } end. |
AW: Spaltenbreite DBGrid automatisch anpassen
Danke. Das ist zwar die "Ich acker mal die ganze Datenmenge ab"-Variante, aber dafür cool gelöst (soweit ich das als Newbie beurteilen kann). Wenn ich mal Zeit hab (als Azubi hab ich die vllt.) mach ich mir den Spass und teste mal ab welcher Datenmenge es performanter wird, die Arbeit von der Datenbank erledigen zu lassen. Wobei die angezeigte Datenmenge im Grid in der Regel so klein ist, dass obiges bestimmt schneller ist.
Wer sich dagegen 12 Millionen Datensätz im Grid anzeigen läßt ist selber Schuld.:-D |
AW: Spaltenbreite DBGrid automatisch anpassen
als gäbe noch die Q&D Option zu Laufzeit im OnPaint über Canvas.TextWidth die Spalten zu vergrößern, sofern sie zu schmal sind.
Delphi-Quellcode:
if DBGrid1.Canvas.TextWidth(Column.Field.AsString) > (Rect.Right - Rect.Left) then
begin Column.Width := DBGrid1.Canvas.TextWidth(Column.Field.AsString); end; |
AW: Spaltenbreite DBGrid automatisch anpassen
Das könnte aber unschöne Effekte beim Scrollen zur Folge haben.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Zitat:
|
AW: Spaltenbreite DBGrid automatisch anpassen
Also wir haben das so gelöst:
Delphi-Quellcode:
Leider mussten wir GetTextExtentPoint32 für die Textbreite verwenden, da Canvas.TextWidth manchmal einen fehlerhaften (zu kleinen) Wert liefert.
function TextGroesse(const Text : string; Font : TFont = nil) : TSize;
var DC : hDC; F : hFont; R : TRect; begin F := 0; DC := GetDC(0); try if Font <> nil then F := SelectObject(DC, Font.Handle); if not GetTextExtentPoint32(DC, Text, Length(Text), Result) then begin Result.cx := 0; Result.cy := 0; end; finally if F <> 0 then SelectObject(DC, F); ReleaseDC(0, DC); end; end; procedure SetColumnWidth(DBGrid : TDBGrid); var i, j : integer; iMaxRow : integer; begin with DBGrid do begin // maximal || Zeilen durchsuchen iMaxRow := Min(40, DataSource.DataSet.RecordCount); try DataSource.DataSet.DisableControls; Visible := false; // notwendig, da controls disabled! DataSource.DataSet.First; // mit Breite der Überschriften inizialisieren for i := 0 to Columns.Count - 1 do begin Columns.Items[i].Width := TextGroesse(Columns[i].Title.Caption, Canvas.Font).cx + 10; end; // auf die größte Breite der ersten iMaxRow Zeilen stellen for j := 0 to iMaxRow - 1 do begin for i := 0 to Columns.Count - 1 do begin Columns.Items[i].Width := Max(TextGroesse(Fields[i].Text, Canvas.Font).cx + 10, Columns.Items[i].Width); end; DataSource.DataSet.Next; end; DataSource.DataSet.First; finally DataSource.DataSet.EnableControls; Visible := true; end; end; end; Bemerkungen: 1. Da wir z.T. sehr viele Datensätze haben können > 10 Mio. haben wir die Breitenberechnung auf 40 DS beschränkt. 2. An die Textbreite wird + 10 angehängt um einen kleinen Abstand zur Begrenzung zu haben. 3. Wir haben auf Bookmarks verzichtet, da die Berechnung der Breite nur beim inizialen Laden der Daten notwenig ist. 4. Besonders wichtig sind DisableControls und Visible := false, damit wird die Funktion um ein vielfaches schneller. Gruß David |
AW: Spaltenbreite DBGrid automatisch anpassen
Man könnte auch den Canvas fragen, wie viele Pixel der Text gerendert hat.
|
AW: Spaltenbreite DBGrid automatisch anpassen
Hallo,
oder mal das TJVDBGrid von den Jedis anschauen, es hat ein Attribut für maximale Spaltebreite, für minimale Spaltenbereite, kann, wenn ich das richtig sehe, auch die Spaltenbreite automatisch auf das richtige Maß bringen. Könnte von daher eine Alternative zum "Selbermachen" sein. |
AW: Spaltenbreite DBGrid automatisch anpassen
Hallo Leute
Hab das StringGrid von ![]() genommen. Ist genial, damit kannn man alles machen. Mit einer einfachen Programmzeile:
Code:
Werden die Spalten automatisch an die Textgrösse angepasst.
AdvStringGrid1.AutoSizeColumns(True, 4);
Ist nicht ganz billig, aber wenn man die Zeit fürs "Rumwursteln" rechnet. Bestimmt nicht die schlechteste Wahl. |
AW: Spaltenbreite DBGrid automatisch anpassen
Das Argument, das das Ganze bei 12 Mio Datensätzen vielleicht doch etwas länger dauert kann man dadurch begegnen, das man einfach vorgibt, das die Messung der Spaltenbreite nach X Zeilen beendet wird. So macht das DevExpress. Dann werden nur die ersten (z.B.) 500 Zeilen eingelesen per Canvas.GetTextWidth ausgemessen. Das reicht eigentlich immer, denn wer scrollt schon 500 Zeilen nach unten.
Das dynamische Anpassen hatte ich mal gemacht, als ich paging implementiert habe. Man freut sich, das es so schön funktioniert, aber irgendwie nervt es nach ner WEile. |
AW: Spaltenbreite DBGrid automatisch anpassen
Ich lasse gewöhnlich den Anwender entscheiden, wie breit er seine Spalten haben möchte, und speichere die Abmessungen in einer extra Tabelle, in der nur solche Anwender-Daten hinterlegt werden. Meine DBGrids starten meist – d.h. wenn es so viele Felder in der Tabelle gibt, daß sie auch auf einem sehr breiten Screen nicht alle gleichzeitig darstellbar sind – mit einer Standard-Spaltenbreite, die sich nicht an der möglichen Länge der Tabellen-Inhalte orientiert, sondern an der Länge des Spalten-Titels. Der Anwender kann sich dann seine bevorzugten Spaltenbreiten selber einstellen, seine Einstellungen werden beim Beenden des Programms (oder auch, wenn man will, nach jeder Spaltenbreiten-Änderung) in der DB gespeichert und bei Programmstart wieder eingelesen und angewendet:
Delphi-Quellcode:
// Spaltenbreiten DBGrid_V_Artikel in FormMain
z := FormMain.DBGrid_V_Artikel.Columns.Count -1; FOR i := 0 TO z DO BEGIN Aus := IntToStr(i); IF i < 10 THEN Aus := N + Aus; Aus := 'TAB_ARTIKEL_' + Aus; FormMain.DBGrid_V_Artikel.Columns[i].Width := DatMod.Dset_Tabellen.FieldByName(Aus).AsInteger; END; |
AW: Spaltenbreite DBGrid automatisch anpassen
Zitat:
|
AW: Spaltenbreite DBGrid automatisch anpassen
Zitat:
|
Alle Zeitangaben in WEZ +1. Es ist jetzt 12:36 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