Как передать макет типа ActiveDocument с сервера на клиент в 1С

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

Выясним причину проблемы

При переводе обработок и печатных форм с обычных форм на управляемые разработчики часто сталкиваются с ошибками при попытке передать макет типа ActiveDocument (документы MS Excel или MS Word) с сервера на клиент.

Проанализируем, почему прямая передача или вызов метода ПолучитьИзВременногоХранилища() не работают. Объект типа ActiveDocument и инициализируемый им COM-объект привязаны к контексту выполнения и памяти конкретного процесса операционной системы. Платформа 1С:Предприятие не может передавать COM-объекты через границу контекстов «Сервер — Клиент».

Кроме того, если пытаться вызывать метод Получить() объекта ActiveDocument на сервере, платформа попытается запустить MS Excel в контексте системной службы сервера 1С. Это приводит к ошибкам, если на сервере не установлен MS Office, используется сервер на базе Linux или у пользователя службы сервера отсутствуют права на запуск DCOM-объектов.

Решение задачи: передача через двоичные данные

Рассмотрим по шагам надежный способ передачи файла макета с сервера на клиент:

  1. На сервере получаем макет объекта обработки или справочника.
  2. Сохраняем макет во временный файл на сервере с помощью метода Записать().
  3. Создаем объект ДвоичныеДанные из временного файла и помещаем его во временное хранилище.
  4. Передаем адрес хранилища на клиент.
  5. На клиенте извлекаем двоичные данные, записываем их во временный файл локального компьютера и инициализируем работу с Excel.

Разберем реализацию функции на сервере:


&НаСервере
Функция ПолучитьМакетСервер(ИмяМакета)
    
    ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xls");
    
    ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
    ЭтотМакет = ОбработкаОбъект.ПолучитьМакет(ИмяМакета);
    ЭтотМакет.Записать(ИмяВременногоФайла);
    
    Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяВременногоФайла));
    
    // Удаляем временный файл на сервере после считывания
    УдалитьФайлы(ИмяВременногоФайла);
    
    Возврат Адрес;
    
КонецФункции

Посмотрим на пример обработки полученных данных на клиенте с помощью ПолучитьCOMОбъект():


&НаКлиенте
Процедура ОткрытьМакетНаКлиенте()
    
    Попытка
        АдресМакета = ПолучитьМакетСервер("Макет");
        
        Если ЗначениеЗаполнено(АдресМакета) Тогда
            ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресМакета);
            ИмяФайлаКлиент = ПолучитьИмяВременногоФайла("xls");
            ДвоичныеДанные.Записать(ИмяФайлаКлиент);
            
            // Инициализируем COM-объект для работы с книгой Excel
            МакетCOM = ПолучитьCOMОбъект(ИмяФайлаКлиент);
            
            // Выполняем действия с листами и ячейками...
        КонецЕсли;
    Исключение
        Сообщить("Не удалось получить макет: " + ОписаниеОшибки());
    КонецПопытки;
    
КонецПроцедуры

Рассмотрим альтернативный способ открытия файла на клиенте через явный запуск приложения Excel:


&НаКлиенте
Процедура ОткрытьЧерезExcelApplication()
    
    АдресМакета = ПолучитьМакетСервер("Макет");
    ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресМакета);
    
    ИмяФайлаКлиент = ПолучитьИмяВременногоФайла("xlsx");
    ДвоичныеДанные.Записать(ИмяФайлаКлиент);
    
    Эксель = Новый COMОбъект("Excel.Application");
    Эксель.Visible = Истина;
    Книга = Эксель.WorkBooks.Open(ИмяФайлаКлиент);
    Лист = Книга.WorkSheets(1);
    
    // Заполнение или обработка листов
    
КонецПроцедуры

Альтернативные варианты и рекомендации

Проанализируем дополнительные подходы к устройству макетов в конфигурации:

  1. Использование типа «Двоичные данные» для макета: Если макет не требуется редактировать прямо внутри конфигуратора 1С через встроенный редактор ActiveDocument, сохраните его в дереве метаданных как макет типа Двоичные данные. В этом случае метод ПолучитьМакет() сразу вернет объект двоичных данных, и на сервере не потребуется создавать временный файл для промежуточного сохранения.
  2. Перевод макета на «Табличный документ»: Если функционал макета позволяет, перенесите его структуру в обычный ТабличныйДокумент. Табличные документы поддерживаются платформой на любых операционных системах, передаются между сервером и клиентом без использования временного хранилища и не требуют наличия MS Office.
← На главную