Что делать, если в ЗУП 3.1 после обновления перестали открываться дополнительные печатные формы?

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

После обновления конфигурации «Зарплата и управление персоналом» до версии 3.1.27.23 (и выше), а также в актуальных релизах «Бухгалтерии предприятия», многие пользователи столкнулись с неприятной ситуацией: внешние печатные формы (ВПФ) перестают работать. При нажатии на кнопку печати не происходит ровным счетом ничего — программа не выдает ошибок, но и форма предварительного просмотра не открывается. В этой статье мы подробно разберем, почему это происходит и как адаптировать ваши обработки под новые требования платформы и БСП.

Выясняем причину: изменения в БСП

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

Кроме того, внедрен механизм «длительной печати». Теперь формирование табличного документа по умолчанию должно происходить в фоновом задании, чтобы интерфейс пользователя не блокировался. Если ваша внешняя обработка пытается открыть форму печати «по старинке», она просто не проходит проверку в процедуре ПриСозданииНаСервере общей формы, срабатывает Отказ = Истина, и окно закрывается до того, как пользователь его увидит.

Рассмотрим два основных способа решения проблемы в зависимости от сложности вашей печатной формы.

Способ 1: Самый простой (для форм без параметров)

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

Откроем модуль объекта внешней печатной формы и найдем функцию СведенияОВнешнейОбработке. Проанализируем строку, где описывается команда печати. Нам нужно заменить тип использования команды.

Вместо открытия формы:


КомандаПечати.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыОткрытиеФормы();

Укажите вызов серверного метода:


КомандаПечати.Использование = ДополнительныеОтчетыИОбработкиКлиентСервер.ТипКомандыВызовСерверногоМетода();

Почему это работает: При использовании ТипКомандыВызовСерверногоМетода управление передается стандартным механизмам БСП. Система сама запустит фоновое задание, вызовет экспортную процедуру Печать в вашем модуле, получит готовый табличный документ и корректно передаст его в новую форму ПечатьДокументов со всеми необходимыми параметрами.

Способ 2: Для печатных форм с собственной формой параметров

Если вашей обработке необходимо предварительно открыть окно для выбора настроек или ввода данных, первый способ не подойдет. В этом случае нам придется переписать обработчик печати в модуле формы самой обработки. Рассмотрим, как теперь должен выглядеть код вызова печати, чтобы он соответствовал требованиям асинхронной работы.

Нам потребуется использовать механизм длительных операций. Разберем пример кода для процедуры, которая запускает процесс формирования документа:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Если это отладка, можем пропустить стандартную логику
    Если ЭтоОтладка Тогда 
        Возврат; 
    КонецЕсли;

    ПараметрыИсточника = Новый Структура;
    ПараметрыИсточника.Вставить("ИдентификаторКоманды", Параметры.ИдентификаторКоманды);
    ПараметрыИсточника.Вставить("ОбъектыНазначения", Параметры.ОбъектыНазначения);

    ПараметрыОткрытия = УправлениеПечатьюСлужебныйКлиент.ПараметрыОткрытияФормыПечати();
    ПараметрыОткрытия.Вставить("ИсточникДанных", Параметры.ДополнительнаяОбработкаСсылка);
    ПараметрыОткрытия.Вставить("ПараметрыИсточника", ПараметрыИсточника);
    ПараметрыОткрытия.Вставить("ПараметрКоманды", Параметры.ОбъектыНазначения);
    
    // Важно: передаем идентификатор текущей формы для хранения результата во временном хранилище
    ПараметрыОткрытия.УникальныйИдентификаторХранилища = ЭтаФорма.УникальныйИдентификатор;

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

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


&НаКлиенте
Процедура ВыполнитьОткрытиеПечатнойФормыПослеФормирования(РезультатФоновойОперации, ПараметрыОткрытия) Экспорт
    Если РезультатФоновойОперации = Неопределено Тогда
        Возврат;
    КонецЕсли;

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

Важные нюансы реализации

Проанализируем несколько критических моментов, без которых печать может не заработать даже с новым кодом:

  1. Уникальный идентификатор: Обязательно передавайте ЭтаФорма.УникальныйИдентификатор. БСП использует его для того, чтобы «привязать» адрес временного хранилища к вашей форме. Если этого не сделать, данные могут быть очищены сборщиком мусора до того, как откроется форма печати.
  2. Отсутствие серверных вызовов в фоновом задании: Убедитесь, что в процедуре Печать в модуле объекта нет обращений к клиентским методам, предупреждениям или вопросам. Фоновое задание не имеет интерфейса и мгновенно завершится с ошибкой при попытке вызвать Сообщить (в некоторых случаях) или Предупреждение.
  3. Работа с офисными документами: Если ваша ВПФ формирует макеты в формате Word или Excel, в структуре СтруктураРезультата должно присутствовать соответствие ОфисныеДокументы. В новых версиях БСП адреса этих файлов должны быть явно прописаны в коллекции печатных форм.

Решение через расширение (для массовых случаев)

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

Нам нужно перехватить процедуру ПриСозданииНаСервере общей формы ПечатьДокументов и в случае, если Параметры.КоллекцияПечатныхФорм пуста, попытаться сформировать её принудительно, используя переданный ИдентификаторКоманды.

Рассмотрим пример кода для расширения (метод «Вместо»):


&Вместо("ПриСозданииНаСервере")
Процедура Расш1_ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    Если Параметры.КоллекцияПечатныхФорм = Неопределено И ЗначениеЗаполнено(Параметры.ПараметрыИсточника.ИдентификаторКоманды) Тогда
        // Пытаемся восстановить коллекцию по идентификатору команды
        ИменаМакетов = СтрРазделить(Параметры.ПараметрыИсточника.ИдентификаторКоманды, ",");
        // Вызываем серверную функцию формирования (её нужно реализовать по аналогии с БСП)
        Параметры.КоллекцияПечатныхФорм = СформироватьПечатныеФормы(ИменаМакетов, Отказ);
    КонецЕсли;
    
    ПродолжитьВызов(Отказ, СтандартнаяОбработка);
КонецПроцедуры

Однако помните, что путь с расширением — это временная мера. Разработчики 1С целенаправленно уходят от синхронной печати в сторону фоновых заданий, поэтому правильнее будет адаптировать код самих внешних обработок.

Резюмируем: Основная проблема после обновления ЗУП 3.1.27.23 заключается в том, что форма печати больше не может открываться «пустой». Используйте ТипКомандыВызовСерверногоМетода для простых форм или внедряйте механизм ДлительныеОперацииКлиент.ОжидатьЗавершение для форм с параметрами. Это обеспечит стабильную работу ваших доработок в будущих версиях программы.

← На главную