![]() |
Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Hallo :)
Ich möchte Einträge aus Editfeldern in eine Listview übertragen, aber nur wenn sie nicht schon in dieser zu finden sind. Mit meinem derzeitigen Code kann ich nur einen Eintrag hinzufügen und danach keinen mehr. Das sehe ich auch an dem Code. ;) Zwei Varianten möchte ich gerne verstehen: 1. Wo muss ich edit1.text einfügen? (Wenn edit1.text schon in der ersten Spalte zu finden ist, soll kein neuer Eintrag erstellt werden und eine showmessage folgen) 2. Wo muss ich edit1.text und edit4.text einfügen? (So wie oben nur wenn edit1.text und edit4.text in der selben Zeile vorhanden sind) Bitte so einfach wie möglich, bin Anfänger.
Delphi-Quellcode:
Danke schon mal. :)procedure TForm2.Button1Click(Sender: TObject); begin if form2.RadioButton1.checked=true and assigned (form1.listview1.items[0])=false then begin with form1.listview1.items.add do begin caption:=edit1.text; subitems.add(edit2.text); subitems.add(edit3.text); subitems.add(edit4.text); showmessage('Eintrag wurde hinzugefügt'); end; end; |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
@DeddyH
Hi :) Ist das nicht gern gesehen, wenn man das gleiche in zwei Foren postet? Kann ja sein, dass jemand der die Lösung weiß nur in einem Forum registriert ist. |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
In den Crossposts bereits geklärt. Hier noch einmal etwas ausführlicher in einer anderen Variante
Delphi-Quellcode:
Dann im MainForm.Destroy Event aufräumen ...interface ... type // später leichter lesbar ... TEindeutigeEintraegeAddResult = (arVorhanden, arNeu); TMainForm: class(TForm) ... private // Feld, in dem die Stringlist Instanz gespeichert wird fEindeutigeEintraege : TStringList // read only Property für die Liste "EindeutigeEintraege". // Über diese Property wird aus dem Programm auf die Liste zugegriffen!! property EindeutigeEintraege:TStringList read get_EindeutigeEintraege; // Getter für die Property "EindeutigeEintraege" function get_EindeutigeEintraege:TStringList; function EindeutigeEintraegeAdd(const neuerEintrag:String):TEindeutigeEintraegeAddResult; protected procedure ButtonIrgendwasClick(Sender:TObject) public end; implementation // Getter für die Property "EindeutigeEintraege" function TMainForm.get_EindeutigeEintraege:TStringList; begin // gibt es die Liste schon als Instanz im Speicher? > wenn ja zurückgeben if assigned(fEindeutigeEintraege) then exit(fEindeutigeEintraege); // anderenfalls neue Instanz erstellen, Liste konfigurieren und zurückgeben fEindeutigeEintraege := TStringList.Create; fEindeutigeEintraege.sorted := true; // muss sein, damit der Duplettencheck greift. ist auch schneller! fEindeutigeEintraege.Duplicates := dupIgnore; // Liste erstellt keine doppelten Einträge (ignoriert diese ohne Fehler zu werfen) // fertig konfigurierte Listeninstanz zurückgeben exit(fEindeutigeEintraege); end; function TMainForm.EindeutigeEintraegeAdd(const neuerEintrag:String):TEindeutigeEintraegeAddResult; var lCount:Integer; begin lCount := EindeutigeEintraege.Count; EindeutigeEintraege.add(neuerEintrag); // wurde ein neuer Eintrag hinzugefügt oder ist die Anzahl der Einträge gleich? // den Eintrag gab es schon if lCount = EindeutigeEintraege.Count then exit(arVorhanden); // neuerEintrag war bereits vorhanden // den Eintrag gab es noch nicht exit(arNeu); end; procedure TMainForm.ButtonIrgendwasClick(Sender:TObject); var lMachWas:Boolean; begin // check: muss etwas getan werden? if form2.RadioButton1.checked then lMachWas := EindeutigeEintraegeAdd(edit1.text) = arNeu; // ab hier ist durch den ersten Aufruf sichergestellt, dass fEindeutigeEintraege instanziert ist try if lMachWas then begin // "with" ist nicht immer von Vorteil. aber um bei deinem Beispiel zu bleiben ... with form1.listview1.items.add do begin caption:=edit1.text; subitems.add(edit2.text); subitems.add(edit3.text); subitems.add(edit4.text); end; showmessage('Eintrag wurde hinzugefügt'); except // Verarbeitung ist in die Grütze gegangen . vorgemerkten eindeutigen Eintrag wieder entfernen EindeutigeEintraege.delete(edit1.text); end; end;
Delphi-Quellcode:
if assigned(fEindeutigeEintraege) then fEindeutigeEintraege.free;
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Zitat:
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Zitat:
Wenn die Frage in einem Forum vollständig beantwortet wurde, dann brauchen sich die Leute aus dem anderen Forum nicht die Mühe machen und eine unnötige neue Antwort zusammentippen ... Zeit ist ja auch irgendwo ein wertvolles Gut. Richtig ? :wink: |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Da habt ihr Recht!
Ich seh mir den Code morgen an. |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Ich habe jetzt folgenden Code geschrieben, da ich eure nicht verstehe und es eine einfache Lösung geben muss.
Delphi-Quellcode:
Bei
procedure TForm2.Button1Click(Sender: TObject);
var i: integer; begin if form2.RadioButton1.checked=true then for i := 0 to 50 do if (form1.ListView1.Items[i].Caption=edit1.text) then showmessage('Eintrag bereits vorhanden') else begin with form1.listview1.items.add do begin caption:=edit1.text; subitems.add(edit2.text); subitems.add(edit3.text); subitems.add(edit4.text); showmessage('Eintrag wurde hinzugefügt'); end; end;
Delphi-Quellcode:
gibt er mir einen sigsegv Fehler wenn das Programm läuft und die Procedure gefordert ist.
(form1.ListView1.Items[i].Caption=edit1.text)
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Warum zählst du denn hier bis 50?
Delphi-Quellcode:
for i := 0 to Form1.Listview1.Items.Count - 1 do
Zitat:
Delphi-Quellcode:
für True.
if Form2.RadioButton1.Checked
Delphi-Quellcode:
für False.
if not Form2.RadioButton1.Checked
So ist es besser. |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Außerdem erst alle Einträge duchsehen, und danach (außerhalb der For-Schleife) dann auswerten, ob es gefunden wurde, oder nicht.
Eventuell gibt es zum Suchen auch eine Methode ala IndexOf, so wie bei vielen Listen/Collections. Anderrum geht es bei "mache etwas, wenn nicht vorhanden" nunmal nicht. Bei "mache etwas, wenn vorhanden, dann kann man die Liste durchgehen, beim Fund etwas machen und dann mit Break abbrechen, falls nicht weitere Funde ebenfalls behandelt werden sollen. Warum benutzt du die Variable Form2, wo der Code schon in TForm2 drin steht? Und die oftmalige Verwendung der Variable Form1 sollte dir ebenfalls ein Hinweis sein, daß hier ein Designproblem vorliegt. Denn der Code gehört ja wohl eindeutig in TForm1 rein, da öfters auf Komponenten dieser Form zugegriffen werden, als auf was Anderes. z.B. in eine
Delphi-Quellcode:
-Methode
FügeHinzu(Text1, Text2, Text3, Text4: string)
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
@cookie
Danke, ich habe das mit true und false geändert. Den Code habe ich auch angepasst, doch gibt es ein kleines Problem. Wenn edit1.text nicht dem letzten Eintrag der Listview entspricht kommt die Meldung 'Eintrag bereits vorhanden' und wird aber trotzdem der Listview hinzugefügt mit der erfolgreichen Mitteilung. Wenn edit1.text dem letzten Eintrag entspricht funktioniert es perfekt. @himitsu Durchsuche ich nicht schon am Anfang die Liste? Wie genau soll ich gefunden bzw nicht gefunden auswerten? Mit IndexOf habe ich keinen Ansatz gefunden. Ist das ein Problem, wenn ich es in Form2 lasse, läuft das Programm dann schlechter?
Delphi-Quellcode:
procedure TForm2.Button1Click(Sender: TObject);
var i: integer; begin if RadioButton1.checked then for i := 0 to Form1.Listview1.Items.Count - 1 do if not (form1.ListView1.Items[i].Caption<>edit1.text) then showmessage('Eintrag bereits vorhanden'); if (form1.ListView1.Items[i].Caption<>edit1.text) then begin with form1.listview1.items.add do begin caption:=edit1.text; subitems.add(edit2.text); subitems.add(edit3.text); subitems.add(edit4.text); showmessage('Eintrag wurde hinzugefügt'); end; end; |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Zitat:
Delphi-Quellcode:
if listview1.Items.IndexOf(DeinItem) = -1 then
... Auf so etwas wollte himitsu hinaus. |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Ich komm irgendwie mit deinen Einrückungen nicht klar und find die unübersichtlich, aber mMn fehlt da in der Version ein else-Zweig. Ausserdem ist es doch schöner, gewisse Dinge auszulagern, dann wird der Code übersichtlicher:
Delphi-Quellcode:
procedure TForm2.Button1Click(Sender: TObject);
var i: integer; begin if RadioButton1.checked then begin if EntryExistsInListView(edit1.text,Form1.Listview1) then showmessage('Eintrag bereits vorhanden') else if AddEntryToListView(edit1.text,Form1.Listview1) then showmessage('Eintrag wurde hinzugefügt') else showmessage('Eintrag war nicht vorhanden, konnte aber auch nicht hinzugefügt werden'); end; end; function EntryExistsInListView(entry:String,LW:TListView):Boolean; var i:integer; begin Result:=false; for i := 0 to LW.Count - 1 do if LW.Items[i].Caption=entry then begin Result:=true; Break; end; //Könnte man dann ggf. ersetzen durch: //Result:=LW.Items.IndexOf(entry)>=0; end; function AddEntryToListView(entry:String,LW:TListView):Boolean; begin Result:=true; LW.items.add LW.items[LW.Count-1].caption:=entry; //Muss man noch um diese Subentries aufbohren //und dafür sorgen, dass wenn irgendwas nicht klappt false als Result geliefert wird. end; |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Es ist grober Unfug die ListView für die Dublettenprüfung zu bemühen. Ist aber ein klassischer Anfängerfehler und habe ich zu meinen Anfangszeiten auch so gemacht, also keine falsche Scham.
Wie macht man es also richtig(er)? Zunächst erstellt man sich eine Klasse, die die Daten selber aufnehmen kann
Delphi-Quellcode:
Da ist nichts aufregendes dran.
unit ModelData;
interface type TDataModel = class private FVal1: string; FVal2: string; FVal3: string; FVal4: string; public constructor Create( const AVal1, AVal2, AVal3, AVal4: string ); property Val1: string read FVal1; property Val2: string read FVal2; property Val3: string read FVal3; property Val4: string read FVal4; end; implementation { TDataModel } constructor TDataModel.Create( const AVal1, AVal2, AVal3, AVal4: string ); begin inherited Create; FVal1 := AVal1; FVal2 := AVal2; FVal3 := AVal3; FVal4 := AVal4; end; end. Der Trick ist jetzt die Daten in einer Liste zu verwalten und diese Liste dann in der ListView zu präsentieren (anzeigen). Dadurch brauche ich jetzt nicht mehr die ListView irgendwie abzuklappern und mich auf den Kopf zu stellen, weil für die Anzeige die echten Daten irgendwie aufbereitet wurden, sondern ich vergleiche nur noch mit der einfachen Liste. Das sieht dann z.B. so aus:
Delphi-Quellcode:
P.S. Da du keine Delphi-Version angegeben hast (Beitrag oder Profil) gehe ich davon aus, dass du schon eine neuere Version mit Generics und den Namespaces hast.
unit FormMain;
interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System.Classes, Vcl.Graphics, Vcl.Controls, Vcl.Forms, Vcl.Dialogs, Vcl.StdCtrls, Vcl.ComCtrls, System.Generics.Collections, ModelData; type TForm1 = class( TForm ) ListView1: TListView; Edit1: TEdit; Edit2: TEdit; Edit3: TEdit; Edit4: TEdit; AddButton: TButton; procedure AddButtonClick( Sender: TObject ); private FDataList: TList<TDataModel>; procedure PresentData; public procedure AfterConstruction; override; procedure BeforeDestruction; override; end; var Form1: TForm1; implementation uses System.Generics.Defaults; {$R *.dfm} { TForm1 } procedure TForm1.AddButtonClick( Sender: TObject ); var LItem: TDataModel; begin // Aus den Eingaben eine Daten-Instanz erzeugen LItem := TDataModel.Create( Edit1.Text, Edit2.Text, Edit3.Text, Edit4.Text ); try // Wenn es diese Daten-Instanz mit diesen Werten noch nicht gibt ... // (dank dem Comparer ist das ganz einfach zu prüfen) if not FDataList.Contains( LItem ) then begin // ... dann fügen wir das in die Liste ein FDataList.Add( LItem ); // setzen die Referenz auf NIL (siehe unten) LItem := nil; // präsentieren die neuen Daten PresentData; end; finally // Wenn LItem <> NIL, dann wird die Instanz zerstört LItem.Free; end; end; procedure TForm1.AfterConstruction; begin inherited; FDataList := TObjectList<TDataModel>.Create( // Dieser Vergleicher (Comparer) kann die Daten in der Liste vergleichen // zum Sortieren, aber auch um mit Contains gleiche Instanzen zu finden TComparer<TDataModel>.Construct( function( const L, R: TDataModel ): Integer begin Result := CompareStr( L.Val1, R.Val1 ); if Result = 0 then Result := CompareStr( L.Val2, R.Val2 ); if Result = 0 then Result := CompareStr( L.Val3, R.Val3 ); if Result = 0 then Result := CompareStr( L.Val4, R.Val4 ); end ), True ); end; procedure TForm1.BeforeDestruction; begin inherited; FDataList.Free; end; procedure TForm1.PresentData; var LDataItem: TDataModel; LListItem: TListItem; begin ListView1.Items.BeginUpdate; try // ListView leeren ListView1.Items.Clear; // durch alle Daten-Instanzen laufen for LDataItem in FDataList do begin // und in die ListeView eintragen LListItem := ListView1.Items.Add; LListItem.Caption := LDataItem.Val1; LListItem.SubItems.Add( LDataItem.Val2 ); LListItem.SubItems.Add( LDataItem.Val3 ); LListItem.SubItems.Add( LDataItem.Val4 ); LListItem.Data := LDataItem; end; finally ListView1.Items.EndUpdate; end; end; end. |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Zitat:
Er fragt das Ganze einmal ab in seinem Miniprojekt. Warum sollte man da eine eigene Klasse erstellen und 5x mehr Code produzieren? |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Zitat:
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Zitat:
(lösch mal leere Zeilen aus einem TMemo und mach das ganze mit einem eigenen Thread und Tstrings, das ist ein echter Aha-Effekt) Gruß K-H |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Danke an cookie22, Jumpy, Sir Rufo und p80286
Das mit dem IndexOf hat bei mir nicht funktioniert.. Ich werd versuchen eure Vorschläge zu verstehen, aber das wird ne Weile dauern. Das mit dem Trennen von Daten und visueller Ansicht scheint mir sinnvoll zu sein. Ich werd mich dazu belesen. |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Danke himitsu
Ich habe jetzt die Radiobuttons entfernt und dafür auf der Form1 mehrere Buttons erstellt, das hat einiges vereinfacht. Jetzt hat jede Listview einen eigenen Button fürs Hinzufügen und die Überprüfung funktioniert. Ich muss dann nur noch herausfinden, wie man folgendes schreibt: Wenn edit1.text und edit4.text in der selben Zeile der Listview auftauchen ist vorhanden true.
Delphi-Quellcode:
procedure TForm7.Button1Click(Sender: TObject);
var i: integer; vorhanden: boolean; begin vorhanden:=false; for i := 0 to Form1.Listview2.Items.Count - 1 do if (form1.ListView2.Items[i].Caption=edit1.text) then vorhanden:=true; if vorhanden=true then showmessage('Eintrag ist bereits vorhanden'); if vorhanden=false then begin with form1.listview2.items.add do begin caption:=edit1.text; subitems.add(edit2.text); subitems.add(edit3.text); subitems.add(edit4.text); showmessage('Eintrag wurde hinzugefügt'); end; end; end; |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Ich habs geschafft. ^^
Delphi-Quellcode:
procedure TForm4.Button1Click(Sender: TObject);
var i: integer; vorhanden: boolean; begin vorhanden:=false; for i := 0 to Form1.Listview7.Items.Count - 1 do if (form1.ListView7.Items[i].Caption=edit1.text) and (form1.ListView7.Items[i].subitems[2]=edit4.text)then vorhanden:=true; if vorhanden=true then showmessage('Eintrag ist bereits vorhanden'); if vorhanden=false then begin with form1.listview7.items.add do begin caption:=edit1.text; subitems.add(edit2.text); subitems.add(edit3.text); subitems.add(edit4.text); subitems.add(edit5.text); showmessage('Eintrag wurde hinzugefügt'); end; end; end; |
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Autsch!
Falsch:
Delphi-Quellcode:
if vorhanden=true
richtig:
Delphi-Quellcode:
Die ganze Zwischenvariable ist aber überflüssig. wenn Du die Einfügeaktion in den else Zweig verlegst.
if vorhanden
|
AW: Eintrag nur hinzufügen wenn nicht in Listview vorhanden
Danke mkinzler
Von der Logik her müsste es klappen, aber es funktioniert mit else nicht. Ich bin froh, dass es funktioniert und lass es deshalb so bestehen. |
Alle Zeitangaben in WEZ +1. Es ist jetzt 14:34 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