Задача: вносить изменения в управляемые формы (особенно в типовых конфигурациях) с минимальными изменениями типовых объектов.
Проблема: Основные типовые конфигурации находятся в режиме совместимости 8.3.10 и ниже, что не позволяет полноценно использовать механизм расширений 1С. Поэтому обычно конфигурацию поставщика снимают с поддержки и изменяют типовые объекты (в частности управляемые формы). А потом получают проблемы при обновлении.
Решение: Вынести изменения реквизитов, команд и элементов в форму-макет. А в типовой форме добавить процедуры заполнения по макету.
Исходные данные: Клиент-серверный вариант установки 1С. Остальное не важно.
Переопределение типовых действий
Первая часть механизма. Позволяет не вносить изменения в типовые процедуры формы или элементов формы. Может использоваться независимо от заполнения формы по макету.
В модуле типовой формы создаём процедуры по типу: <префикс>_<имя типовой процедуры>(<параметры>). Параметры те же, что и у типовых процедур, например так:
&НаСервере
Процедура демо_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
КонецПроцедуры
&НаКлиенте
Процедура демо_ПриОткрытии(Отказ)
КонецПроцедуры
&НаКлиенте
Процедура демо_НомерПоПлануПриИзменении(Элемент)
КонецПроцедуры
В конце модуля типовой формы делаем вызов процедуры общего модуля, например так:
#Если НаСервере Тогда
демо_РаботаСФормамиСервер.УстановитьДействие(ЭтаФорма, "ПриСозданииНаСервере");
демо_РаботаСФормамиСервер.УстановитьДействие(ЭтаФорма, "ПриОткрытии");
демо_РаботаСФормамиСервер.УстановитьДействие(ЭтаФорма, "ПриИзменении", "НомерПоПлану");
#КонецЕсли
Синтаксис простой: УстановитьДействие(<Форма>, <ИмяСобытия>, <ИмяЭлемента>).
Важно выполнять на сервере, т.к. УправляемаяФорма между клиентом и сервером не сериализуется и не передается.
Данная процедура переопределяет переданное действие формы или элемента формы (процедура УстановитьДействие) или кнопки формы (свойство Действие), а также создаёт (если ранее не создан) в указанной форме служебный реквизит типа СписокЗначений. И добавляет в него соответствие старого действия и нового действия (чтобы впоследствии можно было вызвать старое действие). Старое действие вызывается вот так:
Выполнить(демо_РаботаСФормамиКлиентСервер.ПолучитьСтароеДействие(ЭтаФорма, "ПриСозданииНаСервере"));
Выполнить(демо_РаботаСФормамиКлиентСервер.ПолучитьСтароеДействие(ЭтаФорма, "ПриИзменении", "НомерПоПлану"));
Заполнение формы по макету
Вторая часть механизма. Состоит из нескольких процедур, которые вызываются в макете и в типовой форме при открытии. С управляемыми формами есть несколько особенностей в отличие от обычных форм.
- Создаем копию типовой формы и убираем из неё весь код модуля формы. Называем её <Префикс>_<Имя типовой формы> (хотя не обязательно, но для порядку). Это будет макет.
- Изменяем макет (добавляем реквизиты, команды, элементы, изменяем, перемещаем существующие элементы).
- Добавляем в макет код, выполняемый на сервере того, что мы поменяли, например вот так:
#Если НаСервере Тогда // демо_РаботаСФормамиСервер.ДобавитьРеквизитМакета(ЭтаФорма, "???"); // демо_РаботаСФормамиСервер.ДобавитьКомандуМакета(ЭтаФорма, Команды.Найти("???")); демо_РаботаСФормамиСервер.ДобавитьЭлементМакета(ЭтаФорма, Элементы.демо_ГруппаНомерПоПлану); демо_РаботаСФормамиСервер.ДобавитьЭлементМакета(ЭтаФорма, Элементы.НомерПоПлану); демо_РаботаСФормамиСервер.ДобавитьЭлементМакета(ЭтаФорма, Элементы.демо_ПрефиксСортировки); демо_РаботаСФормамиСервер.ДобавитьЭлементМакета(ЭтаФорма, Элементы.демо_Декорациясортировка); демо_РаботаСФормамиСервер.ДобавитьЭлементМакета(ЭтаФорма, Элементы.демо_КодСортировки); #КонецЕсли
- В типовую форму добавляем несколько процедур в определенном порядке (что-то на клиенте, что-то на сервере).
Основная процедура "ПриОткрытии", остальное можно найти в приложенной конфигурации.&НаКлиенте Процедура демо_ПриОткрытии(Отказ) Выполнить(демо_РаботаСФормамиКлиентСервер.ПолучитьСтароеДействие(ЭтаФорма, "ПриОткрытии")); Макет = ПолучитьФорму(демо_ПолучитьИмяМакета(),,, Истина); РеквизитыМакета = демо_РаботаСФормамиКлиент.ПолучитьРеквизитыМакета(Макет); КомандыМакета = демо_РаботаСФормамиКлиент.ПолучитьКомандыМакета(Макет); ЭлементыМакета = демо_РаботаСФормамиКлиент.ПолучитьЭлементыМакета(Макет); демо_НастроитьФормуПоМакету(РеквизитыМакета, КомандыМакета, ЭлементыМакета); демо_РаботаСФормамиКлиент.НастроитьФормуПоМакету(ЭтаФорма, Макет); демо_ПереместитьЭлементыПоМакету(ЭлементыМакета); КонецПроцедуры
Порядок следующий:
- Получение макета. Процедура ПолучитьФорму доступна только на клиенте.
- Получение реквизитов, команд и элементов макета. Были добавлены в макет при получении формы выше.
- Добавляем реквизиты, команды и элементы в типовую форму из макета. Требует перехода на сервер, т.к. форма не передается между клиентом и сервером.
- Настройка формы по макету. Все свойства уже созданных ранее элементов заполняем на клиенте.
- Перемещение элементов. Делаем на сервере после заполнения свойств на клиенте, т.к. вид элемента заполняется на клиенте.
Итоги
- 3 общих процедуры.
- Макет, в котором визуально редактируем изменения типовых форм.
- Типовая форма визуально не изменена.
- В модуле формы добавлены несколько процедур.
- Все вышеперечисленное выше минимально пересекается с типовыми объектами и удобно для обновления.
Ссылки
Изначально механизм реализовал у себя для обычных форм (лет 7 назад). И успешно экономил кучу времени на обновлении.
Идея и исходный код переопределения взяты отсюда: http://kb.mista.ru/article.php?id=268. Доработано.
Настройка формы по макету отсюда: http://kb.mista.ru/article.php?id=327. Доработано.