Как передать данные из Таблицы Значений с сервера на клиент для выгрузки в Excel?

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

В процессе разработки на платформе 1С:Предприятие 8.3 программисты часто сталкиваются с необходимостью передать результат сложного запроса с сервера на клиент для последующей обработки или выгрузки в локальные файлы пользователя. Основная сложность заключается в том, что объект типа ТаблицаЗначений существует только в серверном контексте (или в толстом клиенте). При попытке передать его "напрямую" в управляемом приложении возникает ошибка преобразования данных XDTO, так как клиентский контекст просто "не знает", как интерпретировать этот тип данных.

В данной статье мы подробно разберем, как обойти это ограничение, рассмотрим наиболее эффективные способы передачи данных и выясним, как правильно формировать файлы Excel, избегая проблем с безопасностью и лицензированием.

Почему возникает ошибка передачи данных?

Разберем причину возникновения ошибки "Ошибка преобразования данных XDTO". Платформа 1С использует механизм сериализации для передачи объектов между сервером и клиентом. ТаблицаЗначений является специализированным объектом базы данных, который содержит не только данные, но и методы их обработки (индексы, поиск, сворачивание). Эти методы не могут быть реализованы на стороне тонкого или веб-клиента. Поэтому при попытке возврата ТаблицаЗначений из функции с заголовком &НаСервере, платформа пытается упаковать её в пакет XDTO, не находит соответствующего типа для клиента и выдает ошибку.

Способ 1. Преобразование Таблицы Значений в массив структур

Это самый популярный и интуитивно понятный способ. Суть его заключается в том, чтобы переложить данные из "недопустимого" типа в "универсальные" типы данных, такие как Массив и Структура, которые прекрасно сериализуются и доступны на клиенте.

Рассмотрим алгоритм реализации этого метода:

  1. На сервере формируем ТаблицаЗначений (например, результатом запроса).
  2. Создаем Массив, в который будем помещать строки.
  3. В цикле обходим таблицу и для каждой строки создаем Структура, где ключи — это имена колонок, а значения — данные ячеек.
  4. Возвращаем массив на клиент.

Пример программного кода для преобразования:


&НаСервере
Функция ПолучитьДанныеДляЭкспорта()
    Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Код, Наименование ИЗ Справочник.Номенклатура");
    ТЗ = Запрос.Выполнить().Выгрузить();
    
    Результат = Новый Массив;
    Для Каждого СтрокаТЗ Из ТЗ Цикл
        СтруктураСтроки = Новый Структура;
        Для Каждого Колонка Из ТЗ.Колонки Цикл
            СтруктураСтроки.Вставить(Колонка.Имя, СтрокаТЗ[Колонка.Имя]);
        КонецЦикла;
        Результат.Добавить(СтруктураСтроки);
    КонецЦикла;
    
    Возврат Результат;
КонецФункции

На клиенте мы можем легко обойти этот массив и заполнить COM-объект Excel:


&НаКлиенте
Процедура ВыгрузитьВExcel()
    Данные = ПолучитьДанныеДляЭкспорта();
    Excel = Новый COMОбъект("Excel.Application");
    Книга = Excel.WorkBooks.Add();
    Лист = Книга.WorkSheets(1);
    
    НомерСтроки = 1;
    Для Каждого СтрокаДанных Из Данные Цикл
        Лист.Cells(НомерСтроки, 1).Value = СтрокаДанных.Наименование;
        Лист.Cells(НомерСтроки, 2).Value = СтрокаДанных.Код;
        НомерСтроки = НомерСтроки + 1;
    КонецЦикла;
    
    Excel.Visible = Истина;
КонецПроцедуры

Способ 2. Использование временного хранилища (для больших объемов)

Если данных очень много (десятки тысяч строк), передача огромного массива структур может замедлить работу системы из-за долгой сериализации. В этом случае проанализируем использование Временного хранилища. Мы можем поместить ТаблицаЗначений в хранилище на сервере, передать на клиент только Адрес (строку), а затем порционно запрашивать данные с сервера.

Однако, как справедливо замечено в обсуждении, если мы все равно планируем использовать COM-объект на клиенте, частые вызовы сервера в цикле (по одной строке) будут крайне неэффективны из-за сетевых задержек. Поэтому метод с массивом структур остается оптимальным для большинства задач среднего масштаба.

Способ 3. Использование Табличного Документа (Native XLSX)

Разберем наиболее современный и "правильный" с точки зрения архитектуры 1С способ. Вместо того чтобы мучительно передавать данные на клиент и поштучно заполнять ячейки через медленный COM-интерфейс, мы можем сформировать ТабличныйДокумент на сервере и сохранить его в формате XLSX.

Преимущества этого метода:

Проанализируем пример реализации:


&НаСервере
Функция СформироватьФайлНаСервере()
    ТабДок = Новый ТабличныйДокумент;
    
    // Заполняем ТабДок данными (можно использовать Построитель или просто вывод областей)
    Запрос = Новый Запрос("ВЫБРАТЬ Ссылка, Код, Наименование ИЗ Справочник.Номенклатура");
    Выборка = Запрос.Выполнить().Выбрать();
    
    Пока Выборка.Следующий() Цикл
        // Здесь логика вывода строк в ТабДок
    КонецЦикла;
    
    ИмяФайла = ПолучитьИмяВременногоФайла("xlsx");
    ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.XLSX);
    
    // Помещаем файл в хранилище, чтобы клиент мог его забрать
    ДанныеФайла = Новый ДвоичныеДанные(ИмяФайла);
    Адрес = ПоместитьВоВременноеХранилище(ДанныеФайла, ЭтаФорма.УникальныйИдентификатор);
    
    Возврат Адрес;
КонецФункции

На стороне клиента нам остается только вызвать стандартный диалог сохранения файла или автоматически открыть его. Это решает проблему "безопасного режима", о которой упоминал автор темы: файлы в формате XLSX (начиная с 2007 стандарта) гораздо лояльнее воспринимаются системой безопасности Windows, чем старые XLS или HTML-файлы с расширением Excel.

Решение проблем с COM-объектом на сервере

Иногда бизнес-логика требует использования именно COM (например, использование сложных макросов или форматирования, недоступного в ТабличныйДокумент). Если вы решили создавать Excel.Application на сервере, вы можете столкнуться с ошибкой "Метод объекта не обнаружен WorkBooks".

Выясним причины и способы решения:

  1. Разрядность: Если сервер 1С 64-битный, а Office — 32-битный, они не смогут взаимодействовать напрямую. Необходимо убедиться в совпадении разрядности.
  2. Профиль пользователя: Служба сервера 1С работает под техническим пользователем (например, USR1CV8). У этого пользователя нет папок рабочего стола, которые необходимы Excel для запуска. Вы можете решить это, создав вручную папку Desktop по адресу: C:\Windows\System32\config\systemprofile\Desktop (и для SysWOW64 на 64-битных ОС).
  3. DCOM: Требуется настройка прав в консоли dcomcnfg для компонента Microsoft Excel Application, чтобы разрешить запуск и активацию от имени системной учетной записи.

Важное замечание: Использование Microsoft Office на сервере официально не рекомендуется компанией Microsoft и может нарушать лицензионное соглашение. Всегда отдавайте предпочтение нативной выгрузке через ТабличныйДокумент в формат XLSX.

Выводы и рекомендации

Подводя итог, проанализируем, какой метод выбрать:

Помните, что архитектура 1С 8.3 ориентирована на минимизацию объема передаваемых данных между сервером и клиентом. Старайтесь выполнять всю тяжелую обработку на стороне сервера, возвращая на клиент лишь готовый результат.

← На главную