Разработчики, активно использующие механизм расширений в платформе «1С:Предприятие 8.3», часто сталкиваются с неприятной особенностью: при заимствовании формы в расширение для изменения ее логики система автоматически «притягивает» связанные метаданные. Это могут быть типы реквизитов, перечисления, справочники или документы. В результате конфигурация расширения замусоривается объектами, которые разработчик не планировал изменять, но за которыми теперь приходится следить при каждом обновлении основной конфигурации.
В этой статье мы подробно разберем, как решить проблему избыточного заимствования, рассмотрим поведение платформы в разных версиях и проанализируем альтернативные программные методы кастомизации интерфейса и логики форм без заимствования их структуры.
Прежде чем переходить к обходным путям, выясним причину проблемы. В старых версиях платформы (до 8.3.14) заимствование формы приводило к обязательному затягиванию в расширение практически всей ссылочной структуры реквизитов формы. Начиная с версий 8.3.14 и 8.3.15, фирма «1С» существенно оптимизировала этот механизм. Теперь при заимствовании формы платформа захватывает лишь минимально необходимый набор метаданных. Если вы работаете на современных релизах платформы, то «мусора» в расширении создается на порядок меньше.
Тем не менее, даже на новых версиях платформы заимствование формы фиксирует ее структуру. Если в основной конфигурации изменятся реквизиты заимствованной формы, при обновлении может возникнуть конфликт. Ниже мы детально разберем проверенные практические способы, как этого избежать.
Если вам обязательно нужно внедрить код непосредственно в модуль формы (например, использовать директивы &Перед, &После или &Вместо для предопределенных процедур формы), но вы хотите обезопасить себя от проблем при обновлениях, можно использовать метод ручной очистки формы в расширении.
Выполним следующие шаги:
Объект), если без него форма отказывается компилироваться.Почему это работает? При работе пользователя платформа объединяет визуальную структуру формы из основной конфигурации и код модуля из расширения. Поскольку в расширении форма не содержит элементов интерфейса, при обновлении основной конфигурации платформа будет сравнивать исключительно программный код модуля, полностью игнорируя любые изменения визуальной части формы в типовом решении. Это сводит риск конфликтов к минимуму.
Это самый надежный, гибкий и рекомендуемый способ разработки, который позволяет вообще не заимствовать форму в расширение. Данный метод активно применяется в современных типовых конфигурациях на базе Библиотеки Стандартных Подсистем (БСП) и является обязательным стандартом для прохождения аудита в облачном сервисе «1С:Фреш».
Суть подхода заключается в том, что мы перехватываем событие создания формы из общего модуля расширения, а затем программно добавляем нужные реквизиты, элементы и назначаем им обработчики событий.
Проанализируем этот процесс на примере конфигурации с БСП:
МодификацияКонфигурацииПереопределяемый.ПриСозданииНаСервере этого модуля ставим условие на перехват нужной нам формы.ИзменитьРеквизиты() для динамического добавления новых реквизитов.Форма.Элементы.Добавить().УстановитьДействие().Посмотрим на практический пример реализации такого кода в общем модуле расширения:
// Процедура-перехватчик в общем модуле МодификацияКонфигурацииПереопределяемый
Процедура ПриСозданииНаСервере(Форма, Отказ, СтандартнаяОбработка) Экспорт
// Определяем форму, которую хотим доработать без заимствования
Если Форма.ИмяФормы = "Документ.РеализацияТоваровУслуг.Форма.ФормаДокумента" Тогда
// 1. Программное добавление нового реквизита на форму
МассивРеквизитов = Новый Массив;
ТипСтрока = Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(150));
НовыйРеквизит = Новый РеквизитФормы("ДополнительныйКомментарий", ТипСтрока, , "Доп. комментарий", Истина);
МассивРеквизитов.Добавить(НовыйРеквизит);
Форма.ИзменитьРеквизиты(МассивРеквизитов);
// 2. Программное создание элемента интерфейса (поле ввода)
// Находим родительскую группу на форме, куда хотим поместить поле
РодительскаяГруппа = Форма.Элементы.Найти("ГруппаПодвал");
Если РодительскаяГруппа = Неопределено Тогда
РодительскаяГруппа = Форма.Элементы.ОсновнаяПанель; // Альтернативный родитель
КонецЕсли;
НовоеПоле = Форма.Элементы.Добавить("ПолеДопКомментарий", Тип("ПолеФормы"), РодительскаяГруппа);
НовоеПоле.Вид = ВидПоляФормы.ПолеВвода;
НовоеПоле.ПутьКДанным = "ДополнительныйКомментарий";
НовоеПоле.Подсказка = "Введите дополнительный комментарий для расширения";
// 3. Установка обработчика события изменения поля
// Обработчик должен находиться в клиентском общем модуле расширения
НовоеПоле.УстановитьДействие("ПриИзменении", "Подключаемый_ДопКомментарийПриИзменении");
КонецЕсли;
КонецПроцедуры
Поскольку обработчики событий элементов формы не могут быть описаны в локальном модуле незаимствованной формы, мы выносим их во внешний общий модуль расширения (например, МодификацияКонфигурацииКлиент). Обратите внимание, что этот модуль должен иметь включенные свойства Клиент (управляемое приложение) и Вызов сервера.
Рассмотрим пример кода обработчика события в общем клиентском модуле:
// В общем клиентском модуле МодификацияКонфигурацииКлиент
Процедура Подключаемый_ДопКомментарийПриИзменении(Элемент) Экспорт
// Платформа автоматически передает элемент формы в качестве параметра.
// Через элемент мы можем получить доступ к самой форме и её контексту.
ТекущаяФорма = Элемент.Родитель;
// Пример логики: проверим заполнение программно добавленного реквизита
ЗначениеРеквизита = ТекущаяФорма.ДополнительныйКомментарий;
Если СокращенноЛП(ЗначениеРеквизита) = "" Тогда
ПоказатьПредупреждение(, "Поле обязательно к заполнению!");
КонецЕсли;
КонецПроцедуры
Для опытных разработчиков существует альтернативный «хакерский» способ, позволяющий добиться чистоты расширения за счет низкоуровневой работы с файлами конфигурации. Этот метод позволяет внедрить программный код в модуль формы, вообще не регистрируя саму форму и её реквизиты в метаданных расширения интерфейсными средствами конфигуратора.
Разберем данный алгоритм по шагам:
В результате вы получаете форму в расширении, у которой полностью отсутствуют заимствованные реквизиты и элементы в дереве метаданных конфигуратора, но при этом модуль формы активен, успешно компилируется и перехватывает нужные вам события.
Если ваша задача состоит в том, чтобы добавить на форму новую кнопку (например, для печати, заполнения табличной части или создания связанного объекта на основании), вам вообще не нужно трогать саму форму или ее модуль.
В БСП встроен мощный механизм подключаемых команд. Чтобы вывести вашу команду на форму документа или справочника, достаточно зарегистрировать ее через расширение переопределяемых модулей БСП (например, УправлениеПечатьюПереопределяемый или ЗаполнениеОбъектовПереопределяемый). Платформа сама найдет вашу команду и автоматически выведет кнопку в стандартные панели формы при ее открытии, а вызовы будут перенаправлены в указанный вами модуль менеджера или общий модуль.
Выбор оптимального способа зависит от решаемой задачи:
&Перед проведением из формы), используйте паттерн «Форма-пустышка». Заимствуйте форму, очистите все реквизиты вручную в конфигураторе и пишите код в модуле.ПриСозданииНаСервере. Это самый чистый способ разработки, гарантирующий абсолютно легкие обновления.