Программное добавление реквизитов на форму документа. Без изменения самой формы.

Применимо к обычным формам. Методика не требует изменения формы, актуально для полностью типовых форм.

Долгое время искал способ программного добавления реквизитов на обычную форму. Не хотелось изменять и включать возможность редактирования у типовой формы, так как это вызывает трудности при обновлении типовой конфигурации. Но в виду того что надо было добавить один — два реквизита в один — два типовых документам, острой необходимости не было. И вот потребовалось добавить в более чем 30 документах реквизит «Подразделение организации» с типом справочник «Подразделения организаций», справочник типовой.

 

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

 

Вкраце последовательность действий:

1. Выводиться форма

2. Увеличиваем высоту формы на общую высоту добавляемых реквизитов  (некая высота — n).

3. Обратно уменьшаем высоту растягиваемых элементов на n, а остальные элементы формы, которые прикреплены к нижнему краю, смещаем на n вверх.

4. Добавляем новые реквизиты, устанавливаем их свойства и привязки. Profit!

 На форме появляются новые реквизиты, привязки корректно отрабатывают, так как мы их не трогали и не меняли. Раньше моя ошибка заключалась в том что я пытался отключить привязку элементов к нижней границе формы, а после добавления новых элементов, пытался их восстановить. В итоге формы нещадно глючили, ломались привязки. А решение оказалось на поверхности. Не надо трогать привязки, все корректируется высотой и положением самого элемента.

 

З.Ы. Возможно будут проблемы с элементами которые привязаны к нижней границе через другой элемент, но в моих 30 документах такого не наблюдалось. В крайнем случае можно сохранить параметры всех элементов на форме: верхняя точка и высота элемента. И после увеличения высоты формы восстановить эти параметры.


Примеры кода, думаю комментариев будет достаточно:

Функция ВыводитьДополнительныеРеквизиты(ДокументОбъект, ФормаДокумента)

    Результат = Ложь;

    Если ДокументОбъект.Метаданные().Реквизиты.Найти(«ПодразделениеОрганизации») <> Неопределено Тогда

        Для Каждого Стр из ФормаДокумента.ЭлементыФормы Цикл

            Если Стр.Данные = «ПодразделениеОрганизации» Тогда

                Возврат Результат;

            КонецЕсли;

        КонецЦикла;

        Результат = Истина;

    КонецЕсли;

    Возврат Результат;

КонецФункции

Процедура ВыводДополнительныхРеквизитов(ДокументОбъект, ФормаДокумента) Экспорт

    // Проверка на наличие дополнительных реквизитов

    Если Не ВыводитьДополнительныеРеквизиты(ДокументОбъект, ФормаДокумента) Тогда Возврат КонецЕсли;

    // Вывод или сохранение дополнительных реквизитов

    // Если элемент формы существует то сохраняем значение

    Элемент = ФормаДокумента.ЭлементыФормы.Найти(«_ПодразделениеОрганизации»);

    Если Элемент = Неопределено Тогда

        ВысотаОбщаяДобавляемыхЭлементовПоВертикали = 27; // Общая высота всех добавляемых элементов

        ВысотаОдногоЭлемента = 19;

        ВысотаНижнейПанели = 0; // будет вычислятся если нижняя панель есть

        РасстояниеМеждуЭлементами = 8;

        // Увеличение высоты

        ФормаДокумента.Высота = ФормаДокумента.Высота + ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

        // Обработка элементов формы

        Для Каждого Стр из ФормаДокумента.ЭлементыФормы Цикл

            _ПервыйЭлемент = Неопределено;

            _ГраницаПервогоЭлемента = Неопределено;

            _ВторойЭлемент = Неопределено;

            _ГраницаВторогоЭлемента = Неопределено;

            Стр.ПолучитьПривязку(ГраницаЭлементаУправления.Низ, _ПервыйЭлемент, _ГраницаПервогоЭлемента, _ВторойЭлемент, _ГраницаВторогоЭлемента);

            Если _ПервыйЭлемент = ФормаДокумента.Панель И _ГраницаПервогоЭлемента = ГраницаЭлементаУправления.Низ Тогда

                // Исключаем нижнюю панель команд

                Если ВРЕГ(СокрЛП(Стр.Имя)) = «ОСНОВНЫЕДЕЙСТВИЯФОРМЫ» Тогда

                    ВысотаНижнейПанели = Стр.Высота;

                    Продолжить;

                КонецЕсли;

                // У растягиваемых элементов уменьшаем высоту, а элементы с фиксированной высотой смещаем вверх

                Стр.ПолучитьПривязку(ГраницаЭлементаУправления.Верх, _ПервыйЭлемент, _ГраницаПервогоЭлемента, _ВторойЭлемент, _ГраницаВторогоЭлемента);

                Если _ПервыйЭлемент = ФормаДокумента.Панель И _ГраницаПервогоЭлемента = ГраницаЭлементаУправления.Низ Тогда

                    Стр.Верх = Стр.Верх ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

                Иначе

                    Стр.Высота = Стр.Высота ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

                КонецЕсли;

            КонецЕсли;

        КонецЦикла;

        ПоложениеПервогоЭлемента = ФормаДокумента.Высота ВысотаОбщаяДобавляемыхЭлементовПоВертикали ВысотаНижнейПанели ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

        // Создание заголовка

        Элемент = ФормаДокумента.ЭлементыФормы.Добавить(Тип(«Надпись»), «_ЗаголовокПодразделениеОрганизации», Истина, ФормаДокумента.Панель);

        Элемент.Заголовок = «Подразделение организации:»;

        // Настройка

        Элемент.Лево = РасстояниеМеждуЭлементами;

        Элемент.Верх = ПоложениеПервогоЭлемента;

        Элемент.Высота = ВысотаОдногоЭлемента;

        Элемент.Ширина = 155;

        // Установка привязок

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Верх, ФормаДокумента.Панель, ГраницаЭлементаУправления.Низ);

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Низ, ФормаДокумента.Панель, ГраницаЭлементаУправления.Низ);

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Право, ФормаДокумента.Панель, ГраницаЭлементаУправления.Лево);

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Лево, ФормаДокумента.Панель, ГраницаЭлементаУправления.Лево);

        // Создание поле ввода

        Элемент = ФормаДокумента.ЭлементыФормы.Добавить(Тип(«ПолеВвода»), «_ПодразделениеОрганизации», Истина, ФормаДокумента.Панель);

        Элемент.ТипЗначения = Новый ОписаниеТипов(«СправочникСсылка.ПодразделенияОрганизаций»);

        Элемент.Данные = «ПодразделениеОрганизации»;

        // Настройка

        Элемент.Лево = РасстояниеМеждуЭлементами + 155 + РасстояниеМеждуЭлементами;

        Элемент.Верх = ПоложениеПервогоЭлемента;

        Элемент.Высота = ВысотаОдногоЭлемента;

        Элемент.Ширина = ФормаДокумента.Ширина — (РасстояниеМеждуЭлементами * 3) — 155;

        // Установка привязок

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Верх, ФормаДокумента.Панель, ГраницаЭлементаУправления.Низ);

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Низ, ФормаДокумента.Панель, ГраницаЭлементаУправления.Низ);

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Право, ФормаДокумента.Панель, ГраницаЭлементаУправления.Право);

        Элемент.УстановитьПривязку(ГраницаЭлементаУправления.Лево, ФормаДокумента.Панель, ГраницаЭлементаУправления.Лево);

        // Заполнение значения

        Если ДокументОбъект.ЭтоНовый() Тогда

            Элемент.Значение = УправлениеПользователями.ПолучитьЗначениеПоУмолчанию(глЗначениеПеременной(«глТекущийПользователь»), «ОсновноеПодразделениеОрганизации»);

        КонецЕсли;

    КонецЕсли;

КонецПроцедуры

18 Comments

  1. adhocprog

    Пробежался глазами, не понял, куда код вставлять? 🙂

    Сам таким пользуюсь, но у меня код в самой форме.

    Reply
  2. panika

    В каждой типовой форме в предопределенной процедуре «ПриОткрытии» есть вызов процедуры из общего модуля «РаботаСДиалогами.УстановитьЗаголовокФормыДокумента()» в ней и добавляем вызов процедуры ВыводДополнительныхРеквизитов(). В этой процедуре в самом начале производится проверка (функция «ВыводитьДополнительныеРеквизиты») нужен ли вывод дополнительных реквизитов.

    Reply
  3. TrinitronOTV

    списибо автору для данный материал, пригодиться в практической работе

    Reply
  4. sstar90

    Спасибо

    Reply
  5. Vyatcheslav

    очень актуально. давно ждал подобного примера. А то франчи понаделали правок в типовые формы, а обновлять мне. )) Буду переписывать.

    Reply
  6. daho

    Да полезная информация. Спасибо!!

    Reply
  7. q_i

    Спасибо за публикацию!

    вот это скорее всего не нужно:

    Элемент.ТипЗначения = Новый ОписаниеТипов(«СправочникСсылка.ПодразделенияОрганизаций»);

    т.к.

    ТипЗначения (ValueType)



    Тип: ОписаниеТипов.

    Содержит объект, описывающий допустимые типы значений для элемента управления.



    Примечание:

    Для элементов управления, не связанных с данными, свойство доступно для записи.

    Для элементов управления, связанных с данными, свойство доступно только для чтения.

    Reply
  8. Sabfir

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

    Reply
  9. Sabfir

    (2) Подскажите, пожалуйста.

    В вашем коде приведен вот такой код:

    ПоложениеПервогоЭлемента = ФормаДокумента.Высота — ВысотаОбщаяДобавляемыхЭлементовПоВертикали — ВысотаНижнейПанели — ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

    Почему мы дважды отнимаем ВысотаОбщаяДобавляемыхЭлементовПоВертикали?

    Ведь логично будет так: высота формы — высота нижней панели — высота самого реквизита.

    То есть:

    ПоложениеПервогоЭлемента = ФормаДокумента.Высота — ВысотаНижнейПанели — ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

    Почему дважды отнимается высота добавленного реквизита не понятно, хотя работает 🙂

    Reply
  10. StepanZaytsev

    нельзя ли было так сделать, за место перебора всех элементов формы.


    Для Каждого Стр из ФормаДокумента.ЭлементыФормы Цикл

    Если Стр.Данные = «ПодразделениеОрганизации» Тогда

    Возврат Результат;

    КонецЕсли;

    КонецЦикла;

    а просто написать Если ФормаДокумента.ЭлементыФормы.Найти(«ПодразделениеОрганизации»)<> Неопределенно Тогда Возврат Результат; КонецЕсли;

    Reply
  11. Nickon

    Инересно, а что делать с этим реквизитом. Да, добавился он на форму. Но данные в нем не сохраняются. Закрыл документ,открыл — данных нет. В чем его «нужность»?

    Reply
  12. validat

    Интересный подход к модификации формы. Было бы хорошо если результат сохранялся на форме.

    Reply
  13. buganov

    (13) AndrewKiev, но ведь весь колхоз делается на форме? Или я не прав? Все равно ковырять изменения формы. Я лично новые реквизиты когда добавляю, помечаю их пурпурным цветом, чтобы после меня было проще ориентироваться в изменениях в диалоге. И это вам известно, что там и как делается, а придет после вас программист и будет думать, что же это за колдунство такое. Да еще в 30 доках!

    Reply
  14. AndrewKiev

    (11) Nickon,

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

    Reply
  15. yermak

    Спасибо! Пригодилось!

    Reply
  16. Asenka

    Реквизит на форму вышеуказанным методом добавила. Можно ли как-то вызвать процедуру «ПриИзменении» для данного реквизита формы?

    Reply
  17. foxey

    (16) Чтобы прописать обработчик события новому реквизиту, используйте метод УстановитьДействие.

    Например,

    НашЭлемент.УстановитьДействие(«ПриИзменении», Новый Действие(«ФлагЗапретРедактированияНажатие»));

    Ну и, соответственно, в модуле формы надо прописать код обработчика:

    Процедура ФлагЗапретРедактированияНажатие(Элемент)
    ….
    КонецПроцедуры

    Reply
  18. Xytras

    спасибо большое автору!

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *