При разработке функционала печати или вывода документов Microsoft Word в системе 1С:Предприятие 8.3 программисты часто сталкиваются с ситуацией, когда код, идеально работающий в толстом клиенте, выдает критическую ошибку в тонком или веб-клиенте. Ошибка «Отсутствует отображение для типа 'ОболочкаActiveDocument'» — одна из самых распространенных. В этой статье мы подробно разберем, почему она возникает, и реализуем надежный механизм работы с шаблонами документов, который будет стабильно функционировать в любой среде.
Для начала проанализируем ситуацию. Тип ActiveDocument в 1С — это по сути обертка над COM-объектом приложения Microsoft Word. Когда мы создаем макет с типом «Active Document» и пытаемся получить его на стороне сервера, 1С создает COM-объект. Однако тонкий клиент и веб-клиент общаются с сервером через протокол передачи данных, использующий XDTO-сериализацию.
Ключевая проблема заключается в том, что COM-объекты (включая ОболочкаActiveDocument) не могут быть сериализованы. Платформа просто «не знает», как превратить живой объект Word в поток байтов для передачи по сети, и выдает ошибку отображения типов. Толстый клиент работает в едином адресном пространстве с объектами, поэтому там эта проблема не проявляется. Чтобы наше решение работало везде, нам нужно отказаться от передачи «объекта» и перейти к передаче «данных».
Самый эффективный и современный способ — это хранение шаблона Word не как ActiveDocument, а как ДвоичныеДанные. Рассмотрим по шагам, как перенастроить конфигурацию и переписать код.
.docx или .doc. Теперь для платформы это просто набор байтов, который она может легко передать с сервера на клиент.Теперь разберем программную реализацию. Нам нужно получить эти данные на сервере, поместить их во временное хранилище, передать адрес на клиент, сохранить файл локально и запустить его.
Рассмотрим пример кода для серверной части:
&НаСервере
Функция ПолучитьМакетНаСервере() Экспорт
// Получаем макет как двоичные данные
// Обратите внимание: имя макета должно соответствовать новому макету с типом Двоичные данные
Макет = Документы.эсЗаданиеСотруднику.ПолучитьМакет("Расш1_МакетWord_ДвоичныеДанные");
// Помещаем во временное хранилище и возвращаем адрес
Возврат ПоместитьВоВременноеХранилище(Макет, ЭтаФорма.УникальныйИдентификатор);
КонецФункции
Теперь проанализируем клиентскую часть. Здесь мы должны получить данные, записать их в файл во временный каталог пользователя и вызвать стандартное приложение ОС для открытия файла:
&НаКлиенте
Процедура ОткрытьДокументWord(Команда)
АдресХранилища = ПолучитьМакетНаСервере();
Если ЭтоАдресВременногоХранилища(АдресХранилища) Тогда
// Получаем двоичные данные из хранилища на клиенте
ДанныеФайла = ПолучитьИзВременногоХранилища(АдресХранилища);
// Формируем путь к временному файлу
ИмяФайла = КаталогВременныхФайлов() + "Инструкция.docx";
// Записываем данные в файл на диске пользователя
ДанныеФайла.Записать(ИмяФайла);
// Запускаем приложение, ассоциированное с расширением .docx
Попытка
ЗапуститьПриложение(ИмяФайла);
Исключение
Сообщить("Не удалось открыть файл. Проверьте, установлен ли Microsoft Word.");
КонецПопытки;
КонецЕсли;
КонецПроцедуры
Если мы планируем использовать веб-клиент, нам нужно учитывать ограничения безопасности браузеров. Браузер не может просто так «взять и записать» файл на диск C:\ пользователя без его ведома. Для полноценной работы нам потребуется Расширение работы с файлами.
Разберем, как модифицировать код для асинхронной работы, которая является стандартом для веб-клиента. Вместо прямой записи файла лучше использовать методы, которые предлагают пользователю сохранить файл или открывают его через диалог.
Рассмотрим использование метода ПолучитьФайлССервера, который является наиболее универсальным:
&НаКлиенте
Асинх Процедура ОткрытьДокументWordАсинх(Команда)
АдресХранилища = ПолучитьМакетНаСервере();
// Параметры получения файла
ПараметрыФайла = Новый ПараметрыПолученияФайла(Истина); // Истина - открыть после получения
ОписаниеФайла = Новый ОписаниеПередаваемогоФайла("Справка.docx", АдресХранилища);
// В веб-клиенте это вызовет стандартное окно загрузки браузера
// или открытие файла, если установлено расширение работы с файлами
Ждать ПолучитьФайлССервераАсинх(ОписаниеФайла, ПараметрыФайла);
КонецПроцедуры
Важно помнить: если в веб-клиенте не установлено расширение работы с файлами, метод ЗапуститьПриложение может не сработать. Поэтому использование ПолучитьФайлССервера является более надежным «дружелюбным» способом взаимодействия с пользователем.
Вернемся к вопросу из исходного сообщения: «На сервере нет ворда». Это стандартная ситуация для серверных мощностей. Попытка вызвать Новый COMОбъект("Word.Application") на сервере без установленного пакета MS Office приведет к ошибке «Интерфейс не поддерживается» или «Класс не зарегистрирован».
Рекомендация: Все манипуляции с заполнением данных в шаблоне (если они требуются) лучше проводить либо на клиенте (где Word есть), либо использовать библиотеки, работающие напрямую со структурой XML файла .docx. Поскольку современный формат Word — это ZIP-архив, 1С может распаковать его на сервере, заменить теги в XML-файлах и собрать обратно. Это позволит формировать документы даже там, где Word не установлен вовсе.
Если ваша конфигурация (например, КА, ERP или УТ) построена на базе БСП, мы крайне рекомендуем использовать штатные механизмы печати. В БСП уже решены проблемы кроссплатформенности и работы в различных клиентах.
Проанализируем работу через общий модуль УправлениеПечатью. Вместо того чтобы изобретать велосипед с записью временных файлов, можно зарегистрировать макет в подсистеме печати. Метод УправлениеПечатьюКлиент.ВыполнитьКомандуПечати берет на себя все нюансы:
Подведем итог нашему разбору. Ошибка «Отсутствует отображение для типа ОболочкаActiveDocument» — это сигнал о том, что вы пытаетесь передать сложный системный объект туда, где его невозможно воссоздать.
Чтобы решить проблему раз и навсегда, придерживайтесь следующего алгоритма:
Используя этот подход, вы обеспечите стабильную работу вашей конфигурации и избавите пользователей от неприятных ошибок при формировании важных документов.