Suchfunktion

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.
Antworten
Patrix2911
Beiträge: 32
Registriert: So 30. Jul 2017, 13:53

Suchfunktion

Beitrag von Patrix2911 »

Hallo, folgendes Szenario:

Ich habe ein Listview, jedes Item hat 1 SubItem. Außerdem habe ich ein Editfeld.

Ich möchte nun, das bei einer Eingabe im Editfeld das komplette ListView durchsucht wird und Dabei das Item bei dem jedes Wort aus dem Editfeld im SubItem vorkommt in einer Variable hinterlegt wird ...

Beispiel: ListView

Code: Alles auswählen

 
44687651   11380 XL apple green
12389712   502EG - forrest green
93847573   11380 L deep black
 


Ich hatte dafür folgenden Code ....

Code: Alles auswählen

 
var Bestand: Double;
    Ts     : TStrings;
    S,S2   : String;
    I,I2   : LongInt;
    Fnd    : Integer;
begin
 If Pos(' ',Form1.Barcode.Text) = 0 then DbItem := Form1.BarCode.Text
                                    else
  Begin
   TS := TStringlist.Create;
   S := Form1.BarCode.Text;
   While Pos(' ',S) > 0 do
    Begin
     S2 := Copy(S,1,Pos(' ',S)-1);
     Delete(S,1,Pos(' ',S));
     TS.Add(UpperCase(S2));
    end;
   If length(S) > 0 then TS.Add(S);
 
   For I := 0 to Form1.ArtikelView.Items.Count-1 do
    Begin
     Fnd := 0;
     For I2 := 0 to TS.Count-1 do
      Begin
       If (I2 = 0) or (I2 = TS.Count) then
        Begin
         If Pos(Ts[I2],UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        end;
       If (I2 > 0) and (I2 < TS.Count) then
        Begin
         If Pos(Ts[I2]+' ',UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        end;
      end;
     If Fnd = Ts.Count then
      Begin
       DbItem := Form1.ArtikelView.Items[i].Caption;
       Break;
      end;
    end;
   TS.Free;
  end;
 


Das funktioniert leider nicht 100%ig so wie ich es mir denke. Suche ich z.B. "11380 L black" ... bleibt die Suche beim Item "11380 XL apple green" stehen ... hat jemand ne bessere Lösung?

Vorab danke für eure Hilfe :)

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Suchfunktion

Beitrag von Soner »

Es sieht so aus, als ob es nie etwas gefunden wird. Erste Zeile war markiert und bleibt markiert.
Versuchmal den zweiten Auszukommentieren:
Patrix2911 hat geschrieben:Hallo, folgendes Szenario:

Ich habe ein Listview, jedes Item hat 1 SubItem. Außerdem habe ich ein Editfeld.

Ich möchte nun, das bei einer Eingabe im Editfeld das komplette ListView durchsucht wird und Dabei das Item bei dem jedes Wort aus dem Editfeld im SubItem vorkommt in einer Variable hinterlegt wird ...

Beispiel: ListView

Code: Alles auswählen

 
44687651   11380 XL apple green
12389712   502EG - forrest green
93847573   11380 L deep black
 


Ich hatte dafür folgenden Code ....

Code: Alles auswählen

 
var Bestand: Double;
    Ts     : TStrings;
    S,S2   : String;
    I,I2   : LongInt;
    Fnd    : Integer;
begin
 If Pos(' ',Form1.Barcode.Text) = 0 then DbItem := Form1.BarCode.Text
                                    else
  Begin
   TS := TStringlist.Create;
   S := Form1.BarCode.Text;
   While Pos(' ',S) > 0 do
    Begin
     S2 := Copy(S,1,Pos(' ',S)-1);
     Delete(S,1,Pos(' ',S));
     TS.Add(UpperCase(S2));
    end;
   If length(S) > 0 then TS.Add(S);
 
   For I := 0 to Form1.ArtikelView.Items.Count-1 do
    Begin
     Fnd := 0;
     For I2 := 0 to TS.Count-1 do
      Begin
       If (I2 = 0) or (I2 = TS.Count) then
        Begin
         If Pos(Ts[I2],UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        end;
{ Was soll das?
 z.B. für 11380 L wird die Variable  Fnd auf 5 erhöht, dann wird untere block nie ausgeführt
       If (I2 > 0) and (I2 < TS.Count) then
        Begin
         If Pos(Ts[I2]+' ',UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
       end;
}

      end;
     If Fnd = Ts.Count then
      Begin
       DbItem := Form1.ArtikelView.Items[i].Caption;
       Break;
      end;
    end;
   TS.Free;
  end;
 


Das funktioniert leider nicht 100%ig so wie ich es mir denke. Suche ich z.B. "11380 L black" ... bleibt die Suche beim Item "11380 XL apple green" stehen ... hat jemand ne bessere Lösung?

Vorab danke für eure Hilfe :)

Patrix2911
Beiträge: 32
Registriert: So 30. Jul 2017, 13:53

Re: Suchfunktion

Beitrag von Patrix2911 »

Ich kann Dir leider nicht ganz folgen?

Also es wird schon etwas gefunden, folgendes Szenario. Suche ich nach "11380 L black" wird der Eintrag mit "11380 L apple green" gefunden.

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Suchfunktion

Beitrag von Soner »

Ich habe sogar weniger auskommentiert, mit dein Kode wird ""11380 XL apple green" nie gefunden. Spielen wir den debugger:

Code: Alles auswählen

 
  //wir laufen nur eine zeile und zwar für:  11380 XL apple green
     Fnd := 0;
     I2=0;
      Begin
       If (I2 = 0) or (I2 = TS.Count) then //eswird nach 11380 gesucht und gefunden
        Begin
         If Pos(Ts[I2],UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        end;
 
      //jetzt ist Fnd :=1 weil oben erhöht
 
     //jetzt ist es 2.lauf loop I2=1
 
     //jetzt wird nach 'L' gesucht
 
       If (I2 > 0) and (I2 < TS.Count) then // >>>> l wird gefunden durch diese "Schummelleife"
        Begin
         If Pos(Ts[I2]+' ',UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        end;
      end;
 
     //jetzt ist es 3.lauf loop I2=1
 
     //jetzt ist Fnd :=2 weil oben erhöht
 
     //jetzt wird nach 'black' gesucht, weil I2 < TS.Count ist,  wird dieser Vergleich ausgeführt:
 
       If (I2 > 0) and (I2 < TS.Count) then
        Begin
         // nicht treffer weil black gibt es nicht in der 1. Zeile
         If Pos(Ts[I2]+' ',UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        end;
      end;
 
 
    //Fnd  =2  also es wird nie gefunden!
     If Fnd = Ts.Count then
      Begin
       DbItem := Form1.ArtikelView.Items[i].Caption;
       Break;
      end;
    end;
 


Versuch das:

Code: Alles auswählen

 
var Bestand: Double;
    Ts     : TStrings;
    S,S2   : String;
    I,I2   : LongInt;
    Fnd    : Integer;
begin
 If Pos(' ',Form1.Barcode.Text) = 0 then DbItem := Form1.BarCode.Text
                                    else
  Begin
   TS := TStringlist.Create;
   S := Form1.BarCode.Text;
   While Pos(' ',S) > 0 do
    Begin
     S2 := Copy(S,1,Pos(' ',S)-1);
     Delete(S,1,Pos(' ',S));
     TS.Add(UpperCase(S2));
    end;
   If length(S) > 0 then TS.Add(S);
 
   For I := 0 to Form1.ArtikelView.Items.Count-1 do
    Begin
     Fnd := 0;
     For I2 := 0 to TS.Count-1 do
      Begin
       //If (I2 = 0) or (I2 = TS.Count) then
        //Begin
         If Pos(Ts[I2],UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        //end;
       {If (I2 > 0) and (I2 < TS.Count) then
        Begin
         If Pos(Ts[I2]+' ',UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
        end;}

      end;
     If Fnd = Ts.Count then
      Begin
       DbItem := Form1.ArtikelView.Items[i].Caption;
       Break;
      end;
    end;
   TS.Free;
  end;
 

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Suchfunktion

Beitrag von Soner »

ich habe es nachgebaut so funktioniert es richtig.
(mein Beispiel konnte ich wegen Forumfehler nicht hochladen)

Code: Alles auswählen

 
var Bestand: Double;
    Ts     : TStrings;
    S,S2   : String;
    I,I2   : LongInt;
    Fnd    : Integer;
begin
 //Wieso wird bei nur ein Suchword nicht gesucht?
 //wenn du das willst kommentiere die nächsten Zeilen aus!
 If Pos(' ',Form1.Barcode.Text) = 0 then DbItem := Form1.BarCode.Text
                                    else
  Begin
   TS := TStringlist.Create;
   S := Form1.BarCode.Text   
    +' ' //sonst wird lezte text nicht kopiert
    ;
   While Pos(' ',S) > 0 do
    Begin
     S2 := Copy(S,1,Pos(' ',S)-1);
     Delete(S,1,Pos(' ',S));
     TS.Add(UpperCase(S2));
    end;
   If length(S) > 0 then TS.Add(S);
 
   For I := 0 to Form1.ArtikelView.Items.Count-1 do
    Begin
     Fnd := 0;
     For I2 := 0 to TS.Count-1 do
      Begin
         If Pos(Ts[I2],UpperCase(Form1.ArtikelView.Items[I].SubItems[0])) > 0 then Fnd := Fnd + 1;
      end;
     If Fnd = Ts.Count then
      Begin
       DbItem := Form1.ArtikelView.Items[i].Caption;
       Break;
      end;
    end;
   TS.Free;
  end;
 

Patrix2911
Beiträge: 32
Registriert: So 30. Jul 2017, 13:53

Re: Suchfunktion

Beitrag von Patrix2911 »

Danke für deine Mühe, das hatte ich schon mal ... leider gibt es hier das Problem

Bild

Hier wird ein falscher Artikel weil das "L" natürlich auch im Wort "black" vorkommt....

Soner
Beiträge: 623
Registriert: Do 27. Sep 2012, 00:07
OS, Lazarus, FPC: Win10Pro-64Bit, Immer letzte Lazarus Release mit SVN-Fixes
CPU-Target: x86_64-win64
Wohnort: Hamburg

Re: Suchfunktion

Beitrag von Soner »

Dein Fehler ist, dass du Pos verwendest, diesen Teil muss du auch selber machen.

Wenn das eine DB-Anwendung ist und du Artikelsuchfunktion für den Benutzer erstellst, dann ist dein Vorgehen komplett falsch.
1. Man läßt die Suche der DB-System, das Läuft bei DB-System sehr schnell, weil die dafür extra Funktionen und Eigenschaften haben. z.B. Indices.
2. Mann liefert nicht nur ein Ergebnis, man liefert alle passende Ergebnisse und der Benutzer verfeinert, seine Suche weiter.

Viel Glück.

Patrix2911
Beiträge: 32
Registriert: So 30. Jul 2017, 13:53

Re: Suchfunktion

Beitrag von Patrix2911 »

Das ListView wird mit Daten aus einer typisierten Datei gefüllt. Da liegt keine Datenbank dahinter.

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Suchfunktion

Beitrag von six1 »

Hi,
habe es abgeändert, ist aber ungetestet.

Code: Alles auswählen

var Bestand: Double;
    Ts     : TStrings;
    S,S2   : String;
    I,I2   : LongInt;
    Fnd    : Integer;
begin
 If Pos(' ',Form1.Barcode.Text) = 0 then
  DbItem := Form1.BarCode.Text;
 else
  Begin
   TS := TStringlist.Create;
   S := uppercase(trim(Form1.BarCode.Text));
   s:=Stringreplace(s,'  ',' ',[rfreplaceall]);
   s:=Stringreplace(s,' ','|',[rfreplaceall]);
   TS.StrictDelimiter:=true;
   TS.Delimiter:='|';
   TS.DelimitedText:=S;
   If length(S) > 0 then TS.Add(S);
 
   For I := 0 to Form1.ArtikelView.Items.Count-1 do
    Begin
     Fnd := 0;
     For I2 := 0 to TS.Count-1 do
      Begin
        S:=UpperCase(trim(Form1.ArtikelView.Items[I].SubItems[0]));
        s:=Stringreplace(s,'  ',' ',[rfreplaceall]);
        s:=Stringreplace(s,' ','|',[rfreplaceall]);
        s:='|'+s+'|';
        If Pos('|'+Ts[I2]+'|',S) > 0 then Fnd := Fnd + 1;
      end;
     If Fnd = Ts.Count then
      Begin
       DbItem := Form1.ArtikelView.Items[i].Caption;
       Break;
      end;
    end;
   TS.Free;
  end;
end


Gruß, Michael
Gruß, Michael

Patrix2911
Beiträge: 32
Registriert: So 30. Jul 2017, 13:53

Re: Suchfunktion

Beitrag von Patrix2911 »

Hallo Michael,

vielen Dank für deine Mühe. Deine Variante klappt, wenn der Text in SubItem[0] = BarCode.Text ist. Das Problem an der Sache ist das ich eine Lösung suche, die SubItem[0] nach allen Vorkommnissen aus BarCode.Text überprüft.

Beispiel:

SubItem[0] ist "11380 l deep black"
BarCode.Text ist "black 11380 l" ... Alle Elemente sind in SubItem[0]
BarCode.Text ist "11380 l black" ... Alle Elemente sind in SubItem[0]
BarCode.Text ist "11380 black l" ... Alle Elemente sind in SubItem[0]
BarCode.Text ist "black 11380 xl" ... Elemente fehlen ... kein Treffer ...

Hast Du dafür vllt. eine Lösung?

Danke & einen schönen Sonntag wünsche ich. :)

Benutzeravatar
six1
Beiträge: 782
Registriert: Do 1. Jul 2010, 19:01

Re: Suchfunktion

Beitrag von six1 »

Hi,
ich habe es nun doch schnell durch den Compiler jagen müssen :)

Code: Alles auswählen

 
var Bestand: Double;
    Ts     : TStrings;
    S,S2   : String;
    I,I2   : LongInt;
    Fnd    : Integer;
begin
 Memo1.lines.clear;
 If Pos(' ',Form1.Barcode.Text) = 0 then begin
  Memo1.lines.add( Form1.BarCode.Text);
 end else Begin
   TS := TStringlist.Create;
   S := uppercase(trim(Form1.BarCode.Text));
   s:=Stringreplace(s,'  ',' ',[rfreplaceall]);
   s:=Stringreplace(s,' ','|',[rfreplaceall]);
   TS.StrictDelimiter:=true;
   TS.Delimiter:='|';
   TS.DelimitedText:=S;
 
   For I := 0 to Form1.ArtikelView.Items.Count-1 do
    Begin
     Fnd := 0;
     S:=UpperCase(trim(Form1.ArtikelView.Items[I].SubItems[0]));
     s:=Stringreplace(s,'  ',' ',[rfreplaceall]);
     s:=Stringreplace(s,' ','|',[rfreplaceall]);
     s:='|'+s+'|';
     For I2 := 0 to TS.Count-1 do
      Begin
        If Pos('|'+Ts[I2]+'|',S) > 0 then
          Fnd := Fnd + 1
        else
          break;
      end;
     If Fnd = Ts.Count then
      Begin
       Memo1.lines.add( Form1.ArtikelView.Items[i].Caption);
      end;
    end;
   TS.Free;
  end;
end;                                         
 


Die Ausgabe habe ich in Memo1.lines umgeleitet, musst du deine Zeilen wieder einfügen..

Gruß, Michael
Gruß, Michael

Patrix2911
Beiträge: 32
Registriert: So 30. Jul 2017, 13:53

Re: Suchfunktion

Beitrag von Patrix2911 »

Hallo Michael.

Vielen Dank, das funktioniert genau so wie ich es brauche!!

Antworten