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

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

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

Как сравнить две таблицы значений в 1С: построчный перебор, запрос с соединением, свертка и объединение. Готовые примеры кода, типичные ошибки и FAQ.

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

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

Ниже разобраны четыре рабочих подхода — перебор с поиском, запрос с полным соединением, свертка объединённой таблицы и сравнение через массивы — с критериями выбора и типичными ошибками.

Определите, что именно нужно сравнить

Прежде чем писать код, сформулируйте задачу. Вариантов несколько: найти строки, которые есть в первой таблице, но отсутствуют во второй; найти строки с совпадающим ключом, но разными значениями реквизитов; проверить полную идентичность таблиц. От этого зависит и алгоритм, и структура результата.

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

Способ 1. Построчный перебор с методом Найти

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

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

СтрокаПоиска = Таблица2.Найти(СтрокаТЗ.Номенклатура, "Номенклатура");

Если СтрокаПоиска = Неопределено Тогда

// Строка есть только в первой таблице

ИначеЕсли СтрокаПоиска.Количество <> СтрокаТЗ.Количество Тогда

// Ключ совпал, но значения различаются

КонецЕсли;

КонецЦикла;

Чтобы найти строки, которые есть только во второй таблице, выполните симметричный обход в обратную сторону. Учтите ограничение: метод Найти ищет по одной колонке. Для составного ключа используйте НайтиСтроки(СтруктураОтбора) с несколькими полями или добавьте в обе таблицы вычисляемую колонку-ключ, склеив значения через разделитель.

Главный недостаток способа — производительность. Поиск по несортированной таблице выполняется линейным перебором, поэтому на таблицах в десятки тысяч строк сравнение займёт заметное время. Для ускорения можно создать индекс: Таблица2.Индексы.Добавить("Номенклатура").

Способ 2. Сравнение запросом с полным соединением

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

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

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

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

"ВЫБРАТЬ Т.Номенклатура, Т.Количество

|ПОМЕСТИТЬ Таб1 ИЗ &Таб1 КАК Т

|;

|ВЫБРАТЬ Т.Номенклатура, Т.Количество

|ПОМЕСТИТЬ Таб2 ИЗ &Таб2 КАК Т

|;

|ВЫБРАТЬ

| ЕСТЬNULL(Т1.Номенклатура, Т2.Номенклатура) КАК Номенклатура,

| Т1.Количество КАК Количество1,

| Т2.Количество КАК Количество2

|ИЗ Таб1 КАК Т1

|ПОЛНОЕ СОЕДИНЕНИЕ Таб2 КАК Т2

|ПО Т1.Номенклатура = Т2.Номенклатура

|ГДЕ Т1.Номенклатура ЕСТЬ NULL

| ИЛИ Т2.Номенклатура ЕСТЬ NULL

| ИЛИ Т1.Количество <> Т2.Количество";

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

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

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

В результирующей таблице строки с NULL в одной из колонок — это записи, отсутствующие в соответствующей таблице. Строки, где оба ключа заполнены, но количества различаются, — изменённые позиции. Такой результат удобно выводить пользователю или обрабатывать дальше.

Учтите нюанс: при передаче таблицы значений параметром запроса её типы колонок должны быть определены корректно. Если колонка составного типа или содержит NULL, запрос может выдать ошибку или неточный результат — при необходимости приведите типы функцией ВЫРАЗИТЬ.

Способ 3. Приём «объединить и свернуть»

Элегантный способ найти различия без циклов и запросов: скопировать обе таблицы в одну, добавив служебную колонку-признак, и свернуть. Одинаковые строки схлопнутся с суммой признака 2, а различающиеся останутся с признаком 1.

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

Общая.Колонки.Добавить("Признак");

Общая.ЗаполнитьЗначения(1, "Признак");

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

НоваяСтрока = Общая.Добавить();

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

НоваяСтрока.Признак = 1;

КонецЦикла;

Общая.Свернуть("Номенклатура,Количество", "Признак");

// Строки с Признак = 1 — различающиеся

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

Сравнение способов

Перебор с Найти()

Простой и наглядный код; подходит для таблиц до нескольких тысяч строк; медленный на больших объёмах без индекса

Запрос с соединением

Быстрый на больших таблицах, результат удобен для отчёта; требует менеджера временных таблиц и аккуратной работы с типами

Объединить и свернуть

Короткий код без запроса; не показывает источник строки без доработки признака, меняет порядок строк

Способ 4. Проверка полной идентичности таблиц

Если нужен только ответ «одинаковые или нет», не обязательно строить таблицу расхождений. Достаточно сравнить количество строк, а затем проверить, что каждая строка первой таблицы находится во второй с теми же значениями. Для ускорения таблицы предварительно сортируют по ключу: Таблица.Сортировать("Номенклатура") — и сравнивают строки попарно в одном цикле.

Для грубой быстрой проверки иногда используют сериализацию: выгрузить таблицу через ЗначениеВСтрокуВнутр() и сравнить полученные строки. Способ работает, но чувствителен к порядку строк и колонок — перед сравнением обе таблицы нужно одинаково отсортировать.

Порядок действий при сравнении
  1. 1
    Определите цель: расхождения, уникальные строки или факт идентичности
  2. 2
    Выровняйте состав и типы колонок обеих таблиц
  3. 3
    Выберите ключ сравнения (ссылка или набор колонок)
  4. 4
    Реализуйте сравнение подходящим способом
  5. 5
    Проверьте результат на контрольном примере с заведомо известными различиями

Типичные ошибки и ограничения

Чаще всего ложные расхождения возникают из-за типов данных: число 10 и строка "10" при сравнении не равны, а числа с разной точностью (10 и 10.00) в запросе могут вести себя неожиданно. Приводите типы заранее. Вторая частая причина — лишние пробелы и неразличимые символы в строковых ключах, особенно после загрузки из Excel; помогает СокрЛП().

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

Типичные ошибки
01
Сравнение без приведения типов — число и строка с одинаковым видом считаются разными значениями
02
Поиск по несортированной таблице без индекса на больших объёмах — сравнение выполняется минутами
03
Игнорирование дублей в ключевой колонке — Найти() возвращает только первую строку, остальные теряются
04
Сравнение таблиц с разным составом колонок — Свернуть() и ЗаполнитьЗначенияСвойств() работают некорректно

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

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

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

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

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

Количество расхождений
Норма

Равно числу заведомо внесённых различий в тестовом примере

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

Лишние или пропущенные строки в результате

Строки-расхождения
Норма

Каждая содержит понятную причину: нет в одной таблице или отличается значение

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

Строки выглядят идентичными, но помечены как различающиеся

Итоговый баланс строк
Норма

Всего = совпавшие + только в первой + только во второй

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

Сумма не сходится — вероятны дубли ключа

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

Есть ли в 1С стандартная функция сравнения таблиц значений?

Нет, встроенной функции нет. Задачу решают перебором с Найти() или НайтиСтроки(), запросом с соединением временных таблиц либо приёмом «объединить и свернуть». Выбор зависит от объёма данных и требуемого результата.

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

Используйте НайтиСтроки() со структурой отбора, где перечислены все ключевые колонки, либо добавьте служебную колонку-ключ, склеив значения через символ-разделитель, который не встречается в данных. В запросе просто перечислите все условия в секции ПО.

Что делать, если в ключевой колонке есть дубли?

Методы Найти() и соединение по ключу при дублях дают недостоверный результат. Сначала сверните обе таблицы по ключу с суммированием числовых колонок или добавьте в ключ дополнительные поля, делающие его уникальным.

Какой способ быстрее для таблиц в 100 тысяч строк?

Запрос с соединением временных таблиц — он обрабатывается на уровне СУБД. Перебор с Найти() без индексов на таком объёме будет работать неприемлемо долго; с добавленным индексом — быстрее, но обычно всё равно медленнее запроса.

Можно ли сравнить табличные части двух документов этими способами?

Да. Выгрузите табличные части в таблицы значений методом Выгрузить(), при необходимости отсортируйте одинаково и применяйте любой из описанных подходов. Это стандартный приём для контроля изменений документа перед записью.

Почему визуально одинаковые строки считаются разными?

Чаще всего причины — разные типы значений (число против строки), лишние пробелы или неразрывные пробелы в строках, различия в регистре букв. Проверьте типы колонок и примените СокрЛП() к строковым ключам перед сравнением.

Итог

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

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