При настройке обмена данными между несколькими информационными базами (например, при слиянии нескольких баз 1С:ЗУП в одну центральную), специалисты часто сталкиваются с проблемой корректной передачи табличных частей. Стандартное поведение механизма обмена в Конвертации данных 2.0 предполагает либо полную очистку табличной части перед загрузкой новыми данными, либо простое добавление строк, что приводит к появлению дублей. В некоторых случаях типовых возможностей обменов становится недостаточно, и особенно остро этот вопрос стоит для табличной части ДополнительныеРеквизиты, где важно сохранить уникальность настроек для каждого сотрудника.
В этой статье мы подробно разберем, почему стандартные флажки поиска могут не работать, и как реализовать интеллектуальное слияние строк, чтобы в целевой базе данные не затирались и не дублировались. Проанализируем ситуацию на примере справочника Сотрудники и его дополнительных реквизитов.
Прежде всего, выясним причину, по которой обычная установка свойства НеОчищать = Истина в правилах конвертации группы свойств (ПКГС) не решает задачу полностью. Когда мы устанавливаем этот флаг, система при загрузке объекта просто дописывает строки из файла обмена в существующую табличную часть объекта-приемника. Если один и тот же реквизит (например, "Номер ТМ") присутствует и в источнике, и в приемнике, у объекта появятся две строки с одинаковым смыслом.
Рассмотрим ситуацию глубже: почему поиск по полям внутри табличной части часто игнорируется? В КД 2.0 механизм сопоставления строк внутри ТЧ работает корректно только тогда, когда ключевые поля поиска (например, ссылка на свойство в Плане видов характеристик) абсолютно идентичны. Если в разных базах один и тот же по смыслу доп. реквизит имеет разные уникальные идентификаторы (GUID), система воспримет их как разные объекты, даже если их наименования совпадают. Следовательно, строки не будут «схлопнуты».
Проанализируем первый и самый важный этап решения: обеспечение идентичности ссылочных данных. Дополнительные реквизиты в ЗУП хранятся в ТЧ, где ключевой колонкой является Свойство. Это ссылка на элемент ПВХ ДополнительныеРеквизитыИСведения.
Для того чтобы слияние строк в справочнике Сотрудники вообще стало возможным, мы должны гарантировать, что ПКО для данного ПВХ настроено на поиск по Наименованию (и, возможно, по владельцу/набору свойств), а не по внутреннему идентификатору. Чтобы быстро сориентироваться в структуре правил, можно использовать портативный обозреватель правил конвертации свойств. Рассмотрим алгоритм настройки:
ДополнительныеРеквизитыИСведения.Наименование и установим для него галочку Поиск.Только после того как мы добьемся, что "НомерТМ" из Базы 1 и "НомерТМ" из Базы 2 при загрузке сопоставляются с одним и тем же элементом ПВХ в целевой базе, мы сможем двигаться дальше.
Как показывает практика, полагаться только на визуальные настройки поиска в табличной части рискованно. Самый надежный метод — написать небольшой программный код в обработчике ПослеЗагрузки правила конвертации объекта (ПКО) Сотрудники. Этот обработчик выполняется, когда объект уже создан/найден, его свойства заполнены, но он еще не записан в базу данных. В этом контексте заполнение значения данных дополнительных сведений объекта из источника в приемник требует четкой логики сопоставления.
Посмотрим на пример кода, который позволит нам «свернуть» табличную часть, удалив дублирующиеся строки и оставив актуальные значения. Предположим, что в целевой базе мы установили НеОчищать = Истина для табличной части ДополнительныеРеквизиты.
// Обработчик "ПослеЗагрузки" в ПКО Сотрудники
// Нам нужно объединить строки по колонке "Свойство"
ТаблицаДопРеквизитов = Объект.ДополнительныеРеквизиты.Выгрузить();
// Если таблица пустая, делать нечего
Если ТаблицаДопРеквизитов.Количество() > 0 Тогда
// Группируем таблицу по свойству.
// Внимание: если значения реквизитов разные,
// нужно решить, какое оставлять. Здесь мы оставляем последнее загруженное.
// Создаем вспомогательную структуру для хранения уникальных свойств
УникальныеСвойства = Новый Соответствие;
ИндексыДляУдаления = Новый Массив;
// Обходим ТЧ с конца, чтобы корректно удалять дубли
КоличествоСтрок = Объект.ДополнительныеРеквизиты.Количество();
Для Сч = 1 По КоличествоСтрок Цикл
ТекущаяСтрока = Объект.ДополнительныеРеквизиты[КоличествоСтрок - Сч];
Если УникальныеСвойства.Получить(ТекущаяСтрока.Свойство) = Неопределено Тогда
// Это первое вхождение свойства (с конца), запоминаем его
УникальныеСвойства.Вставить(ТекущаяСтрока.Свойство, Истина);
Иначе
// Такое свойство уже встречалось выше, значит это дубль, помечаем на удаление
ИндексыДляУдаления.Добавить(ТекущаяСтрока);
КонецЕсли;
КонецЦикла;
// Удаляем дубликаты
Для Каждого СтрокаДляУдаления Из ИндексыДляУдаления Цикл
Объект.ДополнительныеРеквизиты.Удалить(СтрокаДляУдаления);
КонецЦикла;
КонецЕсли;
Разберем, что именно делает этот код. Мы анализируем заполненную табличную часть Объект.ДополнительныеРеквизиты. С помощью объекта Соответствие мы отслеживаем уже встреченные свойства. Если мы видим, что такое Свойство уже есть в списке, мы удаляем текущую строку. Таким образом, после выполнения кода в коллекции останутся только уникальные строки.
Существует еще один продвинутый способ — подготовить данные еще на этапе выгрузки или непосредственно в момент инициализации табличной части.
Проанализируем ситуацию: если мы хотим, чтобы система вела себя стандартно, но при этом учитывала существующие в базе-приемнике строки, мы можем в обработчике ПередЗагрузкой (на уровне ТЧ) загрузить уже имеющиеся данные из базы-приемника в память, объединить их с входящими данными и передать результат в ОбъектКоллекция.
Однако наиболее эффективным и понятным для поддержки остается метод с ПослеЗагрузки, так как он работает с уже готовым объектом 1С, что минимизирует ошибки при работе с типами данных КД 2.0.
Поскольку 1С:ЗУП базируется на Библиотеке стандартных подсистем (БСП), работа с дополнительными реквизитами имеет свои особенности. Важно помнить:
ДополнительныеРеквизиты имеет смысл вызвать экспортные процедуры БСП, такие как УправлениеСвойствами.ЗаписатьСвойстваУОбъекта().НеОчищать = Истина всегда проверяйте, не приведет ли это к раздуванию базы из-за мусорных данных, которые могли быть удалены в базе-источнике, но останутся в базе-приемнике навсегда.Мы выяснили, что для решения задачи слияния табличных частей необходимо выполнить три условия. Во-первых, обеспечить синхронизацию элементов ПВХ по наименованию. Во-вторых, использовать флаг НеОчищать в настройках ПКГС. В-третьих, реализовать программную очистку дублей в обработчике ПослеЗагрузки. Для тестирования и регистрации изменений рекомендуем использовать инструмент универсальный обмен данными в формате XML.
Такой комплексный подход гарантирует, что данные из трех разных баз ЗУП будут корректно объединены в одной, а дополнительные реквизиты сотрудников не превратятся в кашу из повторяющихся строк. Рассмотренные примеры кода можно адаптировать для любых других табличных частей, где требуется логика "обновления существующих строк и добавления новых" вместо полной перезаписи.