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