Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Поиск записи


Автор: MacTep 9.2.2005, 14:17
Как организовать поиск в базе данных таким образом, чтобы пользовательно по нажатию любой клавиши видел, что активной стала та запись, в которой какое-либо поле начинается с той буквы, которую нажал пользователь? Я пишу так:

Код

procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char);
begin
 Main.Locate('NameFilm',Key,[loPartialKey]);
end;


Работает только при первом нахождении записи. после второго нажатия на эту же клавишу активной остатся старая запись, а следующую запись с такой же первой буквой не становится активной. Как испрвить? Буду рад всем предложениям! smile

Автор: Alex 9.2.2005, 22:31
А если так:
Код

Main.Locate('NameFilm',Key,[loCaseInsensitive]);

Автор: MacTep 10.2.2005, 10:22
Alex, так как ты предложил работать тоже не будет, так как ключ поиска loPartialKey предполагает и добавление к нему loCaseInsensitive. Т.е. Дельфи сама приписывает это значение к ключу loPartialKey (прочитал об этом в книге). Так что вопрос по прежнему остается открытым! smile А хотелось бы его как можно быстрее закрыть...

Автор: z-END 10.2.2005, 10:44
хочется - закрывай=)
а вообще Locate ищет первую запись не от текущей, а с первой, по этому ничего не выйдет

Автор: Sharl 10.2.2005, 13:29
Можно по другому подойти ,использовав все время обновляемую
TTable.Filter


Автор: z-END 10.2.2005, 15:53
Sharl ой незнаю... при нажатии на педаль каждый раз делать:
1. DisableControls//отключаем контролы
2. Filter ( причем я слабо себе представляю как ты опишешь это в фильтре) //выполняем поиск необходимой записи
3. x :=KeyFieldValue; //присваеваем х - данные ключевого поля, (без него вообще дохлый номер)
4. Filtered := False; //отключаем фильтр
5. Loacte (x); // находим по ключевому полю требуемую запись
6. EnableControls //включаем контролы
если в БД куча записей ты представляешь сколько время на это уйдет, а если данные уже отображаются отфильтрованными, че тогда?!
Наверно правильней при нажатии создавать SQL-запрос (вот тока в запросах несилен, незнаю мона так делать или нет), в который поместить все записи содержашие данную букву, при повторном нажатии перемещать указатель скула на сл.запись и передвигать его аналогично в основной БД.

Автор: Alex 10.2.2005, 17:21
а я бы подглядел как это делает EhLib в своем поиске smile

Автор: Akella 10.2.2005, 17:41
Цитата(Alex @ 10.2.2005, 17:21)
а я бы подглядел как это делает EhLib в своем поиске

Я тоже отключаю такую возможность, в том случае если много записей, т.к. начинает тормозить.
Добавлено @ 17:44
а так работает нормально
Код

tFilterPrep - TTable
idxFName - индекс
edGroupFind - TEdit
 if tFilterPrep.IndexName <> 'idxFName' then tFilterPrep.IndexName:='idxFName';
 tFilterPrep.FindNearest([edGroupFind.Text]);

Автор: Sharl 10.2.2005, 18:32
Цитата

Наверно правильней при нажатии создавать SQL-запрос (вот тока в запросах несилен, незнаю мона так делать или нет), в который поместить все записи содержашие данную букву, при повторном нажатии перемещать указатель скула на сл.запись и передвигать его аналогично в основной БД.

z-END
Да.
Наверно для решения этой задачи лучше использовать SQL

запрос может быть примерно таким
Код

SELECT *(или имена полей таблиц)  FROM имя_таблицы WHERE искомое_поле LIKE 'введенные_символы%'
(% - означает - остальное неважно).


А потом в проге делать
Код

Query1.Next;


Еще один метод
Можно использовать
Query1(или Table1).Database.StartTransaction;
перед переходом

Table1.Delete;
и снова Locate,

В конце работы с поиском
Query1.Database.Rollback;

Но наверно метод второй более дикий по отношению к user-у?



Автор: MacTep 11.2.2005, 01:43
Спасибо всем за советы, попробую что-нибудь придумать. Посмотрим, что из этого получится...

Автор: Akella 11.2.2005, 11:06
Нуно использовать принцип пробежки по все полям с использованием фанкции POS


Процедура поиска по всем полям

Код


Procedure FindRec(What,Mes:String;DS:TDataSet;sFields:array of String;
                            foFromBegin,foCaseSansitive,ShowMes:Boolean);
{
What            - строка для поиска (editFind.Text)
DS              - таблица (TTable,TQuery и т.д.)
Fields          - список полей, по которым нужно вести поиск (['Field1','Field3','Field7'])
foFromBegin     - поиск от начала таблицы (true - от начала или False от текущей записи)
foCaseSansitive - поиск с зависимостью от регистра символов (true - зависит от регистра или False не зависит от регистра)
}
  Function FieldInFields(_Field:String;_Fields:array of String):Boolean;//
  Var
   x:byte;
  begin//содержиться ли текущее поле в масива полей, предназначенных для поиска
    Result:=False;
    For x:=Low(_Fields) to High(_Fields) do
      if _Field = _Fields[x] then begin
        result:=true;
        exit;
      end;//if
  end;//func

Var
i,q,f,w:integer;
begin
ds.DisableControls;//для ускорения отключаем таблицу
w:=ds.RecNo;
try
  //если поиск сначала таблицы
    if foFromBegin then q:=0 else q:=ds.RecNo;
  //идем по всем записям
    For i:=q to ds.RecordCount-1 do begin
  //пробег по всем полям
      For f:=0 to ds.FieldCount-1 do begin
  //если текущее поле содержится в массиве полей, предназначенных для поиска
        if FieldInFields(ds.Fields[f].FieldName,sFields) then begin
  //проверка на регистр
          if (foCaseSansitive = True) AND (POS(What,ds.Fields[f].AsString)<>0) then exit;
          if (foCaseSansitive = False) AND (POS(AnsiUpperCase(What),AnsiUpperCase(ds.Fields[f].AsString))<>0) then exit;
        end;//if FieldInFields(ds.Fields[f].FieldName,sField) then begin
      end;//For f:=0 to ds.FieldCount-1 do begin
      ds.Next;
    end;//For i:=q to ds.RecordCount-1 do begin
    ds.RecNo:=w;
    if ShowMes then ShowMessage(mes);
finally
  ds.EnableControls;//даже если произойдет исключение, то таблицу надо включить
end;//try-finally
end;//proc


Пример использования


FindRec(edFindText.Text,'',dm.tSpis,['Dirname','Type','PathName','Prim'],False,cbRegister.Checked,False);


Автор: Sharl 11.2.2005, 13:51
Bce отлично , но проблематично
Код

ds.RecNo

скажем для Access-a надо ручками пересчитать и каждый раз сканировать с первой записи или поставить TBookmark- и


Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)