gifts2017

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

Опубликовал Иван Назаров (panika) в раздел Программирование - Работа с интерфейсом

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

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

 

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

 

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

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

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

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

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

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

 

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


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


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

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

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

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

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

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

            КонецЕсли;

        КонецЦикла;

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

    КонецЕсли;

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

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



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



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

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



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

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

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

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

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

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

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

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



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

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



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

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

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

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

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

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

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

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



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

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

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

                    Продолжить;

                КонецЕсли;



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

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

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

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

                Иначе

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

                КонецЕсли;



            КонецЕсли;

        КонецЦикла;



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



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

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

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



       
// Настройка

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

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

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

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



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

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

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

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

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



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

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

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

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



       
// Настройка

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

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

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

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



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

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

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

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

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



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

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

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

        КонецЕсли;



    КонецЕсли;

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

См. также

Подписаться Добавить вознаграждение
Комментарии
1. Владимир Гусев (adhocprog) 11.04.13 13:18
Пробежался глазами, не понял, куда код вставлять? :)
Сам таким пользуюсь, но у меня код в самой форме.
2. Иван Назаров (panika) 11.04.13 14:06
В каждой типовой форме в предопределенной процедуре "ПриОткрытии" есть вызов процедуры из общего модуля "РаботаСДиалогами.УстановитьЗаголовокФормыДокумента()" в ней и добавляем вызов процедуры ВыводДополнительныхРеквизитов(). В этой процедуре в самом начале производится проверка (функция "ВыводитьДополнительныеРеквизиты") нужен ли вывод дополнительных реквизитов.
3. Александр Лыткин (TrinitronOTV) 12.04.13 13:46
списибо автору для данный материал, пригодиться в практической работе
4. Сергей (sstar90) 14.04.13 11:36
5. Вячеслав Григорьев (Vyatcheslav) 17.04.13 10:34
очень актуально. давно ждал подобного примера. А то франчи понаделали правок в типовые формы, а обновлять мне. )) Буду переписывать.
6. Dmitriy (daho) 17.04.13 19:20
Да полезная информация. Спасибо!!
7. q_i 13.05.13 19:10
Спасибо за публикацию!
вот это скорее всего не нужно:
Элемент.ТипЗначения = Новый ОписаниеТипов("СправочникСсылка.ПодразделенияОрганизаций");

т.к.
ТипЗначения (ValueType)
...
Тип: ОписаниеТипов.
Содержит объект, описывающий допустимые типы значений для элемента управления.
...
Примечание:
Для элементов управления, не связанных с данными, свойство доступно для записи.
Для элементов управления, связанных с данными, свойство доступно только для чтения.
...
8. Sabfir Sabfir (Sabfir) 03.07.13 10:58
Класная статья. Было бы хорошо еще это все дело подвязать на некий регистр сведений, где бы указывалось какой реквизит на какую форму добавлять.
9. Sabfir Sabfir (Sabfir) 09.08.13 18:42
(2) panika, Подскажите, пожалуйста.
В вашем коде приведен вот такой код:
ПоложениеПервогоЭлемента = ФормаДокумента.Высота - ВысотаОбщаяДобавляемыхЭлементовПоВертикали - ВысотаНижнейПанели - ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

Почему мы дважды отнимаем ВысотаОбщаяДобавляемыхЭлементовПоВертикали?
Ведь логично будет так: высота формы - высота нижней панели - высота самого реквизита.
То есть:
ПоложениеПервогоЭлемента = ФормаДокумента.Высота - ВысотаНижнейПанели - ВысотаОбщаяДобавляемыхЭлементовПоВертикали;

Почему дважды отнимается высота добавленного реквизита не понятно, хотя работает :)
10. Stepan dffsdfsdf (StepanZaytsev) 16.12.13 14:14
нельзя ли было так сделать, за место перебора всех элементов формы.

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

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

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

КонецЕсли;

КонецЦикла;


а просто написать Если ФормаДокумента.ЭлементыФормы.Найти("ПодразделениеОрганизации")<> Неопределенно Тогда Возврат Результат; КонецЕсли;
11. Николай (Nickon) 03.08.14 18:32
Инересно, а что делать с этим реквизитом. Да, добавился он на форму. Но данные в нем не сохраняются. Закрыл документ,открыл - данных нет. В чем его "нужность"?
12. Z Lu (validat) 03.08.14 20:29
Интересный подход к модификации формы. Было бы хорошо если результат сохранялся на форме.
13. Андрей Пшинка (AndrewKiev) 08.09.14 13:56
(11) Nickon,
если я верно понял вопрос, то ответ таков: реквизит предварительно должен быть добавлен в конфигураторе, сути этого метода в том, чтобы облегчить обновление релизов. При обновлении тяжело сравнивать изменения в диалогах форм, а так их не будет
14. Александр Буганов (buganov) 08.09.14 10:19
(13) AndrewKiev, но ведь весь колхоз делается на форме? Или я не прав? Все равно ковырять изменения формы. Я лично новые реквизиты когда добавляю, помечаю их пурпурным цветом, чтобы после меня было проще ориентироваться в изменениях в диалоге. И это вам известно, что там и как делается, а придет после вас программист и будет думать, что же это за колдунство такое. Да еще в 30 доках!
15. Евгений Ермак (yermak) 30.06.16 08:26
16. А В (Asenka) 12.09.16 11:37
Реквизит на форму вышеуказанным методом добавила. Можно ли как-то вызвать процедуру "ПриИзменении" для данного реквизита формы?
17. Игорь Костюк (foxey) 23.09.16 12:29
(16) Чтобы прописать обработчик события новому реквизиту, используйте метод УстановитьДействие.
Например,
НашЭлемент.УстановитьДействие("ПриИзменении", Новый Действие("ФлагЗапретРедактированияНажатие"));

Ну и, соответственно, в модуле формы надо прописать код обработчика:
Процедура ФлагЗапретРедактированияНажатие(Элемент)
....
КонецПроцедуры

Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа