Как передать результат запроса с сервера на клиент для записи в XML?

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

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

Способ 1: Формирование XML-файла на сервере (Рекомендуемый)

Проанализируем ситуацию: зачем передавать «сырые» данные на клиент, если конечная цель — получить файл? Самым производительным способом будет перенос всей логики формирования XML на сервер. На клиенте мы лишь инициируем процесс и получаем готовый результат. Рассмотрим по шагам, как это реализовать.

Шаг 1. Формирование данных на сервере. Используем объект ЗаписьXML для создания структуры файла непосредственно в памяти сервера (в строке) или во временном файле.


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

Шаг 2. Получение и сохранение на клиенте. Проанализируем, как получить эти данные. Мы используем адрес временного хранилища, чтобы «скачать» сформированный контент.


&НаКлиенте
Процедура СохранитьФайл(Команда)
    Адрес = СформироватьXMLНаСервере();
    
    // Получаем данные из хранилища
    Данные = ПолучитьИзВременногоХранилища(Адрес);
    
    // Записываем данные в файл на диске клиента
    ИмяФайла = "C:\Temp\Nomenclature.xml";
    ТекстовыйДокумент = Новый ТекстовыйДокумент;
    ТекстовыйДокумент.УстановитьТекст(Данные);
    ТекстовыйДокумент.Записать(ИмяФайла, КодировкаТекста.UTF8);
    
    Сообщить("Файл успешно сохранен: " + ИмяФайла);
КонецПроцедуры

Способ 2: Передача данных через массив структур

Если логика формирования XML слишком сложна для сервера или требует интерактивного взаимодействия с пользователем на клиенте, мы можем передать данные в виде коллекции, которая поддерживается на клиенте. Наилучший вариант здесь — Массив, содержащий объекты типа Структура.

Выясним причину выбора именно этой связки: Массив и Структура являются универсальными типами, которые сериализуются платформой при передаче между контекстами. Разберем пример кода:


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

&НаКлиенте
Процедура ОбработатьНаКлиенте()
    Данные = ПолучитьДанныеМассивом();
    
    // Теперь на клиенте мы можем перебирать массив и формировать XML
    Запись = Новый ЗаписьXML;
    Запись.ОткрытьФайл("C:\Nomenclature.xml");
    // ... логика записи ...
    Запись.Закрыть();
КонецПроцедуры

Способ 3: Использование реквизитов формы (ДанныеФормыКоллекция)

Рассмотрим еще один интересный механизм. Если на управляемой форме создать реквизит с типом ТаблицаЗначений, платформа автоматически преобразует его в ДанныеФормыКоллекция на клиенте. Этот объект ведет себя почти как таблица значений и доступен в обоих контекстах.

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

  1. Добавим в дерево реквизитов формы новый реквизит ТоварыДляВыгрузки с типом ТаблицаЗначений.
  2. Добавим колонки (Код, Наименование).
  3. На сервере заполним его.

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

&НаКлиенте
Процедура ЗаписатьИзРеквизита(Команда)
    ЗаполнитьТаблицуНаСервере();
    
    // На клиенте обращаемся напрямую к реквизиту формы
    Для Каждого Строка Из ТоварыДляВыгрузки Цикл
        // Здесь можно выполнять любую логику, данные уже на клиенте
        Сообщить(Строка.Наименование);
    КонецЦикла;
КонецПроцедуры

Способ 4: Сериализация через JSON (Современный подход)

Для передачи больших объемов данных между сервером и клиентом часто эффективнее использовать JSON. Проанализируем ситуацию: JSON-строка передается быстрее, чем массив структур, и занимает меньше оперативной памяти. Платформа 1С предоставляет встроенные средства для быстрой сериализации.


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

&НаКлиенте
Процедура ПрочитатьJSONНаКлиенте()
    СтрокаJSON = ПолучитьДанныеJSON();
    
    ЧтениеJSON = Новый ЧтениеJSON;
    ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
    Данные = ПрочитатьJSON(ЧтениеJSON); // Получаем массив структур
    ЧтениеJSON.Закрыть();
КонецПроцедуры

Подведем итоги и выберем лучшее решение

Проанализировав все способы, можно сделать следующие выводы:

  1. Если нужно просто сохранить файл: Используйте Способ 1. Формируйте XML на сервере через ЗаписьXML и передавайте либо готовую строку, либо ДвоичныеДанные через временное хранилище. Это избавит клиентское приложение от лишних вычислений.
  2. Если данные нужно показать пользователю перед выгрузкой: Используйте Способ 3 (Реквизит формы). Это самый естественный путь для управляемых форм.
  3. Для обмена сложными структурами: Подойдет Способ 2 (Массив структур) или Способ 4 (JSON). JSON предпочтительнее, если записей очень много (десятки тысяч), так как он работает быстрее встроенной сериализации массивов.

Важное примечание: При работе с файлами на клиенте в современных версиях (8.3.15+) рекомендуется использовать асинхронные методы, такие как ПолучитьФайлССервераАсинх(), чтобы интерфейс программы не блокировался во время передачи данных.

← На главную