Как выгрузить все значения ячеек таблицы значений в табличную часть с одной колонкой?

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

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

Постановка задачи и специфика данных

Представим ситуацию: у нас есть объект ТаблицаЗначений, количество колонок в котором заранее не зафиксировано (например, формируется динамически пользователем или выгружается из движений регистров). В целевой табличной части (ТабличнаяЧасть) определена всего одна колонка, допустим, Значение. Задача заключается в том, чтобы каждое отдельное значение из каждой ячейки таблицы значений было помещено в отдельную строку табличной части. Если в таблице значений 2 строки и 2 колонки, на выходе в табличной части должно быть создано 4 строки.

Способ 1. Универсальный построчный перебор через двойной цикл

Рассмотрим базовое и самое прямое решение задачи. Чтобы извлечь данные из каждой ячейки, мы организуем вложенный цикл: внешний цикл будет обходить строки таблицы значений, а внутренний — коллекцию Колонки таблицы значений. Посмотрим на программную реализацию:


// Очищаем табличную часть перед заполнением
Объект.ТабличнаяЧасть.Очистить();

// Обходим все строки исходной таблицы значений
Для Каждого СтрТЗ Из ИсходнаяТЗ Цикл
    // Для каждой строки обходим коллекцию колонок
    Для Каждого ТекКолонка Из ИсходнаяТЗ.Колонки Цикл
        
        ЗначениеЯчейки = СтрТЗ[ТекКолонка.Имя];
        
        // Создаем новую строку в табличной части
        НоваяСтрока = Объект.ТабличнаяЧасть.Добавить();
        НоваяСтрока.Значение = ЗначениеЯчейки;
        
    КонецЦикла;
КонецЦикла;

Разберем по шагам, как работает этот фрагмент кода:

  1. Мы вызываем метод Очистить() у табличной части, чтобы исключить наложение новых данных на старые.
  2. С помощью конструкции Для Каждого СтрТЗ Из ИсходнаяТЗ перебираем поочередно каждую строку.
  3. Вложенный цикл Для Каждого ТекКолонка Из ИсходнаяТЗ.Колонки позволяет обратиться к имени текущей колонки через свойство ТекКолонка.Имя.
  4. Обращение СтрТЗ[ТекКолонка.Имя] получает значение ячейки на пересечении текущей строки и колонки.
  5. Метод Добавить() создает новую строку в табличной части, куда мы и записываем полученное значение.

Способ 2. Оптимизированная пакетная загрузка через массив

Построчное добавление элементов через метод Добавить() при большом количестве данных может работать медленно. Часто возникает вопрос: можно ли использовать платформенные методы ВыгрузитьКолонку() и ЗагрузитьКолонку()?

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

Однако мы можем сформировать единый одномерный Массив со всеми элементами и загрузить его за один вызов метода. Рассмотрим подробнее этот алгоритм:


ОбщийМассив = Новый Массив;

// Собираем значения всех ячеек в плоский массив
Для Каждого СтрТЗ Из ИсходнаяТЗ Цикл
    Для Каждого ТекКолонка Из ИсходнаяТЗ.Колонки Цикл
        ОбщийМассив.Добавить(СтрТЗ[ТекКолонка.Имя]);
    КонецЦикла;
КонецЦикла;

// Очищаем табличную часть и загружаем массив целиком
Объект.ТабличнаяЧасть.Очистить();
Объект.ТабличнаяЧасть.ЗагрузитьКолонку(ОбщийМассив, "Значение");

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

Важные ограничения: типы данных и дубликаты

При решении подобных задач критически важно учитывать структуру самой базы данных и особенности платформы 1С:

  1. Несоответствие типов данных: реквизит табличной части всегда имеет строго определенный тип (или ограниченный составной тип). Если ячейка таблицы значений содержит значение типа, не входящего в описание реквизита (например, Неопределено, NULL, системные типы или неподходящий тип ссылки), платформа не сможет сохранить такое значение либо оно очистится. Перед добавлением данных рекомендуется проверять их тип через ТипЗнч().
  2. Дублирование информации: если исходная таблица значений формируется на основе движений регистров или документов, одинаковые значения могут встречаться сотни раз. Сохранение полных дубликатов приводит к неконтролируемому раздуванию базы данных и снижению производительности при записи объекта. Для исключения дублей значения перед добавлением можно фильтровать, например, через коллекцию Соответствие:

УникальныеЗначения = Новый Соответствие;

Для Каждого СтрТЗ Из ИсходнаяТЗ Цикл
    Для Каждого ТекКолонка Из ИсходнаяТЗ.Колонки Цикл
        
        ТекЗначение = СтрТЗ[ТекКолонка.Имя];
        
        // Фильтруем пустые значения и исключаем дубликаты
        Если ЗначениеЗаполнено(ТекЗначение) Тогда
            УникальныеЗначения.Вставить(ТекЗначение, Истина);
        КонецЕсли;
        
    КонецЦикла;
КонецЦикла;

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

Архитектурная альтернатива для критериев отбора

Нередко программисты прибегают к созданию такой одноколоночной табличной части в документе (например, в документе «Корректировка регистров»), чтобы включить реквизит табличной части в состав Критерия отбора и отображать документ в связанных ссылках справочника. Разберем, почему создание отдельной табличной части здесь часто является избыточным решением:

  1. Штатные возможности Критериев отбора: платформа 1С позволяет напрямую включать в состав критерия отбора измерения регистров сведений, накопления, бухгалтерии и расчета. Поскольку документ выступает регистратором записей, платформа автоматически связывает документ со значением справочника через стандартный реквизит Регистратор. Включать искусственную табличную часть в документ не требуется.
  2. Механизмы БСП: в типовых конфигурациях связь между объектами часто строится через подсистему «Связанные документы» Библиотеки Стандартных Подсистем. В переопределяемых процедурах подсистемы можно настроить запрос к таблицам движений нужных регистров с отбором по регистратору, исключив дублирование информации в структуре документа.

Таким образом, для простой технической трансформации данных оптимально использовать двойной цикл либо пакетную загрузку через массив, контролируя совпадение типов и исключая дублирование данных.

← На главную