Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2007.05.27;
Скачать: CL | DM;

Вниз

Поиск в 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;
Скачать: CL | DM;

Наверх




Память: 0.58 MB
Время: 0.098 c
2-1178814419
webpauk
2007-05-10 20:26
2007.05.27
рисование в treeview


15-1177837127
SkySpeed
2007-04-29 12:58
2007.05.27
Форматирование винчестера без возможности восстановления инфы....


15-1177291363
koha
2007-04-23 05:22
2007.05.27
Прочитал Джеффри РИХТЕР "Создание эффективных WIN32-приложений"


15-1177835989
SkySpeed
2007-04-29 12:39
2007.05.27
Проблема с IDE-SATA


15-1177693897
Pazitron_Brain
2007-04-27 21:11
2007.05.27
Бывают ли?