#Область ОписаниеПеременных
&НаКлиенте
Перем ОтчетыДляОтправки;
#КонецОбласти
#Область ОбработчикиСобытийФормы
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
УстановитьУсловноеОформление();
КомпонентаНечеткогоПоиска = ОбщегоНазначения.ПодключитьКомпонентуИзМакета("FuzzyStringMatchExtension", "ОбщийМакет.КомпонентаПоискаСтрок");
Если КомпонентаНечеткогоПоиска <> Неопределено Тогда
НечеткийПоиск = Истина;
КонецЕсли;
НастройкиФормыПоУмолчанию = НастройкиПоискаУдаленияДублей();
НастройкиФормы = ОбщегоНазначения.ХранилищеОбщихНастроекЗагрузить(ИмяФормы, "", НастройкиФормыПоУмолчанию);
ЗаполнитьЗначенияСвойств(НастройкиФормыПоУмолчанию, НастройкиФормы);
НастройкиФормы = НастройкиФормыПоУмолчанию;
ЗаполнитьЗначенияСвойств(НастройкиФормы, Параметры);
ПриСозданииНаСервереИнициализацияДанных(НастройкиФормы);
ИнициализироватьКомпоновщикОтбораИПравила(НастройкиФормы);
ОтображениеСостояния = Элементы.ПоискНеВыполнялся.ОтображениеСостояния;
ОтображениеСостояния.Видимость = Истина;
ОтображениеСостояния.Текст = НСтр("ru = 'Поиск дублей не выполнялся.
|Задайте условия отбора и сравнения и нажмите ""Найти дубли"".'");
ОтображениеСостояния = Элементы.ВыполнениеПоиска.ОтображениеСостояния;
ОтображениеСостояния.Видимость = Истина;
ОтображениеСостояния.Картинка = Элементы.ДлительнаяОперация48.Картинка;
ОтображениеСостояния = Элементы.ВыполнениеУдаления.ОтображениеСостояния;
ОтображениеСостояния.Видимость = Истина;
ОтображениеСостояния.Картинка = Элементы.ДлительнаяОперация48.Картинка;
ОтображениеСостояния = Элементы.ДублейНеНайдено.ОтображениеСостояния;
ОтображениеСостояния.Видимость = Истина;
ОтображениеСостояния.Текст = НСтр("ru = 'Не обнаружено дублей по указанным параметрам.
|Измените условия отбора и сравнения, нажмите ""Найти дубли""'");
СохраняемыеВНастройкахДанныеМодифицированы = Истина;
ИнициализироватьНастройкиПошаговогоМастера();
ШагПоиск = ДобавитьШагМастера(Элементы.ШагПоискНеВыполнялся);
ШагПоиск.КнопкаНазад.Видимость = Ложь;
ШагПоиск.КнопкаДалее.Заголовок = НСтр("ru = 'Найти дубли >'");
ШагПоиск.КнопкаДалее.Подсказка = НСтр("ru = 'Найти дубли по указанным критериям'");
ШагПоиск.КнопкаОтмена.Заголовок = НСтр("ru = 'Закрыть'");
ШагПоиск.КнопкаОтмена.Подсказка = НСтр("ru = 'Отказаться от поиска и замены дублей'");
Шаг = ДобавитьШагМастера(Элементы.ШагВыполнениеПоиска);
Шаг.КнопкаНазад.Видимость = Ложь;
Шаг.КнопкаДалее.Видимость = Ложь;
Шаг.КнопкаОтмена.Заголовок = НСтр("ru = 'Прервать'");
Шаг.КнопкаОтмена.Подсказка = НСтр("ru = 'Прервать поиск дублей'");
Шаг = ДобавитьШагМастера(Элементы.ШагВыборОсновногоЭлемента);
Шаг.КнопкаНазад.Видимость = Ложь;
Шаг.КнопкаДалее.Заголовок = НСтр("ru = 'Удалить дубли >'");
Шаг.КнопкаДалее.Подсказка = НСтр("ru = 'Удалить дубли'");
Шаг.ПриНажатииКнопкиДалее = "ШагВыборОсновногоЭлементаПриНажатииКнопкиДалее";
Шаг.КнопкаОтмена.Заголовок = НСтр("ru = 'Закрыть'");
Шаг.КнопкаОтмена.Подсказка = НСтр("ru = 'Отказаться от поиска и замены дублей'");
Шаг = ДобавитьШагМастера(Элементы.ШагВыполнениеУдаления);
Шаг.КнопкаНазад.Видимость = Ложь;
Шаг.КнопкаДалее.Видимость = Ложь;
Шаг.КнопкаОтмена.Заголовок = НСтр("ru = 'Прервать'");
Шаг.КнопкаОтмена.Подсказка = НСтр("ru = 'Прервать удаление дублей'");
Шаг = ДобавитьШагМастера(Элементы.ШагУспешноеУдаление);
Шаг.КнопкаНазад.Заголовок = НСтр("ru = 'Повторить поиск'");
Шаг.КнопкаНазад.Подсказка = НСтр("ru = 'Начать новый поиск с другими параметрами'");
Шаг.КнопкаДалее.Видимость = Ложь;
Шаг.КнопкаОтмена.КнопкаПоУмолчанию = Истина;
Шаг.КнопкаОтмена.Заголовок = НСтр("ru = 'Закрыть'");
Шаг = ДобавитьШагМастера(Элементы.ШагНеудачныеЗамены);
Шаг.КнопкаНазад.Видимость = Ложь;
Шаг.КнопкаДалее.Заголовок = НСтр("ru = 'Повторить удаление >'");
Шаг.КнопкаДалее.Подсказка = НСтр("ru = 'Удалить дубли'");
Шаг.КнопкаОтмена.Заголовок = НСтр("ru = 'Закрыть'");
Шаг = ДобавитьШагМастера(Элементы.ШагДублейНеНайдено);
Шаг.КнопкаНазад.Видимость = Ложь;
Шаг.КнопкаДалее.Заголовок = НСтр("ru = 'Найти дубли >'");
Шаг.КнопкаДалее.Подсказка = НСтр("ru = 'Найти дубли по указанным критериям'");
Шаг.КнопкаОтмена.Заголовок = НСтр("ru = 'Закрыть'");
Шаг = ДобавитьШагМастера(Элементы.ШагВозниклаОшибка);
Шаг.КнопкаНазад.Видимость = Ложь;
Шаг.КнопкаДалее.Видимость = Ложь;
Шаг.КнопкаОтмена.Заголовок = НСтр("ru = 'Закрыть'");
НастройкиМастера.ТекущийШаг = ШагПоиск;
УстановитьВидимостьДоступность(ЭтотОбъект);
Элементы.ГруппаПодробно.Видимость = Ложь;
ОтображаемаяСтепеньРодства = 2;
УстановитьОтборВозможныхДублей(ЭтотОбъект);
Если ОбщегоНазначения.ЭтоМобильныйКлиент() Тогда
Элементы.Шапка.ВыравниваниеЭлементовИЗаголовков = ВариантВыравниванияЭлементовИЗаголовков.ЭлементыПравоЗаголовкиЛево;
Элементы.КоманднаяПанель.Видимость = Ложь;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПриОткрытии(Отказ)
ПриАктивацииШагаМастера();
ОтчетыДляОтправки = Новый Соответствие;
КонецПроцедуры
&НаКлиенте
Процедура ПередЗакрытием(Отказ, ЗавершениеРаботы, ТекстПредупреждения, СтандартнаяОбработка)
Если Не НастройкиМастера.ПоказатьДиалогПередЗакрытием Тогда
Возврат;
КонецЕсли;
Если ЗавершениеРаботы Тогда
Возврат;
КонецЕсли;
Отказ = Истина;
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Если ТекущаяСтраница = Элементы.ШагВыполнениеПоиска Тогда
ТекстВопроса = НСтр("ru = 'Прервать поиск дублей и закрыть форму?'");
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыполнениеУдаления Тогда
ТекстВопроса = НСтр("ru = 'Прервать удаление дублей и закрыть форму?'");
КонецЕсли;
Кнопки = Новый СписокЗначений;
Кнопки.Добавить(КодВозвратаДиалога.Прервать, НСтр("ru = 'Прервать'"));
Кнопки.Добавить(КодВозвратаДиалога.Нет, НСтр("ru = 'Не прерывать'"));
Обработчик = Новый ОписаниеОповещения("ПослеПодтвержденияОтменыЗадания", ЭтотОбъект);
ПоказатьВопрос(Обработчик, ТекстВопроса, Кнопки, , КодВозвратаДиалога.Нет);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовШапкиФормы
&НаКлиенте
Процедура ОбластьПоискаДублейОткрытие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ОткрытьФорму(ОбластьПоискаДублей + ".ФормаСписка");
КонецПроцедуры
&НаКлиенте
Процедура ОбластьПоискаДублейНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Имя = ПолноеИмяФормы("ОбластьПоискаДублей");
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("АдресНастроек", АдресНастроек);
ПараметрыФормы.Вставить("ОбластьПоискаДублей", ОбластьПоискаДублей);
Обработчик = Новый ОписаниеОповещения("ОбластьПоискаДублейЗавершениеВыбора", ЭтотОбъект);
ОткрытьФорму(Имя, ПараметрыФормы, ЭтотОбъект, , , , Обработчик);
КонецПроцедуры
&НаКлиенте
Процедура ОбластьПоискаДублейЗавершениеВыбора(Результат, ПараметрыВыполнения) Экспорт
Если ТипЗнч(Результат) <> Тип("Строка") Тогда
Возврат;
КонецЕсли;
ОбластьПоискаДублей = Результат;
ИнициализироватьКомпоновщикОтбораИПравила(Неопределено);
ПерейтиНаШагМастера(Элементы.ШагПоискНеВыполнялся);
КонецПроцедуры
&НаКлиенте
Процедура ОбластьПоискаДублейПриИзменении(Элемент)
ИнициализироватьКомпоновщикОтбораИПравила(Неопределено);
ПерейтиНаШагМастера(Элементы.ШагПоискНеВыполнялся);
КонецПроцедуры
&НаКлиенте
Процедура ОбластьПоискаДублейОчистка(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
КонецПроцедуры
&НаКлиенте
Процедура ВсеМестаИспользованияНеобработанныхНажатие(Элемент)
ПоказатьМестаИспользования(НеобработанныеДубли);
КонецПроцедуры
&НаКлиенте
Процедура ВсеМестаИспользованияНажатие(Элемент)
ПоказатьМестаИспользования(НайденныеДубли);
КонецПроцедуры
&НаКлиенте
Процедура ПредставлениеПравилОтбораНачалоВыбора(Элемент, ДанныеВыбора, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ПодключитьОбработчикОжидания("ПриНачалеВыбораПравилОтбора", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ПриНачалеВыбораПравилОтбора()
Имя = ПолноеИмяФормы("ПравилаОтбора");
ЭлементСписка = Элементы.ОбластьПоискаДублей.СписокВыбора.НайтиПоЗначению(ОбластьПоискаДублей);
Если ЭлементСписка = Неопределено Тогда
ПредставлениеОбластиПоискаДублей = Неопределено;
Иначе
ПредставлениеОбластиПоискаДублей = ЭлементСписка.Представление;
КонецЕсли;
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("АдресСхемыКомпоновки", АдресСхемыКомпоновки);
ПараметрыФормы.Вставить("АдресНастроекКомпоновщикаОтбора", АдресНастроекКомпоновщикаОтбора());
ПараметрыФормы.Вставить("ИдентификаторОсновнойФормы", УникальныйИдентификатор);
ПараметрыФормы.Вставить("ПредставлениеОбластиОтбора", ПредставлениеОбластиПоискаДублей);
Обработчик = Новый ОписаниеОповещения("ПравилаОтбораЗавершениеВыбора", ЭтотОбъект);
ОткрытьФорму(Имя, ПараметрыФормы, ЭтотОбъект, , , , Обработчик);
КонецПроцедуры
&НаКлиенте
Процедура ПравилаОтбораЗавершениеВыбора(АдресРезультата, ПараметрыВыполнения) Экспорт
Если ТипЗнч(АдресРезультата) <> Тип("Строка") Или Не ЭтоАдресВременногоХранилища(АдресРезультата) Тогда
Возврат;
КонецЕсли;
ОбновитьКомпоновщикОтбора(АдресРезультата);
ПерейтиНаШагМастера(Элементы.ШагПоискНеВыполнялся);
КонецПроцедуры
&НаКлиенте
Процедура ПредставлениеПравилОтбораОчистка(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
КомпоновщикПредварительногоОтбора.Настройки.Отбор.Элементы.Очистить();
ПерейтиНаШагМастера(Элементы.ШагПоискНеВыполнялся);
СохранитьПользовательскиеНастройки();
КонецПроцедуры
&НаКлиенте
Процедура ПредставлениеПравилПоискаНажатие(Элемент, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Имя = ПолноеИмяФормы("ПравилаПоиска");
ЭлементСписка = Элементы.ОбластьПоискаДублей.СписокВыбора.НайтиПоЗначению(ОбластьПоискаДублей);
Если ЭлементСписка = Неопределено Тогда
ПредставлениеОбластиПоискаДублей = Неопределено;
Иначе
ПредставлениеОбластиПоискаДублей = ЭлементСписка.Представление;
КонецЕсли;
ПараметрыФормы = Новый Структура;
ПараметрыФормы.Вставить("ОбластьПоискаДублей", ОбластьПоискаДублей);
ПараметрыФормы.Вставить("ОписаниеПрикладныхПравил", ОписаниеПрикладныхПравил);
ПараметрыФормы.Вставить("АдресНастроек", АдресНастроекПравилПоиска());
ПараметрыФормы.Вставить("ПредставлениеОбластиОтбора", ПредставлениеОбластиПоискаДублей);
Обработчик = Новый ОписаниеОповещения("ПравилаПоискаЗавершениеВыбора", ЭтотОбъект);
ОткрытьФорму(Имя, ПараметрыФормы, ЭтотОбъект, , , , Обработчик);
КонецПроцедуры
&НаКлиенте
Процедура ПравилаПоискаЗавершениеВыбора(АдресРезультата, ПараметрыВыполнения) Экспорт
Если ТипЗнч(АдресРезультата) <> Тип("Строка") Или Не ЭтоАдресВременногоХранилища(АдресРезультата) Тогда
Возврат;
КонецЕсли;
ОбновитьПравилаПоиска(АдресРезультата);
ПерейтиНаШагМастера(Элементы.ШагПоискНеВыполнялся);
КонецПроцедуры
&НаКлиенте
Процедура ОписаниеСостоянияНайденныхДублейОбработкаНавигационнойСсылки(Элемент, Ссылка, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
Если Ссылка = "СпособУдаления" Тогда
СпособУдаления = ?(СпособУдаления = "Непосредственно", "Пометка", "Непосредственно");
ОбновитьОписаниеСостоянияНайденныхДублей();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура СсылкаПодробнееНажатие(Элемент)
СтандартныеПодсистемыКлиент.ПоказатьПодробнуюИнформацию(Неопределено, Элемент.Подсказка);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыНайденныеДубли
&НаКлиенте
Процедура НайденныеДублиПриАктивизацииСтроки(Элемент)
ПодключитьОбработчикОжидания("ОтложенныйОбработчикАктивизацииСтрокиДублей", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОтложенныйОбработчикАктивизацииСтрокиДублей()
ИдентификаторСтроки = Элементы.НайденныеДубли.ТекущаяСтрока;
Если ИдентификаторСтроки = Неопределено Или ИдентификаторСтроки = ИдентификаторТекущейСтроки Тогда
Возврат;
КонецЕсли;
ИдентификаторТекущейСтроки = ИдентификаторСтроки;
ОбновитьМестаИспользованияКандидата(ИдентификаторСтроки);
КонецПроцедуры
&НаСервере
Процедура ОбновитьМестаИспользованияКандидата(Знач ИдентификаторСтроки)
ТекущаяСтрока = НайденныеДубли.НайтиПоИдентификатору(ИдентификаторСтроки);
Если ТекущаяСтрока.ПолучитьРодителя() = Неопределено Тогда
МестаИспользованияКандидата.Очистить();
НаименованиеОригинала = Неопределено;
ПомеченыНаУдалениеИНеИспользуются = Истина;
Для Каждого Кандидат Из ТекущаяСтрока.ПолучитьЭлементы() Цикл
Если Кандидат.Основной Тогда
НаименованиеОригинала = Кандидат.Наименование;
ИначеЕсли Кандидат.НомерКартинки <> 4 Или Кандидат.Количество > 0 Тогда
ПомеченыНаУдалениеИНеИспользуются = Ложь;
КонецЕсли;
КонецЦикла;
Описание = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Для элемента ""%1"" найдено дублей: %2'"),
НаименованиеОригинала, ТекущаяСтрока.Количество);
Если ПомеченыНаУдалениеИНеИспользуются Тогда
Описание = Описание + Символы.ПС
+ НСтр("ru = 'Однако все они помечены на удаление и не используются, поэтому удаление дублей уже не требуется.'");
КонецЕсли;
Элементы.ГруппаПодробно.Заголовок = НСтр("ru = 'Сведения:'");
Элементы.ОписаниеТекущейГруппыДублей.Заголовок = Описание;
Элементы.СтраницыМестаИспользования.ТекущаяСтраница = Элементы.ОписаниеГруппы;
Возврат;
КонецЕсли;
ТаблицаИспользования = ПолучитьИзВременногоХранилища(АдресМестИспользования);
Фильтр = Новый Структура("Ссылка", ТекущаяСтрока.Ссылка);
МестаИспользованияКандидата.Загрузить(ТаблицаИспользования.Скопировать(ТаблицаИспользования.НайтиСтроки(Фильтр)));
Если ТекущаяСтрока.Количество = 0 Тогда
Элементы.ОписаниеТекущейГруппыДублей.Заголовок = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Элемент ""%1"" не используется'"),
ТекущаяСтрока.Наименование);
Элементы.ГруппаПодробно.Заголовок = НСтр("ru = 'Сведения:'");
Элементы.СтраницыМестаИспользования.ТекущаяСтраница = Элементы.ОписаниеГруппы;
Иначе
Элементы.ГруппаПодробно.Заголовок = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Места использования ""%1"" (%2):'"),
ТекущаяСтрока.Наименование,
ТекущаяСтрока.Количество);
Элементы.СтраницыМестаИспользования.ТекущаяСтраница = Элементы.МестаИспользования;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура НайденныеДублиВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
ОткрытьФормуДубля(Элемент.ТекущиеДанные);
КонецПроцедуры
&НаКлиенте
Процедура НайденныеДублиПометкаПриИзменении(Элемент)
ДанныеСтроки = Элементы.НайденныеДубли.ТекущиеДанные;
ДанныеСтроки.Пометка = ДанныеСтроки.Пометка % 2;
ИзменитьПометкиКандидатов(ДанныеСтроки);
ОписаниеОшибкиПоискаДублей = "";
ВсегоНайденоДублей = 0;
Для Каждого Дубль Из НайденныеДубли.ПолучитьЭлементы() Цикл
Для Каждого Потомок Из Дубль.ПолучитьЭлементы() Цикл
Если Не Потомок.Основной И Потомок.Пометка Тогда
ВсегоНайденоДублей = ВсегоНайденоДублей + 1;
КонецЕсли;
КонецЦикла;
КонецЦикла;
ОбновитьОписаниеСостоянияНайденныхДублей();
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыНеобработанныеДубли
&НаКлиенте
Процедура НеобработанныеДублиПриАктивизацииСтроки(Элемент)
ПодключитьОбработчикОжидания("ОтложенныйОбработчикАктивизацииСтрокиНеобработанныхДублей", 0.1, Истина);
КонецПроцедуры
&НаКлиенте
Процедура ОтложенныйОбработчикАктивизацииСтрокиНеобработанныхДублей()
ДанныеСтроки = Элементы.НеобработанныеДубли.ТекущиеДанные;
Если ДанныеСтроки = Неопределено Тогда
Возврат;
КонецЕсли;
ОбновитьМестаИспользованияНеобработанныхДубли( ДанныеСтроки.ПолучитьИдентификатор() );
КонецПроцедуры
&НаСервере
Процедура ОбновитьМестаИспользованияНеобработанныхДубли(Знач СтрокаДанных)
ДанныеСтроки = НеобработанныеДубли.НайтиПоИдентификатору(СтрокаДанных);
Если ДанныеСтроки.ПолучитьРодителя() = Неопределено Или ДанныеСтроки.Основной Тогда
МестаИспользованияНеобработанных.Очистить();
Элементы.ОписаниеТекущейГруппыДублей1.Заголовок = НСтр("ru = 'Для просмотра причин выберите проблемный элемент-дубль.'");
Элементы.СтраницыМестаИспользованияНеобработанных.ТекущаяСтраница = Элементы.ОписаниеГруппыНеобработанных;
Возврат;
КонецЕсли;
Если ДанныеСтроки.Количество = 0 Тогда
МестаИспользованияНеобработанных.Очистить();
Элементы.ОписаниеТекущейГруппыДублей1.Заголовок =
НСтр("ru = 'Выбранный дубль не заменен из-за невозможности замены других дублей.'");
Элементы.СтраницыМестаИспользованияНеобработанных.ТекущаяСтраница = Элементы.ОписаниеГруппыНеобработанных;
Иначе
ТаблицаОшибок = ПолучитьИзВременногоХранилища(АдресРезультатаЗамены);
Фильтр = Новый Структура("Ссылка", ДанныеСтроки.Ссылка);
Данные = ТаблицаОшибок.Скопировать( ТаблицаОшибок.НайтиСтроки(Фильтр) );
Данные.Колонки.Добавить("Пиктограмма");
Данные.ЗаполнитьЗначения(Истина, "Пиктограмма");
МестаИспользованияНеобработанных.Загрузить(Данные);
Элементы.МестаИспользованияКандидата.Заголовок = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не удалось заменить дубли в некоторых местах (%1)'"),
ДанныеСтроки.Количество);
Элементы.СтраницыМестаИспользованияНеобработанных.ТекущаяСтраница = Элементы.ОписаниеМестИспользованияНеобработанных;
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура НеобработанныеДублиВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
ОткрытьФормуДубля(Элементы.НеобработанныеДубли.ТекущиеДанные);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыМестаИспользованияНеобработанных
&НаКлиенте
Процедура МестаИспользованияНеобработанныхПриАктивизацииСтроки(Элемент)
ТекущиеДанные = Элемент.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
ОписаниеОшибкиНеобработанных = "";
Элементы.ДекорацияОтправитьОтчетОбОшибке.Видимость = Ложь;
Возврат;
КонецЕсли;
ОписаниеОшибкиНеобработанных = ?(ТекущиеДанные.ИнформацияОбОшибке <> Неопределено,
ОбработкаОшибок.СообщениеОбОшибкеДляПользователя(ТекущиеДанные.ИнформацияОбОшибке),
ТекущиеДанные.ТекстОшибки);
Если ТекущиеДанные.ИнформацияОбОшибке = Неопределено Тогда
Элементы.ДекорацияОтправитьОтчетОбОшибке.Видимость = Ложь;
Иначе
СтандартныеПодсистемыКлиент.НастроитьВидимостьИЗаголовокСсылкиОтправкиОтчетаОбОшибке(
Элементы.ДекорацияОтправитьОтчетОбОшибке, ТекущиеДанные.ИнформацияОбОшибке);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура МестаИспользованияНеобработанныхВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
ТекущиеДанные = МестаИспользованияНеобработанных.НайтиПоИдентификатору(ВыбраннаяСтрока);
ПоказатьЗначение(, ТекущиеДанные.ОбъектОшибки);
КонецПроцедуры
&НаКлиенте
Процедура ДекорацияОтправитьОтчетОбОшибкеНажатие(Элемент)
ТекущиеДанные = Элементы.МестаИспользованияНеобработанных.ТекущиеДанные;
Если ТекущиеДанные = Неопределено Тогда
Возврат;
КонецЕсли;
ОтчетДляОтправки = ОтчетыДляОтправки[ТекущиеДанные.ИнформацияОбОшибке];
Если ОтчетДляОтправки = Неопределено Тогда
ОтчетДляОтправки = Новый ОтчетОбОшибке(ТекущиеДанные.ИнформацияОбОшибке);
ОтчетыДляОтправки[ТекущиеДанные.ИнформацияОбОшибке] = ОтчетДляОтправки;
КонецЕсли;
СтандартныеПодсистемыКлиент.ПоказатьОтчетОбОшибке(ОтчетДляОтправки);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыМестаИспользованияКандидата
&НаКлиенте
Процедура МестаИспользованияКандидатаВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
ТекущиеДанные = МестаИспользованияКандидата.НайтиПоИдентификатору(ВыбраннаяСтрока);
ПоказатьЗначение(, ТекущиеДанные.Данные);
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиСобытийЭлементовТаблицыФормыВозможныеДубли
&НаКлиенте
Процедура ОтображаемаяСтепеньРодстваПриИзменении(Элемент)
УстановитьОтборВозможныхДублей(ЭтотОбъект);
КонецПроцедуры
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьОтборВозможныхДублей(Форма)
Если Форма.ОтображаемаяСтепеньРодства = 1 Тогда
Форма.Элементы.ВозможныеДубли.ОтборСтрок = Неопределено;
Иначе
Форма.Элементы.ВозможныеДубли.ОтборСтрок = Новый ФиксированнаяСтруктура("СтепеньРодства", 2);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ВозможныеДублиВыбранПриИзменении(Элемент)
ТекущиеДанные = Элементы.ВозможныеДубли.ТекущиеДанные;
ВыбранныеСтроки = ВозможныеДубли.НайтиСтроки(Новый Структура("Выбран", Истина));
Для каждого СтрокаДубля Из ВыбранныеСтроки Цикл
Если СтрокаДубля.ПолучитьИдентификатор() = ТекущиеДанные.ПолучитьИдентификатор() Тогда
Продолжить;
КонецЕсли;
СтрокаДубля.Выбран = Ложь;
КонецЦикла;
ВозможныйДубльВыбран = ТекущиеДанные.Выбран;
ВозможныйДубльВыбранныйТип = ТекущиеДанные.ТипОбъектаМетаданных;
ПриАктивацииШагаМастера();
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьСостояниеВозможныхДублей()
ЗаголовокГруппы = НСтр("ru='В процессе работы могли возникнуть дубли в других списках (%1)'");
КоличествоНеобработанных = ВозможныеДубли.НайтиСтроки(Новый Структура("Обработано", Ложь)).Количество();
Элементы.ГруппаВозможныеДубли.Заголовок = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ЗаголовокГруппы, КоличествоНеобработанных);
Элементы.ГруппаВозможныеДубли.Видимость = КоличествоНеобработанных > 0;
КонецПроцедуры
#КонецОбласти
#Область ОбработчикиКомандФормы
&НаКлиенте
Процедура ОбработчикКнопкиМастера(Команда)
Если Команда.Имя = НастройкиМастера.КнопкаДалее Тогда
ШагМастераДалее();
ИначеЕсли Команда.Имя = НастройкиМастера.КнопкаНазад Тогда
ШагМастераНазад();
ИначеЕсли Команда.Имя = НастройкиМастера.КнопкаОтмена Тогда
ШагМастераОтмена();
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОтметитьКакОригинал(Команда)
ДанныеСтроки = Элементы.НайденныеДубли.ТекущиеДанные;
Если ДанныеСтроки = Неопределено Или ДанныеСтроки.Основной Тогда
Возврат;
КонецЕсли;
Родитель = ДанныеСтроки.ПолучитьРодителя();
Если Родитель = Неопределено Тогда
Возврат;
КонецЕсли;
ОтметитьЭлементКакОригинал(ДанныеСтроки, Родитель);
КонецПроцедуры
&НаКлиенте
Процедура ОткрытьКандидатаВДубли(Команда)
ОткрытьФормуДубля(Элементы.НайденныеДубли.ТекущиеДанные);
КонецПроцедуры
&НаКлиенте
Процедура ОткрытьНеобработанныйДубль(Команда)
ОткрытьФормуДубля(Элементы.НеобработанныеДубли.ТекущиеДанные);
КонецПроцедуры
&НаКлиенте
Процедура РазвернутьГруппыДублей(Команда)
РазвернутьГруппуДублей();
КонецПроцедуры
&НаКлиенте
Процедура СвернутьГруппыДублей(Команда)
СвернутьГруппуДублей();
КонецПроцедуры
&НаКлиенте
Процедура ПовторитьПоиск(Команда)
ПерейтиНаШагМастера(Элементы.ШагВыполнениеПоиска);
КонецПроцедуры
&НаКлиенте
Процедура УстановитьВсеФлажки(Команда)
ЭлементыСписка = НайденныеДубли.ПолучитьЭлементы();
Для Каждого Элемент Из ЭлементыСписка Цикл
УстановитьПометкиВДереве(Элемент, Истина, Истина);
Родитель = Элемент.ПолучитьРодителя();
Если Родитель = Неопределено Тогда
ПроверитьПометкуРодителя(Элемент)
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура СнятьВсеФлажки(Команда)
ЭлементыСписка = НайденныеДубли.ПолучитьЭлементы();
Для Каждого Элемент Из ЭлементыСписка Цикл
УстановитьПометкиВДереве(Элемент, Ложь, Истина);
Родитель = Элемент.ПолучитьРодителя();
Если Родитель = Неопределено Тогда
ПроверитьПометкуРодителя(Элемент)
КонецЕсли;
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура Подробно(Команда)
Элементы.ГруппаПодробно.Видимость = Не Элементы.ГруппаПодробно.Видимость;
Элементы.Подробнее.Заголовок = ?(Элементы.ГруппаПодробно.Видимость, НСтр("ru = '<< Скрыть'"), НСтр("ru = 'Подробнее >>'"));
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
#Область ПереключениеСтраницМастера
&НаСервере
Процедура ИнициализироватьНастройкиПошаговогоМастера()
НастройкиМастера = Новый Структура;
НастройкиМастера.Вставить("Шаги", Новый Массив);
НастройкиМастера.Вставить("ТекущийШаг", Неопределено);
НастройкиМастера.Вставить("ГруппаСтраниц", Элементы.ШагиМастера.Имя);
НастройкиМастера.Вставить("КнопкаДалее", Элементы.ШагМастераДалее.Имя);
НастройкиМастера.Вставить("КнопкаНазад", Элементы.ШагМастераНазад.Имя);
НастройкиМастера.Вставить("КнопкаОтмена", Элементы.ШагМастераОтмена.Имя);
НастройкиМастера.Вставить("ПоказатьДиалогПередЗакрытием", Ложь);
Элементы.ШагМастераДалее.Видимость = Ложь;
Элементы.ШагМастераНазад.Видимость = Ложь;
Элементы.ШагМастераОтмена.Видимость = Ложь;
КонецПроцедуры
&НаСервере
Функция ДобавитьШагМастера(Знач Страница)
ОписаниеШага = Новый Структура;
ОписаниеШага.Вставить("Индекс", 0);
ОписаниеШага.Вставить("ИмяСтраницы", "");
ОписаниеШага.Вставить("КнопкаНазад", КнопкаМастера());
ОписаниеШага.Вставить("КнопкаДалее", КнопкаМастера());
ОписаниеШага.Вставить("ПриНажатииКнопкиДалее", "");
ОписаниеШага.Вставить("КнопкаОтмена", КнопкаМастера());
ОписаниеШага.ИмяСтраницы = Страница.Имя;
ОписаниеШага.КнопкаНазад = КнопкаМастера();
ОписаниеШага.КнопкаНазад.Заголовок = НСтр("ru = '< Назад'");
ОписаниеШага.КнопкаДалее = КнопкаМастера();
ОписаниеШага.КнопкаДалее.КнопкаПоУмолчанию = Истина;
ОписаниеШага.КнопкаДалее.Заголовок = НСтр("ru = 'Далее >'");
ОписаниеШага.КнопкаОтмена = КнопкаМастера();
ОписаниеШага.КнопкаОтмена.Заголовок = НСтр("ru = 'Отмена'");
НастройкиМастера.Шаги.Добавить(ОписаниеШага);
ОписаниеШага.Индекс = НастройкиМастера.Шаги.ВГраница();
Возврат ОписаниеШага;
КонецФункции
&НаКлиентеНаСервереБезКонтекста
Процедура УстановитьВидимостьДоступность(Форма)
Элементы = Форма.Элементы;
НастройкиМастера = Форма.НастройкиМастера;
ТекущийШаг = НастройкиМастера.ТекущийШаг;
Элементы[НастройкиМастера.ГруппаСтраниц].ТекущаяСтраница = Элементы[ТекущийШаг.ИмяСтраницы];
ОбновитьСвойстваКнопкиМастера(Элементы[НастройкиМастера.КнопкаДалее], ТекущийШаг.КнопкаДалее);
ОбновитьСвойстваКнопкиМастера(Элементы[НастройкиМастера.КнопкаНазад], ТекущийШаг.КнопкаНазад);
ОбновитьСвойстваКнопкиМастера(Элементы[НастройкиМастера.КнопкаОтмена], ТекущийШаг.КнопкаОтмена);
КонецПроцедуры
&НаКлиенте
Процедура ПерейтиНаШагМастера(Знач ШагИлиИндексИлиГруппаФормы)
Тип = ТипЗнч(ШагИлиИндексИлиГруппаФормы);
Если Тип = Тип("Структура") Тогда
ОписаниеШага = ШагИлиИндексИлиГруппаФормы;
ИначеЕсли Тип = Тип("Число") Тогда
ИндексШага = ШагИлиИндексИлиГруппаФормы;
Если ИндексШага < 0 Тогда
ВызватьИсключение НСтр("ru = 'Попытка выхода назад из первого шага мастера'");
ИначеЕсли ИндексШага > НастройкиМастера.Шаги.ВГраница() Тогда
ВызватьИсключение НСтр("ru = 'Попытка выхода за последний шаг мастера'");
КонецЕсли;
ОписаниеШага = НастройкиМастера.Шаги[ИндексШага];
Иначе
ШагНайден = Ложь;
ИмяИскомойСтраницы = ШагИлиИндексИлиГруппаФормы.Имя;
Для Каждого ОписаниеШага Из НастройкиМастера.Шаги Цикл
Если ОписаниеШага.ИмяСтраницы = ИмяИскомойСтраницы Тогда
ШагНайден = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Если Не ШагНайден Тогда
ВызватьИсключение СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Не найден шаг ""%1"".'"),
ИмяИскомойСтраницы);
КонецЕсли;
КонецЕсли;
НастройкиМастера.ТекущийШаг = ОписаниеШага;
УстановитьВидимостьДоступность(ЭтотОбъект);
ПриАктивацииШагаМастера();
КонецПроцедуры
#КонецОбласти
#Область СобытияМастера
&НаКлиенте
Процедура ПриАктивацииШагаМастера()
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Если ТекущаяСтраница = Элементы.ШагПоискНеВыполнялся Тогда
Элементы.Шапка.Доступность = Истина;
ПредставлениеПравилОтбора = Строка(КомпоновщикПредварительногоОтбора.Настройки.Отбор);
Если ПустаяСтрока(ПредставлениеПравилОтбора) Тогда
ПредставлениеПравилОтбора = НСтр("ru = 'Все элементы'");
КонецЕсли;
Союз = " " + НСтр("ru = 'И'") + " ";
ТекстПравил = "";
Для Каждого Правило Из ПравилаПоиска Цикл
Если Правило.Правило = "Равно" Тогда
Сравнение = Правило.ПредставлениеРеквизита + " " + НСтр("ru = 'совпадает'");
ИначеЕсли Правило.Правило = "Подобно" Тогда
Сравнение = Правило.ПредставлениеРеквизита + " " + НСтр("ru = 'совпадает по похожим словам'");
Иначе
Продолжить;
КонецЕсли;
ТекстПравил = ?(ТекстПравил = "", "", ТекстПравил + Союз) + Сравнение;
КонецЦикла;
Если УчитыватьПрикладныеПравила Тогда
Для Позиция = 1 По СтрЧислоСтрок(ОписаниеПрикладныхПравил) Цикл
СтрокаПравила = СокрЛП(СтрПолучитьСтроку(ОписаниеПрикладныхПравил, Позиция));
Если Не ПустаяСтрока(СтрокаПравила) Тогда
ТекстПравил = ?(ТекстПравил = "", "", ТекстПравил + Союз) + СтрокаПравила;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если ПустаяСтрока(ТекстПравил) Тогда
ТекстПравил = НСтр("ru = 'Правила не заданы'");
КонецЕсли;
Если СкрыватьНезначимыеДубли Тогда
СтрокаПравил = НСтр("ru = 'не показывать помеченные на удаление без мест использования'");
ТекстПравил = ?(ТекстПравил = "", "", ТекстПравил + Союз) + СтрокаПравил;
КонецЕсли;
ПредставлениеПравилПоиска = ТекстПравил;
Элементы.ПредставлениеПравилОтбора.Доступность = Не ПустаяСтрока(ОбластьПоискаДублей);
Элементы.ПредставлениеПравилПоиска.Доступность = Не ПустаяСтрока(ОбластьПоискаДублей);
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыполнениеПоиска Тогда
Если Не ЭтоАдресВременногоХранилища(АдресСхемыКомпоновки) Тогда
Возврат;
КонецЕсли;
Элементы.Шапка.Доступность = Ложь;
НастройкиМастера.ПоказатьДиалогПередЗакрытием = Истина;
НайтиИУдалитьДублиКлиент();
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыборОсновногоЭлемента Тогда
Элементы.Шапка.Доступность = Истина;
Элементы.ПовторитьПоиск.Видимость = Истина;
РазвернутьГруппуДублей();
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыполнениеУдаления Тогда
Элементы.Шапка.Доступность = Ложь;
НастройкиМастера.ПоказатьДиалогПередЗакрытием = Истина;
НайтиИУдалитьДублиКлиент();
ИначеЕсли ТекущаяСтраница = Элементы.ШагУспешноеУдаление Тогда
Элементы.Шапка.Доступность = Ложь;
Если ВозможныйДубльВыбран Тогда
Элементы.ШагМастераНазад.Заголовок = НСтр("ru='Новый поиск'");
Элементы.ШагМастераНазад.КнопкаПоУмолчанию = Истина;
Иначе
Элементы.ШагМастераНазад.Заголовок = НСтр("ru='Повторить поиск'");
Элементы.ШагМастераНазад.КнопкаПоУмолчанию = Ложь;
КонецЕсли;
ИначеЕсли ТекущаяСтраница = Элементы.ШагНеудачныеЗамены Тогда
Элементы.Шапка.Доступность = Ложь;
ИначеЕсли ТекущаяСтраница = Элементы.ШагДублейНеНайдено Тогда
Элементы.Шапка.Доступность = Истина;
Если ПустаяСтрока(ОписаниеОшибкиПоискаДублей) Тогда
Сообщение = НСтр("ru = 'Не обнаружено дублей по указанным параметрам.'");
Иначе
Сообщение = ОписаниеОшибкиПоискаДублей;
КонецЕсли;
Элементы.ДублейНеНайдено.ОтображениеСостояния.Текст = Сообщение + Символы.ПС
+ НСтр("ru = 'Измените условия и нажмите ""Найти дубли""'");
ИначеЕсли ТекущаяСтраница = Элементы.ШагВозниклаОшибка Тогда
Элементы.Шапка.Доступность = Истина;
Элементы.СсылкаПодробнее.Видимость = ЗначениеЗаполнено(Элементы.СсылкаПодробнее.Подсказка);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ШагМастераДалее()
ОчиститьСообщения();
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Шаг = НастройкиМастера.ТекущийШаг;
ОбработчикДалееЗавершение = Новый ОписаниеОповещения("ШагМастераДалееЗавершение", ЭтотОбъект);
Если ТекущаяСтраница = Элементы.ШагПоискНеВыполнялся Тогда
Если ПустаяСтрока(ОбластьПоискаДублей) Тогда
ПоказатьПредупреждение(, НСтр("ru = 'Выберите область поиска дублей'"));
Возврат;
КонецЕсли;
ВыполнитьОбработкуОповещения(ОбработчикДалееЗавершение, Шаг.Индекс + 1);
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыборОсновногоЭлемента Тогда
Элементы.ПовторитьПоиск.Видимость = Ложь;
Если ЗначениеЗаполнено(Шаг.ПриНажатииКнопкиДалее) Тогда
Обработчик = Новый ОписаниеОповещения(Шаг.ПриНажатииКнопкиДалее, ЭтотОбъект,
Новый Структура("ОбработчикЗавершения", ОбработчикДалееЗавершение));
ВыполнитьОбработкуОповещения(Обработчик, Шаг.Индекс + 1);
Иначе
ВыполнитьОбработкуОповещения(ОбработчикДалееЗавершение, Шаг.Индекс + 1);
КонецЕсли;
ИначеЕсли ТекущаяСтраница = Элементы.ШагНеудачныеЗамены Тогда
ВыполнитьОбработкуОповещения(ОбработчикДалееЗавершение, Элементы.ШагВыполнениеУдаления);
ИначеЕсли ТекущаяСтраница = Элементы.ШагДублейНеНайдено Тогда
ВыполнитьОбработкуОповещения(ОбработчикДалееЗавершение, Элементы.ШагВыполнениеПоиска);
Иначе
ВыполнитьОбработкуОповещения(ОбработчикДалееЗавершение, Шаг.Индекс + 1);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ШагМастераДалееЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = Неопределено Тогда
Возврат;
КонецЕсли;
ПерейтиНаШагМастера(Результат);
КонецПроцедуры
&НаКлиенте
Процедура ШагМастераНазад()
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Если ТекущаяСтраница = Элементы.ШагУспешноеУдаление Тогда
Если ВозможныйДубльВыбран Тогда
ОтобратьВыбранныеМестаИспользования(ВозможныйДубльВыбранныйТип);
ОбластьПоискаДублейЗавершениеВыбора(ВозможныйДубльВыбранныйТип, Неопределено);
ШагМастераДалее();
Иначе
ПерейтиНаШагМастера(Элементы.ШагПоискНеВыполнялся);
КонецЕсли;
Иначе
Шаг = НастройкиМастера.ТекущийШаг;
ПерейтиНаШагМастера(Шаг.Индекс - 1);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ШагМастераОтмена()
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Если ТекущаяСтраница = Элементы.ШагВыполнениеПоиска
Или ТекущаяСтраница = Элементы.ШагВыполнениеУдаления Тогда
НастройкиМастера.ПоказатьДиалогПередЗакрытием = Ложь;
КонецЕсли;
Если Открыта() Тогда
Закрыть();
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область СобытияШага_ВыборОсновногоЭлемента
&НаКлиенте
Процедура ШагВыборОсновногоЭлементаПриНажатииКнопкиДалее(ОписаниеСледующегоШага, ДополнительныеПараметры) Экспорт
ПараметрыОбработчика = Новый Структура("ОписаниеСледующегоШага, ОбработчикЗавершения",
ОписаниеСледующегоШага, ДополнительныеПараметры.ОбработчикЗавершения);
Если ВозвращеноМеньшеЧемНайдено Тогда
ОбработчикОтвета = Новый ОписаниеОповещения("ШагВыборОсновногоЭлементаПриНажатииКнопкиДалееЗавершение", ЭтотОбъект, ПараметрыОбработчика);
ПоказатьВопрос(
ОбработчикОтвета,
НСтр("ru='Отображены не все найденные дубли. Будут обработаны все найденные дубли.
|Начать обработку дублей?'"), РежимДиалогаВопрос.ДаНет);
Иначе
ВыполнитьОбработкуОповещения(ДополнительныеПараметры.ОбработчикЗавершения, ОписаниеСледующегоШага);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ШагВыборОсновногоЭлементаПриНажатииКнопкиДалееЗавершение(Результат, ДополнительныеПараметры) Экспорт
Если Результат = КодВозвратаДиалога.Да Тогда
ВыполнитьОбработкуОповещения(
ДополнительныеПараметры.ОбработчикЗавершения,
ДополнительныеПараметры.ОписаниеСледующегоШага);
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область Служебные
&НаСервере
Функция НастройкиПоискаУдаленияДублей()
Результат = Новый Структура;
Результат.Вставить("УчитыватьПрикладныеПравила", Истина);
Результат.Вставить("ОбластьПоискаДублей", "");
Результат.Вставить("НастройкиКД", Неопределено);
Результат.Вставить("ПравилаПоиска", Неопределено);
Результат.Вставить("СпособУдаления", "Пометка");
Результат.Вставить("СкрыватьНезначимыеДубли", Истина);
Возврат Результат;
КонецФункции
&НаКлиенте
Функция ПолноеИмяФормы(КраткоеИмяФормы)
Имена = СтрРазделить(ИмяФормы, ".");
Возврат Имена[0] + "." + Имена[1] + ".Форма." + КраткоеИмяФормы;
КонецФункции
&НаКлиенте
Процедура ОткрытьФормуДубля(Знач ТекущиеДанные)
Если ТекущиеДанные = Неопределено Или Не ЗначениеЗаполнено(ТекущиеДанные.Ссылка) Тогда
Возврат;
КонецЕсли;
ПоказатьЗначение(,ТекущиеДанные.Ссылка);
КонецПроцедуры
&НаКлиенте
Процедура ПоказатьМестаИспользования(ДеревоИсточник)
МассивСсылок = Новый Массив;
Для Каждого ГруппаДублей Из ДеревоИсточник.ПолучитьЭлементы() Цикл
Для Каждого СтрокаДерева Из ГруппаДублей.ПолучитьЭлементы() Цикл
МассивСсылок.Добавить(СтрокаДерева.Ссылка);
КонецЦикла;
КонецЦикла;
ПараметрыОтчета = Новый Структура;
ПараметрыОтчета.Вставить("Отбор", Новый Структура("НаборСсылок", МассивСсылок));
РежимОкна = РежимОткрытияОкнаФормы.БлокироватьОкноВладельца;
ОткрытьФорму("Отчет.МестаИспользованияСсылок.Форма", ПараметрыОтчета, ЭтотОбъект, , , , , РежимОкна);
КонецПроцедуры
&НаКлиенте
Процедура РазвернутьГруппуДублей(Знач СтрокаДанных = Неопределено)
Если СтрокаДанных <> Неопределено Тогда
Элементы.НайденныеДубли.Развернуть(СтрокаДанных, Истина);
КонецЕсли;
ВсеСтроки = Элементы.НайденныеДубли;
Для Каждого ДанныеСтроки Из НайденныеДубли.ПолучитьЭлементы() Цикл
ВсеСтроки.Развернуть(ДанныеСтроки.ПолучитьИдентификатор(), Истина);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура СвернутьГруппуДублей(Знач СтрокаДанных = Неопределено)
Если СтрокаДанных <> Неопределено Тогда
Элементы.НайденныеДубли.Свернуть(СтрокаДанных);
Возврат;
КонецЕсли;
ВсеСтроки = Элементы.НайденныеДубли;
Для Каждого ДанныеСтроки Из НайденныеДубли.ПолучитьЭлементы() Цикл
ВсеСтроки.Свернуть(ДанныеСтроки.ПолучитьИдентификатор());
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура УстановитьПометкиВДереве(Дерево, Пометка, ПроверятьРодителя)
ЭлементыСтроки = Дерево.ПолучитьЭлементы();
Для Каждого Элемент Из ЭлементыСтроки Цикл
Элемент.Пометка = Пометка;
УстановитьПометкиВДереве(Элемент, Пометка, Ложь);
КонецЦикла;
Родитель = Дерево.ПолучитьРодителя();
Если ПроверятьРодителя И Родитель <> Неопределено Тогда
ПроверитьПометкуРодителя(Родитель);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ПроверитьПометкуРодителя(Родитель)
ПометкаРодителя = Истина;
ЭлементыСтроки = Родитель.ПолучитьЭлементы();
Для Каждого Элемент Из ЭлементыСтроки Цикл
Если Не Элемент.Пометка Тогда
ПометкаРодителя = Ложь;
Прервать;
КонецЕсли;
КонецЦикла;
Родитель.Пометка = ПометкаРодителя;
КонецПроцедуры
&НаКлиенте
Процедура ИзменитьПометкиКандидатов(Знач ДанныеСтроки)
ПроставитьПометкиВниз(ДанныеСтроки);
ПроставитьПометкиВверх(ДанныеСтроки);
КонецПроцедуры
&НаКлиенте
Процедура ПроставитьПометкиВниз(Знач ДанныеСтроки)
Значение = ДанныеСтроки.Пометка;
Для Каждого Потомок Из ДанныеСтроки.ПолучитьЭлементы() Цикл
Потомок.Пометка = Значение;
ПроставитьПометкиВниз(Потомок);
КонецЦикла;
КонецПроцедуры
&НаКлиенте
Процедура ПроставитьПометкиВверх(Знач ДанныеСтроки)
РодительСтроки = ДанныеСтроки.ПолучитьРодителя();
Если РодительСтроки <> Неопределено Тогда
ВсеИстина = Истина;
НеВсеЛожь = Ложь;
Для Каждого Потомок Из РодительСтроки.ПолучитьЭлементы() Цикл
ВсеИстина = ВсеИстина И (Потомок.Пометка = 1);
НеВсеЛожь = НеВсеЛожь Или (Потомок.Пометка > 0);
КонецЦикла;
Если ВсеИстина Тогда
РодительСтроки.Пометка = 1;
ИначеЕсли НеВсеЛожь Тогда
РодительСтроки.Пометка = 2;
Иначе
РодительСтроки.Пометка = 0;
КонецЕсли;
ПроставитьПометкиВверх(РодительСтроки);
КонецЕсли;
КонецПроцедуры
&НаКлиенте
Процедура ОтметитьЭлементКакОригинал(Знач ДанныеСтроки, Знач Родитель)
Для Каждого Потомок Из Родитель.ПолучитьЭлементы() Цикл
Потомок.Основной = Ложь;
КонецЦикла;
ДанныеСтроки.Основной = Истина;
ДанныеСтроки.Пометка = 1;
ИзменитьПометкиКандидатов(ДанныеСтроки);
Родитель.Наименование = ДанныеСтроки.Наименование + " (" + Родитель.Количество + ")";
КонецПроцедуры
&НаКлиенте
Процедура ОбновитьОписаниеСостоянияНайденныхДублей()
ЕстьПодсистемаУдаленияПомеченных = ОбщегоНазначенияКлиент.ПодсистемаСуществует(
"СтандартныеПодсистемы.УдалениеПомеченныхОбъектов");
Если ПустаяСтрока(ОписаниеОшибкиПоискаДублей) Тогда
Описание = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Выбрано дублей: %1 из %2.'"),
ВсегоНайденоДублей, ВсегоЭлементов);
Иначе
Описание = ОписаниеОшибкиПоискаДублей;
КонецЕсли;
Если ЕстьПодсистемаУдаленияПомеченных Тогда
Если СпособУдаления = "Пометка" Тогда
ТекстПодсказки = НСтр("ru = 'Выбранные элементы будут <a href = ""[Действие]"">помечены на удаление</a> и заменены на оригиналы (отмечены стрелкой).'");
ПараметрыСтроки = Новый Структура("Действие", "СпособУдаления");
ТекстПодсказки = СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(ТекстПодсказки, ПараметрыСтроки);
Иначе
ТекстПодсказки = НСтр("ru = 'Выбранные элементы будут <a href = ""[Действие]"">безвозвратно удалены</a> и заменены на оригиналы (отмечены стрелкой).'");
ПараметрыСтроки = Новый Структура("Действие", "СпособУдаления");
ТекстПодсказки = СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(ТекстПодсказки, ПараметрыСтроки);
КонецЕсли;
Иначе
ТекстПодсказки = НСтр("ru = 'Выбранные элементы будут помечены на удаление и заменены на оригиналы (отмечены стрелкой).'");
КонецЕсли;
ОписаниеСостоянияНайденныхДублей = СтроковыеФункцииКлиент.ФорматированнаяСтрока(Описание + Символы.ПС + ТекстПодсказки);
КонецПроцедуры
&НаСервере
Функция АдресНастроекКомпоновщикаОтбора()
Возврат ПоместитьВоВременноеХранилище(КомпоновщикПредварительногоОтбора.Настройки, УникальныйИдентификатор);
КонецФункции
&НаСервере
Функция АдресНастроекПравилПоиска()
Настройки = Новый Структура;
Настройки.Вставить("УчитыватьПрикладныеПравила", УчитыватьПрикладныеПравила);
Настройки.Вставить("ВсеВариантыСравнения", ВсеВариантыСравнения);
Настройки.Вставить("ПравилаПоиска", РеквизитФормыВЗначение("ПравилаПоиска"));
Настройки.Вставить("СкрыватьНезначимыеДубли", СкрыватьНезначимыеДубли);
Возврат ПоместитьВоВременноеХранилище(Настройки);
КонецФункции
&НаСервере
Процедура ОбновитьКомпоновщикОтбора(Знач АдресРезультата)
Результат = ПолучитьИзВременногоХранилища(АдресРезультата);
УдалитьИзВременногоХранилища(АдресРезультата);
КомпоновщикПредварительногоОтбора.ЗагрузитьНастройки(Результат);
КомпоновщикПредварительногоОтбора.Восстановить(СпособВосстановленияНастроекКомпоновкиДанных.Полное);
СохранитьПользовательскиеНастройки();
КонецПроцедуры
&НаСервере
Процедура ОбновитьПравилаПоиска(Знач АдресРезультата)
Результат = ПолучитьИзВременногоХранилища(АдресРезультата);
УдалитьИзВременногоХранилища(АдресРезультата);
УчитыватьПрикладныеПравила = Результат.УчитыватьПрикладныеПравила;
СкрыватьНезначимыеДубли = Результат.СкрыватьНезначимыеДубли;
ЗначениеВРеквизитФормы(Результат.ПравилаПоиска, "ПравилаПоиска");
СохранитьПользовательскиеНастройки();
КонецПроцедуры
&НаСервере
Процедура ИнициализироватьКомпоновщикОтбораИПравила(Знач НастройкиФормы)
ПредставлениеПравилОтбора = "";
ПредставлениеПравилПоиска = "";
ТаблицаНастроек = ПолучитьИзВременногоХранилища(АдресНастроек);
СтрокаТаблицыНастроек = ТаблицаНастроек.Найти(ОбластьПоискаДублей, "ПолноеИмя");
Если СтрокаТаблицыНастроек = Неопределено Тогда
ОбластьПоискаДублей = "";
Возврат;
КонецЕсли;
ОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоПолномуИмени(ОбластьПоискаДублей);
СхемаКомпоновки = Новый СхемаКомпоновкиДанных;
ИсточникДанных = СхемаКомпоновки.ИсточникиДанных.Добавить();
ИсточникДанных.ТипИсточникаДанных = "Local";
НаборДанных = СхемаКомпоновки.НаборыДанных.Добавить(Тип("НаборДанныхЗапросСхемыКомпоновкиДанных"));
НаборДанных.Запрос = "ВЫБРАТЬ " + ДоступныеРеквизитыОтбора(ОбъектМетаданных) + " ИЗ " + ОбластьПоискаДублей;
НаборДанных.АвтоЗаполнениеДоступныхПолей = Истина;
АдресСхемыКомпоновки = ПоместитьВоВременноеХранилище(СхемаКомпоновки, УникальныйИдентификатор);
КомпоновщикПредварительногоОтбора.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(СхемаКомпоновки));
ТаблицаПравил = РеквизитФормыВЗначение("ПравилаПоиска");
ТаблицаПравил.Очистить();
ИсключаемыеРеквизиты = Новый Структура("ПометкаУдаления, Ссылка, Предопределенный, ИмяПредопределенныхДанных, ЭтоГруппа");
Для Каждого РеквизитМетаданные Из ОбъектМетаданных.Реквизиты Цикл
Если Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(РеквизитМетаданные) Тогда
ИсключаемыеРеквизиты.Вставить(РеквизитМетаданные.Имя);
КонецЕсли;
КонецЦикла;
ДобавитьПравилаРеквизитов(ТаблицаПравил, ИсключаемыеРеквизиты, ВсеВариантыСравнения, ОбъектМетаданных.СтандартныеРеквизиты, НечеткийПоиск);
ДобавитьПравилаРеквизитов(ТаблицаПравил, ИсключаемыеРеквизиты, ВсеВариантыСравнения, ОбъектМетаданных.Реквизиты, НечеткийПоиск);
ОтборыЗагружены = Ложь;
НастройкиКД = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(НастройкиФормы, "НастройкиКД");
Если ТипЗнч(НастройкиКД) = Тип("НастройкиКомпоновкиДанных") Тогда
Для Сч = -(НастройкиКД.Отбор.Элементы.Количество()-1) По 0 Цикл
Отбор = НастройкиКД.Отбор.Элементы[-Сч];
Если СтрНайти(Отбор.Представление, ПредставлениеВыбранногоМестаИспользования()) > 0 Тогда
ОбщегоНазначенияКлиентСервер.УдалитьЭлементыГруппыОтбора(НастройкиКД.Отбор,, Отбор.Представление);
КонецЕсли;
КонецЦикла;
КомпоновщикПредварительногоОтбора.ЗагрузитьНастройки(НастройкиКД);
ОтборыЗагружены = Истина;
КонецЕсли;
ПравилаЗагружены = Ложь;
СохраненныеПравила = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(НастройкиФормы, "ПравилаПоиска");
Если ТипЗнч(СохраненныеПравила) = Тип("ТаблицаЗначений") Тогда
ПравилаЗагружены = Истина;
Для Каждого СохраненноеПравило Из СохраненныеПравила Цикл
Правило = ТаблицаПравил.Найти(СохраненноеПравило.Реквизит, "Реквизит");
Если Правило <> Неопределено
И Правило.ВариантыСравнения.НайтиПоЗначению(СохраненноеПравило.Правило) <> Неопределено Тогда
Правило.Правило = СохраненноеПравило.Правило;
КонецЕсли;
КонецЦикла;
КонецЕсли;
Если Не ОтборыЗагружены Тогда
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбора( КомпоновщикПредварительногоОтбора.Настройки.Отбор,
"ПометкаУдаления", Ложь, ВидСравненияКомпоновкиДанных.Равно,, Ложь);
КонецЕсли;
Если ЭтоАдресВременногоХранилища(АдресВыбранныхМестИспользования) Тогда
ВыбранныеМестаИспользования = ПолучитьИзВременногоХранилища(АдресВыбранныхМестИспользования);
ГруппаОтбора = Неопределено;
Если ВыбранныеМестаИспользования.ЗначениеОтбора.Количество() > 0 Тогда
ГруппаОтбора = ОбщегоНазначенияКлиентСервер.СоздатьГруппуЭлементовОтбора(
КомпоновщикПредварительногоОтбора.Настройки.Отбор.Элементы,
ВыбранныеМестаИспользования.ПредставлениеОтбора,
ТипГруппыЭлементовОтбораКомпоновкиДанных.ГруппаИли);
КонецЕсли;
Для каждого РеквизитЗначениеОтбора Из ВыбранныеМестаИспользования.ЗначениеОтбора Цикл
ОбщегоНазначенияКлиентСервер.УстановитьЭлементОтбора(ГруппаОтбора,
РеквизитЗначениеОтбора.Ключ, РеквизитЗначениеОтбора.Значение,
ВидСравненияКомпоновкиДанных.ВСписке, "", Истина);
КонецЦикла;
УдалитьИзВременногоХранилища(АдресВыбранныхМестИспользования);
АдресВыбранныхМестИспользования = "";
КонецЕсли;
Если Не ПравилаЗагружены Тогда
Правило = ТаблицаПравил.Найти("Наименование", "Реквизит");
Если Правило <> Неопределено Тогда
ЗначениеДляСравнения = ?(НечеткийПоиск, "Подобно", "Равно");
Если Правило.ВариантыСравнения.НайтиПоЗначению(ЗначениеДляСравнения) <> Неопределено Тогда
Правило.Правило = ЗначениеДляСравнения;
КонецЕсли;
КонецЕсли;
КонецЕсли;
ОписаниеПрикладныхПравил = Неопределено;
Если СтрокаТаблицыНастроек.СобытиеПараметрыПоискаДублей Тогда
ПрикладныеПараметры = ПоискИУдалениеДублей.ПараметрыПоискаДублей(ТаблицаПравил, КомпоновщикПредварительногоОтбора);
МенеджерОбъектаМетаданных = ОбщегоНазначения.МенеджерОбъектаПоПолномуИмени(ОбъектМетаданных.ПолноеИмя());
МенеджерОбъектаМетаданных.ПараметрыПоискаДублей(ПрикладныеПараметры);
ОписаниеПрикладныхПравил = "";
Для Каждого Описание Из ПрикладныеПараметры.ОграниченияСравнения Цикл
ОписаниеПрикладныхПравил = ОписаниеПрикладныхПравил + Символы.ПС + Описание.Представление;
КонецЦикла;
ОписаниеПрикладныхПравил = СокрЛП(ОписаниеПрикладныхПравил);
КонецЕсли;
КомпоновщикПредварительногоОтбора.Восстановить(СпособВосстановленияНастроекКомпоновкиДанных.Полное);
ТаблицаПравил.Сортировать("ПредставлениеРеквизита");
ЗначениеВРеквизитФормы(ТаблицаПравил, "ПравилаПоиска");
ИдентификаторОбластиПоискаДублей = Справочники.ИдентификаторыОбъектовМетаданных
.НайтиПоРеквизиту("ПолноеИмя", ОбластьПоискаДублей);
ТипОбластиПоискаДублей = ТипЗнч(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ИдентификаторОбластиПоискаДублей, "ЗначениеПустойСсылки"));
ТипыОбработанныхОбъектов = Новый ОписаниеТипов(
ОбщегоНазначенияКлиентСервер.ЗначениеВМассиве(ТипОбластиПоискаДублей));
Если НастройкиФормы = Неопределено Тогда
СохранитьПользовательскиеНастройки();
КонецЕсли;
КонецПроцедуры
&НаСервере
Процедура ПриСозданииНаСервереИнициализацияДанных(НастройкиФормы)
УчитыватьПрикладныеПравила = НастройкиФормы.УчитыватьПрикладныеПравила;
ОбластьПоискаДублей = НастройкиФормы.ОбластьПоискаДублей;
СпособУдаления = НастройкиФормы.СпособУдаления;
СкрыватьНезначимыеДубли = НастройкиФормы.СкрыватьНезначимыеДубли;
ТаблицаНастроек = ПоискИУдалениеДублей.НастройкиОбъектовМетаданных();
АдресНастроек = ПоместитьВоВременноеХранилище(ТаблицаНастроек, УникальныйИдентификатор);
СписокВыбора = Элементы.ОбластьПоискаДублей.СписокВыбора;
КешКартинок = Новый Соответствие;
Для Каждого СтрокаТаблицы Из ТаблицаНастроек Цикл
КартинкаВида = КартинкаВидаМетаданных(КешКартинок, СтрокаТаблицы.Вид);
СписокВыбора.Добавить(СтрокаТаблицы.ПолноеИмя, СтрокаТаблицы.ПредставлениеСписка, , КартинкаВида);
КонецЦикла;
ВсеВариантыСравнения.Добавить("Равно", НСтр("ru = 'Совпадает'"));
ВсеВариантыСравнения.Добавить("Подобно", НСтр("ru = 'Совпадает по похожим словам'"));
КонецПроцедуры
&НаСервере
Процедура СохранитьПользовательскиеНастройки()
НастройкиФормы = Новый Структура;
НастройкиФормы.Вставить("УчитыватьПрикладныеПравила", УчитыватьПрикладныеПравила);
НастройкиФормы.Вставить("ОбластьПоискаДублей", ОбластьПоискаДублей);
НастройкиФормы.Вставить("НастройкиКД", КомпоновщикПредварительногоОтбора.Настройки);
НастройкиФормы.Вставить("ПравилаПоиска", ПравилаПоиска.Выгрузить());
НастройкиФормы.Вставить("СкрыватьНезначимыеДубли", СкрыватьНезначимыеДубли);
ОбщегоНазначения.ХранилищеОбщихНастроекСохранить(ИмяФормы, "", НастройкиФормы);
КонецПроцедуры
&НаСервере
Процедура УстановитьУсловноеОформление()
ЦветПоясняющийТекст = Метаданные.ЭлементыСтиля.ПоясняющийТекст.Значение;
ЦветПоясняющийОшибкуТекст = Метаданные.ЭлементыСтиля.ПоясняющийОшибкуТекст.Значение;
ЦветНедоступныеДанные = Метаданные.ЭлементыСтиля.ТекстЗапрещеннойЯчейкиЦвет.Значение;
ЭлементыУсловногоОформления = УсловноеОформление.Элементы;
ЭлементыУсловногоОформления.Очистить();
ЭлементОформления = ЭлементыУсловногоОформления.Добавить();
ОтборОформления = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборОформления.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("НайденныеДубли.Ссылка");
ОтборОформления.ВидСравнения = ВидСравненияКомпоновкиДанных.НеЗаполнено;
ОтборОформления.ПравоеЗначение = Истина;
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Текст", "");
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("НайденныеДублиКоличество");
ЭлементОформления = ЭлементыУсловногоОформления.Добавить();
ОтборОформления = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборОформления.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("НайденныеДубли.Основной");
ОтборОформления.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборОформления.ПравоеЗначение = Истина;
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Видимость", Ложь);
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Отображать", Ложь);
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("НайденныеДублиПометка");
ЭлементОформления = ЭлементыУсловногоОформления.Добавить();
ОтборОформления = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборОформления.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("НайденныеДубли.Ссылка");
ОтборОформления.ВидСравнения = ВидСравненияКомпоновкиДанных.Заполнено;
ОтборОформления.ПравоеЗначение = Истина;
ОтборОформления = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборОформления.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("НайденныеДубли.Количество");
ОтборОформления.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборОформления.ПравоеЗначение = 0;
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("Текст", НСтр("ru = '-'"));
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("НайденныеДублиКоличество");
ЭлементОформления = ЭлементыУсловногоОформления.Добавить();
ОтборОформления = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборОформления.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("НайденныеДубли.Пометка");
ОтборОформления.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборОформления.ПравоеЗначение = 0;
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветНедоступныеДанные);
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("НайденныеДубли");
ЭлементОформления = ЭлементыУсловногоОформления.Добавить();
ОтборОформления = ЭлементОформления.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
ОтборОформления.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("ВозможныеДубли.Обработано");
ОтборОформления.ВидСравнения = ВидСравненияКомпоновкиДанных.Равно;
ОтборОформления.ПравоеЗначение = Истина;
ЭлементОформления.Оформление.УстановитьЗначениеПараметра("ЦветТекста", ЦветаСтиля.ТекстЗапрещеннойЯчейкиЦвет);
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ВозможныеДублиИмяОбъектаМетаданных");
ПолеОформления = ЭлементОформления.Поля.Элементы.Добавить();
ПолеОформления.Поле = Новый ПолеКомпоновкиДанных("ВозможныеДублиИсточники");
КонецПроцедуры
&НаСервере
Функция ПараметрыУдаленияДублей()
ПараметрыУдаления = Новый Соответствие;
ИндексПорции = 0;
ДеревоДублей = РеквизитФормыВЗначение("НайденныеДубли");
ФильтрПоиска = Новый Структура("Основной", Истина);
Для Каждого ГруппыДублей Из ДеревоДублей.Строки Цикл
ПарыЗамен = Новый Соответствие;
Оригинал = ГруппыДублей.Строки.НайтиСтроки(ФильтрПоиска)[0].Ссылка;
Для Каждого Дубль Из ГруппыДублей.Строки Цикл
Если Дубль.Пометка = 1 И Дубль.Ссылка <> Оригинал Тогда
ПарыЗамен[Дубль.Ссылка] = Оригинал;
КонецЕсли;
КонецЦикла;
КоличествоЗамен = ПарыЗамен.Количество();
Если КоличествоЗамен = 0 Тогда
Продолжить;
КонецЕсли;
ОбщееКоличествоВыбранных = ОбщееКоличествоВыбранных + КоличествоЗамен;
ПараметрыПроцедуры = Новый Структура;
ПараметрыПроцедуры.Вставить("УчитыватьПрикладныеПравила", УчитыватьПрикладныеПравила);
ПараметрыПроцедуры.Вставить("СпособУдаления", СпособУдаления);
ПараметрыПроцедуры.Вставить("ПарыЗамен", ПарыЗамен);
ПараметрыВызоваСервера = Новый Массив;
ПараметрыВызоваСервера.Добавить(ПараметрыПроцедуры);
ПараметрыУдаления.Вставить(ИндексПорции, ПараметрыВызоваСервера);
ИндексПорции = ИндексПорции + 1;
КонецЦикла;
Возврат ПараметрыУдаления;
КонецФункции
&НаСервереБезКонтекста
Функция ДоступныеРеквизитыОтбора(ОбъектМетаданных)
Результат = Новый Массив;
Для Каждого РеквизитМетаданные Из ОбъектМетаданных.СтандартныеРеквизиты Цикл
Если Не РеквизитМетаданные.Тип.СодержитТип(Тип("ХранилищеЗначения")) Тогда
Результат.Добавить(РеквизитМетаданные.Имя);
КонецЕсли
КонецЦикла;
Для Каждого РеквизитМетаданные Из ОбъектМетаданных.Реквизиты Цикл
Если Не РеквизитМетаданные.Тип.СодержитТип(Тип("ХранилищеЗначения"))
Или Не ОбщегоНазначения.ОбъектМетаданныхДоступенПоФункциональнымОпциям(РеквизитМетаданные) Тогда
Результат.Добавить(РеквизитМетаданные.Имя);
КонецЕсли
КонецЦикла;
Возврат СтрСоединить(Результат, ",");
КонецФункции
&НаСервереБезКонтекста
Процедура ДобавитьПравилаРеквизитов(ТаблицаПравил, Знач ИсключаемыеРеквизиты, Знач ВсеВариантыСравнения,
Знач КоллекцияРеквизитов, Знач ДоступенНечеткийПоиск)
Для Каждого МетаданныеРеквизита Из КоллекцияРеквизитов Цикл
Если ИсключаемыеРеквизиты.Свойство(МетаданныеРеквизита.Имя) Тогда
Продолжить;
КонецЕсли;
ВариантыСравнения = ВариантыСравненияДляТипа(МетаданныеРеквизита.Тип, ВсеВариантыСравнения, ДоступенНечеткийПоиск);
Если ВариантыСравнения = Неопределено Тогда
Продолжить;
КонецЕсли;
СтрокаПравил = ТаблицаПравил.Добавить();
СтрокаПравил.Реквизит = МетаданныеРеквизита.Имя;
СтрокаПравил.ВариантыСравнения = ВариантыСравнения;
СтрокаПравил.ПредставлениеРеквизита = МетаданныеРеквизита.Представление();
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Функция ВариантыСравненияДляТипа(Знач ДоступныеТипы, Знач ВсеВариантыСравнения, Знач ДоступенНечеткийПоиск)
ЭтоХранилище = ДоступныеТипы.СодержитТип(Тип("ХранилищеЗначения"));
Если ЭтоХранилище Тогда
Возврат Неопределено;
КонецЕсли;
ЭтоСтрока = ДоступныеТипы.СодержитТип(Тип("Строка"));
ЭтоФиксированнаяСтрока = ЭтоСтрока И ДоступныеТипы.КвалификаторыСтроки <> Неопределено
И ДоступныеТипы.КвалификаторыСтроки.Длина <> 0;
Если ЭтоСтрока И Не ЭтоФиксированнаяСтрока Тогда
Возврат Неопределено;
КонецЕсли;
Результат = Новый СписокЗначений;
ЗаполнитьЗначенияСвойств(Результат.Добавить(), ВсеВариантыСравнения[0]);
Если ДоступенНечеткийПоиск И ЭтоСтрока Тогда
ЗаполнитьЗначенияСвойств(Результат.Добавить(), ВсеВариантыСравнения[1]);
КонецЕсли;
Возврат Результат;
КонецФункции
&НаСервереБезКонтекста
Функция КартинкаВидаМетаданных(КешКартинок, Вид)
Картинка = КешКартинок[Вид];
Если Картинка = Неопределено Тогда
Картинка = БиблиотекаКартинок[Вид];
КешКартинок.Вставить(Вид, Картинка);
КонецЕсли;
Возврат Картинка;
КонецФункции
#КонецОбласти
#Область РаботаСДлительнымиОперациями
&НаКлиенте
Процедура НайтиИУдалитьДублиКлиент()
ОтчетыДляОтправки = Новый Соответствие;
ДлительнаяОперация = НайтиИУдалитьДубли();
Если ДлительнаяОперация = Неопределено Тогда
НастройкиМастера.ПоказатьДиалогПередЗакрытием = Ложь;
ПерейтиНаШагМастера(Элементы.ШагВыборОсновногоЭлемента);
Возврат;
КонецЕсли;
НастройкиОжидания = ДлительныеОперацииКлиент.ПараметрыОжидания(ЭтотОбъект);
НастройкиОжидания.ВыводитьОкноОжидания = Ложь;
НастройкиОжидания.ВыводитьПрогрессВыполнения = Истина;
НастройкиОжидания.ОповещениеОПрогрессеВыполнения = Новый ОписаниеОповещения("НайтиИУдалитьДублиПрогресс", ЭтотОбъект);
Обработчик = Новый ОписаниеОповещения("НайтиИУдалитьДублиЗавершение", ЭтотОбъект);
ДлительныеОперацииКлиент.ОжидатьЗавершение(ДлительнаяОперация, Обработчик, НастройкиОжидания);
КонецПроцедуры
&НаСервере
Функция НайтиИУдалитьДубли()
ПараметрыПроцедуры = Новый Структура;
ПараметрыПроцедуры.Вставить("УчитыватьПрикладныеПравила", УчитыватьПрикладныеПравила);
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Если ТекущаяСтраница = Элементы.ШагВыполнениеПоиска Тогда
Элементы.ВыполнениеПоиска.ОтображениеСостояния.Текст = НСтр("ru = 'Поиск дублей...'");
ИмяПроцедуры = "Обработка.ПоискИУдалениеДублей.МодульОбъекта.ФоновыйПоискДублей";
ПараметрыПроцедуры.Вставить("ОбластьПоискаДублей", ОбластьПоискаДублей);
ПараметрыПроцедуры.Вставить("МаксимальноеЧислоДублей", 1500);
МассивПравилПоиска = Новый Массив;
Для Каждого Правило Из ПравилаПоиска Цикл
МассивПравилПоиска.Добавить(Новый Структура("Реквизит, Правило", Правило.Реквизит, Правило.Правило));
КонецЦикла;
ПараметрыПроцедуры.Вставить("ПравилаПоиска", МассивПравилПоиска);
ПараметрыПроцедуры.Вставить("СхемаКомпоновки", ПолучитьИзВременногоХранилища(АдресСхемыКомпоновки));
ПараметрыПроцедуры.Вставить("НастройкиКомпоновщикаПредварительногоОтбора", КомпоновщикПредварительногоОтбора.Настройки);
ПараметрыПроцедуры.Вставить("СкрыватьНезначимыеДубли", СкрыватьНезначимыеДубли);
НастройкиЗапуска = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
НастройкиЗапуска.НаименованиеФоновогоЗадания = НСтр("ru = 'Поиск и удаление дублей: Поиск дублей'");
Возврат ДлительныеОперации.ВыполнитьВФоне(ИмяПроцедуры, ПараметрыПроцедуры, НастройкиЗапуска);
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыполнениеУдаления Тогда
ПараметрыУдаления = ПараметрыУдаленияДублей();
Если ПараметрыУдаления.Количество() = 0 Тогда
ОбщегоНазначения.СообщитьПользователю(НСтр("ru = 'Выберите хотя бы одну группу дублей.'"),, "НайденныеДубли");
Возврат Неопределено;
КонецЕсли;
Элементы.ВыполнениеУдаления.ОтображениеСостояния.Текст = НСтр("ru = 'Обработка дублей...'");
ИмяПроцедуры = "Обработка.ПоискИУдалениеДублей.МодульОбъекта.ФоновоеУдалениеДублей";
НастройкиЗапуска = ДлительныеОперации.ПараметрыВыполненияВФоне(УникальныйИдентификатор);
НастройкиЗапуска.НаименованиеФоновогоЗадания = НСтр("ru = 'Поиск и удаление дублей: Удаление дублей'");
КоличествоПорций = ПараметрыУдаления.Количество();
Возврат ДлительныеОперации.ВыполнитьФункциюВНесколькоПотоков(ИмяПроцедуры, НастройкиЗапуска, ПараметрыУдаления);
КонецЕсли;
КонецФункции
&НаКлиенте
Процедура НайтиИУдалитьДублиПрогресс(Результат, ДополнительныеПараметры) Экспорт
Если Результат.Статус <> "Выполняется"
Или Результат.Прогресс = Неопределено Тогда
Возврат;
КонецЕсли;
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Если ТекущаяСтраница = Элементы.ШагВыполнениеПоиска Тогда
Сообщение = НСтр("ru = 'Поиск дублей...'");
Если Результат.Прогресс.Текст = "РассчитыватьМестаИспользования" Тогда
Сообщение = НСтр("ru = 'Выполняется расчет мест использования дублей...'");
ИначеЕсли Результат.Прогресс.Процент > 0 Тогда
Сообщение = Сообщение + " "
+ СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = '(найдено %1)'"), Результат.Прогресс.Процент);
КонецЕсли;
Элементы.ВыполнениеПоиска.ОтображениеСостояния.Текст = Сообщение;
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыполнениеУдаления Тогда
ПараметрыПрогресса = Неопределено;
Если Результат.Прогресс.Свойство("ДополнительныеПараметры", ПараметрыПрогресса)
И ПараметрыПрогресса = "ПрогрессМногопоточногоПроцесса" Тогда
Возврат;
КонецЕсли;
Если НЕ ПустаяСтрока(Результат.Прогресс.Текст) Тогда
Если ПараметрыПрогресса = Неопределено Тогда
Сообщение = Результат.Прогресс.Текст;
Иначе
Сообщение = ТекстПрогресса(ПараметрыПрогресса, Результат.Прогресс.Текст);
КонецЕсли;
Иначе
Сообщение = НСтр("ru = 'Обработка дублей...'");
КонецЕсли;
Элементы.ВыполнениеУдаления.ОтображениеСостояния.Текст = Сообщение;
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ТекстПрогресса(Знач ПараметрыПрогресса, Знач ИсходныйТекстПрогресса)
ЭтоЗамена = СтрНачинаетсяС(ИсходныйТекстПрогресса, НСтр("ru = 'Замена дублей'"));
ИмяРеквизитаПрогресса = ?(ЭтоЗамена, "КоличествоОбработанных", "КоличествоУдаленных");
Если ЭтоЗамена Тогда
ОбщееКоличествоОбработанных = ОбщееКоличествоОбработанных + ПараметрыПрогресса.КоличествоОбработанных;
Иначе
ОбщееКоличествоУдаленных = ОбщееКоличествоУдаленных + ПараметрыПрогресса.КоличествоОбработанных;
КонецЕсли;
ТекстПрогресса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Замена дублей... обработано (%1 из %2)'"),
ОбщееКоличествоОбработанных,
ОбщееКоличествоВыбранных);
Если СпособУдаления = "Непосредственно" Тогда
ТекстПрогресса = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = '%1
|Удаление дублей... обработано (%2 из %3)'"),
ТекстПрогресса,
ОбщееКоличествоУдаленных,
ОбщееКоличествоВыбранных);
КонецЕсли;
Возврат ТекстПрогресса;
КонецФункции
&НаКлиенте
Процедура НайтиИУдалитьДублиЗавершение(Результат, ДополнительныеПараметры) Экспорт
НастройкиМастера.ПоказатьДиалогПередЗакрытием = Ложь;
Активизировать();
ТекущаяСтраница = Элементы.ШагиМастера.ТекущаяСтраница;
Если Результат = Неопределено Тогда
Возврат;
КонецЕсли;
Если Результат.Статус <> "Выполнено" Тогда
Если ТекущаяСтраница = Элементы.ШагВыполнениеПоиска Тогда
Кратко = НСтр("ru = 'Не удалость найти дубли по причине:'");
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыполнениеУдаления Тогда
Кратко = НСтр("ru = 'Удаление дублей не выполнено по причине:'");
КонецЕсли;
Кратко = Кратко + Символы.ПС + Результат.КраткоеПредставлениеОшибки;
Подробно = Кратко + Символы.ПС + Символы.ПС + Результат.ПодробноеПредставлениеОшибки;
Элементы.НадписьТекстОшибки.Заголовок = Кратко;
Элементы.СсылкаПодробнее.Подсказка = Подробно;
ПерейтиНаШагМастера(Элементы.ШагВозниклаОшибка);
Возврат;
КонецЕсли;
Шаг = НастройкиМастера.ТекущийШаг;
Если ТекущаяСтраница = Элементы.ШагВыполнениеПоиска Тогда
ВсегоНайденоДублей = ЗаполнитьРезультатыПоискаДублей(Результат.АдресРезультата);
ВсегоЭлементов = ВсегоНайденоДублей;
Если ВсегоНайденоДублей > 0 Тогда
ОбновитьОписаниеСостоянияНайденныхДублей();
ПерейтиНаШагМастера(Шаг.Индекс + 1);
Иначе
ПерейтиНаШагМастера(Элементы.ШагДублейНеНайдено);
КонецЕсли;
ИначеЕсли ТекущаяСтраница = Элементы.ШагВыполнениеУдаления Тогда
Успех = ЗаполнитьРезультатыУдаленияДублей(Результат.АдресРезультата);
ОбщегоНазначенияКлиент.ОповеститьОбИзмененииОбъектов(ТипыОбработанныхОбъектов);
Если Успех = Истина Тогда
ОбновитьСостояниеВозможныхДублей();
ПерейтиНаШагМастера(Шаг.Индекс + 1);
Иначе
ПерейтиНаШагМастера(Элементы.ШагНеудачныеЗамены);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
&НаСервере
Функция ЗаполнитьРезультатыПоискаДублей(Знач АдресРезультата)
Данные = ПолучитьИзВременногоХранилища(АдресРезультата);
ОписаниеОшибкиПоискаДублей = Данные.ОписаниеОшибки;
ДеревоНайденныхДублей = РеквизитФормыВЗначение("НайденныеДубли");
ЭлементыДерева = ДеревоНайденныхДублей.Строки;
ЭлементыДерева.Очистить();
МестаИспользования = Данные.МестаИспользования;
ТаблицаДублей = Данные.ТаблицаДублей;
ВозвращеноМеньшеЧемНайдено = Данные.ВозвращеноМеньшеЧемНайдено;
ФильтрСтрок = Новый Структура("Родитель");
ФильтрМест = Новый Структура("Ссылка");
ВсегоНайденоДублей = 0;
ГруппыДублей = ТаблицаДублей.НайтиСтроки(ФильтрСтрок);
Для Каждого ГруппаДубля Из ГруппыДублей Цикл
ФильтрСтрок.Родитель = ГруппаДубля.Ссылка;
ЭлементыГруппы = ТаблицаДублей.НайтиСтроки(ФильтрСтрок);
ГруппаДерева = ЭлементыДерева.Добавить();
ГруппаДерева.Количество = ЭлементыГруппы.Количество();
ГруппаДерева.Пометка = 1;
ГруппаДерева.НомерКартинки = -1;
ОригинальныйЭлемент = Неопределено;
МаксимальноМестИспользования = -1;
Для Каждого Элемент Из ЭлементыГруппы Цикл
СтрокаДерева = ГруппаДерева.Строки.Добавить();
ЗаполнитьЗначенияСвойств(СтрокаДерева, Элемент, "Ссылка, Код, Наименование");
ФильтрМест.Ссылка = Элемент.Ссылка;
МестИспользования = МестаИспользования.НайтиСтроки(ФильтрМест).Количество();
СтрокаДерева.Количество = МестИспользования;
СтрокаДерева.Пометка = ?(Элемент.ПометкаУдаления И МестИспользования = 0, 0, 1);
СтрокаДерева.НомерКартинки = ?(Элемент.ПометкаУдаления, 4, 3);
Если МаксимальноМестИспользования < МестИспользования Тогда
Если ОригинальныйЭлемент <> Неопределено Тогда
ОригинальныйЭлемент.Основной = Ложь;
КонецЕсли;
ОригинальныйЭлемент = СтрокаДерева;
МаксимальноМестИспользования = МестИспользования;
ОригинальныйЭлемент.Основной = Истина;
КонецЕсли;
ВсегоНайденоДублей = ВсегоНайденоДублей + 1;
КонецЦикла;
ПометкаГруппы = Ложь;
Для Каждого СтрокаДерева Из ГруппаДерева.Строки Цикл
Если Не СтрокаДерева.Основной И СтрокаДерева.Пометка Тогда
ПометкаГруппы = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
ГруппаДерева.Пометка = ПометкаГруппы;
ГруппаДерева.Наименование = ОригинальныйЭлемент.Наименование + " (" + ГруппаДерева.Количество + ")";
ГруппаДерева.Строки.Сортировать("Наименование");
КонецЦикла;
ЗначениеВРеквизитФормы(ДеревоНайденныхДублей, "НайденныеДубли");
МестаИспользованияКандидата.Очистить();
Элементы.ОписаниеТекущейГруппыДублей.Заголовок = НСтр("ru = 'Дублей не найдено'");
Если ЭтоАдресВременногоХранилища(АдресМестИспользования) Тогда
УдалитьИзВременногоХранилища(АдресМестИспользования);
КонецЕсли;
АдресМестИспользования = ПоместитьВоВременноеХранилище(МестаИспользования, УникальныйИдентификатор);
Возврат ВсегоНайденоДублей;
КонецФункции
&НаСервере
Функция ЗаполнитьРезультатыУдаленияДублей(Знач АдресРезультата)
РезультатВыполненияВФоне = ПолучитьИзВременногоХранилища(АдресРезультата);
ТаблицаОшибок = ПолучитьИзВременногоХранилища(РезультатВыполненияВФоне[0].АдресРезультата);
Для ИндексПорции = 1 По КоличествоПорций - 1 Цикл
АдресРезультатаПорции = РезультатВыполненияВФоне[ИндексПорции].АдресРезультата;
ТаблицаОшибокПорции = ПолучитьИзВременногоХранилища(АдресРезультатаПорции);
ОбщегоНазначенияКлиентСервер.ДополнитьТаблицу(ТаблицаОшибокПорции, ТаблицаОшибок);
КонецЦикла;
ОбщееКоличествоОбработанных = 0;
ОбщееКоличествоУдаленных = 0;
ОбщееКоличествоВыбранных = 0;
КоличествоПорций = 0;
ПрогрессУдаления.Очистить();
Если ЭтоАдресВременногоХранилища(АдресРезультатаЗамены) Тогда
УдалитьИзВременногоХранилища(АдресРезультатаЗамены);
КонецЕсли;
ЗавершеноБезОшибок = ТаблицаОшибок.Количество() = 0;
ПоследнийКандидат = Неопределено;
Если ЗавершеноБезОшибок Тогда
ВсегоОбработано = 0;
ВсегоОсновных = 0;
Для Каждого ГруппаДублей Из НайденныеДубли.ПолучитьЭлементы() Цикл
Если ГруппаДублей.Пометка Тогда
Для Каждого Кандидат Из ГруппаДублей.ПолучитьЭлементы() Цикл
Если Кандидат.Основной Тогда
ПоследнийКандидат = Кандидат.Ссылка;
ВсегоОбработано = ВсегоОбработано + 1;
ВсегоОсновных = ВсегоОсновных + 1;
ИначеЕсли Кандидат.Пометка Тогда
ВсегоОбработано = ВсегоОбработано + 1;
КонецЕсли;
КонецЦикла;
КонецЕсли;
КонецЦикла;
Если ВсегоОсновных = 1 Тогда
Если ПоследнийКандидат = Неопределено Тогда
ОписаниеСостоянияНайденныхДублей = Новый ФорматированнаяСтрока(
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Все найденные дубли (%1) успешно объединены'"),
ВсегоОбработано));
Иначе
ПоследнийКандидатСтрокой = ОбщегоНазначения.ПредметСтрокой(ПоследнийКандидат);
ОписаниеСостоянияНайденныхДублей = Новый ФорматированнаяСтрока(
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Все найденные дубли (%1) успешно объединены
|в ""%2""'"),
ВсегоОбработано, ПоследнийКандидатСтрокой));
КонецЕсли;
Иначе
ОписаниеСостоянияНайденныхДублей = Новый ФорматированнаяСтрока(
СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(
НСтр("ru = 'Все найденные дубли (%1) успешно объединены.
|Оставлено элементов (%2).'"),
ВсегоОбработано,
ВсегоОсновных));
КонецЕсли;
КонецЕсли;
НеобработанныеДубли.ПолучитьЭлементы().Очистить();
МестаИспользованияНеобработанных.Очистить();
МестаИспользованияКандидата.Очистить();
Если ЗавершеноБезОшибок Тогда
ЗаполнитьВозможныеДубли();
НайденныеДубли.ПолучитьЭлементы().Очистить();
ЕстьВажныеВозможныеДубли = ВозможныеДубли.НайтиСтроки(Новый Структура("СтепеньРодства",2)).Количество() > 0;
ОтображаемаяСтепеньРодства = ?(ЕстьВажныеВозможныеДубли, 2, 1);
УстановитьОтборВозможныхДублей(ЭтотОбъект);
Возврат Истина;
КонецЕсли;
АдресРезультатаЗамены = ПоместитьВоВременноеХранилище(ТаблицаОшибок, УникальныйИдентификатор);
ЗначениеВРеквизитФормы(РеквизитФормыВЗначение("НайденныеДубли"), "НеобработанныеДубли");
Фильтр = Новый Структура("Ссылка");
Родители = НеобработанныеДубли.ПолучитьЭлементы();
ПозицияРодителя = Родители.Количество() - 1;
Пока ПозицияРодителя >= 0 Цикл
Родитель = Родители[ПозицияРодителя];
Потомки = Родитель.ПолучитьЭлементы();
ПозицияПотомка = Потомки.Количество() - 1;
ОсновнойПотомок = Потомки[0];
Пока ПозицияПотомка >= 0 Цикл
Потомок = Потомки[ПозицияПотомка];
Если Потомок.Основной Тогда
ОсновнойПотомок = Потомок;
Фильтр.Ссылка = Потомок.Ссылка;
Потомок.Количество = ТаблицаОшибок.НайтиСтроки(Фильтр).Количество();
ИначеЕсли ТаблицаОшибок.Найти(Потомок.Ссылка, "Ссылка") = Неопределено Тогда
Потомки.Удалить(Потомок);
Иначе
Фильтр.Ссылка = Потомок.Ссылка;
Потомок.Количество = ТаблицаОшибок.НайтиСтроки(Фильтр).Количество();
КонецЕсли;
ПозицияПотомка = ПозицияПотомка - 1;
КонецЦикла;
КоличествоПотомков = Потомки.Количество();
Если КоличествоПотомков = 1 И Потомки[0].Основной Тогда
Родители.Удалить(Родитель);
Иначе
Родитель.Количество = КоличествоПотомков - 1;
Родитель.Наименование = ОсновнойПотомок.Наименование + " (" + КоличествоПотомков + ")";
КонецЕсли;
ПозицияРодителя = ПозицияРодителя - 1;
КонецЦикла;
Возврат Ложь;
КонецФункции
&НаСервере
Процедура ЗаполнитьВозможныеДубли()
ИдентификаторОбрабатываемогоОбъекта = ИдентификаторОбластиПоискаДублей;
ОбрабатываемыйОбъектМетаданных = ОбщегоНазначения.ОбъектМетаданныхПоИдентификатору(ИдентификаторОбрабатываемогоОбъекта);
ОбработанныйВозможныйДубль = ВозможныеДубли.НайтиСтроки(
Новый Структура("ТипОбъектаМетаданных", ОбрабатываемыйОбъектМетаданных.ПолноеИмя()));
Если ОбработанныйВозможныйДубль.Количество() > 0 Тогда
ОбработанныйВозможныйДубль[0].Обработано = Истина;
КонецЕсли;
МестаИспользования = ПолучитьИзВременногоХранилища(АдресМестИспользования);
ПредполагаемыеВозможныеДубли = СформироватьВозможныеДубли(МестаИспользования);
ОтборПоискаВозможныхДублей = СформироватьОтборВозможныхДублей(РеквизитФормыВЗначение("НайденныеДубли"));
ТипОбрабатываемогоОбъекта = ТипЗнч(ОбщегоНазначения.ЗначениеРеквизитаОбъекта(ИдентификаторОбрабатываемогоОбъекта,
"ЗначениеПустойСсылки"));
Для каждого МестоИспользования Из ПредполагаемыеВозможныеДубли Цикл
Если ОбрабатываемыйОбъектМетаданных = МестоИспользования
ИЛИ МестоИспользования = Неопределено Тогда
Продолжить;
КонецЕсли;
КлючиСвязи = КлючиСвязиМетаданных(ТипОбрабатываемогоОбъекта, МестоИспользования);
Если КлючиСвязи.Количество() > 0 Тогда
ДобавитьВозможныйДубль(ОбрабатываемыйОбъектМетаданных, МестоИспользования, КлючиСвязи, ОтборПоискаВозможныхДублей);
КонецЕсли;
КонецЦикла;
ВыбранныеОбработанныеСтроки = ВозможныеДубли.НайтиСтроки(Новый Структура("Обработано, Выбран", Истина, Истина));
Для каждого СтрокаВозможныеДубли Из ВыбранныеОбработанныеСтроки Цикл
СтрокаВозможныеДубли.Выбран = Ложь;
КонецЦикла;
КонецПроцедуры
&НаСервереБезКонтекста
Функция СформироватьОтборВозможныхДублей(ДеревоДублей)
Отбор = Новый Массив;
Для каждого ГруппаДублей Из ДеревоДублей.Строки Цикл
Для каждого СтрокаДубля Из ГруппаДублей.Строки Цикл
Отбор.Добавить(СтрокаДубля.Ссылка);
КонецЦикла;
КонецЦикла;
Возврат Отбор;
КонецФункции
&НаСервереБезКонтекста
Функция СформироватьВозможныеДубли(МестаИспользования)
ИсключаемыеТипы = ПоискИУдалениеДублей.ТипыИсключаемыеИзВозможныхДублей();
ПредполагаемыеМестаИспользования = Новый Массив;
Для каждого МестоИспользования Из МестаИспользования Цикл
ТипМестаИспользования = ТипЗнч(МестоИспользования.Данные);
Если МестоИспользования.ВспомогательныеДанные
ИЛИ МестоИспользования.ЭтоСлужебныеДанные
ИЛИ НЕ ОбщегоНазначения.ЭтоСсылка(ТипМестаИспользования)
ИЛИ ИсключаемыеТипы.Найти(ТипМестаИспользования) <> Неопределено Тогда
Продолжить;
КонецЕсли;
ОписаниеМетаданных = ?(МестоИспользования.Метаданные <> Неопределено, МестоИспользования.Метаданные, МестоИспользования.Данные.Метаданные());
МетаданныеПодходят = ОбщегоНазначения.ЭтоСправочник(ОписаниеМетаданных)
ИЛИ ОбщегоНазначения.ЭтоПланВидовХарактеристик(ОписаниеМетаданных);
Если НЕ МетаданныеПодходят Тогда
Продолжить;
КонецЕсли;
Если ПредполагаемыеМестаИспользования.Найти(ОписаниеМетаданных) = Неопределено Тогда
ПредполагаемыеМестаИспользования.Добавить(ОписаниеМетаданных);
КонецЕсли;
КонецЦикла;
Возврат ПредполагаемыеМестаИспользования;
КонецФункции
&НаСервере
Процедура ДобавитьВозможныйДубль(ОбрабатываемыйОбъектМетаданных, МестоИспользования, КлючиСвязи, Отбор = Неопределено)
ПредставлениеМестаИспользования = МестоИспользования.Представление();
ПолноеИмяМестаИспользования = МестоИспользования.ПолноеИмя();
ТекущийПорядковыйНомер = ?(ВозможныеДубли.Количество(),ВозможныеДубли[ВозможныеДубли.Количество() - 1].Порядок + 1, 0);
ОтборДублей = Новый Структура("ТипОбъектаМетаданных", ПолноеИмяМестаИспользования);
ДобавленныеДубли = ВозможныеДубли.НайтиСтроки(ОтборДублей);
Если ДобавленныеДубли.Количество() > 0 Тогда
ВозможныйДубль = ДобавленныеДубли[0];
Если ВозможныйДубль.Источники.НайтиПоЗначению(ПолноеИмяМестаИспользования) <> Неопределено Тогда
ВозможныйДубль.Источники.Добавить(ОбрабатываемыйОбъектМетаданных.Представление());
КонецЕсли;
ИнформацияОбОтбореВозможныхДублей = ПолучитьИзВременногоХранилища(ВозможныйДубль.АдресОтбора);
Иначе
ВозможныйДубль = ВозможныеДубли.Добавить();
ВозможныйДубль.ИмяОбъектаМетаданных = ПредставлениеМестаИспользования;
ВозможныйДубль.ТипОбъектаМетаданных = ПолноеИмяМестаИспользования;
ВозможныйДубль.Порядок = ТекущийПорядковыйНомер;
ВозможныйДубль.Обработано = Ложь;
Источники = Новый СписокЗначений;
Источники.Добавить(ОбрабатываемыйОбъектМетаданных.Представление());
ВозможныйДубль.Источники = Источники;
ИнформацияОбОтбореВозможныхДублей = Новый Соответствие;
КонецЕсли;
ВозможныйДубль.СтепеньРодства = ?(КлючиСвязи.Найти(2, "СтепеньРодства") <> Неопределено, 2, 1);
ВозможныйДубль.ИсточникиПредставление = СтрСоединить(ВозможныйДубль.Источники.ВыгрузитьЗначения(), ", ");
Для каждого КлючиСвязи Из КлючиСвязи Цикл
ОтборВозможныхДублей = ИнформацияОбОтбореВозможныхДублей[КлючиСвязи.Имя];
Если ОтборВозможныхДублей = Неопределено Тогда
ИнформацияОбОтбореВозможныхДублей.Вставить(КлючиСвязи.Имя, Отбор);
Иначе
ОбщегоНазначенияКлиентСервер.ДополнитьМассив(ОтборВозможныхДублей, Отбор);
ИнформацияОбОтбореВозможныхДублей.Вставить(КлючиСвязи.Имя, ОтборВозможныхДублей);
КонецЕсли;
КонецЦикла;
ВозможныйДубль.АдресОтбора = ПоместитьВоВременноеХранилище(ИнформацияОбОтбореВозможныхДублей, УникальныйИдентификатор);
КонецПроцедуры
&НаСервереБезКонтекста
Функция КлючиСвязиМетаданных(Знач ТипОбрабатываемогоОбъекта, Знач МестоИспользования)
Результат = Новый ТаблицаЗначений;
Результат.Колонки.Добавить("Имя");
Результат.Колонки.Добавить("СтепеньРодства");
Для каждого РеквизитМестаИспользования Из МестоИспользования.Реквизиты Цикл
Если РеквизитМестаИспользования.Тип.Типы().Найти(ТипОбрабатываемогоОбъекта) <> Неопределено Тогда
СвязьМетаданных = Результат.Добавить();
СвязьМетаданных.Имя = РеквизитМестаИспользования.Имя;
СвязьМетаданных.СтепеньРодства = 1;
КонецЕсли;
КонецЦикла;
Для каждого РеквизитМестаИспользования Из МестоИспользования.СтандартныеРеквизиты Цикл
Если РеквизитМестаИспользования.Тип.Типы().Найти(ТипОбрабатываемогоОбъекта) <> Неопределено Тогда
СвязьМетаданных = Результат.Добавить();
СвязьМетаданных.Имя = РеквизитМестаИспользования.Имя;
СвязьМетаданных.СтепеньРодства = 2;
КонецЕсли;
КонецЦикла;
Возврат Результат;
КонецФункции
&НаКлиенте
Процедура ПослеПодтвержденияОтменыЗадания(Ответ, ПараметрыВыполнения) Экспорт
Если Ответ = КодВозвратаДиалога.Прервать Тогда
НастройкиМастера.ПоказатьДиалогПередЗакрытием = Ложь;
Закрыть();
КонецЕсли;
КонецПроцедуры
#КонецОбласти
#Область СлужебныеПроцедурыИФункцииМастера
&НаКлиентеНаСервереБезКонтекста
Функция КнопкаМастера()
Результат = Новый Структура;
Результат.Вставить("Заголовок", "");
Результат.Вставить("Подсказка", "");
Результат.Вставить("Доступность", Истина);
Результат.Вставить("Видимость", Истина);
Результат.Вставить("КнопкаПоУмолчанию", Ложь);
Возврат Результат;
КонецФункции
&НаКлиентеНаСервереБезКонтекста
Процедура ОбновитьСвойстваКнопкиМастера(КнопкаМастера, Описание)
ЗаполнитьЗначенияСвойств(КнопкаМастера, Описание);
КнопкаМастера.РасширеннаяПодсказка.Заголовок = Описание.Подсказка;
КонецПроцедуры
&НаСервере
Процедура ОтобратьВыбранныеМестаИспользования(Знач ВыбранныйТип)
Перем АдресОтбора;
ВыбранныеМестаИспользования = Новый Структура("ПредставлениеОтбора, ЗначениеОтбора","", Новый Структура);
ВыбранныйДубль = ВозможныеДубли.НайтиСтроки(Новый Структура("ТипОбъектаМетаданных", ВыбранныйТип));
ВыбранныеМестаИспользования.ПредставлениеОтбора = ПредставлениеВыбранногоМестаИспользования();
Если ВыбранныйДубль.Количество() > 0 Тогда
ВыбранныйДубль = ВыбранныйДубль[0];
АдресОтбора = ВыбранныйДубль.АдресОтбора;
КонецЕсли;
Если ЭтоАдресВременногоХранилища(АдресОтбора) Тогда
Отбор = ПолучитьИзВременногоХранилища(АдресОтбора);
Для каждого РеквизитЗначениеОтбора Из Отбор Цикл
ЗначениеОтбора = Новый СписокЗначений;
ЗначениеОтбора.ЗагрузитьЗначения(РеквизитЗначениеОтбора.Значение);
ВыбранныеМестаИспользования.ЗначениеОтбора.Вставить(РеквизитЗначениеОтбора.Ключ, ЗначениеОтбора);
КонецЦикла;
КонецЕсли;
АдресВыбранныхМестИспользования = ПоместитьВоВременноеХранилище(ВыбранныеМестаИспользования, УникальныйИдентификатор);
КонецПроцедуры
&НаСервере
Функция ПредставлениеВыбранногоМестаИспользования()
Возврат НСтр("ru='Элементы, среди которых возможны дубли'");
КонецФункции
#КонецОбласти
#КонецОбласти