В процессе разработки на платформе 1С:Предприятие 8.3 (особенно в конфигурациях на базе БСП, таких как ЗУП КОРП 3.1, ERP или КА) программисты регулярно сталкиваются с необходимостью конвертации данных из одних коллекций в другие. Одной из наиболее частых задач является преобразование Структуры или Массива структур в полноценную ТаблицуЗначений.
Такая необходимость возникает при обработке API-запросов (парсинге JSON), передаче параметров между клиентом и сервером, а также при подготовке данных для последующего использования во временных таблицах запросов. В этой статье мы подробно разберем все способы решения этой задачи, укажем на критические ошибки стандартных подходов и рассмотрим особенности работы в контексте управляемых форм.
---
Рассмотрим классический вариант ручного обхода структуры, который чаще всего предлагают на форумах. Идея заключается в динамическом создании колонок таблицы значений на основе ключей структуры с последующим переносом данных через системную процедуру ЗаполнитьЗначенияСвойств.
Проанализируем базовый пример кода:
// Создаем пустую таблицу значений
ТЗ = Новый ТаблицаЗначений;
// Обходим ключи структуры и добавляем одноименные колонки в таблицу
Для Каждого КлючЗначение Из ТвояСтруктура Цикл
ТЗ.Колонки.Добавить(КлючЗначение.Ключ);
КонецЦикла;
// Добавляем новую строку в таблицу и заполняем ее данными структуры
ЗаполнитьЗначенияСвойств(ТЗ.Добавить(), ТвояСтруктура);
В чем заключается главная опасность этого кода?
Обратите внимание на метод ТЗ.Колонки.Добавить(КлючЗначение.Ключ). При таком вызове колонки таблицы значений создаются без явного указания типов данных. По умолчанию тип созданной колонки будет равен Неопределено.
Если в дальнейшем вы попытаетесь передать эту таблицу значений в качестве параметра в запрос (например, для помещения во временную таблицу через конструкцию ПОМЕСТИТЬ), платформа 1С выдаст ошибку выполнения. Запрос требует строго типизированных полей. Для проверки структуры и содержимого временных таблиц при отладке запросов можно использовать инструмент для фиксации и отладки временных таблиц в запросах.
---
Чтобы избежать проблем при работе с запросами и гарантировать корректное поведение системы, структуру необходимо переносить с динамическим определением типов. Разберем усовершенствованный шаблон кода:
ТЗ = Новый ТаблицаЗначений;
Для Каждого КлючЗначение Из ТвояСтруктура Цикл
// Определяем тип значения текущего свойства структуры
МассивТипов = Новый Массив;
МассивТипов.Добавить(ТипЗнч(КлючЗначение.Value)); // Для платформы 1С используем КлючЗначение.Значение
ОписаниеТипаКолонки = Новый ОписаниеТипов(МассивТипов);
// Создаем строго типизированную колонку
ТЗ.Колонки.Добавить(КлючЗначение.Ключ, ОписаниеТипаКолонки);
КонецЦикла;
// Безопасно заполняем строку данными
ЗаполнитьЗначенияСвойств(ТЗ.Добавить(), ТвояСтруктура);
Если в структуре содержатся стандартные примитивные типы (число, строка, дата), и нам требуется задать для них определенные ограничения (например, длину строки или разрядность числа), мы можем использовать вспомогательные функции БСП (Библиотеки Стандартных Подсистем):
ОбщегоНазначения.ОписаниеТипаЧисло(Разрядность, ДробнаяЧасть) — возвращает описание типа "Число" с заданными параметрами.ОбщегоНазначения.ОписаниеТипаСтрока(Длина) — возвращает описание типа "Строка" фиксированной или переменной длины.ОбщегоНазначения.ОписаниеТипаДата(ЧастиДаты.ДатаВремя) — возвращает описание типа "Дата".---
На практике структуры редко обрабатываются поодиночке. Гораздо чаще веб-сервисы или HTTP-запросы возвращают нам Массив, состоящий из множества однотипных объектов Структура. Нам нужно развернуть этот массив в одну полноценную таблицу значений.
Рассмотрим готовое универсальное решение, которое автоматически создает структуру колонок по первому элементу массива, а затем быстро заполняет всю таблицу:
ТаблицаРезультат = Новый ТаблицаЗначений;
Если МассивСтруктур.Количество() > 0 Тогда
// Шаг 1. Формируем типизированные колонки по первому элементу массива
ПерваяСтруктура = МассивСтруктур[0];
Для Каждого КлючЗначение Из ПерваяСтруктура Цикл
МассивТипов = Новый Массив;
МассивТипов.Добавить(ТипЗнч(КлючЗначение.Значение));
ОписаниеТипа = Новый ОписаниеТипов(МассивТипов);
ТаблицаРезультат.Колонки.Добавить(КлючЗначение.Ключ, ОписаниеТипа);
КонецЦикла;
// Шаг 2. Заполняем таблицу строк из массива структур
Для Каждого ЭлементМассива Из МассивСтруктур Цикл
// Проверяем, что элемент действительно является структурой
Если ТипЗнч(ЭлементМассива) = Тип("Структура") Тогда
НоваяСтрока = ТаблицаРезультат.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, ЭлементМассива);
КонецЕсли;
КонецЦикла;
КонецЕсли;
Важное замечание: Данный алгоритм предполагает, что все структуры в массиве имеют одинаковый набор ключей. Если структуры могут отличаться по составу свойств, перед вызовом ЗаполнитьЗначенияСвойств потребуется дополнительно проверять наличие ключей или предварительно собирать уникальный список всех возможных колонок по всему массиву.
---
При работе в интерфейсе управляемых форм (особенно в таких конфигурациях, как ЗУП КОРП 3.1) ключевое значение имеет клиент-серверная архитектура платформы 1С. Здесь действуют строгие ограничения:
ТаблицаЗначений физически не может существовать на стороне Клиента. Попытка вызвать конструктор Новый ТаблицаЗначений на клиенте вызовет аварийное завершение программы. Соответственно, все вышеописанные преобразования должны выполняться строго на сервере (желательно в процедурах с директивой &НаСервереБезКонтекста для экономии трафика).ДанныеФормыКоллекция, а строка таблицы — типом ДанныеФормыЭлемент или ДанныеФормыСтруктура.Если ваша задача состоит в том, чтобы выгрузить данные из таблицы формы в реальную таблицу значений на сервере для последующей обработки, используйте встроенные методы платформы:
// На сервере преобразуем коллекцию формы в реальную таблицу значений
ТЗ = РеквизитФормыВЗначение("ИмяРеквизитаФормы");
// Выполняем любые операции (запросы, поиск, фильтрация)
// ...
// Записываем измененную таблицу обратно на форму
ЗначениеВРеквизитФормы(ТЗ, "ИмяРеквизитаФормы");
Если же под "структурой" в вашем коде изначально скрывался объект ДанныеФормыКоллекция, вы можете моментально преобразовать его в таблицу значений всего одной строкой кода на сервере:
// Прямая выгрузка данных формы в таблицу значений
ТЗ = Объект.ИмяТабличнойЧасти.Выгрузить();
---
В Библиотеке Стандартных Подсистем (БСП) разработчикам доступен готовый набор инструментов для обратного преобразования — из таблиц значений в более легкие структуры и массивы. Это крайне полезно при передаче результатов запроса на клиентскую сторону.
Проанализируем ключевые функции общего модуля ОбщегоНазначения:
Функция ОбщегоНазначения.ТаблицаЗначенийВМассив(ТаблицаЗначений) преобразует переданную таблицу в массив структур, где ключами каждой структуры выступают имена колонок. Полученный массив без проблем передается на клиент.
Функция ОбщегоНазначения.СтрокаТаблицыЗначенийВСтруктуру(СтрокаТаблицы) позволяет мгновенно превратить одну выбранную строку таблицы значений в структуру. Это избавляет от необходимости писать ручной обход свойств.
Подведем итог: Для быстрого переноса одной структуры в ТЗ используйте ручной обход с обязательной типизацией колонок через ОписаниеТипов. При работе с массивами объектов автоматизируйте процесс по первому элементу. На управляемых формах всегда четко разграничивайте типы данных ТаблицаЗначений и ДанныеФормыКоллекция, выполняя сложные преобразования строго на стороне сервера.