При разработке новых печатных форм для самописной конфигурации 1С, особенно если в планах стоит внедрение Библиотеки стандартных подсистем (БСП), возникает критически важный вопрос: как спроектировать код таким образом, чтобы минимизировать переработки и обеспечить бесшовную интеграцию в будущем? Мы рассмотрим подход, который позволит вам создавать печатные формы, удобные для отладки уже сейчас и максимально готовые к требованиям БСП в перспективе.
Для начала, давайте разберем предложенный подход к разработке и отладке печатных форм. Этот метод позволяет разрабатывать и тестировать формы независимо от основной конфигурации, что особенно удобно, если опыт работы с управляемыми формами и БСП пока невелик.
Мы будем создавать каждую печатную форму как отдельную внешнюю обработку (или включаемую в конфигурацию, но с возможностью автономного запуска). У такой обработки должна быть форма. На этой форме мы располагаем поле ввода, в которое можно будет указать ссылку на документ (например, ДокументСсылка), и кнопку "Печать". Эта кнопка позволит нам отлаживать печатную форму напрямую, без необходимости запускать ее из документа.
При этом, для запуска обработки из документа конфигурации, мы добавим в форму документа команду. Эта команда будет открывать нашу обработку, передавая в нее ссылку на текущий документ в качестве параметра.
В обработчике события ПриСозданииНаСервере формы обработки мы анализируем переданные параметры. Если в параметрах формы обнаружена ссылка на документ, это означает, что обработка была вызвана из документа. В этом случае мы автоматически запускаем процедуру печати, а затем устанавливаем Отказ = Истина, чтобы форма обработки закрылась сразу после выполнения печати. Таким образом, пользователь увидит только результат печати, а не промежуточную форму отладки.
Рассмотрим пример такого подхода:
// Модуль формы обработки
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
Если ПараметрыФормы.Свойство("ДокументСсылкаДляПечати") Тогда
// Если параметр передан, значит, вызов из документа
СсылкаДокумента = ПараметрыФормы.ДокументСсылкаДляПечати;
// Создаем табличный документ для печати
ТабДок = Новый ТабличныйДокумент;
// Вызываем экспортную процедуру из модуля объекта обработки для формирования печати
// Передаем ссылку на документ и табличный документ
МодульОбъекта.НапечататьДокумент(СсылкаДокумента, ТабДок);
// Показываем сформированный табличный документ
ТабДок.Показать();
// Устанавливаем Отказ = Истина, чтобы форма закрылась автоматически
Отказ = Истина;
КонецЕсли;
КонецПроцедуры
// В модуле объекта обработки (тут будет основная логика)
Процедура НапечататьДокумент(СсылкаНаДокумент, ТабличныйДокумент) Экспорт
// Здесь будет вся логика по заполнению табличного документа
// Например, получение данных из документа, заполнение макета
// ...
// Пример получения макета из обработки
Макет = ПолучитьМакет("МойОсновнойМакет");
// Пример получения данных документа
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
// Пример заполнения области макета
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьЗаголовок.Параметры.ТекстЗаголовка = "Печатная форма документа " + ДокументОбъект.Номер;
ТабличныйДокумент.Вывести(ОбластьЗаголовок);
// ... дальнейшее заполнение ...
КонецПроцедуры
// Процедура обработки нажатия кнопки "Печать" на форме обработки (для отладки)
Процедура КомандаПечать(Команда)
Если ЗначениеЗаполнено(ПолеВводаДокументСсылка) Тогда
ТабДок = Новый ТабличныйДокумент;
МодульОбъекта.НапечататьДокумент(ПолеВводаДокументСсылка, ТабДок);
ТабДок.Показать();
Иначе
ПоказатьПредупреждение(, "Выберите документ для печати.");
КонецЕсли;
КонецПроцедуры
Такой подход обеспечивает удобство отладки и тестирования на текущем этапе.
Теперь давайте сосредоточимся на том, как сделать этот код максимально готовым к интеграции с БСП. Главный принцип здесь — это максимальная модульность, универсальность и независимость кода от конкретного контекста вызова. БСП предлагает унифицированный механизм работы с внешними печатными формами (ВПФ), и мы должны подстраиваться под его ожидания.
Критически важно размещать всю основную логику формирования табличного документа (запросы, обработку данных, заполнение макетов) в модуле объекта обработки. Это подтверждается мнением многих опытных разработчиков 1С. Почему именно там? Механизм внешних печатных форм БСП по умолчанию вызывает экспортные процедуры или функции, расположенные именно в модуле объекта ВПФ. Это делает код легко переносимым и доступным для вызова из любого места, включая БСП.
Этот пункт является одним из самых важных для обеспечения совместимости с БСП. Мы должны исключить прямое использование реквизитов обработки для хранения ссылок на документы или других данных, необходимых для печати. Вместо этого, всегда передавайте ссылки на документы или другие необходимые данные в качестве параметров экспортных процедур.
Почему избегать реквизитов? Механизм БСП вызывает серверные (экспортные) методы обработок, передавая им данные в качестве параметров. Контекст, в котором работает ваша форма обработки, отличается от контекста вызова БСП. Если вы будете полагаться на реквизиты обработки, заполненные из формы, то при вызове из БСП эти реквизиты могут быть пустыми или содержать некорректные данные. Код, написанный с передачей всех данных через параметры, становится более универсальным и независимым от способа вызова.
Всегда используем массив ссылок. Механизм печати БСП позволяет пользователю выбирать для печати не один, а сразу несколько документов. Соответственно, стандартная экспортная функция печати в БСП ожидает на вход массив ссылок на объекты, для которых требуется выполнить печать. Даже если на текущем этапе вы печатаете по одному документу, проектируйте свои функции так, чтобы они могли принять массив. В случае печати одного документа, вы просто передадите массив, содержащий одну ссылку.
Передаем ТабличныйДокумент. Табличный документ, в который будет выводиться результат печати, также должен передаваться как параметр. Вызывающая сторона (будь то ваша отладочная форма или БСП) создает экземпляр ТабличныйДокумент и передает его вашей функции для заполнения. Это позволяет более гибко управлять результатом печати, например, добавлять его в коллекцию печатных форм БСП.
Рассмотрим пример экспортной процедуры печати, разработанной с учетом этих принципов:
// Модуль объекта обработки
Процедура Печать(МассивОбъектов, ОбъектыПечати, ИмяМакета, КоллекцияПечатныхФорм, ОбъектыДляПечати) Экспорт
// МассивОбъектов: Массив ссылок на объекты, для которых выполняется печать (например, МассивДокументСсылок).
// ОбъектыПечати: Может быть ТабличныйДокумент для прямой печати или использоваться внутри КоллекцияПечатныхФорм.
// ИмяМакета: Идентификатор макета, если в обработке их несколько.
// КоллекцияПечатныхФорм: Коллекция, в которую необходимо добавить результат печати (для БСП).
// ОбъектыДляПечати: Дополнительные параметры, передаваемые БСП.
Если КоллекцияПечатныхФорм = Неопределено Тогда
// Если КоллекцияПечатныхФорм не передана, мы находимся в режиме отладки или прямого вызова
// Создаем свой табличный документ для показа
РезультатПечати = Новый ТабличныйДокумент;
Иначе
// Используем табличный документ, который будет передан в КоллекцияПечатныхФорм
РезультатПечати = Новый ТабличныйДокумент;
КонецЕсли;
Для Каждого СсылкаНаДокумент Из МассивОбъектов Цикл
// Получаем макет из обработки. Можно передавать ИмяМакета как параметр.
Макет = ПолучитьМакет(ИмяМакета);
// Получаем данные документа по ссылке
Попытка
ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();
Исключение
Продолжить; // Пропускаем, если объект не найден или недоступен
КонецПопытки;
// Здесь размещаем всю логику по заполнению табличного документа
// ...
// Пример: Заполнение заголовка
ОбластьЗаголовок = Макет.ПолучитьОбласть("Заголовок");
ОбластьЗаголовок.Параметры.Заполнить(ДокументОбъект); // Заполняем параметры из свойств объекта
РезультатПечати.Вывести(ОбластьЗаголовок);
// Пример: Вывод табличной части
Для Каждого СтрокаТЧ Из ДокументОбъект.Товары Цикл
ОбластьСтрока = Макет.ПолучитьОбласть("СтрокаТабличнойЧасти");
ОбластьСтрока.Параметры.Заполнить(СтрокаТЧ);
РезультатПечати.Вывести(ОбластьСтрока);
КонецЦикла;
// ...
КонецЦикла;
Если КоллекцияПечатныхФорм <> Неопределено Тогда
// Если КоллекцияПечатныхФорм передана, добавляем результат в нее (для БСП)
НоваяПечатнаяФорма = КоллекцияПечатныхФорм.Добавить();
НоваяПечатнаяФорма.ИмяМакета = ИмяМакета;
НоваяПечатнаяФорма.ТабличныйДокумент = РезультатПечати;
Иначе
// В режиме отладки просто показываем документ
РезультатПечати.Показать();
КонецЕсли;
КонецПроцедуры
// Для вашей формы отладки
// Модуль формы обработки
Процедура КомандаПечать(Команда)
Если ЗначениеЗаполнено(ПолеВводаДокументСсылка) Тогда
МассивДляПечати = Новый Массив;
МассивДляПечати.Добавить(ПолеВводаДокументСсылка);
// Вызываем нашу универсальную процедуру печати
МодульОбъекта.Печать(МассивДляПечати, Неопределено, "МойОсновнойМакет", Неопределено, Неопределено);
Иначе
ПоказатьПредупреждение(, "Выберите документ для печати.");
КонецЕсли;
КонецПроцедуры
Вопрос о том, как хранить макеты — все в одной обработке, или каждую печатную форму в отдельной, — является вопросом архитектуры и личных предпочтений. Рассмотрим несколько подходов:
Одна обработка — все макеты. Этот подход подразумевает создание одной универсальной обработки, которая содержит макеты для всех печатных форм (или всех форм для определенного типа документа). В модуле объекта такой обработки будут функции для формирования каждой из этих форм.
Одна обработка — одна печатная форма. Каждая печатная форма разрабатывается как отдельная внешняя обработка.
Для интеграции с БСП чаще всего используется подход, когда функциональность внешней печатной формы (ВПФ) привязана к одной обработке. Эта обработка может содержать несколько команд печати, каждая из которых будет соответствовать определенному макету или алгоритму. Такой подход позволяет достичь оптимального баланса между модульностью и управляемостью.
СведенияОВнешнейОбработке() для БСПФункция СведенияОВнешнейОбработке() является обязательной для регистрации вашей внешней печатной формы в БСП. Она должна быть экспортной и расположена в модуле объекта обработки. Эта функция возвращает структуру, описывающую вашу печатную форму и команды печати, которые она предоставляет. Без нее БСП не сможет "увидеть" и подключить вашу обработку как ВПФ.
Вопрос о том, когда создавать эту функцию — сразу или ближе к интеграции с БСП, — имеет разные мнения. Некоторые предлагают отложить ее, чтобы не усложнять разработку на ранних этапах. Однако, раннее понимание и прототипирование этой функции поможет лучше подготовить структуру обработки. Вы можете создать минимальную заглушку для этой функции, которая возвращает основные сведения, а затем постепенно ее расширять.
Давайте посмотрим на основные элементы структуры, которую должна возвращать функция СведенияОВнешнейОбработке():
Вид: Строка, всегда "ПечатнаяФорма".Наименование: Отображаемое имя печатной формы (например, "Моя ТОРГ-12").Версия: Номер версии обработки.Назначение: Массив строк с именами метаданных, к которым относится печатная форма (например, "Документ.РеализацияТоваровУслуг").Команды: Массив структур, описывающих команды печати, которые предоставляет ваша обработка. Каждая структура команды обычно содержит:
Идентификатор: Уникальный строковый идентификатор команды (например, "ПечатьТОРГ12").Представление: Текст, который будет отображаться в меню печати (например, "ТОРГ-12 (Моя)").Модификатор: Строка, определяющая, как команда будет выглядеть в стандартных меню печати. Часто используется "Печать".ПоказыватьВФорме: Булево, указывает, нужно ли показывать команду в форме объекта.Алгоритмы: Структура, содержащая имена функций в модуле объекта, которые БСП будет вызывать для выполнения определенных действий, например, для печати (Печать) или получения макета (ПолучитьМакет). Обычно достаточно указать функцию Печать, которая и будет выполнять всю основную работу.Пример реализации функции СведенияОВнешнейОбработке():
// Модуль объекта обработки
Функция СведенияОВнешнейОбработке() Экспорт
ПараметрыРегистрации = Новый Структура;
ПараметрыРегистрации.Вставить("Вид", "ПечатнаяФорма");
ПараметрыРегистрации.Вставить("Наименование", "Печатные формы для реализации");
ПараметрыРегистрации.Вставить("Версия", "1.0.0.1");
ПараметрыРегистрации.Вставить("КраткоеПредставление", "Дополнительные печатные формы для документа Реализация");
// Указываем, к каким объектам метаданных относится эта ВПФ
Назначение = Новый Массив;
Назначение.Добавить("Документ.РеализацияТоваровУслуг");
ПараметрыРегистрации.Вставить("Назначение", Назначение);
// Описание команд печати, которые предоставляет эта ВПФ
Команды = Новый Массив;
// Первая команда: Печать ТОРГ-12
КомандаТОРГ12 = Новый Структура;
КомандаТОРГ12.Вставить("Идентификатор", "ПечатьТОРГ12");
КомандаТОРГ12.Вставить("Представление", "ТОРГ-12 (Моя)");
КомандаТОРГ12.Вставить("Модификатор", "Печать"); // Подключается к стандартной кнопке "Печать"
КомандаТОРГ12.Вставить("ПоказыватьВФорме", Истина); // Показывать в форме документа
Команды.Добавить(КомандаТОРГ12);
// Вторая команда: Печать Счет-фактуры (если в этой же обработке)
// КомандаСчетФактура = Новый Структура;
// КомандаСчетФактура.Вставить("Идентификатор", "ПечатьСчетФактура");
// КомандаСчетФактура.Вставить("Представление", "Счет-фактура (Моя)");
// КомандаСчетФактура.Вставить("Модификатор", "Печать");
// КомандаСчетФактура.Вставить("ПоказыватьВФорме", Истина);
// Команды.Добавить(КомандаСчетФактура);
ПараметрыРегистрации.Вставить("Команды", Команды);
// Указываем алгоритм, который БСП будет вызывать для печати
Алгоритмы = Новый Структура;
Алгоритмы.Вставить("Печать", "Печать"); // Имя экспортной процедуры в модуле объекта
// Если нужно получить макеты не из объекта ВПФ, а из другой функции, можно указать
// Алгоритмы.Вставить("ПолучитьМакет", "ПолучитьМойМакет");
ПараметрыРегистрации.Вставить("Алгоритмы", Алгоритмы);
Возврат ПараметрыРегистрации;
КонецФункции
Обратите внимание, что процедура Печать, указанная в структуре Алгоритмы, будет вызвана с параметрами, которые мы уже обсуждали: МассивОбъектов, ОбъектыПечати, ИмяМакета, КоллекцияПечатныхФорм и ОбъектыДляПечати. Ваша процедура Печать должна уметь обрабатывать эти параметры.
Для поддержания чистоты кода и уменьшения дублирования, мы рекомендуем выносить повторяющуюся логику в отдельные общие модули вашей самописной конфигурации. Например, функции для форматирования чисел, строк, работы с адресами, склонения по падежам могут быть реализованы в общих модулях. Это позволит многократно использовать их в разных печатных формах, не дублируя код в каждой обработке, и упростит их дальнейшую поддержку.
Подход с отдельной формой обработки для отладки, которую мы описали в самом начале, является очень эффективным и гибким. Он позволяет вам разрабатывать и тестировать каждую печатную форму изолированно, быстро выявлять ошибки и проверять корректность отображения данных, не требуя полной интеграции в конфигурацию или развертывания сложной инфраструктуры БСП. После того как форма отлажена, ее код уже готов к вызову из БСП, так как соответствует всем необходимым принципам.
Таким образом, мы видим, что, хотя на первый взгляд задача может показаться сложной, последовательное применение описанных принципов позволяет создать гибкое и легко интегрируемое решение. Сосредоточившись на модульности, передаче параметров и предварительном учете структуры, ожидаемой БСП, вы значительно сократите трудозатраты при будущем внедрении стандартных подсистем.