Поможем написать учебную работу
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.

Предоплата всего

Подписываем
Если у вас возникли сложности с курсовой, контрольной, дипломной, рефератом, отчетом по практике, научно-исследовательской и любой другой работой - мы готовы помочь.
Предоплата всего
Подписываем
Создание приложений для работы с базами данных.
Средства Delphi, предназначенные для разработки и эксплуатации приложений, использующих базы данных:
Особенности программ для работы с БД.
Некоторые поддерживаемые в Delphi типы БД.
Локальные и файл серверные БД.
Клиент-серверные БД.
Создание и просмотр псевдонимов баз данных.
Обзор компонентов, используемых для связи с базами данных.
Создание приложений для работы с базами данных.
Базы данных используют, когда надо работать с большими объемами данных.
Реляционная база данных это набор таблиц, процедур и др. объектов, поддерживающих ее работу. Таблица имеет имя идентификатор, по которому на нее можно сослаться. Пример таблицы данных о сотрудниках Pers:
Номер |
Группа |
Курс |
Фамилия |
Имя |
Отчество |
Год рождения |
Пол |
Характеристика |
Фотография |
Num |
Group |
Year |
Fam |
Nam |
Par |
Year_b |
Sex |
Charact |
Photo |
1 |
РР-11 |
Иванов |
Иван |
Иванович |
1985 |
м |
… |
… |
|
2 |
РР-12 |
Петров |
Петр |
Петрович |
1986 |
м |
… |
… |
|
3 |
РР-11 |
Сидоров |
Сидор |
Сидорович |
1985 |
м |
… |
… |
|
4 |
РР-13 |
Иванова |
Ирина |
Ивановна |
1986 |
ж |
… |
… |
|
… |
… |
… |
… |
… |
… |
… |
… |
… |
Столбцы таблицы соответствуют характеристикам объектов полям. Каждое поле характеризуется именем и типом хранящихся данных. Имя поля это идентификатор, который используется в различных программах для манипуляции данными. Как и любой идентификатор, имя поля может состоять только из латинских букв, только из одного слова и т. д. (строка 2 в таблице).
Тип поля характеризует тип хранящихся в поле данных. Это могут быть строки, числа,булевы значения, большие тексты (например, характеристики сотрудников), изображения (фотографии сотрудников) и т.п.
Каждая строка таблицы соответствует одному из объектов. Она называется записью и содержит значения всех полей, характеризующих данный объект.
При построении таблиц баз данных важно обеспечить непротиворечивость информации. Обычно это делается введением ключевых полей обеспечивающих уникальность каждой записи. Ключевым может быть одно или несколько полей. В приведенном примере можно было бы сделать ключевыми совокупность полей Fam, Nam, Par. Но в этом случае нельзя было бы заносить в таблицу сведения о полных однофамильцах, у которых совпадают фамилия, имя и отчество. Поэтому в таблицу введено первое поле Num номер, которое можно сделать ключевым, обеспечивающим уникальность каждой записи.
При работе с таблицей пользователь или программа как бы скользит курсором по записям. В каждый момент времени есть некоторая текущая запись, с которой и ведется работа. Записи в таблицах данных могут располагаться без какого-либо порядка, просто в последовательности их ввода (появления новых сотрудников). Но когда таблицы предъявляются пользователю, они должны быть упорядочены. Пользователь может хотеть просматривать их в алфавитном порядке, или рассортированными по отделам, или по возрасту и т.п.
Для упорядочивания данных используется понятие индекса. Индекс показывает, в какой последовательности желательно просматривать таблицу. Он является как бы посредником между пользователем и таблицей:
Индексы могут быть первичными и вторичными.
Например, первичным индексом могут служить поля, отмеченные при создании базы данных как ключевые. А вторичные индексы могут создаваться из других полей как в процессе создания самой базы данных , так и позднее в процессе работы с ней. Вторичным индексам присваиваются имена идентификаторы, по которым их можно использовать.
База данных обычно содержит не одну, а множество таблиц. Например, база данных о некоторой организации может содержать таблицу имеющихся в ней подразделений с характеристикой каждого из них.
Таблица Dep с полями Dep и Proisv
Отдел |
Тип |
Dep |
Proisv |
Бухгалтерия |
управление |
Цех 1 |
производство |
Цех 2 |
производство |
В связанных таблицах обычно одна выступает как главная, а другая или несколько других - как вспомогательные, управляемые главной. Главная и вспомогательные таблицы связываются друг с другом ключом. В качестве ключа могут выступать какие-то поля, присутствующие в обеих таблицах.
В примере головной может быть таблица Dep, вспомогательной Pers, а связываться они могут по полю Dep, присутствующему в обеих таблицах.
Каждой записи в главной таблице Dep соответствуют те записи вспомогательной таблицы Pers, в которых ключевое поле Dep с названием отдела совпадает с названием отдела в текущей записи главной таблицы. Иначе говоря, если в текущей записи главной таблицы в поле Dep написано «Бухгалтерия», то во вспомогательной таблице Pers выделяются все записи сотрудников бухгалтерии.
Создают базы данных и обрабатывают запросы к ним системы управления базами данных СУБД: Paradox, Microsoft Access, FoxPro, Oracle, InterBase и т.д.
Разные СУБД по разному организуют и хранят базы данных. Paradox использует для каждой таблицы один файл. В Microsoft Access и InterBase несколько таблиц хранятся как один файл. В этом случае база данных это имя файла с путем доступа к нему. Системы типа клиент/сервер (Sybase, Microsoft SQl, Oracle) хранят все данные на отдельном компьютере и общаются с клиентом посредством специального языка SQL.
Для упорядочения обращения к базам данных используют псевдонимы баз данных. Псевдоним (alias) содержит всю информацию, необходимую для обеспечения доступа к базе данных. Эта информация сообщается только один раз при создании псевдонима. А приложение для связи с базой данных использует псевдоним. В этом случае приложению безразлично, где физически расположена база данных, а часто безразлична и СУБД, создавшая и обслуживающая эту базу данных. При смене системы каталогов, сервера и т.п. ничего в приложении переделывать не надо. Достаточно, чтобы администратор базы данных ввел соответствующую информацию в псевдоним.
Кеширование всех изменений означает, что все изменения данных, вставка новых записей, удаление существующих записей, проводимые пользователем, сначала делаются не в самой базе данных, а запоминаются в памяти во временной виртуальной таблице. И только по особой команде после всех проверок правильности вносимыхв таблицу данных пользователю предоставляется возможность или зафиксировать все эти изменения в базе данных, или отказаться от этого и вернуться к тому состоянию, которое было до начала редактирования.
Фиксация изменений в базе данных производится с помощью транзакций. Это совокупность команд, изменяющих базу данных. Пользователю предоставляется возможность завершить транзакцию или внесением всех изменений в реальную базу данных, или откатом от этого с возвратом к тому состоянию, которое было до начала транзакции.
Средства Delphi, предназначенные для разработки и эксплуатации приложений, использующих базы данных:
BDE (Borland Database Engine) машина баз данных Borland. Представляет собой набор DLL-библиотек, обеспечивающих низкоуровневый доступ к локальным и клиент-серверным БД. Должна устанавливаться на каждом компьютере, который использует приложения для работы с БД, написанные для Delphi.
SQL Links драйверы для работы с удаленными серверами данных (MS SQL Server, Oracle)
BDE Administrator утилита для установки псевдонимов (имен) баз данных, параметров БД и драйверов баз данных на конкретном компьютере. При работе с БД из приложения, созданного с помощью Delphi, доступ к базе данных производится по ее псевдониму. Параметры определяемой псевдонимом БД, действуют только для этой БД; параметры, установленные для драйвера БД, действуют для всех баз данных, использующих драйвер. Кроме того, можно произвести установку таких общих для всех БД параметров, как формат даты и времени, форматы представления числовых значений, используемый языковый драйвер и т.д.
Database Desktop (DBD) средство для создания, изменения и просмотра БД. Эта утилита прежде всего ориентирована на работу с таблицами локальных СУБД, например Paradox. Можно с некоторыми ограничениями создавать и просматривать таблицы баз данных, работающих под управлением серверов: InterBase, MS SQL Server, Oracle.
DBD позволяет программисту возможность сформировать запрос к БД методом QBE (Query By Example запрос по образцу).
SQL Explorer универсальная утилита, совмещающая многие функции BDE Administrator и DBD. С ее помощью можно создавать и просматривать псевдонимы БД, просматривать структуры и содержимое таблиц БД, формировать запросы к БД на языке SQL, создавать словари данных (шаблоны полей таблиц).
SQL Monitor средство для трассировки выполнения SQL-запросов.
Невизуальные компоненты для работы с БД служат для соединения приложения с таблицами БД в локальных и распределенных системах. Они расположены на странице Data Access палитры компонентов. С помощью невизуальных компонентов осуществляется подключение к базам данных, формирование запросов к ним, манипулирование таблицами.
Визуальные компоненты для работы с БД предназначены для визуализации записей наборов данных или их отдельных полей. Эти компоненты расположены на странице Data Controls палитры компонентов. Они служат основным инструментом разработки пользовательского интерфейса доступа к данным.
Особенности программ для работы с БД.
Характерной особенностью созданных с помощью Delphi программ для работы с БД является непременное использование в них BDE (процессор реляционной базы данных Borland Database Engine, включенный в состав Delphi), которая осуществляет роль связующего моста между программой и БД.
BDE берет на себя всю низкоуровневую работы по обеспечению клиентской программы нужными ей данными, поэтому в общем случае взаимодействие программы с данными происходит следующим образом:
BDE не является частью программы. В зависимости от типа СУБД она может размещаться на машине клиента или сервера.
Обычно между программой и BDE располагается слой компонентов, существенно упрощающих разработку программ. Невизуальные компоненты осуществляют непосредственную работу с BDE, и три из них (TTable, TQuery, TStoredProc) служат наборами данных, в то время как визуальные
компоненты отображают поставляемые им данные и служат для создания удобного интерфейса пользователя. Между наборами данных и визуальными компонентами обязательно располагаются компоненты TDataSource, играющие роль клапанов, открывающих или закрывающих потоки данных, которыми обмениваются источники с визуальными компонентами (см рис.).
Некоторые поддерживаемые в Delphi типы БД.
Локальные и файл серверные БД.
В локальных БД базы данные располагаются на машине клиента. В файл серверных БД базы данные располагаются на сетевом файл-сервере.
Локальный вариант может обеспечить лишь однопользователький режим доступа к данным.
В файл-серверных БД данные располагаются на сетевом файл-сервере, который может быть доступен одновременно нескольким пользователям. Данные в БД хранятся в единственном экземпляре, а каждый клиент в каждый момент времени работает с некоторой локальной копией данных, причем управление данными целиком возлагается на клиентские программы. Именно они должны заботиться о синхронизации локальных копий данных на каждом клиентском месте с содержимым основной (и единственной) базы данных.
При выполнении запроса к БД, расположенной на файловом сервере, в действительности происходит запрос к локальной копии данных на компьютере пользователя. Поэтому перед выполнением запроса данные в локальной копии в полном объеме обновляются из реальной БД. Так, если таблица БД состоит из 10000 записей, а для выполнения запроса нужно только 10 записей, все равно клиенту передаются все 10000 записей. Таким образом серьезно загружается сеть.
Клиент-серверные БД.
В архитектуре клиент-сервер между BDE и базой данных появляется важное промежуточное звено сервер БД (специальная программа, управляещая базой данных).
Клиент формирует запрос к серверу на языке запросов SQL (Structured Query Language структурированный язык запросов), являющемсяпромышленным стандартом для реляционных баз данных. SQL-сервер обеспечивает интерпретацию запроса, его выполнение, формирование результата и выдачу этого результата клиенту. При этом ресурсы клиентского компьютера не участвуют в физическом выполнении запроса: клиентский компьютер лишь отсылает запрос к серверной БД и получает результат, после чего интерпретирует его необходимым образом и представляет пользователю. По сети передаытся только те данные, которые нужны клиенту.
При выполнении запросов сервером существенно повышается степень безопасности данных, поскольку правила целостности данных определяются на сервере и являются едиными для всех приложений, использующих эту БД. Мощный аппарат транзакций, поддерживаемый SQL-серверами, блокирует одновременное изменение одних и тех же данных различными пользователями и предоставляет возможность откатов к первоначальным значениям при внесении в БД изменений, закончившихся аварийно.
Создание и просмотр псевдонимов баз данных.
Обчно вызов Database Desktop включен в главное меню Delphi в раздел Tools. Если это не сделано можно включить его туда командой Tools|Configure Tools… (файл DBD32.exe).
DBD позволяет создавать таблицы баз данных некоторых СУБД, задавать и изменять их структуру.
В можно создавать и просматривать псевдонимы, выполнив команду Tools|Alias Manager. При этом появляется окно Alias Manager:
При выборе псевдонима в списке Database Alias автоматически изменяется тип драйвера в выпадающем списке
Вызов этой программы производится из главного меню Delphi командой Database| Explore.
Обзор компонентов, используемых для связи с базами данных.
Компоненты, используемые для связи с базами данных, расположены в библиотеки компонентов на странице Data Access (доступ к данным) и Data Controls (управление данными).
Каждое приложение, использующее базы данных, обычно имеет по крайней мере по одному компоненту следующих трех типов:
- Компоненты наборы данных (data set), непосредственно связывающиеся с базой данных. Это такие компоненты, как Table, Query, Stored proc.
- Компонент источник данных (data source), осуществляющий обмен информацией между компонентами первого типа и компонентами визуализации и управления данными. Таким компонентом является DataSource.
Компоненты визуализации и управления данными, такие как DBGrid, DBText, DBEdit и др.
Схема взаимодействия компонентов Delphi с базой данных:
Основные свойства компонента Table и простейшие приложения
на его основе.
Установка связей между компонентами и базой данных, навигация по таблице.
Простейшее приложение для отображения в форме таблицы Pers из базы данных Paradox dbP:
В качестве набора данных используем компонент Table (со страницы Data Access). Источником данных будет компонент DataSource. Это невизуальные компоненты.
В качестве компонента визуализации: DBGrid со страницы Data Control. Это визуальный компонент, в котором будут отображаться данные. Align=alClient.
Установим цепочку связей между этими компонентами в соответствии со схемой взаимодействия компонентов Delphi с базой данных:
Связь между визуальным компонентом и источником данных: свойству DataSource у компонента DBGrid1 в инспекторе объектов присвоить значение из выпадающего списка DataSource1.
Связь между источником данных и набором данных: свойству Dataset у компонента DataSource1 в инспекторе объектов присвоить значение из выпадающего списка Table1.
Связь между набором данных и необходимой таблицей базы данных: для этого предназначены два свойства компонента Table DatabaseName и TableName. В выпадающем списке свойства DatabaseName показываются все доступные BDE псевдонимы баз данных. Выбрать ранее созданный псевдоним dbP. После этого в выпадающем списке свойства TableName появятся таблицы, доступные в данной базе данных. Выберите таблицу Pers.
Можно связаться с таблицей в процессе проектирования, если установить свойство таблицы Table1 Active в true.
Запустив приложение можно просматривать данные, редактировать их (отредактирован-ные данные будут помещаться в базу данных в момент перехода от редактируемой записи к любой другой). Поле Num невозможно изменить, поскольку оно автоматически изменяется и доступно только для чтения. Нельзя задать произвольное имя подразделения Dep, так как имеется таблица Dep, задана целостность на уровне ссылок и допустимы только те значения Dep, которые имеются в головной таблице Dep.
Заранее выставлять для таблиц Active = true допустимо только в процессе настройки и отладки приложения, работающего с локальными базами данных.
В законченном приложении во всех таблицах сначала должно быть установлено Active = false, затем при событии формы эти свойства могут быть установлены в true, а при событии формы onDestroy эти свойства опять должны быть установлены в false. Это исключит неоправданное поддержание связи с базой данных, которое занимает ресурсы, а при работе в сети мешает доступу к базе данных других пользователей.
Некоторые свойства компонента DBGrid: ReadOnly запрещение редактирования данных, тот же эффект дает для свойства Options dgEditing=false.
У компонента Table есть булево свойство Exclusive определяет доступ к используемой таблице при одновременном обращении к ней нескольких приложений (например, при работе в сети или в многозадачном режиме). Exclusive=true таблица будет закрыта для других приложений, это свойство можно менять только при Active=false.
Рассмотрим еще один компонент, управляющий работлй с таблицей навигатор DBNavigator (со страницы Data Control). DBNavigator имеет кнопки для управления данными:
nbFirst |
перемещение к первой записи |
nbPrior |
перемещение к предыдущей записи |
nbNext |
перемещение к следующей записи |
nbLast |
перемещение к последней записи |
nbInsert |
вставить новую запись перед текущей |
nbDelete |
удалить текущую запись |
nbEdit |
редактировать текущую запись |
nbPost |
послать отредактированную информацию в базу данных |
nbCancel |
отменить результаты редактирования или добавления новой записи |
bnRefresh |
очистить буфер, связанный с набором данных |
DBNavigator имеет свойство VisibleButtons, пользуясь которым можно убрать любые ненужные в данном приложении кнопки. Если нужно запретить пользователю вводить новые записи nbInsert=false. Если нужно запретить редактирование оставить только кнопки nbFirst, nbPrior, nbNext, nbLast.
DBNavigator связывается с источником данных также через свойство DataSource. При работе с DBNavigator внесенные изменения зафиксируются в таблице после нажатия кнопки nbPost.
Зададим соединение с базой данных в момент начала работы приложения в событии onCreate:
procedure TForm1.FormCreate(Sender: TObject);
begin
Table1.Active:=true;
end;
И разрыв соединения в момент закрытия формы:
procedure TForm1.FormDestroy(Sender: TObject);
begin
Table1.Active:=false;
end;
Свойства полей
У компонента Table есть свойства IndexName и IndexFieldName.
Свойство IndexName содержит выпадающий список индексов, созданных для таблицы. Если выбрать индекс FIO, записи будут представленными упорядоченными по алфавиту. Индекс depfio упорядочивает по подразделениям, а внутри подразделения по алфавиту. В свойстве IndexFieldName просто перечислены предусмотренные в индексах
комбинации полей, если вы забыли. что обозначают имена индексов.
Для редактирования отдельных полей имеется Редактор Полей, вызывается двойным щелчком на компоненте Table.
Каждое поле это объект, свойства которого отображаются в Инспекторе объектов. Класс поля зависит от типа поле: TStringField, TSmallIntField, TBooleanField и т.п. Эти классы являются производными от класса TField базового класса полей.
Некоторые основные свойства полей:
Alignment |
Выравнивание отображаемого текста внутри колонки: влево, вправо, по центру |
DisplayLabel |
Заголовок столбца данного поля |
DisplayWidth |
Ширина колонки число символов |
EditMask, EditFormat |
Форматы отображения данных |
DisplayValue |
Для логических полей: какие значения должны отображаться, если поле имеет значение true или false. |
ReadOnly |
При значании true запрещает вводить данные в поле |
Visible |
При значении false делает поле невидимым |
Вид приложения после установки всех необходимых свойств:
Перенос полей на форму из редактора полей.
Из Редактора Полей можно перетаскивать поля на форму с помощью мыши. Такой упрощенный вариант можно использовать, чтобы просмотреть, что находится в неизвестных таблицах. Например, создадим приложение для просмотра содержимого таблицы biolife.db демонстрационной базы данных DBDEMOS:
- Поместите на форму компонент Table и свяжите его с таблицей biolife.db демонстрационной базы данных DBDEMOS (DatabaseName, TableName).
- Сделайте двойной щелчок на Table1, затем щелкните правой мышкой в окне Редактора полей и из всплявающего меню выберите раздел Add all fields добавить все поля. В окне появяться имена всех полей таблицы. Установите их свойства DisplayLabel, чтобы было понятно то,что отображается (класс, семейство, вид, длина, описание, изображение)
- Щелкните правой кнопкой мыши и из всплывающего меню выберите раздел Select All выделить все поля. Все поля окажутся выделенными. Перетащите их мышью на форму. На форме будут автоматически созданы компоненты, отображающие данные каждого поля и снабженные метками, указанными в свойствах DisplayLabel полей.
- Разместите компоненты должным образом на площади формы, установите в компоненте Table1 свойство Active=true, добавьте навигатор и приложение готово.
На форме автоматически появились:
- источник данных DataSource1, связанный своим свойством DataSet с набором данных Table1;
- компоненты поля редактирования - DBEdit, связанные с данными через свойство Datasource и отображающие данные полей (свойство DataField ) Category(класс), Common_Name(семейство) и т.д. У DBEdit нет свойства Text (оно не объявлено как published для отображения в Инспекторе Объектов). Можно программно во время выполнения устанавливать и читать свойство Text, но нельзя устанавливать его во время проектирования.
- Для отображения поля Notes (Описание) на форме разместился компонент DBMemo1. Это аналог компонента Memo. Поле Graphic (изображение) отображается в компоненте DBImage1 (аналог компонента Image), который используется для просмотра и редактирования изображений. Изображение в DBImage можно вставить во время работы приложения из буфера обмена. В компонентах DBMemo1 и DBImage1 в Инспекторе объеков отсутствуют поля Lines и Picture. Эти свойства можно читать или устанавливать только во время выполнения приложения. Зафиксировать изменения в базе данных можно кнопкой nbPost на навигаторе.
- Чтобы случайно не испортить содержимое демонстрационной базы данных свойству ReadOnly компонента Table1 нужно присвоить значение false.
Ограничения вводимых значений.
Несколько возможноcтей ограничений вводимых значений предоставляют свойства полей:
- Для числовых полей имеются свойства MinValue и Maxvalue. При нарушении этих пределов будет генерироваться исключение EDatabaseError, которое лучше перехватывать в приложении, чтобы выдавать пользователю сообщение на русском языке. например, если требуется принимать на работу сотрудников от 20 до 30 лет, можно установить для поля Year_b ограничения MinValue=1970 и Maxvalue=1980.
- Можно использовать свойства CustomConstraint, которое позволяет написать ограничение на значение поля в виде строки SQL, например: (Year_b>1970) and (Year_b<1980). Свойство ConstraintErrorMessage содержит строку текста, который будет показан пользователю в случае, если он вводит данные, не удовлетворяющие поставленным ограничениям, например: «Возраст претендента на должность не подходит». Это свойство подходит не только к числовым полям.
- Можно использовать обработку события поля onValidate. Это событие возникает перед записью введенного значения поля в буфер записи. Тут можно предусмотреть любые проверки, при появлении недопустимых значений выдать пользователю сообщение.
procedure TForm1.Table1Year_bValidate(Sender: TField);
begin
if (Table1Year_b.Value<1970)and(Table1Year_b.Value>1930) then exit
else begin
ShowMessage('Событие onValidate');
Abort;
end;
end;
Если все нормально, то после события onValidate возникает еще событие onСhange, в обработчике которого тоже еще не поздно сгенерировать исключение.
Есть возможность осуществлять проверку на уровне записи, анализируя различные ее поля. Для этого используется свойство Constraints компонента Table. При выборе этого свойства в Инспекторе объектов открывается окно, в котором, щелкая на кнопке Add можно занести набор ограничений, каждое из которых является самостоятельным объектом со свойствами CustomConstraint (строка SQL, определяющая допустимые ограничения) и ErorMessage (строка текста, которая будет представлена пользователю в случае нарушения ограничений). Например: «Принимаем только мужчин > 1955 г.р. и женщин > 1965 г.р.».
Вычисляемые поля.
Создадим вычисляемое поле, значение которого вычисляется на основании значений других полей записи. Например, поле, вычисляющее возраст сотрудника по году его рождения:
- Вызвать Редактор полей двойным щелчком на Table1. Из контекстного меню Редактора полей выбрать раздел New. Появится окно добавления нового поля в разделе Field Properties (свойства поля) нужно указать:
_ имя поля (Name) назовем его Age
_ тип данных (Type) Smallint;
_ и для некоторых типов (например, для строк) размер (Size).
- В группе радиокнопок Field Type выбрать Calculated.
- Нажать на кнопку OK и вернуться в окно Редактора полей, там появится новое поле Age. Изменить для этого поля в Инспекторе объектов значение DisplayLabel на «Возраст».
- Чтобы указать процедуру вычислений надо выйти из Редактора полей, выделить Table1, перейти в Инспектор объектов и задать обработчик события OnCalcFields, которое наступает каждый раз, когда нада обновить значение вычисляемых полей таблицы. В этом обработчике можно использовать процедуру DecodeDate для преобразования ее первого аргумента, имеющего тип TDateTime (этот тип используется в Delphi для хранения дат и времени), в целые значения года, месяца и дня.
Заголовок процедуры:
procedure DecodeDate(Date: TDateTime; var Year, Month, Day: Word);
Следующий программный код можно использовать, чтобы отобразить текущие значения года, месяца, дня, часа, минуты, секунды, миллисекунды из функции Now, которая возвращает значение текущих даты и времени: Date + Time:
function Now: TDateTime;
procedure TForm1.Button1Click(Sender: TObject);
var
Present: TDateTime;
Year, Month, Day, Hour, Min, Sec, MSec: Word;
begin
Present:= Now;
DecodeDate(Present, Year, Month, Day);
Label1.Caption := 'Сегодня число ' + IntToStr(Day) + ' месяца ' + IntToStr(Month) + ' года ' + IntToStr(Year);
DecodeTime(Present, Hour, Min, Sec, MSec);
Label2.Caption := IntToStr(Hour)+ ' часов '+ IntToStr(Min) + ' минуты ' ;
end;
Результат: Обработчик события OnCalcFields может выглядеть
следующим образом:
procedure TForm1.Table1CalcFields (DataSet: TDataSet);
Var
Year, Month, Day:Word;
begin
DecodeDate(Date,Year,Month,Day);
Table1Age.Value:=Year- Table1Year_b.Value;
end;
Фильтрация данных.
Компонент Table позволяет также отфильтровывать данные по определенным критериям с использоваием свойств: Filter, Filtered, FilterOptions.
Свойство Filtered включает или выключает использование фильтра.
В свойстве Filter записывается сам фильтр в виде строки, содержащей ограничения на значения полей. Например, если свойство Filtered=true и в свойстве Filter записано:
- Dep=Цех 1, то в таблице отобразятся только те записи, в которых поле Dep имеет значение Цех 1
- Dep=Цех * отображение всех записей, в которых значение поля Dep начинается с Цех (При этом опция foNoPartialCompare свойства FilterOptions должно быть false). Свойство FilterOptions содержит опции foNoPartialCompare(=true запрещает частичное совпадение при сравнении) и foCaseInsentitive делает сравнение строк нечувствительным к региситру (если включить эту опцию, то «Цех 1» и «цех 1» будут считаться идентичными).
- При записи условий можно использовать операции отношения =,>,>=,<,<=,<>, а также логические операции and, or, not. Фильтр:
(Dep=Цех 1) and (Year_b<=1970) and (Year_b>=1940)
отобразит сотрудников цеха 1, чей год рождения лежит в заданных пределах. Но использовать в фильтре имена вычисляемых полей (например, поля Age) не разрешается.
Добавим в приложение возможность фильтрации отображаемых записей по отделам, по возрасту и по обоим критериям (см. Рис):
- Перенесем на форму группу радиокнопок RadioGroup (Name=RGF). Зададим в редакторе свойству RGF.Items строки: Нет, Все, Отдел, Возраст. RGF.ItemIndex=1, RGF.Columns=2, RGF.Caption=Фильтрация
- Перенесем на форму выпадающий список ComboBox (Name=CBDep) для выбора подразделения, по которому производится фильтрация. В свойство CBDep.Items занести список имен подразделений.
- Два элемента SpinEdit со страницы Samples (Name=SEmin и SEmax) для задания диапазона возраста при фильтрации. Задать в этих компонентах соотвествующие значения MaxValue, MinValue, Value.
- Кнопку с заголовком «Обновить».
- Фильтрация в приложении должна проводиться при следующих событиях:
- щелчок в группе радиокнопок RGFClick (его текст приведен ниже, для остальных событий проводится делегирование),
- при событии OnChange выпадающего списка отделов
- щелчок на кнопке «Обновить» (при изменении диапазона возраста).
procedure TForm1.RGFClick(Sender: TObject);
begin
Table1.IndexName:='depfio';
if (RGF.ItemIndex=0) then Table1.Filtered:=false //отсутствие фильтрации
else begin if (RGF.ItemIndex=2) //фильтрация по отделу 'Dep=…
then Table1.Filter:='Dep='''+CBDep.Text+''''
else if (RGF.ItemIndex=3) //фильтрация по возрасту Year_b<=… и Year_b>=…
then begin
Table1.Filter:='(Year_b<='+IntToStr(Year-SEMin.Value) +')and(Year_b>='+IntToStr(Year-SEMax.Value)+')';
Table1.IndexName:='Year';
end
else begin //фильтрация по отделу и по возрасту
Table1.Filter:='(Dep='''+CBDep.Text+''')and(Year_b<='+IntToStr(Year-SEMin.Value)
+')and(Year_b>='+IntToStr(Year-SEMax.Value)+')';
end;
Table1.Filtered:=true;
end;
end;
(!!!Второй способ обеспечить фильтрацию использовать обработку события OnFilterRecord!!!).
!!!Использование словарей атрибутов полей.!!!
Создать новый словарь можно с помощью программы SQL Explorer, вызываемой командой главного меню Database|Explore. Для создания нового словаря нада перейти на страницу Dictionary и выполнить команду Dictionary|New. Откроется диалоговое окно создания нового словаря:
-
в первой сторочке нужно указать имя, по которому в дальнейшем можно выбрать этот словарь из других;
- во второй строчке база данных, в которой сохраняется словарь;
-
в третьей строчке имя таблицы, в которой будет сохраняться словать (словарь по умолчанию сохраняется в виде таблицы Paradox);
- в четвертой строчке произвольный комментарий.
Зарегистрировать имеющийся словарь можно командой Dictionary|Registry, выбрав базу данных и имя таблицы:
Некоторые компоненты визуализации данных.
Компонент DBGrid имеет свойство Columns, представляющее собой набор объектов, каждый из которых отражает один солбец таблицы. При выделении этого свойства появляется кнопка, при нажатии на которую открывается окно Редактора Столбцов. Добавлять столбцы в Редактора Столбцов можно по одному, щелкая на первой слева кнопке Add и указывая для них в Инспекторе Объектов соответствующие поля в свойстве FieldName (или выбирая в контекстном меню раздел Add). А можно выбрать все столбцы сразу, выбрав в контекстном меню раздел Add All Fields или щелкнув на второй кнопке справа.
Для выделенного столбца в Инспекторе Объектов отметим следующие свойства:
- ButtonStyle определяет стиль ввода данных в поле текущей записи, может принимать следующие значения:
cbsAuto |
Появление при редактировании кнопки, связанной с выпадающим списком допустимых значений |
cbsEllipsis |
Появление при редактировании кнопки с многоточием …, при щелчке на которой возникает событие OnEditButtonClick компонента DBGrid, в котором можно предусмотреть выбор соответствующего значения. Какое именно поле редактируется в обработчике OnEditButtonClick можно узнать по свойству SelectedField компонента DBGrid. Через это же свойство в поле заносится установленное пользователем значение. |
cbsNone |
Обычное редактирование без каких-либо кнопок |
-
PickList список допустимых значений поля (для столбца Dep можно занести «Бухгалтерия», «Цех 1», «Цех 2»; а для столбца Sex «м», «ж».). Если список PickList не заполнен, то никакой кнопки при редактировании не появляется.
- DropDownRows (по умолчанию 7) определяет допустимое число строк в списке, отображаемое без появления полос прокрутки. Если реальное число строк меньше, размер списка устанавливается автоматически.
Обзор компонентов отображения данных со страницы Data Control:
DBText |
аналог обычной метки Label, но связанный сданными. Позволяет отображать данные некоторого поля, но не дает возможности его редактировать. Тип отображаемого поля может быть различным: строка, число, булева величина. Компонент автоматически переводит соответствующие типы в отображаеме символы. |
DBEdit |
связанный с данными аналог обычного окна редактирования Edit. Позволяет отображать и редактировать данные полей различных типов: строка, число, булева величина. Если задать в компоненте свойство ReadOnly=true, то он превратиться в элемент отображения, как и DBText |
DBMemo |
связанный с данными аналог обычного многострочного редактора Memo. Позволяет отображать и редактировать данные поля типа Memo, а также данные любых типов, указанных выше для предыдущих компонентов. |
DBRichEdit |
связанный с данными аналог обычного многострочного окна редактирования текста в обогащенном формате RTF, область применения та же, что и для компонента DBMemo. |
DBImage |
связанный с данными аналог обычного компонента Image. Компонент позволяет отображать графические поля, например фоторгафии сотрудников. |
DBCheckBox |
связанный с данными аналог обычного индикатора CheckBox. Позволяет отображать и редактировать данные поля булевского типа. Если при выводе ланных поле имеет значение True, то индикатор включсется. И наоборот, при редактировании поля присваиваемое ему значение определяется состоянием индикатора. |
DBRadioGroup |
связанный с данными аналог группы радиокнопок RadioGroup. Позволяет отображать и редактировать поля с ограниченным множеством возможных значений. В нашеи примере это может относится к полю Dep.!!! |
|
|
Все перечисленные компоненты имеют свойства DataSource источник данных (компонент типа TDataSource) и DataField поле, с которым связан компонент.
Для всех этих компонентов в Инспекторе Объектов отсутствуют основные свойства, отображающие содержание: Caption, Text, Image и т.п. Все эти свойства доступны в компонентах толь ко во время выполнения. Эти свойства это значения соответствующих полей таблицы базы данных.
Компонент Session.
Компоненты Session осуществляют общее управление связыванием приложения с базами данных. Delphi автоматически генерирует объект Session в каждом приложении, работающем с базами данных. На этот объект можно ссылаться через глобальную переменную Session.
Для демонстрации методов компонента Session построим приложение, позволяющее просматривать любую заданную пользователем таблицу в любой заданной им доступной базе данных. Это приложение содержит два выпадающих списка типа TComboBox, названных cbAlias для выбора пользователем базы данных и cbTable для выбора таблицы. кнопка просмотр предназначена для просмотра выбранной таблицы в компоненте TDBGrid, связанной цепочкой ссылок с компонентами DataSource1 и Table1.
При создании формы, в обработчике события onCreate нужно загрузить список cbAlias доступными BDE псевдонимами. Это делает метод GetAliasNames объекта Session, который передает в свой параметр типа Tstrings перечень псевдонимов баз данных, зарегистрированных в BDE.
procedure GetAliasNames(List: TStrings);
Обработчик события onCreate должен выглядеть следующим образом:
procedure TForm1.FormCreate(Sender: TObject);
begin
Session.GetAliasNames(cbAlias.Items);//список псевдонимов передается в список cbAlias
end;
При выборе пользователем базы данных в списке cbAlias надо загрузить список cbTable перечнем таблиц выбранной базы данных. Это можно сделать включением в обработчик события onChange компонента cbAlias вызов метода GetTableNames объекта Session:
procedure GetTableNames(const DatabaseName, Pattern: String; Extensions, SystemTables: Boolean; List: TStrings);
Метод GetTableNames загружает в свой последний параметр перечень таблиц базы данных, заданной своим первым аргументом. Второй параметр метода позволяет задать шаблон, отбирающий имена таблиц («р*» - отберет имена таблиц, начинающихся с символа «р»). Пустой шаблон означает выбор всех таблиц. Третий параметр, установленный в true, означает, что в имена таблиц будет включаться расширение файла (это необходимо для таблиц Paradox и dBase). Четвертый параметр задается равным false для баз данных Paradox и dBase, а для баз данных, основанных на SQL, этот параметр устанавливается в true, чтобы возвращать и таблицы двнных и системные таблицы, определяющие структуру данных.
Обработчик события onChange компонента cbAlias:
procedure TForm1.cbAliasChange(Sender: TObject);
begin
Session.GetTableNames(cbAlias.Text,'',true,false,cbTable.Items);
cbTable.ItemIndex:=0;
end;
Обработчик нажатия кнопки «Просмотр»:
procedure TForm1.Button1Click(Sender: TObject);
begin
if cbTable.Text=''
then begin ShowMessage(''); exit; end;
Table1.Active:=false;
Table1.DatabaseName:=cbAlias.Text;//задание свойства DatabaseName
Table1.TableName:=cbTable.Text;// задание свойства TableName
Table1.Active:=true;
end;
Модуль приложения:
unit USession;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, Db, DBTables, Grids, DBGrids;
type
TForm1 = class(TForm)
cbAlias: TComboBox;
cbTable: TComboBox;
StaticText1: TStaticText;
StaticText2: TStaticText;
Button1: TButton;
DBGrid1: TDBGrid;
DataSource1: TDataSource;
Table1: TTable;
procedure FormCreate(Sender: TObject);
procedure cbAliasChange(Sender: TObject);
procedure Button1Click(Sender: TObject);
private { Private declarations }
public { Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.FormCreate(Sender: TObject);
begin
Session.GetAliasNames(cbAlias.Items);
end;
procedure TForm1.cbAliasChange(Sender: TObject);
begin
Session.GetTableNames(cbAlias.Text,'',true,false,cbTable.Items);
cbTable.ItemIndex:=0;
end;
procedure TForm1.Button1Click(Sender: TObject);
begin
if cbTable.Text=''
then begin
ShowMessage(''); exit;
end;
Table1.Active:=false;
Table1.DatabaseName:=cbAlias.Text;
Table1.TableName:=cbTable.Text;
Table1.Active:=true;
end;
end.
Компонент BatchMove.
Предназначен для групповых операций переноса данных из одного набора в другой. Основные свойства:
- Source источник данных;
- Destination приемник данных типа TTable;
- Mode определяет режим переноса данных:
batAppend |
Записи из источника добавляются в приемник, не изменяя существующих там записей. Таблица приемник должна существовать до начала переноса данных |
batUpdate |
Записи в таблице приемнике с ключевыми полями, соответствующими полям в таблице источнике, изменяются на записи из источника. Новые записи в приемник не добавляются. Таблица приемник должна существовать до начала переноса данных и должна иметь индекс. |
batAppendUpdate |
Записи в таблице приемнике с ключевыми полями, соответствующими полям в таблице источнике, изменяются на записи из источника. Записи из таблицы источника, которые не имеют соответствия в приемнике, добавляются туда. Таблица приемник должна существовать до начала переноса данных и должна иметь индекс. |
batDelete |
Записи в таблице приемнике, которым находится соответствие в источнике, удаляются из приемника. Таблица приемник должна существовать до начала переноса данных и должна иметь индекс. |
batCopy |
Таблица приемник создантся и заполняется записями источника. Если таблица приемник уже существовала, то ее содеожимое заменяется на содержимое источника. |
Основной метод компонента Execute выполняет операцию переноса данных. Свойство MovedCount указывает число записей, успешно перенесенных в таблицу-приемник.
При переносе записей из одной таблицы в другую могут возникать проблемы, связанные с несоответствием типов полей в таблице-источнике и таблице-приемнике. В этих случаях свойство AbortOnProblem указывает, должна ли немедленно прекращаться операция, вызвавшая несоответствие типов полей в таблице-источнике и таблице-приемнике.
При задании AbortOnProblem=false желательно одновременно задать свойство ProblemTableName. Это свойство указывает имя таблицы Paradox, в которую будут помещаться записи, в которых обнаружено несоответствие типов полей и которые поэтому не помещены в приемник. Свойство ProblemCount определяет число записей, вкоторых возникли такие проблемы. При задании AbortOnProblem=false записи с полями несоответствующих типов все-таки могут помещаться в таблицу-приемник компонент BatchMove пытается в этом случае преобразоватьтип поля таблицы-источника в тип поля таблицы-приемника. Если такое преобразование возможно, то никаких проблем при переносе записей не возникает.
В некоторых случаях перенос отдельных записей может оказаться невозможным из=за того, что они нарушают целостность данных в таблице-приемнике, например, дублируют значение ключевого поля, которые должны быть уникальнымиВ этих случаях анализируется свойство AbortOnKeyViol и соответствующие ему KeyViolTableName и KeyViolCount.
- !!!ChangedTableName, ChangeCount
- Свойство Mappings типа Tstrings позволяет задать таблицу соответствия полей источника и приемника. По умолчанию поля таблиц переносятся в поля приемника с теми же именами и в той же последовательности, как в источнике (Свойство Mappings задавать не надо). В свойстве Mappings можно указать только часть полей, значения которых надо переносить и в какое поле приемника надо переносить значение поля источника. Если в свойстве Mappings задать строку
DepNew=Dep
то значение поля Dep из источника будет переносится в поле DepNew приемника.
Таким образом, компонент BatchMove является удобным средством копирования, объединения, упорядочивания таблиц.
Построим пример для просмотра режимов работы BatchMove. Будем создавать копию таблицы Pers базы данных dbP и дальше использовать эту копию как приемник. Копия будет располагаться в той же базе данных dbP и иметь имя Pers2:
- перенести на форму по 2 экземпляра компонентов Table, DataSource, DBGrid.
- Table1, DataSource1, DBGrid1 свяжите с источником таблицей Pers базы данных dbP. В компоненте DBGrid1 можно будет просматривать и менять содержащуюся в ней информацию.
- Table2, DataSource2, DBGrid2 свяжите друг с другом, но не связывайте Table2 ни с какой базой данных. Этот компонент будет приемником, в который будут переносится даные их первой таблицы.
- Добавьте на форму компонент BatchMove. Source=Table1, Destination=Table2. Все режимы переноса будут задаваться программно.
- Добавьте на форму метку Label для отображения числа скопированных записей.
- Добавьте на форму кнопки Button, соответствующих различным режимам переноса данных («копировать» для режима batCopy, «добавить» для режима batAppend и т.п.)
- Добавьте на форму кнопку «удалить таблицу».
- В раздел private описания класса добавить процедуру Exec, которая будут выполнять перенос данных из источника в приемник в заданном режиме:
procedure TForm1.Exec;
begin
Table2.Active:=false; //таблица-приемник закрывается
Table2.DatabaseName:=Table1.DatabaseName; //задается база данных
Table2.TableName:='Pers2.db'; //задается таблица-приемник
if (BatchMove1.Mode=batCopy)or(Table2.Exists) then begin //проверяется режим копирования и существование таблицы 2; для всех режимов кроме batCopy таблица должна существовать
BatchMove1.Execute; //осуществляется перенос данных
Table2.Active:=true; //таблица-приемник открывается и в DBGrid2 можно видеть ее содержимое
Label1.Caption:='Обработано '+IntToStr(BatchMove1.MovedCount)+' записей';
end else ShowMessage('Для выполнения этой операции'+#13+'таблица должна существовать');
end;
- Обработчики щелчков на кнопках Button1,2 и т.д. задают режим переноса данных и вызывают процедуру Exec:
procedure TForm1.Button1Click(Sender: TObject); //копировать таблицу
begin
BatchMove1.Mode:=batCopy;
Exec;
end;
- Обработчик щелчка на кнопке «Удалить таблицу»:
procedure TForm1.Button3Click(Sender: TObject); //удалить таблицу
begin
if (Table2.Exists) then begin //если таблица существует
Table2.Close;
Table2.DeleteTable; //таблица удаляется методом DeleteTable
end;
end;
Добавить обработчики для формы OnCreate ( Table1.Active:=true;) и OnDestroy
( Table1.Active:=false;
Table2.Active:=false;)
- Проверить работоспособность приложения и различные способы объединения данных двух таблиц.
- Добавить в приложение возможности из примера, использующего методы компонента Session: обеспечить выбор базы данных и копируемой таблицы. Добавить возможность сохранять таблицу приемник в указанном каталоге под указанным именем (добавив компонент SaveDialog).
Для перекачки данных из таблиц, созданных в одной СУБД, в таблицы другой СУБД требуется только совместимость типов полей этих таблиц.
Модуль приложения:
unit UBatchmove;
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, Grids, DBGrids, Db, DBTables, StdCtrls;
type
TForm1 = class(TForm)
Table1: TTable;
Table2: TTable;
DataSource1: TDataSource;
DataSource2: TDataSource;
DBGrid1: TDBGrid;
DBGrid2: TDBGrid;
BatchMove1: TBatchMove;
Label1: TLabel;
Button1: TButton;
Button2: TButton;
Button3: TButton;
procedure Button1Click(Sender: TObject);
procedure Button3Click(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure FormDestroy(Sender: TObject);
procedure Button2Click(Sender: TObject);
private { Private declarations }
procedure Exec;
public { Public declarations }
end;
var
Form1: TForm1;
implementation
{$R *.DFM}
procedure TForm1.Exec;
begin
Table2.Active:=false; //таблица-приемник закрывается
Table2.DatabaseName:=Table1.DatabaseName; //задается база данных
Table2.TableName:='Pers2.db'; //задается таблица-приемник
if (BatchMove1.Mode=batCopy)or(Table2.Exists) then begin //для всех режимов кроме batCopy таблица должна существовать
BatchMove1.Execute; //осуществляется перенос данных
Table2.Active:=true; //таблица-приемник открывается и в DBGrid2 можновидеть ее содержимое
Label1.Caption:='Обработано '+IntToStr(BatchMove1.MovedCount)+' записей';
end else ShowMessage('Для выполнения этой операции'+#13+'таблица должна существовать');
end;
procedure TForm1.Button1Click(Sender: TObject); //копировать таблицу
begin
BatchMove1.Mode:=batCopy;
Exec;
end;
procedure TForm1.Button3Click(Sender: TObject); //удалить таблицу
begin
if (Table2.Exists) then begin
Table2.Close;
Table2.DeleteTable;
end;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
Table1.Active:=true;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Table1.Active:=false;
Table2.Active:=false;
end;
procedure TForm1.Button2Click(Sender: TObject); //добавить записи
begin
BatchMove1.Mode:=batAppend;
Exec;
end;
end.
Пример.
unit Udb2;
interface
uses
SysUtils, WinTypes, WinProcs, Messages, Classes, Graphics, Controls, Forms, Dialogs, StdCtrls, DBCtrls, DB, DBTables, Grids, DBGrids, ExtCtrls, Mask, Spin, ComCtrls;
type
TForm1 = class(TForm)
PLeft: TPanel;
DataSource1: TDataSource;
Table1: TTable;
Table1Dep: TStringField;
Table1Proisv: TBooleanField;
Table3: TTable;
Table3Dep: TStringField;
Table3Proisv: TBooleanField;
DataSource3: TDataSource;
DBEdit1: TDBEdit;
DataSource2: TDataSource;
Table2: TTable;
Table2Dep: TStringField;
Table2Fam: TStringField;
Table2Nam: TStringField;
Table2Par: TStringField;
Table2Year_b: TSmallintField;
Table2Sex: TBooleanField;
CheckBox1: TCheckBox;
PanelTop: TPanel;
LabelMain: TLabel;
PanelDep: TPanel;
PanelTyp: TPanel;
PanelPers: TPanel;
TPers: TDBGrid;
Table2Age: TSmallintField;
Table2Photo: TGraphicField;
Button2: TButton;
PageControl1: TPageControl;
TabSearch: TTabSheet;
TabEdit: TTabSheet;
RGF: TRadioGroup;
Button1: TButton;
LabelAge: TLabel;
LabelMin: TLabel;
SEmin: TSpinEdit;
LabelMax: TLabel;
SEmax: TSpinEdit;
RSex: TRadioGroup;
LabelSearch: TLabel;
PanelFam: TPanel;
Edit1: TEdit;
LabelDep: TLabel;
CBEDep: TComboBox;
LabelFam: TLabel;
EFam: TEdit;
LabelNam: TLabel;
ENam: TEdit;
EPar: TEdit;
LabelYear: TLabel;
SEYear: TSpinEdit;
RGSex: TRadioGroup;
BPost: TButton;
LabelPar: TLabel;
DBNavigator1: TDBNavigator;
Table2Charact: TMemoField;
BInsert: TButton;
BDelete: TButton;
CBDep: TComboBox;
procedure CBDepChange(Sender: TObject);
procedure FormCreate(Sender: TObject);
procedure Table2CalcFields(DataSet: TDataset);
procedure Edit1Change(Sender: TObject);
procedure CheckBox1Click(Sender: TObject);
procedure BPostClick(Sender: TObject);
procedure RGFClick(Sender: TObject);
procedure Button2Click(Sender: TObject);
procedure PageControl1Change(Sender: TObject);
procedure Table2AfterScroll(DataSet: TDataSet);
procedure Table2BeforePost(DataSet: TDataSet);
procedure BInsertClick(Sender: TObject);
procedure BDeleteClick(Sender: TObject);
procedure FormDestroy(Sender: TObject);
private{ Private declarations }
public { Public declarations }
end;
var
Form1: TForm1;
const ChangePhoto:boolean=false;
implementation
{$R *.DFM}
uses udba2;
var Year, Month, Day: Word;
const CanPost:boolean=false;
procedure TForm1.CBDepChange(Sender: TObject);
begin
with Table2 do
if CBDep.ItemIndex = CBDep.Items.Count-1 then
begin
MasterFields := '';
IndexFieldNames := 'Fam;Nam;Par';
DBEdit1.DataSource := nil;
end
else
begin
MasterFields := 'Dep';
IndexFieldNames := 'Dep;Fam;Nam;Par';
DBEdit1.DataSource := DataSource1;
Table1.FindNearest([CBDep.Text]);
end;
{Передача фокуса таблице Tpers, иначе в ней
не отразятся изменения}
Tpers.SetFocus;
end;
procedure TForm1.FormCreate(Sender: TObject);
begin
{Заполнение ComboBox CBdep и CBEDep именами отделов}
DecodeDate(Date,Year,Month,Day);
Table1.Active := true;
Table1.First;
CBDep.Clear;
CBEDep.Clear;
while not Table1.eof do
begin
CBDep.Items.Add(Table1Dep.AsString);
CBEDep.Items.Add(Table1Dep.AsString);
Table1.Next;
end;
CBdep.Items.Add('все отделы');
CBDep.ItemIndex:=0;
CBEDep.ItemIndex:=0;
Table1.First;
Table2.Active := true;
Table3.Active := true;
PageControl1.ActivePage := TabSearch;
end;
procedure TForm1.Table2CalcFields(DataSet: TDataset);
begin
table2Age.value:=Year-table2year_b.Value;
end;
procedure TForm1.Edit1Change(Sender: TObject);
begin
if CBdep.Text = 'все отделы'
then Table2.FindNearest([Edit1.Text])
else Table2.FindNearest([CBdep.Text,Edit1.Text]);
end;
procedure TForm1.CheckBox1Click(Sender: TObject);
begin
Table2Dep.Visible := CheckBox1.Checked;
end;
procedure TForm1.BPostClick(Sender: TObject);
var s:string;
const s1=',';
begin
s:='';
if Table2Dep.AsString <> CBEDep.Text
then s := 'отдел';
if Table2Fam.AsString <> EFam.Text
then begin
if s <> '' then s := s + s1;
s := s + ' фамилию';
end;
if Table2Nam.AsString <> ENam.Text
then begin
if s <> '' then s := s + s1;
s := s + ' имя';
end;
if Table2Par.AsString <> EPar.Text
then begin
if s <> '' then s := s + s1;
s := s + ' отчество';
end;
if Table2Year_b.AsInteger <> SEYear.Value
then begin
if s <> '' then s := s + s1;
s := s + ' год рождения';
end;
if Table2Sex.AsBoolean <> (RGSex.ItemIndex = 0)
then begin
if s <> '' then s := s + s1;
s := s + ' пол';
end;
if Form2.DBMemo1.Modified
then begin
if s <> '' then s := s + s1;
s := s + ' характеристику';
end;
if ChangePhoto
then begin
if s <> '' then s := s + s1;
s := s + ' фотографию';
end;
if s <> '' then if Application.MessageBox(PChar('Действительно хотите изменить '+s+'?'),
'Подтвердите сохранение изменений', MB_YESNOCANCEL+MB_ICONQUESTION) = IDYES
then begin
Table2.Edit;
Table2Dep.AsString := CBEDep.Text;
Table2Fam.AsString := EFam.Text;
Table2Nam.AsString := ENam.Text;
Table2Par.AsString := EPar.Text;
Table2Year_b.AsInteger := SEYear.Value;
Table2Sex.AsBoolean := (RGSex.ItemIndex = 0);
CanPost := true;
Table2.Post;
CanPost := false;
Form2.DBMemo1.Modified := false;
ChangePhoto:=false;
end;
end;
procedure TForm1.RGFClick(Sender: TObject);
var s:string[50];
begin
s:='';
Case RGF.ItemIndex of
1,2: s:='(Year_b<='+IntToStr(Year-SEmin.Value) +')and(Year_b>='+IntToStr(Year-SEmax.Value)+')';
end;
Case RGF.ItemIndex of
1,3: begin
if s<>'' then s:=s+'and';
if RSex.ItemIndex=0
then s:=s+'(Sex=true)'
else s:=s+'(Sex=false)';
end;
end;
Table2.Filter := s;
Table2.Filtered := (RGF.ItemIndex > 0);
end;
procedure TForm1.Button2Click(Sender: TObject);
begin
If not Form2.Visible then Form2.Show;
end;
procedure TForm1.PageControl1Change(Sender: TObject);
begin
if PageControl1.ActivePage = TabEdit
then begin
Form2.DBMemo1.ReadOnly := false;
Table2AfterScroll(Table2);
end
else Form2.DBMemo1.ReadOnly := true;
end;
procedure TForm1.Table2AfterScroll(DataSet: TDataSet);
begin
if PageControl1.ActivePage = TabEdit
then begin
RGF.ItemIndex := 0;
CBEDep.ItemIndex:=CBEDep.Items.IndexOf(Table2Dep.AsString);
EFam.Text := Table2Fam.AsString;
ENam.Text := Table2Nam.AsString;
EPar.Text := Table2Par.AsString;
SEYear.Value := Table2Year_b.AsInteger;
if Table2Sex.AsBoolean
then RGSex.ItemIndex := 0
else RGSex.ItemIndex := 1;
end
end;
procedure TForm1.Table2BeforePost(DataSet: TDataSet);
begin
if not CanPost
then begin
DataSet.Cancel;
Abort;
end;
end;
procedure TForm1.BInsertClick(Sender: TObject);
begin
Table2.Insert;
PageControl1Change(Self);
end;
procedure TForm1.BDeleteClick(Sender: TObject);
begin
if MessageDlg('Действительно хотите удалить запись?', mtConfirmation,[mbYes,mbNo],0) = mrYes
then Table2.Delete;
end;
procedure TForm1.FormDestroy(Sender: TObject);
begin
Table1.Active := false;
Table2.Active := false;
Table3.Active := false;
end;
end.
unit Udba2;
interface
uses
Windows, Messages, SysUtils, Classes, Graphics, Controls, Forms, Dialogs, DBCtrls, StdCtrls, ExtCtrls;
type
TForm2 = class(TForm)
DBMemo1: TDBMemo;
PPhoto: TPanel;
DBImage1: TDBImage;
procedure DBImage1Click(Sender: TObject);
private { Private declarations }
public { Public declarations }
end;
var
Form2: TForm2;
implementation
{$R *.DFM}
uses Udb2;
procedure TForm2.DBImage1Click(Sender: TObject);
begin
ChangePhoto := true;
end;
end.