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