Сравнение табличных частей в 1С:Предприятие — одна из самых востребованных задач при работе с документами, особенно когда требуется выявить расхождения между версиями, найти дубликаты или проконтролировать корректность переноса данных. В отличие от обычных реквизитов, табличные части содержат набор строк с одинаковой структурой, что усложняет их анализ стандартными средствами платформы. Без правильного подхода сравнение может занять часы ручной работы или привести к ошибкам из-за пропущенных строк, изменённых значений или несовпадения порядка записей.
В этой статье мы разберём 5 практических способов сравнения табличных частей — от простых ручных методов до автоматизированных решений с использованием запросов и встроенного языка. Вы узнаете, как избежать типичных ловушек (например, сравнения по ссылкам вместо значений), какие инструменты платформы 1С 8.3 ускорят процесс, и где применять программный код для сложных сценариев. Особое внимание уделим сравнению табличных частей с учётом иерархии (подчинённых таблиц), что актуально для документов типа «Заказ клиента» или «Реализация товаров».
1. Ручное сравнение: когда достаточно визуального анализа
Если табличные части небольшие (до 20-30 строк) и имеют простую структуру, их можно сравнить вручную прямо в интерфейсе 1С. Этот метод не требует программирования, но подходит только для разовых проверок. Основной инструмент — форма документа с включённым режимом просмотра табличных частей бок о бок.
Чтобы открыть два документа одновременно:
- 📄 Откройте первый документ в отдельном окне через контекстное меню (правый клик →
Открыть в новом окне). - 🔍 Используйте фильтр по дате/номеру, чтобы быстро найти второй документ для сравнения.
- 📊 Расположите окна рядом (в Windows: зажмите клавишу
Windows+ стрелку влево/вправо). - 🔄 Включите сортировку по ключевому реквизиту (например, по
Номенклатуре) в обеих таблицах для удобства.
Преимущество метода — скорость для мелких задач. Однако уже при 50+ строках велик риск пропустить расхождения, особенно если они касаются незначительных изменений (например, корректировки количества на 0.01). Кроме того, ручное сравнение не фиксирует результаты — при необходимости документации придётся вести протокол вручную.
⚠️ Внимание: При ручном сравнении табличных частей с динамическим составом колонок (например, когда реквизиты добавляются через механизм дополнительных реквизитов) часть данных может остаться незамеченной. Всегда проверяйте полный состав колонок в обеих таблицах через контекстное меню → Настройки списка.
2. Сравнение через отчёты: универсальный способ без программирования
Для пользователей без навыков программирования оптимальный вариант — использование стандартных отчётов 1С, таких как Универсальный отчёт или Анализ данных. Эти инструменты позволяют выгрузить табличные части в удобный для сравнения формат (например, Excel) и применить условное форматирование для выделения расхождений.
Пошаговая инструкция:
- Откройте
Универсальный отчётчерез менюОтчёты → Стандартные отчёты. - В настройках отчёта укажите источник данных — документ с нужной табличной частью (например,
Документ.РеализацияТоваровУслуг.Товары). - Добавьте все необходимые поля в вывод, включая служебные (например,
Ссылкадля идентификации строк). - Экспортируйте данные в Excel через кнопку
Выгрузить. - Повторите шаги для второго документа и сравните файлы с помощью функции
Сравнить и объединить книгив 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С. Это позволит не только находить расхождения, но и автоматически формировать отчёты, отправлять уведомления или даже исправлять ошибки.
Пример кода для сравнения табличных частей двух документов с выводом результата в таблицу значений:
Процедура СравнитьТабличныеЧасти(Док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С могут быть недостаточными. В таких случаях помогают внешние инструменты:
- 📊 1С:Конвертация данных — для сравнения структур табличных частей в разных конфигурациях.
- 🔧 SQL-клиенты (например, DBeaver) — для прямых запросов к базе 1С (требует навыков работы с 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С?
Да, но для этого потребуется:
- Выгрузить данные из обеих баз в промежуточный формат (например, JSON или CSV).
- Написать обработку, которая загрузит данные и выполнит сравнение.
- Или использовать внешние инструменты (например, SQL-клиент для прямых запросов к обеим базам).
Готовых инструментов для такого сравнения в 1С нет, поэтому обычно пишут кастомные решения.
Как сравнить табличные части, если в них разное количество строк?
Используйте ПОЛНОЕ СОЕДИНЕНИЕ (FULL JOIN) в запросах или проверяйте наличие строк в обеих табличных частях через вложенные циклы (как в примере программного сравнения выше). Это позволит выявить:
- Строки, присутствующие только в первом документе.
- Строки, присутствующие только во втором документе.
- Строки с расхождениями по значениям.
Какие реквизиты табличной части нельзя сравнивать напрямую?
Не рекомендуется сравнивать:
- Ссылки на объекты — вместо этого используйте
УникальныйИдентификатор(). - Двоичные данные (например, картинки в реквизитах типа
ХранилищеЗначения) — сравнивайте через хэши. - Динамические списки — их содержимое формируется в момент обращения и может отличаться.
- Реквизиты с вычисляемыми значениями — они могут меняться в зависимости от контекста.
Как ускорить сравнение больших табличных частей (10 000+ строк)?
Для оптимизации:
- Преобразуйте табличные части в
ТаблицуЗначенийи отсортируйте по ключевому полю. - Используйте
ИндексированныеКоллекции(например,Соответствие) для быстрого поиска строк. - Разбейте сравнение на пакеты (например, по 1000 строк) с паузами через
Подождать(). - Для SQL-сравнения создайте временные таблицы с индексами по ключевым полям.
На платформе 8.3.20+ также можно использовать ПараллельныеЗадачи для распределения нагрузки.
Можно ли автоматически исправить расхождения в табличных частях?
Да, но с осторожностью. Для автоматического исправления:
- Напишите процедуру, которая будет копировать данные из "правильного" документа в ошибочный.
- Добавьте проверки на права доступа (
ПраваНаИзменение()). - Создайте механизм отката (например, сохраняйте оригинальные данные перед изменением).
- Логируйте все изменения с указанием пользователя и времени.
Пример кода для копирования строк:
Процедура ИсправитьРасхождения(ДокОшибка, ДокЭталон)
ТЧОшибка = ДокОшибка.Товары;
ТЧЭталон = ДокЭталон.Товары;
// Очищаем ошибочную табличную часть
ТЧОшибка.Очистить();
// Копируем строки из эталона
Для Каждого СтрокаЭталон Из ТЧЭталон Цикл
НоваяСтрока = ТЧОшибка.Добавить();
НоваяСтрока.Номенклатура = СтрокаЭталон.Номенклатура;
НоваяСтрока.Количество = СтрокаЭталон.Количество;
// Копируем остальные реквизиты
КонецЦикла;
ДокОшибка.Записать();
КонецПроцедуры
⚠️ Автоматическое исправление рекомендуется только для технических расхождений (например, округление количества). Для бизнес-данных лучше использовать полуавтоматический режим с подтверждением пользователя.