При разработке внешних печатных форм (ВПФ) для конфигураций на обычных формах, таких как «Управление торговлей 10.3», программисты часто сталкиваются со специфическим поведением печатной подсистемы. Типичная ситуация: вы создали внешнюю печатную форму Универсального передаточного документа (УПД), добавили форму для интерактивного выбора ответственного лица (например, для заполнения полей доверенности), но при выводе на экран выбранные данные в макете не отображаются.
В этой статье мы подробно разберем, почему возникает эта проблема, как устроена область видимости переменных во внешних обработках и какими способами можно передать данные из интерактивной формы ВПФ в макет, формируемый через общие модули конфигурации.
Проанализируем архитектуру работы типовой печати УПД в УТ 10.3. Когда пользователь нажимает кнопку печати, запускается алгоритм, который обращается к общему модулю УчетНДС, в частности к процедурам УчетНДС.ВывестиСчетФактуруВТабличныйДокумент() и УчетНДС.ВывестиПодвалУниверсальногоПередаточногоДокументаВТабличныйДокумент(). Здесь кроются сразу две серьезные проблемы для разработчика внешней печатной формы:
Доверенность или ДоверенноеЛицо после нажатия кнопки выбора), абсолютно невидимы для процедур общего модуля УчетНДС. Общий модуль работает в собственном контексте и принимает только те данные, которые явно переданы ему через параметры. Попытка объявить глобальные или экспортные переменные внутри общего модуля для обмена данными — это грубая ошибка, которая приведет к сбою компиляции или непредсказуемому поведению системы в многопользовательском режиме.ПолучитьОбщийМакет("УниверсальныйПередаточныйДокумент"). Даже если вы детально отредактировали макет внутри вашей внешней печатной формы (добавили новые параметры, изменили шрифт или логотип), программа проигнорирует эти изменения, так как обратится к стандартному общему макету из конфигурации.Для решения этих проблем существует три надежных архитектурных подхода. Рассмотрим каждый из них подробно, чтобы вы могли выбрать наиболее подходящий под ваши задачи.
Если вам не требуется изменять структуру самого макета, а нужно лишь заполнить стандартные параметры (такие как ФИО руководителя, доверенность, должность отпускающего) своими значениями, этот способ является самым элегантным и безопасным.
Проанализируем, как передаются данные в общий модуль. Функция ПодготовитьДанныеДляПечатиУниверсальногоПередаточногоДокумента() собирает всю информацию о документе в структуру ДанныеДляПечати. Затем эта структура передается в процедуры вывода макета. Мы можем перехватить эту структуру в модуле объекта нашей ВПФ, дополнить ее нужными значениями из нашей интерактивной формы и передать дальше.
Разберем по шагам реализацию этого механизма.
Шаг 1. Настройка интерактивной формы выбора в ВПФ.
В форме нашей внешней обработки (назовем ее ФормаВыбора) настроим обработчики нажатия кнопок выбора ответственных лиц. При нажатии на кнопку мы должны закрыть форму и передать выбранные значения обратно в модуль объекта.
Процедура КнопкаИвановНажатие(Элемент)
РезультатВыбора = Новый Структура;
РезультатВыбора.Вставить("ДоверенноеЛицо", "Иванов Иван Иванович");
РезультатВыбора.Вставить("Доверенность", "По доверенности № 01/20-ШМ от 09 января 2020 года");
// Закрываем форму и возвращаем структуру с данными
ЭтаФорма.Закрыть(РезультатВыбора);
КонецПроцедуры
Шаг 2. Модальный вызов формы из модуля объекта ВПФ.
В модуле объекта ВПФ в основной функции Печать() нам необходимо открыть созданную форму модально, получить из нее структуру параметров и внедрить их в процесс печати.
Функция Печать() Экспорт
// Получаем форму нашей ВПФ для интерактивного выбора
ФормаВыбора = ЭтотОбъект.ПолучитьФорму("ФормаВыбора");
ПараметрыВыбора = ФормаВыбора.ОткрытьМодально();
// Проверяем, сделал ли пользователь выбор или просто закрыл форму
Если ТипЗнч(ПараметрыВыбора) <> Тип("Структура") Тогда
Возврат Неопределено;
КонецЕсли;
// Вызываем основную процедуру формирования печатного листа
ТабДокумент = СформироватьУПД(ПараметрыВыбора);
Возврат ТабДокумент;
КонецФункции
Шаг 3. Внедрение параметров в структуру печати.
Теперь рассмотрим функцию СформироватьУПД, в которой мы получаем стандартную структуру данных для печати и дополняем ее нашими пользовательскими параметрами перед выводом на печать.
Функция СформироватьУПД(ПараметрыВыбора)
// Вызываем стандартную функцию подготовки данных
ДанныеДляПечати = ПодготовитьДанныеДляПечатиУниверсальногоПередаточногоДокумента();
Если ДанныеДляПечати = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
// Внедряем наши переменные в структуру данных для печати.
// Обратите внимание: ключи структуры должны строго соответствовать именам
// параметров в областях оригинального макета УПД.
ДанныеДляПечати.Вставить("ФИОРуководителя", ПараметрыВыбора.ДоверенноеЛицо);
ДанныеДляПечати.Вставить("Доверенность", ПараметрыВыбора.Доверенность);
// Создаем табличный документ и вызываем заполнение через общий модуль
ТабДокумент = Новый ТабличныйДокумент;
Макет = ПолучитьОбщийМакет("УниверсальныйПередаточныйДокумент981");
УчетНДС.ВывестиСчетФактуруВТабличныйДокумент(ТабДокумент, Макет, ДанныеДляПечати);
УчетНДС.ВывестиПодвалУниверсальногоПередаточногоДокументаВТабличныйДокумент(ТабДокумент, Макет, ДанныеДляПечати);
Возврат ТабДокумент;
КонецФункции
Данный способ хорош тем, что мы не перегружаем внешнюю печатную форму дублированием кода типовой конфигурации. Однако он сработает только в том случае, если в оригинальном макете конфигурации уже присутствуют параметры с именами ФИОРуководителя и Доверенность в нужных нам областях.
Если вам требуется не просто заполнить базовые поля, но и существенно изменить сам макет (например, добавить новые строки, колонки, изменить логику компоновки областей), то предыдущий способ не подойдет, так как общий модуль все равно проигнорирует ваш встроенный макет.
В этой ситуации лучшим решением будет локализация кода. Мы полностью перенесем процедуры вывода макета из общего модуля УчетНДС в модуль объекта нашей ВПФ и перенаправим получение макета на внутренний макет обработки.
Проанализируем этот процесс детально:
УчетНДС в конфигураторе. Нам понадобятся процедуры ВывестиСчетФактуруВТабличныйДокумент и ВывестиПодвалУниверсальногоПередаточногоДокументаВТабличныйДокумент.ПолучитьОбщийМакет(). Замените их на обращение к локальному макету вашей печатной формы: ЭтотОбъект.ПолучитьМакет().Посмотрим на пример измененного кода вывода подвала в модуле объекта ВПФ:
Процедура ЛокальныйВыводПодвалаУПД(ТабДокумент, Макет, ДанныеДляПечати, ПараметрыВыбора)
// Получаем нужную область из нашего локального макета ВПФ
ОбластьМакетаПодвал = Макет.ПолучитьОбласть("Подвал");
// Заполняем стандартные параметры из структуры ДанныеДляПечати
ОбластьМакетаПодвал.Параметры.Заполнить(ДанныеДляПечати);
// Напрямую присваиваем значения нашим уникальным параметрам,
// которые мы получили из интерактивной формы выбора
ОбластьМакетаПодвал.Параметры.Доверенность = ПараметрыВыбора.Доверенность;
ОбластьМакетаПодвал.Параметры.ФИОРуководителя = ПараметрыВыбора.ДоверенноеЛицо;
ОбластьМакетаПодвал.Параметры.ФИОГлавногоБухгалтера = ПараметрыВыбора.ДоверенноеЛицо;
// Выводим область в результирующий табличный документ
ТабДокумент.Вывести(ОбластьМакетаПодвал);
КонецПроцедуры
Преимущества локализации: Полная независимость от обновлений конфигурации в части макетов. Вы вольны добавлять любые логотипы, новые параметры и дополнительные ячейки. Вся логика находится внутри одного файла обработки.
Недостатки: Если фирма «1С» выпустит глобальное законодательное обновление формата УПД (изменятся колонки, ставки НДС или требования к реквизитам), вам придется вручную обновлять скопированный код внутри вашей ВПФ, сверяясь с новым кодом из общего модуля конфигурации.
Существует еще один очень практичный способ, который позволяет избежать как копирования огромных массивов кода из общих модулей, так и сложной передачи структур. Это метод постобработки готового документа.
Суть метода заключается в том, что мы позволяем типовым механизмам полностью сформировать печатную форму УПД стандартным образом. Затем, получив готовый объект ТабличныйДокумент, мы выполняем по нему текстовый поиск и заменяем шаблонные значения на нужные нам данные прямо перед выводом на экран.
Рассмотрим, как это выглядит на практике:
Функция Печать() Экспорт
// Шаг 1. Получаем выбор пользователя через модальную форму
ФормаВыбора = ЭтотОбъект.ПолучитьФорму("ФормаВыбора");
ПараметрыВыбора = ФормаВыбора.ОткрытьМодально();
Если ТипЗнч(ПараметрыВыбора) <> Тип("Структура") Тогда
Возврат Неопределено;
КонецЕсли;
// Шаг 2. Формируем полностью стандартный документ средствами общего модуля
ТабДокумент = СформироватьСтандартныйТабДокумент();
// Шаг 3. Производим замену текста в готовом табличном документе
// Ищем ячейку, где выведена стандартная фамилия руководителя, и заменяем её
ОбластьРуководителя = ТабДокумент.НайтиТекст("[ФИО_Стандартного_Руководителя]");
Если ОбластьРуководителя <> Неопределено Тогда
ОбластьРуководителя.Текст = ПараметрыВыбора.ДоверенноеЛицо;
КонецЕсли;
// Точно так же находим ячейку с основанием передачи (доверенностью)
ОбластьОснования = ТабДокумент.НайтиТекст("Основание передачи (сдачи) / получения");
Если ОбластьОснования <> Неопределено Тогда
// Мы можем заменить текст в найденной ячейке или сместиться на нужные координаты
ОбластьОснования.Текст = "Основание: " + ПараметрыВыбора.Доверенность;
КонецЕсли;
Возврат ТабДокумент;
КонецФункции
Этот способ невероятно лаконичен и надежен при обновлениях конфигурации: структура кода УПД в общем модуле может кардинально измениться, но если итоговый текст на печатной форме остался прежним, ваш поиск и замена отработают корректно.
Однако помните о минусах: поиск по тексту может замедлить формирование документа, если печатная форма содержит сотни страниц. Кроме того, если в макете изменится хотя бы один символ в строке поиска, алгоритм не сможет найти ячейку для замены.
Мы проанализировали три основных подхода к решению проблемы заполнения параметров макета во внешних печатных формах для УТ 10.3: