Программная доработка форм - отличный способ избежать проблем с обновлениями типовой конфигурации.
Однако во время обновления могут поменяться имена элементов формы, на которые завязаны наши программные доработки. В таком случае форма просто не откроется, и придется выводить emergency релиз. Имена элементов формы в типовых конфигурациях меняются регулярно, отследить это очень трудно. Собственно, доработка заключается в том, чтобы хранить в регистре сведений настройки доработок форм.
Создаем регистр сведений ДоработкиФорм
Типы данных:
ИдентификаторОбъектаМетаданных - справочник ИдентификаторыОбъектовМетаданных (если конфигурация не на основе БСП и такого справочника нет, то можно взять тип Строка, будет заполнятся так: Строка(ТипОбъекта)).
Используется, Видимость - Булево
ИмяФормы, ИмяЭлемента - Строка 128
Все остальные ресурсы - Строка 256
В дорабатываемой форме в процедуре ПриСозданииНаСервере добавляем одну строку:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
//...
ДоработкиФорм.ИзменитьФорму(ЭтаФорма);
КонецПроцедуры
Эта единственная строка кода, которую нужно будет поддерживать при обновлении.
Можно добавить ее в общую типовую процедуру, вызываемую из большинства форм, в таком случае форма останется полностью типовой.
Для БП 3.0 и в целом конфигураций основанных на БСП:
УправлениеПечатью.ПриСозданииНаСервере
или ДополнительныеОтчетыИОбработки.ПриСозданииНаСервере
Для УТ 10, КА 1, УПП 1: МеханизмНумерацииОбъектов.УстановитьДоступностьПоляВводаНомера - вызывается при открытии формы практически всех объектов.
Также можно обрабатывать одно событие у программно добавленных элементов вообще без изменений:
Для УТ 10, КА 1, УПП 1: практически в любой форме есть метод ДействияФормыРедактироватьНомер(Кнопка), из него идет вызов МеханизмНумерацииОбъектов.ИзменениеВозможностиРедактированияНомера; указываем его в качестве обработчика нужного события, далее в общем модуле делаем что требуется
БП 3.0: Подключаемый_ВыполнитьКомандуПечати, остальное аналогично
(thnx Роман Сюзев (sorb))
Добавляем процедуру в серверный общий модуль (у меня называется ДоработкиФорм):
// Изменение формы при создании на сервере
//
// Параметры:
// Форма - УправляемаяФорма - изменяемая форма объекта
//
Процедура ИзменитьФорму(ЭтаФорма) Экспорт
ОбъектМетаданныхФорма = Метаданные.НайтиПоПолномуИмени(ЭтаФорма.ИмяФормы);
ОбъектМетаданных = ОбъектМетаданныхФорма.Родитель();
ИдентификаторОбъектаМетаданных = Справочники.ИдентификаторыОбъектовМетаданных.ИдентификаторОбъектаМетаданных(ОбъектМетаданных);
Подстроки = СтроковыеФункцииКлиентСервер.РазложитьСтрокуВМассивПодстрок(ЭтаФорма.ИмяФормы, ".");
ИмяФормы = Подстроки[Подстроки.ВГраница()];
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| ДоработкиФорм.ИмяЭлемента,
| ДоработкиФорм.Используется,
| ДоработкиФорм.Видимость,
| ДоработкиФорм.ТипЭлемента,
| ДоработкиФорм.Родитель,
| ДоработкиФорм.ВидПоляФормы,
| ДоработкиФорм.ПутьКДанным,
| ДоработкиФорм.Заголовок,
| ДоработкиФорм.ИмяКоманды,
| ДоработкиФорм.ИмяТабличнойЧасти,
| ДоработкиФорм.ИмяСобытия,
| ДоработкиФорм.Действие,
| ДоработкиФорм.ПередЭлементом
|ИЗ
| РегистрСведений.ДоработкиФорм КАК ДоработкиФорм
|ГДЕ
| ДоработкиФорм.ИдентификаторОбъектаМетаданных = &ИдентификаторОбъектаМетаданных
| И ДоработкиФорм.ИмяФормы = &ИмяФормы
| И ДоработкиФорм.Используется";
Запрос.УстановитьПараметр("ИдентификаторОбъектаМетаданных", ИдентификаторОбъектаМетаданных);
Запрос.УстановитьПараметр("ИмяФормы", ИмяФормы);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Если ЗначениеЗаполнено(Выборка.Родитель) Тогда
Если ЭтаФорма.Элементы.Найти(Выборка.Родитель) = Неопределено Тогда
ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Не найден элемент формы " + Выборка.Родитель);
Продолжить;
КонецЕсли;
Родитель = ЭтаФорма.Элементы[Выборка.Родитель];
Иначе
Родитель = ЭтаФорма;
КонецЕсли;
Если ЗначениеЗаполнено(Выборка.ИмяКоманды) Тогда
Команда = ЭтаФорма.Команды.Найти(Выборка.ИмяКоманды);
Если Команда = Неопределено Тогда
Команда = ЭтаФорма.Команды.Добавить(Выборка.ИмяКоманды);
Команда.Действие = Выборка.ИмяКоманды;
Команда.Заголовок = Выборка.Заголовок;
Элемент = ЭтаФорма.Элементы.Добавить(Выборка.ИмяЭлемента, Тип(Выборка.ТипЭлемента), Родитель);
Элемент.ИмяКоманды = Выборка.ИмяКоманды;
Элемент.Заголовок = Выборка.Заголовок;
Иначе
Команда.Действие = Выборка.Действие;
КонецЕсли;
ИначеЕсли ЗначениеЗаполнено(Выборка.ИмяТабличнойЧасти) Тогда
ЭлементТаблица = ЭтаФорма.Элементы.Добавить(Выборка.ИмяЭлемента, Тип(Выборка.ТипЭлемента), Родитель);
ЭлементТаблица.ПутьКДанным = Выборка.ПутьКДанным;
ЭлементТаблица.Отображение = ОтображениеТаблицы.Список;
Колонки = ОбъектМетаданных.ТабличныеЧасти[Выборка.ИмяТабличнойЧасти].Реквизиты;
Для каждого Колонка Из Колонки Цикл
ЭлементКолонка = ЭтаФорма.Элементы.Добавить(Выборка.ИмяТабличнойЧасти + Колонка.Имя, Тип("ПолеФормы"), ЭлементТаблица);
ЭлементКолонка.Вид = ВидПоляФормы.ПолеВвода;
ЭлементКолонка.ПутьКДанным = "Объект." + Выборка.ИмяТабличнойЧасти + "." + Колонка.Имя;
КонецЦикла;
Иначе
Элемент = ЭтаФорма.Элементы.Найти(Выборка.ИмяЭлемента);
Если Элемент = Неопределено Тогда
Элемент = ЭтаФорма.Элементы.Добавить(Выборка.ИмяЭлемента, Тип(Выборка.ТипЭлемента), Родитель);
Элемент.Вид = ВидПоляФормы[Выборка.ВидПоляФормы];
Элемент.ПутьКДанным = Выборка.ПутьКДанным;
Элемент.Заголовок = Выборка.Заголовок;
КонецЕсли;
Элемент.Видимость = Выборка.Видимость;
Если ЗначениеЗаполнено(Выборка.ИмяСобытия) Тогда
Элемент.УстановитьДействие(Выборка.ИмяСобытия, Выборка.Действие);
КонецЕсли;
Если ЗначениеЗаполнено(Выборка.ПередЭлементом) Тогда
ЭтаФорма.Элементы.Переместить(Элемент, Родитель, ЭтаФорма.Элементы.Найти(Выборка.ПередЭлементом));
КонецЕсли;
КонецЕсли;
КонецЦикла;
КонецПроцедуры
Что позволяет такая доработка:
1) Добавление/изменение элемента формы.
2) Добавление/изменение табличной части на форме.
3) Добавление/переопределение команды формы.
При этом форма остается полностью типовой, кроме одной строки в процедуре ПриСозданииНаСервере.
В результате, если во время обновления изменились имена элементов форм, то пользователю будет выведено соответветствующее сообщение. Все что нужно сделать - это изменить запись в регистре сведений, без изменения конфигурации.
Примеры.
1) Добавить свой реквизит формы с обработчиком ПриИзменении
ИдентификаторОбъектаМетаданных | Справочник1 (Справочник) |
ИмяФормы | ФормаЭлемента |
ИмяЭлемента | "МойЭлемент" |
Используется | Истина |
Видимость | Истина |
ТипЭлемента | "ПолеФормы" |
Родитель | |
ВидПоляФормы | "ПолеВвода" |
ПутьКДанным | "Объект.НовыйРеквизит" |
Заголовок | "Мой элемент" |
ИмяКоманды | |
ИмяТабличнойЧасти | |
ИмяСобытия | "ПриИзменении" |
Действие | "МойОбработчикКоманды" |
ПередЭлементом | "ИмяСуществующегоЭлемента" |
Родитель - имя группы элементов формы, в которую нужно поместить наш элемент.
ВидПоляФормы - системное перечисление (ПолеВвода, ПолеФлажка и т.п.)
Действие - имя команды (в модуле формы должна быть процедура МойОбработчикКоманды(Команда)). Можно переопределить существующий типовой обработчик.
ПередЭлементом - перед каким элементов вставить наш. Можно использовать для перемещения существующего типового элемента.
2) Добавить свою табличную часть
ИдентификаторОбъектаМетаданных | Справочник1 (Справочник) |
ИмяФормы | ФормаЭлемента |
ИмяЭлемента | "МояТЧ" |
Используется | Истина |
Видимость | Истина |
ТипЭлемента | "ТаблицаФормы" |
Родитель | |
ВидПоляФормы | |
ПутьКДанным | "Объект.НоваяТабличнаяЧасть" |
Заголовок | |
ИмяКоманды | |
ИмяТабличнойЧасти | "НоваяТабличнаяЧасть" |
ИмяСобытия | |
Действие | |
ПередЭлементом |
3)Добавить свою кнопку
ИдентификаторОбъектаМетаданных | Справочник1 (Справочник) |
ИмяФормы | ФормаЭлемента |
ИмяЭлемента | "НоваяКоманда" |
Используется | Истина |
Видимость | Истина |
ТипЭлемента | "КнопкаФормы" |
Родитель | |
ВидПоляФормы | |
ПутьКДанным | |
Заголовок | "Моя команда" |
ИмяКоманды | "МойОбработчикКоманды" |
ИмяТабличнойЧасти | |
ИмяСобытия | |
Действие | "МойОбработчикКоманды" |
ПередЭлементом |
При таком составе ресурсов не получится создавать группы формы, страницы и переопределять несколько обработчиков. Я добавлял ресурсы по мере необходимости, надобности в других свойствах не было.Можно просто создать справочник НастройкиЭлементовФормы в который включить все нужные свойства, он будет единственным ресурсом.