Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2007.05.27;
Скачать: [xml.tar.bz2];

Вниз

Поиск в ListBox   Найти похожие ветки 

 
kodov   (2007-03-19 16:22) [0]

Здравствуйте!
Помогите пожалуйста разобраться с проблемой.
Есть код:
var
i: integer;
flag: boolean;
begin
if personslist.Items.Count=0 then
begin
showmessage("There are no elements to find");
mainform.Show;
end
else if edit1.Text="" then begin
showmessage("Enter something to find");
mainform.Show;
end;
i:=0;
flag:=false;
repeat
if Pos(LowerCase(Edit1.Text),LowerCase(personslist.Items.Strings[i]))<>0 then
begin
personslist.Selected[i]:=true;
n:=i;
flag:=true;
end;
inc(i);
until (i=personslist.Count-1) or (flag=true);
end;
Этот код работает, но когда в списке более 300 элементов,то
поиск подглючивает. Он никак не хочет находить последние несколько элементов.
Заранее спасибо.


 
Степан   (2007-03-19 16:35) [1]

Можно попробовать заменить:

personslist.Count на personslist.Items.Count
personslist.Items.Strings[i] на personslist.Items[i]

а так вроде все правильно... вроде :)


 
Elen ©   (2007-03-19 16:36) [2]

Наверное тебе мешает  or (flag=true). Задача какая? отселектировать найденное? или найти первое попавшееся?


 
RASkov   (2007-03-19 16:37) [3]

> [0] kodov   (19.03.07 16:22)

ListBox.ItemIndex := ListBox.Perform(LB_FINDSTRING, -1, LongInt(PChar(Edit1.Text)));


 
Knight ©   (2007-03-19 17:48) [4]

Фих знает... Вроде ищет всё..

var
 i: integer;
 flag: boolean;
begin
 i:=0;
 flag:=False;
 if personslist.Items.Count=0 then begin
   showmessage("There are no elements to find");
   mainform.Show;
 end else if edit1.Text="" then begin
   showmessage("Enter something to find");
   mainform.Show;
 end else begin
   while (i<personslist.Count) and not flag do begin
     flag:=Pos(LowerCase(Edit1.Text),LowerCase(personslist.Items.Strings[i]))<>0;
     if flag then begin
       n:=i;
       personslist.Selected[i]:=true;
     end else inc(i);
   end;
 end;


 
kodov   (2007-03-19 20:29) [5]

Мне нужно найти первое попавшееся.
И мне нужно частичное совпадение.


 
Knight ©   (2007-03-19 21:04) [6]

Так и что? Вариант не идеальный, но работает и при количестве строк больше тысячи&#133


 
RASkov   (2007-03-19 21:47) [7]

> [4] Knight ©   (19.03.07 17:48)

Не верно будет работать с русским текстом. Т.е. твой вариант не найдет - если в Edit1.Text будет = "строка", а в ListBox"е Item со значением = "Строка" или "стРока"....
Не работает LowerCase для русских символов (D7)....

> [5] kodov   (19.03.07 20:29)

Попробуй [3]...


 
Knight ©   (2007-03-19 21:57) [8]

> [7] RASkov   (19.03.07 21:47)
> Не работает LowerCase для русских символов (D7)&#133

Просто не читая скопировал с варианта автора ветки&#133 Надо туда Ansi добавить.


 
RASkov   (2007-03-19 22:16) [9]

> [8] Knight ©   (19.03.07 21:57)

И "твой" вариант работает медленнее :) для сравнения:
Это, по больше части, для автора вопроса...

procedure TForm1.Button1Click(Sender: TObject);
var N: Integer;
begin
 ListBox1.Items.BeginUpdate; Screen.Cursor:=crHourGlass;
 ListBox1.Items.Add("Строка");
 for N := 0 to 50000 do ListBox1.Items.Insert(0, IntToStr(N));
 ListBox1.Items.EndUpdate; Screen.Cursor:=crDefault;
end;

procedure TForm1.Button2Click(Sender: TObject);
begin
 ListBox1.ItemIndex := ListBox1.Perform(LB_FINDSTRING, -1, LongInt(PChar(Edit1.Text)));
end;

procedure TForm1.Button3Click(Sender: TObject);
var
i: integer;
flag: boolean;
begin
i:=0;
flag:=False;
if ListBox1.Items.Count=0 then begin
  showmessage("There are no elements to find");
  Exit;
end else if edit1.Text="" then begin
  showmessage("Enter something to find");
  Edit1.SetFocus;
end else begin
*   while (i < ListBox1.Count) and not flag do begin
*     flag:=Pos(LowerCase(Edit1.Text), LowerCase(ListBox1.Items.Strings[i])) <> 0;
*     if flag then begin
*       ListBox1.Selected[i]:=true;
*     end else inc(i);
*   end;
end;
end;


Кстати можно заменить часть кода на это:
....
end else begin
  while (i<ListBox1.Count) and (Pos(LowerCase(Edit1.Text), LowerCase(ListBox1.Items.Strings[i]))=0) do INC(i);
  ListBox1.ItemIndex:=i;
end;


 
Knight ©   (2007-03-19 22:55) [10]

Зато у меня ищёт и ищет правильно&#133 а у тебя не ищет. Точнее твоя команда работает по принципу List1.Items.IndexOf(Edit1.Text)
А в
end else begin
 while (i<ListBox1.Count) and (Pos(LowerCase(Edit1.Text), LowerCase(ListBox1.Items.Strings[i]))=0) do INC(i);
 ListBox1.ItemIndex:=i;
end;

будет ошибка если ничего не найдёно, т.к. i вылетит за пределы списка.


var i: integer;
begin
i:=0;
if PersonsList.Items.Count=0 then ShowMessage("There are no elements to find")
else if Edit1.Text="" then ShowMessage("Enter something to find")
else while (i<PersonsList.Items.Count) and (Pos(AnsiLowerCase(Edit1.Text),AnsiLowerCase(PersonsList.Items[i]))=0) do Inc(i);
if i<PersonsList.Items.Count then PersonsList.ItemIndex:=i
else MainForm.Show;
end;


 
RASkov   (2007-03-20 02:04) [11]

> [10] Knight ©   (19.03.07 22:55)

> Точнее твоя команда работает по принципу List1.Items.IndexOf(Edit1.Text)

function TStrings.IndexOf(const S: string): Integer;
begin
 for Result := 0 to GetCount - 1 do
   if CompareStrings(Get(Result), S) = 0 then Exit;
 Result := -1;
end;

Ничего похожего.... Даже больше на ваш код похоже.

> а у тебя не ищет

А ты пробовал? :)

> будет ошибка если ничего не найдёно, т.к. i вылетит за пределы списка.

Ничего подобного... Сам попробуй ListBox1.ItemIndex:=ListBox1.Count+10;
(D7, WinXP SP2) на всяк....


 
RASkov   (2007-03-20 02:07) [12]

> Точнее твоя команда работает по принципу List1.Items.IndexOf(Edit1.Text)

Сорри... понял.
Моя штука не ищет вхождение, только сначала строки...


 
kodov   (2007-03-20 19:06) [13]

Спасибо за ответы, попробую.


 
kodov   (2007-03-20 19:27) [14]

Только что попробовал варианты, RASkov, ваш поиск действительно работает лучше моего.
Есть еще один вопрос, вот код для кнопки Найти далее.

var
i : integer;
begin
for i:=n+1 to personslist.Count-1 do
begin
if Pos(LowerCase(Edit1.Text),LowerCase(personslist.Items.Strings[i]))<>0 then
begin
personslist.Selected[i]:=true;
editbtn.Click;
n:=i;
break;
end;
end;
Проблема в том, что у меня стоит строка "Fortecstar LiFetime",
при нажатии кнопки Найти, поиск её находит, а затем где-то через 7 строк,
стоит строка "Fortecstar FTA LiFetime". Так вот, при нажатии кнопки Найти далее, поиск ни фига не хочет находить следующую строку.
Какие будут соображения по этому поводу?
Заранее благодарен.


 
RASkov   (2007-03-20 19:33) [15]

> [14] kodov   (20.03.07 19:27)

Если тебе подошел мой вариант(поиск с начала строки) то попробуй вот это:

procedure TForm1.Button2Click(Sender: TObject);
begin
with ListBox do
 ItemIndex := ListBox.Perform(LB_FINDSTRING, ItemIndex, LongInt(PChar(Edit1.Text)));
end;

Но это не ищет вхождение строки, а только с начала....


 
RASkov   (2007-03-20 19:34) [16]

with ListBox do
ItemIndex := Perform(LB_FINDSTRING, ItemIndex, LongInt(PChar(Edit1.Text)));


 
RASkov   (2007-03-20 21:24) [17]

Или примерно так:
procedure TForm1.Button2Click(Sender: TObject);
var S: String; N: Integer;
begin
 {Тут всякие проверки на верность personslist.Count, Edit1.Text=""....}
 S := AnsiLowerCase(Edit1.Text); //или лучше Edit1.CharCase = eclowerCase - (все немного быстрее будет)
 if personslist.Tag = -1 then personslist.ItemIndex := -1;
 personslist.Tag := personslist.ItemIndex + 1;
 for N := personslist.Tag to personslist.Count - 1 do
  if Pos(S, AnsiLowerCase(personslist.Items[N])) > 0 then begin
   personslist.ItemIndex := N;
   Break;
  end;
  if personslist.Tag = personslist.ItemIndex + 1 then begin
   if personslist.Tag = 0 then ShowMessage("Не найдено: " + Edit1.Text)
    else ShowMessage("Больше не найдено: " + Edit1.Text);
   Button2.Caption := "Найти";
   personslist.Tag := -1;
  end else Button2.Caption := "Найти далее";
end;


 
kodov   (2007-03-21 17:53) [18]

Огромное спасибо всем за оветы и особенно RASkov"у.


 
kodov   (2007-03-21 23:19) [19]

А вот еще один способ поиска в ListBox.
Ставим на форму Richedit и пишем в создании формы:
richedit1.lines:=listbox1.items;
Затем производим поиск в ricedit с помощью Finddialog.
var
 Form1: TForm1;
 SPos: Integer;
-------------
procedure TForm1.Button1Click(Sender: TObject);
begin
SPos := RichEdit1.SelStart;
 with FindDialog1 do
 begin
   FindText := RichEdit1.SelText;
   Position := Point(Form1.Left, Form1.Top + RichEdit1.Top + RichEdit1.Height);
   Options := Options + [frHideUpDown, frHideWholeWord];    
Execute;  
end;

end;

procedure TForm1.FindDialog1Find(Sender: TObject);
begin
with FindDialog1 do

   if frMatchCase in Options then
     RichEdit1.SelStart := Pos(FindText, Copy(RichEdit1.Lines.Text, SPos + 1,
                               Length(RichEdit1.Lines.Text))) + SPos - 1
   else
     RichEdit1.SelStart := Pos(AnsiLowerCase(FindText),
                               AnsiLowerCase(Copy(RichEdit1.Lines.Text, SPos + 1, Length(RichEdit1.Lines.Text)))) +
                               SPos - 1;
   if RichEdit1.SelStart >= SPos then
   begin
     RichEdit1.SelLength := Length(finddialog1.FindText);
     SPos := RichEdit1.SelStart + RichEdit1.SelLength + 1;
   end
   else
     if MessageDlg("Текст "" + finddialog1.FindText + "" не найден. Продолжать диалог?",
                   mtConfirmation, mbYesNoCancel, 0) <> mrYes then
       finddialog1.CloseDialog;
   RichEdit1.SetFocus;
     end;
А затем, когда что-нибудь найдено в Richedit, то выделить в ListBox строку под номером таким же, как и номер выделенной строки в richedit.
Только как это осуществить?
Может кто поможет?


 
Knight ©   (2007-03-21 23:47) [20]

&laquo;Да вы батенька извхащенец&raquo; © :)))


 
Knight ©   (2007-03-21 23:52) [21]

Есть ещё вариант&#133 создать динамически создать бд с одной таблицей, например, Paradox&#133 Занести туда все значения из лист бокса под номерами строк&#133 делать выборку посредством TQuery по условию и посредством кнопок к_первой-вперёд-назад-к_последней перемещаться по выборке и позиционировать листбокс на нужной строке&#133 %)


 
RASkov   (2007-03-22 01:02) [22]

> Только как это осуществить?
> Может кто поможет?

Лучше копай в сторону [21] :) шутка. Ну это-ж надо до такого додуматься....:)


 
Knight ©   (2007-03-22 10:17) [23]

> [22] RASkov   (22.03.07 01:02)
> Ну это-ж надо до такого додуматься....:)


А чё.. если уж через ричедит можно, то пусть уж BDE ищет.. у него башка большая %)))


 
RASkov   (2007-03-22 11:47) [24]

> [23] Knight ©   (22.03.07 10:17)
> Ну это-ж надо до такого додуматься....:)
> А чё.. если уж через ричедит можно, то пусть уж BDE ищет

Это вобще-то о [19] по большей части сказано :)) ну и [21] просто в тему. Супер. :)


 
kodov   (2007-03-22 15:40) [25]

Значит мой вариант не очень?
Ну а всё-таки, как это осуществить?


 
Knight ©   (2007-03-22 15:54) [26]

> [25] kodov   (22.03.07 15:40)
> Значит мой вариант не очень?
> Ну а всё-таки, как это осуществить?

Повтори ещё раз.. чё-то я уже нить вопроса потерял.. то одно надо, то другое... а так уже все исходные варианты даны... даже с базой :)


 
RASkov   (2007-03-22 16:07) [27]

> [25] kodov   (22.03.07 15:40)
> Значит мой вариант не очень?

Какой... [19]? Что значит не очень? Нет, он очень... очень... ну очень.. очень извращенный. :)

> Ну а всё-таки, как это осуществить?

Что? Уже о БД для поиска задумался?
:)


 
Knight ©   (2007-03-22 16:18) [28]

Если с искать далее, то цикл тотде, только поиск не с нуля, а с номера текущей строки... и делов.


 
RASkov   (2007-03-22 16:25) [29]

> [28] Knight ©   (22.03.07 16:18)
> Если с искать далее, то цикл тотде, только поиск не с нуля, а с номера текущей строки... и делов.

> а так уже все исходные варианты даны

Правильно наверное замечено в "прочих" в ветке про давание кода....
Код нужно давать тот, и только тот, который нужен автору вопроса... :)
Иначе начинается [19], [21]..
- [21] - не удивляйся, щас и реализация пойдет...:)


 
Knight ©   (2007-03-22 16:34) [30]

> [29] RASkov   (22.03.07 16:25)
> Правильно наверное замечено в "прочих" в ветке про давание
> кода....


Точно..

procedure TForm1.Button1Click(Sender: TObject);
var i: integer;
begin
 if PersonsList.Items.Count=0 then ShowMessage("There are no elements to find")
 else if Edit1.Text="" then ShowMessage("Enter something to find")
 else begin
   i:=PersonsList.ItemIndex+1;
   while (i<PersonsList.Items.Count) and (Pos(AnsiLowerCase(Edit1.Text),AnsiLowerCase(PersonsList.Items[i]))=0) do Inc(i);
   if i<PersonsList.Items.Count then PersonsList.ItemIndex:=i
   else ShowMessage("Больше ничего не найдено");
 end;
end;


 
RASkov   (2007-03-22 16:41) [31]

> [30] Knight ©   (22.03.07 16:34)

Не... это не то, нечто похожее ему было уже предложено... следом рич"едит :(


 
Knight ©   (2007-03-22 16:45) [32]

> [31] RASkov   (22.03.07 16:41)
> нечто похожее


Чтоб варианты были.. я просто перевёл свой пост в код :)


 
RASkov   (2007-03-22 16:56) [33]

> [32] Knight ©   (22.03.07 16:45)
> просто перевёл свой пост в код

[21] переведи ;)


 
Knight ©   (2007-03-22 17:08) [34]

Перевёл бы, да идтить надо... мож вечером :)


 
Knight ©   (2007-03-23 00:52) [35]


> [33] RASkov   (22.03.07 16:56)
> [21] переведи ;)

Так&#133 на скорую руку без блокировок и проверок&#133 но даже вроде работает %)))))))
На форме Query1 (BDE), ListBox1, Edit1, SpeedButton1-5 с тегами 0-4.

procedure TForm1.FormCreate(Sender: TObject);
begin
 if FileExists(ExtractFilePath(Application.ExeName)+"PList.db") then DeleteFile(ExtractFilePath(Application.ExeName)+"PList.db");

 Query1.DatabaseName:=ExtractFilePath(Application.ExeName);
 Query1.SQL.Text:="CREATE TABLE PList (ID INTEGER, P_NAME VARCHAR(255))";
 Query1.ExecSQL;
end;

//------ &#151; Заполнение списка и таблицы&#133 где-то &#151; ------------
 Query1.SQL.Text:="INSERT INTO PList (ID,P_Name) VALUES (:ID,:P_NAME)";
 Query1.Prepare;
// Какой-то цикл
   Query1.Params.ParamByName("ID").AsInteger:=ListBox1.Items.Add("234324");
   Query1.Params.ParamByName("P_NAME").AsString:="234324";
   Query1.ExecSQL;
// Конец какого-то цикла
//-----------------------------------------------------------

procedure TForm1.Button2Click(Sender: TObject);
var k:Integer;
begin
 if Sender is TSpeedButton then begin
   k:=(Sender as TSpeedButton).Tag;
   if k=0 then begin       // выборка по клавише &laquo;FIND&raquo;
     Query1.SQL.Text:="SELECT * FROM PList WHERE P_NAME LIKE &laquo;%&raquo; || :P_Name || &laquo;%&raquo; ORDER BY ID";
     Query1.Prepare;
     Query1.Params.ParamByName("P_NAME").AsString:=Edit1.Text;
     Query1.Open;
     if Query1.RecordCount>0 then k:=1;
   end;
   case k of
     1: Query1.First; // первая подходящая строка
     2: Query1.Prior; // предыдущая
     3: Query1.Next;  // следующая
     4: Query1.Last;  // последняя
   end;
   if k in [1,2,3,4] then begin
     Panel1.Caption:=IntToStr(Query1.RecNo)+"/"+IntToStr(Query1.RecordCount);
     ListBox1.ItemIndex:=Query1.FieldByName("ID").AsInteger;
   end;
 end;
end;


 
kodov   (2007-03-23 19:33) [36]

Спасибо всем за ответы.


 
_Knight_   (2007-03-26 11:07) [37]

Хоть бы поделился результатом.. :)


 
RASkov   (2007-03-26 14:35) [38]

> [37] _Knight_   (26.03.07 11:07)

Он пока выбирает, на чем-же лучше остановиться - RichEdit или ДБ...
:))
ЗЫ Не в обиду автору. Просто я таких извращений еще не видел :)


 
kodov   (2007-03-26 15:40) [39]

Всё получилось.
Я выбрал предыдущий вариант Raskov"а.
А Ричэдит - это просто для себя узнать, интересно, просто у меня уже ничего не получалось и я подумал, что это тоже вариант.


 
SCz   (2007-03-29 15:17) [40]

With lbFl do
begin
 for i := 0 to (Items.Count - 1) do
   begin
   if Pos(AnsiUpperCase(eSearch.Text), AnsiUpperCase(Items[i])) <> 0 then
     begin
     ItemIndex := i;
     lbFl.SetFocus;
     Exit;
     end;
   end;
end;



Страницы: 1 2 вся ветка

Форум: "Основная";
Текущий архив: 2007.05.27;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.56 MB
Время: 0.074 c
2-1178731051
Strate
2007-05-09 21:17
2007.05.27
Динамичное создение контролов


9-1139755441
angour
2006-02-12 17:44
2007.05.27
помощь по созданию игры "ГО" в Delphi


15-1177889760
Tirael
2007-04-30 03:36
2007.05.27
mobility 2003


15-1177575500
infom
2007-04-26 12:18
2007.05.27
Повернуть отрезок на определенный угол.


15-1177426273
GeLLeR
2007-04-24 18:51
2007.05.27
Нужно сжать музыку...





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский