Работа в облачных сервисах, таких как 1C:Fresh, накладывает на разработчика ряд специфических ограничений. Одно из самых критичных — категорический запрет на использование COMОбъект на стороне сервера. Это создает серьезную проблему, когда необходимо сформировать сложный отчет в формате XLS на основании существующего шаблона (например, для налоговой службы), где важна структура листов, формулы и форматирование. В этой статье мы подробно разберем, как обойти это ограничение, передать данные и сохранить функциональность вашего шаблона.
В локальных версиях 1С разработчики привыкли использовать COMОбъект("Excel.Application") прямо на сервере. Это удобно: запрос собрал данные, объект открыл файл, заполнил ячейки и сохранил результат. Однако в архитектуре 1C:Fresh серверная часть работает в изолированном защищенном режиме. Попытка инициализации COM-объекта вызовет исключение безопасности. Рассмотрим, какие стратегии позволяют решить эту задачу легальными способами.
Поскольку работать с Excel на сервере нельзя, логичным выходом будет перенос процесса формирования файла на сторону клиента. Однако на клиенте нет доступа к базе данных и запросам. Следовательно, нам нужно сначала собрать все необходимые данные на сервере и передать их на клиентскую сторону. Проанализируем, как это сделать наиболее эффективно.
Вместо передачи тяжелой ТаблицаЗначений, которая не всегда удобно сериализуется напрямую, лучше использовать Массив Структур. Рассмотрим пример кода для формирования данных на сервере:
&НаСервере
Функция СформироватьДанныеДляЭкспорта()
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Продажи.Номенклатура.Наименование КАК Наименование,
| Продажи.КоличествоОборот КАК Количество,
| Продажи.СуммаОборот КАК Сумма
|ИЗ
| РегистрНакопления.Продажи.Обороты(&НачалоПериода, &КонецПериода) КАК Продажи";
Запрос.УстановитьПараметр("НачалоПериода", Объект.ДатаНачала);
Запрос.УстановитьПараметр("КонецПериода", Объект.ДатаОкончания);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
ДанныеДляКлиента = Новый Массив;
Пока Выборка.Следующий() Цикл
СтрокаДанных = Новый Структура;
ЗаполнитьЗначенияСвойств(СтрокаДанных, Выборка);
ДанныеДляКлиента.Добавить(СтрокаДанных);
КонецЦикла;
Возврат ДанныеДляКлиента;
КонецФункции
Теперь на стороне клиента мы можем принять этот массив и использовать стандартный COMОбъект, который на локальном компьютере пользователя (если установлен MS Office) будет работать без ограничений сервиса Fresh.
Если структура шаблона не слишком сложная, можно воспользоваться методом ТабличныйДокумент. Разберем по шагам этот алгоритм:
ТабличныйДокумент.Записать() с типом файла XLS или XLSX.Важное ограничение: Как было отмечено в обсуждении, метод ТабДок.Записать() всегда создает новый файл. Если ваш шаблон содержит скрытые технические листы с макросами или сложными формулами (как это часто бывает в банковских или налоговых формах), ТабличныйДокумент их "затрет", сохранив только визуальное представление данных. Поэтому данный метод подходит только для простых отчетов.
Для оптимизации работы в 1C:Fresh, особенно при больших объемах данных, рекомендуется использовать Временное хранилище. Проанализируем ситуацию, когда нам нужно передать сам файл-шаблон с сервера на клиент, заполнить его и предложить пользователю сохранить результат.
Рассмотрим схему взаимодействия:
&НаКлиенте
Процедура СформироватьОтчетExcel(Команда)
// 1. Получаем структуру данных и адрес шаблона во временном хранилище
РезультатСервера = ПолучитьПодготовленныеДанныеИШаблон();
// 2. Получаем файл из хранилища на локальный диск клиента
ИмяФайлаШаблона = ПолучитьИмяВременногоФайла("xlsx");
ДвоичныеДанныеШаблона = ПолучитьИзВременногоХранилища(РезультатСервера.АдресШаблона);
ДвоичныеДанныеШаблона.Записать(ИмяФайлаШаблона);
// 3. Работаем с COM на клиенте
Попытка
Excel = Новый COMОбъект("Excel.Application");
Книга = Excel.Workbooks.Open(ИмяФайлаШаблона);
Лист = Книга.Sheets(3); // Обращаемся к нужному листу, например, к третьему
НомерСтроки = 10; // Допустим, данные начинаются с 10 строки
Для Каждого СтрокаТЗ Из РезультатСервера.Данные Цикл
Лист.Cells(НомерСтроки, 1).Value = СтрокаТЗ.Наименование;
Лист.Cells(НомерСтроки, 2).Value = СтрокаТЗ.Количество;
НомерСтроки = НомерСтроки + 1;
КонецЦикла;
Excel.Visible = Истина; // Показываем готовый файл пользователю
Исключение
Сообщить("Ошибка при работе с Excel: " + ОписаниеОшибки());
Если Excel <> Неопределено Тогда
Excel.Quit();
КонецЕсли;
КонецПопытки;
КонецПроцедуры
Выясним важную деталь: если пользователь запускает 1C:Fresh через браузер (Веб-клиент), то COMОбъект не будет работать даже на клиенте. В этом случае единственным надежным способом остается формирование файла на сервере без использования технологий Microsoft. Для этого применяются специализированные библиотеки, работающие напрямую с форматом OpenXML (XLSX — это по сути ZIP-архив с XML-файлами).
Если вы столкнулись с необходимостью работы именно в веб-клиенте, рассмотрите вариант использования NativeXLSX или аналогичных решений на чистом языке 1С. Эти механизмы позволяют модифицировать конкретные xml компоненты внутри файла .xlsx, не затрагивая листы с формулами и технической информацией.
Проанализировав проблему, мы можем выделить следующие рекомендации для разработчиков в среде Fresh:
Массив из Структур.ТабДок.Записать(). Используйте только прямое заполнение ячеек через COM на клиенте или прямую правку XML на сервере.Таким образом, несмотря на жесткие ограничения 1C:Fresh, комбинирование серверных вычислений и клиентской обработки позволяет создавать полноценные инструменты для экспорта данных в сложные форматы отчетности.