Как отследить завершение формирования файлов Word при групповой печати внешних печатных форм

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

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

Почему возникает проблема «каши» и рассинхронизации

Разберем ситуацию на программном уровне. Когда мы вызываем клиентский метод Печать внешней обработки, внутри которого происходит обращение к COM-объекту Word.Application, 1С отправляет команду операционной системе на запуск процесса или взаимодействие с ним. Однако Word является внешним по отношению к 1С приложением. Код 1С внутри цикла Для каждого выполняется синхронно в контексте платформы, но команды COM-серверу могут помещаться в очередь или выполняться в отдельном потоке Word. Программа 1С не «ждет» физического появления файла на диске или закрытия окна Word, если это явно не прописано в коде, и переходит к следующей итерации цикла.

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


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

Выясним причину странного поведения сообщений Сообщить. Из-за высокой скорости работы интерпретатора 1С и задержек в инициализации COM-объектов, сообщения «Старт» и «Стоп» могут выводиться раньше, чем визуально откроется окно Word. Если в коде ВПФ используются асинхронные вызовы или обработчики ожидания, ситуация усугубляется еще сильнее.

Решение 1: Проверка блокировки и существования файла

Если ваша задача — дождаться момента, когда все файлы будут сформированы для дальнейшей обработки (например, для сбора в один архив), самым простым, но действенным методом является цикл проверки доступности файла. Файл, который формируется Word-ом, обычно заблокирован операционной системой до момента окончания записи или закрытия потока.

Рассмотрим алгоритм реализации такой проверки:

  1. При формировании файла в ВПФ передавайте заранее определенное имя файла.
  2. В основном цикле печати после вызова метода Печать добавьте процедуру ожидания.
  3. В этой процедуре в цикле пытайтесь открыть файл в исключительном режиме.

Пример реализации функции ожидания:


Функция ФайлГотовКРаботе(ПолноеИмяФайла)
    ФайлНаДиске = Новый Файл(ПолноеИмяФайла);
    Если Не ФайлНаДиске.Существует() Тогда
        Возврат Ложь;
    КонецЕсли;

    Попытка
        // Пытаемся переименовать файл сам в себя - 
        // это самый быстрый способ проверить блокировку ОС
        ПереместитьФайл(ПолноеИмяФайла, ПолноеИмяФайла);
        Возврат Истина;
    Исключение
        Возврат Ложь;
    КонецПопытки;
КонецФункции

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

Решение 2: Использование свойств COM-объекта Word

Если у вас есть возможность модифицировать код внутри ВПФ или получить ссылку на объект Word.Application, мы можем проанализировать внутреннее состояние принтера Word. У объекта Word есть свойство BackgroundPrintingStatus, которое показывает количество заданий в очереди фоновой печати.

Разберем, как это применить. Пока значение BackgroundPrintingStatus больше нуля, Word продолжает обработку документа. Проанализируем пример кода ожидания:


// Предположим, MSWord - это ссылка на COM-объект Word.Application
Пока MSWord.BackgroundPrintingStatus > 0 Цикл
    // Ждем завершения фоновых процессов Word
    #Если Клиент Тогда
        ОбработкаПрерыванияПользователя();
    #КонецЕсли
КонецЦикла;

Важно помнить, что этот метод работает только в том случае, если вы сохраняете ссылку на COM-объект в течение всего процесса печати. Если форма ВПФ закрывается и объект уничтожается, отследить состояние будет невозможно.

Решение 3: Реализация очереди через обработчик ожидания

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

Посмотрим на шаги реализации:

  1. Помещаем список всех ВПФ, которые нужно напечатать, в массив ОчередьПечати.
  2. Создаем процедуру НапечататьСледующийИзОчереди().
  3. В этой процедуре извлекаем первый элемент массива, вызываем его метод Печать.
  4. Если в массиве еще остались элементы, вызываем ПодключитьОбработчикОжидания("НапечататьСледующийИзОчереди", 1, Истина).

Такой подход дает Word-у необходимую «паузу» в 1 секунду между инициализациями процессов, что обычно достаточно для стабильной работы без перемешивания потоков сообщений.

Решение 4: Формирование на сервере (рекомендуемый современный подход)

Если проект позволяет отойти от использования клиентских методов и COM-соединений, крайне рекомендуем перевести формирование документов Word на серверную сторону. Современные форматы .docx являются обычными zip-архивами с xml внутри. Библиотеки для работы с ними позволяют формировать документы без установленного Microsoft Word на сервере.

Преимущества этого метода:

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

Рекомендации по использованию БСП

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

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

Выясним итог: для решения вашей проблемы в текущем коде наиболее эффективным будет внедрение очереди печати через обработчик ожидания или цикл проверки занятости файла. Это позволит синхронизировать быстрый код 1С с медленным процессом формирования документов в Microsoft Word.

← На главную