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