Доработка функции ОбщегоНазначения.ЗаменитьСсылки для автоматической чистки или свёртки табличных частей

Стандартная обработка по замене дублей ругается на документ с неуникальными строками.
Предполагается, что их нужно либо а) удалить, либо б) свернуть.
Я немного модифицировал код функции ОбщегоНазначения.ЗаменитьСсылки, встроив в него вызов процедуры, переопределяемой в модуле менеджера соответствующего документа. И в этом модуле менеджера мы уже сами определяем — удалить или свернуть. Ну и вообще там чего хошь можно с этой коллекцией сделать — сам же ж процедуру пишешь…

В функции ОбщегоНазначения.ЗаменитьСсылки можно вставить вызов переопределяемых обработчиков событий по технологии как в БСП, переопределив их в модулях менеджеров этих требующих уникальности строк документов.

Суть метода быстрее всего понять из этого куска кода:

Функция ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования, ОбрабатываемыеСтроки)

Вместо вызова ЗаменитьВКоллекцииСтрок(…) в типовой вставляем наш кусок кода:

 // Табличные части
Для Каждого Элемент Из Описание.ТабличныеЧасти Цикл
СтандартнаяОбработка = Истина;
Если МодульМенеджера <> Неопределено Тогда
МодульМенеджера.ПриЗаменеВКоллекцииСтрок(
"ТабличныеЧасти",
Элемент.Имя,
Объект,
Объект[Элемент.Имя],
Элемент.СписокПолей,
ПарыЗамен,
СтандартнаяОбработка);
КонецЕсли;

// несмотря на наличие вызова модуля - применяем стандартную обработку
Если СтандартнаяОбработка Тогда
ЗаменитьВКоллекцииСтрок(
"ТабличныеЧасти",
Элемент.Имя,
Объект,
Объект[Элемент.Имя],
Элемент.СписокПолей,
ПарыЗамен);
КонецЕсли;
КонецЦикла;

 

Конечно надо инициализировать МодульМенеджера. Я это делаю в том же модуле ОбщегоНазначения

Функция ИзмененныеОбъектыПриЗаменеВОбъекте(ПараметрыВыполнения, МестоИспользования, ОбрабатываемыеСтроки)
 МодульМенеджера = ПараметрыВыполнения.МодулиМенеджеровПриЗаменеВКоллекцииСтрок[ТипЗнч(Данные)];

Конечно надо инициализировать это соответствие, и пр…  (эту всю кухню смотрите в исходниках, про неё в статье читать скучно, не говоря о том чтобы писать)

[Не намного, но всё же] веселее писать про модуль менеджера документа. Вот пример для УстановкаЦенНоменклатуры:

Процедура ПриЗаменеВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СтруктураПолей, Знач ПарыЗамен, СтандартнаяОбработка) Экспорт

Если ВидКоллекции = "ТабличныеЧасти" Тогда
Если ИмяКоллекции = "Товары" Тогда
СтандартнаяОбработка = Ложь;
ПоискИУдалениеДублей.УдалитьДублиВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, СтруктураПолей, ПарыЗамен);
КонецЕсли;

ИначеЕсли ВидКоллекции = "Движения" Тогда

Если ИмяКоллекции = "РегистрСведений.ЦеныНоменклатуры" Тогда
СтандартнаяОбработка = Ложь;
ПоискИУдалениеДублей.УдалитьДублиВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, СтруктураПолей, ПарыЗамен);
КонецЕсли;

КонецЕсли;


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

Вот пример процедуры общего модуля ПоискИУдалениеДублей — это чтобы не писать в каждом модуле менеджера документа одно и то же — вынес случаи а) и б) в общий модуль:

Процедура УдалитьДублиВКоллекцииСтрок(ВидКоллекции, ИмяКоллекции, Объект, Коллекция, Знач СтруктураПолей, Знач ПарыЗамен) Экспорт

// не представляю какие там бывают коллекции, но
Если Не СтруктураПолей.Свойство("Номенклатура") Тогда
Возврат;
КонецЕсли;

РабочаяКоллекция = Коллекция.Выгрузить();
ПараметрыОтбора = Новый Структура("Номенклатура");

СоответствиеЦелевыхСсылок = ОбщегоНазначения.СоответствиеЗначенийСоответствия(ПарыЗамен);
мСоответствиеЦелевыхСсылок = Новый Соответствие;

Для каждого ЭлементЦелевыхСсылок Из СоответствиеЦелевыхСсылок Цикл

ПараметрыОтбора.Номенклатура = ЭлементЦелевыхСсылок.Ключ;
Если РабочаяКоллекция.НайтиСтроки(ПараметрыОтбора).Количество() > 0 Тогда
мСоответствиеЦелевыхСсылок.Вставить(ЭлементЦелевыхСсылок.Ключ, Истина); // надо переносить данные, потому что из ОбщегоНазначения вернулось ReadOnly соответствие
КонецЕсли;

КонецЦикла;

Модифицировано = Ложь;
Для каждого Пара Из ПарыЗамен Цикл

ЦелеваяСсылка = Пара.Значение;
ПараметрыОтбора.Номенклатура = Пара.Ключ;
НайденныеСтроки = РабочаяКоллекция.НайтиСтроки(ПараметрыОтбора);
Н = НайденныеСтроки.Количество() - 1;
Пока Н >= 0 Цикл
ТекущаяСтрока = НайденныеСтроки[Н];
Если Не мСоответствиеЦелевыхСсылок[ЦелеваяСсылка] = Истина Тогда
// присваиваем вручную в первой встречной строке товара целевую ссылку
//ЗарегистрироватьФактЗамены(Данные, СтрокаТовара.Номенклатура, ЦелеваяСсылка, "ТабличныеЧасти", "Товары", ТаблицаТоваров.Индекс(СтрокаТовара), "Номенклатура");
ТекущаяСтрока.Номенклатура = ЦелеваяСсылка;
мСоответствиеЦелевыхСсылок.Вставить(ЦелеваяСсылка, Истина);
Иначе
РабочаяКоллекция.Удалить(ТекущаяСтрока);
КонецЕсли;

Модифицировано = Истина;

Н = Н - 1;
КонецЦикла;

КонецЦикла;

Если Модифицировано Тогда
Коллекция.Загрузить(РабочаяКоллекция);
КонецЕсли;

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

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

Ещё есть элегантный кусок модуля ПоискИУдалениеДублейПереопределяемый, вот он:

#Область ПрограммныйИнтерфейс

// Определить объекты, в модулях менеджеров которых предусмотрена возможность параметризации
// алгоритма поиска дублей с помощью экспортных процедур ПараметрыПоискаДублей, ПриПоискеДублей
// и ВозможностьЗаменыЭлементов.
//
// Параметры:
//   Объекты - Соответствие - объекты, в модулях менеджеров которых размещены экспортные процедуры.
//       ** Ключ     - Строка - полное имя объекта метаданных, подключенного к подсистеме "Поиск и удаление дублей".
//                              Например, "Справочник.Контрагенты".
//       ** Значение - Строка - имена экспортных процедур, определенных в модуле менеджера.
//                              Могут быть указаны:
//                              "ПараметрыПоискаДублей",
//                              "ПриПоискеДублей",
//                              "ВозможностьЗаменыЭлементов".
//                              Каждое имя должно начинаться с новой строки.
//                              Если указана пустая строка, то в модуле менеджера определены все процедуры.
//++ Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах
//    "ПриЗаменеВКоллекцииСтрок"
//-- Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах
//
// Пример:
//  1. В справочнике определены все процедуры:
//  Объекты.Вставить(Метаданные.Справочники.Контрагенты.ПолноеИмя(), "");
//
//  2. Определены только процедуры ПараметрыПоискаДублей и ПриПоискеДублей:
//  Объекты.Вставить(Метаданные.Справочники.ЗадачиПроекта.ПолноеИмя(), "ПараметрыПоискаДублей
//                   |ПриПоискеДублей");
//
Процедура ПриОпределенииОбъектовСПоискомДублей(Объекты) Экспорт

//++ Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах
Объекты.Вставить(Метаданные.Документы.УстановкаЦенНоменклатуры.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.РегистрацияЦенНоменклатурыПоставщика.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.РегистрацияОстатковНоменклатурыПоставщика.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.ЗаказПоставщику.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
Объекты.Вставить(Метаданные.Документы.ПоступлениеТоваровУслуг.ПолноеИмя(), "ПриЗаменеВКоллекцииСтрок");
//-- Альберт -- Поиск и замена дублей. Переопределение замены ссылок в документах

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

#КонецОбласти

Во вложении один файл с исходниками, разбитый по областям — именам тех модулей, куда надо вставлять код.

P.S. Друзья, я это никогда нигде не внедрял, (на своей фирме оно как-то само создалось) поэтому могут быть ляпы типа "забыл ещё модуль такой-то". Не судите строго, спрашивайте, догружу недостающие 🙂

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *