![]() |
Datenbank: ABS_Database • Version: 7.92 • Zugriff über: ABSTable/ABSQuery
Einträge aus Datenbankfeld in Combobox
Hallo,
in einer Tabelle habe ich ein Feld, welches ich als Wert einer Combobox zuweise. Das passiert, weil vorhandene Werte bei Neueingaben zur Verfügung stehen sollen. Nun dauert das ganze sehr lange, weil ich alle Einträge durchlaufe und zu einer Liste hinzufüge, die ich dann der jeweiligen Combobox zuweise. Das ist mein Code dazu:
Delphi-Quellcode:
Habt ihr eine Idee, wie ich die ganze Sache beschleunigen kann und wenn, geht das per SQL Befehl?
procedure TForm3.InitComboBox(Table_toInit: TABSTable);
var X: Integer; Dummy_String: string; Dummy_SL1, Dummy_SL2: TStringList; Dummy_SL_Regal, Dummy_SL_Fach: TStringList; begin { Ersten Datensatz anwählen } Form_Bibo2.ABSTable1.First; { Listen initialisieren } Dummy_SL1 := TStringList.Create; Dummy_SL1.Sorted := True; Dummy_SL1.Duplicates := dupIgnore; Dummy_SL2 := TStringList.Create; Dummy_SL2.Sorted := True; Dummy_SL2.Duplicates := dupIgnore; Dummy_SL_Regal := TStringList.Create; Dummy_SL_Regal.Sorted := True; Dummy_SL_Regal.Duplicates := dupIgnore; Dummy_SL_Fach := TStringList.Create; Dummy_SL_Fach.Sorted := True; Dummy_SL_Fach.Duplicates := dupIgnore; for X := low(Const_Autors) to high(Const_Autors) do Dummy_SL1.Add(Const_Autors[X]); for X := low(Const_Publishers) to high(Const_Publishers) do Dummy_SL2.Add(Const_Publishers[X][1]); { Solange nicht das Tabellenende erreicht ist mache.. } while not Table_toInit.Eof do begin { Spalte einlesen Autor } Dummy_String := Trim(Table_toInit.FieldByName(Table_Bibo2.Labels_DB[1]).AsString); { Länge prüfen } if Length(Dummy_String) > 0 then begin { Zur Liste hinzufügen } Dummy_SL1.Add(Dummy_String); end; { Spalte einlesen Publisher } Dummy_String := Trim(Table_toInit.FieldByName(Table_Bibo2.Labels_DB[5]).AsString); { Länge prüfen } if Length(Dummy_String) > 0 then begin { Zur Liste hinzufügen } Dummy_SL2.Add(Dummy_String); { Breite des Eintrages an die ComBobox weitergeben } end; { Spalte einlesen Regal } Dummy_String := Trim(Table_toInit.FieldByName(Table_Bibo2.Labels_DB[10]).AsString); { Länge prüfen } if Length(Dummy_String) > 0 then begin { Zur Liste hinzufügen } Dummy_SL_Regal.Add(Dummy_String); { Breite des Eintrages an die ComBobox weitergeben } end; { Spalte einlesen Fach } Dummy_String := Trim(Table_toInit.FieldByName(Table_Bibo2.Labels_DB[11]).AsString); { Länge prüfen } if Length(Dummy_String) > 0 then begin { Zur Liste hinzufügen } Dummy_SL_Fach.Add(Dummy_String); { Breite des Eintrages an die ComBobox weitergeben } end; { Nächsten Datensatz anwählen } Table_toInit.Next; end; { .. und zurück zum ersten Datensatz } Table_toInit.First; { ComboBox-Inhalte nun zuweisen } ComboBox_AddBook_Author.Items.Assign(Dummy_SL1); ComboBox_AddBook_Publisher.Items.Assign(Dummy_SL2); ComboBox_AddBook_Regal.Items.Assign(Dummy_SL_Regal); ComboBox_AddBook_Fach.Items.Assign(Dummy_SL_Fach); { Listen aus dem Speicher entfernen } Dummy_SL1.Free; Dummy_SL2.Free; Dummy_SL_Regal.Free; Dummy_SL_Fach.Free; end; LG Mathias |
AW: Einträge aus Datenbankfeld in Combobox
Zitat:
es ist nicht nur deswegen. ![]() Und natürlich kannst du auch die jeweiligen Daten für jede ComboBox mit einer Abfrage von der DB holen, anstatt das aus diesem Dataset auszulesen, inkl. Sortierung und Gruppierung bzw. Distinct (Doppeltes entfernen). Autors und Publisher braucht man nur zu machen, wenn noch nichts in der ComboBox steht (beim ersten Mal), denn es ändert sich eh nie wieder (Konstante). Und das sind nicht zufällig einfache statische oder dynamische String-Arrays?
Delphi-Quellcode:
ComboBox_AddBook_Author.Items.Clear;
ComboBox_AddBook_Author.Items.AddStrings(Const_Autors); //bzw. if ComboBox_AddBook_Author.Items.Count = 0 then ComboBox_AddBook_Author.Items.AddStrings(Const_Autors); |
AW: Einträge aus Datenbankfeld in Combobox
Hallo,
was ist denn das Ziel des ganzen? Ich verstehe z.B. nicht, warum du das Sorted am Anfang machst und nicht zum Schluss. Frage2: Wie viele Einträge haben denn die einzelnen ComboBoxen? Frage3: { Ersten Datensatz anwählen } Form_Bibo2.ABSTable1.First; { Solange nicht das Tabellenende erreicht ist mache.. } while not Table_toInit.Eof do { .. und zurück zum ersten Datensatz } Table_toInit.First; Sind ganz andere Tabellen. |
AW: Einträge aus Datenbankfeld in Combobox
Zitat:
DisableControls kann ich leider nicht einsetzen, weil ich die Datenbank zum Beginn des Programmstarts auf Plausibilität prüfe. Hier Teste ich z.B. auch, ob es in der Datenbankstruktur Änderungen gab. Dazu muss ich auch die Tabelle einmal öffnen, um gelöschte Felder (Field) erkennen zu können. Die Autoren sind als Array of String deklariert. Const_Autors : array [ 1 .. 5889 ] of string = ( 'Autor 1', 'Autor 2' .... ); Bei der Verwendung von Deinem Code ergibt sich eine Fehlermeldung: [dcc32 Fehler] Unit3.pas(212): E2250 Es gibt keine überladene Version von 'AddStrings', die man mit diesen Argumenten aufrufen kann |
AW: Einträge aus Datenbankfeld in Combobox
Zitat:
Ich bin kein Programmierer, mir fehlen viele Grundlagen. Sortet und dupignore hatte ich zum Anfang gestellt, weil ich hoffte, dass doppelte Einträge somit besser gefiltert werden. Frage 2: Const_Autors : array [ 1 .. 5889 ] of string = ('Autor 1', 'Autor 2', ... ); Hinzu kommen noch die Autoren aus der Datenbank, welche vom Benutzer hinzugefügt wurden. Frage 3: Danke, das war noch ein Flüchtigkeitsfehler, es waren dennoch die gleichen Tabellen. |
AW: Einträge aus Datenbankfeld in Combobox
DisableControls hat doch nichts mit irgendwelchen Prüfungen zu tun?
Es hängt die GUI ab, damit diese nicht "sinnlos", beim Scrollen durch das DataSet, alles in die Edits lädt, was eh niemand sehen will. Bei dupIgnore muß man Sorted=True machen, da die StringList sonst den Inhalt nicht schnell prüfen kann. Auf die Semantik einer Datenbank bezogen macht mit Sorted=True das IndexOf einen IndexScan und mit False ein FullTableScan, denn in einer sortierten Liste lässt sich schneller suchen. Zitat:
Tipp: Das kann man hier im Profil angeben. (und in einigen Unterforen auch nochmal, falls die Frage mal abweichend vom Profil ist) ![]() Mist, dachte das war als
Delphi-Quellcode:
und nicht als
array of string
Delphi-Quellcode:
deklariert.
TArray<string>
Dann geht es leider nur mit dynamischen Arrays. :cry: |
AW: Einträge aus Datenbankfeld in Combobox
Zitat:
2. Delphi 10.3 CE 3.
Delphi-Quellcode:
ist was anderes als
array of string
Delphi-Quellcode:
?
TArray<string>
Die Schleife des Array wird schnell eingelesen. Die Datenbankoperation dauert sehr lange. Da hätte ich mir gewünscht, eine schnellere Variante nutzen zu können. LG Mathias |
AW: Einträge aus Datenbankfeld in Combobox
Als "Typ" ist es das Gleiche (nur eine andere Notation),
aber als "Paramater" ist Ersteres ein "Open Array" und kein "Dynamic Array". Also "Open Array" kann es praktisch jede Art von Array-Typ annehmen, sie die Format-Funktion, wo man auch direkt
Delphi-Quellcode:
reingeben kann.
[irgendwas, anderes, hier]
Und "Static Array" sind Jene, welche mit fester Größe definiert wurden. Außerdem können en oder zwei Ressourcen-Schutzblöcke nie schaden. (try finally) * TForm3 ist ein "blöder" Name. * Wie bereits jemand sagte ist "Form_Bibo2.ABSTable1" die falsche Tabelle oder die falsche Variable (denn es gibt ja Table_toInit als Parameter). * Zwischendrin ein paar alternative Schreibweisen. (siehe Kommentare) * Ich weiß, es fehlen paar Leerzeichen. (Tipp: siehe [Zitat] unten rechts :wink:)
Delphi-Quellcode:
// ich weiß nicht seit wann, aber Array-Konstanten kann man nun auch ohne Längenangabe deklarieren
// und damit geht dann auch AddStrings. const //Const_Autors: array[0..2] of string = ['a', 'b', 'c']; Const_Autors: TArray<string> = ['a', 'b', 'c']; Const_Publishers: array of array of string = [['d', 'g'], ['e', 'h'], ['f', 'i']]; procedure TForm3.InitComboBox(Table_toInit: TABSTable); var TFAutor, TFPublisher, TFRegal, TFFach: TField; SLAutor, SLPublisher, SLRegal, SLFach: TStringList; i: Integer; S: string; begin TFAutor := Table_toInit.FieldByName(Table_Bibo2.Labels_DB[1]); // nicht in jedem Schleifendurchlauf erneut das Field suchen TFPublisher := Table_toInit.FieldByName(Table_Bibo2.Labels_DB[5]); TFRegal := Table_toInit.FieldByName(Table_Bibo2.Labels_DB[10]); TFFach := Table_toInit.FieldByName(Table_Bibo2.Labels_DB[11]); SLAutor := TStringList.Create(dupIgnore, True, False); SLPublisher := TStringList.Create(dupIgnore, True, False); SLRegal := TStringList.Create(dupIgnore, True, False); SLFach := TStringList.Create(dupIgnore, True, False); Table_toInit.DisableControls; // GUI vorübergehend abhängen/deaktiveren, damit die nicht "sinnlos" bei jedem First/Next mitarbeitet. try { for S in Const_Autors do // Einzeln übergeben, oder wie Nachfolgend als Eins SLAutor.Add(S); } SLAutor.AddStrings(Const_Autors); { // seit Delphi 2009? var Pub: array of string; // der Unter-Typ von Const_Publishers[i] -> oben, VOR begin definiert for Pub in Const_Publishers do SLPublisher.Add(Pub[1]); // seit Delphi 10.4 nutzbar (war angelbich schon heimlich in 10.3 drin) for var Pub in Const_Publishers do SLPublisher.Add(Pub[1]); } for i := low(Const_Publishers) to high(Const_Publishers) do SLPublisher.Add(Const_Publishers[i][1]); { // DisableControls erst an der Schleife und nicht ins übergeordnete Try-Finally integriert Table_toInit.DisableControls; try Table_toInit.First; while not Table_toInit.Eof do begin ... Table_toInit.Next; end; Table_toInit.First; finally Table_toInit.EnableControls; end; } Table_toInit.First; while not Table_toInit.Eof do begin S := TFAutor.AsString.Trim; if S <> '' then SLAutor.Add(S); S := TFPublisher.AsString.Trim; if S <> '' then SLPublisher.Add(S); S := TFRegal.AsString.Trim; if S <> '' then SLRegal.Add(S); S := TFFach.AsString.Trim; if S <> '' then SLFach.Add(S); Table_toInit.Next; end; Table_toInit.First; { // Wozu überhaupt das Trim? // "falsche" Daten sind einfach "ungültig" ... gehört in den Daten behoben und nicht in der Anzeige Table_toInit.First; while not Table_toInit.Eof do begin if not TFAutor.IsEmpty then SLAutor.Add (TFAutor.AsString); if not TFPublisher.IsEmpty then SLPublisher.Add(TFPublisher.AsString); if not TFRegal.IsEmpty then SLRegal.Add (TFRegal.AsString); if not TFFach.IsEmpty then SLFach.Add (TFFach.AsString); Table_toInit.Next; end; Table_toInit.First; // Man könnte auch einfach "Alles" hinzufügen (ohne if-not-empty) und anschließend das '' wieder entfernen. //if SLAutor.Find('', i) then SLAutor.Delete(i); // und vorher in der Schleife bloß die SLAutor.Add(TFAutor.AsString); oder SLAutor.Add(TFAutor.AsString.Trim); } ComboBox_AddBook_Author.Items.Assign(SLAutor); ComboBox_AddBook_Publisher.Items.Assign(SLPublisher); ComboBox_AddBook_Regal.Items.Assign(SLRegal); ComboBox_AddBook_Fach.Items.Assign(SLFach); finally SLAutor.Free; SLPublisher.Free; SLRegal.Free; SLFach.Free; Table_toInit.EnableControls; end; end; |
AW: Einträge aus Datenbankfeld in Combobox
Hallo,
weißt Du denn, wo genau das Performance-Problem ist? Was sagt denn der Debugger? |
AW: Einträge aus Datenbankfeld in Combobox
Zitat:
In der *dpr habe ich mittels GetTickCount jede Form-Erstellung gemessen. Komisch war hier immer, dass die Zeiten sehr gering waren. Ich hänge heute Abend das Project mal an. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 08:08 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 by Thomas Breitkreuz