Форма для работы с рейсами – заполнение выпадающего списка данными
Для демонстрации методики заполнения выпадающего списка создадим новую форму FormFlight. В верхней части формы находиться список, который должен показывать все рейсы. Чтобы ограничить список будем показывать только рейсы, вылетающие из указанного нами аэропорта. Выбор аэропорта вылета будем осуществлять при помощи выпадающего списка ComboBoxFrom.
Разместим на форме компоненты для работы с данными
Назначение запроса | Компонент доступа к данным (IBQuery) | Компонент модификации данных (IBUpdateSQL) | Компонент источник данных DataSource |
Находит аэропорты, из которых совершаются рейсы | IBQueryAP | ||
Извлекает данные по рейсам (название авиакомпании, номер авиалиний, дата вылета, тип самолета, название аэропортов откуда и куда) | IBQueryFl | DataSourceFl | |
Извлекает ФИО и роль членов экипажа для выбранного рейса | IBQueryEQ | IBQueryEQ | IBUpdateSQLEQ |
Данные по личности (для Lookup полей) | IBQueryPr |
Для начала обеспечим первоначальное заполнение списка, для этого у формы создадим событие на создание - OnCreate (можно было также сделать событие на показ формы - OnShow). В этом событии нужно выполнить запрос, получающий все возможные аэропорты вылета. Нам нужно сохранить в нашем списке не только название аэропорта, но и его код. Для этого применим хитрый прием. Сначала напомним, что список строк (Items) может также использоваться для хранения для каждой строки ссылки на объект; осуществить это можно с помощью AddObject и свойства Objects. Обманем компонент и будем хранить не ссылки на какой – либо объект, а целые значения первичного ключа. Этого можно добиться путем преобразования целого типа в тип TObject. При использовании сохраненного значения для него нужно будет совершить обратное преобразование.
Итак, событие будет иметь следующий вид.
procedure TFormFlight.FormCreate(Sender: TObject);
Begin
ComboBoxFrom.Items.Add(' '); //вначале списка будет пустая строка
IBQueryAP.SQL.Text := 'select distinct AP.AP_CODE, AP.AP_NAME '
+ ‘from AIRPORT AP '
+ 'inner join AIRLINE AL on AP.AP_CODE =
+ 'AL.AL_AP_FROM order by AP.AP_NAME';
IBQueryAP.Open;
while not IBQueryAP.Eof do begin //вставляем в список аэропорты
ComboBoxFrom.Items.AddObject(IBQueryAP.FieldByName('AP_NAME').AsString,
TObject(IBQueryAP.FieldByName('AP_CODE').AsInteger));
IBQueryAP.Next;
end;
end;
Вначале списка будет вставлена пустая строка, при выборе которой мы должны будем получить все рейсы.
Сохраненные значения первичного ключа будут использоваться при выборе аэропорта из выпадающего списка, т.е. нам нужно создать обработчик OnClick для списка ComboBoxFrom.
Получив код аэропорта из списка, подставим его в значение параметра запроса, для того чтобы ограничить результат по аэропорту вылета. При этом если была выбрана пустая строка, ограничение должно сниматься, т.е. мы должны получить все рейсы независимо от аэропорта вылета. Для этого используем особый способ применения параметра. Запрос будет выглядеть следующим образом:
SELECT A.AL_NUM, F.FL_DATE, A.AL_AP_FROM, A.AL_AP_TO, A.AL_PL_CODE, F.FL_BRD_NUM, AL_AC_CODE
FROM AIRLINE A
INNER JOIN FLIGHT F ON A.AL_NUM = F.FL_NUM
WHERE :from IN (A.AL_AP_FROM, 0)
Как работает такая конструкция? Если параметру передать ненулевое значение, будут отобраны только те записи, у которых значение поля равно указанному значению. Если передать 0, условие будет проигнорировано, и запрос вернет все записи.
При выборе строки в ниспадающем списке подставим значение кода аэропорта в параметр запроса и переоткроем этот запрос.
procedure TFormFlight.ComboBoxFromClick(Sender: TObject);
Begin
IBQueryFl.Close;
IBQueryFl.ParamByName('from').AsInteger := Integer(ComboBoxFrom.Items.Objects[ComboBoxFrom.ItemIndex]);
IBQueryFl.Open;
end;
Как видно, мы используем преобразование типа TObject к целому типу.
В нижней части формы будет располагаться список экипажа для указанного рейса. Соответствующий запрос (IBQueryEQ) будет иметь вид
SELECT PR.PR_NAME, PR.PR_NAME2, PR.PR_NAME3, RNK.RNK_NAME,
EQ.EQ_CODE, EQ.EQ_FL_DATE, EQ.EQ_RNK_CODE, EQ.EQ_PR_CODE, EQ.EQ_FL_NUM
FROM EQUIPAGE EQ
INNER JOIN RANK RNK ON EQ.EQ_RNK_CODE = RNK.RNK_CODE
INNER JOIN PERSON PR ON EQ.EQ_PR_CODE = PR.PR_CODE
WHERE EQ.EQ_FL_NUM = :NUM AND EQ.EQ_FL_DATE = :DT
Подстановка параметров и переоткрытие запроса производится при изменение текущих значения рейса (отработке события DataChange для компонента DataSourceFl)
procedure TFormFlight.DataSourceFlDataChange(Sender: TObject;
Field: TField);
Begin
IBQueryEQ.Close;
//члены экипажа зависят от номера авиалинии и даты рейса
IBQueryEQ.ParamByName('NUM').AsString := IBQueryFlAL_NUM.Value;
IBQueryEQ.ParamByName('DT').AsDate := IBQueryFlFL_DATE.Value;
IBQueryEQ.Open;
end;
Сделаем запрос IBQueryEQ редактируемым при помощи компоненты UpdateSQL.