При переводе обработок и печатных форм с обычных форм на управляемые разработчики часто сталкиваются с ошибками при попытке передать макет типа ActiveDocument (документы MS Excel или MS Word) с сервера на клиент.
Проанализируем, почему прямая передача или вызов метода ПолучитьИзВременногоХранилища() не работают. Объект типа ActiveDocument и инициализируемый им COM-объект привязаны к контексту выполнения и памяти конкретного процесса операционной системы. Платформа 1С:Предприятие не может передавать COM-объекты через границу контекстов «Сервер — Клиент».
Кроме того, если пытаться вызывать метод Получить() объекта ActiveDocument на сервере, платформа попытается запустить MS Excel в контексте системной службы сервера 1С. Это приводит к ошибкам, если на сервере не установлен MS Office, используется сервер на базе Linux или у пользователя службы сервера отсутствуют права на запуск DCOM-объектов.
Рассмотрим по шагам надежный способ передачи файла макета с сервера на клиент:
Записать().ДвоичныеДанные из временного файла и помещаем его во временное хранилище.Разберем реализацию функции на сервере:
&НаСервере
Функция ПолучитьМакетСервер(ИмяМакета)
ИмяВременногоФайла = ПолучитьИмяВременногоФайла("xls");
ОбработкаОбъект = РеквизитФормыВЗначение("Объект");
ЭтотМакет = ОбработкаОбъект.ПолучитьМакет(ИмяМакета);
ЭтотМакет.Записать(ИмяВременногоФайла);
Адрес = ПоместитьВоВременноеХранилище(Новый ДвоичныеДанные(ИмяВременногоФайла));
// Удаляем временный файл на сервере после считывания
УдалитьФайлы(ИмяВременногоФайла);
Возврат Адрес;
КонецФункции
Посмотрим на пример обработки полученных данных на клиенте с помощью ПолучитьCOMОбъект():
&НаКлиенте
Процедура ОткрытьМакетНаКлиенте()
Попытка
АдресМакета = ПолучитьМакетСервер("Макет");
Если ЗначениеЗаполнено(АдресМакета) Тогда
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресМакета);
ИмяФайлаКлиент = ПолучитьИмяВременногоФайла("xls");
ДвоичныеДанные.Записать(ИмяФайлаКлиент);
// Инициализируем COM-объект для работы с книгой Excel
МакетCOM = ПолучитьCOMОбъект(ИмяФайлаКлиент);
// Выполняем действия с листами и ячейками...
КонецЕсли;
Исключение
Сообщить("Не удалось получить макет: " + ОписаниеОшибки());
КонецПопытки;
КонецПроцедуры
Рассмотрим альтернативный способ открытия файла на клиенте через явный запуск приложения Excel:
&НаКлиенте
Процедура ОткрытьЧерезExcelApplication()
АдресМакета = ПолучитьМакетСервер("Макет");
ДвоичныеДанные = ПолучитьИзВременногоХранилища(АдресМакета);
ИмяФайлаКлиент = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанные.Записать(ИмяФайлаКлиент);
Эксель = Новый COMОбъект("Excel.Application");
Эксель.Visible = Истина;
Книга = Эксель.WorkBooks.Open(ИмяФайлаКлиент);
Лист = Книга.WorkSheets(1);
// Заполнение или обработка листов
КонецПроцедуры
Проанализируем дополнительные подходы к устройству макетов в конфигурации:
ПолучитьМакет() сразу вернет объект двоичных данных, и на сервере не потребуется создавать временный файл для промежуточного сохранения.ТабличныйДокумент. Табличные документы поддерживаются платформой на любых операционных системах, передаются между сервером и клиентом без использования временного хранилища и не требуют наличия MS Office.