Советы по Delphi

         

Модуль 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; 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.
[000069]



Содержание раздела