Как изменить реквизит документа после его печати и обновить интерфейс

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В практике разработки на платформе 1С:Предприятие 8 часто возникает задача фиксации факта печати документа. Например, необходимо изменить статус документа с «Подготовлен» на «Напечатан» сразу после того, как пользователь сформировал печатную форму. На первый взгляд задача кажется простой, но она скрывает в себе несколько технических нюансов: от выбора места внесения изменений до корректного обновления открытых форм у пользователя. В этой статье мы подробно разберем, как реализовать этот функционал правильно и эффективно.

Способ 1. Прямое изменение реквизита в модуле менеджера

Чаще всего код формирования печатных форм располагается в модуле менеджера документа в процедуре Печать. В эту процедуру передается массив МассивОбъектов (или ОбъектыПечати), который содержит ссылки на документы, отправленные на печать. Проанализируем, как можно изменить реквизит напрямую через объект.

Для изменения данных нам необходимо получить объект документа из ссылки, изменить значение реквизита и записать его. Рассмотрим пример кода:


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

КонецПроцедуры

Важный момент: использование прямого изменения объекта (ПолучитьОбъект().Записать()) может быть избыточным и «тяжелым» для системы. При вызове метода Записать() срабатывают все подписки на события и проверки в модуле документа, что может замедлить процесс печати, особенно если печатается большой пакет документов.

Способ 2. Использование регистра сведений (архитектурно верный подход)

Как отмечают опытные разработчики, изменять сам объект только ради отметки о печати — не всегда лучшее решение. Более гибким и производительным подходом является использование регистра сведений. Мы можем создать непериодический регистр сведений, например, СтатусыПечатиДокументов, где измерением будет ссылка на документ, а ресурсом — статус или дата печати.

Выясним преимущества этого метода:

  1. Скорость: запись в регистр происходит быстрее, чем перезапись всего документа.
  2. Отсутствие блокировок: вы не блокируете объект документа для других пользователей на время проведения.
  3. История: если сделать регистр периодическим, можно хранить историю всех распечаток.

Пример записи в регистр сведений:


МенеджерЗаписи = РегистрыСведений.СтатусыПечатиДокументов.СоздатьМенеджерЗаписи();
МенеджерЗаписи.Документ = СсылкаНаДокумент;
МенеджерЗаписи.Статус = "Напечатан";
МенеджерЗаписи.ДатаПечати = ТекущаяДата();
МенеджерЗаписи.Записать(Истина);

Решение проблемы «юзабилити»: обновление форм

После того как данные в базе изменены (в объекте или в регистре), пользователь может не увидеть изменений, если у него открыта форма этого документа или список документов. Платформа 1С не обновляет открытые формы автоматически при программном изменении данных на сервере. Разберем, как заставить интерфейс «перерисоваться».

Проанализируем ситуацию: печать обычно инициируется с клиента. Чтобы обновить формы, нам нужно передать сигнал клиентскому приложению. Для этого идеально подходит метод ОповеститьОбИзменении() или Оповестить().

Если вы используете стандартную подсистему печати БСП, код в модуле менеджера выполняется на сервере. Чтобы обновить формы, рекомендуется после завершения печати на клиенте вызвать следующий код:


// В обработчике завершения печати на клиенте
Для Каждого СсылкаИзСписка Из МассивНапечатанныхДокументов Цикл
    ОповеститьОбИзменении(СсылкаИзСписка);
КонецЦикла;

Метод ОповеститьОбИзменении(Ссылка) — это встроенный механизм платформы. Он сообщает всем открытым формам и динамическим спискам, что данные конкретного объекта изменились. Платформа сама найдет нужные строки в списках и обновит их.

Учет особенностей БСП и фоновой печати

Современные конфигурации на базе БСП (Библиотека стандартных подсистем) часто выполняют формирование табличного документа в фоновом задании. Это означает, что попытка изменить реквизиты должна происходить именно там, где формируется результат. Однако стоит помнить о правах доступа.

У пользователя могут быть права на просмотр и печать документа, но отсутствовать права на его изменение. В этом случае попытка выполнить Записать() вызовет ошибку. Чтобы этого избежать, процедуру записи статуса можно вынести в привилегированный модуль или использовать конструкцию:


УстановитьПривилегированныйРежим(Истина);
// Код изменения статуса
УстановитьПривилегированныйРежим(Ложь);

Транзакционные риски: Будьте осторожны. Если вы измените статус документа в начале процедуры печати, а затем произойдет ошибка формирования макета (например, программная ошибка в коде формирования секций), документ останется со статусом «Напечатан», хотя фактически пользователь ничего не увидел. Правильнее всего менять статус в самом конце, когда табличный документ уже полностью сформирован и готов к выводу.

Использование Дополнительных Сведений

Если вы не хотите добавлять новый реквизит в документ или создавать свой регистр, можно воспользоваться механизмом Дополнительных сведений, который есть почти во всех типовых решениях. Это по сути готовый регистр сведений БСП. Вы можете программно создавать или изменять значение свойства «Статус печати» для любого документа, не меняя структуру метаданных самой конфигурации. Это особенно удобно, если ваша база находится на поддержке и вы используете расширения.

Подводя итог, наиболее надежным и современным способом является запись факта печати в отдельный регистр сведений с последующим вызовом ОповеститьОбИзменении() на стороне клиента для обновления пользовательского интерфейса.

← На главную