Поиск в DBF через DBGrid

Модераторы: Duncon, Naeel Maqsudov, Игорь Акопян, Хыиуду

Ответить
registr
Сообщения: 2
Зарегистрирован: 26 апр 2005, 11:56

Всем гуру от Дельфи -хелп ми. Имеется форма с компонентом DBCRTLGrid и подключенной через BDE базой basa.dbf (на форме значит есть DataSourse и Ttable) . В базе 3 поля: FIO, phone и adres. Также на фрейме с именем pan_instr1, присоединенной к форме лежит компонент FINDDIALOG с именем finddialog1 и кнопкой для открытия этого диалога.
ВОПРОС: вот пользователь ввел что-то в это окно поиска и нажал "найти". Надо что бы система нашла и/или отфильтровала записи с встречающимся текстом. Причем если пользователь ввел например "46" то надо что бы нашлись телефоны с номером где встречается число "46" или адрес (текст) например "дом №46". Если ввел "Ленин" :) то фамилию "Ленинский" и адрес "ул.Ленин". В общем - по аналогии с Access: нажал -нашел первую удовлетворяющую запись, нажал "Найти далее" - ищет дальше. Если это сложно: то разовый фильтр показывающий все записи где встречается данное условие поиска.
И второй ВОПРОС: Необходимо отфильтровать эту базу по условию, длина фамилии в поле FIO не превышает 7 знаков или заканчивается на "*ов"
Заранее огромное спасибо. Прошу простить если некорректно описал проблему. Опыта маловато - и наставника нет. все сам, методом тыка.
Из-за этого объясните как можно подробнее ! :) Еще раз СПАСИБО
Аватара пользователя
LAngel
Сообщения: 277
Зарегистрирован: 30 мар 2005, 08:19
Откуда: Ульяновск
Контактная информация:

:) гы...
Ставим

Код: Выделить всё

  Table1.Filter := 'Adres <> ''''' //Любое условие, которое было бы всегда верным
  Table1.Filtered := True;
Потом пишем обработчик onFilterRecord для таблицы:

Код: Выделить всё

procedure TForm1.Table1FilterRecord(DataSet: TDataSet;
  var Accept: Boolean);
var i: Integer;
begin
  Accept := False;
  for i := 1 to DataSet.FieldCount do
    if pos(Edit1.Text, DataSet.Fields.Fields[i-1].AsString) > 0
    then Accept := True;
end;
Ну и обработчик изменений в Едите, в котором пользователь строку поиска вводит:

Код: Выделить всё

procedure TForm1.Edit1Change(Sender: TObject);
begin
  Table1.Refresh;
end;
У меня такое работает. Причем довольно быстро. :)
С уважением, Lost Angel...
registr
Сообщения: 2
Зарегистрирован: 26 апр 2005, 11:56

Спасибо большое ! Задавал вопрос на 4 форумах, только этот ответ сработал без глюков.
Поэтому если можно, то спрошу дальше: Возможно ли этот код переделать на цикл? Ведь сейчас он находит только 1 вхождение?! А если надо дальше искать "*ЛЕНИН*"(см. вопрос). И 2: дать сообщение "Искомый текст не найден". ?
И вот такие вопросы. Покажите образцы команд на фильтры для след. условий:
1) Отфильтровать по полю FIO все записи, длина фамилии которых меньше 7 знаков
table1.filter:=
или
событие onTable1FilterRecord
2) ... фамилии заканчиваются/содержат на "*ов/*"
3) в идеале в DBGride эту часть текста еще и закрасить другим цветом :)
И в не тему: у меня на форме лежит LookupComboBox. Там по списку тоже фильтруется. Но вот гадость - как "сбросить, очистить, обновить" строку в нем, перевести в состояние при открытии формы, когда там пусто (в 1-ой, отображаемой строчке) как до нажатия на стрелку?

Заранее спасибо, очень надеюсь на ответ !!
Аватара пользователя
LAngel
Сообщения: 277
Зарегистрирован: 30 мар 2005, 08:19
Откуда: Ульяновск
Контактная информация:

Если table.refresh делать не в обработчике изменений, а, например по кнопке рядом с эдитом. Тогда можно и проверить на "найден или нет" очень просто - таблица будет пуста :)

Код: Выделить всё

Table1.refresh;
if Table1.eof then ShowMessage('Искомый текст не найден');
Смысла переделывать на цикл нет. потому, что он фильтрует таблицу и оставляет только те записи, которые удовлетворяют условию. Можно пробежаться по таблице и вывести данные куда-нить, если это необходимо.

Код: Выделить всё

  Table1.First;
  while not Table1.eof do
    ShowMessage(Table1.FieldByName('FIO').asString); // например
    Table1.next;
  end;
1) в онтэйблфилтер:
Accept := Length(DataSet.FieldByName('FIO').asString) < 7;
2) там же.
Accept := pos('ов', DataSet.FieldByName('FIO').asString) > 0;
3) Вот выделять цветом - сложнее. Если интересно, могу написать примерчик, надо обрабатывать перерисовку. и самому рисовать текст в ячейках. (Ну или использовать rxDBGrid, там это делается проще)

C ComboBox'ом... Там есть метод Text, который и содержит строку в самом комбо. Её можно менять по своему усмотрению.
Если же это DBLookupComboBox, то там Text менять нельзя. Да и он всегда отображает содержимое поля из таблицы списка. Т.е. либо сделать Table.close (для таблицы списка), либо перевести её в положение при старте программы: Table.First
С уважением, Lost Angel...
RoKon
Сообщения: 82
Зарегистрирован: 27 мар 2005, 12:24
Откуда: Saransk City
Контактная информация:

А почему нельзя использовать SQL? Все будет намного проще и нагляднее. Даже если исползуется DBase и BDE, есть же TQuery.

Код: Выделить всё

select * from TableName
where address like '%36%'
и т.п.
if Table1.eof
- не есть пустая таблица, EOF - означает что курсор установлен на последней записи. Для определения наличия записей в наборе данных (таблице) следует использовать Table1.IsEmpty или

Код: Выделить всё

select count(*) from TableName
вернет кол-во записей в таблице.
The trurh is out there...
Ответить