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

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

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

Особенности типов данных и колонок в 1С 7.7

В платформе 1С 7.7 классический массив создается только статически через объявление переменной с указанием размерности: Перем МойМассив[10]. Такой массив не является самостоятельным ссылочным объектом базы данных или среды исполнения, поэтому его невозможно напрямую передать в ячейку таблицы значений. Однако, если колонка таблицы значений создана без строгого указания типа, она способна принимать значения любых типов, включая динамические объекты платформы.

Рассмотрим основные подходы к хранению множества связанных данных в ячейках таблицы значений.

Способ 1. Использование объекта «СписокЗначений» внутри ячейки

Наиболее удобный объектный способ организовать вложенный набор данных — использовать динамический объект СписокЗначений. Для каждой строки таблицы значений создается свой экземпляр списка, в который добавляются нужные элементы.

Посмотрим на пример программного наполнения таблицы значений:


// Создаем основную таблицу значений
ТЗ = СоздатьОбъект("ТаблицаЗначений");
ТЗ.НоваяКолонка("Код");
ТЗ.НоваяКолонка("Наименование");
ТЗ.НоваяКолонка("ВложенныйСписок"); // Тип колонки не указываем

// Добавляем строку и наполняем вложенный список
ТЗ.НоваяСтрока();
ТЗ.Код = "001";
ТЗ.Наименование = "Основной товар";

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

Для чтения и обхода данных из такой ячейки достаточно обратиться к свойству строки как к обычному списку:


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

Важное замечание: Метод Сортировать() таблицы значений не может упорядочивать строки по колонкам, содержащим составные объекты (такие как СписокЗначений или вложенная ТаблицаЗначений). Сортировку следует выполнять только по стандартным колонкам с простыми или ссылочными типами.

Способ 2. Сериализация структуры в строку («ЗначениеВСтрокуВнутр»)

Если требуется компактное представление данных или их последующая передача/сохранение в строковый реквизит (например, шапки документа), можно использовать внутреннюю сериализацию платформы через функции ЗначениеВСтрокуВнутр() и ЗначениеИзСтрокиВнутр().

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


// Формируем промежуточный список
Спис = СоздатьОбъект("СписокЗначений");
Спис.ДобавитьЗначение("Исполнитель 1");
Спис.ДобавитьЗначение("Исполнитель 2");

// Помещаем сериализованную строку в ячейку таблицы значений
ТЗ.НоваяСтрока();
ТЗ.ВложенныеДанныеСтрокой = ЗначениеВСтрокуВнутр(Спис);

// При извлечении данных восстанавливаем объект обратно
ВосстановленныйСписок = СоздатьОбъект("СписокЗначений");
ВосстановленныйСписок = ЗначениеИзСтрокиВнутр(ТЗ.ВложенныеДанныеСтрокой);

Способ 3. Строка с фиксированным разделителем

Если вложенные данные состоят из простых идентификаторов, чисел или коротких строк, наиболее производительным решением будет хранение значений в обычной текстовой строке с использованием разделителя (например, запятой, точки с запятой или символа перевода строки).

Посмотрим на пример разбора строки через функции работы с текстовыми строками платформы:


// Запись данных через разделитель переноса строк
ТЗ.НоваяСтрока();
ТЗ.СписокКодов = "Код1" + РазделительСтрок + "Код2" + РазделительСтрок + "Код3";

// Разбор данных из ячейки
ТекСтрокаДанных = ТЗ.СписокКодов;
КолСтрок = СтрКоличествоСтрок(ТекСтрокаДанных);

Для Индекс = 1 По КолСтрок Цикл
    ЗначениеЭлемента = СтрПолучитьСтроку(ТекСтрокаДанных, Индекс);
    // Обработка отдельного значения
КонецЦикла;

Способ 4. Денормализация данных (плоская таблица)

Когда исходный массив данных очень велик (десятки и сотни тысяч записей), создание отдельного объекта СписокЗначений для каждой строки таблицы значений приведет к повышенному расходу памяти и замедлению работы сборщика мусора 1С 7.7. В этом случае оптимальным решением является переход к плоской (денормализованной) таблице значений.

Разберем по шагам алгоритм работы с плоской таблицей:

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

// Структура плоской таблицы:
// Колонка 1: ИД_Родителя (Число/Строка)
// Колонка 2: ЗначениеВложенногоЭлемента

ТЗ.Сортировать("ИД_Родителя+");
ТекИД = "";

ТЗ.ВыбратьСтроки();
Пока ТЗ.ПолучитьСтроку() = 1 Цикл
    Если ТЗ.ИД_Родителя <> ТекИД Тогда
        ТекИД = ТЗ.ИД_Родителя;
        // Действия при начале обработки нового родительского блока
    КонецЕсли;
    
    // Обработка вложенного элемента
    ОбработатьЭлемент(ТЗ.ЗначениеВложенногоЭлемента);
КонецЦикла;

Выбор конкретного варианта зависит от решаемой задачи: для небольших наборов параметров в интерфейсе отлично подходит объект СписокЗначений в нетипизированной колонке, а при масштабных выгрузках и расчетах предпочтительнее использовать строковые разделители или денормализованные таблицы.

← На главную