Модуль, позволяющий в Delphi осуществить форму запроса для компонентов DBGrid
|
Визит министра здравоохранения (МЗ) в одну из психиатрических лечебниц. Осмотрев палаты, процедурные залы, столовую МЗ изьявляет желание проверить, как содержатся буйнопомешанные больные, опасные для окружающих. Спускаются на 1-й этаж, Главный врач (ГВ) отпирает стальную кованую дверь. За дверью длинный коридор. МЗ переходит от камеры, к камере, читает таблички, иногда заглядывает внутрь. Около одной из камер. МЗ:
- Так-так. Острая паранойя, OS/2 Warp, мания величия...
Заглядывает в окошко. Угрюмый тип, увидев МЗ, начинает метаться по камере, крича: "Ла-а-меры!!! Ла-а-а-меры!!! Суксь, Суксь МастДайная!!!"
МЗ: (Обращается к ГВ) Часто он так?
ГВ: Как новое лицо увидит, сразу приступ... Идут дальше.
МЗ: Так-так. Острая паранойя.
UNIX, мания величия... Заглядывает в окошко. Угpюмый тип, оторвавшись от созерцания собственных рук, поворачивается, и расплывшись в улыбке, изрекает: "Истинная многозадачность, полный контроль, Рулез Форева!"
МЗ: (Обращается к ГВ) Тихий какой! Выздоравливает?
ГВ: Hет, временное улучшение.
(Повернувшись к окошку) - NT!
Больной, вскочив с кровати, начинает метаться по камере, крича: "А-а-а!!! Вытесняющая многозадачность!!! Исходные тексты!!! Суксь!!! Ла-а-а-меpы!!!"
Идут дальше.
МЗ: Так-так. Острая паранойя.
Windows'95, мания величия. Заглядывает в окошко... Камера пуста. МЗ: (Hедоумённо поворачивается к ГВ)
- А где же больной? Hа процедурах?
ГВ: Видите ли... Только поймите нас правильно... Бухгалтерия у нас на Excel, личные дела больных на Access...
|
Предлагаю Вашему вниманию модуль Delphi для модального диалога,
поддерживающий форму запроса (Query By Form - QBF) для компонентов DbGrid с
возможностью получения данных от Table-компонентов (не используя
Query-компонентов).
Встроенные характеристики обмена данными в Delphi делают эту задачу намного
труднее, чем, например, в таких ресурсоемких инструментальных средствах, как
Oracle Forms (Оракловые формы). Данный модуль не такой мощный как встроенные
QBF-возможности Оракловых форм, но он заполняет значительную брешь в
функциональности Delphi.
Имейте в виду, что модуль охраняется авторским правом, как требует того
лицензия, и желательно, чтобы вы сохранили полностью весь код данного модуля.
Имейте в виду, что авторские условия допускают безвозмездное использование
данного модуля для любых целей.
unit Db_QBF; { Форма запроса базы данных }
{ Все права защищены. Автор Rick Rutt.
Данный модуль может без какой-либо оплаты быть использован в программе,
скопирован или распространен любым человеком и для любой цели, если все
копии данного модуля сохраняют это авторское уведомление.
Автор предоставляет разрешение каждому для создания производного кода, если
каждая производная работа содержит авторское уведомление и строку
"Части данной работы основываются на Db_QBF.PAS, созданным Rick Rutt."
}
{ Данный модуль обеспечивает простую, но эффективную форму запроса
для доступа приложений к базам данных, используя Borland Delphi.
Данный модуль также располагает сервисом Sort By Form (форма сортировки).
Форма запроса отображает модальное диалоговое окно с компонентом StringGrid,
содержащим искомые поля, полученные при вызове DbGrid. Пользователь может
ввести точную величину поиска для любого количества полей и использовать
функцию drag and drop (перетащи и брось) для изменения порядка сортировки полей.
(Только тех полей, которые содержат искомые величины, влияющие на сортировку.)
Когда пользователь щелкает в диалоговом окне на кнопку OK, данный модуль
модифицирует значение свойства IndexFieldNames компонента DbGrid, применяет
диапазон поиска (точные величины), и обновляет данные.
В случае, если пользователь не указывает ни одной из величин поиска,
данный модуль очищает значение свойства IndexFieldNames компонента DbGrid,
очищает диапазон поиска и обновляет данные.
Сервис Sort By Form работает аналогично, за исключением того,
что не принимает в расчет величину поиска, введенную пользователем. Пользователь
пользуется функцией drag and drop (перетащи и брось) для установления порядка
сортировки и затем нажимает на кнопку OK. Данный модуль модифицирует
значение свойства IndexFieldNames компонента DbGrid, очищает диапазон поиска
и обновляет данные.
}
{ Создайте соответствуюшую форму диалога, используя меню "File/New.../Dialogs"
и выбрав пункт "Standard Dialog Box". Разместите на форме компонент StringGrid
(Вы найдете его в палитре компонентов на странице "Additional").
Установите следующие размеры StringGrid: высота 161 и ширина 305.
И, наконец, замените исходный код новой формы (PAS-файл) данным модулем.
}
interface
uses WinTypes, WinProcs, Classes, Graphics, Forms, Controls, Buttons,
StdCtrls, ExtCtrls, Grids, DBGrids;
{ Следующие две процедуры обеспечивают механизм доступа
сервисов данного модуля.
Кнопка (или пункт меню) вызывают процедуру,
передавая ей в качестве аргумента DbGrid. (Не забудьте добавить строку
"uses Db_QBF;" в секцию реализации модуля вызова форм.)
Ограничение: компонент DbGrid должен ссылаться на DataSource,
который, в свою очередь, ссылается на DataSet, работающий с
таблицой. Данный модуль не поддерживает запрос напрямую к
DataSet ввиду отсутствия свойства IndexFieldNames.
}
procedure QueryByForm(grid: TDbGrid);
procedure SortByForm(grid: TDbGrid);
{ Следующая секция управляется средой Delphi. }
type
TdlgQBF = class(TForm)
OKBtn: TBitBtn;
CancelBtn: TBitBtn;
HelpBtn: TBitBtn;
gridQBF: TStringGrid;
procedure OKBtnClick(Sender: TObject);
procedure CancelBtnClick(Sender: TObject);
private
{ Private declarations }
public
{ Public declarations }
end;
var
dlgQBF: TdlgQBF;
implementation
{ Следующая секция пишется программистом
с помощью среды Delphi. }
uses Dialogs, Db, DbTables;
{$R *.DFM}
const
qbfRowHeight = 16;
qbfColWidth = 150;
qbfFieldLabel = '<<Поле>>';
qbfValueLabel = '<<Значение>>';
qbfQueryCaption = 'Запрос для таблицы ';
qbfSortCaption = 'Порядок сортировки для таблицы ';
var
{ Объявим некоторые элементы управления, участвующие
в QBF-диалоге при нажатии кнопки OK. }
CallingGrid: TDbGrid;
CallingMode: (modeQuery, modeSort);
procedure SetupAndShowForm;
{ Инициализация формы, обеспечивающей визуализацию
работы двух объявленных выше процедур }
var
i, j, n: integer;
tbl: TTable;
f: TField;
begin
n := CallingGrid.FieldCount;
if n <= 0 then
begin { Вместо вывода сообщений могут генерится исключительные ситуации }
MessageDlg(
'При обращении к DbGrid, модуль Db_QBF не обнаружил полей',
mtWarning, [mbOK], 0);
end
else if CallingGrid.DataSource = nil then
begin
MessageDlg(
'При обращении к DbGrid, модуль Db_QBF не обнаружил ссылки на DataSource',
mtWarning, [mbOK], 0);
end
else if CallingGrid.DataSource.DataSet = nil then
begin
MessageDlg(
'При обращении к DbGrid, модуль Db_QBF обнаружил подключенный
DataSource без ссылки на DataSet',
mtWarning, [mbOK], 0);
end
else if not (CallingGrid.DataSource.DataSet is TTable) then
begin
MessageDlg(
'При обращении к DbGrid, модуль Db_QBF обнаружил подключенный
DataSource с сылкой на DataSet, не являющийся таблицей.',
mtWarning, [mbOK], 0);
end
else
with dlgQBF.gridQBF do
begin
{ Данные свойства могут быть изменены и в режиме проектирования }
DefaultRowHeight := qbfRowHeight;
Scrollbars := ssVertical;
ColCount := 2; { Для режима сортировки необходимы две пустые колонки }
{ Данные свойства должны быть установлены во время выполнения программы }
RowCount := Succ(n);
Cells[0, 0] := qbfFieldLabel;
Options := Options + [goRowMoving];
tbl := TTable(CallingGrid.DataSource.DataSet);
if CallingMode = modeQuery then
begin
dlgQBF.Caption := qbfQueryCaption + tbl.TableName;
Cells[1, 0] := qbfValueLabel;
Options := Options + [goEditing];
{ Позволяем пользователю ввести значение }
DefaultColWidth := qbfColWidth;
end
else
begin
dlgQBF.Caption := qbfSortCaption + tbl.TableName;
Cells[1, 0] := '';
{ Ввод "пустышки" для первой, нефункциональной колонки }
Options := Options - [goEditing]; { Убираем возможность редактирования }
DefaultColWidth := (2 * qbfColWidth);
{ Этим трюком мы помещаем две пустых секции над одной колонкой }
end;
j := 0; { Фактическое число полей, показываемое пользователю }
for i := 1 to n do
begin
f := CallingGrid.Fields[Pred(i)];
if f.DataType in [ftBlob, ftBytes, ftGraphic, ftMemo, ftUnknown,
ftVarBytes] then
RowCount := Pred(RowCount) { Игнорируем неиндексируемые поля }
else
begin
Inc(j);
Cells[0, j] := f.FieldName;
Cells[1, j] := ''; { Сбрасываем искомую величину }
end;
end;
dlgQBF.HelpBtn.Visible := False; { Помощь, понятно, отсутствует... }
dlgQBF.ShowModal;
end; { with dlgQBF.gridQBF }
end;
procedure QueryByForm(Grid: TDbGrid);
begin
CallingGrid := Grid; { Сохраняем для использования при нажатии на кнопку OK }
CallingMode := modeQuery;
SetupAndShowForm;
end;
procedure SortByForm(Grid: TDbGrid);
begin
CallingGrid := Grid; { Сохраняем для использования при нажатии на кнопку ОК }
CallingMode := modeSort;
SetupAndShowForm;
end;
procedure TdlgQBF.CancelBtnClick(Sender: TObject);
begin
{ Просто прячем диалог, не делая никаких изменений в вызывающем Grid'е. }
dlgQBF.Hide;
end;
procedure TdlgQBF.OKBtnClick(Sender: TObject);
var
flds, sep, val: string;
i, n, nfld: integer;
begin
flds := ''; { Список полей, разделенных ';'. }
sep := ''; { Разделитель ';' ставится после добавления первого поля. }
nfld := 0; { Количество полей в списке. }
with dlgQBF.gridQBF do
begin
n := Pred(RowCount);
if n > 0 then
for i := 1 to n do
begin
val := Cells[1, i];
{ Значение поиска, введенное пользователем (если имеется) }
if (CallingMode = modeSort)
or (val <> '') then
begin
flds := flds + sep + Cells[0, i];
sep := ';';
nfld := Succ(nfld);
end;
end;
with CallingGrid.DataSource.DataSet as TTable do
begin
IndexFieldNames := flds;
if (CallingMode = modeSort)
or (flds = '') then
begin
CancelRange;
end
else
begin
SetRangeStart;
for i := 1 to n do
begin
val := Cells[1, i];
if val <> '' then
begin
FieldByName(Cells[0, i]).AsString := val;
end;
end;
{Устанавливаем конец диапазона так, чтобы он соответствовал его началу}
SetRangeEnd;
for i := 1 to n do
begin
val := Cells[1, i];
if val <> '' then
begin
FieldByName(Cells[0, i]).AsString := val;
end;
end;
ApplyRange;
end;
Refresh;
end; { with CallingGrid.DataSource.DataSet }
end; { with dlgQBF.gridQBF }
dlgQBF.Hide;
end;
end.
|
|