Как вызвать диалог сохранения файла Word, сформированного на сервере 1С?

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

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

Почему нельзя передать COM-объект с сервера на клиент?

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

Алгоритм правильного сохранения файла

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

  1. На сервере: Формируем документ Word, используя ActiveDocument.
  2. На сервере: Сохраняем результат во временный файл на диске сервера.
  3. На сервере: Читаем этот файл в объект ДвоичныеДанные.
  4. На сервере: Помещаем данные во ВременноеХранилище и получаем адрес (строку).
  5. На клиенте: Получаем этот адрес, вызываем ДиалогВыбораФайла и сохраняем данные по выбранному пользователем пути.

Разберем реализацию каждого этапа в коде.

Этап 1: Формирование и помещение в хранилище (Сервер)

Нам необходимо создать функцию, которая выполнит всю «грязную» работу с COM-объектами на стороне сервера и вернет нам лишь «билет» на скачивание файла — адрес во временном хранилище.


&НаСервере
Функция СформироватьФайлНаСервере()
    
    // 1. Создаем объект Word
    Попытка
        Word = Новый COMОбъект("Word.Application");
    Исключение
        Сообщить("MS Word не установлен на сервере!");
        Возврат "";
    КонецПопытки;
    
    // 2. Работаем с шаблоном (пример упрощен)
    Шаблон = Word.Documents.Add("C:\Templates\Contract.dotx");
    // Здесь идет заполнение параметров документа
    // Шаблон.Variables("ИмяКлиента").Value = "Иванов И.И.";
    
    // 3. Сохраняем сформированный документ во временную папку сервера
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("docx");
    Шаблон.SaveAs(ИмяВременногоФайла);
    
    // Закрываем Word, чтобы процессы не висели в памяти
    Word.Quit();
    
    // 4. Переводим файл в двоичные данные и кладем в хранилище
    ДвоичныеДанные = Новый ДвоичныеДанные(ИмяВременногоФайла);
    АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ЭтаФорма.УникальныйИдентификатор);
    
    // Удаляем временный файл с диска сервера, он больше не нужен
    УдалитьФайлы(ИмяВременногоФайла);
    
    Возврат АдресХранилища;
    
КонецФункции

Этап 2: Выбор пути и сохранение (Клиент)

Теперь рассмотрим клиентскую процедуру. Мы должны сначала получить адрес из серверной функции, а затем спросить у пользователя, куда он хочет сохранить файл, используя ДиалогВыбораФайла.


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

Важные нюансы работы на сервере

Проанализируем ситуацию с использованием COM-объектов на стороне сервера более глубоко. Важно помнить: компания Microsoft официально не рекомендует использовать офисные приложения на стороне сервера (в неинтерактивных сессиях). Это может привести к нестабильности, когда процессы WINWORD.EXE «зависают» и потребляют ресурсы, не закрываясь корректно.

Если ваш сервер 1С работает под 64-битной версией Windows, а Microsoft Office установлен 32-битный, вы столкнетесь с проблемой инициализации COM-объекта. В этом случае потребуется настройка службы компонентов (DCOM Config) для библиотеки Microsoft Word Document, чтобы разрешить запуск от имени конкретного пользователя.

Современный асинхронный подход

В современных версиях платформы (начиная с 8.3.15) рекомендуется использовать асинхронные методы для работы с файлами. Это особенно критично для Веб-клиента, где синхронные вызовы блокируют работу браузера. Вместо прямого использования Диалог.Выбрать() и Записать(), стоит рассмотреть метод НачатьПолучениеФайлаССервера(). Это позволяет приложению оставаться отзывчивым во время передачи данных.

Альтернатива: формирование без COM

Чтобы полностью избежать проблем с установкой Word на сервер, мы можем использовать методы прямой генерации файлов формата .docx. Поскольку современный документ Word — это фактически ZIP-архив с набором XML-файлов, существуют библиотеки и методы, позволяющие программно изменять содержимое этих XML-структур. В этом случае мы работаем с файлом как с двоичными данными или текстом, подставляя значения в теги шаблона. Такой файл формируется мгновенно, не требует установленного Office на сервере и легко передается на клиент через ту же схему с ПоместитьВоВременноеХранилище.

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

← На главную