Разработка механизмов печати и формирования документов часто сталкивается с архитектурным ограничением платформы 1С: разделением на клиентскую и серверную части. Типичная ситуация: мы успешно заполнили вордовский шаблон на сервере (так как именно там есть доступ к данным базы), но теперь нам нужно отдать этот файл пользователю, чтобы он выбрал место для сохранения на своем компьютере. Попытка просто передать переменную, содержащую COMОбъект (Word), приводит к ошибке «Отсутствует отображение для типа COMОбъект». Разберем подробно, почему так происходит и как реализовать корректную схему работы.
Проанализируем причину возникновения ошибки. COMОбъект — это не сам файл, а программный интерфейс для управления приложением Microsoft Word, которое запущено в памяти конкретного компьютера. Если мы создаем объект на сервере, он живет в оперативной памяти сервера. Когда мы пытаемся передать его на клиент, платформа 1С не может «перетащить» запущенный процесс WINWORD.EXE через сеть. Сервер и клиент — это разные среды, и между ними можно передавать только те типы данных, которые платформа умеет сериализовать (превращать в поток байтов), такие как строки, числа, структуры или ДвоичныеДанные.
Для решения задачи нам нужно изменить подход: вместо передачи управления приложением, мы должны передать сам сформированный файл. Рассмотрим пошагово, как это сделать:
ActiveDocument.ДвоичныеДанные.ВременноеХранилище и получаем адрес (строку).ДиалогВыбораФайла и сохраняем данные по выбранному пользователем пути.Разберем реализацию каждого этапа в коде.
Нам необходимо создать функцию, которая выполнит всю «грязную» работу с 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. Переводим файл в двоичные данные и кладем в хранилище
ДвоичныеДанные = Новый ДвоичныеДанные(ИмяВременногоФайла);
АдресХранилища = ПоместитьВоВременноеХранилище(ДвоичныеДанные, ЭтаФорма.УникальныйИдентификатор);
// Удаляем временный файл с диска сервера, он больше не нужен
УдалитьФайлы(ИмяВременногоФайла);
Возврат АдресХранилища;
КонецФункции
Теперь рассмотрим клиентскую процедуру. Мы должны сначала получить адрес из серверной функции, а затем спросить у пользователя, куда он хочет сохранить файл, используя ДиалогВыбораФайла.
&НаКлиенте
Процедура СформироватьИСохранить(Команда)
// Получаем адрес файла
АдресФайла = СформироватьФайлНаСервере();
Если ПустаяСтрока(АдресФайла) Тогда
Возврат;
КонецЕсли;
// Настраиваем диалог сохранения
Диалог = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
Диалог.Заголовок = "Выберите путь для сохранения договора";
Диалог.ПолноеИмяФайла = "НовыйДоговор.docx";
Диалог.Фильтр = "Документ Word (*.docx)|*.docx";
Если Диалог.Выбрать() Тогда
ВыбранныйПуть = Диалог.ПолноеИмяФайла;
// Получаем файл из хранилища и записываем на диск клиента
Данные = ПолучитьИзВременногоХранилища(АдресФайла);
Данные.Записать(ВыбранныйПуть);
// Предлагаем сразу открыть файл пользователю
Попытка
ЗапуститьПриложение(ВыбранныйПуть);
Исключение
Сообщить("Файл сохранен, но не удалось открыть его автоматически.");
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Проанализируем ситуацию с использованием COM-объектов на стороне сервера более глубоко. Важно помнить: компания Microsoft официально не рекомендует использовать офисные приложения на стороне сервера (в неинтерактивных сессиях). Это может привести к нестабильности, когда процессы WINWORD.EXE «зависают» и потребляют ресурсы, не закрываясь корректно.
Если ваш сервер 1С работает под 64-битной версией Windows, а Microsoft Office установлен 32-битный, вы столкнетесь с проблемой инициализации COM-объекта. В этом случае потребуется настройка службы компонентов (DCOM Config) для библиотеки Microsoft Word Document, чтобы разрешить запуск от имени конкретного пользователя.
В современных версиях платформы (начиная с 8.3.15) рекомендуется использовать асинхронные методы для работы с файлами. Это особенно критично для Веб-клиента, где синхронные вызовы блокируют работу браузера. Вместо прямого использования Диалог.Выбрать() и Записать(), стоит рассмотреть метод НачатьПолучениеФайлаССервера(). Это позволяет приложению оставаться отзывчивым во время передачи данных.
Чтобы полностью избежать проблем с установкой Word на сервер, мы можем использовать методы прямой генерации файлов формата .docx. Поскольку современный документ Word — это фактически ZIP-архив с набором XML-файлов, существуют библиотеки и методы, позволяющие программно изменять содержимое этих XML-структур. В этом случае мы работаем с файлом как с двоичными данными или текстом, подставляя значения в теги шаблона. Такой файл формируется мгновенно, не требует установленного Office на сервере и легко передается на клиент через ту же схему с ПоместитьВоВременноеХранилище.
Подведем итог: Главный секрет успеха заключается в том, чтобы не пытаться передать «живой» объект Word, а вовремя превратить его в «тушку» файла (двоичные данные). Сервер создает данные — клиент их забирает и сохраняет. Это надежная и стабильная схема, работающая во всех типах клиентов 1С.