Ввести на основании

Готовые скрипты, модули расширений, динамические библиотеки и вспомогательные утилиты.
Аватара пользователя
Владимир
Администратор
Сообщения: 653
Зарегистрирован: 10 фев 2018, 18:27
Откуда: Белгород
Контактная информация:

Ввести на основании

Сообщение Владимир » 05 сен 2019, 11:43

Ввести на основании - действие кнопки.
Создает новый документ на основании текущего, заполняет поля и копирует данные подчиненных форм (таблиц).


Изображение Изображение

Параметры и опции:

Ввести на основании - имя документа создаваемого на основании текущей записи (может быть указана текущая форма).

Заполнить поля:
  • Поле текущей формы - выбор поля предназначенного для копирования в поле формы назначения.
  • (или) Выражение - выражение, вычисляемое в контексте формы-источника. Может использоваться вместо Поля текущей формы совместно с функциями выражений. Имеет приоритет перед Полем текущей формы (если указано выражение - выбранное Поле текущей формы игнорируется)
  • Поле формы назначения - выбор поля в форме назначения для помещения в него значения Поля текущей формы или результата Выражения.
Копировать данные таблиц:
  • Табл.-источник - выбор таблицы текущей формы.
  • Поле - выбор полей текущей формы для копирования в таблицу назначения.
  • Табл. назначения - выбор таблицы формы назначения.
  • Поле - выбор полей формы назначения
Вычислить выражение в форме назначения - заполненное выражение будет вычислено в контексте формы назначения.

Собственный заголовок окна - опция позволяет установить собственный заголовок для окна документа вводимого на основании.

Цикличный ввод на основании - при установке флага инициируется добавление документа по принципу "один за другим" после сохранения предыдущего. При нажатии "Отмена" или закрытии формы крестиком - цикл добавления записей прекращается.
Код расширенияПоказать

Код: Выделить всё

{@module
author=Develop-Soft [ https://forum.develop-soft.ru ]
version=2.0
description=Типовые учетные операции
Действия:
1. Ввести на основании - действие кнопки. Создает новый документ на основании
текущего, заполняет поля и копирует данные таблиц (поддерживается 2 таблицы).

Изменения:
v 1 от 05.09.2019
  - выход первой версии
v 1.1 от 13.09.2019
  - добавлен параметр "Цикличный ввод"
v 2.0b от 15.09.2019
  - В "заполнить поля" добавлено поле ввода выражения (вычисляется в форме-источнике).
  - Добавлено неограниченное количество копируемых таблиц
  - Добавлено поле ввода выражения для вычисления в форме назначения.
v 2.0rc от 16.09.2019
  - Добавлено "После сохранения документа" (перейти к новой записи или остаться в текущей)
v 2.0 от 25.01.2020
    - Исправлена ошибка зависания записи в режиме редактирования
    - Добавлена проверка обязательных полей
    - Добавлен алгоритм перехода к созданной записи (если закладка целевой формы
  была закрыта - она открывается и выполняется переход)
...
@}

{@action
ID=71652B46-73B9-4504-9664-E5B6815B4657
Target=button
OrigName=EnterOnBasis
Name=Ввести на основании
Group=Типовые учетные операции
UI=<ui>
<form name="dest_frm" caption="Ввести на основании:" required="1"/>
<grid name="_fldgrid" caption="Заполнить поля">
    <field name="src_fld" caption="Поле текущей формы"
    filter="text;number;date;time;object;checkbox,counter"/>
   <expr name="expr" caption="(или) Выражение" />
    <field name="dest_fld" caption="Поле назначения" source="dest_frm"
    filter="text;number;date;time;object;checkbox"/>
  </grid>
    <divider caption="Копировать данные таблиц:"/>
 <grid name="fields2" caption="">
  <childform name="_src2" caption="Табл.-источник" />
  <field name="destfield2" caption="Поле" source="_src2"
    filter="text;number;date;time;object;checkbox" required="1"/>
  <childform name="_dest2" caption="Табл. назначения" source="dest_frm" />
    <field name="srcfield2" caption="Поле" source="_dest2"
    filter="text;number;date;time;object;checkbox" required="1"/>
  </grid>
  <expr name="DstFmExpr" caption="Вычислить выражение в форме назначения:" source="dest_frm"/>
  <divider caption="Дополнительно:"/>
  <text name="_FName" Caption="Собственный заголовок окна">
  <checkbox name="circle" caption="Цикличный ввод на основании">
  <list name="afterpost" caption="После сохранения документа:"
  items="Оставаться в текущей записи;Перейти к созданной записи"
  defaultvalue="Оставаться в текущей записи"/>
  <divider/>
</ui>
Description=
<b>Ввести на основании - действие кнопки.<br>Создает новый документ на основании
текущего, заполняет поля и копирует данные подчиненных форм (таблиц)</b><br><br><br>
<b>Параметры и опции:</b><br><br>
<b>Ввести на основании</b> - имя документа создаваемого на основании текущей
записи (может быть указана текущая форма).
<br><br>
<b>Заполнить поля:</b><br><br>
<ul>
<li><b>Поле текущей формы</b> - выбор поля предназначенного для копирования в
поле формы назначения.</li>
<li><b>(или) Выражение</b> - выражение, вычисляемое в контексте формы-источника.
 Может использоваться вместо Поля текущей формы совместно с функциями выражений.
  Имеет приоритет перед Полем текущей формы (если указано выражение - выбранное
  Поле текущей формы игнорируется)</li>
<li><b>Поле формы назначения</b> - выбор поля в форме назначения для помещения
в него значения Поля текущей формы или результата Выражения.</li>
</ul><br><br>
<b>Копировать данные таблиц:</b> <br><br>
<ul>
<li><b>Табл.-источник</b> - выбор таблицы текущей формы.</li>
<li><b>Поле</b> - выбор полей текущей формы для копирования в таблицу
назначения.</li>
<li><b>Табл. назначения</b> - выбор таблицы формы назначения.</li>
<li><b>Поле</b> - выбор полей формы назначения</li>
</ul><br><br>
<b>Вычислить выражение в форме назначения</b> - заполненное выражение будет
вычислено в контексте формы назначения.<br><br>
<b>Собственный заголовок окна</b> - опция позволяет установить собственный
заголовок для окна документа вводимого на основании.<br><br>
<b>Цикличный ввод на основании</b> - при установке флага инициируется добавление
 документа по принципу "один за другим" после сохранения предыдущего.
 При нажатии "Отмена" или закрытии формы крестиком - цикл добавления записей
 прекращается.
@}

var Old_DstFmEWOS:TNotifyEvent;
    CustomFormName:string;


procedure FillTable(DstFm: TdxForm; SourceTable, DestTable: String; TablesFields: TVariantArray2d);
var
SrcTbl, DestTbl: TdxForm;
i: Integer;
src, dest: String;
begin
if (SourceTable = '') or (DestTable = '') or (Length(TablesFields) = 0)
then Exit;
SrcTbl := Self.Forms[SourceTable];
DestTbl := DstFm.Forms[DestTable];
SrcTbl.DisableControls;
SrcTbl.MoveFirst;

  try
  while not SrcTbl.EOF do
  begin
    DestTbl.Append;
    for i := 0 to Length(TablesFields) - 1 do
    begin
      src := TablesFields[i][0];
      dest := TablesFields[i][1];
      DestTbl[dest] := SrcTbl[src];  // если  DestTbl.DisableControls то AV
    end;
    DestTbl.Post;
    SrcTbl.MoveNext;
  end;
  except
   debug('FillTable: ' + ExceptionParam);
  finally
    DestTbl.MoveFirst;
  end;
 SrcTbl.EnableControls;
end;

procedure DstFmEWOS(Sender: TObject);
var Ew:TEditWindow;
    S:string;
begin
if Old_DstFmEWOS<>nil then Old_DstFmEWOS(Sender);
Ew := TEditWindow(Sender);
if Trim(CustomFormName)<>'' then
S := CustomFormName else
S:= Ew.Form.FormCaption;
Ew.Top:=Ew.Top+30;
Ew.Left:=Ew.Left+30;
Ew.Caption:= S + ' (Ввод на основании)';
end;











function EnterOnBasis(
    DestForm:string;
    Fields, Tables: TVariantArray2d;
    DstFmExpr,
    FName:string;
    CirceCreate:integer;
    AfterDstPost:String
    ):integer;
var
  DstFm: TdxForm;
  i,j, RecId: Integer;
  dest, expr, src: String;
  ExprResult:variant;
  ModalResult:integer;
  SL,SL2, SL3:TStringList;
  ST,STF,DT,DTF:string;
  TablesFields: TVariantArray2d;
  DstFmPageOpened:boolean;

begin
  result:=0;
  try
  Self.Enabled:=false;
  if Self.EditWindow<>nil then
  Self.EditWindow.Buttons.Enabled := false;
  if (Self.State=dsInsert) then
  begin
  MsgBox('Ввести на основании: ошибка!',
  'Для корректного "ввода на основании" необходимо предварительно сохранить запись');
  exit;
  end;
  if Self.State <> dsEdit then
  if MessageDlg('Ввести на основании: "'+DestForm+'"',
  'Необходимо перевести текущую запись в режим редактирования.'+#10#10+'Продолжить?',
  mtConfirmation,[mbYes,mbCancel]) <> mrYes then
  exit;
  if not Self.Validate then exit;
  try
    if Self.State = dsEdit then
    if EvalExpr('MODIFIEDREC',Self)=1 then
    begin
      if MessageDlg('Ввести на основании: "'+DestForm+'"',
      'Текущая запись изменилась и будет сохранена.'+#10#10+'Продолжить?',
      mtConfirmation,[mbYes,mbCancel]) = mrYes then
        Self.Post
          else
        exit;
    end;
    Self.Edit;
    CustomFormName := FName;
    DstFm := TdxForm.Create(DestForm);
    DstFm.OpenRecord(0);
    DstFm.Append;

    for i := 0 to Length(Fields) - 1 do
    begin
      src := Fields[i][0];
      expr := Fields[i][1];
      dest := Fields[i][2];
      try
        ExprResult := EvalExpr(expr,Self);
        DstFm[dest] := ExprResult;
      except
      end;
    if ExprResult=null then
      try
        DstFm[dest] := Self[src];
      except
        Continue;
      end;
    end;

SL:=TStringList.Create;
for i := 0 to Length(Tables) - 1 do
begin
ST := Tables[i][0];
STF:= Tables[i][1];
DT:= Tables[i][2];
DTF:= Tables[i][3];
SL.Values[ST+'*'+DT]:=SL.Values[ST+'*'+DT]+#13#10+STF+'/'+DTF;
end;

for i:=0 to SL.Count-1 do
  begin
    SL2:=TStringList.Create;
    SplitStr(SL.Names[i],'*',SL2);
    ST:=SL2[0];
    DT:=SL2[1];
    SL2.Free;
    SL2:=TStringList.Create;
    SL2.Text:=trim(SL.Values[SL.Names[i]]);
    SetArrayLength(TablesFields,SL2.Count);
      for j:=0 to SL2.Count-1 do
        begin
          SL3:=TStringList.Create;
          SplitStr(SL2[j],'/',SL3);
          SetArrayLength(TablesFields[j],2);
          TablesFields[j][0]:=SL3[0]
          TablesFields[j][1]:=SL3[1]
          SL3.Free;
        end;
    FillTable(DstFm, ST, DT, TablesFields);
    SetArrayLength(TablesFields,0);
    SL2.Free;
  end;
SL.Free;

    try
      EvalExpr(DstFmExpr,DstFm);
    except
    end;

    Old_DstFmEWOS:=DstFm.EditWindow.OnShow;
    DstFm.EditWindow.OnShow:=@DstFmEWOS;
    DstFm.EditWindow.ShowModal;
    if DstFm.EditWindow.ModalResult = mrOk then
    begin
      DstFm.Post;
      if DstFm.Id = Self.Id then
        begin
          if AfterDstPost='Оставаться в текущей записи' then
          begin
            RecId:=Self.Recid;
            Self.Post;
            Self.Refresh;
            Self.GotoRecord(RecId);
            Self.Edit;
          end
          else
           begin
             Self.Post;
             if Self.EditWindow<>nil then
             Self.EditWindow.Close;
             Self.Refresh;
             Self.MoveLast;
           end;
        end
      else // not DstFm.Id = Self.Id
        begin
        RecId:=DstFm.Recid;

        Self.Post;
        if Self.EditWindow<>nil then
        Self.EditWindow.Close;
        DstFmPageOpened := false;
        for i:=0 to MainWindow.Pages.PageCount-1 do
          begin
            if MainWindow.FormViews[i].Form.id = DstFm.Id then
            begin
              MainWindow.FormViews[i].Form.Refresh;
              if AfterDstPost='Перейти к созданной записи' then
              begin
                MainWindow.FormViews[i].Form.GoToRecord(RecId);
                MainWindow.Pages.ActivePageIndex:=i;
                MainWindow.FormViews[i].Grid.SetFocus;
              end;
              DstFmPageOpened := true;
              Break;
            end;
          end;
          if not DstFmPageOpened then
          begin
           MainWindow.Pages.ActivePage :=
           MainWindow.CreatePage(DstFm.FormCaption,vtDefault); // Фак...
           MainWindow.FormViews[MainWindow.Pages.ActivePageIndex].Form.GoToRecord(RecId);
           MainWindow.FormViews[MainWindow.Pages.ActivePageIndex].Grid.SetFocus;
          end;
        end;
    result := DstFm.Recid;
    end

    else
    begin
    DstFm.Cancel;
    result := 0;
    end;
  finally
    if DstFm<>nil then
    begin
      ModalResult:=DstFm.EditWindow.ModalResult;
      DstFm.Free;
      DstFm:=nil;
    end;
    CustomFormName := '';
    if (ModalResult=mrOk) and (CirceCreate=1) then
      EnterOnBasis(
      DestForm,
      Fields, Tables,
      DstFmExpr,
      FName,
      CirceCreate,
      AfterDstPost
      );
    ModalResult:=0;
  end;
finally
Self.Enabled:=true;
if Self.EditWindow<>nil then
Self.EditWindow.Buttons.Enabled := true;
end;
end;

Скачать:
Ввести на основании v2.0.epas
Обновление от 25.01.2020
(13.17 КБ) 69 скачиваний
Список изменений
Предыдущие версииПоказать
Ввести на основании v2.0b.epas
(10.44 КБ) 172 скачивания
Ввести на основании v1.1.epas
(8.97 КБ) 127 скачиваний
Ввести на основании v1.0.epas
(7.92 КБ) 154 скачивания

Демо

Похожие расширения: "Заполнить по"


Поддержка проекта

Теги:

Аватара пользователя
Владимир
Администратор
Сообщения: 653
Зарегистрирован: 10 фев 2018, 18:27
Откуда: Белгород
Контактная информация:

Ввести на основании

Сообщение Владимир » 13 сен 2019, 18:22

Обновление:
v1.1 - добавлен "Цикличный ввод". (подробности в шапке).

Добавлены примеры в демобазе:
- Создание нескольких документов вводов на основании в одной кнопке.
- Вариант выставления счета клиенту (из формы справочника "Клиенты")
- Ввод на основании с условием (если не пустая таблица товаров в документе-основании).
- Цикличный ввод товара.

Аватара пользователя
Владимир
Администратор
Сообщения: 653
Зарегистрирован: 10 фев 2018, 18:27
Откуда: Белгород
Контактная информация:

Ввести на основании

Сообщение Владимир » 15 сен 2019, 22:06

Обновление:
v1.1:
  • Исправлены некоторые ошибки.
v2.0 beta:
(Версия несовместима со старыми модулями. Требуется повторная установка и настройка.)
  • В "заполнить поля" добавлено поле ввода выражения (вычисляется в форме-источнике).
  • Добавлено неограниченное количество копируемых таблиц
  • Добавлено поле ввода выражения для вычисления в форме назначения.
  • Добавлен вывод результата (1 - если запись "документа на основании" была сохранена и 0 - не сохранена)
Изображение

Аватара пользователя
Владимир
Администратор
Сообщения: 653
Зарегистрирован: 10 фев 2018, 18:27
Откуда: Белгород
Контактная информация:

Ввести на основании

Сообщение Владимир » 25 янв 2020, 14:14

Обновление:
v2.0:
  • Исправлена ошибка зависания записи в режиме редактирования
  • Добавлена проверка обязательных полей
  • Добавлен алгоритм перехода к созданной записи (если закладка целевой формы
    была закрыта - она открывается и выполняется переход)

Ответить