Форум: "Основная";
Текущий архив: 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]Так и что? Вариант не идеальный, но работает и при количестве строк больше тысячи…
← →
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)…
Просто не читая скопировал с варианта автора ветки… Надо туда 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]Зато у меня ищёт и ищет правильно… а у тебя не ищет. Точнее твоя команда работает по принципу 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]«Да вы батенька извхащенец» © :)))
← →
Knight © (2007-03-21 23:52) [21]Есть ещё вариант… создать динамически создать бд с одной таблицей, например, Paradox… Занести туда все значения из лист бокса под номерами строк… делать выборку посредством TQuery по условию и посредством кнопок к_первой-вперёд-назад-к_последней перемещаться по выборке и позиционировать листбокс на нужной строке… %)
← →
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] переведи ;)
Так… на скорую руку без блокировок и проверок… но даже вроде работает %)))))))
На форме 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;
//------ — Заполнение списка и таблицы… где-то — ------------
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 // выборка по клавише «FIND»
Query1.SQL.Text:="SELECT * FROM PList WHERE P_NAME LIKE «%» || :P_Name || «%» 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.042 c