При разработке в клиент-серверном варианте 1С:Предприятия часто возникает классическая дилемма: необходимо сформировать печатную форму в формате Word, используя заранее подготовленный макет, однако на серверной машине пакет Microsoft Office не установлен. Попытка создать COMОбъект("Word.Application") непосредственно на сервере в этом случае приведет к ошибке. В данной статье мы разберем, как правильно организовать передачу данных между сервером и клиентом, чтобы использовать ресурсы локального компьютера пользователя для формирования и отображения документа.
Рассмотрим ситуацию: в конфигурации (например, КА или ERP) в расширении создан макет типа «Двоичные данные» или «Active document», содержащий шаблон договора. Когда код выполняется на сервере, 1С имеет доступ к макету, но не имеет инструментов для его визуализации или заполнения через COM, так как библиотеки Word отсутствуют в операционной системе сервера. Наша задача — извлечь макет на сервере, передать его на клиент и уже там запустить Word.
Это наиболее прямой и эффективный способ, когда требуется использовать привычные методы работы с объектной моделью Microsoft Office. Основная идея заключается в том, что сервер подготавливает двоичные данные макета, а клиент их принимает и сохраняет в локальный временный файл.
Проанализируем пошагово реализацию этого метода. Нам понадобятся две процедуры: одна серверная для получения данных и одна клиентская для их обработки.
Шаг 1. Получение макета на сервере
На стороне сервера мы обращаемся к метаданным макета и помещаем его во временное хранилище. Это позволяет передать большой объем данных (файл) между контекстами выполнения кода.
&НаСервере
Функция ПолучитьАдресМакетаВоВременномХранилище() Экспорт
// Создаем уникальный идентификатор для адреса в хранилище
АдресХранилища = Новый УникальныйИдентификатор;
// Получаем макет из метаданных (указываем путь к макету в расширении или основной конфигурации)
// Например, для документа "ЗаданиеСотруднику"
Макет = Документы.эсЗаданиеСотруднику.ПолучитьМакет("ПФ_DOC_Ворд");
// Помещаем макет в хранилище и возвращаем адрес для клиента
Возврат ПоместитьВоВременноеХранилище(Макет, АдресХранилища);
КонецФункции
Шаг 2. Работа на стороне клиента
Теперь на клиенте мы вызываем серверную функцию, получаем адрес, извлекаем данные и инициализируем COM-объект. Обратите внимание, что создание объекта Word.Application происходит именно здесь.
&НаКлиенте
Процедура СформироватьДокументWord(Команда)
// Получаем адрес макета с сервера
АдресМакета = ПолучитьАдресМакетаВоВременномХранилище();
// Извлекаем данные из хранилища на клиент
МакетФайла = ПолучитьИзВременногоХранилища(АдресМакета);
// Получаем COM-объект (Word должен быть установлен на ПК пользователя)
Попытка
Word = МакетФайла.Получить(); // Получаем объект из двоичных данных макета
// Сначала скрываем приложение, чтобы пользователь не видел процесс заполнения
Word.Application.Visible = Ложь;
// Активируем первый документ в коллекции
Документ = Word.Application.Documents(1);
Документ.Activate();
// Здесь можно добавить код заполнения параметров (поиск и замена текста)
// Делаем документ видимым для пользователя
Word.Application.Visible = Истина;
Исключение
Сообщить("Ошибка при работе с Word: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Если вы работаете в современной конфигурации, такой как «Комплексная автоматизация», в ней уже присутствует подсистема «Печать». Использование БСП — это более профессиональный и надежный путь, так как он автоматически обрабатывает очистку временных файлов и корректно работает с различными версиями офисного ПО.
В БСП для этих целей используются механизмы модуля УправлениеПечатью. Вместо ручного манипулирования макетами, мы рекомендуем изучить функции:
УправлениеПечатью.МакетПечатнойФормы — для получения структуры макета.УправлениеПечатьюКлиент.ВыполнитьКомандуПечати — для стандартизированного вывода.Преимущество БСП заключается в том, что вы можете использовать специальные теги в Word-документе вида {v8 ИмяПоля}. Платформа 1С умеет автоматически заменять эти теги данными из структуры, которую вы подготовите на сервере, без прямого обращения к методам COM-объекта в коде.
Иногда задача состоит не в программном заполнении шаблона, а в простом открытии готового файла для ознакомления. В этом случае использование COM-объекта может быть избыточным и потенциально нестабильным (например, если у пользователя установлен не Microsoft Word, а LibreOffice). Выясним, как сделать это проще.
Рассмотрим алгоритм с использованием метода ЗапуститьПриложение():
.docx во временный каталог пользователя.ЗапуститьПриложение(ПутьКФайлу).
&НаКлиенте
Процедура ОткрытьМакетБезCOM()
Адрес = ПолучитьАдресМакетаНаСервере();
Данные = ПолучитьИзВременногоХранилища(Адрес);
// Получаем безопасное имя временного файла
ПутьКФайлу = ПолучитьИмяВременногоФайла("docx");
// Записываем данные на диск клиента
Данные.Записать(ПутьКФайлу);
// Запускаем приложение по умолчанию для данного типа файла
ЗапуститьПриложение(ПутьКФайлу);
КонецПроцедуры
Этот метод наиболее безопасен, так как он не зависит от конкретной версии Word и не «вешает» процесс в памяти при возникновении программных ошибок.
Проанализируем основные ошибки, которые совершают начинающие разработчики при реализации подобных задач:
КаталогВременныхФайлов() возвращает разные пути на сервере и на клиенте. Никогда не пытайтесь записать файл на сервере и прочитать его по тому же пути на клиенте в клиент-серверном режиме.ПолучитьФайл() для скачивания документа пользователем.Active document может быть ограничено. В таких случаях лучше хранить шаблоны как Двоичные данные.Выбор конкретного метода зависит от ваших задач. Если нужно просто показать документ — используйте ЗапуститьПриложение. Если требуется сложная замена текста по множеству закладок и сохранение управления над документом — используйте передачу через временное хранилище и COM на клиенте.