Как преобразовать массив структур в таблицу значений в 1С?

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

В практике разработки на платформе 1С:Предприятие мы часто сталкиваемся с необходимостью обработки данных, полученных из внешних источников — для этой задачи есть универсальный ETL-инструмент загрузки данных в 1С. Это может быть результат чтения JSON, ответ от HTTP-сервиса или результат работы какого-либо алгоритма, возвращающего данные в виде массива. Часто этот массив содержит структуры.

Работать с массивом структур не всегда удобно: его нельзя напрямую выгрузить в табличное поле на форме, к нему сложно применить методы НайтиСтроки или построитель запроса. Поэтому возникает задача: как быстро и универсально преобразовать массив в Таблицу Значений (ТЗ), особенно если количество колонок велико (например, 97, как в исходном вопросе), и мы не хотим прописывать каждую колонку вручную.

Давайте разберем эффективные алгоритмы решения этой задачи, проанализируем возможные ошибки и рассмотрим примеры кода.

Постановка задачи

У нас есть переменная (допустим, МассивДанных), которая является массивом. Каждый элемент этого массива — это структура, где Ключ — это имя будущей колонки, а Значение — данные ячейки. Нам нужно получить объект ТаблицаЗначений с аналогичным набором колонок и данными.

Решение 1: Универсальный перебор (Рекомендуемый способ)

Самый надежный и понятный способ — это использование цикла. Однако, чтобы не создавать колонки вручную, мы можем пойти на хитрость: взять структуру первого элемента массива и на ее основании построить "каркас" нашей будущей таблицы.

Давайте разберем алгоритм по шагам:

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

Рассмотрим готовую функцию, которую можно использовать в своих модулях (на основе решения из обсуждения):


Функция МассивСтруктурВТаблицуЗначений(МассивСтруктур) Экспорт
	
	// Если массив пуст, возвращаем пустую таблицу (или Неопределено, зависит от вашей логики)
	Если МассивСтруктур.Количество() = 0 Тогда
		Возврат Новый ТаблицаЗначений;
	КонецЕсли;
	
	// 1. Создаем структуру таблицы по первому элементу
	// Предполагаем, что все структуры в массиве имеют одинаковый набор ключей
	СтруктураПервойСтроки = МассивСтруктур[0];
	ТЗ = Новый ТаблицаЗначений;
	
	Для Каждого ЭлементСтруктуры Из СтруктураПервойСтроки Цикл
		// Добавляем колонку. Тип пока не указываем (он будет Произвольный)
		ТЗ.Колонки.Добавить(ЭлементСтруктуры.Ключ);
	КонецЦикла;
	
	// 2. Заполняем данными
	Для Каждого ЭлементМассива Из МассивСтруктур Цикл
		НоваяСтрока = ТЗ.Добавить();
		// Магия платформы: автоматически сопоставляет ключи структуры и имена колонок ТЗ
		ЗаполнитьЗначенияСвойств(НоваяСтрока, ЭлементМассива);
	КонецЦикла;
	
	Возврат ТЗ;

КонецФункции

Этот код решает проблему ручного добавления 97 колонок. Вы просто передаете массив, а функция сама определяет состав полей.

Возможные ошибки и нюансы

В процессе реализации могут возникнуть ошибки. Разберем одну из них, упомянутую в обсуждении.

Ошибка: «Итератор для значения не определен»

Такая ошибка возникает в строке Для Каждого ... Из ... Цикл, если переменная, по которой мы пытаемся итерироваться, не является коллекцией (например, это число, строка или Неопределено, а не Структура или Массив).

Если вы столкнулись с такой ошибкой при разборе массива, это может означать, что:

  1. В массиве содержатся не только структуры, но и примитивные типы данных.
  2. Вам пришел "Массив массивов", а не "Массив структур" (у массивов нет именованных ключей, только индексы).

В коде выше мы полагаемся на то, что МассивСтруктур[0] — это именно Структура. Если данные разнородны, стоит добавить проверку ТипЗнч().

Решение 2: Использование JSON (Для продвинутых)

Существует еще один элегантный способ преобразования, который не требует написания циклов для заполнения строк. Платформа 1С умеет десериализовать JSON сразу в Таблицу Значений.

Если ваши данные — это массив структур, то с точки зрения JSON это идеальный массив объектов, который полностью совместим с форматом Таблицы Значений. Мы можем "обмануть" систему: записать массив в JSON-строку, а потом прочитать эту строку, явно указав, что хотим получить ТаблицаЗначений.

Посмотрим, как это выглядит:


Функция МассивВТаблицуЧерезJSON(МассивДанных) Экспорт
	
	// 1. Сериализуем массив в строку JSON
	ЗаписьJSON = Новый ЗаписьJSON;
	ЗаписьJSON.УстановитьСтроку();
	ЗаписатьJSON(ЗаписьJSON, МассивДанных);
	СтрокаJSON = ЗаписьJSON.Закрыть();
	
	// 2. Читаем JSON обратно, но указываем ожидаемый тип - ТаблицаЗначений
	ЧтениеJSON = Новый ЧтениеJSON;
	ЧтениеJSON.УстановитьСтроку(СтрокаJSON);
	
	// Важно: ПрочитатьJSON умеет создавать ТЗ самостоятельно
	Попытка
		ТЗ = ПрочитатьJSON(ЧтениеJSON, Тип("ТаблицаЗначений"));
	Исключение
		// Если структура данных не соответствует плоской таблице, метод упадет
		ТЗ = Новый ТаблицаЗначений;
	КонецПопытки;
	
	Возврат ТЗ;
	
КонецФункции

Этот метод часто работает быстрее циклов на больших объемах данных, так как выполняется на уровне платформы C++.

Важные замечания по типизации колонок

При использовании первого метода (через цикл) мы создаем колонки так: ТЗ.Колонки.Добавить(Имя). При этом тип колонки остается "Произвольным".

Это допустимо для простых задач, но может вызвать проблемы, если:

Как улучшить код?

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


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

Однако помните про "Проблему первого элемента": если в первой строке в поле "Сумма" стоит 0 (число), а во второй строке Неопределено (Null), то типизированная колонка может не принять значение из второй строки, или наоборот. Поэтому подход с произвольным типом является наиболее безопасным, если вы не уверены в качестве входящих данных на 100%.

Резюме

Для преобразования массива с большим количеством колонок в Таблицу Значений:

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