Разработка и Конфигурация · 10 мин
Как объединить две таблицы значений в 1С
Как объединить две таблицы значений в 1С: цикл с переносом строк, ВыполнитьОбъединение, запрос с ОБЪЕДИНИТЬ ВСЕ. Примеры кода, ошибки и проверка результата.
Объединение двух таблиц значений — типовая задача при разработке отчётов, обработок и обменов данными в 1С. Например, нужно собрать в одну таблицу остатки с двух складов, склеить результаты двух запросов или дополнить таблицу документа внешними данными. Встроенного метода «объединить» у объекта ТаблицаЗначений нет, поэтому задачу решают несколькими способами: перебором строк, объединением через запрос или специальными методами платформы.
Выбор способа зависит от трёх условий: совпадают ли колонки таблиц, нужно ли устранять дубли и где выполняется код — на сервере с доступом к запросам или в толстом клиенте. Ниже разобраны рабочие варианты с примерами кода, ограничениями и способами проверки результата.
Как подготовить таблицы перед объединением
Главное условие корректного объединения — совпадающий состав колонок. Если во второй таблице есть колонки, которых нет в первой, данные этих колонок при простом переносе строк потеряются или вызовут ошибку, в зависимости от способа. Поэтому перед объединением проверьте структуру обеих таблиц.
Посмотреть состав колонок можно так: перебрать коллекцию Таблица.Колонки и сравнить имена. При необходимости недостающие колонки добавляют методом Колонки.Добавить("ИмяКолонки", ОписаниеТипа). Порядок колонок при переносе значений не важен — обращение идёт по имени.
Для Каждого Колонка Из Таблица2.Колонки Цикл
Если Таблица1.Колонки.Найти(Колонка.Имя) = Неопределено Тогда
Таблица1.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);
КонецЕсли;
КонецЦикла;
Отдельно проверьте типы значений в одноимённых колонках. Если в первой таблице колонка «Сумма» имеет тип Число(15,2), а во второй — Строка, при переносе возможны неявные преобразования или ошибки. Приведите типы заранее, если таблицы формируются из разных источников.
Объединение циклом с переносом строк
Универсальный способ, работающий везде — на сервере, в толстом клиенте, во внешних обработках. Суть: перебираем строки второй таблицы, для каждой добавляем новую строку в первую и копируем значения.
Для Каждого СтрокаТ2 Из Таблица2 Цикл
НоваяСтрока = Таблица1.Добавить();
ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТ2);
КонецЦикла;
Метод ЗаполнитьЗначенияСвойств копирует значения только по совпадающим именам колонок, поэтому различия в составе не вызовут ошибку — лишние данные просто не перенесутся. Если нужно перенести только часть колонок, передайте их список вторым параметром: ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТ2, "Номенклатура, Количество, Сумма").
Способ подходит для таблиц небольшого и среднего размера — до нескольких десятков тысяч строк. На очень больших таблицах цикл работает медленнее запроса, потому что каждая итерация выполняется встроенным языком без оптимизации.
- 1Проверьте и при необходимости добавьте недостающие колонки в целевую таблицу
- 2Переберите строки второй таблицы циклом Для Каждого
- 3Для каждой строки вызовите Добавить() и ЗаполнитьЗначенияСвойств
- 4Сверьте итоговое количество строк с суммой строк обеих таблиц
Объединение через запрос с ОБЪЕДИНИТЬ ВСЕ
Если таблицы велики или результат нужен сразу с сортировкой и группировкой, эффективнее поместить обе таблицы во временные таблицы запроса и объединить их оператором ОБЪЕДИНИТЬ ВСЕ. Этот вариант доступен там, где можно выполнить запрос — на сервере и в толстом клиенте.
Запрос = Новый Запрос;
Запрос.МенеджерВременныхТаблиц = Новый МенеджерВременныхТаблиц;
Запрос.Текст =
"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Т1 ИЗ &Таблица1 КАК Т1
|;
|ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Т2 ИЗ &Таблица2 КАК Т2
|;
|ВЫБРАТЬ * ИЗ ВТ_Т1
|ОБЪЕДИНИТЬ ВСЕ
|ВЫБРАТЬ * ИЗ ВТ_Т2";
Запрос.УстановитьПараметр("Таблица1", Таблица1);
Запрос.УстановитьПараметр("Таблица2", Таблица2);
Результат = Запрос.Выполнить().Выгрузить();
Разница между ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ принципиальна: вариант без ВСЕ устраняет полностью совпадающие строки-дубликаты, вариант с ВСЕ сохраняет все строки обеих таблиц. Для простого «склеивания» почти всегда нужен именно ОБЪЕДИНИТЬ ВСЕ — он к тому же выполняется быстрее, так как платформе не требуется поиск дублей.
Колонки в объединяемых выборках должны совпадать по количеству и совместимости типов. Если состав различается, вместо * перечислите колонки явно и дополните недостающие конструкцией NULL КАК ИмяКолонки или значением по умолчанию.
Какой способ выбрать в разных ситуациях
Сравнение вариантов
Универсален, работает везде, легко отлаживается. Медленнее на больших таблицах.
Быстрый на больших объёмах, позволяет сразу сортировать и группировать. Требует сервера или толстого клиента и одинаковых типов колонок.
Не самостоятельный способ, а дополнение: убирает дубли и суммирует числовые колонки уже в объединённой таблице.
Практическое правило простое: если обе таблицы уже есть в памяти и их размер умеренный — используйте цикл, он проще и прозрачнее в отладке. Если таблицы получены из запросов и дальше планируется ещё одна выборка — объединяйте на уровне запроса, не выгружая промежуточные результаты.
Отдельный случай — когда нужна не конкатенация, а слияние по ключу: например, к строкам первой таблицы добавить колонки из второй по совпадению номенклатуры. Это уже не объединение, а соединение — оно решается запросом с ЛЕВОЕ СОЕДИНЕНИЕ либо методом Найти() по ключевой колонке в цикле.
Как выбрать действие
Устранение дублей и свёртка результата
После объединения часто требуется убрать повторяющиеся строки. Для таблицы значений это делает метод Свернуть(КолонкиГруппировок, КолонкиСуммирования): он группирует строки по указанным колонкам и суммирует числовые значения. Если суммировать нечего, второй параметр опускают — тогда останутся просто уникальные комбинации значений.
Таблица1.Свернуть("Номенклатура, Склад", "Количество, Сумма");
Учтите важное ограничение: Свернуть удаляет из таблицы все колонки, не указанные в параметрах. Если нужно сохранить остальные данные, сначала скопируйте таблицу методом Скопировать() и сворачивайте копию, либо выполняйте группировку в запросе с СГРУППИРОВАТЬ ПО.
Альтернатива без потери колонок — поиск дублей вручную: создать соответствие, где ключом служит строка из значений ключевых колонок, и удалять повторные строки. Это дольше писать, но даёт полный контроль над тем, какая из дублирующихся строк останется.
Проверка результата и типичные ошибки
Минимальная проверка после объединения — контроль количества строк: при простом склеивании итог должен равняться сумме строк обеих таблиц. Сравните Таблица1.Количество() до и после. Если строк меньше ожидаемого — где-то сработало устранение дублей; если больше — возможно, объединение выполнено дважды.
Как проверить результат
Равно сумме строк исходных таблиц при склеивании
Меньше — сработало устранение дублей; больше — повторное объединение
Все значения из второй таблицы присутствуют в итоговой
Часть значений пуста — не совпали типы или имена колонок
Итог равен сумме итогов обеих таблиц
Итог расходится — потеря строк или неверная свёртка
Ещё одна частая проблема — модификация таблицы, которая используется где-то ещё: например, таблица является реквизитом формы или источником данных динамического списка. Перед объединением сделайте копию через Скопировать() и работайте с ней, если исходная таблица должна остаться неизменной.
Частые вопросы
Можно ли объединить таблицы с разным набором колонок?
Да. При объединении циклом недостающие колонки нужно добавить в целевую таблицу методом Колонки.Добавить(), лишние колонки второй таблицы просто не перенесутся. В запросе вместо звёздочки перечислите колонки явно и дополните недостающие конструкцией NULL КАК ИмяКолонки.
Чем ОБЪЕДИНИТЬ отличается от ОБЪЕДИНИТЬ ВСЕ в запросе 1С?
ОБЪЕДИНИТЬ устраняет полностью совпадающие строки-дубликаты, ОБЪЕДИНИТЬ ВСЕ сохраняет все строки обеих выборок. Второй вариант быстрее и обычно нужен именно он — если дубли не требуются, их убирают осознанно через Свернуть() или группировку.
Как объединить таблицы и сразу получить итоги по дублям?
После объединения вызовите Свернуть("КолонкиГруппировки", "СуммовыеКолонки") — строки с одинаковыми значениями ключевых колонок сольются, а числовые поля просуммируются. Помните, что колонки, не указанные в параметрах, будут удалены, поэтому при необходимости работайте с копией таблицы.
Почему после объединения часть значений стала пустой?
Чаще всего причина в несовпадении типов одноимённых колонок: например, в одной таблице колонка имеет тип Число, в другой — Строка. Проверьте ТипЗначения колонок обеих таблиц и приведите их к единому типу до объединения.
Как объединить таблицы по ключу, а не просто склеить?
Это задача соединения, а не объединения. В запросе используйте ЛЕВОЕ СОЕДИНЕНИЕ по ключевому полю. Без запроса — перебирайте строки первой таблицы и ищите соответствие во второй методом Найти(Значение, "ИмяКолонки"), затем заполняйте добавленные колонки.
Что быстрее на больших таблицах — цикл или запрос?
Запрос с ОБЪЕДИНИТЬ ВСЕ заметно эффективнее на таблицах с десятками и сотнями тысяч строк, так как обработка выполняется на уровне платформы, а не интерпретатором встроенного языка. Для небольших таблиц разница неощутима, и проще использовать цикл.
Что важно запомнить
Простое склеивание таблиц делается циклом с Добавить() и ЗаполнитьЗначенияСвойств, большие объёмы — запросом с ОБЪЕДИНИТЬ ВСЕ. Перед объединением проверьте состав и типы колонок, после — сверьте количество строк и итоги. Для устранения дублей используйте Свернуть() на копии таблицы, а слияние по ключу делайте соединением, а не объединением.