Сравнение табличных частей в 1С:Предприятие — одна из самых востребованных задач при работе с документами, особенно когда требуется выявить расхождения между версиями, найти дубликаты или проконтролировать корректность переноса данных. В отличие от обычных реквизитов, табличные части содержат набор строк с одинаковой структурой, что усложняет их анализ стандартными средствами платформы. Без правильного подхода сравнение может занять часы ручной работы или привести к ошибкам из-за пропущенных строк, изменённых значений или несовпадения порядка записей.

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

1. Ручное сравнение: когда достаточно визуального анализа

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

Чтобы открыть два документа одновременно:

  • 📄 Откройте первый документ в отдельном окне через контекстное меню (правый клик → Открыть в новом окне).
  • 🔍 Используйте фильтр по дате/номеру, чтобы быстро найти второй документ для сравнения.
  • 📊 Расположите окна рядом (в Windows: зажмите клавишу Windows + стрелку влево/вправо).
  • 🔄 Включите сортировку по ключевому реквизиту (например, по Номенклатуре) в обеих таблицах для удобства.

Преимущество метода — скорость для мелких задач. Однако уже при 50+ строках велик риск пропустить расхождения, особенно если они касаются незначительных изменений (например, корректировки количества на 0.01). Кроме того, ручное сравнение не фиксирует результаты — при необходимости документации придётся вести протокол вручную.

⚠️ Внимание: При ручном сравнении табличных частей с динамическим составом колонок (например, когда реквизиты добавляются через механизм дополнительных реквизитов) часть данных может остаться незамеченной. Всегда проверяйте полный состав колонок в обеих таблицах через контекстное меню → Настройки списка.
📊 Как часто вам приходится сравнивать табличные части в 1С?
Ежедневно
Несколько раз в неделю
Редко, по необходимости
Никогда не делал

2. Сравнение через отчёты: универсальный способ без программирования

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

Пошаговая инструкция:

  1. Откройте Универсальный отчёт через меню Отчёты → Стандартные отчёты.
  2. В настройках отчёта укажите источник данных — документ с нужной табличной частью (например, Документ.РеализацияТоваровУслуг.Товары).
  3. Добавьте все необходимые поля в вывод, включая служебные (например, Ссылка для идентификации строк).
  4. Экспортируйте данные в Excel через кнопку Выгрузить.
  5. Повторите шаги для второго документа и сравните файлы с помощью функции Сравнить и объединить книги в Excel.

Этот метод подходит для одноразовых проверок и не требует изменения конфигурации. Однако он не лишён недостатков: экспорт/импорт данных занимает время, а при большом объёме строк Excel может тормозить. Кроме того, так невозможно автоматизировать процесс для регулярных проверок.

Выбрать корректный источник данных в универсальном отчёте|

Добавить все реквизиты табличной части, включая скрытые|

Указать период или фильтр по документам|

Проверить формат выгрузки (лучше CSV для больших объёмов)|

Сохранить оба файла с понятными именами (например, "Реализация_123.csv")-->

3. Сравнение с помощью запросов: мощь языка 1С

Для опытных пользователей и разработчиков самый эффективный способ — использование языка запросов 1С. Запросы позволяют сравнивать табличные части по любым критериям, учитывать иерархию, агрегировать данные и выводить результаты в удобном виде. Например, можно найти строки, которые есть в одном документе, но отсутствуют в другом, или выявить расхождения по конкретным полям.

Пример запроса для сравнения табличных частей документов РеализацияТоваровУслуг по номенклатуре и количеству:

ВЫБРАТЬ

Товары1.Ссылка КАК Ссылка,

Товары1.Номенклатура КАК Номенклатура,

Товары1.Количество КАК КоличествоДок1,

Товары2.Количество КАК КоличествоДок2,

(Товары1.Количество - Товары2.Количество) КАК Разница

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК Товары1

ЛЕВОЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг.Товары КАК Товары2

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

И Товары1.Ссылка.Номер = "000123"

И Товары2.Ссылка.Номер = "000124"

ГДЕ

Товары1.Количество <> Товары2.Количество

ИЛИ Товары2.Ссылка ЕСТЬ NULL

Этот запрос вернёт все строки, где количество товаров отличается между документами №000123 и №000124, а также строки, присутствующие только в первом документе. Для обратного сравнения (строки только во втором документе) добавьте условие ИЛИ Товары1.Ссылка ЕСТЬ NULL.

⚠️ Внимание: При сравнении табличных частей через запросы всегда учитывайте тип сравнения. Например, для реквизитов типа СправочникСсылка (номенклатура, контрагенты) сравнивайте по УникальномуИдентификатору(), а не по наименованию — это исключит ошибки при переименовании элементов справочников.
Тип сравнения Пример условия в запросе Когда использовать
По ссылке Товары1.Номенклатура = Товары2.Номенклатура Для точного совпадения элементов справочников
По уникальному идентификатору Товары1.Номенклатура.УникальныйИдентификатор() = Товары2.Номенклатура.УникальныйИдентификатор() Если возможны переименования элементов
По строковому представлению СОКРЛП(Товары1.Номенклатура) = СОКРЛП(Товары2.Номенклатура) Для сравнения по наименованиям (риск ошибок!)
По нескольким полям Товары1.Номенклатура = Товары2.Номенклатура И Товары1.Характеристика = Товары2.Характеристика Для таблиц с составными ключами (например, номенклатура + характеристика)

4. Программное сравнение: автоматизация через встроенный язык

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

Пример кода для сравнения табличных частей двух документов с выводом результата в таблицу значений:

Процедура СравнитьТабличныеЧасти(Док1, Док2, ИмяТабличнойЧасти)

// Создаём таблицу для результата

Результат = Новый ТаблицаЗначений;

Результат.Колонки.Добавить("ТипРасхождения", Новый ОписаниеТипов("Строка"));

Результат.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));

Результат.Колонки.Добавить("КоличествоДок1");

Результат.Колонки.Добавить("КоличествоДок2");

// Получаем табличные части

ТЧ1 = Док1[ИмяТабличнойЧасти];

ТЧ2 = Док2[ИмяТабличнойЧасти];

// Сравниваем строки первого документа

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

Найдено = Ложь;

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

Если Строка1.Номенклатура.УникальныйИдентификатор() = Строка2.Номенклатура.УникальныйИдентификатор() Тогда

Если Строка1.Количество <> Строка2.Количество Тогда

НоваяСтрока = Результат.Добавить();

НоваяСтрока.ТипРасхождения = "Разное количество";

НоваяСтрока.Номенклатура = Строка1.Номенклатура;

НоваяСтрока.КоличествоДок1 = Строка1.Количество;

НоваяСтрока.КоличествоДок2 = Строка2.Количество;

КонецЕсли;

Найдено = Истина;

Прервать;

КонецЕсли;

КонецЦикла;

Если НЕ Найдено Тогда

НоваяСтрока = Результат.Добавить();

НоваяСтрока.ТипРасхождения = "Отсутствует во втором документе";

НоваяСтрока.Номенклатура = Строка1.Номенклатура;

НоваяСтрока.КоличествоДок1 = Строка1.Количество;

КонецЕсли;

КонецЦикла;

// Сравниваем строки второго документа (на предмет отсутствия в первом)

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

Найдено = Ложь;

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

Если Строка2.Номенклатура.УникальныйИдентификатор() = Строка1.Номенклатура.УникальныйИдентификатор() Тогда

Найдено = Истина;

Прервать;

КонецЕсли;

КонецЦикла;

Если НЕ Найдено Тогда

НоваяСтрока = Результат.Добавить();

НоваяСтрока.ТипРасхождения = "Отсутствует в первом документе";

НоваяСтрока.Номенклатура = Строка2.Номенклатура;

НоваяСтрока.КоличествоДок2 = Строка2.Количество;

КонецЕсли;

КонецЦикла;

Возврат Результат;

КонецПроцедуры

Этот код можно встроить в обработку или использовать как функцию в других процедурах. Преимущества программного подхода:

  • 🤖 Полная автоматизация — сравнение запускается по расписанию или по событию (например, при проведении документа).
  • 📊 Гибкость — можно добавлять дополнительные проверки (например, по ценам, скидкам, НДС).
  • 📤 Интеграция — результаты сравнения можно сразу отправлять по email или сохранять в базу.
💡

Для ускорения программного сравнения больших табличных частей (1000+ строк) предварительно преобразуйте их в ТаблицуЗначений и отсортируйте по ключевому полю. Это сократит время выполнения в 2-3 раза.

5. Сравнение с учётом иерархии: работа с подчинёнными таблицами

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

Для сравнения иерархических табличных частей используйте рекурсивный обход или многоуровневые запросы. Пример для документов с подчинёнными таблицами:

Процедура СравнитьИерархическиеТабличныеЧасти(Док1, Док2)

// Сравниваем основную табличную часть

ОсновныеРасхождения = СравнитьТабличныеЧасти(Док1, Док2, "Товары");

// Для каждой строки с расхождениями сравниваем подчинённые таблицы

Для Каждого Строка Из ОсновныеРасхождения Цикл

Если Строка.ТипРасхождения = "Разное количество" Тогда

// Находим соответствующие строки в оригинальных документах

СтрокаДок1 = НайтиСтрокуПоНоменклатуре(Док1.Товары, Строка.Номенклатура);

СтрокаДок2 = НайтиСтрокуПоНоменклатуре(Док2.Товары, Строка.Номенклатура);

// Сравниваем подчинённую таблицу "СерийныеНомера"

Если СтрокаДок1.СерийныеНомера.Количество() <> СтрокаДок2.СерийныеНомера.Количество() Тогда

ПодробныеРасхождения = СравнитьТабличныеЧасти(СтрокаДок1, СтрокаДок2, "СерийныеНомера");

Строка.Подробности = ПодробныеРасхождения;

КонецЕсли;

КонецЕсли;

КонецЦикла;

Возврат ОсновныеРасхождения;

КонецПроцедуры

Функция НайтиСтрокуПоНоменклатуре(ТабличнаяЧасть, Номенклатура)

Для Каждого Строка Из ТабличнаяЧасть Цикл

Если Строка.Номенклатура.УникальныйИдентификатор() = Номенклатура.УникальныйИдентификатор() Тогда

Возврат Строка;

КонецЕсли;

КонецЦикла;

Возврат Неопределён;

КонецФункции

Такой подход позволяет выявлять расхождения на всех уровнях вложенности. Например, если в документах совпадает количество товаров, но отличаются серийные номера, это будет зафиксировано в отчёте.

⚠️ Внимание: При работе с иерархическими табличными частями всегда проверяйте наличие подчинённых таблиц через Метаданные. В некоторых конфигурациях (например, 1С:ERP) подчинённые таблицы могут быть динамическими и не отображаться в основной форме документа.

6. Использование внешних инструментов: когда 1С не справляется

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

  • 📊 1С:Конвертация данных — для сравнения структур табличных частей в разных конфигурациях.
  • 🔧 SQL-клиенты (например, DBeaver) — для прямых запросов к базе (требует навыков работы с PostgreSQL или MS SQL).
  • 📈 Power BI/Tableau — для визуализации расхождений в больших объёмах данных.
  • 🤖 Скрипты на Python — для автоматизированного сравнения выгруженных данных (например, через pandas).

Пример использования SQL для сравнения табличных частей (для баз на PostgreSQL):

SELECT

t1._IDRRef AS id_doc1,

t2._IDRRef AS id_doc2,

t1._Fld123RRef AS nom_id, -- Поле "Номенклатура"

t1._Fld124 AS qty1, -- Поле "Количество" в док1

t2._Fld124 AS qty2 -- Поле "Количество" в док2

FROM

_Document123_TabPart123 t1 -- Табличная часть "Товары" документа "РеализацияТоваровУслуг"

FULL OUTER JOIN

_Document123_TabPart123 t2

ON t1._Fld123RRef = t2._Fld123RRef

AND t1._Document123_IDRRef = (SELECT _IDRRef FROM _Document123 WHERE _Number = '000123')

AND t2._Document123_IDRRef = (SELECT _IDRRef FROM _Document123 WHERE _Number = '000124')

WHERE

t1._Fld124 <> t2._Fld124

OR t1._Fld124 IS NULL

OR t2._Fld124 IS NULL;

Внешние инструменты уместны, когда:

  • 📂 Нужно сравнить данные из разных баз (например, рабочей и тестовой).
  • 🕒 Требуется анализ исторических изменений (например, кто и когда изменил табличную часть).
  • 📊 Необходима визуализация расхождений для отчётности.
Как выгрузить табличную часть в Excel через SQL?

Для выгрузки данных из табличной части 1С в Excel через SQL:

1. Подключитесь к базе 1С через DBeaver или другой SQL-клиент.

2. Найдите таблицу с данными документа (имя начинается с "_Document{ID}_TabPart{ID}").

3. Выполните запрос с JOIN к справочникам для получения читаемых наименований.

4. Экспортируйте результат в CSV и откройте в Excel.

Обратите внимание: структура базы 1С может меняться при обновлениях, поэтому перед выгрузкой сверьте актуальные имена таблиц и полей.

Типичные ошибки и как их избежать

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

Ошибка Причина Как избежать
Сравнение по наименованиям вместо ссылок Если номенклатура была переименована, строки не совпадут. Используйте УникальныйИдентификатор() или Ссылка.УникальныйИдентификатор().
Игнорирование порядка строк В табличных частях порядок строк может не совпадать, что сбивает визуальное сравнение. Всегда сортируйте данные по ключевому полю перед сравнением.
Неучёт пустых значений NULL в одном документе и 0 в другом могут считаться одинаковыми. Явно проверяйте на ЗначениеЗаполнено().
Сравнение только основной таблицы Подчинённые табличные части (например, серийные номера) остаются без внимания. Проверяйте иерархию через рекурсивные процедуры.
Несоответствие версий платформы В разных версиях 1С могут отличаться методы работы с табличными частями. Тестируйте код на целевой версии платформы.

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

  • 🔧 Используйте Попытка...Исключение для обработки отсутствующих полей.
  • 📋 Выгружайте метаданные табличных частей перед сравнением (через Метаданные.ТабличныеЧасти).
  • 🔄 Применяйте динамическое формирование запросов на основе доступных реквизитов.
💡

Перед массовым сравнением табличных частей всегда проверяйте их структуру через Метаданные. Это убережёт от ошибок при изменении конфигурации.

FAQ: Ответы на частые вопросы

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

Да, но для этого потребуется:

  1. Выгрузить данные из обеих баз в промежуточный формат (например, JSON или CSV).
  2. Написать обработку, которая загрузит данные и выполнит сравнение.
  3. Или использовать внешние инструменты (например, SQL-клиент для прямых запросов к обеим базам).

Готовых инструментов для такого сравнения в 1С нет, поэтому обычно пишут кастомные решения.

Как сравнить табличные части, если в них разное количество строк?

Используйте ПОЛНОЕ СОЕДИНЕНИЕ (FULL JOIN) в запросах или проверяйте наличие строк в обеих табличных частях через вложенные циклы (как в примере программного сравнения выше). Это позволит выявить:

  • Строки, присутствующие только в первом документе.
  • Строки, присутствующие только во втором документе.
  • Строки с расхождениями по значениям.
Какие реквизиты табличной части нельзя сравнивать напрямую?

Не рекомендуется сравнивать:

  • Ссылки на объекты — вместо этого используйте УникальныйИдентификатор().
  • Двоичные данные (например, картинки в реквизитах типа ХранилищеЗначения) — сравнивайте через хэши.
  • Динамические списки — их содержимое формируется в момент обращения и может отличаться.
  • Реквизиты с вычисляемыми значениями — они могут меняться в зависимости от контекста.
Как ускорить сравнение больших табличных частей (10 000+ строк)?

Для оптимизации:

  • Преобразуйте табличные части в ТаблицуЗначений и отсортируйте по ключевому полю.
  • Используйте ИндексированныеКоллекции (например, Соответствие) для быстрого поиска строк.
  • Разбейте сравнение на пакеты (например, по 1000 строк) с паузами через Подождать().
  • Для SQL-сравнения создайте временные таблицы с индексами по ключевым полям.

На платформе 8.3.20+ также можно использовать ПараллельныеЗадачи для распределения нагрузки.

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

Да, но с осторожностью. Для автоматического исправления:

  1. Напишите процедуру, которая будет копировать данные из "правильного" документа в ошибочный.
  2. Добавьте проверки на права доступа (ПраваНаИзменение()).
  3. Создайте механизм отката (например, сохраняйте оригинальные данные перед изменением).
  4. Логируйте все изменения с указанием пользователя и времени.

Пример кода для копирования строк:

Процедура ИсправитьРасхождения(ДокОшибка, ДокЭталон)

ТЧОшибка = ДокОшибка.Товары;

ТЧЭталон = ДокЭталон.Товары;

// Очищаем ошибочную табличную часть

ТЧОшибка.Очистить();

// Копируем строки из эталона

Для Каждого СтрокаЭталон Из ТЧЭталон Цикл

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

НоваяСтрока.Номенклатура = СтрокаЭталон.Номенклатура;

НоваяСтрока.Количество = СтрокаЭталон.Количество;

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

КонецЦикла;

ДокОшибка.Записать();

КонецПроцедуры

⚠️ Автоматическое исправление рекомендуется только для технических расхождений (например, округление количества). Для бизнес-данных лучше использовать полуавтоматический режим с подтверждением пользователя.