Suchfunktion

Für alles, was in den übrigen Lazarusthemen keinen Platz, aber mit Lazarus zutun hat.

Suchfunktion

Beitragvon Patrix2911 » 20. Jan 2018, 11:20 Suchfunktion

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 :)
Patrix2911
 
Beiträge: 31
Registriert: 30. Jul 2017, 12:53

Beitragvon Soner » 20. Jan 2018, 16:09 Re: Suchfunktion

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 :)
Soner
 
Beiträge: 411
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Patrix2911 » 20. Jan 2018, 20:19 Re: Suchfunktion

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.
Patrix2911
 
Beiträge: 31
Registriert: 30. Jul 2017, 12:53

Beitragvon Soner » 20. Jan 2018, 21:00 Re: Suchfunktion

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: 411
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Soner » 20. Jan 2018, 21:21 Re: Suchfunktion

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;
 
Soner
 
Beiträge: 411
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Patrix2911 » 20. Jan 2018, 21:31 Re: Suchfunktion

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....
Patrix2911
 
Beiträge: 31
Registriert: 30. Jul 2017, 12:53

Beitragvon Soner » 20. Jan 2018, 22:01 Re: Suchfunktion

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.
Soner
 
Beiträge: 411
Registriert: 26. Sep 2012, 23:07
Wohnort: Hamburg
OS, Lazarus, FPC: Win7Pro-32Bit, Immer letzte Lazarus Release mit SVN-Fixes | 
CPU-Target: 32Bit
Nach oben

Beitragvon Patrix2911 » 20. Jan 2018, 23:54 Re: Suchfunktion

Das ListView wird mit Daten aus einer typisierten Datei gefüllt. Da liegt keine Datenbank dahinter.
Patrix2911
 
Beiträge: 31
Registriert: 30. Jul 2017, 12:53

Beitragvon six1 » 21. Jan 2018, 10:25 Re: Suchfunktion

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
six1
 
Beiträge: 23
Registriert: 1. Jul 2010, 18:01

Beitragvon Patrix2911 » 21. Jan 2018, 13:05 Re: Suchfunktion

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. :)
Patrix2911
 
Beiträge: 31
Registriert: 30. Jul 2017, 12:53

Beitragvon six1 » 21. Jan 2018, 14:56 Re: Suchfunktion

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
six1
 
Beiträge: 23
Registriert: 1. Jul 2010, 18:01

Beitragvon Patrix2911 » 21. Jan 2018, 15:26 Re: Suchfunktion

Hallo Michael.

Vielen Dank, das funktioniert genau so wie ich es brauche!!
Patrix2911
 
Beiträge: 31
Registriert: 30. Jul 2017, 12:53

• Themenende •

Zurück zu Sonstiges



Wer ist online?

Mitglieder in diesem Forum: 0 Mitglieder und 3 Gäste

porpoises-institution
accuracy-worried