Как вывести макет ActiveDocument на печать из внешней обработки в 1С?

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

Работа с макетами типа ActiveDocument (традиционно это файлы Microsoft Word или Excel) часто вызывает затруднения у начинающих разработчиков 1С, особенно при переходе от файловой базы к клиент-серверному варианту работы. Основная сложность заключается в том, что серверная часть 1С не умеет напрямую взаимодействовать с графическим интерфейсом приложений MS Office. В этой статье мы подробно разберем, как правильно организовать печать Word-шаблона из внешней обработки, рассмотрим типичные ошибки и напишем отказоустойчивый код.

Почему ActiveDocument не печатается на сервере?

Разберем ситуацию: в файловом режиме код работает прекрасно, но как только обработка запускается в составе 1C:ERP на сервере, возникают ошибки. Выясним причину. Серверные процессы 1С работают в так называемой «нулевой сессии» Windows. В этой среде запуск приложений с графическим интерфейсом (GUI), таких как WINWORD.EXE, либо полностью запрещен, либо сильно ограничен политиками безопасности. Кроме того, у системного пользователя USR1CV8, под которым обычно запущена служба сервера, нет прав на инициализацию COM-объектов Microsoft Office.

Важное правило: формирование и заполнение макета ActiveDocument должно происходить исключительно на стороне клиента (&НаКлиенте). Роль сервера сводится к тому, чтобы извлечь двоичные данные макета из конфигурации (или внешней обработки) и передать их на клиентскую машину.

Шаг 1. Получение макета во внешней обработке

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


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

Обратите внимание на использование РеквизитФормыВЗначение("Объект"). Это критически важный момент для внешних обработок, так как только через него мы получаем доступ к методу ПолучитьМакет() на сервере.

Шаг 2. Подготовка файла на стороне клиента

Теперь рассмотрим, как принять эти данные на клиенте и открыть их в приложении MS Word. Посмотрим на алгоритм: мы должны забрать двоичные данные из хранилища, сохранить их в локальный временный файл на диске пользователя и передать путь к этому файлу в COM-объект Word.Application.


&НаКлиенте
Процедура НапечататьМакетWord(Команда)
    
    // Получаем адрес с сервера
    АдресМакета = ПолучитьАдресМакетаВоВременномХранилище();
    
    Если ЭтоАдресВременногоХранилища(АдресМакета) Тогда
        
        // Получаем двоичные данные на клиент
        ДанныеМакета = ПолучитьИзВременногоХранилища(АдресМакета);
        
        // Формируем путь к временному файлу на локальном компьютере
        ПутьКЛокальномуФайлу = КаталогВременныхФайлов() + "Template_" + Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + ".docx";
        ДанныеМакета.Записать(ПутьКЛокальномуФайлу);
        
        // Запускаем печать или редактирование
        ВывестиДанныеВWord(ПутьКЛокальномуФайлу);
        
    КонецЕсли;
    
КонецПроцедуры

Шаг 3. Взаимодействие с COM-объектом Word

Рассмотрим подробнее процедуру взаимодействия с MS Word. Нам необходимо инициализировать COM-соединение, открыть документ и сделать его видимым для пользователя. Проанализируем пример кода, который также включает безопасное завершение работы в случае ошибки:


&НаКлиенте
Процедура ВывестиДанныеВWord(ПутьКФайлу)
    
    Попытка
        // Пытаемся создать объект Word
        WordПриложение = Новый COMОбъект("Word.Application");
    Исключение
        Сообщить("Не удалось запустить Microsoft Word. Убедитесь, что программа установлена.");
        Возврат;
    КонецПопытки;
    
    Попытка
        // Открываем документ
        Документ = WordПриложение.Documents.Open(ПутьКФайлу);
        WordПриложение.Visible = Истина;
        WordПриложение.Activate();
        
        // Здесь можно добавить код для поиска и замены тегов в макете
        // Пример: Документ.Content.Find.Execute("{НомерДокумента}", , , , , , , , , "001", 2);
        
    Исключение
        // Если что-то пошло не так, закрываем Word, чтобы процесс не висел в памяти
        Если WordПриложение <> Неопределено Тогда
            WordПриложение.Quit(Ложь); // Закрыть без сохранения
            WordПриложение = Неопределено;
        КонецЕсли;
        Сообщить("Произошла ошибка при работе с документом: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Типичные ошибки и их решение

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

Рекомендация: Всегда давайте своим функциям уникальные префиксы, например, Satoshi_ПолучитьМакет или Сервер_ПолучитьМакетДляПечати. Это исключит путаницу с глобальным контекстом 1С.

Еще один важный момент связан с использованием Библиотеки стандартных подсистем (БСП). Если вы работаете в 1C:ERP, 1C:КА или 1С:УТ 11, в конфигурации уже есть готовые механизмы для печати документов в формате Word. Выясним преимущества использования БСП:

  1. Кроссплатформенность: БСП частично умеет работать с документами без установленного Word на сервере (при использовании формата DOCX как XML-структуры).
  2. Удобство: Вы можете использовать теги вида {v8 ИмяПоля} прямо в макете, и БСП автоматически заполнит их данными из вашей выборки.
  3. Стабильность: Механизмы БСП включают в себя отработанные алгоритмы очистки временных файлов и корректного закрытия COM-соединений.

Рассмотрим, как это выглядит в БСП. Вместо ручного манипулирования COM-объектом, вы вызываете функции общего модуля УправлениеПечатьюMSWord. Это значительно сокращает объем кода в вашей внешней обработке и делает его более надежным.

Заключение

Подведем итоги. Чтобы успешно вывести на печать макет ActiveDocument во внешней обработке, необходимо придерживаться следующей последовательности действий:

  1. На сервере извлекаем макет из объекта внешней обработки через РеквизитФормыВЗначение.
  2. Передаем данные на клиент через временное хранилище.
  3. На клиенте сохраняем двоичные данные в локальный файл.
  4. Используем COMОбъект("Word.Application") для открытия этого файла.
  5. Обязательно оборачиваем работу с Word в блоки Попытка...Исключение, чтобы предотвратить "зависание" процессов WINWORD.EXE в диспетчере задач.

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

← На главную