Здравствуйте. Установлена RAD Studio 11.3, у которой отсутствует вкладка BDE и, соответственно, компонент Table, который обеспечивает доступ к таблице средствами механизма BDE.
|
Индексы, фильтрация, отчетность
Подстановочные поля
Иной раз приходится добавлять поле, которого изначально в данной таблице не было. Возьмите главную форму – там у нас выходит поле с номером автора, но не с его фамилией, а пользователю номер вряд ли поможет. Значит, для его удобства нам нужно будет вставить поле, где бы вместо номера выходили фамилия, имя и отчество автора. Это поле мы будем брать из таблицы авторов, подставлять нужные значения и выводить их так, будто изначально они были в первой таблице.
Создание нового поля возможно только при неактивной таблице, поэтому закройте таблицу TBooks (свойство Active переведите в False ).
Щелкните дважды по компоненту TBooks, который находится в модуле DM, чтобы открыть редактор полей. Далее щелкните по свободному месту редактора правой кнопкой и выберите команду "New Field" (новое поле). Появится окно, где мы должны указать все необходимые атрибуты поля.
В поле 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 – запросов. Сервер эти данные обрабатывает, и пользователю возвращается результат – только те данные, которые необходимы. А в предыдущем случае каждый клиент получал свою копию полной БД. Нетрудно сообразить, что клиент – серверный подход значительно ускоряет работу с БД и снижает нагрузку на сеть.
Однако начинать программирование БД следует все же с локальных приложений. По мере накопления опыта вы будете двигаться дальше, к сетевым и клиент – серверным БД.