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