Как реализовать печать в формате Word из внешней обработки в 1С 8.3

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

При разработке внешних обработок часто возникает задача добавить возможность вывода данных в печатную форму формата Microsoft Word (docx). Если в типовых печатных формах (ВПФ) всё жестко регламентировано БСП (Библиотекой стандартных подсистем), то во внешней обработке, которая не привязана к конкретному объекту метаданных, разработчики часто сталкиваются с трудностями. Рассмотрим подробнее, как правильно связать форму обработки, её модуль объекта и механизмы БСП для формирования офисных документов.

Постановка задачи и анализ ситуации

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

Основная проблема, с которой сталкиваются программисты (как показано в обсуждении), — это ошибка Метод объекта не обнаружен (Найти) при вызове функций БСП. Это происходит из-за того, что структура коллекции печатных форм не инициализирована должным образом или идентификаторы макетов не совпадают. Выясним причину: функции БСП ожидают строго определенные типы данных (ТаблицаЗначений) и наличие определенных колонок.

Шаг 1. Подготовка формы обработки

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


&НаКлиенте
Процедура Печать(Команда)
    
    // Вызываем серверную функцию для подготовки данных
    КоллекцияПечатныхФормМассив = ПечатьНаСервере();
    
    // Используем стандартный клиентский метод БСП для вывода окна печати
    УправлениеПечатьюКлиент.ПечатьДокументов(КоллекцияПечатныхФормМассив);
    
КонецПроцедуры

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

Шаг 2. Реализация логики в модуле объекта

Теперь посмотрим на пример реализации логики в модуле объекта. Здесь важно правильно использовать методы УправлениеПечатью.СведенияОПечатнойФорме и правильно работать с макетом Word, который должен храниться в обработке как Двоичные данные.


Процедура СформироватьПечатныеФормы(КоллекцияПечатныхФорм, ОбъектыПечати, ТаблицаСотрудников) Экспорт 
    
    // Получаем макет из состава обработки
    ДвоичныеДанныеМакета = ПолучитьМакет("ПФ_DOC_Извещение");
    
    Если ДвоичныеДанныеМакета <> Неопределено Тогда
        
        // Получаем структуру сведений о печатной форме из коллекции
        // Идентификатор "Извещение" должен СТРОГО совпадать с тем, что передали в ПодготовитьКоллекциюПечатныхФорм
        ПечатнаяФорма = УправлениеПечатью.СведенияОПечатнойФорме(КоллекцияПечатныхФорм, "Извещение");
        
        // Для Word-документов НЕЛЬЗЯ использовать ПечатнаяФорма.ТабличныйДокумент
        // Вместо этого используется соответствие ОфисныеДокументы
        
        // Инициализируем макет офисного документа
        Макет = УправлениеПечатью.ИнициализироватьМакетОфисногоДокумента(ДвоичныеДанныеМакета, Неопределено);
        ПечатнаяФормаДокумента = УправлениеПечатью.ИнициализироватьПечатнуюФорму(Неопределено, Макет.НастройкиСтраницыМакета, Макет);
        
        // Описываем области (если в Word-файле есть Begin_Область / End_Область)
        // Если печать простая (замена параметров), можно пропустить создание областей
        
        // Пример заполнения параметров для каждого сотрудника
        Для Каждого СтрокаСотрудник Из ТаблицаСотрудников Цикл
            
            ДанныеЗаполнения = Новый Структура;
            ДанныеЗаполнения.Вставить("ФИО", СтрокаСотрудник.ФИО);
            ДанныеЗаполнения.Вставить("Должность", СтрокаСотрудник.Должность);
            
            // Если документ многостраничный (на каждого сотрудника своя страница)
            // УправлениеПечатью.ПрисоединитьОбласть(ПечатнаяФормаДокумента, Макет.Область("Основная"), ДанныеЗаполнения);
        КонецЦикла;
        
        // Формируем итоговый документ во временное хранилище
        АдресХранилища = УправлениеПечатью.СформироватьДокумент(ПечатнаяФормаДокумента);
        
        // Очищаем ресурсы
        УправлениеПечатью.ОчиститьСсылки(ПечатнаяФормаДокумента, Ложь);
        УправлениеПечатью.ОчиститьСсылки(Макет);
        
        // Помещаем результат в структуру печатной формы
        ОфисныеДокументы = Новый Соответствие;
        ОфисныеДокументы.Вставить(АдресХранилища, "ИзвещениеСотрудников.docx");
        
        ПечатнаяФорма.ОфисныеДокументы = ОфисныеДокументы;
        
    КонецЕсли;

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

Особенности работы с макетами Word

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

  1. Параметры в тексте документа должны выглядеть так: {v8 ИмяПараметра}.
  2. Если вам нужно выводить таблицу или повторяющиеся блоки, используйте механизмы областей. В Word это делается через закладки (bookmarks) или специальные теги v8 Begin_ИмяОбласти и v8 End_ИмяОбласти.
  3. Важный момент: БСП версии 3.0 и выше позволяет формировать Word без использования COM-соединения на сервере (через прямой парсинг XML). Это значительно ускоряет работу и позволяет печатать на серверах под управлением Linux.

Разбор типичных ошибок

В ходе обсуждения автор столкнулся с ошибкой: Значение не является значением объектного типа (ТабличныйДокумент). Выясним причину: это классическая ошибка при попытке применить логику MXL-печати (табличных документов) к офисным документам.

Запомним правила:

Альтернативный метод (COM-объект)

Если ваша база работает только на Windows и вам не нужно использовать механизмы БСП, можно воспользоваться прямым обращением к MS Word через COM. Рассмотрим этот пример для понимания разницы:


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

Однако такой метод считается устаревшим. Рекомендуем использовать стандартные механизмы УправлениеПечатью, так как они обеспечивают стабильность, корректную очистку временных файлов и независимость от установленного ПО на сервере.

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

← На главную