Версия для печати темы
Нажмите сюда для просмотра этой темы в оригинальном формате
Форум программистов > Delphi: Базы данных и репортинг > Формирование DBTreeView на лету из даты


Автор: Rodeon 16.12.2016, 18:00
Задача: добавление приказа в базу данных, и в DBTreeView. Чтобы автоматически строило дерево ГОД - Месяц - Номер приказа. Автоматом создавало недостающие ноды.
Имеем:
база данных FireByrd.
Создана база данных, добавил поле ID_PRIKAZ по которому связь с другой базой:
Код

CREATE TABLE PRIKAZ_TREE (
    ID         INTEGER NOT NULL,
    ID_ID      INTEGER NOT NULL,
    "DISPLAY"  CHAR(20) NOT NULL,
    ID_SORT    SMALLINT NOT NULL,
    ID_PRIKAZ  INTEGER NOT NULL
);

ALTER TABLE PRIKAZ_TREE ADD CONSTRAINT PK_PRIKAZ_TREE PRIMARY KEY (ID);


Создан генератор:
Код

CREATE SEQUENCE GEN_PRIKAZ_TREE_ID;


Создан триггер-автоинкремент:
Код

CREATE OR ALTER TRIGGER PRIKAZ_TREE_BI FOR PRIKAZ_TREE
ACTIVE BEFORE INSERT POSITION 0
as
begin
  if (new.id is null) then
    new.id = gen_id(GEN_PRIKAZ_TREE_ID,1);
end


Добавленны константы:
Код

Const
  Month: array[1..12] of String = ('Январь', 'Февраль', 'Март', 'Апрель', 'Май', 'Июнь', 'Июль', 'Август', 'Сентябрь', 'Октябрь', 'Ноябрь', 'Декабрь');


Добавленны переменные:
Код

Var
  ID_return, Prymary_Node, Secondary_Node: Integer;


Собственно сама часть программы, все работает, не жалуюсь, создает дерево как с пустого места, так и если был уже год, месяц или и то и другое:
Код

begin
  Prymary_Node:=-1;
  Secondary_Node:=-1;
  MainForm.IBQuery1.Active:=False;
  MainForm.IBQuery1.SQL.Text:='select * from PRIKAZ_TREE WHERE (DISPLAY=:0)';
  MainForm.IBQuery1.Params[0].AsString:=IntToStr(YearOf(sDateEdit1.Date));
  MainForm.IBQuery1.Active:=True;
  {Если нод с таким именем есть, в нашем случае год, то получаем его ID, если нету то создаем}
  If MainForm.IBQuery1.RecordCount>0 then Prymary_Node:=MainForm.IBQuery1.FieldValues['ID'] else
  Begin
    Prymary_Node:=0;
    with MainForm.IBQuery1 do
    Begin
      SQL.Text:=('INSERT INTO PRIKAZ_TREE (ID_ID, DISPLAY, ID_SORT) VALUES (:ID_ID, :DISPLAY, :ID_SORT)');
      ParamByname('ID_ID').AsInteger := Prymary_Node;
      ParamByname('DISPLAY').AsString :=IntToStr(YearOf(sDateEdit1.Date));
      ParamByname('ID_SORT').AsInteger :=YearOf(sDateEdit1.Date);
      ExecSQL;
  {Получаем ID вновь созданного нода - год}
      SQL.Text:=('select gen_id(GEN_PRIKAZ_TREE_ID,0) from rdb$database');
      Open;
      ID_return:=FieldByName('GEN_ID').AsInteger;
      Close;
  {Сразу создаем месяц, так как его не могло быть если нет года}
      SQL.Text:=('INSERT INTO PRIKAZ_TREE (ID_ID, DISPLAY, ID_SORT) VALUES (:ID_ID, :DISPLAY, :ID_SORT)');
      ParamByname('ID_ID').AsInteger := ID_return;
      ParamByname('DISPLAY').AsString :=Month[MonthOf(sDateEdit1.Date)];
      ParamByname('ID_SORT').AsInteger :=MonthOf(sDateEdit1.Date);
      ExecSQL;
  {Снова получаем ID вновь созданного нода - месяц}
      SQL.Text:=('select gen_id(GEN_PRIKAZ_TREE_ID,0) from rdb$database');
      Open;
      ID_return:=FieldByName('GEN_ID').AsInteger;
      Close;
  {Добавляем наконец номер приказа в созданный год, месяц}
      SQL.Text:=('INSERT INTO PRIKAZ_TREE (ID_ID, DISPLAY, ID_SORT) VALUES (:ID_ID, :DISPLAY, :ID_SORT)');
      ParamByname('ID_ID').AsInteger := ID_return;
      ParamByname('DISPLAY').AsString :=sEdit1.Text;
      If TryStrToInt(sEdit1.Text, i) then ParamByname('ID_SORT').AsInteger:=StrToInt(sEdit1.Text) Else ParamByname('ID_SORT').AsInteger:=0;
      ExecSQL;
    End;
  End;
  {Проверка, если нод с годом уже есть}
  If Prymary_Node>0 Then
  with MainForm.IBQuery1 do
  Begin
    Active:=False;
    SQL.Text:='select * from PRIKAZ_TREE WHERE (DISPLAY=:0) AND (ID_ID=:1)';
    Params[0].AsString:=Month[MonthOf(sDateEdit1.Date)];
    Params[1].AsInteger:=Prymary_Node;
    Active:=True;
    If RecordCount>0 then
    Begin
      Prymary_Node:=MainForm.IBQuery1.FieldValues['ID'];
      {Если есть месяц, год добавляем номер приказа}
      SQL.Text:=('INSERT INTO PRIKAZ_TREE (ID_ID, DISPLAY, ID_SORT) VALUES (:ID_ID, :DISPLAY, :ID_SORT)');
      ParamByname('ID_ID').AsInteger := Prymary_Node;
      ParamByname('DISPLAY').AsString :=sEdit1.Text;
      If TryStrToInt(sEdit1.Text, i) then ParamByname('ID_SORT').AsInteger:=StrToInt(sEdit1.Text) Else ParamByname('ID_SORT').AsInteger:=0;
      ExecSQL;
    End else
    Begin
    {Если нет месяца - создаем месяц}
      SQL.Text:=('INSERT INTO PRIKAZ_TREE (ID_ID, DISPLAY, ID_SORT) VALUES (:ID_ID, :DISPLAY, :ID_SORT)');
      ParamByname('ID_ID').AsInteger := Prymary_Node;
      ParamByname('DISPLAY').AsString :=Month[MonthOf(sDateEdit1.Date)];
      ParamByname('ID_SORT').AsInteger :=MonthOf(sDateEdit1.Date);
      ExecSQL;
    {Получаем ID вновь созданного нода - месяц}
      SQL.Text:=('select gen_id(GEN_PRIKAZ_TREE_ID,0) from rdb$database');
      Open;
      ID_return:=FieldByName('GEN_ID').AsInteger;
      Close;
    {Добавляем наконец номер приказа в созданный месяц}
      SQL.Text:=('INSERT INTO PRIKAZ_TREE (ID_ID, DISPLAY, ID_SORT) VALUES (:ID_ID, :DISPLAY, :ID_SORT)');
      ParamByname('ID_ID').AsInteger := ID_return;
      ParamByname('DISPLAY').AsString :=sEdit1.Text;
      If TryStrToInt(sEdit1.Text, i) then ParamByname('ID_SORT').AsInteger:=StrToInt(sEdit1.Text) Else ParamByname('ID_SORT').AsInteger:=0;
      ExecSQL;
    End;
  End;


Сортировку решил добавлением еще одного поля ID_SORT. Собственно в который заносится Integer года, месяц и если возможно №приказа, если невозможно преобразовать №приказа в число, то 0.

Запрос стал:
Код

select * from PRIKAZ_TREE ORDER BY ID_SORT


Вопрос в следующем: может как-то можно все это упростить?

Powered by Invision Power Board (http://www.invisionboard.com)
© Invision Power Services (http://www.invisionpower.com)