Форум программистов
 

Восстановите пароль или Зарегистрируйтесь на форуме, о проблемах и с заказом рекламы пишите сюда - alarforum@yandex.ru, проверяйте папку спам!

Вернуться   Форум программистов > Delphi программирование > Общие вопросы Delphi
Регистрация

Восстановить пароль
Повторная активизация e-mail

Купить рекламу на форуме - 42 тыс руб за месяц

Ответ
 
Опции темы Поиск в этой теме
Старый 07.09.2009, 19:23   #1
мимо
Пользователь
 
Регистрация: 13.06.2009
Сообщений: 61
По умолчанию Работа с ListView

Есть поиск и добавление файлов в ListView.
Есть поиск в каждом файле, в каждой строке, слова через Edit1.Text
Как через POS осуществить поиск по строкам в файлах в ListView?
Код:
procedure BeginFind;
var
 Index,SelIndex,ReplaceResult:Integer;
 ErrorStr:string;
begin
 FilesTotal:=MainForm.ListView.SelCount;
 ReplaceForm.Caption:='Поиск';
 try
  ReplaceForm.Show;
  with MainForm do
   begin
    SelIndex:=0;
    for Index:=0 to ListView.Items.Count-1 do
     begin
      CurrentFileName:=ListView.Items[Index].SubItems[0]+'\'+ListView.Items[Index].Caption;
      ReplaceResult:=FindSubStrInFile(CurrentFileName);
      end;
      if ReplaceResult<0
       then ListView.Items[Index].SubItems[2]:=ErrorStr
       else ListView.Items[Index].SubItems[2]:=IntToStr(ReplaceResult);
      if ReplaceResult>0
       then Inc(FilesChanged);
      Inc(SelIndex);
      ReplaceForm.RefreshData;
     end;
   end;
 finally
  ReplaceForm.Close;
  ReplaceForm:=nil;
 end;
end;
думаю, нужно добавить такое выражение:
Код:
for Index:=0 to ListView.Items.Count-1 do
     begin
if (Pos('слово', ListView.Items.Item[Index].Caption) <> 0) and (Pos('второе слово', ListView.Items.Item[Index].Caption) <> 0)
  then
только как закончить? может сначала нужно создать TStringList?

Последний раз редактировалось мимо; 08.09.2009 в 13:07.
мимо вне форума Ответить с цитированием
Старый 08.09.2009, 06:42   #2
Скандербег
Форумчанин
 
Регистрация: 04.04.2009
Сообщений: 438
По умолчанию

В добавленном коде содержится попытка искать "слово" совсем не в файле, а в строке пункта ListWiew (Caption). Может быть Caption и содержат строки с именами файлов, но все же это не сами файлы, которые, как минимум, для поиска в них, надо открывать.

В приведенном коде есть функция FindSubStrInFile - это, видимо, и есть та функция, которая открывает файл и ищет "слово" в нем, возвращая результат поиска.
Может быть в реализации этой функции и находятся ответы на ваши вопросы.

Что касается конкретного вопроса " как через POS искать слово" (теплится надежда, что это текстовый файл), то это очень просто: загружаете файл (имя которого находится в Caption ListView) в TStringList и применяете Pos.
Pos('слово', SL.Text) (SL в этом примере переменная типа TStringList).
Pos возвращает либо 0 (не найдено), либо число >0 (найдено в такой-то позиции).
Но Pos ВСЕГДА вернет (если вернет) первое вхождение "слово" в тексте и если в этом тексте есть еще такое же слово, то оно не будет найдено. Для расширенного поиска используется функция PosEx (модуль StrUtils).
Скандербег вне форума Ответить с цитированием
Старый 08.09.2009, 13:06   #3
мимо
Пользователь
 
Регистрация: 13.06.2009
Сообщений: 61
По умолчанию

да. спасибо, уже разобрался. тут поиск происходит только в названиях файлов, находящихся в ListView.
а тогда как записать, если заданное нами слово не найдено в файле, то файл удаляется из ListView? (т.е. if ReplaceResult=0, then ...)

Последний раз редактировалось мимо; 08.09.2009 в 13:14.
мимо вне форума Ответить с цитированием
Старый 08.09.2009, 23:11   #4
Скандербег
Форумчанин
 
Регистрация: 04.04.2009
Сообщений: 438
По умолчанию

Удалить то item с именем файла не сложно:
ListView1.Items.Delete(<индекс>), где <индекс> - число в диапазоне 0..ListView.Items.Count-1

Но в безусловном цикле, который приведен в коде этого делать нельзя. Засада кроется в том, что после первого же удаления количество items станет меньше чем было задано при входе в цикл (ListView.Items.Count). Рано или поздно в цикле произойдет ошибка обращения по некорректному адресу.

Ситуацию может исправить цикл с предусловием.
Код:
index := 0;
while index < ListView.Items.Count do begin
  ...
  if ReplaceResult = 0 then
    ListView1.Items.Delete(index)
  else
    Inc(index);
end;
Скандербег вне форума Ответить с цитированием
Старый 09.09.2009, 18:12   #5
мимо
Пользователь
 
Регистрация: 13.06.2009
Сообщений: 61
По умолчанию

странно, если брать index, то выдает ошибку - Assignment to FOR-Loop variable 'Index'
а если вместо index поставить SelIndex, то при нахождении искомого слова - все нормально, а если не находит, то вылетает с ошибкой - accessviolation.
либо оставить только if ReplaceResult = 0 и при не нахождении искомого слово очищается весь ListView (
мимо вне форума Ответить с цитированием
Старый 09.09.2009, 22:11   #6
Скандербег
Форумчанин
 
Регистрация: 04.04.2009
Сообщений: 438
По умолчанию

Ошибка "Assignment to FOR-Loop variable 'Index'" понятно от чего происходит: вы почему то решили оставить цикл For и вставить в него цикл while, хотя ясно было сказано, что for в этом случае не годится и его надо заменить на while.
А в других ошибках (они, скорее, логические) надо разбираться, нужны исходные тексты проекта, иначе не понятно что в них происходит. Впрочем, и эти ошибки тоже, вероятно, происходят от того что оставлен цикл for.

Последний раз редактировалось Скандербег; 09.09.2009 в 22:18.
Скандербег вне форума Ответить с цитированием
Старый 12.02.2011, 16:54   #7
casio23
Форумчанин
 
Аватар для casio23
 
Регистрация: 29.12.2010
Сообщений: 186
По умолчанию Попробуй этот вариант

Код:
procedure LV_FindAndSelectItems(lv: TListView; const S: string; column: Integer);
var
  i: Integer;
  found: Boolean;
  lvItem: TListItem;
begin
  Assert(Assigned(lv));
  Assert((lv.ViewStyle = vsReport) or (column = 0));
  Assert(S <> '');
  for i := 0 to lv.Items.Count - 1 do
  begin
    lvItem := lv.Items[i];
    if column = 0 then
      found := AnsiCompareText(lvItem.Caption, S) = 0
    else if column > 0 then
    begin
      if lvItem.SubItems.Count >= Column then
        found := AnsiCompareText(lvItem.SubItems[column - 1], S) = 0
      else
        found := False; 
    end
    else 
      found := False;
    if found then
    begin
      lv.Selected := lvItem;
    end;
  end;
end;
Код:
procedure TForm.Edit1Change(Sender: TObject);
var
rct:TRECT;
i: integer;
const LVM_GETITEMRECT=4110;  LVIR_BOUNDS=0;
begin
for i:=0 to ListView1.Items.Count-1  do
begin
If pos(Edit1.Text, ListView1.Items[i].Caption)>0 then
begin
ListView1.Selected:=ListView1.Items[i];
rct.Left:=0;
SendMessage(ListView1.Handle,LVM_GETITEMRECT,0,integer(@rct));
ListView1.Scroll(0,(i-ListView1.TopItem.Index)*(rct.Bottom-rct.Top));
end;
end;

Последний раз редактировалось casio23; 12.02.2011 в 16:57. Причина: /
casio23 вне форума Ответить с цитированием
Старый 12.02.2011, 17:05   #8
Пепел Феникса
Старожил
 
Аватар для Пепел Феникса
 
Регистрация: 28.01.2009
Сообщений: 21,000
По умолчанию

не нужно некропостить.
Хорошо поставленный вопрос это уже половина ответа. | Каков вопрос, таков ответ.
Программа делает то что написал программист, а не то что он хотел.
Функции/утилиты ждут в параметрах то что им надо, а не то что вы хотите.
Пепел Феникса вне форума Ответить с цитированием
Ответ


Купить рекламу на форуме - 42 тыс руб за месяц

Опции темы Поиск в этой теме
Поиск в этой теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Как перетащить элемент ListView в другой ListView? Paul Hindenburg Компоненты Delphi 5 26.01.2013 11:35
Listview Neymexa Общие вопросы .NET 0 13.05.2009 21:19
ListView Лубышев Общие вопросы Delphi 6 18.07.2008 16:04
ListView Terran Общие вопросы Delphi 2 05.04.2008 23:15
ListView Garacio Компоненты Delphi 1 17.12.2006 15:30