Опубликован: 07.04.2008 | Уровень: специалист | Доступ: платный
Лекция 32:

Индексы, фильтрация, отчетность

< Лекция 31 || Лекция 32: 12 || Лекция 33 >

Подстановочные поля

Иной раз приходится добавлять поле, которого изначально в данной таблице не было. Возьмите главную форму – там у нас выходит поле с номером автора, но не с его фамилией, а пользователю номер вряд ли поможет. Значит, для его удобства нам нужно будет вставить поле, где бы вместо номера выходили фамилия, имя и отчество автора. Это поле мы будем брать из таблицы авторов, подставлять нужные значения и выводить их так, будто изначально они были в первой таблице.

Создание нового поля возможно только при неактивной таблице, поэтому закройте таблицу TBooks (свойство Active переведите в False ).

Щелкните дважды по компоненту TBooks, который находится в модуле DM, чтобы открыть редактор полей. Далее щелкните по свободному месту редактора правой кнопкой и выберите команду "New Field" (новое поле). Появится окно, где мы должны указать все необходимые атрибуты поля.

Создание нового поля

Рис. 32.1. Создание нового поля

В поле Name раздела Field properties нужно указать имя нового поля. Назовем его Fio_Avtors. Далее, в поле Type нужно указать тип нового поля, у нас это String, строковое поле для вывода фамилий авторов. В разделе Fieldtype нужно выбрать тип поля, выберем Lookup, это значит, что мы будем брать данные из другой таблицы.

Остался раздел Lookup definition. Здесь в поле Key Fields мы должны указать поле нашей таблицы, откуда мы будем брать значения. У нас это Avtor, здесь хранятся числа – номера авторов. В поле Dataset мы укажем таблицу, откуда будем брать значения, это таблица TAvtors. В поле Lookup Keys укажем начальное поле, которое хранит цифры – номера авторов, поле Key2. А в поле Result Field – результативное поле, значения которого будем подставлять. Это поле FIO.

Далее нажмите кнопку ОК. В редакторе полей перетащите новое поле поближе к полю Avtor, в начало таблицы. Переведите таблицу в активное состояние. Уже в проекте видны недостатки – заголовок подстановочного поля выходит латинскими буквами, и поле Avtor, содержащее цифры, уже не нужно. Снова вызовите редактор полей. Поле Avtor сделайте невидимым ( visible в false ). У поля Fio_Avtors в свойстве DisplayLabel укажите "Авторы". Теперь данные в сетке выходят в удобочитаемом виде. Новое поле никак не влияет на таблицы. Оно необходимо только для вывода данных в нормальном виде.

Далее займемся поиском нужной записи с помощью фильтров.

Фильтрация данных

Фильтрация данных предназначена для облегчения и ускорения поиска необходимой записи. Если у нас в базе всего около 100-200 записей, то найти нужную запись несложно путем обычного перебора записей, с первой по последнюю, либо пока не будет найдена нужная запись. А вот если записей миллион? Или сто миллионов? Тогда время поиска заметно увеличится, и тут придет на помощь фильтрация.

Когда вы применяете фильтр, то на экран выходят только те данные, которые удовлетворяют условиям фильтра. В нашем примере удобней всего делать фильтр по названию книги, так как подстановочное поле использовать в фильтре нельзя, а авторы у нас числятся как целые числа. На экран выйдут только те книги, название которых удовлетворяет условиям поиска, а уж среди них найти нужную книгу будет несложно.

Приступим к программированию. На панель главной формы, которая находится под меню, установите один компонент Label, на котором напишите "Найти книгу:", и один Edit, у которого удалите текст и сделайте его немного длинней. Когда мы будем вводить название книги в поле ввода Edit, на сетке будут отображаться только отфильтрованные данные.

Для компонента Edit создайте событие onChange, где напишите такой код:

//если пусто - не фильтруем.
  if Length(Edit1.Text) = 0 then begin
    fDM.TBooks.Filtered := False;
    Exit;
  end 
  else fDM.TBooks.Filtered := True;
  //индексируем по названию, чтобы они были по алфавиту
  fDM.TBooks.IndexName := 'Sort_Nazvanie';
  //устанавливаем фильтр:
  fDM.TBooks.Filter := 'Nazvanie>='+QuotedStr(Edit1.Text);

Здесь мы вначале проверяем – есть ли текст? Если нет, то убираем фильтр ( Filtered := False ) и выходим из процедуры. Если же текст есть, то указываем, что таблица должна фильтроваться: Filtered := True. Далее, чтобы быстрей найти нужную книгу из списка отфильтрованных записей, делаем сортировку по названию книги.

И наконец, устанавливаем сам фильтр. Функция QuotedStr() возвращает текст, заключенный в кавычки. Можно было бы кавычки установить самостоятельно, однако здесь есть некоторые сложности – приходится считать, сколько же кавычек нужно ставить. Дело в том, что условие фильтрации требует такой записи:

Table1.Filter := 'значение';

А само значение может быть в таком виде:

Nazvanie >= 'Значение'

То есть, внутри строки будет еще одна строка, которую необходимо поставить в одинарные кавычки. Чтобы внутри текста указать одинарную кавычку, ее нужно написать дважды, так что строка превратится в такой вид:

fDM.TBooks.Filter := 'Nazvanie>='''+ Edit1.Text+'''';

Чтобы избежать таких сложностей подсчитывания кавычек, и существует функция QuotedStr().

Отчетность

Для создания отчетности существует очень много способов. Наиболее "продвинутый", но и наиболее сложный – вывод отчета с помощью компонентов отчетности, таких как Quick Report. Другой профессиональный способ – вывод отчета в файл MS Excel или MS Word. Мы разберем самый простой способ отчетности – будем выводить отчет в компонент Memo, а при желании – сохранять его в файл.

Создайте новую форму. В свойстве Name укажите fOtchet, в свойстве Caption – "Отчет", а саму форму сохраните в модуле Otchet.

Далее, в верхнюю часть формы установим Memo, и растянем его по всему верху (свойство Align = alTop ).

В нижней части поместим кнопку и компонент SaveDialog. На кнопке напишем "Сохранить в файл".

У Memo уберем весь текст, и установим вертикальную прокрутку. Не забудем добавить к этой форме модуль DM с помощью команды Uses Unit, а в главной форме той же командой добавим новое окно Otchet.

По нажатию кнопки напишем такой код:

if SaveDialog1.Execute then
    Memo1.Lines.SaveToFile(SaveDialog1.FileName);

Теперь нам необходимо написать код, по которому Memo будет заполняться данными. Это лучше всего сделать по событию главной формы onShow:

var
  s : String;
begin
  //очищаем Memo:
  Memo1.Lines.Clear;
  //устанавливаем закладку:
  bm := fDM.TBooks.Bookmark;
  //готовим таблицу:
  fDM.TBooks.First;
  fDM.TBooks.Filtered := False;
  //делаем отпервой до последней записи:
  while not fDM.TBooks.Eof do begin
    //собираем данные в переменную s:
    s := 'Автор: '+ GetFIO(fDM.TBooks['Avtor'])+#13+#10;
    s := s + 'Название: '+ fDM.TBooks['Nazvanie']+#13+#10;
    s := s + 'Экземпляров: '+ IntToStr(fDM.TBooks['Exemp'])+#13+#10;
    s := s + 'Стоимость: '+ FloatToStr(fDM.TBooks['Cena'])+#13+#10;
    s := s + 'Дата поставки: '+DateToStr(fDM.TBooks['Date'])+#13+#10;
    s := s + '--------------------------------------------' +#13+#10;
    fDM.TBooks.Next;
    Memo1.Lines.Add(s);
  end; //while
  //переходим на закладку:
  fDM.TBooks.Bookmark := bm;
  bm := '';

Мы указали функцию GetFIO(), которой пока нет. Эта функция будет принимать номер автора, и возвращать его фамилию, имя и отчество. Создайте эту функцию выше процедуры onShow:

function GetFIO(i : Integer):String;
begin
  Result := '';
  fDM.TAvtors.First;

  while not fDM.TAvtors.Eof do begin
    if fDM.TAvtors['Key2'] = i then begin
      Result := fDM.TAvtors['FIO'];
      Break;
    end; //if
    fDM.TAvtors.Next;
  end; //while
  if Length(Result)= 0 then
    Result := 'Автор не найден';
end;

Вот теперь все! Сохраните проект, скомпилируйте его и посмотрите, как он работает. Мы в этом проекте использовали почти все приемы работы с таблицами, хотя приложение, конечно, получилось не совсем профессиональным. Например, если удалить автора из таблицы авторов, то разрушится целостность таблиц – книга будет указывать автора, которого нет. В профессиональных проектах все это учитывается, однако на это уходит гораздо больше времени, и пишется гораздо больше кода. Когда вы освоите работу с таблицами самостоятельно, для вас все это не будет представлять никаких проблем.

Подытоживая сказанное о базах данных, заметим еще раз, что приложения бывают локальными – когда приложение и сама база данных располагаются на машине клиента. Такой подход следует использовать в приложениях, в которых сотрудники предприятия не должны обращаться к одним и тем же данным, например, в собственном телефонном справочнике, в приложении с кулинарными рецептами, в каталоге домашней библиотеки и тому подобными программами.

Сетевая база данных работает примерно так же, как локальная, только сама база данных находится на сетевом ресурсе, и с ее данными работают несколько клиентских приложений. Такой подход следует использовать для небольших сетевых приложений, когда сотрудников, работающих с данными тоже немного. Если записей в таблице перевалит за десяток тысяч, то обработка такой базы данных очень сильно загрузит сеть.

Клиент – серверная база данных работает иначе. Данные хранятся на сервере. Там же хранится СУБД (Система Управления Базами Данных). Пользователь работает не напрямую с данными, а получает к ним доступ из СУБД с помощью SQL – запросов. Сервер эти данные обрабатывает, и пользователю возвращается результат – только те данные, которые необходимы. А в предыдущем случае каждый клиент получал свою копию полной БД. Нетрудно сообразить, что клиент – серверный подход значительно ускоряет работу с БД и снижает нагрузку на сеть.

Однако начинать программирование БД следует все же с локальных приложений. По мере накопления опыта вы будете двигаться дальше, к сетевым и клиент – серверным БД.

< Лекция 31 || Лекция 32: 12 || Лекция 33 >
Виктор Пелих
Виктор Пелих

Здравствуйте.
Прохожу курс "Введение в программирование на Delphi"
Добрался до Лекции 29: Введение в базы данных.

Установлена RAD Studio 11.3, у которой отсутствует вкладка BDE и, соответственно, компонент Table,  который обеспечивает доступ к таблице средствами механизма BDE.
Поиск в интернете подсказал 
BDE Installer for RAD Studio, Delphi, C++Builder 10.3 Rio
Подскажите, имеется ли ещё возможность использовать механизм BDE в Delphi11 и если такая возможность есть, как подключить BDE к Delphi11?
С уважением...

 

Федор Антонов
Федор Антонов

Здравствуйте!

Записался на ваш курс, но не понимаю как произвести оплату.

Надо ли писать заявление и, если да, то куда отправлять?

как я получу диплом о профессиональной переподготовке?

Данила Некрасов
Данила Некрасов
Россия, Пермь, ПНИПУ
Сергей Федоров
Сергей Федоров
Россия