Модуль Db_QBF.PAS, позволяющий в Delphi осуществить форму запроса для компонентов DbGrid
Предлагаю Вашему вниманию модуль 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;
beginn := 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;
beginflds := ''; { Список полей, разделенных ';'. }
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. |