Мы рассмотрим, как интегрировать собственную печатную форму в стандартный механизм "Комплект документов с настройкой" в конфигурации 1С:Управление торговлей 11.5, используя расширения. Эта задача часто возникает, когда требуется добавить специфическую форму, которая должна выводиться вместе с типовыми документами, например, в составе реализации товаров и услуг. Мы проанализируем два основных подхода: модификацию типового механизма формирования комплекта через расширение и использование внешних печатных форм, обсудим их преимущества, недостатки и особенности реализации, чтобы вы могли выбрать наиболее подходящий вариант для вашей задачи.
Мы выяснили, что заполнение комплекта печатных форм для документа происходит в экспортной функции КомплектПечатныхФорм, расположенной в модуле менеджера соответствующего документа. В нашем случае, это будет модуль менеджера документа "Реализация товаров и услуг", то есть Документ.РеализацияТоваровУслуг.МодульМенеджера. Непосредственно изменить эту функцию в типовой конфигурации мы не можем, поскольку это приведет к снятию с поддержки и усложнит обновления. Однако, мы можем сделать это через расширение, используя аннотацию &Вместо, которая позволяет полностью заменить типовую процедуру или функцию своей реализацией.
Анализируем распространенную ошибку: зацикливание при попытке вызвать типовую функцию.
Изначально, у нас может возникнуть идея полностью заменить типовую функцию КомплектПечатныхФорм и в ней попытаться вызвать исходную функцию, чтобы получить ее результат и затем дополнить его своими формами. Это кажется логичным, поскольку мы хотим сохранить типовой функционал и лишь добавить к нему свой. Если мы попытаемся использовать код вида:
&Вместо("КомплектПечатныхФорм") Функция МойКомплектПечатныхФорм(ИдентификаторыОбъектовПечати, ИмяФормы) Экспорт
// Получаем типовой комплект (и пусть там в типовой меняют что хотят)
МойКомплект = КомплектПечатныхФорм(ИдентификаторыОбъектовПечати, ИмяФормы); // <--- Ошибка зацикливания здесь!
// Дополняем своими формами
// ...
Возврат МойКомплект;
КонецФункции
Мы столкнемся с серьезной проблемой – бесконечным зацикливанием (рекурсивным вызовом). Причина этого поведения заключается в том, что когда мы используем аннотацию &Вместо("КомплектПечатныхФорм"), наша функция МойКомплектПечатныхФорм полностью замещает типовую. Следовательно, когда внутри нашей замещающей функции мы снова пытаемся вызвать КомплектПечатныхФорм, система вызывает не оригинальную типовую функцию, а *нашу же замещающую* функцию. Это приводит к бесконечной рекурсии, переполнению стека вызовов и аварийному завершению работы 1С:Предприятия.
Корректное решение: использование метода ПродолжитьВызов().
Для корректного вызова замещаемой типовой функции и избежания зацикливания, в механизме расширений 1С предусмотрен специальный метод глобального контекста – ПродолжитьВызов(). Этот метод позволяет нам передать управление исходной (типовой) процедуре или функции, выполнить ее код, а затем вернуть управление обратно в наше расширение. Таким образом, мы можем получить результат типового выполнения, а затем модифицировать его или добавить свою логику до или после выполнения типового кода.
Правильный подход для добавления нашей печатной формы в коллекцию комплекта будет выглядеть следующим образом:
// В модуле менеджера расширения, связанного с документом РеализацияТоваровУслуг
// Например, в расширении "МоеРасширение", создаем модуль менеджера документа РеализацияТоваровУслуг
// и в нем добавляем следующий код:
// Расширение.МоеРасширение.Документ.РеализацияТоваровУслуг.МодульМенеджера
&Вместо("КомплектПечатныхФорм") Функция МойКомплектПечатныхФорм(ИдентификаторыОбъектовПечати, ИмяФормы) Экспорт
// 1. Вызываем типовую функцию с теми же параметрами, что и у оригинальной,
// и получаем ее результат (стандартный набор печатных форм).
// Метод ПродолжитьВызов() гарантирует, что будет вызвана исходная функция.
МойКомплект = ПродолжитьВызов(ИдентификаторыОбъектовПечати, ИмяФормы);
// 2. Теперь МойКомплект содержит все типовые печатные формы.
// Мы можем дополнить его своими формами.
// Коллекция МойКомплект является ТаблицейЗначений и имеет колонки:
// ИмяМакета, Представление, Порядок, НастройкаПоУмолчанию, Видимость,
// Заголовок, ИдентификаторКоманды, ДополнительныеСвойства.
// 3. Проверяем, не была ли наша форма уже добавлена, чтобы избежать дублирования
// или конфликтов, если вдруг типовой функционал изменится и добавит форму с таким именем.
Если НЕ МойКомплект.Найти("МояСвояПечать", "ИмяМакета") Тогда
// 4. Добавляем новую строку в коллекцию, описывающую нашу печатную форму.
НоваяСтрока = МойКомплект.Добавить();
НоваяСтрока.ИмяМакета = "МояСвояПечать"; // Уникальное имя макета, которое мы хотим добавить
НоваяСтрока.Представление = "Моя собственная форма реализации"; // Представление для пользователя в списке комплекта
НоваяСтрока.Порядок = 100; // Порядок вывода в списке (чем меньше, тем выше)
НоваяСтрока.НастройкаПоУмолчанию = Истина; // Будет ли эта форма выбрана по умолчанию в комплекте
НоваяСтрока.Видимость = Истина; // Видимость формы в настройках комплекта (можно ли ее включить/выключить)
НоваяСтрока.Заголовок = ""; // Можно указать дополнительный заголовок для формы в комплекте
// Если наша форма не является внешним файлом, а встроена в расширение,
// ИдентификаторКоманды должен совпадать с Идентификатором команды печати,
// которую мы добавим для вызова нашей формы.
НоваяСтрока.ИдентификаторКоманды = "МояСвояПечать";
// Мы можем добавить ДополнительныеСвойства, если наша форма требует специфических параметров.
КонецЕсли;
// 5. Возвращаем модифицированный комплект печатных форм.
Возврат МойКомплект;
КонецФункции
Критически важно тщательно передать все параметры, которые принимает исходная функция КомплектПечатныхФорм (ИдентификаторыОбъектовПечати и ИмяФормы), в метод ПродолжитьВызов(). Несоответствие параметров приведет к ошибкам вызова типовой функции.
Добавление команды печати для вашей формы.
Однако, просто добавить запись о макете в коллекцию МойКомплект недостаточно. Нам также необходимо, чтобы система знала, как сформировать табличный документ для этой печатной формы, когда пользователь выберет ее в комплекте. Это обычно делается путем добавления команды печати, которая указывает на обработчик формирования самой печатной формы.
В подсистеме "Печать" Библиотеки стандартных подсистем (БСП), команды для печати обычно добавляются в процедуре ДобавитьКомандыПечати модуля менеджера документа (например, Документ.РеализацияТоваровУслуг.МодульМенеджера.ДобавитьКомандыПечати). Мы можем расширить и эту процедуру, используя аннотацию &После или &Вместо, чтобы добавить свою команду печати. Использование &После в данном случае предпочтительнее, так как мы просто дополняем список команд, не изменяя существующие.
Рассмотрим пример добавления команды с использованием &После:
// В модуле менеджера расширения Документа "РеализацияТоваровУслуг"
&После("ДобавитьКомандыПечати")
Процедура МойДобавитьКомандыПечати(КомандыПечати)
// 1. Создаем новую команду печати.
НоваяКоманда = КомандыПечати.Добавить();
// 2. Уникальный идентификатор команды. Он должен совпадать с ИмяМакета,
// которое мы добавили в функцию КомплектПечатныхФорм.
НоваяКоманда.Идентификатор = "МояСвояПечать";
НоваяКоманда.Представление = "Моя собственная форма реализации"; // Название, которое увидит пользователь в меню "Печать"
НоваяКоманда.МногострочнаяСекция = Истина; // Если форма может печататься для нескольких выделенных документов
НоваяКоманда.ПроверкаПроведенияПередПечатью = Истина; // Нужно ли проверять проведение документа перед печатью
// 3. Обработчик, который будет вызван для формирования печатной формы.
// Мы указываем ПолноеИмяМодуляРасширения.ИмяЭкспортнойФункции.
// Эта функция должна быть экспортной и находиться в общем модуле нашего расширения
// (или в модуле менеджера расширения, если это более удобно).
НоваяКоманда.Обработчик = "МоеРасширение_ОбщийМодуль.ВыполнитьКомандуПечатиМояСвояПечать";
НоваяКоманда.Порядок = 100; // Порядок в списке команд (для сортировки)
НоваяКоманда.Назначение = "Документ.РеализацияТоваровУслуг"; // К какому объекту метаданных относится эта команда
КонецПроцедуры
Обработчик, указанный в поле НоваяКоманда.Обработчик, должен быть экспортной функцией или процедурой в общем модуле нашего расширения (например, МоеРасширение_ОбщийМодуль), которая принимает параметры печати и возвращает (или выводит) табличный документ. Мы рассмотрим, как создать такую функцию:
// В общем модуле расширения (например, МоеРасширение_ОбщийМодуль.bsl),
// который должен быть создан в расширении и иметь свойство "Глобальный" или "ВызовСервера".
Функция ВыполнитьКомандуПечатиМояСвояПечать(ИдентификаторКоманды, МассивОбъектов, ОбъектыПечати) Экспорт
// 1. Создаем новый экземпляр ТабличногоДокумента, в который будем выводить нашу форму.
ТабличныйДокумент = Новый ТабличныйДокумент;
ТабличныйДокумент.ИмяПараметровПечати = ИдентификаторКоманды; // Важно для БСП
// 2. Получаем макет печатной формы.
// Макет должен быть добавлен в наше расширение, например, как Макет.МойМакетПечатнойФормы.
Макет = Документы.РеализацияТоваровУслуг.ПолучитьМакет("МойМакетПечатнойФормы");
// 3. Заполняем табличный документ данными.
// МассивОбъектов содержит ссылки на документы, для которых формируется печать.
Для Каждого СсылкаНаОбъект Из МассивОбъектов Цикл
Попытка
ОбъектДокумент = СсылкаНаОбъект.ПолучитьОбъект();
Если ОбъектДокумент = Неопределено Тогда
Продолжить; // Объект не найден или помечен на удаление
КонецЕсли;
// Выводим заголовок формы
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьЗаголовок.Параметры.НазваниеДокумента = "Моя собственная реализация";
ОбластьЗаголовок.Параметры.Номер = ОбъектДокумент.Номер;
ОбластьЗаголовок.Параметры.Дата = ОбъектДокумент.Дата;
ОбластьЗаголовок.Параметры.Организация = ОбъектДокумент.Организация;
ОбластьЗаголовок.Параметры.Контрагент = ОбъектДокумент.Контрагент;
ТабличныйДокумент.Вывести(ОбластьЗаголовок);
// Выводим строки табличной части
ОбластьТабличнойЧасти = Макет.ПолучитьОбласть("СтрокаТабличнойЧасти");
НомерСтроки = 1;
Для Каждого СтрокаТЧ Из ОбъектДокумент.Товары Цикл
ОбластьТабличнойЧасти.Параметры.НомерПоПорядку = НомерСтроки;
ОбластьТабличнойЧасти.Параметры.Номенклатура = СтрокаТЧ.Номенклатура;
ОбластьТабличнойЧасти.Параметры.Количество = СтрокаТЧ.Количество;
ОбластьТабличнойЧасти.Параметры.Цена = СтрокаТЧ.Цена;
ОбластьТабличнойЧасти.Параметры.Сумма = СтрокаТЧ.Сумма;
ТабличныйДокумент.Вывести(ОбластьТабличнойЧасти);
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
// Выводим подвал
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ОбластьПодвал.Параметры.ИтогоСумма = ОбъектДокумент.СуммаДокумента;
ТабличныйДокумент.Вывести(ОбластьПодвал);
Если МассивОбъектов.Количество() > 1 Тогда
// Добавляем разрыв страницы, если печатаем несколько документов
ТабличныйДокумент.НоваяСтраница();
КонецЕсли;
Исключение
// Обработка ошибок при получении объекта или формировании
ЗаписьЖурналаРегистрации("МояСвояПечать", УровеньЖурналаРегистрации.Ошибка,
Метаданные.Документы.РеализацияТоваровУслуг, СсылкаНаОбъект,
"Ошибка формирования печатной формы: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
// 4. Если мы используем подсистему УправлениеПечатью,
// иногда может потребоваться явное указание области печати для корректного вывода в комплекте.
// УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабличныйДокумент, ИдентификаторКоманды);
// Однако, для большинства случаев, если команда правильно зарегистрирована, это может быть необязательно.
// 5. Возвращаем сформированный табличный документ.
Возврат ТабличныйДокумент;
КонецФункции
Риски и рекомендации при использовании &Вместо.
Подход с &Вместо несет определенные риски при обновлении конфигурации. Если разработчики 1С существенно изменят сигнатуру (набор и типы параметров) или внутреннюю логику функции КомплектПечатныхФорм, наше расширение может перестать работать корректно. Метод ПродолжитьВызов() позволяет минимизировать эти риски, поскольку мы не дублируем всю логику типовой функции, а лишь дополняем ее результат. Однако, мы все равно должны быть готовы к адаптации расширения после крупных обновлений, так как нам придется проверять совместимость нашей замещающей функции с новой версией типовой.
Важно помнить, что после любых изменений в расширении, связанных с командами печати и комплектами, может потребоваться перезапуск программы 1С:Предприятия. Это связано с тем, что информация о командах печати и макетах может кэшироваться системой для оптимизации производительности.
Альтернативным и зачастую более предпочтительным способом добавления новых печатных форм в "Комплект документов с настройкой" является использование механизма внешних печатных форм (ВПФ). Этот подход считается менее инвазивным, поскольку он не требует изменения типовых процедур конфигурации через &Вместо, что делает его более устойчивым к обновлениям. ВПФ автоматически интегрируются в "Комплект документов с настройкой" после их корректной регистрации.
Создание файла внешней печатной формы (.epf).
Для создания ВПФ нам потребуется отдельный файл внешней обработки с расширением .epf. Этот файл будет содержать макет печатной формы и всю логику ее формирования. Мы можем создать его в конфигураторе, как обычную внешнюю обработку, а затем сохранить ее в файл.
Внешняя печатная форма, чтобы быть корректно распознанной подсистемой БСП "Дополнительные отчеты и обработки", должна содержать, как минимум, следующие экспортные функции и процедуры в модуле объекта внешней обработки:
СведенияОВнешнейОбработке(): Эта функция должна возвращать структуру с метаданными обработки (наименование, вид, версию) и, что особенно важно, описание команд печати, которые предоставляет данная ВПФ.Печать(): Это основная экспортная функция, которая вызывается системой для формирования печатной формы. Она принимает массив ссылок на объекты и должна возвратить сформированный табличный документ.ПолучитьМакет(): Вспомогательная функция, которая возвращает макет печатной формы, если он хранится внутри ВПФ.Рассмотрим структуру ключевых функций:
// В модуле объекта внешней обработки (.epf файла)
// Функция для предоставления сведений о внешней обработке и ее командах.
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма"); // Указываем, что это печатная форма
ПараметрыРегистрации.Вставить("Наименование", "МояВнешняяПечатнаяФорма"); // Название обработки
ПараметрыРегистрации.Вставить("Версия", "1.0"); // Версия обработки
ПараметрыРегистрации.Вставить("БезопасныйРежим", Истина); // Работает ли обработка в безопасном режиме
ПараметрыРегистрации.Вставить("Информация", "Демонстрационная внешняя печатная форма для УТ 11.5");
// Создаем таблицу команд, которые будут доступны пользователю.
ТаблицаКоманд = Новый ТаблицаЗначений;
ТаблицаКоманд.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка")); // Название команды для пользователя
ТаблицаКоманд.Колонки.Добавить("Идентификатор", Новый ОписаниеТипов("Строка")); // Уникальный идентификатор команды
ТаблицаКоманд.Колонки.Добавить("Использование", Новый ОписаниеТипов("Строка")); // Тип использования: "Печать", "Заполнение", "ДополнительныйОтчет"
ТаблицаКоманд.Колонки.Добавить("ПоказыватьОповещение", Новый ОписаниеТипов("Булево")); // Показывать оповещение после выполнения
ТаблицаКоманд.Колонки.Добавить("Модификатор", Новый ОписаниеТипов("Строка")); // Дополнительный модификатор (например, "Печать", "Сохранить")
ТаблицаКоманд.Колонки.Добавить("Назначение", Новый ОписаниеТипов("Массив")); // Массив типов объектов, к которым привязана команда
// Добавляем нашу команду печати
НоваяКоманда = ТаблицаКоманд.Добавить();
НоваяКоманда.Представление = "Моя внешняя печать (ВПФ)";
НоваяКоманда.Идентификатор = "МояВнешняяПечатьВПФ"; // Уникальный идентификатор команды для ВПФ
НоваяКоманда.Использование = "Печать"; // Это команда для печати
НоваяКоманда.ПоказыватьОповещение = Ложь; // Не показывать оповещение по умолчанию
НоваяКоманда.Назначение = Новый Массив;
НоваяКоманда.Назначение.Добавить("Документ.РеализацияТоваровУслуг"); // Привязываем команду к документу "РеализацияТоваровУслуг"
ПараметрыРегистрации.Вставить("Команды", ТаблицаКоманд);
Возврат ПараметрыРегистрации;
КонецФункции
// Основная функция, которая вызывается для формирования печатной формы.
Функция Печать(МассивОбъектов, ОбъектыПечати, ИмяМакета, КоллекцияПечатныхФорм, ОбъектыДляФормирования) Экспорт
ТабличныйДокумент = Новый ТабличныйДокумент;
// Получаем макет из внешней обработки. Макет должен быть добавлен в дерево объектов ВПФ.
Макет = ЭтотОбъект.ПолучитьМакет("МойМакетВПФ");
// Здесь размещается вся логика заполнения ТабличногоДокумента на основе данных из документов.
// МассивОбъектов - это массив ссылок на документы, для которых формируется печать.
// Мы можем использовать его для получения данных и вывода на макет.
// Пример заполнения (аналогично примеру выше, но уже внутри ВПФ):
Для Каждого СсылкаНаОбъект Из МассивОбъектов Цикл
Попытка
ОбъектДокумент = СсылкаНаОбъект.ПолучитьОбъект();
Если ОбъектДокумент = Неопределено Тогда
Продолжить;
КонецЕсли;
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьЗаголовок.Параметры.НазваниеДокумента = "Внешняя форма реализации";
ОбластьЗаголовок.Параметры.Номер = ОбъектДокумент.Номер;
ОбластьЗаголовок.Параметры.Дата = ОбъектДокумент.Дата;
ОбластьЗаголовок.Параметры.Организация = ОбъектДокумент.Организация;
ОбластьЗаголовок.Параметры.Контрагент = ОбъектДокумент.Контрагент;
ТабличныйДокумент.Вывести(ОбластьЗаголовок);
ОбластьТабличнойЧасти = Макет.ПолучитьОбласть("СтрокаТабличнойЧасти");
НомерСтроки = 1;
Для Каждого СтрокаТЧ Из ОбъектДокумент.Товары Цикл
ОбластьТабличнойЧасти.Параметры.НомерПоПорядку = НомерСтроки;
ОбластьТабличнойЧасти.Параметры.Номенклатура = СтрокаТЧ.Номенклатура;
ОбластьТабличнойЧасти.Параметры.Количество = СтрокаТЧ.Количество;
ОбластьТабличнойЧасти.Параметры.Цена = СтрокаТЧ.Цена;
ОбластьТабличнойЧасти.Параметры.Сумма = СтрокаТЧ.Сумма;
ТабличныйДокумент.Вывести(ОбластьТабличнойЧасти);
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
ОбластьПодвал.Параметры.ИтогоСумма = ОбъектДокумент.СуммаДокумента;
ТабличныйДокумент.Вывести(ОбластьПодвал);
Если МассивОбъектов.Количество() > 1 Тогда
ТабличныйДокумент.НоваяСтраница();
КонецЕсли;
Исключение
ЗаписьЖурналаРегистрации("МояВнешняяПечатьВПФ", УровеньЖурналаРегистрации.Ошибка,
Метаданные.Документы.РеализацияТоваровУслуг, СсылкаНаОбъект,
"Ошибка формирования внешней печатной формы: " + ОписаниеОшибки());
КонецПопытки;
КонецЦикла;
// В некоторых случаях, для корректной работы в комплекте, особенно если форма
// формируется для нескольких документов, может потребоваться использование УправлениеПечатью.ЗадатьОбластьПечатиДокумента.
// Однако, для большинства ВПФ, если они правильно привязаны, система автоматически обрабатывает их.
// Мы рекомендуем протестировать, нужна ли эта строка.
// УправлениеПечатью.ЗадатьОбластьПечатиДокумента(ТабличныйДокумент, ИдентификаторКоманды);
Возврат ТабличныйДокумент;
КонецФункции
Регистрация внешней печатной формы в 1С.
После того как файл .epf создан и содержит всю необходимую логику и макет, его необходимо зарегистрировать в базе 1С. Для этого перейдите в раздел "НСИ и администрирование" – "Печатные формы, отчеты и обработки" – "Дополнительные отчеты и обработки".
.epf.СведенияОВнешнейОбработке() и создаст команды печати.Документ.РеализацияТоваровУслуг), если это не было сделано автоматически или требуется уточнение.После регистрации, команды печати из вашей ВПФ станут доступны для выбора в "Комплекте документов с настройкой" для соответствующих документов. Пользователи смогут включать или выключать вашу форму в свой набор печатных документов без каких-либо доработок конфигурации.
Особенности получения данных в ВПФ.
Одно из замечаний автора (Сообщение 10) касалось того, что при использовании ВПФ придется "тянуть заполнение печатной формы данными". Действительно, в случае ВПФ вся логика получения необходимых данных из базы и их вывода на макет должна быть реализована внутри самой внешней обработки. Однако, это предоставляет большую гибкость и независимость от типовой конфигурации. Функция Печать() в ВПФ получает массив ссылок на документы (МассивОбъектов), что позволяет нам легко получить необходимые объекты и их данные для формирования табличного документа.
Мы используем стандартные методы языка 1С, такие как Ссылка.ПолучитьОбъект(), для доступа к данным документа и его табличных частей. Вся работа с запросами, выборками данных, расчетами и форматированием выполняется непосредственно в коде ВПФ, что дает нам полный контроль над процессом.
Преимущества и недостатки ВПФ.
Основные преимущества использования ВПФ:
.epf легко передается между базами и подключается без необходимости изменения конфигурации или расширения. Это упрощает внедрение и поддержку.Недостатки ВПФ:
Следует отметить, что для объектов, добавленных *самим расширением* (т.е., если вы создали новый документ или справочник в расширении), их идентификаторы могут быть записаны в справочник ИдентификаторыОбъектовРасширений, а не ИдентификаторыОбъектовМетаданных. Это может потребовать дополнительной настройки при регистрации ВПФ, если внешняя печатная форма предназначена для печати *расширенного* документа. Однако для типового документа "Реализация товаров и услуг" таких сложностей обычно не возникает, и ВПФ регистрируется стандартным образом.
При выборе между двумя рассмотренными подходами – модификацией типовой функции через &Вместо и использованием внешних печатных форм – мы рекомендуем отдавать предпочтение внешним печатным формам, если это возможно. ВПФ обеспечивают большую гибкость, меньшую зависимость от внутренней структуры типовой конфигурации и значительно упрощают процесс обновления системы. Метод &Вместо следует использовать только тогда, когда вам необходимо именно изменить *логику* работы типовой функции, а не просто добавить новый элемент в ее результат.
Независимо от выбранного метода, мы должны помнить о тщательном тестировании. После добавления или изменения печатной формы всегда проверяйте ее работу в различных сценариях:
В 1С:Управление торговлей 11.5 и в современных версиях БСП (начиная с 2.5) активно развивается подход к разработке через расширения. 1С рекомендует использовать расширения для модификации типового функционала, что позволяет сохранять конфигурацию на поддержке. Для печатных форм, которые не требуют глубокого изменения логики типовой системы, ВПФ остаются очень жизнеспособным, удобным и надежным вариантом. Механизм "Комплект документов с настройкой" предоставляет мощный инструмент для конечных пользователей, позволяя им самостоятельно настраивать состав форм для печати, что является важным аспектом адаптации системы без программирования.
Мы убедились, что оба подхода имеют свои плюсы и минусы, и выбор конкретного метода зависит от специфики задачи, требований к устойчивости обновлений и предпочтений разработчика. Главное – следовать принципам работы с расширениями и БСП для обеспечения стабильности и поддерживаемости решения.