KAN`ский блог Мысли вслух…
  • Июл
    14

    Создание диалоговой формы «Справочник-редактор»

    Filed under: Без рубрики;

    Справочник предназначен для ввода, отображения и редактирования данных хранимым в качестве таблиц.

    Состоит из одной двухстраничной формы представленной на рисунке 1 и 2.

    При этом первая страница-закладка (рисунок 1) предназначена для отображения и выбора данных в виде компактного списка, а вторая (рисунок 2) является редактором и полностью отображает все поля таблицы, которая является источником данных. Следует избегать ненужных и непонятных цифр, а отображать данные в привычной для пользователя форме, если возможно то в графической.




    рис.1.

    рис.2.

    Как видно на рисунке 1, первая закладка состоит из не изменяемой части — кнопок управления («Первая», «Последняя» «Создать», «Редактировать», «Выбрать и закрыть») и части списка, в которой следует отображать только минимально необходимый набор полей, одно — два.

    При выводе формы на экран (событие Form1OnShow) должна выполнится следующая процедура:

    procedure TForm1.FormShow(Sender: TObject);

    begin

    DBGrid1.SetFocus; // фокус на список

    PSor:=’’; // Данная переменная определяет сортировку , о ней позднее…

    PageControl1.ActivePage:=TabSheet1; //Сделать видимой закладку 1.

    SQL4PRIKAZ; // Подготовить запрос

    end;

    При этом процедура SQL4PRIKAZ имеет следующий вид:

    procedure TForm1.SQL4PRIKAZ;

    Var TempBool: Boolean;

    begin

    case VarInt of

    01001: // Выбор запроса в зависимости от значения переменной VarInt

    begin

    Query1.SQL.Add(SQL1+ PSor);

    end;

    else // По умолчанию все записи.

    begin

    Query1.SQL.Add(SQLx+ PSor);

    end;

    end;

    TempBool:= ((Query1.IsEmpty) or not(Query1.Active)); // Изменяем переменную в зависимости от наличия ошибок и данных

    If TempBool

    then ShowMessage (‘Нет данных для отображения!’)

    else

    Begin

    DataSource1.DataSet:=Query1; // Ассоциируем данные

    DBGrid1.DataSource:=DataSource1; // и средства отображения

    End;

    DBGrid1.Visible:=not( TempBool ); // Показывает список, только если все в порядке

    PageControl1.Enable:= not( TempBool );// делаем доступными список и редактор

    End;

    Для сортировка отображаемых данных, возможно использовать обработчик события на клик по заголовку списка, в форме должна быть определена переменная хранящая порядок сортировки в примере это PSor, кроме этого в главном модуле желательно определить следующие константы DESC = ‘ DESC’; ORDERBY =’ ORDER BY ‘; для некоторой экономии памяти

    procedure TForm1.DBGrid1TitleClick(Column: TColumn);

    var TempStr : string;

    begin

    PID:=Query1.Fieldbyname(‘PID’).AsString; // запомним где находились

    TempStr:=PSor; //запомним прежней фильтр

    PSor:=ORDERBY + Column.FieldName; // создаем новый фильтр

    if TempStr=PSor then PSor:=PSor+DESC; // если фильтр не изменился, то сортируем в обратном порядке..

    SQL4PRIKAZ; // выполняем запрос

    GoToLastPos; // вернемся на прежнее место…

    end;

    Иногда для выбора данных из справочника удобно использовать следующую возможность, по нажатию клавиш на клавиатуре курсор переносится на запись содержащую введенную последовать символов, для этого на форме нам понадобится таймер (срабатывает через 3 секунды), а также мы будем обрабатывать события нажатия клавиши на списке отображения. Нам также понадобится переменная для хранения введенных символов в примере это PREPODSel:

    procedure TForm1.Timer1Timer(Sender: TObject);// срабатывание таймера

    begin

    Timer1.Enabled:=False; // останавливаем таймер

    PREPODSel:=»; // очищаем переменную

    Caption:=’Сотрудники’; //очищаем заголовок формы

    end;

    procedure TForm1.DBGrid1KeyPress(Sender: TObject; var Key: Char); // нажатие кнопок на списке

    begin

    Timer1.Enabled:=False; // перезапускаем таймер

    Timer1.Enabled:=True;

    PREPODSel:=PREPODSel+Key; // увеличиваем строку символов

    Query1.Locate(‘PREPODFIO‘, PREPODSel, [loPartialKey]); // пытаемся перейти на ближайшую похожую запись

    Caption:=’Сотрудники — ‘ + PREPODSel; // изменяем заголовок формы, чтобы то, что мы наводили

    end;

    При закрытии формы справочника, необходимо вернуть данные для этого на Form1OnClose вешаем следующий обработчик:

    procedure TForm1.FormClose(Sender: TObject; var Action: TCloseAction);

    begin

    try

    ValueN:= Query1.FieldByName(‘Name’).AsString; // «Человеческое обозначение»

    Value:= Query1.FieldByName(‘ID’).AsString; // «Обозначение машины»

    ValueDate:= Query1.FieldByName(‘Date’).AsString; // Если нужно то и дату

    except

    ValueN:= ‘-=НЕТ ДАННЫХ=-‘; // В случаи сбоя оговоренные «Пустые данные»

    Value:= ‘-1’;

    ValueDate:= DateToStr(now);

    end;

    end;

    Переменные ValueXXXX : String; должны быть определены в модуле данных, для передачи данных между формами, также как и VarIntXXXX : Integer;

    Вторая закладка, изображенная на рисунке 2, более «наворочена» и состоит из нескольких видов объектов:

    1. Поля ввода (например «ФИО»), в данное поле возможно вводить данные в одну строчку, при этом стоит ограничить максимально возможное количество символов которое возможно ввести в данное поле (Edit1.MaxLenght:=50);

    2. Поля выбора из списка (например «Уч. степень»), в данное поле нельзя непосредственно ввести данные (Edit2.ReadOnly:=True), данные в данное поле вводятся путем выбора из списка для этого на событие Edit2OnClick вешаем такой обработчик:

    procedure TForm1.Edit2Click(Sender: TObject);

    Var TVarInt, TVarInt1 : integer;

    begin

    TVarInt := VarInt; // Запоминаем старые переменные

    TVarInt1:= TVarInt1;

    VarInt:=00201; // Передача данных в вызываемую форму для определения вида SQL запроса

    form2.showmodal; // Вызов подчиненного справочника

    if Value=’-1′ // Проверяем наличие пустых данных

    then ShowMessage(‘Внимание! Ошибка передачи данных’)

    else

    Begin

    edit2.text:=ValueN; // Запись в поле понятных человеку данных

    ust:=Value; //Запись в переменную данных понятных для базы данных, переменная должна быть определена заранее, после слова implementation.

    End;

    VarInt:= TVarInt; // Восстанавливаем переменные

    VarInt1:= TVarInt1;

    SQL4PRIKAZ; // Освежаем старый запрос

    GoToLastPos; // Возвращаем указатель на прежнюю запись

    end;

    3. Группы кнопочного выбора «RadioButton» (например «Пол»);

    4. Поля ввода «Memo» (например «Адрес») для ввода данных в несколько строк, тут как и в предыдущем случаи без особенностей;

    5. Кнопки с ассоциированным редактором (например «Темы ДР») для ввода большого количества данных, которые не удобно показывать при пролистывании данных;

    Создадим еще одну форму простого редактора (состоит из MEMO и двух кнопок «ОК», «Отменить»), а вызывать его будем через следующую процедуру:

    procedure BLOBview (filed: string); // в качестве переменной передаем имя поля из которого будем брать данные

    begin

    Query2.Close; // Выбираем из Базы данных только редактируемое поле

    Query2.SQL.Clear;

    Query2.SQL.Add(‘Select ‘+filed+’ FROM PREPOD’);

    Query2.SQL.Add(‘WHERE PREPODID=’+ PREPODID);

    Query2.Open;

    IF Query1.IsEmpty // Заполняем редактор

    THEN form3.Memo1.Lines.Clear

    ELSE form3.Memo1.Text:=Query1.FieldBYNAME(filed).AsString;

    Form3.showmodal; //Показываем редактор

    If MR=mrOk then // Если в редакторе нажали «ОК»

    begin

    IF form3.Memo1.Text<>Query1.FieldBYNAME(filed).AsString //Если изменили чтото

    THEN

    begin

    Query2.Close; // обновляем поле

    Query2.SQL.Clear;

    Query2.SQL.Add( ‘Update PREPOD’ );

    Query2.SQL.Add( ‘set ‘+filed+’ =:blobfl’ );

    Query2.SQL.Add( ‘Where REPODID=’+PREPODID );

    Query2.ParamByName(‘blobfl’).AsString:=form3.Memo1.Text;

    Query2.ExecSQL;

    Transaction1.CommitRetaining;

    end;

    end;

    end;

    6. Кнопки с ассоциированным списком (например «Приказы»), обработчик точно такой же, как и для Edit2OnClick;

    7. Списки (например «Читает следующие дисциплины»), тоже самое, что и описанная форма целиком.

    Стоит также завести процедуру, которая будет обновлять содержимое (второй) закладки редактора при изменении позиции курсора в отображаемой таблице:

    procedure ReFill;

    begin

    PRIKAZID:=Query1.FieldByName(‘PRIKAZID‘).AsString; //изменяем номер редактируемой записи

    TempQuery(Query2, FORMAT(‘SELECT * FROM PRIKAZ_SEL1(%s)’,[ PRIKAZID ])); //выполнение запроса выбора одной полной записи из базы данных, PRIKAZ_SEL1 это хранимая процедура на SQL сервере

    Edit1.Text:=Query2.FieldByName(‘PRIKAZNOM’).AsString; // присвоение поля ввода (п.1.)

    Memo1.Text:=Query2.FieldByName(‘PRIKAZNM’).AsString; //присвоение MEMO (п.4.)

    Edit3.Text:=Query2.FieldByName(‘PRIKAZVIDNM‘).AsString; //присвоение поля выбора из списка в виде понятным человеку(п.2.)

    PRIKAZVID:=Query2.FieldByName(‘PRIKAZVID’).AsString; // в виде для машины

    TempQuery(Query2, FORMAT(‘SELECT * FROM PRIKAZ_ADV(%s)’,[ PRIKAZID ])); // запрос заполнения списка (п.7.)

    end;

    Дважды была использована следующая функция:

    procedure TempQuery(ADateSet:TQuery ; SQL:String ); // Данная функция просто сокращает повторяющиеся операторы.

    begin

    if ADateSet.Active then ADateSet.Close;

    ADateSet.SQL.Clear;

    ADateSet.SQL.Add(SQL);

    ADateSet.Open;

    end;

    Теперь обработка нажатия кнопок управления («первый», «последний», «предыдущий», «следующий»):

    procedure TForm1.BitBtnNClick(Sender: TObject);

    begin

    Query1.{First, Last, Prior, Next}; //Просто подставляем нужное слово

    ReFill

    end;

    Добавление новой записи:

    procedure TForm1.BitBtn6Click(Sender: TObject);

    begin

    StoredProc1.StoredProcName:=’PREPOD_INS’; // Опять процедура сервера

    StoredProc1.ExecProc;

    Transaction1.CommitRetaining;

    PREPODId:= StoredProc1.ParamByName(‘ PREPODId ‘).AsString; //Которая возражает один параметр – новый индекс

    SQL4PRIKAZ; //Обновляем запрос

    GoToLastPos; //Переходим на новый элемент

    ReFill; //перезаполняем редактор

    PageControl1.ActivePage:=TabSheet2;

    end;

    procedure GoToLastPos; //Данная процедура перемещает указатель на указанную запись

    begin

    Query1.Locate(‘PREPODID’,PREPODID, [loCaseInsensitive]);

    end;

    По нажатию кнопки «Редактировать» нужно просто выполнить PageControl1.ActivePage:=TabSheet2;

    При ручном выборе второй закладки (редактора) должно выполняться просто REFILL.

    Обновление измененной записи будет выглядеть так:

    procedure TForm1.BitBtn5Click(Sender: TObject);

    begin

    StoredProc1.StoredProcName:=’PREPOD_UPD’; // Опять процедура на сервере

    StoredProc1.Prepare; //Нужно «Предупредить» процедуру о параметрах

    if RadioButton2.Checked //Это сохранение группы кнопочного выбора «RadioButton» (п.3.)

    then StoredProc1.ParamByName(‘PREPODPOL’).AsString := ‘0’

    else StoredProc1.ParamByName(‘PREPODPOL’).AsString := ‘1’;

    StoredProc1.ParamByName(‘PREPODID’).AsString := PREPODID; //это сохранение поля выбора (п.2)

    StoredProc1.ParamByName(‘PREPODFIO’).AsString := edit1.Text; // а дальше все как обычно

    StoredProc1.ParamByName(‘PREPODDR’).AsDateTime := DateTimePicker2.DateTime;

    StoredProc1.ParamByName(‘PREPODADR’).AsString:= memo2.Text;

    StoredProc1.ExecProc; // Исполняем процедуру

    Transaction1.CommitRetaining;

    StoredProc1.UnPrepare; //Снимаем приготовление

    SQL4PRIKAZ;

    GoToLastPos

    end;

    Пример процедуры добавления записи:

    CREATE PROCEDURE PERIODEDNS_INS (

    PERIODEDNSDATE TIMESTAMP,

    PERIODEDNSTYPE INTEGER)

    AS

    DECLARE VARIABLE PERIODEDNSID INTEGER;

    BEGIN

    select MAX(PERIODEDNSID) FROM PERIODEDNS INTO :PERIODEDNSID; // можно конечно использовать триггер, но иногда нужно знать какой именно номер мы получили…

    if (PERIODEDNSID is null) then PERIODEDNSID=0;

    PERIODEDNSID=PERIODEDNSID+1;

    INSERT INTO PERIODEDNS (PERIODEDNSID,PERIODEDNSDATE,PERIODEDNSTYPE)

    VALUES (:PERIODEDNSID,:PERIODEDNSDATE,:PERIODEDNSTYPE);

    END

    Пример процедуры обновления:

    CREATE PROCEDURE PERIODEDNS_UP (

    PERIODEDNSID INTEGER,

    PERIODEDNSDATE TIMESTAMP,

    PERIODEDNSTYPE INTEGER)

    AS

    BEGIN

    UPDATE PERIODEDNS

    SET

    PERIODEDNSDATE = :PERIODEDNSDATE,

    PERIODEDNSTYPE = :PERIODEDNSTYPE

    WHERE PERIODEDNSID = :PERIODEDNSID;

    END

    Пример процедуры выбора одной строки:

    CREATE PROCEDURE PRIKAZVID_SEL1 (

    PRIKAZVIDID INTEGER)

    RETURNS (

    PRIKAZVIDPRM BLOB sub_type 0 segment size 80,

    PRIKAZVIDTEMP BLOB sub_type 0 segment size 80)

    AS

    BEGIN

    FOR SELECT PRIKAZVIDPRM,PRIKAZVIDTEMP

    FROM PRIKAZVID

    WHERE PRIKAZVIDID=:PRIKAZVIDID

    INTO :PRIKAZVIDPRM,:PRIKAZVIDTEMP

    DO

    BEGIN

    SUSPEND;

    END

    END

    Комментарии к записи Создание диалоговой формы «Справочник-редактор» отключены

Comments are closed.