В процессе разработки на платформе 1С:Предприятие программисты часто сталкиваются с необходимостью объединения данных из нескольких источников. Одной из самых частых задач является слияние двух объектов типа ТаблицаЗначений. Несмотря на кажущуюся простоту, этот процесс имеет свои нюансы, связанные с производительностью, типизацией колонок и структурой данных. В этой статье мы подробно разберем все возможные подходы, проанализируем типичные ошибки и выясним, какой метод лучше использовать в конкретных ситуациях.
Это классический и самый наглядный метод, который подходит для небольших и средних таблиц. Основная идея заключается в переборе строк одной таблицы и добавлении их в другую. Для автоматического сопоставления колонок по именам мы используем системную процедуру ЗаполнитьЗначенияСвойств.
Рассмотрим пример реализации универсальной процедуры для дополнения одной таблицы данными из другой:
// Дополняет таблицу значений-приемник данными из таблицы значений-источник
Процедура ДополнитьТаблицу(ТаблицаИсточник, ТаблицаПриемник) Экспорт
Для Каждого СтрокаИсточника Из ТаблицаИсточник Цикл
// Добавляем новую пустую строку в приемник
НоваяСтрока = ТаблицаПриемник.Добавить();
// Копируем данные из источника в приемник по совпадающим именам колонок
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаИсточника);
КонецЦикла;
КонецПроцедуры
Проанализируем ситуацию, когда этот метод может не сработать. Как правило, это происходит из-за того, что в ТаблицаПриемник отсутствуют колонки с теми же именами, что и в ТаблицаИсточник. Метод ЗаполнитьЗначенияСвойств работает только по совпадающим идентификаторам свойств. Если в приемнике нет колонки "Сумма", данные из источника просто не будут скопированы.
Важное примечание по параметрам: Функция ЗаполнитьЗначенияСвойств имеет дополнительные параметры СписокСвойств и ИсключаемыеСвойства. Если вам нужно перенести только определенные колонки, обязательно укажите их в третьем параметре через запятую. Это повысит читаемость кода и исключит лишние операции.
Часто программисты сталкиваются с тем, что строки добавляются, но значения в ячейках остаются пустыми. Выясним причину: чаще всего дело в несовпадении типов элементов в колонках двух таблиц. Например, в одной таблице колонка "Артикул" имеет тип Строка, а в другой — Число. При попытке заполнения значения могут игнорироваться или приводиться к некорректному виду.
Если структуры таблиц разные, рассмотрим следующий алгоритм действий:
ОписаниеТипов.Такой подход гарантирует, что ни одна колонка не будет потеряна и типы данных будут соблюдены.
Если таблицы содержат тысячи или десятки тысяч строк, использование цикла может существенно замедлить работу системы. В этом случае наиболее эффективным вариантом будет использование объекта Запрос. Платформа позволяет передавать таблицы значений в запрос в качестве параметров.
Разберем по шагам, как это реализовать:
ОБЪЕДИНИТЬ ВСЕ для слияния данных.Пример кода для объединения через запрос:
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
// Устанавливаем таблицы как параметры
Запрос.УстановитьПараметр("ТЗ1", Таблица1);
Запрос.УстановитьПараметр("ТЗ2", Таблица2);
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Данные ИЗ &ТЗ1 КАК ТЗ1
;
ВЫБРАТЬ * ИЗ ВТ_Данные КАК ТЗ
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ * ИЗ &ТЗ2 КАК ТЗ2";
РезультатЗапроса = Запрос.Выполнить();
ТаблицаРезультат = РезультатЗапроса.Выгрузить();
Важно: Для работы этого метода колонки исходных таблиц должны иметь строго определенные типы (не Произвольный). Если типы не заданы, запрос выдаст ошибку при попытке обращения к таблице как к источнику данных. Для оптимизации наполнения временных таблиц в запросе подойдёт разбор нюансов использования оператора ДОБАВИТЬ для временной таблицы.
Если ваша конфигурация построена на базе БСП, не нужно изобретать велосипед. В общем модуле ОбщегоНазначенияКлиентСервер (или аналогичных в зависимости от версии БСП) уже реализованы вспомогательные функции для работы с коллекциями.
Функция ДополнитьТаблицу из БСП делает ровно то, что мы описывали в первом способе, но она уже протестирована и является стандартом разработки. Рекомендуется всегда проверять наличие подходящих методов в модулях ОбщегоНазначения, прежде чем писать собственный цикл.
Иногда под термином "объединить" понимается не добавление строк в конец, а дополнение текущих строк новыми колонками из другой таблицы по ключевому полю (аналог SQL JOIN). В этом случае крайне важно использовать индексацию для оптимизации поиска.
Проанализируем ситуацию: у нас есть основная таблица и вспомогательная с ценами. Чтобы быстро подтянуть цены, мы можем сделать следующее:
ТЗ_Цены.Индексы.Добавить("Номенклатура");.Найти(). Благодаря индексу поиск будет происходить мгновенно.
// Пример оптимизированного поиска
ТЗ_Цены.Индексы.Добавить("Номенклатура");
Для Каждого Строка Из ТЗ_Основная Цикл
НайденнаяСтрока = ТЗ_Цены.Найти(Строка.Номенклатура, "Номенклатура");
Если НайденнаяСтрока <> Неопределено Тогда
Строка.Цена = НайденнаяСтрока.Цена;
КонецЕсли;
КонецЦикла;
Если нам нужно создать таблицу с точно такой же структурой, как у существующей, используем метод СкопироватьКолонки(). Это создаст пустую таблицу с идентичными именами и типами полей. Если же нам нужна полная копия с данными, используем Скопировать(). Эти методы работают на уровне ядра системы и выполняются максимально быстро.
Подведем итог: выбор метода объединения зависит от ваших целей. Рассмотрим основные рекомендации:
ЗаполнитьЗначенияСвойств.Правильный выбор метода объединения таблиц значений не только упрощает код, но и значительно повышает стабильность и скорость работы вашего прикладного решения.