Как выгрузить данные отчета СКД в XML-файл в 1С 8.3

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

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

В этой статье мы подробно разберем, почему возникают эти ошибки, как правильно получать данные из СКД для программной обработки и как корректно сформировать XML-документ требуемой структуры.

Анализ типичных ошибок при формировании XML

Рассмотрим основные заблуждения и причины сбоев, с которыми сталкиваются разработчики при попытке экспорта отчета:

  1. Попытка сопоставить ТабличныйДокумент и объект XDTO: Метод ЗаполнитьЗначенияСвойств выполняет прямое копирование значений только свойств первого уровня с одинаковыми именами. Объект ТабличныйДокумент содержит ячейки, области и графическое оформление, а не плоский список реквизитов или прикладных бизнес-данных. По этой причине скопировать данные табличного документа в свойства типа XDTO таким способом невозможно.
  2. Ошибки типа данных в методе ЗаписатьТекст: Объект ЗаписьXML требует строгого соблюдения типов параметров. Метод ЗаписатьТекст принимает исключительно строковые значения (тип Строка). Передача числа, даты, булевого значения или ссылки напрямую вызывает ошибку времени выполнения.
  3. Избыточность стандартной сериализации: Использование объекта СериализаторXDTO жестко привязано к внутренним типам 1С и схеме пространств имен платформы. При сериализации объектов платформы генерируется большое количество технических служебных атрибутов (например, xsi:type), что недопустимо, если сторонний сервис ожидает строгую кастомную структуру.

Способ 1. Потоковое формирование XML через объект ЗаписьXML

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

Разберем по шагам, как выгрузить данные и избежать ошибок типизации. Главное правило — все выгружаемые значения примитивных типов (числа, даты) необходимо приводить к корректному строковому представлению с помощью функции XMLСтрока() или Формат().

Посмотрим на пример кода формирования XML-файла:


// Инициализируем объект записи и настраиваем параметры файла
ЗаписьXML = Новый ЗаписьXML;
ПараметрыЗаписиXML = Новый ПараметрыЗаписиXML("UTF-8", "1.0", Ложь);
ИмяФайла = "C:\test\REG_" + Формат(ТекущаяДата(), "ДФ=yyyyMMdd_HHmmss") + ".xml";

ЗаписьXML.ОткрытьФайл(ИмяФайла, ПараметрыЗаписиXML);
ЗаписьXML.ЗаписатьОбъявлениеXML();

// Записываем корневой элемент
ЗаписьXML.ЗаписатьНачалоЭлемента("DATAPACKET");

// Пример записи вложенного узла с данными
ЗаписьXML.ЗаписатьНачалоЭлемента("FlightInfo");

// Запись текстового узла с обязательным преобразованием в XML-строку
ЗаписьXML.ЗаписатьНачалоЭлемента("FlightNumber");
ЗаписьXML.ЗаписатьТекст(XMLСтрока(Рейс.FlightNumber));
ЗаписьXML.ЗаписатьКонецЭлемента(); // FlightNumber

ЗаписьXML.ЗаписатьНачалоЭлемента("DepartureDate");
ЗаписьXML.ЗаписатьТекст(XMLСтрока(Рейс.ДатаВылета));
ЗаписьXML.ЗаписатьКонецЭлемента(); // DepartureDate

ЗаписьXML.ЗаписатьКонецЭлемента(); // FlightInfo

// Закрываем корневой элемент и файл
ЗаписьXML.ЗаписатьКонецЭлемента(); // DATAPACKET
ЗаписьXML.Закрыть();

Важное замечание: Глобальная функция XMLСтрока() преобразует переданное значение любого базового типа (число, дата, булево, ссылки) в канонический строковый формат XML (например, даты в формате YYYY-MM-DDThh:mm:ss, а разделители дробной части чисел — в виде точки), что гарантирует валидность создаваемого документа.

Способ 2. Получение данных отчета в коллекцию значений для выгрузки

Для программной обработки результатов отчета СКД вывод в табличный документ не подходит. Вместо этого настроим процессор вывода на выгрузку в объект ТаблицаЗначений или ДеревоЗначений с помощью ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений.

Рассмотрим пример выполнения компоновки и последующей выгрузки строк отчета в XML:


// 1. Получение схемы и настроек компоновки
СхемаКомпоновкиДанных = Отчеты.ОтчётПоОтгрузкеПростой.ПолучитьМакет("ОсновнаяСхемаКомпоновкиДанных");
Настройки = СхемаКомпоновкиДанных.НастройкиПоУмолчанию;

ДанныеРасшифровки = Новый ДанныеРасшифровкиКомпоновкиДанных;
КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, Настройки, ДанныеРасшифровки);

// 2. Инициализация процессора компоновки
ПроцессорКомпоновки = Новый ПроцессорКомпоновкиДанных;
ПроцессорКомпоновки.Инициализировать(МакетКомпоновки, , ДанныеРасшифровки, Истина);

// 3. Вывод результата в Таблицу Значений
ТаблицаРезультата = Новый ТаблицаЗначений;
ПроцессорВывода = Новый ПроцессорВыводаРезультатаКомпоновкиДанныхВКоллекциюЗначений;
ПроцессорВывода.УстановитьОбъект(ТаблицаРезультата);
ПроцессорВывода.Вывести(ПроцессорКомпоновки);

// 4. Построчная выгрузка полученной таблицы в XML
ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\test\report_data.xml", "UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("ReportData");

Для Каждого Стр Из ТаблицаРезультата Цикл
    ЗаписьXML.ЗаписатьНачалоЭлемента("Row");
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Номенклатура");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(Стр.Номенклатура));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Количество");
    ЗаписьXML.ЗаписатьТекст(XMLСтрока(Стр.Количество));
    ЗаписьXML.ЗаписатьКонецЭлемента();
    
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Row
КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента(); // ReportData
ЗаписьXML.Закрыть();

Способ 3. Прямой обход процессора компоновки данных

Если отчет содержит большой объем строк, выгрузка всей таблицы значений в оперативную память может вызвать повышенное потребление ресурсов сервера. В таких сценариях эффективнее использовать потоковое чтение напрямую из ПроцессорКомпоновкиДанных без создания промежуточных коллекций.

Проанализируем пример потоковой обработки:


ЗаписьXML = Новый ЗаписьXML;
ЗаписьXML.ОткрытьФайл("C:\test\stream_report.xml", "UTF-8");
ЗаписьXML.ЗаписатьОбъявлениеXML();
ЗаписьXML.ЗаписатьНачалоЭлемента("Report");

// Потоковый обход элементов результата компоновки
Пока Истина Цикл
    ЭлементРезультата = ПроцессорКомпоновки.СледующийЭлемент();
    Если ЭлементРезультата = Неопределено Тогда
        Прервать;
    КонецЕсли;
    
    // Обрабатываем только строки с записями данных
    Если ЭлементРезультата.ТипЭлемента = ТипЭлементаРезультатаКомпоновкиДанных.Интервал 
        Или ЭлементРезультата.ЗначенияПараметров.Количество() = 0 Тогда
        Продолжить;
    КонецЕсли;
    
    ЗаписьXML.ЗаписатьНачалоЭлемента("Record");
    Для Каждого Параметр Из ЭлементРезультата.ЗначенияПараметров Цикл
        ЗаписьXML.ЗаписатьНачалоЭлемента(Параметр.Имя);
        ЗаписьXML.ЗаписатьТекст(XMLСтрока(Параметр.Значение));
        ЗаписьXML.ЗаписатьКонецЭлемента();
    КонецЦикла;
    ЗаписьXML.ЗаписатьКонецЭлемента(); // Record
КонецЦикла;

ЗаписьXML.ЗаписатьКонецЭлемента(); // Report
ЗаписьXML.Закрыть();

Рекомендации по выбору метода

  1. ЗаписьXML: Оптимальный выбор для генерации файлов по сторонним спецификациям и схемам, так как потребляет минимум памяти и позволяет точно контролировать каждый тег и атрибут.
  2. Вывод в коллекцию (ТаблицаЗначений): Удобен при необходимости предварительной обработки, сортировки или фильтрации данных отчета перед формированием итогового документа.
  3. ТабличныйДокумент.Записать: Используйте только в том случае, если требуется сохранить сам макет электронного отчета в стандартном формате электронных таблиц XML (SpreadsheetML), а не выгрузить чистые прикладные данные.
← На главную