Создание индексных полей обеспечивает сортировку данных по этим полям, что также облегчает поиск данных - ведь найти нужную фамилию или имя проще, если они отсортированы по алфавиту. Причем имеется возможность сортировать записи не только по возрастанию, но и по убыванию, хотя в большинстве руководств по Delphi эта возможность не описывается.
При создании в базе данных таблицы LichData мы указали поля "Фамилия" и "Имя", как индексированные. Этим и воспользуемся. Чтобы включить сортировку записей по полю "Фамилия", достаточно указать название поля в свойстве IndexFieldNames таблицы:
fDM.TLichData.IndexFieldNames := 'Фамилия';
Если требуется отключить сортировку, этому свойству присваивается пустая строка:
fDM.TLichData.IndexFieldNames := '';
Существует еще одна хитрость, о которой мало где можно прочитать. При индексировании таблицы к имени поля можно прибавить строку " ASC ", если мы желаем сортировать в возрастающем порядке (по умолчанию), или " DESC ", если сортируем в убывающем порядке. Сортировка " ASC " используется по умолчанию. Добавим возможность сортировки по фамилии и имени в нашу программу. Для этого на главную форму установим компонент TPopupMenu с вкладки Standard палитры компонентов. Дважды щелкните по компоненту, чтобы открыть редактор меню. Создадим следующие пункты:
Сортировать по фамилииСортировать по имениНе сортировать-Обратная сортировка
В редакторе меню выделите пункт "Сортировать по фамилии" и измените свойство Name этого пункта на NFam. Пункт "Сортировать по имени" переименуйте в NImya. Пункт "Не сортировать" - в NNet, а пункт "Обратная сортировка" - в NObrat.
Вначале создайте обработчик событий для пункта "Не сортировать" (дважды щелкните по пункту). Тут все просто:
Для обработчика событий пункта "Сортировать по фамилии" код немного сложней:
{Сортировать по фамилии}procedure TfMain.NFamClick(Sender: TObject);var stype : String;begin //выбираем направление сортировки: if NObrat.Checked then stype := ' DESC' //обратная сортировка else stype := ' ASC'; //прямая сортировка //сортируем fDM.TLichData.IndexFieldNames := 'Фамилия' + stype;end;
Здесь, в зависимости от состояния свойства Checked пункта "Обратная сортировка" мы присваиваем строковой переменной stype либо значение ' ASC ' (прямая сортировка), либо ' DESC ' (обратная сортировка). Обратите внимание, что перед строкой имеется пробел, он нужен, чтобы строка не "прилепилась" к названию поля. Далее мы устанавливаем индекс, указывая имя поля и добавляя к нему значение переменной stype. Таким образом, если Checked пункта "Обратная сортировка" имеет значение True (галочка установлена), мы добавляем ' DESC ', или ' ASC ' в противном случае. В результате имя индексного поля может быть либо "Фамилия ASC", либо "Фамилия DESC ".
Сортировку по имени кодируем аналогичным образом:
{Сортировать по имени}procedure TfMain.NImyaClick(Sender: TObject);var stype : String;begin //выбираем направление сортировки: if NObrat.Checked then stype := ' DESC' else stype := ' ASC'; //сортируем fDM.TLichData.IndexFieldNames := 'Имя' + stype;end;
Нам осталось указать код пункта всплывающего меню "Обратная сортировка". Тут нам нужно не просто установить галочку, если ее не было, но также проверить - есть ли сортировка по какому либо полю? Если таблица отсортирована, требуется ее пересортировать по этому же полю, но уже в обратном порядке. Вот код:
{Команда "Обратная сортировка"}procedure TfMain.NObratClick(Sender: TObject);begin //изменяем направление сортировки NObrat.Checked := not NObrat.Checked; //если сортировка по фамилии, пересортируем if Pos('Фамилия',fDM.TLichData.IndexFieldNames)>0 then fMain.NFamClick(Sender); //если сортировка по имени, пересортируем if Pos('Имя',fDM.TLichData.IndexFieldNames)>0 then fMain.NImyaClick(Sender);end;
Как видите, мы использовали функцию Pos(), которая возвратит ноль, если в строке не найдено указанной подстроки, или номер символа, с которого эта подстрока начинается, если она есть. Нам нужно определить, не входит ли в имя индексного поля "Фамилия" или "Имя". Ведь к имени поля добавлена строка ' ASC ' или ' DESC ', так что прямая проверка
if fDM.TLichData.IndexFieldNames = 'Фамилия' then
результата не даст, в любом случае результатом было бы False. Ну а для пересортировки мы вызываем соответствующий пунктменю, чтобы не писать код сортировки еще раз, например:
fMain.NFamClick(Sender);
Следует заметить, что при большом количестве записей в таблице смена индексного поля будет несколько замедлять работу приложения. Тем не менее, индексация таблицы - очень удобный и часто применяемый способ организации вывода записей.
В свойстве PopupMenu верхней сетки DBGrid1 выберите созданное только что всплывающее меню, чтобы оно открывалось только над этой сеткой, сохраните проект, скомпилируйте его и опробуйте сортировку данных.
Напоследок заметим, что мы имеем возможность применить одновременно и фильтрацию записей, и их индексацию. Это позволяет нам создать достаточно мощный и удобный для пользователя механизм поиска записей в нашей программе.