В функции ОбщегоНазначения.ЗаменитьСсылки можно вставить вызов переопределяемых обработчиков событий по технологии как в БСП, переопределив их в модулях менеджеров этих требующих уникальности строк документов.
Суть метода быстрее всего понять из этого куска кода:
Функция ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования, ОбрабатываемыеСтроки)
Вместо вызова ЗаменитьВКоллекцииСтрок(...) в типовой вставляем наш кусок кода:
// Табличные части
Для Каждого Элемент Из Описание.ТабличныеЧасти Цикл
СтандартнаяОбработка = Истина;
Если МодульМенеджера <> Неопределено Тогда
МодульМенеджера.ПриЗаменеВКоллекцииСтрок(
"ТабличныеЧасти",
Элемент.Имя,
Объект,
Объект[Элемент.Имя],
Элемент.СписокПолей,
ПарыЗамен,
СтандартнаяОбработка);
КонецЕсли;
// несмотря на наличие вызова модуля - применяем стандартную обработку
Если СтандартнаяОбработка Тогда
ЗаменитьВКоллекцииСтрок(
"ТабличныеЧасти",
Элемент.Имя,
Объект,
Объект[Элемент.Имя],
Элемент.СписокПолей,
ПарыЗамен);
КонецЕсли;
КонецЦикла;
Конечно надо инициализировать МодульМенеджера. Я это делаю в том же модуле ОбщегоНазначения
Функция ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования, ОбрабатываемыеСтроки)
МодульМенеджера = ПараметрыВыполнения.МодулиМенеджеровПриЗаменеВКоллекцииСтрок[ТипЗнч(Данные)];
Конечно надо инициализировать это соответствие, и пр... (эту всю кухню смотрите в исходниках, про неё в статье читать скучно, не говоря о том чтобы писать)
[Не намного, но всё же] веселее писать про модуль менеджера документа. Вот пример для УстановкаЦенНоменклатуры:
Процедура ПриЗаменеВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СтруктураПолей, Знач ПарыЗамен, СтандартнаяОбработка) Экспорт
Если ВидКоллекции = "ТабличныеЧасти" Тогда
Если ИмяКоллекции = "Товары" Тогда
СтандартнаяОбработка = Ложь;
ПоискИУдалениеДублей.УдалитьДублиВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, СтруктураПолей, ПарыЗамен);
КонецЕсли;
ИначеЕсли ВидКоллекции = "Движения" Тогда
Если ИмяКоллекции = "РегистрСведений.ЦеныНоменклатуры" Тогда
СтандартнаяОбработка = Ложь;
ПоискИУдалениеДублей.УдалитьДублиВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, СтруктураПолей, ПарыЗамен);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Вот пример процедуры общего модуля ПоискИУдалениеДублей - это чтобы не писать в каждом модуле менеджера документа одно и то же - вынес случаи а) и б) в общий модуль:
Процедура УдалитьДублиВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СтруктураПолей, Знач ПарыЗамен) Экспорт
// не представляю какие там бывают коллекции, но
Если Не СтруктураПолей.Свойство("Номенклатура") Тогда
Возврат;
КонецЕсли;
РабочаяКоллекция = Коллекция.Выгрузить();
ПараметрыОтбора = Новый Структура("Номенклатура");
СоответствиеЦелевыхСсылок = ОбщегоНазначения.СоответствиеЗначенийСоответствия(ПарыЗамен);
мСоответствиеЦелевыхСсылок = Новый Соответствие;
Для каждого ЭлементЦелевыхСсылок Из СоответствиеЦелевыхСсылок Цикл
ПараметрыОтбора.Номенклатура = ЭлементЦелевыхСсылок.Ключ;
Если РабочаяКоллекция.НайтиСтроки(ПараметрыОтбора).Количество() > 0 Тогда
мСоответствиеЦелевыхСсылок.Вставить(ЭлементЦелевыхСсылок.Ключ, Истина); // надо переносить данные, потому что из ОбщегоНазначения вернулось ReadOnly соответствие
КонецЕсли;
КонецЦикла;
Модифицировано = Ложь;
Для каждого Пара Из ПарыЗамен Цикл
ЦелеваяСсылка = Пара.Значение;
ПараметрыОтбора.Номенклатура = Пара.Ключ;
НайденныеСтроки = РабочаяКоллекция.НайтиСтроки(ПараметрыОтбора);
Н = НайденныеСтроки.Количество() - 1;
Пока Н >= 0 Цикл
ТекущаяСтрока = НайденныеСтроки[Н];
Если Не мСоответствиеЦелевыхСсылок[ЦелеваяСсылка] = Истина Тогда
// присваиваем вручную в первой встречной строке товара целевую ссылку
//ЗарегистрироватьФактЗамены(Данные, СтрокаТовара.Номенклатура, ЦелеваяСсылка, "ТабличныеЧасти", "Товары", ТаблицаТоваров.Индекс(СтрокаТовара), "Номенклатура");
ТекущаяСтрока.Номенклатура = ЦелеваяСсылка;
мСоответствиеЦелевыхСсылок.Вставить(ЦелеваяСсылка, Истина);
Иначе
РабочаяКоллекция.Удалить(ТекущаяСтрока);
КонецЕсли;
Модифицировано = Истина;
Н = Н - 1;
КонецЦикла;
КонецЦикла;
Если Модифицировано Тогда
Коллекция.Загрузить(РабочаяКоллекция);
КонецЕсли;
КонецПроцедуры
Какие там бывают коллекции - я до сих пор не представляю. Названия нужных ВидКоллекции ловил в отладчике.
Ещё есть элегантный кусок модуля ПоискИУдалениеДублейПереопределяемый, вот он:
#Область ПрограммныйИнтерфейс
// Определить объекты, в модулях менеджеров которых предусмотрена возможность параметризации
// алгоритма поиска дублей с помощью экспортных процедур ПараметрыПоискаДублей, ПриПоискеДублей
// и ВозможностьЗаменыЭлементов.
//
// Параметры:
// Объекты - Соответствие - объекты, в модулях менеджеров которых размещены экспортные процедуры.
// ** Ключ - Строка - полное имя объекта метаданных, подключенного к подсистеме "Поиск и удаление дублей".
// Например, "Справочник.Контрагенты".
// ** Значение - Строка - имена экспортных процедур, определенных в модуле менеджера.
// Могут быть указаны:
// "ПараметрыПоискаДублей",
// "ПриПоискеДублей",
// "ВозможностьЗаменыЭлементов".
// Каждое имя должно начинаться с новой строки.
// Если указана пустая строка, то в модуле менеджера определены все процедуры.
//++ Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах
// "ПриЗаменеВКоллекцииСтрок"
//-- Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах
//
// Пример:
// 1. В справочнике определены все процедуры:
// Объекты.Вставить(Метаданные.Справочники.Контрагенты.ПолноеИмя(), "");
//
// 2. Определены только процедуры ПараметрыПоискаДублей и ПриПоискеДублей:
// Объекты.Вставить(Метаданные.Справочники.ЗадачиПроекта.ПолноеИмя(), "ПараметрыПоискаДублей
// |ПриПоискеДублей");
//
Процедура ПриОпределенииОбъектовСПоискомДублей(Объекты) Экспорт
//++ Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах
Объекты.Вставить(Метаданные.Документы.УстановкаЦенНоменклатуры.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.РегистрацияЦенНоменклатурыПоставщика.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.РегистрацияОстатковНоменклатурыПоставщика.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.ЗаказПоставщику.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.ПоступлениеТоваровУслуг.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
//-- Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах
КонецПроцедуры
#КонецОбласти
Во вложении один файл с исходниками, разбитый по областям - именам тех модулей, куда надо вставлять код.
P.S. Друзья, я это никогда нигде не внедрял, (на своей фирме оно как-то само создалось) поэтому могут быть ляпы типа "забыл ещё модуль такой-то". Не судите строго, спрашивайте, догружу недостающие :)