К статье
Практический материал

Разработка и Конфигурация · 10 мин

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

Как объединить две таблицы значений в 1С: цикл с переносом строк, ВыполнитьОбъединение, запрос с ОБЪЕДИНИТЬ ВСЕ. Примеры кода, ошибки и проверка результата.

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

Выбор способа зависит от трёх условий: совпадают ли колонки таблиц, нужно ли устранять дубли и где выполняется код — на сервере с доступом к запросам или в толстом клиенте. Ниже разобраны рабочие варианты с примерами кода, ограничениями и способами проверки результата.

Как подготовить таблицы перед объединением

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

Посмотреть состав колонок можно так: перебрать коллекцию Таблица.Колонки и сравнить имена. При необходимости недостающие колонки добавляют методом Колонки.Добавить("ИмяКолонки", ОписаниеТипа). Порядок колонок при переносе значений не важен — обращение идёт по имени.

Для Каждого Колонка Из Таблица2.Колонки Цикл

Если Таблица1.Колонки.Найти(Колонка.Имя) = Неопределено Тогда

Таблица1.Колонки.Добавить(Колонка.Имя, Колонка.ТипЗначения);

КонецЕсли;

КонецЦикла;

Отдельно проверьте типы значений в одноимённых колонках. Если в первой таблице колонка «Сумма» имеет тип Число(15,2), а во второй — Строка, при переносе возможны неявные преобразования или ошибки. Приведите типы заранее, если таблицы формируются из разных источников.

Объединение циклом с переносом строк

Универсальный способ, работающий везде — на сервере, в толстом клиенте, во внешних обработках. Суть: перебираем строки второй таблицы, для каждой добавляем новую строку в первую и копируем значения.

Для Каждого СтрокаТ2 Из Таблица2 Цикл

НоваяСтрока = Таблица1.Добавить();

ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаТ2);

КонецЦикла;

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

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

Порядок действий при объединении циклом
  1. 1
    Проверьте и при необходимости добавьте недостающие колонки в целевую таблицу
  2. 2
    Переберите строки второй таблицы циклом Для Каждого
  3. 3
    Для каждой строки вызовите Добавить() и ЗаполнитьЗначенияСвойств
  4. 4
    Сверьте итоговое количество строк с суммой строк обеих таблиц

Объединение через запрос с ОБЪЕДИНИТЬ ВСЕ

Если таблицы велики или результат нужен сразу с сортировкой и группировкой, эффективнее поместить обе таблицы во временные таблицы запроса и объединить их оператором ОБЪЕДИНИТЬ ВСЕ. Этот вариант доступен там, где можно выполнить запрос — на сервере и в толстом клиенте.

Запрос = Новый Запрос;

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

Запрос.Текст =

"ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Т1 ИЗ &Таблица1 КАК Т1

|;

|ВЫБРАТЬ * ПОМЕСТИТЬ ВТ_Т2 ИЗ &Таблица2 КАК Т2

|;

|ВЫБРАТЬ * ИЗ ВТ_Т1

|ОБЪЕДИНИТЬ ВСЕ

|ВЫБРАТЬ * ИЗ ВТ_Т2";

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

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

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

Разница между ОБЪЕДИНИТЬ и ОБЪЕДИНИТЬ ВСЕ принципиальна: вариант без ВСЕ устраняет полностью совпадающие строки-дубликаты, вариант с ВСЕ сохраняет все строки обеих таблиц. Для простого «склеивания» почти всегда нужен именно ОБЪЕДИНИТЬ ВСЕ — он к тому же выполняется быстрее, так как платформе не требуется поиск дублей.

Колонки в объединяемых выборках должны совпадать по количеству и совместимости типов. Если состав различается, вместо * перечислите колонки явно и дополните недостающие конструкцией NULL КАК ИмяКолонки или значением по умолчанию.

Какой способ выбрать в разных ситуациях

Сравнение вариантов

Цикл с Добавить()

Универсален, работает везде, легко отлаживается. Медленнее на больших таблицах.

Запрос с ОБЪЕДИНИТЬ ВСЕ

Быстрый на больших объёмах, позволяет сразу сортировать и группировать. Требует сервера или толстого клиента и одинаковых типов колонок.

Свернуть() после объединения

Не самостоятельный способ, а дополнение: убирает дубли и суммирует числовые колонки уже в объединённой таблице.

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

Отдельный случай — когда нужна не конкатенация, а слияние по ключу: например, к строкам первой таблицы добавить колонки из второй по совпадению номенклатуры. Это уже не объединение, а соединение — оно решается запросом с ЛЕВОЕ СОЕДИНЕНИЕ либо методом Найти() по ключевой колонке в цикле.

Маршрут решения

Как выбрать действие

Строки нужно просто добавить одна к другой, таблицы небольшиеИспользуйте цикл с Добавить() и ЗаполнитьЗначенияСвойств
Таблицы большие или нужна сортировка и группировка результатаПоместите таблицы в запрос и выполните ОБЪЕДИНИТЬ ВСЕ
Нужно дополнить строки данными из второй таблицы по ключуИспользуйте соединение в запросе или Найти() по ключевой колонке
После объединения нужны уникальные строки с суммамиВызовите Свернуть() с указанием колонок группировки и суммирования

Устранение дублей и свёртка результата

После объединения часто требуется убрать повторяющиеся строки. Для таблицы значений это делает метод Свернуть(КолонкиГруппировок, КолонкиСуммирования): он группирует строки по указанным колонкам и суммирует числовые значения. Если суммировать нечего, второй параметр опускают — тогда останутся просто уникальные комбинации значений.

Таблица1.Свернуть("Номенклатура, Склад", "Количество, Сумма");

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

Альтернатива без потери колонок — поиск дублей вручную: создать соответствие, где ключом служит строка из значений ключевых колонок, и удалять повторные строки. Это дольше писать, но даёт полный контроль над тем, какая из дублирующихся строк останется.

Проверка результата и типичные ошибки

Минимальная проверка после объединения — контроль количества строк: при простом склеивании итог должен равняться сумме строк обеих таблиц. Сравните Таблица1.Количество() до и после. Если строк меньше ожидаемого — где-то сработало устранение дублей; если больше — возможно, объединение выполнено дважды.

Контрольные точки

Как проверить результат

Количество строк
Норма

Равно сумме строк исходных таблиц при склеивании

Тревожный признак

Меньше — сработало устранение дублей; больше — повторное объединение

Значения ключевых колонок
Норма

Все значения из второй таблицы присутствуют в итоговой

Тревожный признак

Часть значений пуста — не совпали типы или имена колонок

Итоги по суммовым колонкам
Норма

Итог равен сумме итогов обеих таблиц

Тревожный признак

Итог расходится — потеря строк или неверная свёртка

Типичные ошибки
01
Использование ОБЪЕДИНИТЬ вместо ОБЪЕДИНИТЬ ВСЕ — теряются одинаковые строки, итоги занижаются
02
Копирование значений через прямое присваивание по именам без проверки состава колонок — ошибка при отсутствии колонки
03
Свертка исходной таблицы вместо копии — безвозвратно удаляются не указанные в параметрах колонки
04
Объединение таблиц с разными типами одноимённых колонок — пустые или искажённые значения в результате
05
Повторный вызов процедуры объединения без очистки целевой таблицы — задвоение данных

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

Частые вопросы

Можно ли объединить таблицы с разным набором колонок?

Да. При объединении циклом недостающие колонки нужно добавить в целевую таблицу методом Колонки.Добавить(), лишние колонки второй таблицы просто не перенесутся. В запросе вместо звёздочки перечислите колонки явно и дополните недостающие конструкцией NULL КАК ИмяКолонки.

Чем ОБЪЕДИНИТЬ отличается от ОБЪЕДИНИТЬ ВСЕ в запросе 1С?

ОБЪЕДИНИТЬ устраняет полностью совпадающие строки-дубликаты, ОБЪЕДИНИТЬ ВСЕ сохраняет все строки обеих выборок. Второй вариант быстрее и обычно нужен именно он — если дубли не требуются, их убирают осознанно через Свернуть() или группировку.

Как объединить таблицы и сразу получить итоги по дублям?

После объединения вызовите Свернуть("КолонкиГруппировки", "СуммовыеКолонки") — строки с одинаковыми значениями ключевых колонок сольются, а числовые поля просуммируются. Помните, что колонки, не указанные в параметрах, будут удалены, поэтому при необходимости работайте с копией таблицы.

Почему после объединения часть значений стала пустой?

Чаще всего причина в несовпадении типов одноимённых колонок: например, в одной таблице колонка имеет тип Число, в другой — Строка. Проверьте ТипЗначения колонок обеих таблиц и приведите их к единому типу до объединения.

Как объединить таблицы по ключу, а не просто склеить?

Это задача соединения, а не объединения. В запросе используйте ЛЕВОЕ СОЕДИНЕНИЕ по ключевому полю. Без запроса — перебирайте строки первой таблицы и ищите соответствие во второй методом Найти(Значение, "ИмяКолонки"), затем заполняйте добавленные колонки.

Что быстрее на больших таблицах — цикл или запрос?

Запрос с ОБЪЕДИНИТЬ ВСЕ заметно эффективнее на таблицах с десятками и сотнями тысяч строк, так как обработка выполняется на уровне платформы, а не интерпретатором встроенного языка. Для небольших таблиц разница неощутима, и проще использовать цикл.

Итог

Что важно запомнить

Простое склеивание таблиц делается циклом с Добавить() и ЗаполнитьЗначенияСвойств, большие объёмы — запросом с ОБЪЕДИНИТЬ ВСЕ. Перед объединением проверьте состав и типы колонок, после — сверьте количество строк и итоги. Для устранения дублей используйте Свернуть() на копии таблицы, а слияние по ключу делайте соединением, а не объединением.