Delphi-PRAXiS

Delphi-PRAXiS (https://www.delphipraxis.net/forum.php)
-   Die Delphi-IDE (https://www.delphipraxis.net/62-die-delphi-ide/)
-   -   strings einer combobox vergleichen (https://www.delphipraxis.net/200286-strings-einer-combobox-vergleichen.html)

neroo 6. Apr 2019 14:19

strings einer combobox vergleichen
 
Hallo,

ich möchte hier nachdem ich die Datei eingelesen haben, die erste spalte der Tabelle zu einer combobox hinzufügen.
Dies mache ich mit dem Befehl combobox.items.add(); aber ich möchte hier die mehrmals vorkommenden strings löschen,
sodass ein string nur einmal vorkommt. Leider komme ich hier nicht weiter. ich wäre dankbar für die Hilfe:-D.

Code:
unit Datei;

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
  Buttons, Grids, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    schliess_knopf: TButton;
    einlesen_knopf: TButton;
    s_standortname: TComboBox;
    Label1: TLabel;
    oeffnen_knopf: TButton;
    ende_knopf: TBitBtn;
    fuss: TStatusBar;
    OpenDialog: TOpenDialog;
    etabelle: TStringGrid;
    procedure beenden(Sender: TObject);
    procedure einlesen(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure schliessen(Sender: TObject);
  end;

var Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }

var anzahl: integer;
    datei_name: string;
    datei: textfile;
procedure TForm1.FormShow(Sender: TObject);
begin
  datei_name:='d:\temp\windenergie01.csv';
  with etabelle do
    begin
      Cells[1,0]:='Standort';
      Cells[2,0]:='Windrad';
      Cells[3,0]:='Nennleistung';
      Cells[4,0]:='Datum';
      Cells[5,0]:='Energiemenge';
    end;

  //
end;

procedure TForm1.schliessen(Sender: TObject);
begin
  //
end;

procedure TForm1.beenden(Sender: TObject);
begin
  close;
end;

procedure TForm1.einlesen(Sender: TObject);
var i,posi: integer;
    maxi,wert: double;

    buffer,eintrag,s1,s2,s3,s4,s5: string;
    ok: boolean;
begin
  with opendialog do
    begin
      title:='Windenergie einlesen';
      filename:=datei_name;
      initialdir:=extractfilepath(datei_name);
      filter:='Windenergieergebnisse (*.csv)|*.csv|alle Dateien (*.*)|*.*';
    end;
  if opendialog.execute then
    begin
      datei_name:=opendialog.filename;
      assignfile(datei,datei_name);
      {$I-}
      reset(datei);
      readln(datei);
      i:=0;
      while not(eof(datei)) do
        begin
          inc(i);
          readln(datei,eintrag);
          //Suedkueste,ElCedro2,3.4MW,01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s1:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);
          //ElCedro2,3.4MW,01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s2:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);
          //3.4MW,01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s3:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);
          //01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s4:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);
          //4092kWh
          s5:=eintrag;


          //
          with etabelle do
            begin
              if i>=rowcount then rowcount:=rowcount+1;
              cells[1,i]:=s1;
              cells[2,i]:=s2;
              cells[3,i]:=s3;
              cells[4,i]:=s4;
              cells[5,i]:=s5;
            end;
          //standortname in combobox schreiben
            d1:=s1;
            s_standortname.Items.Add(etabelle.Cells[1,i]);

          //--

          //
        end;
      closefile(datei);
      {$I+}
      ok:=(ioresult=0);
      //--


      //--
    end;

end; //einlesen



end.

H.Bothur 6. Apr 2019 17:21

AW: strings einer combobox vergleichen
 
Moin,

wahrscheinlich gibt es 1000 bessere Lösungen aber wie wäre es damit

Delphi-Quellcode:
 
function NameBereitsVorhanden(const SuchString: String): Boolean;
var
  i: integer;
  gefunden: Boolean;
begin
  gefunden := false;
  for i := 0 to ETabelle.Count -1 do
  begin
    if SuchString := ETabelle:.String[i] then gefunden := true;
  end;
  Result := gefunden
end;

         //
          with etabelle do
            begin
              if i>=rowcount then rowcount:=rowcount+1;
              cells[1,i]:=s1;
              cells[2,i]:=s2;
              cells[3,i]:=s3;
              cells[4,i]:=s4;
              cells[5,i]:=s5;
            end;
          //standortname in combobox schreiben
            d1:=s1;
            if not NameBereitsVorhanden(etabelle.Cells[1,i]) then s_standortname.Items.Add(etabelle.Cells[1,i]);
Das ist Pseudo-Code - also nicht kopieren, aber der Ansatz ist eine Idee :-)

gruß
hans

Delphi.Narium 6. Apr 2019 17:42

AW: strings einer combobox vergleichen
 
Delphi-Quellcode:
          //standortname in combobox schreiben
          d1:=s1;
          if s_standortname.Items.IndexOf(etabelle.Cells[1,i]) < 0 then begin
            s_standortname.Items.Add(etabelle.Cells[1,i]);
          end;

Michael II 6. Apr 2019 17:53

AW: strings einer combobox vergleichen
 
Du schreibst, dass du die Einträge einzeln zu deiner Combobox hinzufügst. In diesem Fall könntest du eine Proc schreiben, welche überprüft, ob neuereintrag bereits in der Liste vorkommt oder nicht:

Delphi-Quellcode:
if combobox.Items.IndexOf( neuereintrag ) < 0 then
  combobox.Items.Add( neuereintrag );

Luckie 6. Apr 2019 18:39

AW: strings einer combobox vergleichen
 
Hat die Combobox nicht sogar eine Eigenschaft, die man nutzen kann, dass sie keine Doubletten beinhaltet?

Michael II 6. Apr 2019 18:56

AW: strings einer combobox vergleichen
 
Kann sein, ich kenn's nur von TStringList - dort über .Duplicates := dupIgnore; aber nur (wieso dem so ist, weiss wohl nicht mal die Firma) wenn die Elemente sortiert sind, also .Sorted := true;

Also etwa so:

Delphi-Quellcode:
  hs := TStringList.Create;
 try
  hs.Sorted := true;
  hs.Duplicates := dupIgnore;
  hs.Text := combobox1.items.Text;
  combobox1.Items.Text := hs.Text;
 finally
  hs.Free;
 end;

Dalai 6. Apr 2019 18:57

AW: strings einer combobox vergleichen
 
Das dachte ich zuerst auch. Sieht aber so aus, als gäbe es da nur TStringList.Duplicates. Da TComboBox.Items aber vom Typ TStrings ist, gibt's da offenbar kein simples Property, um Duplikate zu verhindern. Daher ist die Variante mit TComboBox.Items.IndexOf wohl ein einfacher Workaround. Oder man erweitert TComboBox mit einer Ableitung um eine Methode, die die Existenz eines Strings in der Liste prüft.

Grüße
Dalai

Luckie 6. Apr 2019 19:08

AW: strings einer combobox vergleichen
 
Ah. OK. Ich hatte nur im Hinterkopf, dass da was war.

Warum aber nicht erst alles in eine Stringliste packen und diese dann der Combobox zuweisen?

Delphi.Narium 6. Apr 2019 19:22

AW: strings einer combobox vergleichen
 
Zitat:

Zitat von Luckie (Beitrag 1429682)
Ah. OK. Ich hatte nur im Hinterkopf, dass da was war.

Warum aber nicht erst alles in eine Stringliste packen und diese dann der Combobox zuweisen?

Weil TStringList intern die Methoden nutzt, die es von TStrings geerbt hat.

Man landet also in beiden Fällen zur Suche nach Dubletten bei IndexOf. Dann kann man es auch direkt verwenden ;-)

Bernhard Geyer 6. Apr 2019 19:29

AW: strings einer combobox vergleichen
 
Lade die Liste erst mit dupIgnore in eine TStringsList und kopiere das Ergebnis dann EnBlock in die ComboBox.
Ist auch noch viel schneller als die Strings einzeln in die ComboBox zu bringen.

Michael II 6. Apr 2019 19:48

AW: strings einer combobox vergleichen
 
Zitat:

Warum aber nicht erst alles in eine Stringliste packen und diese dann der Combobox zuweisen?
Zitat:

Lade die Liste erst mit dupIgnore in eine TStringsList und kopiere das Ergebnis dann EnBlock in die ComboBox.
Ist auch noch viel schneller als die Strings einzeln in die ComboBox zu bringen.
In #6 ja bereits so gepostet. Der Ansatz macht aber nur Sinn, wenn die Combobox Elemente sortiert sein dürfen, da dupIgnore nur bei sortierten Listen Wirkung zeigt...

dummzeuch 6. Apr 2019 19:56

AW: strings einer combobox vergleichen
 
Zitat:

Zitat von Michael II (Beitrag 1429687)
In #6 ja bereits so gepostet. Der Ansatz macht aber nur Sinn, wenn die Combobox Elemente sortiert sein dürfen, da dupIgnore nur bei sortierten Listen Wirkung zeigt...

Es macht auch Sinn, wenn sie nicht sortiert sein sollen, dann muss man halt mit IndexOf arbeiten. Es ist trotzdem deutlich schneller, weil keine Windows-Messages in der Gegend rumgeschickt werden.

Man kann auch mit zwei Stringlists arbeiten: Einer sortierten und einer unsortierten. Insert liefert -1 zurück, wenn der String beim Einfügen in eine sortierte Stringlist bereits existierte. In dem Fall fügt man ihn nicht in die unsoriterte ein.

Und noch ein Hinweis zum Code in #6: Statt Text zuzuweisen kann man auch gleich die StringList auf Items zuweisen.

Delphi-Quellcode:
combobox1.Items := Text;

Luckie 6. Apr 2019 20:05

AW: strings einer combobox vergleichen
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1429685)
Lade die Liste erst mit dupIgnore in eine TStringsList und kopiere das Ergebnis dann EnBlock in die ComboBox.
Ist auch noch viel schneller als die Strings einzeln in die ComboBox zu bringen.

Genau das habe ich doch vorgeschlagen!

Bernhard Geyer 6. Apr 2019 20:26

AW: strings einer combobox vergleichen
 
Zitat:

Zitat von Luckie (Beitrag 1429692)
Zitat:

Zitat von Bernhard Geyer (Beitrag 1429685)
Lade die Liste erst mit dupIgnore in eine TStringsList und kopiere das Ergebnis dann EnBlock in die ComboBox.
Ist auch noch viel schneller als die Strings einzeln in die ComboBox zu bringen.

Genau das habe ich doch vorgeschlagen!

Deinen zweiten Post habe ich übersehen :oops:

neroo 7. Apr 2019 12:57

AW: strings einer combobox vergleichen
 
Zitat:

Zitat von Bernhard Geyer (Beitrag 1429685)
Lade die Liste erst mit dupIgnore in eine TStringsList und kopiere das Ergebnis dann EnBlock in die ComboBox.
Ist auch noch viel schneller als die Strings einzeln in die ComboBox zu bringen.

Danke für eure Antworten

wie kann man die strings in der liste aufaddieren? denn die Liste läuft innerhalb einer while schleife und deshalb wird nur der letzte Eintrag zu der liste hinzugefügt.
Code:
stringlist:=TStringList.Create;
            stringlist.Sorted:=true;
            stringlist.Duplicates:=dupIgnore;
            with stringlist do
               begin
               add(etabelle.cells[1,i]);
               end;

            with ListBox1 do
              begin
              items.Assign(stringlist);
              end;

            stringlist.free;

Luckie 7. Apr 2019 13:18

AW: strings einer combobox vergleichen
 
Wo ist da eine while-Schleife in deinem Code?

Code:
StringListe erzeugen
StringListe Eigenschaften setzen
while()
begin
  StringListe.Add();
end;
StringListe Combobox zuweisen
StringListe freigeben
Und lass das with-do bitte weg. Es erschwert das Debuggen und führt schnell zu schwer zufindeden Fehlern.

neroo 7. Apr 2019 13:28

AW: strings einer combobox vergleichen
 
Zitat:

Zitat von Luckie (Beitrag 1429745)
Wo ist da eine while-Schleife in deinem Code?

Code:
StringListe erzeugen
StringListe Eigenschaften setzen
while()
begin
  StringListe.Add();
end;
StringListe Combobox zuweisen
StringListe freigeben
Und lass das with-do bitte weg. Es erschwert das Debuggen und führt schnell zu schwer zufindeden Fehlern.

Code:
unit klausur011; //21.03.2019

{$mode objfpc}{$H+}

interface

uses
  Classes, SysUtils, FileUtil, Forms, Controls, Graphics, Dialogs, ComCtrls,
  Buttons, Grids, StdCtrls;

type

  { TForm1 }

  TForm1 = class(TForm)
    ComboBox1: TComboBox;
    Label4: TLabel;
    Label5: TLabel;
    Label6: TLabel;
    ListBox1: TListBox;
    M_menge: TLabel;
    Label2: TLabel;
    K_menge: TLabel;
    Label3: TLabel;
    sanzahl: TLabel;
    schliess_knopf: TButton;
    einlesen_knopf: TButton;
    Label1: TLabel;
    oeffnen_knopf: TButton;
    ende_knopf: TBitBtn;
    fuss: TStatusBar;
    OpenDialog: TOpenDialog;
    etabelle: TStringGrid;
    procedure beenden(Sender: TObject);
    procedure einlesen(Sender: TObject);
    procedure FormShow(Sender: TObject);
    procedure schliessen(Sender: TObject);
  end;

var Form1: TForm1;

implementation

{$R *.lfm}

{ TForm1 }
Type TFeld= array [0..1000] of string;
var k:integer;
    datei_name: string;
    datei: textfile;
    element:TFeld;

procedure TForm1.FormShow(Sender: TObject);
begin
  datei_name:='d:\temp\windenergie01.csv';
  with etabelle do
    begin
      Cells[1,0]:='Standort';
      Cells[2,0]:='Windrad';
      Cells[3,0]:='Nennleistung';
      Cells[4,0]:='Datum';
      Cells[5,0]:='Energiemenge';
    end;

  //
end;

procedure TForm1.schliessen(Sender: TObject);
begin
  //
end;

procedure TForm1.beenden(Sender: TObject);
begin
  close;
end;

procedure TForm1.einlesen(Sender: TObject);
var i,posi,anzahl: integer;
    wert,menge: double;
    buffer,eintrag,s1,s2,s3,s4,s5,s6,d1: string; stringlist:TStringList;
    ok:boolean;
begin
  with opendialog do
    begin
      title:='Windenergie einlesen';
      filename:=datei_name;
      initialdir:=extractfilepath(datei_name);
      filter:='Windenergieergebnisse (*.csv)|*.csv|alle Dateien (*.*)|*.*';
    end;
  //-------------------------------------------------------------------------------
  if opendialog.execute then
    begin

      datei_name:=opendialog.filename;
      assignfile(datei,datei_name);
      {$I-}
      reset(datei);
      readln(datei);
      i:=0; menge:=0.0;  anzahl:=0;

      while not(eof(datei)) do
        begin
          inc(i);
          readln(datei,eintrag);
          //Suedkueste,ElCedro2,3.4MW,01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s1:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);


          //ElCedro2,3.4MW,01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s2:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);
          //3.4MW,01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s3:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);
          //01.02.2017,4092kWh
          posi:=pos(',',eintrag);
          s4:=copy(eintrag,1,posi-1);
          delete(eintrag,1,posi);
          //4092kWh
          s5:=eintrag;
          //Energiemenge berechnen in kWh
          posi:=Pos('k',s5);
          s6:=Copy(s5,1,posi-1);
          menge:=menge+strtofloat(s6);
          K_menge.Caption:=Floattostr(menge);
          //Energie menge in nWh
          wert:=menge/1000;
          M_menge.caption:=Floattostr(wert);
          //Tabellenausgabe
          with etabelle do
            begin
              if i>=rowcount then rowcount:=rowcount+1;
              cells[0,i]:=inttostr(i);
              cells[1,i]:=s1; element[i]:=s1; // in feld speichern
              cells[2,i]:=s2;
              cells[3,i]:=s3;
              cells[4,i]:=s4;
              cells[5,i]:=s5;
            end; //etabelle

            //standortname in combobox schreiben
            stringlist:=TStringList.Create;
            //stringlist.Sorted:=true;
            //stringlist.Duplicates:=dupIgnore;
            with stringlist do
              begin
               for i:=1 to anzahl do
               Add(element[i]);
              end;


            with combobox1 do
              begin
              Assign(stringlist);
              end;

            stringlist.free;

            //zeilenanzahl ermitteln
            inc(anzahl);
            sanzahl.caption:=inttostr(anzahl);


          //-----------------------

          fuss.Panels[0].Text:=datei_name;
          closefile(datei);

      {$I+}

        end; // hier ist die while schleife

      ok:=(ioresult=0);

end; //opendlg
end; // begin block

end.

Luckie 7. Apr 2019 13:55

AW: strings einer combobox vergleichen
 
Du erzeugst die StringListe ja jedes mal neu in der Schleife, wenn ich das richtig gesehen habe. Das kann ja nicht funktionieren, wie gewollt. Einmal vor der Schleife erzeugen und dann füllen.

Noch ein Tipp: Zerleg die Ellen lange Prozedur in mehrere kleinere. Das macht den Code übersichtlicher und leichter verständlich.

neroo 7. Apr 2019 14:32

AW: strings einer combobox vergleichen
 
Zitat:

Zitat von Luckie (Beitrag 1429749)
Du erzeugst die StringListe ja jedes mal neu in der Schleife, wenn ich das richtig gesehen habe. Das kann ja nicht funktionieren, wie gewollt. Einmal vor der Schleife erzeugen und dann füllen.

Noch ein Tipp: Zerleg die Ellen lange Prozedur in mehrere kleinere. Das macht den Code übersichtlicher und leichter verständlich.

Ich habs gemacht und es funktioniert jetzt. gibt es jetzt eine Eigenschaft, die die Stringgrid Tabelle mit der Combobox verbindet, sodass wenn man auf einen Eintrag in der Combobox klickt, werden nur die entsprechenden Einträge von der Tabelle
angezeigt.

Luckie 7. Apr 2019 14:34

AW: strings einer combobox vergleichen
 
Das wirst du selber programmieren müssen, indem du nach dem gewählten Eintrag der Combobox im Stringgrid suchst. Alle Zeilen durch gehen und mit pos vergleichen.

neroo 7. Apr 2019 14:38

AW: strings einer combobox vergleichen
 
es hört sich schwer an :?

Luckie 7. Apr 2019 14:48

AW: strings einer combobox vergleichen
 
Nö. Soll nur in einer Spalte gesucht werden musst du ja nur die Zeilen durchgehen, dir den Inhalt der Spalte holen und mit dem gewählten Eintrag vergleichen. Wenn identisch, hast du die Zeile im StringGrid gefunden.

Soll in jeder Spalte gesucht werden, wird es etwas komplizierter, da du dann zwei verschachtelte Schleifen brauchst: Eine für die Zeilen und darin eine für die Spalten.

Setz erst mal die erste Anforderung um: Der gesuchte Inhalt ist immer in der ersten Spalte.

Code:
SuchString := Combobox ausgewählt
for i := 0 to ZeilenStringGrid - 1 do
begin
  sgString := Zeile[i,0] // oder so ähnlich. Habe jetzt die Syntax nicht im Kopf
  if SuchString = sgString // gefunden
  begin
    Zeile im StringGrid hervorheben
    break;
end;


Alle Zeitangaben in WEZ +1. Es ist jetzt 05:34 Uhr.

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