Как объединить две таблицы значений в 1С: подробное руководство

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

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

Способ 1. Использование цикла и метода ЗаполнитьЗначенияСвойств

Это классический и самый наглядный метод, который подходит для небольших и средних таблиц. Основная идея заключается в переборе строк одной таблицы и добавлении их в другую. Для автоматического сопоставления колонок по именам мы используем системную процедуру ЗаполнитьЗначенияСвойств.

Рассмотрим пример реализации универсальной процедуры для дополнения одной таблицы данными из другой:


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

Проанализируем ситуацию, когда этот метод может не сработать. Как правило, это происходит из-за того, что в ТаблицаПриемник отсутствуют колонки с теми же именами, что и в ТаблицаИсточник. Метод ЗаполнитьЗначенияСвойств работает только по совпадающим идентификаторам свойств. Если в приемнике нет колонки "Сумма", данные из источника просто не будут скопированы.

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

Способ 2. Проблема несоответствия типов данных

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

Если структуры таблиц разные, рассмотрим следующий алгоритм действий:

  1. Создаем новую (третью) таблицу значений.
  2. Формируем структуру колонок, объединяющую поля обеих исходных таблиц. При этом для каждой колонки желательно задать максимально широкое ОписаниеТипов.
  3. Последовательно выгружаем данные из первой и второй таблиц в новую.

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

Способ 3. Объединение через запрос (самый быстрый вариант)

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

Разберем по шагам, как это реализовать:

  1. Передаем обе таблицы во временные таблицы запроса.
  2. Используем оператор ОБЪЕДИНИТЬ ВСЕ для слияния данных.
  3. Выполняем запрос и выгружаем результат в новую таблицу значений.

Пример кода для объединения через запрос:


Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;

// Устанавливаем таблицы как параметры
Запрос.УстановитьПараметр("ТЗ1", Таблица1);
Запрос.УстановитьПараметр("ТЗ2", Таблица2);

Запрос.Текст = 
    "ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ1 КАК ТЗ1
    ;
    ВЫБРАТЬ * ИЗ ВТ_Данные КАК ТЗ
    ОБЪЕДИНИТЬ ВСЕ
    ВЫБРАТЬ * ИЗ &ТЗ2 КАК ТЗ2";

РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультат = РезультатЗапроса.Выгрузить();

Важно: Для работы этого метода колонки исходных таблиц должны иметь строго определенные типы (не Произвольный). Если типы не заданы, запрос выдаст ошибку при попытке обращения к таблице как к источнику данных. Для оптимизации наполнения временных таблиц в запросе подойдёт разбор нюансов использования оператора ДОБАВИТЬ для временной таблицы.

Способ 4. Использование Библиотеки стандартных подсистем (БСП)

Если ваша конфигурация построена на базе БСП, не нужно изобретать велосипед. В общем модуле ОбщегоНазначенияКлиентСервер (или аналогичных в зависимости от версии БСП) уже реализованы вспомогательные функции для работы с коллекциями.

Функция ДополнитьТаблицу из БСП делает ровно то, что мы описывали в первом способе, но она уже протестирована и является стандартом разработки. Рекомендуется всегда проверять наличие подходящих методов в модулях ОбщегоНазначения, прежде чем писать собственный цикл.

Способ 5. Горизонтальное объединение (JOIN)

Иногда под термином "объединить" понимается не добавление строк в конец, а дополнение текущих строк новыми колонками из другой таблицы по ключевому полю (аналог SQL JOIN). В этом случае крайне важно использовать индексацию для оптимизации поиска.

Проанализируем ситуацию: у нас есть основная таблица и вспомогательная с ценами. Чтобы быстро подтянуть цены, мы можем сделать следующее:

  1. Добавить индекс к вспомогательной таблице: ТЗ_Цены.Индексы.Добавить("Номенклатура");.
  2. В цикле по основной таблице использовать метод Найти(). Благодаря индексу поиск будет происходить мгновенно.

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

Способ 6. Прямое копирование структуры

Если нам нужно создать таблицу с точно такой же структурой, как у существующей, используем метод СкопироватьКолонки(). Это создаст пустую таблицу с идентичными именами и типами полей. Если же нам нужна полная копия с данными, используем Скопировать(). Эти методы работают на уровне ядра системы и выполняются максимально быстро.

Резюме и рекомендации

Подведем итог: выбор метода объединения зависит от ваших целей. Рассмотрим основные рекомендации:

Правильный выбор метода объединения таблиц значений не только упрощает код, но и значительно повышает стабильность и скорость работы вашего прикладного решения.

← На главную