////////////////////////////////////////////////////////////////////////////////
// ПЕРЕМЕННЫЕ МОДУЛЯ

Перем мРезультатыПоиска Экспорт;
Перем мМетаданныеОбъекта Экспорт;
Перем мИмяТипаСсылки Экспорт;
Перем мКорневойТипОбъекта Экспорт;
Перем мПутьКДаннымПоляНечеткогоСравнения;
Перем мСтруктураКлючаПоиска;
Перем мПредставления;
Перем мТекущаяГруппа;
Перем мСписокРеквизитов;
Перем мЗависимыеМетаданные;
Перем мПостроительЗапросаОтбора;
Перем мМассивОтложеннойЗагрузкиРеквизитов;
Перем мОтборТекущемуПоПравилу;
Перем мНастройкиВосстановлены;
Перем мИмяСтарогоОбъектаМД;
Перем мТекущаяСтрокаУровняЦенности;
Перем мСхемаКомпоновкиОбщая;
Перем мСхемаКомпоновкиПар;
Перем мПсевдонимТаблицы;
Перем мПоляСравнения;
Перем мИмяПоляЦенность;
Перем мИмяПоляКоличествоЭлементов;
Перем мИмяПоляКоличествоСсылок;
Перем мИмяПоляНомерГруппы;
Перем мИмяПоляНеправильныеСсылки;
Перем мИмяПоляПравильныйЭлемент;
Перем мИмяПоляНеправильныйЭлемент;
Перем мИмяПоляПравильныеДанные;
Перем мИмяФлагаПравильныйЭлемент;
Перем мИмяФлагаПравильныеДанные;
Перем мИмяПоляИдентификатор;
Перем мОбработкаПоискаСсылок;
Перем мТекущееПравило;
Перем мПроизвольныйЗапрос;
Перем мПолеТекстовогоДокументаСКонтекстнойПодсказкой;
Перем мСуффиксСлужбеныхПолей;

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ И ФУНКЦИИ ОБЩЕГО НАЗНАЧЕНИЯ

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

Процедура ЗагрузитьГруппуРезультатовПоиска(НоваяТекущаяГруппа = Неопределено)
	
	Если НоваяТекущаяГруппа <> Неопределено Тогда
		мТекущаяГруппа = НоваяТекущаяГруппа;
	КонецЕсли;
	ЭлементыТекущейГруппы.Очистить();
	ЭлементыФормы.ЭлементыТекущейГруппы.ТолькоПросмотр = (мТекущаяГруппа = Неопределено);
	Если мТекущаяГруппа = Неопределено Тогда
		Возврат;
	КонецЕсли;
	СоставТекущейГруппы = мРезультатыПоиска.Скопировать(Новый Структура(мИмяПоляНомерГруппы, мТекущаяГруппа[мИмяПоляНомерГруппы]));
	ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(СоставТекущейГруппы, ЭлементыТекущейГруппы);
	ЗагрузитьРеквизитыЭлементовТекущейГруппы();
	СброситьДоступность();
	//ЭлементыФормы.НайденныеГруппы.ТекущаяСтрока = мТекущаяГруппа;
	
КонецПроцедуры

Функция ПолучитьТаблицуРеквизитовПоМассивуСсылок(МассивСсылок)
	
	Запрос = Новый Запрос;
	Запрос.Текст = 
	"ВЫБРАТЬ *
	|ИЗ
	|	" + ПолучитьОпределениеИсточникаДанных() + " КАК _Таблица
	|ГДЕ
	|	_Таблица.Ссылка В(&МассивСсылок)";
	Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
	Если РежимПроизвольногоЗапроса Тогда
		ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(мПроизвольныйЗапрос.Параметры, Запрос.Параметры);
	КонецЕсли; 
	Попытка
		ТаблицаРезультата = Запрос.Выполнить().Выгрузить();
	Исключение
		Сообщить(ОписаниеОшибки());
		ТаблицаРезультата = Новый ТаблицаЗначений;
		ТаблицаРезультата.Колонки.Добавить("Ссылка");
		Возврат ТаблицаРезультата;
	КонецПопытки; 
	ТаблицаРезультата.Индексы.Добавить("Ссылка");
	ЗаполнитьЗначенияСвойств(ТаблицаРезультата.Добавить(), ирОбщий.ПолучитьМенеджерЛкс(мМетаданныеОбъекта).ПустаяСсылка());
	Возврат ТаблицаРезультата;
	
КонецФункции // ()

// <Описание функции>
//
// Параметры:
//  <Параметр1>  – <Тип.Вид> – <описание параметра>
//                 <продолжение описания параметра>;
//  <Параметр2>  – <Тип.Вид> – <описание параметра>
//                 <продолжение описания параметра>.
//
// Возвращаемое значение:
//               – <Тип.Вид> – <описание значения>
//                 <продолжение описания значения>;
//  <Значение2>  – <Тип.Вид> – <описание значения>
//                 <продолжение описания значения>.
//
Функция ЗагрузитьРеквизитыЭлементовТекущейГруппы(ВыборочныйМассив = Неопределено)

	Если ВыборочныйМассив = Неопределено Тогда
		ВыборочныйМассив = ЭлементыТекущейГруппы.ВыгрузитьКолонку("Ссылка");
	КонецЕсли; 
	МаксимальныйРазмерГруппы = 1000;
	Если ВыборочныйМассив.Количество() > МаксимальныйРазмерГруппы Тогда
		Сообщить("Реквизиты элементов группы не были загружены, т.к. ее размер превышает " + МаксимальныйРазмерГруппы);
		Результат = Ложь;
	Иначе
		ТаблицаРеквизитов = ПолучитьТаблицуРеквизитовПоМассивуСсылок(ВыборочныйМассив);
		Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ЭлементыТекущейГруппы.Количество(), "Загрузка реквизитов");
		Для Каждого СтрокаСоставаГруппы Из ЭлементыТекущейГруппы Цикл
			ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
			СтрокаРезультатовПоиска = ТаблицаРеквизитов.Найти(СтрокаСоставаГруппы.Ссылка, "Ссылка");
			Если СтрокаРезультатовПоиска <> Неопределено Тогда
				ЗаполнитьЗначенияСвойств(СтрокаСоставаГруппы, СтрокаРезультатовПоиска, , "Ссылка");
			КонецЕсли; 
			СтрокаСоставаГруппы[мИмяПоляИдентификатор] = "" + ирОбщий.ПолучитьИдентификаторСсылкиЛкс(СтрокаСоставаГруппы.Ссылка);
		КонецЦикла;
		ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
		ПриИзмененииАвтовидимостьКолонокСоставаГруппы();
		Результат = Истина;
	КонецЕсли; 
	Возврат Результат;

КонецФункции // ЗагрузитьРеквизитыЭлементовТекущейГруппы()

Функция ПолучитьЗначениеНастройки(ИмяНастройки) 
	
	Возврат Неопределено;
	
КонецФункции

Функция ПолучитьСтрокуУпорядочиванияГруппДублей(БезПоляКоличестваЭлементов = Истина)
	
	Если БезПоляКоличестваЭлементов Тогда
		ИсключаемоеПоле = мИмяПоляКоличествоЭлементов;
	Иначе
		ИсключаемоеПоле = "";
	КонецЕсли; 
	СтрокаПорядка = ирОбщий.ПолучитьСтрокуПорядкаКомпоновкиЛкс(КомпоновщикСравнения.Настройки.Порядок, ИсключаемоеПоле);
	Если ЗначениеЗаполнено(СтрокаПорядка) Тогда
		СтрокаПорядка = " УПОРЯДОЧИТЬ ПО " + СтрокаПорядка;
	КонецЕсли; 
	Возврат СтрокаПорядка;
	
КонецФункции

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

Функция ПолучитьЗапросПоискаДублей(ЗапросСОтборомОбщим, выхТекстИдексов = "", выхПоискПоПохожимСловам = Неопределено)
	
	выхПоискПоПохожимСловам = ЭтоПоискПоПохожимСловам();
	ТекстИсточника = ПолучитьОпределениеИсточникаДанных();
	ЗапросСОтборомПар = Неопределено;
	Если ЗначениеЗаполнено("" + КомпоновщикПар.Настройки.Отбор) Тогда
		ЗапросСОтборомПар = ирОбщий.ПолучитьЗапросИзКомпоновкиЛкс(мСхемаКомпоновкиПар, КомпоновщикПар.ПолучитьНастройки(),, "Пары", мИмяПоляПравильныйЭлемент);
	КонецЕсли; 
	//ИмяТаблицы = мПлатформа.ПолучитьНовоеУникальноеИмя();
	ИмяТаблицы = "Т";
	ТекстГДЕ = "";
	ТекстВЫБРАТЬ = "";
	ТекстКлюча = "";
	// Нужен для обхода проблемы с отсечением правых пробелов строк при группировке (сравнении)
	выхТекстИдексов = "";
	ТекстУсловия = "";
	ТекстСоединения = "ИСТИНА";
	ТекстСоединенияПравильный = "";
	ТекстСоединенияНеправильный = "";
	ТекстВЫБРАТЬПары = "";
	Для Каждого ПолеСравнения Из мПоляСравнения Цикл
		ПолноеИмяПоля = "" + ПолеСравнения.Поле;
		Если Ложь
			Или ПолноеИмяПоля = мИмяПоляКоличествоЭлементов
		Тогда
			Продолжить;
		КонецЕсли;
		ИмяПоля = мПлатформа.ПолучитьИдентификаторИзПредставления(ПолноеИмяПоля);
		ДоступноеПоле = КомпоновщикСравнения.Настройки.ДоступныеПоляПорядка.НайтиПоле(ПолеСравнения.Поле);
		мПредставления.Вставить(ИмяПоля, ДоступноеПоле.Заголовок);
		Если выхПоискПоПохожимСловам И ПолноеИмяПоля = мПутьКДаннымПоляНечеткогоСравнения Тогда
			ИмяПоляНечеткогоСравнения = ИмяПоля;
			Продолжить;
		КонецЕсли;
		ВыражениеПоля = ОбренутьВыражениеЗапросаДляГруппировки(мПсевдонимТаблицы + "." + ПолноеИмяПоля, ДоступноеПоле.ТипЗначения);
		//ТекстСоединения    = ТекстСоединения    + Символы.ПС + "И " + мПсевдонимТаблицы + "." + ИмяПоля + " = ПервичныеГруппыДублей." + ИмяПоля;
		ТекстСоединения    = ТекстСоединения    + Символы.ПС + "И " + ВыражениеПоля + " = ПервичныеГруппыДублей." + ИмяПоля;
		выхТекстИдексов    = выхТекстИдексов    + ", " + ИмяПоля;
		ТекстВЫБРАТЬ       = ТекстВЫБРАТЬ       + ", " + ВыражениеПоля + " КАК " + ИмяПоля; // запрещенные имена например "Соединение" так вызывают ошибку?
		ТекстКлюча         = ТекстКлюча         + ", " + ВыражениеПоля;
		ТекстУсловия       = ТекстУсловия       + "И " + ВыражениеПоля + " ЕСТЬ НЕ NULL ";
		
		ВыражениеПоляПравильный = ОбренутьВыражениеЗапросаДляГруппировки("Правильный." + ПолноеИмяПоля, ДоступноеПоле.ТипЗначения);
		ТекстСоединенияПравильный = ТекстСоединенияПравильный + Символы.ПС + "И " + ВыражениеПоляПравильный + " = ПервичныеГруппыДублей." + ИмяПоля;
		ВыражениеПоляНеправильный = ОбренутьВыражениеЗапросаДляГруппировки("Неправильный." + ПолноеИмяПоля, ДоступноеПоле.ТипЗначения);
		ТекстСоединенияНеправильный = ТекстСоединенияНеправильный + Символы.ПС + "И " + ВыражениеПоляНеправильный + " = ПервичныеГруппыДублей." + ИмяПоля;
		ТекстВЫБРАТЬПары = ТекстВЫБРАТЬПары + ", ФинальныеПары.Правильный." + ПолноеИмяПоля + " КАК " + ИмяПоля;
	КонецЦикла;
	мСтруктураКлючаПоиска = Новый Структура(Сред(выхТекстИдексов, 2));
	ТекстОтбораДублей = ирОбщий.ПолучитьТекстОтбораЗапросаКомпоновкиЛкс(ЗапросСОтборомОбщим, мПсевдонимТаблицы);
	ТекстЗапросаПоиска = "// Первичные группы дублей
	|ВЫБРАТЬ 0 КАК Пустышка,
	|	КОЛИЧЕСТВО(" + мПсевдонимТаблицы + ".Ссылка) КАК " + мИмяПоляКоличествоЭлементов + ТекстВЫБРАТЬ + "
	|ПОМЕСТИТЬ ПервичныеГруппыДублей
	|ИЗ " + ТекстИсточника + " КАК " + мПсевдонимТаблицы + "
	|ГДЕ ИСТИНА " + ТекстУсловия + " И (" + ТекстОтбораДублей + ")
	|СГРУППИРОВАТЬ ПО 0" + ТекстКлюча + "
	|ИМЕЮЩИЕ КОЛИЧЕСТВО(" + мПсевдонимТаблицы + ".Ссылка) > 1
	|";
	ТекстЗапросаПоиска = ТекстЗапросаПоиска + ";
	|";
	ЗапросПоиска = Новый Запрос;
	ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(ЗапросСОтборомОбщим.Параметры, ЗапросПоиска.Параметры);
	ВыражениеПоляЦенность = ДобавитьВыражениеЦенности(ЗапросПоиска);
	ТекстУпорядочитьПоЦенности = ПолучитьСтрокуПорядкаЦенности();
	ТекстУпорядочитьГруппы = ирОбщий.ПолучитьСтрокуПорядкаКомпоновкиЛкс(КомпоновщикСравнения.Настройки.Порядок, мПутьКДаннымПоляНечеткогоСравнения, "_");
	Если ЗапросСОтборомПар <> Неопределено Тогда
		//ирОбщий.ДобавитьПрефиксВсемПараметрамЗапросаЛкс(ЗапросСОтборомПар, "Пары");
		ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(ЗапросСОтборомПар.Параметры, ЗапросПоиска.Параметры);
		ТекстОтбораПар = ирОбщий.ПолучитьТекстОтбораЗапросаКомпоновкиЛкс(ЗапросСОтборомПар, "Неправильный");
		ТекстЗапросаПоиска = ТекстЗапросаПоиска + 
		"
		|//{Запрос: ЭлементыПервичныхГрупп
		|ВЫБРАТЬ " + мПсевдонимТаблицы + ".Ссылка КАК Ссылка" + ТекстВЫБРАТЬ + "
		|ПОМЕСТИТЬ ЭлементыПервичныхГрупп
		|ИЗ " + ТекстИсточника  + " КАК " + мПсевдонимТаблицы + " ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПервичныеГруппыДублей КАК ПервичныеГруппыДублей
		|ПО " + ТекстСоединения + "
		|ГДЕ" + ТекстОтбораДублей + "
		|ИНДЕКСИРОВАТЬ ПО Ссылка
		|;
		|// Пары Правильный-Неправильный
		|ВЫБРАТЬ
		|	Правильный.Ссылка КАК Правильный,
		|	Неправильный.Ссылка КАК Неправильный
		|ПОМЕСТИТЬ ПарыДоПоглощения
		|ИЗ ПервичныеГруппыДублей КАК ПервичныеГруппыДублей
		|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ " + ТекстИсточника + " КАК Правильный 
		|	ПО ИСТИНА " + ТекстСоединенияПравильный + "
		|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЭлементыПервичныхГрупп КАК ЭлементыПервичныхГрупп1 
		|	ПО Правильный.Ссылка = ЭлементыПервичныхГрупп1.Ссылка
		|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ " + ТекстИсточника + " КАК Неправильный
		|	ПО ИСТИНА " + ТекстСоединенияНеправильный + "
		|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ ЭлементыПервичныхГрупп КАК ЭлементыПервичныхГрупп2 
		|	ПО Неправильный.Ссылка = ЭлементыПервичныхГрупп2.Ссылка
		|ГДЕ Правильный.Ссылка <> Неправильный.Ссылка 
		|	И " + СокрЛ(ТекстОтбораПар) + "
		|;";
		ТекстЗапросаОбработкиПар = ПолучитьЗапросПодготовкиПар(ТекстИсточника, ВыражениеПоляЦенность, ТекстВЫБРАТЬПары, ТекстУпорядочитьГруппы, ТекстУпорядочитьПоЦенности);
		ТекстЗапросаПоиска = ТекстЗапросаПоиска + ТекстЗапросаОбработкиПар;
	Иначе
		ТекстЗапросаПоиска = ТекстЗапросаПоиска + "
		|//{Запрос: ФинальныеГруппы
		|ВЫБРАТЬ * ИЗ ПервичныеГруппыДублей
		|";
		Если ЗначениеЗаполнено(ТекстУпорядочитьГруппы) Тогда
			ТекстЗапросаПоиска = ТекстЗапросаПоиска + " УПОРЯДОЧИТЬ ПО " + ТекстУпорядочитьГруппы;
		КонецЕсли; 
		ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(ЗапросСОтборомОбщим.Параметры, ЗапросПоиска.Параметры);
		ТекстВЫБРАТЬ = ТекстВЫБРАТЬ + ", " + ВыражениеПоляЦенность + " КАК " + мИмяПоляЦенность;
		Если выхПоискПоПохожимСловам Тогда
			ТекстВЫБРАТЬ = ТекстВЫБРАТЬ + ", " + мПутьКДаннымПоляНечеткогоСравнения + " КАК " + ИмяПоляНечеткогоСравнения;
		КонецЕсли; 
		ТекстЗапросаПоиска = ТекстЗапросаПоиска + ";
		|//{Запрос: ЭлементыФинальныхГрупп
		|ВЫБРАТЬ " + мПсевдонимТаблицы + ".Ссылка КАК Ссылка" + ТекстВЫБРАТЬ + "
		|ИЗ " + ТекстИсточника  + " КАК " + мПсевдонимТаблицы + " ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПервичныеГруппыДублей КАК ПервичныеГруппыДублей
		|ПО " + ТекстСоединения + "
		|ГДЕ" + ТекстОтбораДублей + " 
		|УПОРЯДОЧИТЬ ПО " + ТекстУпорядочитьПоЦенности + "
		|";
	КонецЕсли; 
	ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(ЗапросСОтборомОбщим.Параметры, ЗапросПоиска.Параметры);
	ЗапросПоиска.Текст = ТекстЗапросаПоиска;
	Если РежимПроизвольногоЗапроса Тогда
		ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(мПроизвольныйЗапрос.Параметры, ЗапросПоиска.Параметры);
	КонецЕсли; 
	Возврат ЗапросПоиска;
	
КонецФункции

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

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

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

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

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

Функция ПолучитьЗапросПодготовкиПар(Знач ТекстИсточника = "", Знач ВыражениеПоляЦенность = "0", Знач ТекстВЫБРАТЬПары = "", Знач ТекстУпорядочитьГруппы = "Правильный",
	Знач ТекстУпорядочитьПоЦенности = "")
	
	Если Не ЗначениеЗаполнено(ТекстИсточника) Тогда
		ТекстИсточника = ПолучитьОпределениеИсточникаДанных();
	КонецЕсли; 
	ТекстЗапросаОбработкиПар = "
	|ВЫБРАТЬ
	|	ПарыДоПоглощения1.Правильный КАК Правильный,
	|	ПарыДоПоглощения1.Неправильный КАК Неправильный
	|ПОМЕСТИТЬ ПарыПослеПоглощенияОтражений
	|ИЗ ПарыДоПоглощения КАК ПарыДоПоглощения1
	|	ЛЕВОЕ СОЕДИНЕНИЕ ПарыДоПоглощения КАК ПарыДоПоглощения2 
	|	ПО ПарыДоПоглощения1.Правильный = ПарыДоПоглощения2.Неправильный И ПарыДоПоглощения1.Неправильный = ПарыДоПоглощения2.Правильный
	|ГДЕ ЛОЖЬ 
	|	ИЛИ ПарыДоПоглощения1.Правильный > ПарыДоПоглощения1.Неправильный
	|	ИЛИ ПарыДоПоглощения2.Правильный ЕСТЬ NULL
	|;
	|ВЫБРАТЬ
	|	Т2.Неправильный КАК Неправильный,
	|	Т2.Правильный КАК Правильный
	|ПОМЕСТИТЬ Пары
	|ИЗ
	|	ПарыПослеПоглощенияОтражений КАК Т
	|		ПРАВОЕ СОЕДИНЕНИЕ ПарыПослеПоглощенияОтражений КАК Т2
	|		ПО Т.Неправильный = Т2.Правильный
	|			И Т.Правильный <> Т2.Неправильный
	|		ЛЕВОЕ СОЕДИНЕНИЕ ПарыПослеПоглощенияОтражений КАК Т3
	|		ПО (Т2.Неправильный = Т3.Неправильный)
	|			И (Т3.Правильный = Т.Правильный)
	|СГРУППИРОВАТЬ ПО
	|	Т2.Правильный,
	|	Т2.Неправильный
	|ИМЕЮЩИЕ
	|	СУММА(ВЫБОР
	|			КОГДА Т3.Правильный ЕСТЬ NULL
	|				ТОГДА 0
	|			ИНАЧЕ 1
	|		КОНЕЦ) = 0
	|; 
	|//{Запрос: НеуникальныеНеправильные
	|ВЫБРАТЬ
	|	Т.Неправильный КАК Ссылка
	|ПОМЕСТИТЬ
	|	НеуникальныеНеправильные
	|ИЗ Пары КАК Т
	|СГРУППИРОВАТЬ ПО
	|	Т.Неправильный
	|ИМЕЮЩИЕ КОЛИЧЕСТВО(*) > 1
	|;
	|//{Запрос: СмешанныеПравильные
	|ВЫБРАТЬ РАЗЛИЧНЫЕ
	|	Т1.Правильный КАК Ссылка
	|ПОМЕСТИТЬ
	|	СмешанныеПравильные
	|ИЗ Пары КАК Т1 ВНУТРЕННЕЕ СОЕДИНЕНИЕ Пары КАК Т2 ПО Т1.Правильный = Т2.Неправильный
	|; // Финальные пары
	|ВЫБРАТЬ
	|	Пары.*
	|ПОМЕСТИТЬ
	|	ФинальныеПары
	|ИЗ Пары КАК Пары 
	|	ЛЕВОЕ СОЕДИНЕНИЕ СмешанныеПравильные КАК СмешанныеПравильные ПО СмешанныеПравильные.Ссылка = Пары.Правильный
	|	ЛЕВОЕ СОЕДИНЕНИЕ НеуникальныеНеправильные КАК НеуникальныеНеправильные ПО НеуникальныеНеправильные.Ссылка = Пары.Неправильный
	|ГДЕ СмешанныеПравильные.Ссылка ЕСТЬ NULL И НеуникальныеНеправильные.Ссылка ЕСТЬ NULL
	|;
	|//{Запрос: ФинальныеГруппы
	|ВЫБРАТЬ 0 КАК Пустышка, КОЛИЧЕСТВО(*) + 1 КАК " + мИмяПоляКоличествоЭлементов + ", ФинальныеПары.Правильный КАК " + мИмяПоляПравильныйЭлемент + ТекстВЫБРАТЬПары + " 
	|ИЗ ФинальныеПары КАК ФинальныеПары
	|СГРУППИРОВАТЬ ПО ФинальныеПары.Правильный";
	Если ЗначениеЗаполнено(ТекстУпорядочитьГруппы) Тогда
		ТекстЗапросаОбработкиПар = ТекстЗапросаОбработкиПар + "
		|УПОРЯДОЧИТЬ ПО " + ТекстУпорядочитьГруппы;
	КонецЕсли;
	ТекстЗапросаОбработкиПар = ТекстЗапросаОбработкиПар + "
	|;
	|//{Запрос: ЭлементыФинальныхГрупп
	|ВЫБРАТЬ 
	|	" + мПсевдонимТаблицы + ".Ссылка КАК Ссылка, 
	|	" + ВыражениеПоляЦенность + " КАК " + мИмяПоляЦенность + ",
	|	ЭлементыГрупп." + мИмяФлагаПравильныйЭлемент + " КАК " + мИмяФлагаПравильныйЭлемент + ",
	|	ЭлементыГрупп." + мИмяПоляПравильныйЭлемент + " КАК " + мИмяПоляПравильныйЭлемент + "
	|ИЗ (ВЫБРАТЬ РАЗЛИЧНЫЕ ИСТИНА КАК " + мИмяФлагаПравильныйЭлемент + ",
	|		ФинальныеПары.Правильный КАК Ссылка, ФинальныеПары.Правильный КАК " + мИмяПоляПравильныйЭлемент + " ИЗ ФинальныеПары КАК ФинальныеПары
	|	ОБЪЕДИНИТЬ ВСЕ 
	|	ВЫБРАТЬ ЛОЖЬ КАК " + мИмяФлагаПравильныйЭлемент + ",
	|		ФинальныеПары.Неправильный КАК Ссылка, ФинальныеПары.Правильный КАК " + мИмяПоляПравильныйЭлемент + " ИЗ ФинальныеПары КАК ФинальныеПары) КАК ЭлементыГрупп
	|	ВНУТРЕННЕЕ СОЕДИНЕНИЕ " + ТекстИсточника  + " КАК " + мПсевдонимТаблицы + "
	|	ПО ЭлементыГрупп.Ссылка = " + мПсевдонимТаблицы + ".Ссылка";
	Если ЗначениеЗаполнено(ТекстУпорядочитьПоЦенности) Тогда
		ТекстЗапросаОбработкиПар = ТекстЗапросаОбработкиПар + "
		|УПОРЯДОЧИТЬ ПО " + ТекстУпорядочитьПоЦенности + "
		|";
	КонецЕсли;
	Возврат ТекстЗапросаОбработкиПар;

КонецФункции

Функция ОбренутьВыражениеЗапросаДляГруппировки(ВыражениеПоля, ОписаниеТипов)
	
	#Если Сервер И Не Сервер Тогда
	    ОписаниеТипов = Новый ОписаниеТипов;
	#КонецЕсли
	Результат = ВыражениеПоля;
	Если ОписаниеТипов.СодержитТип(Тип("Строка")) Тогда 
		Если ОписаниеТипов.КвалификаторыСтроки.Длина = 0 Тогда
			Результат = "ПОДСТРОКА(ВЫРАЗИТЬ(" + Результат + " КАК СТРОКА(300)), 1, 300)";
		КонецЕсли; 
		Если УчитыватьПравыеПробелыСтрок Тогда
			Результат = Результат + " + ""_"""
		КонецЕсли; 
	КонецЕсли; 
	Возврат Результат;
	
КонецФункции
	
Функция ДобавитьВыражениеЦенности(ЗапросПоиска)

	Если ШкалаЦенности.Количество() > 0 Тогда
		ВыражениеПоляЦенность = "ВЫБОР";
		Уровень = 1;
		Для Каждого УровеньЦенности Из ШкалаЦенности Цикл
			НастройкаКомпоновкиВарианта = ирОбщий.ВосстановитьНастройкуКомпоновкиИзСтрокиXMLЛкс(УровеньЦенности.НастройкаКомпоновкиXML);
			ЗапросВарианта = ирОбщий.ПолучитьЗапросИзКомпоновкиЛкс(мСхемаКомпоновкиОбщая, НастройкаКомпоновкиВарианта, , "В" + Уровень, "Ссылка");
			ТекстОтбораВарианта = ирОбщий.ПолучитьТекстОтбораЗапросаКомпоновкиЛкс(ЗапросВарианта, мПсевдонимТаблицы);
			ВыражениеПоляЦенность = ВыражениеПоляЦенность + "
			|	КОГДА " + ТекстОтбораВарианта + "
			|		ТОГДА " + XMLСтрока(Уровень);
			ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(ЗапросВарианта.Параметры, ЗапросПоиска.Параметры);
			Уровень = Уровень + 1;
		КонецЦикла;
		ВыражениеПоляЦенность = ВыражениеПоляЦенность + "
		|		ИНАЧЕ " + XMLСтрока(Уровень);
		ВыражениеПоляЦенность = ВыражениеПоляЦенность + Символы.ПС + "КОНЕЦ";
	Иначе
		ВыражениеПоляЦенность = "0";
	КонецЕсли; 
	Возврат ВыражениеПоляЦенность;

КонецФункции

Функция ПолучитьСтрокуПорядкаЦенности()

	ТекстУпорядочить = мИмяПоляЦенность;
	ТекстПорядкаЦенности = ирОбщий.ПолучитьСтрокуПорядкаКомпоновкиЛкс(КомпоновщикЦенности.Настройки.Порядок);
	Если ТекстПорядкаЦенности <> "" Тогда
		ТекстУпорядочить = ТекстУпорядочить + ", " + ТекстПорядкаЦенности;
	КонецЕсли; 
	Возврат ТекстУпорядочить;

КонецФункции

Функция ДобавитьОбщиеКолонкиВРезультатыПоиска()

	мРезультатыПоиска.Колонки.Добавить(мИмяПоляНомерГруппы, , мПредставления[мИмяПоляНомерГруппы]);
	Если мРезультатыПоиска.Колонки.Найти(мИмяФлагаПравильныйЭлемент) = Неопределено Тогда
		мРезультатыПоиска.Колонки.Добавить(мИмяФлагаПравильныйЭлемент, Новый ОписаниеТипов("Булево"), мПредставления[мИмяФлагаПравильныйЭлемент]);
	КонецЕсли; 
	мРезультатыПоиска.Колонки.Добавить(мИмяФлагаПравильныеДанные, Новый ОписаниеТипов("Булево"), мПредставления[мИмяФлагаПравильныеДанные]);
	мРезультатыПоиска.Колонки.Добавить(мИмяПоляКоличествоСсылок, , мПредставления[мИмяПоляКоличествоСсылок]);
	мРезультатыПоиска.Колонки.Добавить(мИмяПоляИдентификатор, , мПредставления[мИмяПоляИдентификатор]);
	Возврат Неопределено;

КонецФункции

Процедура НайтиПоПохожимСловам(ЗапросПоиска, ТекстИдексов)
	
	мРезультатыПоиска = Новый ТаблицаЗначений;
	мРезультатыПоиска.Колонки.Добавить(мИмяПоляЦенность);
	ТаблицаСлов = Новый ТаблицаЗначений;
	Для Каждого ПолеСравнения Из мПоляСравнения Цикл
		ПолноеИмяПоля = "" + ПолеСравнения.Поле;
		Если ПолноеИмяПоля = мИмяПоляКоличествоЭлементов Тогда
			Продолжить;
		КонецЕсли;
		ИмяПоля = мПлатформа.ПолучитьИдентификаторИзПредставления(ПолноеИмяПоля);
		Если "" + ПолеСравнения.Поле = мПутьКДаннымПоляНечеткогоСравнения Тогда
			ИмяПоляНечеткогоСравнения = ИмяПоля;
		КонецЕсли;
		ДоступноеПоле = КомпоновщикСравнения.Настройки.ДоступныеПоляПорядка.НайтиПоле(ПолеСравнения.Поле);
		мПредставления.Вставить(ИмяПоля, ДоступноеПоле.Заголовок);
		ТаблицаСлов.Колонки.Добавить(ИмяПоля);
		мРезультатыПоиска.Колонки.Добавить(ИмяПоля);
		НайденныеГруппы.Колонки.Добавить(ИмяПоля);
	КонецЦикла;
	ТаблицаСлов.Колонки.Добавить("Ссылка");
	ТаблицаСлов.Колонки.Добавить("СписокСлов");
	РезультатПакета = ЗапросПоиска.ВыполнитьПакет();
	#Если Сервер И Не Сервер Тогда
	    мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	ИндексыИменРезультатов = мПлатформа.ПолучитьСтруктуруРезультатаПакетногоЗапроса(ЗапросПоиска.Текст);
	ПервичныеГруппы = РезультатПакета[ИндексыИменРезультатов.ФинальныеГруппы].Выгрузить();
	МассивСтроковыхПолейСравнения = Новый Массив;
	Для Каждого ЭлементСравнения Из мСтруктураКлючаПоиска Цикл
		Если ПервичныеГруппы.Колонки[ЭлементСравнения.Ключ].ТипЗначения.СодержитТип(Тип("Строка")) Тогда
			МассивСтроковыхПолейСравнения.Добавить(ЭлементСравнения.Ключ);
		КонецЕсли;
	КонецЦикла;
	Для Каждого СтрокаГруппы Из ПервичныеГруппы Цикл
		ВосстановитьЗначенияСтрокВСтрокеРезультатаЗапроса(МассивСтроковыхПолейСравнения, СтрокаГруппы);
	КонецЦикла;
	ОбщаяТаблицаОбъекта = РезультатПакета[ИндексыИменРезультатов.ЭлементыФинальныхГрупп].Выгрузить();
	ОбщаяТаблицаОбъекта.Индексы.Добавить(Сред(ТекстИдексов, 2));
	
	НомерГруппы = 1;
	мРезультатыПоиска.Колонки.Добавить("Ссылка");
	ДобавитьОбщиеКолонкиВРезультатыПоиска();
	#Если Сервер И Не Сервер Тогда
	    мПлатформа = Обработки.ирПлатформа.Создать();
	#КонецЕсли
	////НечеткоеСравнениеСлов = мПлатформа.ПолучитьОбъектВнешнейКомпонентыИзМакета("StrMatchExtension", "AddIn.AddInNative.StrMatchExtension", "StrMatchExtension");
	//НечеткоеСравнениеСлов = мПлатформа.ПолучитьCOMОбъектИзМакета("StrMatchExtension", "StrMatchExtension", ,, "StrMatchExtension");
	//НечеткоеСравнениеСлов = мПлатформа.ПолучитьОбъектВнешнейКомпонентыИзМакета("FuzzySearch", "AddIn.FuzzySearch.FuzzyStringMatchExtension", "FuzzySearch");
	Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ПервичныеГруппы.Количество(), "Первичные группы элементов");
	КлючПоиска = Новый Структура(Сред(ТекстИдексов, 2));
	ПорогПохожести = 0.49 + 0.5 * Макс(0, (70 - ДопустимоеРазличиеСлов) / 70);
	Для Каждого ПервичнаяГруппа Из ПервичныеГруппы Цикл
		ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
		ЗаполнитьЗначенияСвойств(КлючПоиска, ПервичнаяГруппа); 
		ТаблицаОбъекта = ОбщаяТаблицаОбъекта.Скопировать(КлючПоиска);
		//Если НечеткоеСравнениеСлов <> Неопределено Тогда
			ИндикаторПохожих = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ПервичныеГруппы.Количество(), "Поиск похожих слов");
			СчетчикОбработанныхСтрок = 0;
			// Сначала обработаем пустые строки, т.к. внешняя компонента их не видит
			СтрокиПустыхСтрок = ТаблицаОбъекта.НайтиСтроки(Новый Структура(ИмяПоляНечеткогоСравнения, ""));
			Если СтрокиПустыхСтрок.Количество() > 0 Тогда
				СтрокаЛевого = СтрокиПустыхСтрок[0];
				СтрокиПустыхСтрок.Удалить(0);
				НачальноеКоличество = СтрокиПустыхСтрок.Количество(); 
				ГруппаПустая = Истина;
				Для Счетчик = 1 По НачальноеКоличество Цикл
					СтрокаПравого = СтрокиПустыхСтрок[НачальноеКоличество - Счетчик];
					ПодобратьЭлементыГруппыПоПохожимСловам(ГруппаПустая, НомерГруппы, СтрокаЛевого, СтрокаПравого, СчетчикОбработанныхСтрок, ТаблицаОбъекта);
				КонецЦикла;
				ТаблицаОбъекта.Удалить(СтрокаЛевого);
				Если Не ГруппаПустая Тогда
					НомерГруппы = НомерГруппы + 1;
				КонецЕсли; 
			КонецЕсли; 
			// Теперь обработаем все оставшиеся (непустые) строки
			Пока ТаблицаОбъекта.Количество() > 1 Цикл
				ирОбщий.ОбработатьИндикаторЛкс(ИндикаторПохожих, СчетчикОбработанныхСтрок);
				СтрокаЛевого = ТаблицаОбъекта[0];
				ЛевоеЗначение = СтрокаЛевого[ИмяПоляНечеткогоСравнения];
				ГруппаПустая = Истина;
				
				//ЛеваяДистанция = НечеткоеСравнениеСлов.Сравнить(ЛевоеЗначение, ЛевоеЗначение);
				//НачальноеКоличество = ТаблицаОбъекта.Количество(); 
				//Для СчетчикТаблицаОбъектов = 1 По НачальноеКоличество - 1 Цикл
				//	СтрокаПравого = ТаблицаОбъекта[НачальноеКоличество - СчетчикТаблицаОбъектов];
				//	ПравоеЗначение = СтрокаПравого[ИмяПоляНечеткогоСравнения];
				//	ПраваяДистанция = НечеткоеСравнениеСлов.Сравнить(ПравоеЗначение, ПравоеЗначение);
				//	Если ЛеваяДистанция > ПраваяДистанция Тогда
				//		БазоваяДистанция = ЛеваяДистанция;
				//	Иначе
				//		БазоваяДистанция = ПраваяДистанция;
				//	КонецЕсли; 
				//	Если БазоваяДистанция > 0 Тогда
				//		Дистанция = НечеткоеСравнениеСлов.Сравнить(ЛевоеЗначение, ПравоеЗначение);
				//		Если Дистанция / БазоваяДистанция >= ПорогПохожести Тогда
				//			ПодобратьЭлементыГруппыПоПохожимСловам(ГруппаПустая, НомерГруппы, СтрокаЛевого, СтрокаПравого, СчетчикОбработанныхСтрок, ТаблицаОбъекта);
				//		КонецЕсли;
				//	Иначе
				//		// нет буквенных символов
				//	КонецЕсли; 
				//КонецЦикла;
				МассивСтрок = ТаблицаОбъекта.ВыгрузитьКолонку(ИмяПоляНечеткогоСравнения);
				МассивСтрок.Удалить(0);
				РазделительСтрок = "~";
				СтрокаИзМассива = ирОбщий.ПолучитьСтрокуСРазделителемИзМассиваЛкс(МассивСтрок, РазделительСтрок);
				// Параметры 4-5-6:
				//SmallStringLength – число, определяющее максимальную длину небольших строк(для них процент совпадения при поиске отличается от сравнения более длинных строк)
				//SmallStringMatch – минимальный процент совпадения для небольших строк.
				//Match – минимальный процент совпадения для больших строк.
				// Создаем компоненту каждый раз, т.к. у нее внутри что то засоряется и повторный вызов возвращает некорректный результат https://partners.v8.1c.ru/forum/t/1429261/m/1643666
				НечеткоеСравнениеСлов = мПлатформа.ПолучитьОбъектВнешнейКомпонентыИзМакета("FuzzySearch", "AddIn.FuzzySearch.FuzzyStringMatchExtension", "FuzzySearch");
				ИндексыНайденныхСовпадений = НечеткоеСравнениеСлов.StringSearch(Нрег(ЛевоеЗначение), Нрег(СтрокаИзМассива), РазделительСтрок, 10, Макс(0, Цел(ПорогПохожести * 100) - 10), Цел(ПорогПохожести * 100));
				ИндексыПохожихСлов = ирОбщий.ПолучитьМассивИзСтрокиСРазделителемЛкс(ИндексыНайденныхСовпадений, ",",, Ложь);
				НачальноеКоличество = ИндексыПохожихСлов.Количество(); 
				Для Счетчик = 1 По НачальноеКоличество Цикл
					ИндексПохожегоСлова = ИндексыПохожихСлов[НачальноеКоличество - Счетчик];
					СтрокаПравого = ТаблицаОбъекта[Число(ИндексПохожегоСлова) + 1];
					ПодобратьЭлементыГруппыПоПохожимСловам(ГруппаПустая, НомерГруппы, СтрокаЛевого, СтрокаПравого, СчетчикОбработанныхСтрок, ТаблицаОбъекта);
				КонецЦикла;

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

Процедура ПодобратьЭлементыГруппыПоПохожимСловам(ГруппаПустая, Знач НомерГруппы, Знач СтрокаЛевого, СтрокаПравого, СчетчикОбработанныхСтрок, Знач ТаблицаОбъекта)
	
	Если ГруппаПустая Тогда
		СтрокаРезультата = мРезультатыПоиска.Добавить();
		ЗаполнитьЗначенияСвойств(СтрокаРезультата, СтрокаЛевого);
		СтрокаРезультата[мИмяПоляНомерГруппы] = НомерГруппы;
	КонецЕсли; 
	СтрокаРезультата = мРезультатыПоиска.Добавить();
	ЗаполнитьЗначенияСвойств(СтрокаРезультата, СтрокаПравого);
	СтрокаРезультата[мИмяПоляНомерГруппы] = НомерГруппы;
	ТаблицаОбъекта.Удалить(СтрокаПравого);
	СчетчикОбработанныхСтрок = СчетчикОбработанныхСтрок + 1;
	ГруппаПустая = Ложь;

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

Процедура ВосстановитьЗначенияСтрокВСтрокеРезультатаЗапроса(Знач МассивСтроковыхПолейСравнения, Знач СтрокаГруппы)
	
	Для Каждого СтроковоеПоле Из МассивСтроковыхПолейСравнения Цикл
		ЗначениеПоля = НРег(СокрП(СтрокаГруппы[СтроковоеПоле]));
		// Заменим неразрывный пробел на нормальный
		ЗначениеПоля = СтрЗаменить(ЗначениеПоля, Символ(10 * 16), " ");
		Если УчитыватьПравыеПробелыСтрок Тогда
			// Удалим служебный символ "_" в конце строки
			ЗначениеПоля = Лев(ЗначениеПоля, СтрДлина(ЗначениеПоля) - 1);
		КонецЕсли; 
		СтрокаГруппы[СтроковоеПоле] = ЗначениеПоля;
	КонецЦикла;

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

Функция ЗаполнитьПравилаЗаменыСсылокПоТекущейГруппе()
	
	Если мТекущаяГруппа = Неопределено Тогда
		Возврат Ложь;
	КонецЕсли; 
	СохранитьТекущуюГруппуРезультатовПоиска();
	Если Не ПроверитьОчиститьТаблицуПравил() Тогда 
		Возврат Ложь;
	КонецЕсли; 
	Если Не ЗаполнитьПравилаПоГруппеДублей(мТекущаяГруппа[мИмяПоляНомерГруппы]) Тогда
		Возврат Ложь;
	КонецЕсли;
	ВыполнитьПоискЗаменяемыхСсылок();
	Возврат Истина;
	
КонецФункции

Функция ПроверитьОчиститьТаблицуПравил()
	
	Результат = Истина;
	Если ПравилаЗаменыСсылок.Количество() > 0 Тогда
		Ответ = Вопрос("Хотите очистить таблицу правил перед заполнением?", РежимДиалогаВопрос.ДаНетОтмена,, КодВозвратаДиалога.Да);
		Если Ответ = КодВозвратаДиалога.Да Тогда
			ПравилаЗаменыСсылок.Очистить();
			//НайденныеСсылки.Очистить();
		ИначеЕсли Ответ = КодВозвратаДиалога.Отмена Тогда
			Результат = Ложь;
		КонецЕсли;
	Иначе
		//НайденныеСсылки.Очистить();
	КонецЕсли;
	Возврат Результат;

КонецФункции

Функция ЗаполнитьПравилаПоГруппеДублей(НомерГруппы)
	
	СоставТекущейГруппы = мРезультатыПоиска.Скопировать(Новый Структура(мИмяПоляНомерГруппы, НомерГруппы));
	СтрокаПравильного = СоставТекущейГруппы.Найти(Истина, мИмяФлагаПравильныйЭлемент);
	Если СтрокаПравильного = Неопределено Тогда
		Предупреждение("Не определен правильный элемент в группе " + НомерГруппы);
		Возврат Ложь;
	КонецЕсли;
	СтрокаПравильныхДанных = СоставТекущейГруппы.Найти(Истина, мИмяФлагаПравильныеДанные);
	Для Каждого СтрокаНеправильного Из СоставТекущейГруппы Цикл
		Если СтрокаНеправильного[мИмяФлагаПравильныйЭлемент] Тогда
			Продолжить;
		КонецЕсли; 
		ЧтоЗаменять = СтрокаНеправильного.Ссылка;
		НаЧтоЗаменять = СтрокаПравильного.Ссылка;
		ЗаменитьДанныеОбъекта = СтрокаПравильныхДанных = СтрокаНеправильного;
		СтрокаЗамены = ПравилаЗаменыСсылок.Найти(ЧтоЗаменять, "ЧтоЗаменять");
		Если СтрокаЗамены = Неопределено Тогда
			СтрокаЗамены = ПравилаЗаменыСсылок.Добавить();
			СтрокаЗамены.ЧтоЗаменять = ЧтоЗаменять;
		КонецЕсли; 
		СтрокаЗамены.НаЧтоЗаменять = НаЧтоЗаменять;
		СтрокаЗамены.Пометка = Истина;
		СтрокаЗамены.ПравилаЗависимых = ПравилаЗависимых.СкопироватьКолонки();
		СтрокаЗамены.ЗаменитьДанныеОбъекта = ЗаменитьДанныеОбъекта;
	КонецЦикла;
	Возврат Истина;
	
КонецФункции

Функция ЗаполнитьПравилаЗаменыСсылокПоВсемГруппам()
	
	Если Не ПроверитьОчиститьТаблицуПравил() Тогда 
		Возврат Ложь;
	КонецЕсли; 
	Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(НайденныеГруппы.Количество());
	Для Каждого ГруппаДублей Из НайденныеГруппы Цикл
		ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
		Если Не ЗаполнитьПравилаПоГруппеДублей(ГруппаДублей[мИмяПоляНомерГруппы]) Тогда
			Возврат Ложь;
		КонецЕсли;
	КонецЦикла;
	ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
	ВыполнитьПоискЗаменяемыхСсылок();
	Возврат Истина;
	
КонецФункции

Процедура СброситьДоступность()
	
	ЭлементыФормы.Панель.Страницы.ЗависимыеЭлементы.Доступность = Ложь;
	//ЭлементыФормы.Панель.Страницы.ПравилаЗаменыСсылок.Доступность = Ложь;
	ЗависимыеОбъекты.Строки.Очистить();
	ЭлементыФормы.КоманднаяПанельЗависимыеОбъекты.Кнопки.ВыполнитьЗамену.Доступность = Ложь;
	
КонецПроцедуры // () 

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

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

Процедура ОчиститьРезультатыПоиска()
	
	мПоляСравнения = Новый Массив();
	мРезультатыПоиска = Новый ТаблицаЗначений;
	мРезультатыПоиска.Колонки.Добавить("Ссылка");
	мРезультатыПоиска.Колонки.Добавить(мИмяПоляЦенность, , мПредставления[мИмяПоляЦенность]);
	ДобавитьОбщиеКолонкиВРезультатыПоиска();
	
	ЭтаФорма.ЭлементыТекущейГруппы = Новый ТаблицаЗначений;
	ЭтаФорма.НайденныеГруппы = Новый ТаблицаЗначений;
	мТекущаяГруппа = Неопределено;
	
	НайденныеГруппы.Колонки.Добавить(мИмяПоляНомерГруппы, , мПредставления[мИмяПоляНомерГруппы]);
	НайденныеГруппы.Колонки.Добавить(мИмяПоляКоличествоЭлементов, , мПредставления[мИмяПоляКоличествоЭлементов]);
	НайденныеГруппы.Индексы.Добавить(мИмяПоляНомерГруппы);
	
	ЭлементыТекущейГруппы.Колонки.Добавить("Ссылка", Новый ОписаниеТипов(мИмяТипаСсылки), "Объект");
	ЭлементыТекущейГруппы.Колонки.Добавить(мИмяПоляКоличествоСсылок, , мПредставления[мИмяПоляКоличествоСсылок]);
	ЭлементыТекущейГруппы.Колонки.Добавить(мИмяПоляНомерГруппы, , мПредставления[мИмяПоляНомерГруппы]);
	ЭлементыТекущейГруппы.Колонки.Добавить(мИмяПоляЦенность, , мПредставления[мИмяПоляЦенность]);
	ЭлементыТекущейГруппы.Колонки.Добавить(мИмяФлагаПравильныйЭлемент, Новый ОписаниеТипов("Булево"), мПредставления[мИмяФлагаПравильныйЭлемент]);
	ЭлементыТекущейГруппы.Колонки.Добавить(мИмяФлагаПравильныеДанные, Новый ОписаниеТипов("Булево"), мПредставления[мИмяФлагаПравильныеДанные]);
	ЭлементыТекущейГруппы.Колонки.Добавить(мИмяПоляИдентификатор, , мПредставления[мИмяПоляИдентификатор]);
	ЭлементыТекущейГруппы.Индексы.Добавить("Ссылка");
	
	Для Каждого СтрокаРеквизита Из мСписокРеквизитов Цикл
		ЭлементыТекущейГруппы.Колонки.Добавить(СтрокаРеквизита.Значение, , СтрокаРеквизита.Представление);
	КонецЦикла;
	НастроитьСлужебныеКолонкиРезультатовПоиска();
	
КонецПроцедуры

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

Процедура НастроитьЭлементыФормыПоРезультатуПоиска()
	
	ЭлементыФормы.НайденныеГруппы.СоздатьКолонки();
	ЭлементыФормы.ЭлементыТекущейГруппы.СоздатьКолонки();
	
	ирОбщий.УстановитьСвойствоВКоллекцииЛкс(ЭлементыФормы.НайденныеГруппы.Колонки, , "-Ширина", 30);
	ирОбщий.УстановитьСвойствоВКоллекцииЛкс(ЭлементыФормы.НайденныеГруппы.Колонки, , "-ТолькоПросмотр", Истина);
	ЭлементыФормы.НайденныеГруппы.Колонки[мИмяПоляНомерГруппы].Ширина = 5;
	ЭлементыФормы.НайденныеГруппы.Колонки[мИмяПоляКоличествоЭлементов].Формат = "ЧН=";
	ЭлементыФормы.НайденныеГруппы.Колонки[мИмяПоляКоличествоЭлементов].Ширина = 5;
		
	ирОбщий.УстановитьСвойствоВКоллекцииЛкс(ЭлементыФормы.ЭлементыТекущейГруппы.Колонки, , "-ТолькоПросмотр", Истина);
	Колонка = ЭлементыФормы.ЭлементыТекущейГруппы.Колонки[мИмяПоляКоличествоСсылок];
	Колонка.Ширина = 5;
	
	Колонка = ЭлементыФормы.ЭлементыТекущейГруппы.Колонки[мИмяПоляНомерГруппы];
	Колонка.ИзменятьВидимость = Ложь;
	Колонка.Видимость = Ложь;
	
	Колонка = ЭлементыФормы.ЭлементыТекущейГруппы.Колонки[мИмяФлагаПравильныйЭлемент];
	Колонка.Данные = "";
	Колонка.ДанныеФлажка = мИмяФлагаПравильныйЭлемент;
	Колонка.УстановитьЭлементУправления(Тип("Флажок"));
	
	Колонка = ЭлементыФормы.ЭлементыТекущейГруппы.Колонки[мИмяФлагаПравильныеДанные];
	Колонка.Данные = "";
	Колонка.ДанныеФлажка = мИмяФлагаПравильныеДанные;
	Колонка.УстановитьЭлементУправления(Тип("Флажок"));
		
	Для Каждого СтрокаРеквизита Из мСписокРеквизитов Цикл
		Колонка = ЭлементыФормы.ЭлементыТекущейГруппы.Колонки.Найти(СтрокаРеквизита.Значение);
		Колонка.Видимость = Ложь;
	КонецЦикла;
	Для Каждого КолонкаТП Из ЭлементыФормы.НайденныеГруппы.Колонки Цикл
		КолонкаТП.ТекстШапки = мПредставления[КолонкаТП.Имя];
	КонецЦикла;
	ирОбщий.ТабличноеПолеВставитьКолонкуНомерСтрокиЛкс(ЭлементыФормы.ЭлементыТекущейГруппы);
	ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяКолонка = ЭлементыФормы.ЭлементыТекущейГруппы.Колонки[1];
	ОбновитьРамкуГруппыНайденныеГруппы();
	ЗагрузитьГруппуРезультатовПоиска();

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

Процедура ОбновитьДоступностьКнопокВпередНазадНайденныхГрупп()
	
	ЭлементыФормы.КоманднаяПанельНайденныеГруппы.Кнопки.СледующаяГруппа.Доступность = НайденныеГруппы.Количество() > 1;
	ЭлементыФормы.КоманднаяПанельНайденныеГруппы.Кнопки.ПредыдущаяГруппа.Доступность = НайденныеГруппы.Количество() > 1;

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

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

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ОБРАБОТЧИКИ СОБЫТИЙ ФОРМЫ

Процедура ПередОткрытием(Отказ, СтандартнаяОбработка)
	
	ДопустимоеРазличиеСлов = 30;
	ПриУстановкеПолногоИмениОбъекта();
		
КонецПроцедуры

Функция ПриУстановкеПолногоИмениОбъекта()

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

КонецФункции

Процедура УстановитьПроизвольныйЗапросПоУмолчанию()
	
	мПроизвольныйЗапрос = Новый Запрос;
	мПроизвольныйЗапрос.Текст = "ВЫБРАТЬ Т.* ИЗ " + ПолноеИмяОбъекта + " КАК Т";

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

Процедура ОбновитьСхемуКомпоновки()
	
	ТекстИсточника = ПолучитьОпределениеИсточникаДанных();
	ЗапросОбщий = Новый Запрос("ВЫБРАТЬ " + мПсевдонимТаблицы + ".* ИЗ " + ТекстИсточника + " КАК " + мПсевдонимТаблицы);
	мСхемаКомпоновкиОбщая = ирОбщий.СоздатьСхемуКомпоновкиПоЗапросу(ЗапросОбщий);
	КомпоновщикОбщегоЗапроса = Новый КомпоновщикНастроекКомпоновкиДанных;
	КомпоновщикОбщегоЗапроса.Инициализировать(Новый ИсточникДоступныхНастроекКомпоновкиДанных(мСхемаКомпоновкиОбщая));
	ПоляЗапроса = КомпоновщикОбщегоЗапроса.Настройки.ДоступныеПоляВыбора.Элементы;
	ТекстВыбора = "";
	ТекстИЗ = "";
	ГруппыПолей = Новый Массив;
	ГруппыПолей.Добавить("Правильный");
	ГруппыПолей.Добавить("Неправильный");
	Для Каждого ГруппаПолей Из ГруппыПолей Цикл
		Для Каждого ВыбранноеПоле Из ПоляЗапроса Цикл
			Если ВыбранноеПоле.Папка Тогда
				Продолжить;
			КонецЕсли; 
			ТекстВыбора = ТекстВыбора + ", " + ГруппаПолей + "." + ВыбранноеПоле.Поле + " КАК " + ГруппаПолей + "_" + ВыбранноеПоле.Поле;
		КонецЦикла;
		Если "Правильный" = ГруппаПолей Тогда
			ИмяПоля = мИмяПоляПравильныйЭлемент;
		ИначеЕсли "Неправильный" = ГруппаПолей Тогда
			ИмяПоля = мИмяПоляНеправильныйЭлемент;
		Иначе 
			ВызватьИсключение "Неизвестная группа полей";
		КонецЕсли; 
		ТекстВыбора = ТекстВыбора + ", " + ГруппаПолей + ".Ссылка" + " КАК " + ИмяПоля;
		ТекстИЗ = ТекстИЗ + ", " + ТекстИсточника + " КАК " + ГруппаПолей;
	КонецЦикла;
	ТекстИЗ = Сред(ТекстИЗ, 3);
	ТекстВыбора = Сред(ТекстВыбора, 3);
	ЗапросПар = Новый Запрос("ВЫБРАТЬ " + ТекстВыбора + " ИЗ " + ТекстИЗ);
		
	мСхемаКомпоновкиПар = ирОбщий.СоздатьСхемуКомпоновкиПоЗапросу(ЗапросПар);
	#Если Сервер И Не Сервер Тогда
		мСхемаКомпоновкиОбщая = Новый СхемаКомпоновкиДанных;
		мСхемаКомпоновкиПар = Новый СхемаКомпоновкиДанных;
	#КонецЕсли
	Для Каждого ГруппаПолей Из ГруппыПолей Цикл
		Для Каждого ВыбранноеПоле Из ПоляЗапроса Цикл
			Если ВыбранноеПоле.Папка Тогда
				Продолжить;
			КонецЕсли; 
			ПолеНабора = мСхемаКомпоновкиПар.НаборыДанных[0].Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
			ПолеНабора.Поле = ГруппаПолей + "_" + ВыбранноеПоле.Поле;
			ПолеНабора.ПутьКДанным = "<" + ГруппаПолей + ">." + ВыбранноеПоле.Поле;
		КонецЦикла;
	КонецЦикла;
	ПолеНабора = мСхемаКомпоновкиПар.НаборыДанных[0].Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
	ПолеНабора.Поле = мИмяПоляНеправильныйЭлемент;
	ПолеНабора.ПутьКДанным = мИмяПоляНеправильныйЭлемент;
	ирОбщий.УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(ПолеНабора, Истина);
	ПолеНабора = мСхемаКомпоновкиПар.НаборыДанных[0].Поля.Добавить(Тип("ПолеНабораДанныхСхемыКомпоновкиДанных"));
	ПолеНабора.Поле = мИмяПоляПравильныйЭлемент;
	ПолеНабора.ПутьКДанным = мИмяПоляПравильныйЭлемент;
	ирОбщий.УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(ПолеНабора, Истина);
	ВычисляемоеПоле = мСхемаКомпоновкиОбщая.ВычисляемыеПоля.Добавить();
	ВычисляемоеПоле.ПутьКДанным = мИмяПоляКоличествоЭлементов;
	ВычисляемоеПоле.Выражение = "0"; // Если этого не сделать будет ошибка 
	ВычисляемоеПоле.ТипЗначения = Новый ОписаниеТипов("Число");
	ВычисляемоеПоле.Заголовок = мПредставления[мИмяПоляКоличествоЭлементов];
	ВычисляемоеПоле.ОграничениеИспользования.Условие = Истина;
	
	ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(мСхемаКомпоновкиОбщая);
	КомпоновщикЦенности.Инициализировать(ИсточникДоступныхНастроек);
	КомпоновщикСравнения.Инициализировать(ИсточникДоступныхНастроек);
	//ПолеНабора = мСхемаКомпоновки.НаборыДанных[0].Поля.Найти(мИмяПоляНеправильныйЭлемент);
	//ирОбщий.УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(ПолеНабора, Истина, Ложь, , , Ложь);
	//ПолеНабора = мСхемаКомпоновки.НаборыДанных[0].Поля.Найти(мИмяПоляПравильныйЭлемент);
	//ирОбщий.УстановитьОграниченияИспользованияПоляНабораДанныхСхемыКомпоновкиЛкс(ПолеНабора, Истина, Ложь, , , Ложь);
	ИсточникДоступныхНастроек = Новый ИсточникДоступныхНастроекКомпоновкиДанных(мСхемаКомпоновкиПар);
	КомпоновщикПар.Инициализировать(ИсточникДоступныхНастроек);
	
	мСписокРеквизитов.Очистить();
	Для Каждого ДоступноеПоле Из КомпоновщикСравнения.Настройки.ДоступныеПоляВыбора.Элементы Цикл
		Если Ложь
			Или ирОбщий.СтрокиРавныЛкс("" + ДоступноеПоле.Поле, "Ссылка") 
			//Или ДоступноеПоле.ТипЗначения.СодержитТип(Тип("ХранилищеЗначения"))
			Или "" + ДоступноеПоле.Поле = мИмяПоляКоличествоЭлементов
			Или ДоступноеПоле.Папка
		Тогда
			Продолжить;
		КонецЕсли; 
		Если "" + ДоступноеПоле.Поле = мИмяПоляКоличествоЭлементов Тогда
			Продолжить;
		КонецЕсли; 
		мРеквизит = мСписокРеквизитов.Добавить();
		мРеквизит.Представление = ДоступноеПоле.Заголовок;
		мРеквизит.Значение = ДоступноеПоле.Поле;
	КонецЦикла; 

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

Функция ПолучитьОпределениеИсточникаДанных()
	
	Если РежимПроизвольногоЗапроса И ЗначениеЗаполнено(мПроизвольныйЗапрос.Текст) Тогда
		ТекстИсточника = "(" + мПроизвольныйЗапрос.Текст + ")";
	Иначе
		ТекстИсточника = ПолноеИмяОбъекта;
	КонецЕсли;
	Возврат ТекстИсточника;

КонецФункции

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

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

Процедура СохранитьНастройкиПоискаПоТаблице()

	НастройкиДляСохранения = ПолучитьСтруктуруНастроекПоискаДублей();
	Если ЗначениеЗаполнено(мИмяСтарогоОбъектаМД) Тогда
		НастройкиПоискаДублей.Вставить(мИмяСтарогоОбъектаМД, НастройкиДляСохранения);
	КонецЕсли; 

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

Процедура ПослеВосстановленияЗначений()
	
	ПриУстановкеПолногоИмениОбъекта();
	//НастройкиОтбора = ирОбщий.ВосстановитьЗначениеЛкс(Метаданные().ПолноеИмя() + ".ПостроительОтчетаОтбора.Настройки");
	//Если НастройкиОтбора <> Неопределено Тогда
	//	ПостроительОтчетаОтбора.УстановитьНастройки(НастройкиОтбора);
	//КонецЕсли;
	ПриИзмененииАвтовидимостьКолонокСоставаГруппы();
	Для Каждого СтрокаПравилаЗамены Из ПравилаЗаменыСсылок Цикл
		СтрокаПравилаЗамены.ПомеченоОбъектов = 0;
		СтрокаПравилаЗамены.НайденоОбъектов = 0;
	КонецЦикла;
	Если ТипЗнч(КомпоновкаСсылающихсяОбъектов) = Тип("НастройкиКомпоновкиДанных") Тогда
		КомпоновщикДопПолей.ЗагрузитьНастройки(КомпоновкаСсылающихсяОбъектов);
	КонецЕсли; 
	ЭлементыФормы.ОбработкаЗаменыДанных.УстановитьТекст(ЭтотОбъект.ОбработкаЗаменыДанных);
	мНастройкиВосстановлены = Истина;
	ОбновитьДоступность();
	
КонецПроцедуры

Процедура КоманднаяПанельНастройкиОтчетаНастройка(Кнопка)
	
	ФормаНастройки = ПолучитьФорму("ФормаНастройки");
	ЗаполнитьЗначенияСвойств(ФормаНастройки, ЭтотОбъект); 
	Если ФормаНастройки.ОткрытьМодально() = Истина Тогда
		ЗаполнитьЗначенияСвойств(ЭтотОбъект, ФормаНастройки); // Опасно
	КонецЕсли; 
	ОбновитьДоступность();
	
КонецПроцедуры

Процедура ОбновитьДоступность()
	
	ЭлементыФормы.ПанельСсылающиесяОбъекты.Страницы.ПравилаЗависимых.Доступность = ИзменятьПоляПоСвязямПараметровВыбора;
	ЭлементыФормы.ОтборПар.Доступность = Не ЗначениеЗаполнено(мПутьКДаннымПоляНечеткогоСравнения);
	ЭлементыФормы.Запрос.Доступность = РежимПроизвольногоЗапроса;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ДЕЙСТВИЯ КОМАНДНОЙ ПАНЕЛЕЙ ФОРМЫ "НастройкиОтчета"

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

Функция ЭтоПоискПоПохожимСловам()
	
	ПоискПоПохожимСловам = Ложь;
	мПоляСравнения = Новый Массив();
	Для Каждого ЭлементПорядка Из КомпоновщикСравнения.Настройки.Порядок.Элементы Цикл
		Если "" + ЭлементПорядка.Поле = мПутьКДаннымПоляНечеткогоСравнения Тогда
			ПоискПоПохожимСловам = ЭлементПорядка.Использование;
		КонецЕсли;
		Если ЭлементПорядка.Использование Тогда
			мПоляСравнения.Добавить(ЭлементПорядка);
		КонецЕсли; 
	КонецЦикла;
	Возврат ПоискПоПохожимСловам;
	
КонецФункции

Функция УстановитьПредставленияСлужебныхПолей()

	мПредставления.Вставить(мИмяПоляИдентификатор, "<Идентификатор>");
	мПредставления.Вставить(мИмяПоляКоличествоЭлементов, "<Количество элементов>");
	мПредставления.Вставить(мИмяПоляКоличествоСсылок, "<Ссылки>");
	мПредставления.Вставить(мИмяПоляНеправильныеСсылки, "<Неправильные ссылки>");
	мПредставления.Вставить(мИмяПоляНомерГруппы, "<Номер группы>");
	мПредставления.Вставить(мИмяПоляЦенность, "<Ценность данных>");
	мПредставления.Вставить(мИмяПоляПравильныйЭлемент, "<Правильный элемент>");
	мПредставления.Вставить(мИмяПоляНеправильныйЭлемент, "<Неправильный элемент>");
	мПредставления.Вставить(мИмяПоляПравильныеДанные, "<Правильные данные>");
	мПредставления.Вставить(мИмяФлагаПравильныйЭлемент, "<Правильный элемент>");
	мПредставления.Вставить(мИмяФлагаПравильныеДанные, "<Правильные данные>");
	Возврат Неопределено;

КонецФункции

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ДЕЙСТВИЯ КОМАНДНОЙ ПАНЕЛЕЙ ФОРМЫ "ЭлементыТекущейГруппы"

Процедура КоманднаяПанельЭлементыТекущейГруппыВыборПравильного(Кнопка)
	
	Если ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока = Неопределено Тогда
		Возврат;
	КонецЕсли;
	СтрокаТаблицы = ЭлементыТекущейГруппы.Найти(Истина, мИмяФлагаПравильныйЭлемент);
	Если СтрокаТаблицы <> Неопределено Тогда
		СтрокаТаблицы[мИмяФлагаПравильныйЭлемент] = Ложь;
	КонецЕсли;
	ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока[мИмяФлагаПравильныйЭлемент] = Истина;
	//ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока[мИмяФлагаПравильныеДанные] = Истина;
	СброситьДоступность();
	СохранитьТекущуюГруппуРезультатовПоиска();
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыПоискСсылок(Кнопка)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	РезультатПоиска = ЗаполнитьПравилаЗаменыСсылокПоТекущейГруппе();
	//ЭлементыФормы.Панель.Страницы.ПравилаЗаменыСсылок.Доступность = РезультатПоиска;
	Если РезультатПоиска Тогда
		ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.ПравилаЗаменыСсылок;
	КонецЕсли;
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыПоискЗависимых(Кнопка)
	
	ВремТаблица = ЭлементыТекущейГруппы.Скопировать();
	СтрокаПравильного = ВремТаблица.Найти(Истина, мИмяФлагаПравильныйЭлемент);
	Если СтрокаПравильного = Неопределено Тогда
		Предупреждение("Не определен правильный элемент");
		Возврат;
	КонецЕсли;
	
	НайденныеЗависимыеСсылки.Очистить();
	мЗависимыеМетаданные = Новый массив;
	ИмяОбъекта = ПолноеИмяОбъекта;
	Для каждого МетаданныеЗависимого Из Метаданные.Справочники Цикл
		СтрокаМетаданные = Неопределено;
		Если МетаданныеЗависимого.Владельцы.Содержит(мМетаданныеОбъекта) Тогда
			мЗависимыеМетаданные.Добавить(МетаданныеЗависимого);
		КонецЕсли; 
	КонецЦикла; 
	
	Правильный = СтрокаПравильного.Ссылка;
	ВремТаблица.Удалить(СтрокаПравильного);
	ЗависимыеОбъекты.Строки.Очистить();
	
	Для каждого МетаданныеЗависимого Из мЗависимыеМетаданные Цикл
		СтрокаМетаданные = Неопределено;
		Для каждого СтрокаНеПравильного Из ВремТаблица Цикл
			СтрокаОбъекта = Неопределено;
			НеПравильный = СтрокаНеПравильного.ссылка;
			МенеджерЗависимого = ирОбщий.ПолучитьМенеджерЛкс(МетаданныеЗависимого);
			Выборка = МенеджерЗависимого.Выбрать(,НеПравильный);
			Пока Выборка.Следующий() Цикл
				Если СтрокаМетаданные = Неопределено Тогда
					СтрокаМетаданные = ЗависимыеОбъекты.Строки.Добавить();
					СтрокаМетаданные.НеПравильный = МетаданныеЗависимого.Представление();
					СтрокаМетаданные.Правильный = МетаданныеЗависимого.Представление();
				КонецЕсли; 
				
				Если СтрокаОбъекта = Неопределено Тогда
					СтрокаОбъекта = СтрокаМетаданные.Строки.Добавить();
					СтрокаОбъекта.НеПравильный = НеПравильный;
					СтрокаОбъекта.Правильный = Правильный;
				КонецЕсли; 
				СтрокаЗависимого = СтрокаОбъекта.Строки.Добавить();
				СтрокаЗависимого.НеПравильный = Выборка.Ссылка;
				Пустой = МенеджерЗависимого.ПустаяСсылка();
				Похожий = МенеджерЗависимого.НайтиПоНаименованию(Выборка.Наименование, Ложь, , Правильный);
				Если Похожий <> Пустой Тогда
					СтрокаЗависимого.ВключатьВПоиск = Истина;
				КонецЕсли; 
				СтрокаЗависимого.Правильный = Похожий;
			КонецЦикла;
		КонецЦикла; 
		Если СтрокаМетаданные <> Неопределено Тогда
			ЭлементыФормы.ЗависимыеОбъекты.Развернуть(СтрокаМетаданные,Истина);
		КонецЕсли; 
	КонецЦикла; 
	ЭлементыФормы.Панель.Страницы.ЗависимыеЭлементы.Доступность = Истина;
	ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.ЗависимыеЭлементы;
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыАвтозамена(Кнопка)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	
	Если Ложь
		Или мРезультатыПоиска = Неопределено 
		или мРезультатыПоиска.НайтиСтроки(Новый Структура(мИмяФлагаПравильныйЭлемент,Истина)).Количество() = 0
	Тогда
		Предупреждение("Не определен правильный элемент ни в одной из групп.");
		Возврат;
	КонецЕсли;
	
	РезультатВопроса = Вопрос("При автоматической замене будет произведен поиск и замена
	|неправильных элементов, в группах, где определен правильный элемент.
	|
	|Обработать неправильные объекты, на которые не останется ссылок, после замены?", РежимДиалогаВопрос.ДаНетОтмена);
	Если РезультатВопроса = КодВозвратаДиалога.Отмена Тогда
		Возврат;
	КонецЕсли;
	
	ОбработатьНеправильные = РезультатВопроса = КодВозвратаДиалога.Да;
	Если ОбработатьНеправильные Тогда
		Ответ = Вопрос("Удалить неправильные элементы, на которые не останется ссылок, непосредственно (иначе пометить на удаление)?", РежимДиалогаВопрос.ДаНет);
		НепосредственноеУдаление = Ответ = КодВозвратаДиалога.Да;
	КонецЕсли;
	АвтозаменаЭлементов(ОбработатьНеправильные, НепосредственноеУдаление);

	ЗагрузитьГруппуРезультатовПоиска();
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ОБРАБОТЧИКИ СОБЫТИЙ ТАБЛИЧНОГО ПОЛЯ "ЭлементыТекущейГруппы"

Процедура ЭлементыТекущейГруппыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	
	ирОбщий.ТабличноеПолеПриВыводеСтрокиЛкс(Элемент, ОформлениеСтроки, ДанныеСтроки, ЭлементыФормы.КоманднаяПанельЭлементыТекущейГруппы.Кнопки.Пустые);
	Если Не ЗначениеЗаполнено(ДанныеСтроки.Ссылка) Тогда
		ОформлениеСтроки.Ячейки.Ссылка.УстановитьТекст("<Пустая ссылка>");
	КонецЕсли;
	
	Если ДанныеСтроки[мИмяПоляКоличествоСсылок] = Неопределено Тогда
		ОформлениеСтроки.Ячейки[мИмяПоляКоличествоСсылок].Текст = "?";
	КонецЕсли;
	
	//Если ДанныеСтроки[мИмяФлагаПравильныйЭлемент] <> Неопределено И ДанныеСтроки[мИмяФлагаПравильныйЭлемент] Тогда
	Если ДанныеСтроки[мИмяФлагаПравильныйЭлемент] = Истина Тогда
		ОформлениеСтроки.ЦветФона   = ЦветаСтиля.ЦветФонаФормы;
		ОформлениеСтроки.Ячейки.Ссылка.Шрифт = Новый Шрифт(,,Истина);
		
		//ИмяКолонки = ПолучитьЗначениеНастройки("Имя реквизита");
		//Если Не ИмяКолонки = Неопределено Тогда
		//	ЯчейкаРеквизита = ОформлениеСтроки.Ячейки.Найти(мПрефиксКолонокРеквизитов + ИмяКолонки);
		//	Если Не ЯчейкаРеквизита = Неопределено Тогда
		//		ЯчейкаРеквизита.Шрифт = Новый Шрифт(,,Истина);
		//	КонецЕсли;
		//КонецЕсли;
		
	КонецЕсли;
	Если ДанныеСтроки[мИмяФлагаПравильныеДанные] Тогда
		ОформлениеСтроки.ЦветТекста = WebЦвета.ТемноСиний;
	КонецЕсли; 
	
КонецПроцедуры

Процедура ОтложенноЗагрузитьРеквизиты() Экспорт
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	Если ЭлементыФормы.ЭлементыТекущейГруппы.Значение.Количество() = 0 Тогда
		Возврат;
	КонецЕсли; 
	ПоследняяСтрока = ЭлементыФормы.ЭлементыТекущейГруппы.Значение[ЭлементыФормы.ЭлементыТекущейГруппы.Значение.Количество() - 1];
	ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока = ПоследняяСтрока;
	КопияМассива = ирОбщий.СкопироватьУниверсальнуюКоллекциюЛкс(мМассивОтложеннойЗагрузкиРеквизитов);
	мМассивОтложеннойЗагрузкиРеквизитов.Очистить();
	ЗагрузитьРеквизитыЭлементовТекущейГруппы(КопияМассива);
	
КонецПроцедуры

Процедура ЭлементыТекущейГруппыПослеУдаления(Элемент)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	
КонецПроцедуры

Процедура ЭлементыТекущейГруппыОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
	
	Если ТипЗнч(ВыбранноеЗначение) <> Тип("Массив") Тогда
		Массив = ирОбщий.БыстрыйМассивЛкс(ВыбранноеЗначение);
	Иначе
		Массив = ВыбранноеЗначение;
	КонецЕсли; 
	Для Каждого ВыбранныйКлюч Из Массив Цикл
		Если ТипЗнч(ВыбранныйКлюч) = Тип(мИмяТипаСсылки) Тогда
			НоваяСтрокаНайденных = ЭлементыТекущейГруппы.Найти(ВыбранныйКлюч, "Ссылка");
			Если НоваяСтрокаНайденных = Неопределено Тогда
				Если Не ПроверитьНаличиеЭлементаПередДобавлением(ВыбранныйКлюч) Тогда
					Продолжить;;
				КонецЕсли; 
				НоваяСтрокаНайденных = ЭлементыТекущейГруппы.Добавить();
				НоваяСтрокаНайденных.Ссылка = ВыбранныйКлюч;
				НоваяСтрокаНайденных[мИмяФлагаПравильныйЭлемент] = Ложь;
				НоваяСтрокаНайденных[мИмяПоляНомерГруппы] = мТекущаяГруппа[мИмяПоляНомерГруппы];
				Если мМассивОтложеннойЗагрузкиРеквизитов = Неопределено Тогда
					мМассивОтложеннойЗагрузкиРеквизитов = Новый Массив;
				КонецЕсли; 
				Если мМассивОтложеннойЗагрузкиРеквизитов.Количество() = 0 Тогда
					ЭтаФорма.ПодключитьОбработчикОжидания("ОтложенноЗагрузитьРеквизиты", 0.1, Истина);
				КонецЕсли; 
				мМассивОтложеннойЗагрузкиРеквизитов.Добавить(ВыбранныйКлюч);
			КонецЕсли;
		КонецЕсли;
	КонецЦикла;
	
КонецПроцедуры

Функция ПроверитьНаличиеЭлементаПередДобавлением(ВыбранноеЗначение)
	
	Результат = Истина;
	НоваяСтрокаНайденных = мРезультатыПоиска.Найти(ВыбранноеЗначение, "Ссылка");
	Если НоваяСтрокаНайденных <> Неопределено Тогда
		Сообщить("Элемент """ + ВыбранноеЗначение + """ нельзя добавить в группу " + мТекущаяГруппа[мИмяПоляНомерГруппы] 
			+ ", т.к. он уже существует в группе " + НоваяСтрокаНайденных[мИмяПоляНомерГруппы]);
		Результат = Ложь;
	КонецЕсли; 
	Возврат Результат;

КонецФункции


////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ДЕЙСТВИЯ КОМАНДНОЙ ПАНЕЛЕЙ ФОРМЫ "НайденныеСсылки"

Процедура КоманднаяПанельНайденныеСсылкиВыполнитьЗамену(Кнопка)
	
	СохранитьТекущееПравилоЗамены(); 
	СоответствиеЗамен = Новый Соответствие;
	Для каждого СтрокаЗамены Из ПравилаЗаменыСсылок Цикл
		Если СтрокаЗамены.Пометка Тогда
			Если ИзменятьПоляПоСвязямПараметровВыбора Тогда
				СоответствиеЗамен.Вставить(СтрокаЗамены.ЧтоЗаменять, Новый Структура("Значение, ПравилаЗависимых", СтрокаЗамены.НаЧтоЗаменять, СтрокаЗамены.ПравилаЗависимых));
			Иначе
				СоответствиеЗамен.Вставить(СтрокаЗамены.ЧтоЗаменять, СтрокаЗамены.НаЧтоЗаменять);
			КонецЕсли; 
		КонецЕсли;
		СтрокаЗамены.ПравилаЗависимых.ЗаполнитьЗначения(0, "НайденоСтрок");
		СтрокаЗамены.ПравилаЗависимых.ЗаполнитьЗначения(Ложь, "Требуется");
	КонецЦикла;
	
	ВыполнитьЗаменуЭлементов(СоответствиеЗамен, ЭтотОбъект.НайденныеСсылки.Выгрузить(Новый Структура("Пометка", Истина)));
	Если ИзмененныеПроведенныеДокументы.Количество() > 0 Тогда
		Ответ = Вопрос("В процессе замены были модифицированы проведенные документы. В большинстве случаев их перепроведение не требуется.
			|Хотите открыть форму просмотра их списка с возможностью перепроведения?",
			РежимДиалогаВопрос.ДаНет);
		Если Ответ = КодВозвратаДиалога.Да Тогда
			ФормаПерепроведения = ПолучитьФорму("ФормаПерепроведенияДокументов", , Новый УникальныйИдентификатор);
			ТаблицаДокументов = ИзмененныеПроведенныеДокументы.Выгрузить();
			ТаблицаДокументов.Сортировать("ДатаДокумента");
			ФормаПерепроведения.ТаблицаДокументов = ТаблицаДокументов;
			ФормаПерепроведения.Открыть();
		КонецЕсли;
	КонецЕсли; 
	//ЗаполнитьПравилаЗаменыСсылокПоТекущейГруппе();
	ВыполнитьПоискЗаменяемыхСсылок();
	ЕстьТребующиеНастройкиПравила = Ложь;
	Для каждого СтрокаЗамены Из ПравилаЗаменыСсылок Цикл
		ЕстьТребующиеНастройкиПравила = ОбновитьКоличествоЗависимыхПравилаЗаменыСсылок(СтрокаЗамены) Или ЕстьТребующиеНастройкиПравила;
	КонецЦикла;
	Если ЕстьТребующиеНастройкиПравила Тогда
		Сообщить("Имеются правила замены зависимых, требующие настройки и включения!");
	КонецЕсли; 
	ЗагрузитьТекущееПравилоЗамены();
	
КонецПроцедуры

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

Функция УдалитьНеправильнуюСсылкуВФорме(УдаляемаяСсылка, НепосредственноеУдаление, СтрокаНеправильного = Неопределено, СтрокаГруппы = Неопределено,
	Знач СсылкаДляЗаменыДанных = Неопределено)

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

КонецФункции

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ОБРАБОТЧИКИ СОБЫТИЙ ТАБЛИЧНОГО ПОЛЯ "НайденныеСсылки"

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

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

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ДЕЙСТВИЯ КОМАНДНОЙ ПАНЕЛЕЙ ФОРМЫ "ЗависимыеОбъекты"

Процедура КоманднаяПанельЗависимыеОбъектыПоискСсылок(Кнопка)
	ПоискЗависимыхСсылок();
	ЭлементыФормы.КоманднаяПанельЗависимыеОбъекты.Кнопки.ВыполнитьЗамену.Доступность = Истина;
КонецПроцедуры

Процедура КоманднаяПанельЗависимыеОбъектыВыполнитьЗамену(Кнопка)
	
	СтруктураОтбора = Новый Структура;
	МассивСтрокВключенныхВПоиск = ЗависимыеОбъекты.Строки.НайтиСтроки(Новый Структура("ВключатьВПоиск", Истина), Истина);
	
	НомерСтроки = 0;
	Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(МассивСтрокВключенныхВПоиск.Количество(), "Правила замены");
	Для каждого Строка Из МассивСтрокВключенныхВПоиск Цикл
		ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
		СтруктураОтбора.Вставить("Ссылка", Строка.НеПравильный);
		СтруктураОтбора.Вставить("Пометка", Истина); //НайденныеЗависимыеСсылки с флагами
		СоответствиеЗамен = Новый Соответствие;
		СоответствиеЗамен.Вставить(Строка.НеПравильный, Строка.Правильный);
		ТаблицаЗависимыхЭлементов = НайденныеЗависимыеСсылки.Скопировать(СтруктураОтбора);
		ВыполнитьЗаменуЭлементов(СоответствиеЗамен, ТаблицаЗависимыхЭлементов);
	КонецЦикла;
	ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
	ПоискЗависимыхСсылок();
	
КонецПроцедуры

Процедура КоманднаяПанельЗависимыеОбъектыУдалитьЭлементы(Кнопка)
	
	Если НайденныеЗависимыеСсылки.Количество() > 0 Тогда
		Предупреждение("На элементы есть ссылки");
		Возврат;
	КонецЕсли;
	
	Ответ = Вопрос("Удалить неправильные элементы непосредственно (иначе пометить на удаление)?", РежимДиалогаВопрос.ДаНетОтмена);
	Если Ответ = КодВозвратаДиалога.Отмена Тогда
		Возврат;
	КонецЕсли;
	НепосредственноеУдаление = Ответ = КодВозвратаДиалога.Да;
	
	БылиИсключения = Ложь;
	ЕСли ОбщаяТранзакция Тогда
		НачатьТранзакцию();
	КонецЕсли;
	СтрокиКУдалению = Новый ТаблицаЗначений;
	СтрокиКУдалению.Колонки.Добавить("СтрокаТаблицы");
	СтрокиКУдалению.Колонки.Добавить("ТаблицаЗначений");
	Для каждого Строка0 Из ЗависимыеОбъекты.Строки Цикл
		Для каждого Строка1 Из Строка0.Строки Цикл
			Для каждого Строка2 Из Строка1.Строки Цикл
				Если Строка2.ВключатьВПоиск Тогда
					Объект = Строка2.НеПравильный.ПолучитьОбъект();
					Попытка
						Если НепосредственноеУдаление Тогда
							ирОбщий.УдалитьОбъектЛкс(Объект);
						Иначе
							ирОбщий.УстановитьПометкуУдаленияОбъектаЛкс(Объект,, Истина);
						КонецЕсли; 
					Исключение
						Сообщить("Обработка """ + Объект + """: " + ОписаниеОшибки());
						Если ОбщаяТранзакция Тогда
							БылиИсключения = Истина;
							Прервать;
						КонецЕсли;
					КонецПопытки;
					Если НепосредственноеУдаление Тогда
						НовСтр = СтрокиКУдалению.Добавить();
						НовСтр.СтрокаТаблицы = Строка2;
						//НовСтр.ТаблицаЗначений = ЗависимыеОбъекты;
						НовСтр.ТаблицаЗначений = Строка1;
					КонецЕсли; 
				КонецЕсли; 
			КонецЦикла; 
		КонецЦикла; 
	КонецЦикла; 
	
	Если ОбщаяТранзакция Тогда
		Если БылиИсключения Тогда
			ОтменитьТранзакцию();
		Иначе
			ЗафиксироватьТранзакцию();
		КонецЕсли;
	КонецЕсли;	
	Если НепосредственноеУдаление Тогда
		Если НЕ БылиИсключения Тогда
			Для Каждого СтрокаКУдалению ИЗ СтрокиКУдалению Цикл
				СтрокаКУдалению.ТаблицаЗначений.Строки.Удалить(СтрокаКУдалению.СтрокаТаблицы);
			КонецЦикла;
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ОБРАБОТЧИКИ СОБЫТИЙ ТАБЛИЧНОГО ПОЛЯ "НайденныеЗависимыеСсылки"

Процедура НайденныеЗависимыеСсылкиПередНачаломИзменения(Элемент, Отказ)
	Если НЕ Элемент.ТекущаяКолонка.Имя = "Пометка" Тогда //НайденныеЗависимыеСсылки с флагами
	
	Данные = Элемент.ТекущиеДанные.Данные;
	ирОбщий.ОткрытьСсылкуИзРезультатаПоискаСсылокЛкс(Данные, Элемент.ТекущиеДанные.Метаданные.ПолноеИмя());
	Отказ = Истина;
	КонецЕсли;

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

////////////////////////////////////////////////////////////////////////////////
// ПРОЦЕДУРЫ - ОБРАБОТЧИКИ СОБЫТИЙ ТАБЛИЧНОГО ПОЛЯ "ЗависимыеОбъекты"

Процедура ЗависимыеОбъектыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	ОформлениеСтроки.Ячейки.ВключатьВПоиск.ОтображатьТекст = Ложь;
	Если ДанныеСтроки.Уровень() = 1  Тогда
		ОформлениеСтроки.ЦветФона   = ЦветаСтиля.ЦветФонаФормы;
		ОформлениеСтроки.ЦветТекста = WebЦвета.ТемноСиний;
		ОформлениеСтроки.Ячейки.ВключатьВПоиск.ОтображатьФлажок = Ложь;
	ИначеЕсли ДанныеСтроки.Уровень() = 0  Тогда
		ОформлениеСтроки.ЦветФона   = ЦветаСтиля.ЦветФонаФормы;
		ОформлениеСтроки.ЦветТекста = WebЦвета.ТемноСиний;
		ОформлениеСтроки.Шрифт = Новый Шрифт(,,Истина);
		ОформлениеСтроки.Ячейки.ВключатьВПоиск.ОтображатьФлажок = Ложь;
	Иначе
//		ОформлениеСтроки.Ячейки.ВключатьВПоиск.ОтображатьФлажок = Истина;
	КонецЕсли; 
КонецПроцедуры

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

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

Процедура КоманднаяПанельНайденныеГруппыАвтоопределениеПравильныхДанных(Кнопка)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	ЗаполнитьПризнакПравильногоПоЦенности(мИмяФлагаПравильныеДанные, мИмяПоляПравильныеДанные);
	ЗагрузитьГруппуРезультатовПоиска();
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыПредыдущаяГруппа(Кнопка)
	
	Если мТекущаяГруппа = НайденныеГруппы[0] Тогда
		Возврат;
	КонецЕсли;
	СохранитьТекущуюГруппуРезультатовПоиска();
	
	мТекущаяГруппа = НайденныеГруппы[НайденныеГруппы.Индекс(мТекущаяГруппа) - 1];
	ЗагрузитьГруппуРезультатовПоиска();
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыСледующаяГруппа(Кнопка)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	Если мТекущаяГруппа = НайденныеГруппы[НайденныеГруппы.Количество() - 1] Тогда
		Возврат;
	КонецЕсли;
	мТекущаяГруппа = НайденныеГруппы[НайденныеГруппы.Индекс(мТекущаяГруппа) + 1];
	ЗагрузитьГруппуРезультатовПоиска();
	
КонецПроцедуры

Процедура ПередСохранениемЗначений(Отказ)
	
	СохранитьНастройкиПоискаПоТаблице();
	ЭтотОбъект.КомпоновкаСсылающихсяОбъектов = КомпоновщикДопПолей.Настройки;
	ЭтотОбъект.ОбработкаЗаменыДанных = ЭлементыФормы.ОбработкаЗаменыДанных.ПолучитьТекст();
	//ирОбщий.СохранитьЗначениеЛкс(Метаданные().ПолноеИмя() + ".ПостроительОтчетаОтбора.Настройки", ПостроительОтчетаОтбора.ПолучитьНастройки());
	
КонецПроцедуры

Процедура ПолноеИмяОбъектаНачалоВыбора(Элемент, СтандартнаяОбработка)
	
	Форма = мПлатформа.ПолучитьФорму("ВыборОбъектаМетаданных", Элемент, ЭтаФорма);

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

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

Процедура НастройкаСравненияПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	
	ИмяПоля = "" + ДанныеСтроки.Поле;
	Если ИмяПоля = мПутьКДаннымПоляНечеткогоСравнения Тогда
		ОформлениеСтроки.ЦветФона = WebЦвета.Аквамарин;
		ОформлениеСтроки.Ячейки.ТипСравнения.УстановитьТекст("По похожим словам");
	Иначе
		Если Не ИмяПоля = мИмяПоляКоличествоЭлементов Тогда
			ОформлениеСтроки.Ячейки.ТипСравнения.УстановитьТекст("По равному значению реквизита");
		КонецЕсли;
	КонецЕсли;
	
КонецПроцедуры

Процедура КоманднаяПанельНастройкиОтчетаСравниватьПоПохожимСловам(Кнопка)
	
	ДанныеНастройки = ЭлементыФормы.НастройкаСравнения.ТекущиеДанные;
	Если ДанныеНастройки <> Неопределено Тогда
		Если мПутьКДаннымПоляНечеткогоСравнения = "" + ДанныеНастройки.Поле Тогда
			мПутьКДаннымПоляНечеткогоСравнения = "";
		Иначе
			ДоступноеПоле = КомпоновщикСравнения.Настройки.ДоступныеПоляПорядка.НайтиПоле(ДанныеНастройки.Поле);
			ЛиСтроковыйТип = ДоступноеПоле.ТипЗначения.СодержитТип(Тип("Строка"));
			Если ЛиСтроковыйТип Тогда
				мПутьКДаннымПоляНечеткогоСравнения = "" + ДанныеНастройки.Поле;
			КонецЕсли;
		КонецЕсли;
	КонецЕсли;
	ЭлементыФормы.НастройкаСравнения.ОбновитьСтроки();
	ОбновитьДоступность();
	
КонецПроцедуры

Процедура ПолноеИмяОбъектаОчистка(Элемент, СтандартнаяОбработка)
	
	Элемент.Значение = "";
	ПриУстановкеПолногоИмениОбъекта();
	
КонецПроцедуры

Процедура НастройкаСравненияПередОкончаниемРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования, Отказ)
	
	Если Не ОтменаРедактирования Тогда
		Если "" + Элемент.ТекущаяСтрока.Поле = "" Тогда
			Элемент.Значение.Элементы.Удалить(Элемент.ТекущаяСтрока);
		КонецЕсли;
	КонецЕсли; 
	
КонецПроцедуры

Процедура НайденныеГруппыВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	//Если ВыбраннаяСтрока <> Неопределено Тогда
		ЗначениеЯчейки = ВыбраннаяСтрока[Колонка.Имя];
		КорневойТипЗначения = ирОбщий.ПолучитьКорневойТипКонфигурацииЛкс(ЗначениеЯчейки);
		Если КорневойТипЗначения <> Неопределено Тогда
			ОткрытьЗначение(ЗначениеЯчейки);
		КонецЕсли;
	//КонецЕсли;
	
КонецПроцедуры

Процедура НайденныеГруппыПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	
	Если ДанныеСтроки = мТекущаяГруппа Тогда
		ОформлениеСтроки.ЦветФона = Новый Цвет(255, 200, 200);
	КонецЕсли;
	
КонецПроцедуры

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

Процедура ОбновитьКоличествоСсылокНайденныхГрупп()
	
	НайденныеГруппы.ЗаполнитьЗначения(Неопределено, мИмяПоляНеправильныеСсылки);
	Для каждого СтрокаЭлемента Из мРезультатыПоиска Цикл
		КоличествоСсылокНаЭлемент = СтрокаЭлемента[мИмяПоляКоличествоСсылок];
		Если Ложь
			Или КоличествоСсылокНаЭлемент = Неопределено
			Или СтрокаЭлемента[мИмяФлагаПравильныйЭлемент] 
		Тогда
			Продолжить;
		КонецЕсли; 
		СтрокаГруппы = НайденныеГруппы.Найти(СтрокаЭлемента[мИмяПоляНомерГруппы], мИмяПоляНомерГруппы);
		СтрокаГруппы[мИмяПоляНеправильныеСсылки] = ?(СтрокаГруппы[мИмяПоляНеправильныеСсылки] = Неопределено, 0, СтрокаГруппы[мИмяПоляНеправильныеСсылки]) + КоличествоСсылокНаЭлемент;
	КонецЦикла;

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

Процедура КоманднаяПанельНайденныеГруппыАвтоопределениеПравильныхЭлементов(Кнопка)

	Ответ = Вопрос("Хотите выбрать правильными элементы с максимальным числом ссылок (Да) или с максимальной ценностью данных (Нет)?", РежимДиалогаВопрос.ДаНет, , КодВозвратаДиалога.Да);
	СохранитьТекущуюГруппуРезультатовПоиска();
	Если Ответ = КодВозвратаДиалога.Да Тогда
		ОпределитьПравильныеЭлементы();
	Иначе
		ЗаполнитьПризнакПравильногоПоЦенности(мИмяФлагаПравильныйЭлемент, мИмяПоляПравильныйЭлемент);
	КонецЕсли;
	ЗагрузитьГруппуРезультатовПоиска();

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

Процедура ЗаполнитьПризнакПравильногоПоЦенности(ИмяКолонкиПризнака, ИмяКолонкиЗначения)
	
	мРезультатыПоиска.ЗаполнитьЗначения(Ложь, ИмяКолонкиПризнака);
	мРезультатыПоиска.Сортировать(мИмяПоляНомерГруппы + "," + мИмяПоляЦенность + "," + ИмяКолонкиПризнака + " Убыв");
	НайденныеГруппы.ЗаполнитьЗначения(Неопределено, ИмяКолонкиЗначения);
	Для каждого СтрокаЭлемента Из мРезультатыПоиска Цикл
		СтрокаГруппы = НайденныеГруппы.Найти(СтрокаЭлемента[мИмяПоляНомерГруппы], мИмяПоляНомерГруппы);
		Если ЗначениеЗаполнено(СтрокаГруппы[ИмяКолонкиЗначения]) Тогда
			Продолжить;
		КонецЕсли; 
		СтрокаГруппы[ИмяКолонкиЗначения] = СтрокаЭлемента.Ссылка;
		СтрокаЭлемента[ИмяКолонкиПризнака] = Истина;
	КонецЦикла;
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыАвтоопределениеПравильных(Кнопка)
	// Вставить содержимое обработчика.
КонецПроцедуры

Процедура НайденныеГруппыПередУдалением(Элемент, Отказ)
	
	Если Элемент.ТекущаяСтрока = Неопределено Тогда
		Возврат;
	КонецЕсли;
	СоставТекущейГруппы = мРезультатыПоиска.НайтиСтроки(Новый Структура(мИмяПоляНомерГруппы, Элемент.ТекущаяСтрока[мИмяПоляНомерГруппы]));
	Для Каждого СтрокаВнутриТекущейГруппы Из СоставТекущейГруппы Цикл
		мРезультатыПоиска.Удалить(СтрокаВнутриТекущейГруппы);
	КонецЦикла;
	Если Элемент.ТекущаяСтрока = мТекущаяГруппа Тогда
		мТекущаяГруппа = Неопределено;
	КонецЕсли;
	
КонецПроцедуры

Процедура НайденныеГруппыПередНачаломДобавления(Элемент, Отказ, Копирование)
	
	Если Копирование Тогда
		Отказ = Истина;
	КонецЕсли;
	
КонецПроцедуры

Процедура ОбновитьРамкуГруппыНайденныеГруппы()

	ирОбщий.ОбновитьТекстПослеМаркераВСтрокеЛкс(ЭлементыФормы.РамкаГруппыНайденныеГруппы.Заголовок, ,
		Строка(НайденныеГруппы.Количество()) + ")", "(");

КонецПроцедуры // ОбновитьРамкуГруппыНайденныеГруппы()

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

Процедура НайденныеГруппыПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
	
	Если Не ОтменаРедактирования Тогда
		Если НоваяСтрока Тогда
			ПриДобавленииНовойГруппы();
		КонецЕсли; 
		ЗагрузитьГруппуРезультатовПоиска(Элемент.ТекущаяСтрока);
	КонецЕсли; 

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

Процедура ЗависимыеОбъектыПриАктивизацииСтроки(Элемент)
	
	Элемент.Колонки.Правильный.ЭлементУправления.КнопкаВыбора = (Элемент.ТекущаяСтрока.Уровень() = 2);
	Элемент.Колонки.Правильный.ТолькоПросмотр   = (Элемент.ТекущаяСтрока.Уровень() = 0);
	Элемент.Колонки.НеПравильный.ТолькоПросмотр = (Элемент.ТекущаяСтрока.Уровень() = 0);
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыДобавитьПустуюСсылку(Кнопка)

	ВыбранноеЗначение = ирОбщий.ПолучитьМенеджерЛкс(мМетаданныеОбъекта).ПустаяСсылка();
	НоваяСтрокаНайденных = ЭлементыТекущейГруппы.Найти(ВыбранноеЗначение, "Ссылка");
	Если НоваяСтрокаНайденных = Неопределено Тогда
		Если Не ПроверитьНаличиеЭлементаПередДобавлением(ВыбранноеЗначение) Тогда
			Возврат;
		КонецЕсли; 
		НоваяСтрокаНайденных = ЭлементыТекущейГруппы.Добавить();
		НоваяСтрокаНайденных.Ссылка = ВыбранноеЗначение;
		НоваяСтрокаНайденных[мИмяФлагаПравильныйЭлемент] = Ложь;
		НоваяСтрокаНайденных[мИмяПоляНомерГруппы] = мТекущаяГруппа[мИмяПоляНомерГруппы];
		ОбновитьСтрокуРезультатовПоиска(НоваяСтрокаНайденных);
		СохранитьТекущуюГруппуРезультатовПоиска();
	КонецЕсли; 
	ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока = НоваяСтрокаНайденных;
		
КонецПроцедуры

Процедура ЭлементыТекущейГруппыВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	Если ЗначениеЗаполнено(ВыбраннаяСтрока.Ссылка) Тогда
		ОткрытьЗначение(ВыбраннаяСтрока.Ссылка);
	КонецЕсли;
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыШиринаКолонок(Кнопка)
	
	ирОбщий.РасширитьКолонкиТабличногоПоляЛкс(ЭлементыФормы.НайденныеГруппы);
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыСжатьКолонки(Кнопка)
	
	ирОбщий.СжатьКолонкиТабличногоПоляЛкс(ЭлементыФормы.НайденныеГруппы);
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыСжатьКолонки(Кнопка)
	
	ирОбщий.СжатьКолонкиТабличногоПоляЛкс(ЭлементыФормы.ЭлементыТекущейГруппы);
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыШиринаКолонок(Кнопка)
	
	ирОбщий.РасширитьКолонкиТабличногоПоляЛкс(ЭлементыФормы.ЭлементыТекущейГруппы);

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

Процедура НайденныеГруппыПослеУдаления(Элемент)
	
	ОбновитьРамкуГруппыНайденныеГруппы();
	//Если мТекущаяГруппа = Неопределено Тогда
	//	ВывестиГруппу(Элемент.ТекущаяСтрока);
	//КонецЕсли;
	
КонецПроцедуры

Процедура КоманднаяПанельОПодсистеме(Кнопка)
	ирОбщий.ОткрытьСправкуПоПодсистемеЛкс(ЭтотОбъект);
КонецПроцедуры

Процедура ГлавнаяКоманднаяПанельНовоеОкно(Кнопка)
	
	ирОбщий.ОткрытьНовоеОкноОбработкиЛкс(ЭтотОбъект);
	
КонецПроцедуры

Процедура ОбновлениеОтображения()
	
	ирОбщий.ОбновитьЗаголовкиСтраницПанелейЛкс(ЭтаФорма);
	ОбновитьДоступностьКнопокВпередНазадНайденныхГрупп();
	ЭлементыФормы.ОтборУровняЦенности.Доступность = мТекущаяСтрокаУровняЦенности <> Неопределено;
	СохранитьОтборТекущегоУровняЦенности();
	
КонецПроцедуры

Процедура ОтборЗначениеОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	
	ирОбщий.ПолеВвода_ОкончаниеВводаТекстаЛкс(Элемент, Текст, Значение, СтандартнаяОбработка);
	
КонецПроцедуры

Процедура ОбновитьСчетчикиПравилЗамены()

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

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

Процедура ВыполнитьПоискЗаменяемыхСсылок(ЗаватьВопрос = Истина)

	ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.ПравилаЗаменыСсылок;
	Если ЗаватьВопрос Тогда
		Ответ = Вопрос("Хотите выполнить поиск ссылающихся объектов?", РежимДиалогаВопрос.ДаНет, , КодВозвратаДиалога.Нет);
		Если Ответ = КодВозвратаДиалога.Нет Тогда
			Возврат;
		КонецЕсли; 
	КонецЕсли; 
	Для Каждого СтрокаПравила Из ПравилаЗаменыСсылок Цикл
		Если Ложь
			Или СтрокаПравила.ЧтоЗаменять = Неопределено
			Или ТипЗнч(СтрокаПравила.ЧтоЗаменять) = Тип("Строка") 
		Тогда
			СтрокаПравила.Пометка = Ложь;
		КонецЕсли; 
	КонецЦикла; 
	КопияЗамен = ПравилаЗаменыСсылок.Скопировать(Новый Структура("Пометка", Истина));
	МассивЗаменяемых = КопияЗамен.ВыгрузитьКолонку("ЧтоЗаменять");
	
	МассивНеуникальных = ирОбщий.ПолучитьНеуникальныеЗначенияКолонкиТаблицыЛкс(КопияЗамен, "ЧтоЗаменять");
	Для Каждого НеуникальноеЗначение Из МассивНеуникальных Цикл
		Сообщить("Заменяемая ссылка """ + НеуникальноеЗначение + """ встречается более одного раза в выбранных правилах", СтатусСообщения.Внимание);
	КонецЦикла; 
	Если МассивНеуникальных.Количество() > 0 Тогда
		Возврат;
	КонецЕсли; 
	Если МассивЗаменяемых.Количество() = 0 Тогда
		Предупреждение("Не выбрано ни одного правила замены!");
		Возврат;
	КонецЕсли;
	
	#Если Сервер И Не Сервер Тогда
	    мОбработкаПоискаСсылок = Обработки.ирРедакторОбъектаБД.Создать();
	#КонецЕсли
	мОбработкаПоискаСсылок.ОбновитьНайденныеСсылки(МассивЗаменяемых);
	ЭтотОбъект.НайденныеСсылки.Загрузить(мОбработкаПоискаСсылок.СсылкиНаОбъект.Выгрузить());
	ЭтаФорма.КоличествоНайденныхСсылок = ЭтотОбъект.НайденныеСсылки.Количество();
	ОбновитьСчетчикиПравилЗамены();
	ирОбщий.ОбновитьДоступныеПоляДляДополнительныхПолейЛкс(ЭтотОбъект.НайденныеСсылки, КомпоновщикДопПолей, ЭлементыФормы.ДоступныеПоляДополнительныхПолей);
	ПрочитатьДополнительныеПоляСсылающихсяОбъектов(); // Это надо делать в самом конце, чтобы пользователь мог прервать этот долгий процесс

КонецПроцедуры // ВыполнитьПоискЗаменяемыхСсылок()

Функция ПрочитатьДополнительныеПоляСсылающихсяОбъектов() Экспорт
	
	СтрокаПорядка = ирОбщий.ПрочитатьДополнительныеПоляСсылающихсяОбъектовЛкс(ЭлементыФормы.НайденныеСсылки, КомпоновщикДопПолей);
	НайденныеСсылки.Сортировать(СтрокаПорядка);
	
КонецФункции

Процедура КоманднаяПанельЗаменаСсылокПоискСсылок(Кнопка)
	
	ВыполнитьПоискЗаменяемыхСсылок(Ложь);

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

Процедура КоманднаяПанельНайденныеСсылкиВключитьВсе(Кнопка)
	
	ирОбщий.ИзменитьПометкиВыделенныхСтрокЛкс(ЭлементыФормы.НайденныеСсылки, , Истина,,, Ложь);
	ОбновитьСчетчикиПравилЗамены();
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеСсылкиВыключитьВсе(Кнопка)
	
	ирОбщий.ИзменитьПометкиВыделенныхСтрокЛкс(ЭлементыФормы.НайденныеСсылки, , Ложь,,, Ложь);
	ОбновитьСчетчикиПравилЗамены();

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

Процедура ЗаменыСсылокПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)

	Если НоваяСтрока И Не Копирование Тогда
		Элемент.ТекущаяСтрока.Пометка = Истина;
		Если ЗначениеЗаполнено(ПолноеИмяОбъекта) Тогда
			Элемент.ТекущаяСтрока.ЧтоЗаменять = Новый (ирОбщий.ИмяТипаИзПолногоИмениМДЛкс(ПолноеИмяОбъекта));
			Элемент.ТекущаяСтрока.НаЧтоЗаменять = Новый (ирОбщий.ИмяТипаИзПолногоИмениМДЛкс(ПолноеИмяОбъекта));
		КонецЕсли; 
	КонецЕсли;
	
КонецПроцедуры

Процедура КоманднаяПанельЗаменаСсылокПереставить(Кнопка)
	
	СохранитьТекущееПравилоЗамены();
	Для Каждого СтрокаЗамены Из ЭлементыФормы.ПравилаЗаменыСсылок.ВыделенныеСтроки Цикл
		Буфер = СтрокаЗамены.ЧтоЗаменять;
		СтрокаЗамены.ЧтоЗаменять = СтрокаЗамены.НаЧтоЗаменять;
		СтрокаЗамены.НаЧтоЗаменять = Буфер;
		СтрокаЗамены.ЗаменитьДанныеОбъекта = Ложь;
		Для Каждого СтрокаЗависимого Из СтрокаЗамены.ПравилаЗависимых Цикл
			Буфер = СтрокаЗависимого.ЧтоЗаменять;
			СтрокаЗависимого.ЧтоЗаменять = СтрокаЗависимого.НаЧтоЗаменять;
			СтрокаЗависимого.НаЧтоЗаменять = Буфер;
			Буфер = СтрокаЗависимого.ВлияющееЧтоЗаменять;
			СтрокаЗависимого.ВлияющееЧтоЗаменять = СтрокаЗависимого.ВлияющееНаЧтоЗаменять;
			СтрокаЗависимого.ВлияющееНаЧтоЗаменять = Буфер;
		КонецЦикла; 
	КонецЦикла; 
	ЗагрузитьТекущееПравилоЗамены();
	
КонецПроцедуры

Процедура ЗаменыСсылокПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	
	ирОбщий.ТабличноеПолеПриВыводеСтрокиЛкс(Элемент, ОформлениеСтроки, ДанныеСтроки, ЭлементыФормы.КоманднаяПанельЗаменаСсылок.Кнопки.Идентификаторы);
	Если ТипЗнч(ДанныеСтроки.ЧтоЗаменять) <> ТипЗнч(ДанныеСтроки.НаЧтоЗаменять) Тогда
		ОформлениеСтроки.Ячейки.Комментарий.УстановитьТекст("Типы ссылок отличаются! Замены в некоторых местах могут быть невозможны");
		ОформлениеСтроки.Ячейки.Комментарий.ЦветФона = WebЦвета.Розовый;
	КонецЕсли; 

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

Процедура ЗаменыСсылокЧтоЗаменятьПриИзменении(Элемент)
	
	ТекущиеДанные = ЭлементыФормы.ПравилаЗаменыСсылок.ТекущиеДанные;
	Если Истина
		И ТекущиеДанные.НаЧтоЗаменять = Неопределено 
		И Элемент.Значение <> Неопределено
		И ЗначениеЗаполнено(Элемент.Значение) 
	Тогда
		ТекущиеДанные.НаЧтоЗаменять = Новый (ТипЗнч(Элемент.Значение));
	КонецЕсли; 
	ТекущиеДанные.НайденоОбъектов = 0;
	ТекущиеДанные.ПомеченоОбъектов = 0;
	ОбновитьСписокВыбораПутиКДаннымВлияющего();
	ОбновитьВлияющееЗависимогоЗначения();

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

Процедура ЗаменыСсылокЧтоЗаменятьОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	
	ирОбщий.ПолеВвода_ОкончаниеВводаТекстаЛкс(Элемент, Текст, Значение, СтандартнаяОбработка, , Истина);
	
КонецПроцедуры

Процедура НайденныеСсылкиВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	Если ТипЗнч(Элемент.ТекущиеДанные.Данные) = Тип("Строка") Тогда 
		СсылающийсяОбъект = ЗначениеИзСтрокиВнутр(Элемент.ТекущиеДанные.Данные);
	Иначе
		СсылающийсяОбъект = Элемент.ТекущиеДанные.Данные;
	КонецЕсли;
	ирОбщий.ОткрытьСсылкуИзРезультатаПоискаСсылокЛкс(СсылающийсяОбъект, ВыбраннаяСтрока.Метаданные);

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

Процедура КоманднаяПанельНайденныеСсылкиОтобратьПоТипам(Кнопка)
	
	ирОбщий.ИзменитьОтборКлиентаПоМетаданнымЛкс(ЭлементыФормы.НайденныеСсылки);
	ОбновитьСчетчикиПравилЗамены();
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеСсылкиВключитьПоПериоду(Кнопка)
	
	НачалоПериода = НачалоГода(ТекущаяДата());
	КонецПериода = КонецГода(ТекущаяДата());
	НастройкаПериода = Новый НастройкаПериода;
	НастройкаПериода.УстановитьПериод(НачалоПериода, ?(КонецПериода='0001-01-01', КонецПериода, КонецДня(КонецПериода)));
	НастройкаПериода.РедактироватьКакИнтервал = Истина;
	НастройкаПериода.РедактироватьКакПериод = Истина;
	НастройкаПериода.ВариантНастройки = ВариантНастройкиПериода.Период;
	Если НастройкаПериода.Редактировать() Тогда
		НачалоПериода = НастройкаПериода.ПолучитьДатуНачала();
		КонецПериода = НастройкаПериода.ПолучитьДатуОкончания();
		КонецПериода = ?(КонецПериода = Дата(1,1,1), КонецГода(ТекущаяДата()), КонецПериода);
		Для Каждого СтрокаОбъекта Из ЭтотОбъект.НайденныеСсылки Цикл
			Если Истина
				И СтрокаОбъекта.Дата >= НачалоПериода
				И СтрокаОбъекта.Дата <= КонецПериода
			Тогда
				СтрокаОбъекта.Пометка = Истина;
			КонецЕсли; 
		КонецЦикла; 
	КонецЕсли; 
	ОбновитьСчетчикиПравилЗамены();
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеСсылкиРедакторОбъектаБД(Кнопка)
	
	ТекущаяСтрока = ЭлементыФормы.НайденныеСсылки.ТекущаяСтрока;
	Если ТекущаяСтрока = Неопределено Тогда
		Возврат;
	КонецЕсли;
	#Если Сервер И Не Сервер Тогда
	    мОбработкаПоискаСсылок = обработки.ирРедакторОбъектаБД.Создать();
	#КонецЕсли
	мОбработкаПоискаСсылок.ОткрытьСсылающийсяОбъектВРедактореОбъектаБД(ТекущаяСтрока);
	
КонецПроцедуры

Процедура НайденныеСсылкиПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	
	ирОбщий.ОтобразитьПустыеЗначенияВЯчейкахТабличногоПоля(ОформлениеСтроки, "Ссылка");
	ирОбщий.НайденныеСтандартноСсылкиПриВыводеСтрокиЛкс(ОформлениеСтроки);
	Ячейки = ОформлениеСтроки.Ячейки;
	Ячейки.ИндексКартинки.ОтображатьКартинку = Истина;
	Если ДанныеСтроки.ИндексКартинки > -1 Тогда 
		Ячейки.ИндексКартинки.ИндексКартинки = ДанныеСтроки.ИндексКартинки;
	КонецЕсли;

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

Процедура ЗаменыСсылокПриАктивизацииСтроки(Элемент)
	
	СохранитьТекущееПравилоЗамены();
	Если мОтборТекущемуПоПравилу Тогда
		ОбновитьОтборПоТекущемуПравилу();
	КонецЕсли;
	мТекущееПравило = ЗагрузитьТекущееПравилоЗамены();
	ОбновитьСписокВыбораПутиКДаннымВлияющего();
	
КонецПроцедуры

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

КонецФункции

Процедура СохранитьТекущееПравилоЗамены()
	
	Если мТекущееПравило <> Неопределено Тогда
		Если ПравилаЗаменыСсылок.Индекс(мТекущееПравило) >= 0 Тогда
			мТекущееПравило.ПравилаЗависимых = ПравилаЗависимых.Скопировать();
			ОбновитьКоличествоЗависимыхПравилаЗаменыСсылок(мТекущееПравило);
		КонецЕсли; 
	КонецЕсли;

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

Функция ОбновитьКоличествоЗависимыхПравилаЗаменыСсылок(ТекущееПравило)
	
	ТекущееПравило.КоличествоПравилЗависимыхВсего = ТекущееПравило.ПравилаЗависимых.Количество(); 
	ТекущееПравило.КоличествоПравилЗависимыхНастроить = ТекущееПравило.ПравилаЗависимых.НайтиСтроки(Новый Структура("Пометка, Требуется", Ложь, Истина)).Количество();
	Возврат ТекущееПравило.КоличествоПравилЗависимыхНастроить > 0;

КонецФункции

Процедура ОбновитьСписокВыбораПутиКДаннымВлияющего()

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

Процедура ОбновитьОтборПоТекущемуПравилу()

	ТекущееПравило = ЭлементыФормы.ПравилаЗаменыСсылок.ТекущаяСтрока;
	Если ТекущееПравило <> Неопределено Тогда
		ЗначениеОтбора = ТекущееПравило.ЧтоЗаменять;
	Иначе
		ЗначениеОтбора = Неопределено;
	КонецЕсли; 
	ЭлементыФормы.НайденныеСсылки.ОтборСтрок.Ссылка.Использование = Истина;
	ЭлементыФормы.НайденныеСсылки.ОтборСтрок.Ссылка.Значение = ЗначениеОтбора;
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеСсылкиОтборПоТекущейЗамене(Кнопка)
	
	мОтборТекущемуПоПравилу = Не Кнопка.Пометка;
	Кнопка.Пометка = мОтборТекущемуПоПравилу;
	Если Не мОтборТекущемуПоПравилу Тогда
		ЭлементыФормы.НайденныеСсылки.ОтборСтрок.Ссылка.Использование = Ложь;
	Иначе
		ОбновитьОтборПоТекущемуПравилу();
	КонецЕсли; 
	
КонецПроцедуры

Процедура НайденныеСсылкиПриИзмененииФлажка(Элемент, Колонка)
	
	ОбновитьСчетчикиПравилЗамены();

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

Процедура КоманднаяПанельНайденныеСсылкиМенеджерТабличногоПоля(Кнопка)
	
	ирОбщий.ОткрытьМенеджерТабличногоПоляЛкс(ЭлементыФормы.НайденныеСсылки, ЭтаФорма);

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

Процедура КоманднаяПанельЗаменаСсылокМенеджерТабличногоПоля(Кнопка)
	
	ирОбщий.ОткрытьМенеджерТабличногоПоляЛкс(ЭлементыФормы.ПравилаЗаменыСсылок, ЭтаФорма);
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыКонсольКомпоновки(Кнопка)
	
	НаборыДанныхОбъекты = Новый Структура("НайденныеГруппы, РезультатыПоиска", НайденныеГруппы, мРезультатыПоиска);
	СхемаКомпоновкиДанных = ирОбщий.СоздатьСхемуПоТаблицамЗначенийЛкс(НаборыДанныхОбъекты);
	#Если Сервер И Не Сервер Тогда
		СхемаКомпоновкиДанных = Новый СхемаКомпоновкиДанных;
	#КонецЕсли
	НастройкиКомпоновки = Новый НастройкиКомпоновкиДанных;
	ирОбщий.НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкиКомпоновки.Выбор, "Ссылка");
	ирОбщий.НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкиКомпоновки.Выбор, мИмяПоляКоличествоСсылок);
	ирОбщий.НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкиКомпоновки.Выбор, "КоличествоСтрокАвто");
	// Из-за сложного сопоставления имен не будет работать
	//Для Каждого Колонка Из ЭлементыФормы.ЭлементыТекущейГруппы.Колонки Цикл
	//	Если Колонка.Видимость Тогда
	//		ирОбщий.НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(НастройкиКомпоновки.Выбор, Сред(Колонка.Имя, СтрДлина(мПрефиксКолонокРеквизитов)));
	//	КонецЕсли; 
	//КонецЦикла; 
	ЭлементСтруктуры = ирОбщий.НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(НастройкиКомпоновки.Структура, "");
	Если мПоляСравнения.Количество() > 0 Тогда
		Для Каждого ПолеСравнения Из НайденныеГруппы.Колонки Цикл
			ПолеГруппировки = ЭлементСтруктуры.ПоляГруппировки.Элементы.Добавить(Тип("ПолеГруппировкиКомпоновкиДанных"));
			ПолеГруппировки.Использование = Истина;
			ПолеГруппировки.Поле = Новый ПолеКомпоновкиДанных(ПолеСравнения.Имя);
			Если мРезультатыПоиска.Колонки.Найти(ПолеСравнения.Имя) <> Неопределено Тогда
				Связь = СхемаКомпоновкиДанных.СвязиНаборовДанных.Добавить();
				Связь.НаборДанныхИсточник = "РезультатыПоиска";
				Связь.ВыражениеИсточник = ПолеСравнения.Имя;
				Связь.НаборДанныхПриемник = "НайденныеГруппы";
				Связь.ВыражениеПриемник = ПолеСравнения.Имя;
			КонецЕсли; 
		КонецЦикла;
		ЭлементСтруктурыДетальныхЗаписей = ирОбщий.НайтиДобавитьЭлементСтруктурыГруппировкаКомпоновкиЛкс(ЭлементСтруктуры.Структура, "");
	КонецЕсли;
	ЭлементОформления = НастройкиКомпоновки.УсловноеОформление.Элементы.Добавить();
	ирОбщий.НайтиДобавитьЭлементОтбораКомпоновкиЛкс(ЭлементОформления.Отбор, мИмяФлагаПравильныйЭлемент, Истина);
	ЗначениеПараметра = ЭлементОформления.Оформление.Элементы.Найти("Шрифт");
	ЗначениеПараметра.Значение = Новый Шрифт(,,Истина);
	ЗначениеПараметра.Использование = Истина;
	КонсольКомпоновокДанных = ирОбщий.ПолучитьОбъектПоПолномуИмениМетаданныхЛкс("Отчет.ирКонсольКомпоновокДанных");
	#Если Сервер И Не Сервер Тогда
		КонсольКомпоновокДанных = Отчеты.ирКонсольКомпоновокДанных.Создать();
	#КонецЕсли
    КонсольКомпоновокДанных.ОткрытьДляОтладки(СхемаКомпоновкиДанных, НастройкиКомпоновки, НаборыДанныхОбъекты, Ложь);
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеСсылкиКонсольКомпоновки(Кнопка)
	
	Отчеты.ирКонсольКомпоновокДанных.Создать().ОткрытьПоТаблицеЗначений(ЭтотОбъект.НайденныеСсылки.Выгрузить());

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

Процедура КоманднаяПанельНайденныеСсылкиОтборБезЗначенияВТекущейКолонке(Кнопка)
	
	ирОбщий.ТабличноеПоле_ОтборБезЗначенияВТекущейКолонке_КнопкаЛкс(ЭлементыФормы.НайденныеСсылки);

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

Процедура ПолноеИмяОбъектаПриИзменении(Элемент)
	
	Если ПриУстановкеПолногоИмениОбъекта() Тогда 
		ирОбщий.ПолеВводаСИсториейВыбора_ПриИзмененииЛкс(Элемент, ЭтаФорма);
	КонецЕсли; 
	
КонецПроцедуры

Процедура ПолноеИмяОбъектаНачалоВыбораИзСписка(Элемент, СтандартнаяОбработка)
	
	ирОбщий.ПолеВводаСИсториейВыбора_НачалоВыбораИзСпискаЛкс(Элемент, ЭтаФорма);

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

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

Процедура ПриОткрытии()
	
	мПолеТекстовогоДокументаСКонтекстнойПодсказкой = ирОбщий.ПолучитьОбъектПоПолномуИмениМетаданныхЛкс("Обработка.ирКлсПолеТекстовогоДокументаСКонтекстнойПодсказкой");
	#Если Сервер И Не Сервер Тогда
		мПолеТекстовогоДокументаСКонтекстнойПодсказкой = Обработки.ирКлсПолеТекстовогоДокументаСКонтекстнойПодсказкой.Создать();
	#КонецЕсли
	мПолеТекстовогоДокументаСКонтекстнойПодсказкой.Инициализировать(, ЭтаФорма, ЭлементыФормы.ОбработкаЗаменыДанных);
	Если мНастройкиВосстановлены <> Истина Тогда
		ПослеВосстановленияЗначений();
	КонецЕсли;

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

// @@@.КЛАСС.ПолеТекстовогоДокументаСКонтекстнойПодсказкой
// Транслятор обработки событий нажатия на кнопки командной панели в компоненту.
//
// Параметры:
//  Кнопка       – КнопкаКоманднойПанели.
//
Процедура КлсПолеТекстовогоДокументаСКонтекстнойПодсказкойНажатие(Кнопка)
	
	ирОбщий.ИнициализироватьГлобальныйКонтекстПодсказкиЛкс(мПолеТекстовогоДокументаСКонтекстнойПодсказкой);
	МассивТиповПравильных = Новый Массив;
	МассивТиповНеправильных = Новый Массив;
	Для Каждого СтрокаПравила Из ПравилаЗаменыСсылок Цикл
		ОбъектМДСсылки = Метаданные.НайтиПоТипу(ТипЗнч(СтрокаПравила.ЧтоЗаменять));
		Если ОбъектМДСсылки <> Неопределено Тогда
			МассивТиповПравильных.Добавить(Тип(СтрЗаменить(ОбъектМДСсылки.ПолноеИмя(), ".", "Объект.")));
		КонецЕсли; 
		ОбъектМДСсылки = Метаданные.НайтиПоТипу(ТипЗнч(СтрокаПравила.НаЧтоЗаменять));
		Если ОбъектМДСсылки <> Неопределено Тогда
			МассивТиповНеправильных.Добавить(Тип(СтрЗаменить(ОбъектМДСсылки.ПолноеИмя(), ".", "Объект.")));
		КонецЕсли; 
	КонецЦикла;
	#Если Сервер И Не Сервер Тогда
	    мПолеТекстовогоДокументаСКонтекстнойПодсказкой = Обработки.ирКлсПолеТекстовогоДокументаСКонтекстнойПодсказкой.Создать();
	#КонецЕсли
	мПолеТекстовогоДокументаСКонтекстнойПодсказкой.ДобавитьСловоЛокальногоКонтекста("ПравильныйОбъект", , Новый ОписаниеТипов(МассивТиповПравильных));
	мПолеТекстовогоДокументаСКонтекстнойПодсказкой.ДобавитьСловоЛокальногоКонтекста("НеправильныйОбъект", , Новый ОписаниеТипов(МассивТиповНеправильных));
	мПолеТекстовогоДокументаСКонтекстнойПодсказкой.ДобавитьСловоЛокальногоКонтекста("СтандартнаяОбработка", , Новый ОписаниеТипов("Булево"));
	мПолеТекстовогоДокументаСКонтекстнойПодсказкой.Нажатие(Кнопка);
	
КонецПроцедуры

Процедура НайденныеГруппыПриАктивизацииСтроки(Элемент)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	ЗагрузитьГруппуРезультатовПоиска(Элемент.ТекущаяСтрока);

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

Процедура КоманднаяПанельЭлементыТекущейГруппыВыборПравильныхДанных(Кнопка)
	
	ТекущаяСтрока = ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока;
	Если ТекущаяСтрока = Неопределено Тогда
		Возврат;
	КонецЕсли;
	СтрокаТаблицы = ЭлементыТекущейГруппы.Найти(Истина, мИмяФлагаПравильныеДанные);
	Если Истина
		И СтрокаТаблицы <> Неопределено
		И СтрокаТаблицы <> ТекущаяСтрока
	Тогда
		СтрокаТаблицы[мИмяФлагаПравильныеДанные] = СтрокаТаблицы = ТекущаяСтрока;
	КонецЕсли;
	ТекущаяСтрока[мИмяФлагаПравильныеДанные] = Не ТекущаяСтрока[мИмяФлагаПравильныеДанные];
	СброситьДоступность();
	СохранитьТекущуюГруппуРезультатовПоиска();

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

Процедура КоманднаяПанельЭлементыТекущейГруппыАвтовидимостьКолонок(Кнопка)
	
	ЭтаФорма.АвтовидимостьКолонокСоставаГруппы = Не Кнопка.Пометка;
	ПриИзмененииАвтовидимостьКолонокСоставаГруппы();
	
КонецПроцедуры

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

Процедура ЦенностьДанныхПриАктивизацииСтроки(Элемент)
	
	СохранитьОтборТекущегоУровняЦенности();
	Если Элемент.ТекущаяСтрока <> Неопределено Тогда
		НастройкаКомпоновкиXML = Элемент.ТекущаяСтрока.НастройкаКомпоновкиXML;
		НастройкиУровняЦености = ирОбщий.ВосстановитьНастройкуКомпоновкиИзСтрокиXMLЛкс(НастройкаКомпоновкиXML);
	Иначе
		НастройкиУровняЦености = Новый НастройкиКомпоновкиДанных;
	КонецЕсли;
	НоваяНастройкаКомпоновки = ирОбщий.СкопироватьНастройкиКомпоновкиЛкс(НастройкиУровняЦености, КомпоновщикЦенности.Настройки, Истина); 
	КомпоновщикЦенности.ЗагрузитьНастройки(НоваяНастройкаКомпоновки);
	мТекущаяСтрокаУровняЦенности = Элемент.ТекущаяСтрока;
	
КонецПроцедуры

Процедура СохранитьОтборТекущегоУровняЦенности()

	Если мТекущаяСтрокаУровняЦенности <> Неопределено Тогда
		Если ШкалаЦенности.Индекс(мТекущаяСтрокаУровняЦенности) = -1 Тогда
			Возврат;
		КонецЕсли; 
		СохраняемаяНастройкаКомпоновки = ирОбщий.СкопироватьНастройкиКомпоновкиЛкс(КомпоновщикЦенности.Настройки, , Истина); 
		мТекущаяСтрокаУровняЦенности.НастройкаКомпоновкиXML = ирОбщий.СохранитьОбъектВВидеСтрокиXMLЛкс(СохраняемаяНастройкаКомпоновки);
		мТекущаяСтрокаУровняЦенности.Уровень = СохраняемаяНастройкаКомпоновки.Отбор;
		Если мТекущаяСтрокаУровняЦенности.Уровень = "" Тогда
			мТекущаяСтрокаУровняЦенности.Уровень = "<Отбор не задан>"
		КонецЕсли; 
	КонецЕсли;

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

Процедура КоманднаяПанельТаблицаПустые(Кнопка)
	
	ирОбщий.КнопкаОтображатьПустыеИИдентификаторыНажатиеЛкс(Кнопка);
	ЭлементыФормы.ЭлементыТекущейГруппы.ОбновитьСтроки();
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыДобавитьПолеКолонкиВСравнение(Кнопка)
	
	ТекущаяКолонка = ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяКолонка;
	Если ТекущаяКолонка = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	ИмяКолонки = ТекущаяКолонка.Имя;
	Если Найти(ИмяКолонки, мСуффиксСлужбеныхПолей) = 0 Тогда
		ПолеПорядка = ирОбщий.НайтиДобавитьЭлементНастроекКомпоновкиПоПолюЛкс(КомпоновщикСравнения.Настройки.Порядок, ИмяКолонки);
		ПолеПорядка.Использование = Истина;
		Сообщить("В сравнение поиска дублей добавлено поле """ + ТекущаяКолонка.ТекстШапки + """");
	КонецЕсли; 
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыОтборПоЗначению(Кнопка)
	
	ТекущаяКолонка = ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяКолонка;
	Если ТекущаяКолонка = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	ТекущаяСтрока = ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока;
	Если ТекущаяСтрока = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	ИмяКолонки = ТекущаяКолонка.Данные;
	Если Найти(ИмяКолонки, мСуффиксСлужбеныхПолей) = 0 Тогда
		ЭлементОтбора = ирОбщий.НайтиДобавитьЭлементОтбораКомпоновкиЛкс(КомпоновщикСравнения.Настройки.Отбор, ИмяКолонки, ТекущаяСтрока[ИмяКолонки], ВидСравнения.Равно);
		Сообщить("В отбор поиска дублей добавлен элемент """ + ЭлементОтбора.ЛевоеЗначение + " равно " + ЭлементОтбора.ПравоеЗначение + """");
	КонецЕсли; 
	
КонецПроцедуры

Процедура ДополнительныеПоляПрочитатьПоля(Кнопка)
	
	ПрочитатьДополнительныеПоляСсылающихсяОбъектов();

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

Процедура ПриПолученииДанныхДоступныхПолей(Элемент, ОформленияСтрок)

	ирОбщий.ПриПолученииДанныхДоступныхПолейКомпоновкиЛкс(ОформленияСтрок);

КонецПроцедуры // ПриПолученииДанныхДоступныхПолей()

Процедура СтруктураКоманднойПанелиНажатие(Кнопка)
	
	ирОбщий.ОткрытьСтруктуруКоманднойПанелиЛкс(ЭтаФорма, Кнопка);
	
КонецПроцедуры

Функция ПолучитьСтруктуруНастроекОбработки()
	
	СтруктураНастроек = Новый Структура();
	СтруктураНастроек.Вставить("ПолноеИмяОбъекта", ПолноеИмяОбъекта);
	КопияРезультатов = Неопределено;
	Если мРезультатыПоиска <> Неопределено Тогда
		КопияРезультатов = мРезультатыПоиска.Скопировать();
		КопияРезультатов.Колонки.Удалить(мИмяПоляКоличествоСсылок);
	КонецЕсли; 
	СтруктураНастроек.Вставить("РезультатыПоиска", КопияРезультатов);
	СтруктураНастроек.Вставить("НайденныеГруппы", НайденныеГруппы);
	СтруктураНастроек.Вставить("ПравилаЗаменыСсылок", ПравилаЗаменыСсылок);
	СтруктураНастроек.Вставить("Настройки", ПравилаЗаменыСсылок);
	СтруктураНастроек.Вставить("СтруктураНастроекПоискаДублей", ПолучитьСтруктуруНастроекПоискаДублей());
	СтруктураНастроек.Вставить("ОбработкаЗаменыДанных", ЭлементыФормы.ОбработкаЗаменыДанных.ПолучитьТекст());
	Возврат СтруктураНастроек;

КонецФункции

Процедура ЗагрузитьНастройкиИзСтруктуры(СтруктураНастроек)
	
	ЭтотОбъект.ПолноеИмяОбъекта = СтруктураНастроек.ПолноеИмяОбъекта;
	ПриУстановкеПолногоИмениОбъекта();
	ОчиститьРезультатыПоиска();
	Если СтруктураНастроек.РезультатыПоиска <> Неопределено Тогда
		ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(СтруктураНастроек.РезультатыПоиска, мРезультатыПоиска);
	КонецЕсли; 
	Если СтруктураНастроек.НайденныеГруппы <> Неопределено Тогда
		ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(СтруктураНастроек.НайденныеГруппы, НайденныеГруппы);
	КонецЕсли; 
	НастроитьЭлементыФормыПоРезультатуПоиска();
	ПравилаЗаменыСсылок.Очистить();
	ирОбщий.ЗагрузитьВТаблицуЗначенийЛкс(СтруктураНастроек.ПравилаЗаменыСсылок, ПравилаЗаменыСсылок);
	ЭлементыФормы.ОбработкаЗаменыДанных.УстановитьТекст(СтруктураНастроек.ОбработкаЗаменыДанных);
	ЗагрузитьНастройкиПоискаДублей(СтруктураНастроек.СтруктураНастроекПоискаДублей);
	
КонецПроцедуры

Процедура КоманднаяПанельОткрытьФайл(Кнопка)
	
	ДиалогВыбораФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Открытие);
	ДиалогВыбораФайла.Заголовок = "Выберите файл для загрузки настроек обработки";
	ДиалогВыбораФайла.Фильтр = ирОбщий.ПолучитьСтрокуФильтраДляВыбораФайлаЛкс("fdr", "Файл поиска дублей и замены ссылок");
	ДиалогВыбораФайла.Расширение = "fdr";
	Если ДиалогВыбораФайла.Выбрать() Тогда
		Поток = Новый ЧтениеXML;
		Поток.ОткрытьФайл(ДиалогВыбораФайла.ПолноеИмяФайла);
		Попытка
			СтруктураНастроек = СериализаторXDTO.ПрочитатьXML(Поток);
		Исключение
			Сообщить("Ошибка чтения настроек из файла: " + ОписаниеОшибки());
			Возврат;
		КонецПопытки; 
		Поток.Закрыть();
		ЗагрузитьНастройкиИзСтруктуры(СтруктураНастроек);
	КонецЕсли;
	
КонецПроцедуры

Процедура КоманднаяПанельСохранить(Кнопка)

	ДиалогВыбораФайла = Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение);
	ДиалогВыбораФайла.Заголовок = "Укажите файл для сохранения настроек обработки";
	ДиалогВыбораФайла.Фильтр = ирОбщий.ПолучитьСтрокуФильтраДляВыбораФайлаЛкс("fdr", "Файл поиска дублей и замены ссылок (ИР)");
	ДиалогВыбораФайла.Расширение = "fdr";
	Если ДиалогВыбораФайла.Выбрать() Тогда
		СтруктураНастроек = ПолучитьСтруктуруНастроекОбработки();
		Поток = Новый ЗаписьXML;
		Поток.ОткрытьФайл(ДиалогВыбораФайла.ПолноеИмяФайла,);
		СериализаторXDTO.ЗаписатьXML(Поток, СтруктураНастроек);
		Поток.Закрыть();
	КонецЕсли; 
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыОбновитьКоличествоСсылок(Кнопка)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	ОпределитьКоличествоСсылок();
	ЗагрузитьГруппуРезультатовПоиска();
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыРедакторОбъектаБДСтроки(Кнопка)
	
	Если ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока = Неопределено Тогда
		Возврат;
	КонецЕсли;
	ирОбщий.ОткрытьСсылкуВРедактореОбъектаБДЛкс(ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока.Ссылка);
	
КонецПроцедуры

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

//НайденныеЗависимыеСсылки с флагами
Процедура НайденныеЗависимыеСсылкиПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	ОформлениеСтроки.Ячейки.Пометка.ОтображатьТекст = Ложь;
КонецПроцедуры

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

//НайденныеЗависимыеСсылки с флагами
Процедура КоманднаяПанельНайденныеЗависимыеСсылкиВключитьВсе(Кнопка)
	ирОбщий.ИзменитьПометкиВыделенныхСтрокЛкс(ЭлементыФормы.НайденныеЗависимыеСсылки, , Истина);
	ОбновитьСчетчикиПравилЗамены();
КонецПроцедуры

Процедура ОбработкаОповещения(ИмяСобытия, Параметр, Источник)
	
	ирОбщий.ФормаОбработкаОповещенияЛкс(ЭтаФорма, ИмяСобытия, Параметр, Источник); 

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

Процедура ПриЗакрытии()
	
	// Удалим лишние колонки и установим фиксированные имена для возможности использования таблицы дублей снаржи
	Если мРезультатыПоиска <> Неопределено Тогда
		НачальноеКоличество = мРезультатыПоиска.Колонки.Количество(); 
		Для СчетчикКолонки = 1 По НачальноеКоличество Цикл
			Колонка = мРезультатыПоиска.Колонки[НачальноеКоличество - СчетчикКолонки];
			Если Ложь
				Или Колонка.Имя = мИмяПоляНомерГруппы
				Или Колонка.Имя = мИмяФлагаПравильныйЭлемент
				Или Колонка.Имя = мИмяФлагаПравильныеДанные
				Или Колонка.Имя = "Ссылка"
			Тогда
				Продолжить;
			КонецЕсли;
			мРезультатыПоиска.Колонки.Удалить(Колонка);
		КонецЦикла;
		мРезультатыПоиска.Колонки[мИмяПоляНомерГруппы].Имя = "НомерГруппы";
		мРезультатыПоиска.Колонки[мИмяФлагаПравильныйЭлемент].Имя = "ПравильныйЭлемент";
		мРезультатыПоиска.Колонки[мИмяФлагаПравильныеДанные].Имя = "ПравильныеДанные";
	КонецЕсли; 
	ирОбщий.Форма_ПриЗакрытииЛкс(ЭтаФорма);

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

Процедура ОтборПравоеЗначениеДляПодробногоОтображенияЭлементаОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	
	ирОбщий.ПолеВвода_ОкончаниеВводаТекстаЛкс(Элемент, Текст, Значение, СтандартнаяОбработка, , Истина);
	
КонецПроцедуры

Процедура ОтборПравоеЗначениеДляКраткогоОтображенияЭлементаОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	
	ирОбщий.ПолеВвода_ОкончаниеВводаТекстаЛкс(Элемент, Текст, Значение, СтандартнаяОбработка, , Истина);

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

Процедура ОтборУровняЦенностиПравоеЗначениеДляПодробногоОтображенияЭлементаОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	
	ирОбщий.ПолеВвода_ОкончаниеВводаТекстаЛкс(Элемент, Текст, Значение, СтандартнаяОбработка, , Истина);

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

Процедура ОтборУровняЦенностиПравоеЗначениеДляКраткогоОтображенияЭлементаОкончаниеВводаТекста(Элемент, Текст, Значение, СтандартнаяОбработка)
	
	ирОбщий.ПолеВвода_ОкончаниеВводаТекстаЛкс(Элемент, Текст, Значение, СтандартнаяОбработка, , Истина);

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

Процедура КоманднаяПанельНайденныеСсылкиКонсольОбработки(Кнопка)
	
	ирОбщий.ОткрытьОбъектыИзВыделенныхЯчеекВПодбореИОбработкеОбъектовЛкс(ЭтаФорма.ЭлементыФормы.НайденныеСсылки);
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыПоискСсылок(Кнопка)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	РезультатПоиска = ЗаполнитьПравилаЗаменыСсылокПоВсемГруппам();
	Если РезультатПоиска Тогда
		ЭлементыФормы.Панель.ТекущаяСтраница = ЭлементыФормы.Панель.Страницы.ПравилаЗаменыСсылок;
	КонецЕсли;

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

Процедура КоманднаяПанельНайденныеГруппыОбновитьЦенность(Кнопка)
	
	СохранитьТекущуюГруппуРезультатовПоиска();
	Запрос = Новый Запрос;
	ВыражениеПоляЦенность = ДобавитьВыражениеЦенности(Запрос);
	ТекстУпорядочить = ПолучитьСтрокуПорядкаЦенности();
	ТекстЗапроса = "
	|ВЫБРАТЬ " + мПсевдонимТаблицы + ".Ссылка, " + ВыражениеПоляЦенность + " КАК " + мИмяПоляЦенность + "
	|ИЗ " + ПолноеИмяОбъекта + " КАК " + мПсевдонимТаблицы + "
	|ГДЕ " + мПсевдонимТаблицы + ".Ссылка В (&Ссылки) 
	|УПОРЯДОЧИТЬ ПО " + ТекстУпорядочить + "
	|";
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("Ссылки", мРезультатыПоиска.ВыгрузитьКолонку("Ссылка"));
	РезультатЗапроса = Запрос.Выполнить().Выгрузить();
	НовыеРезультатыПоиска = мРезультатыПоиска.СкопироватьКолонки();
	Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(РезультатЗапроса.Количество());
	Счетчик = 1;
	СтрокаПорядкаЦенности = ирОбщий.ПолучитьСтрокуПорядкаКомпоновкиЛкс(КомпоновщикЦенности.Настройки.Порядок);
	Для Каждого СтрокаРезультата Из РезультатЗапроса Цикл
		ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
		НоваяСтрока = НовыеРезультатыПоиска.Добавить();
		СтараяСтрока = мРезультатыПоиска.Найти(СтрокаРезультата.Ссылка, "Ссылка");
		ЗаполнитьЗначенияСвойств(НоваяСтрока, СтараяСтрока);
		ЗаполнитьЗначенияСвойств(НоваяСтрока, СтрокаРезультата);
		// 7тч783тгшпт
		Если СтрокаПорядкаЦенности <> "" Тогда
			НоваяСтрока[мИмяПоляЦенность] = Счетчик;
		КонецЕсли; 
		Счетчик = Счетчик + 1;
	КонецЦикла;
	ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
	мРезультатыПоиска = НовыеРезультатыПоиска;
	ЗагрузитьГруппуРезультатовПоиска();
	
КонецПроцедуры

Процедура КлсУниверсальнаяКомандаНажатие(Кнопка) Экспорт 
	
	ирОбщий.УниверсальнаяКомандаФормыЛкс(ЭтаФорма, Кнопка);
	
КонецПроцедуры

Процедура ОбработчикОжиданияСПараметрамиЛкс() Экспорт 
	
	ирОбщий.ОбработчикОжиданияСПараметрамиЛкс();

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

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

Процедура КоманднаяПанельЭлементыТекущейГруппыПодбор(Кнопка)
	
	Отказ = Истина;
	ЕСли ПолноеИмяОбъекта = Неопределено Тогда
		Возврат;
	КонецЕсли;
	ТекущаяСтрока = ЭлементыФормы.ЭлементыТекущейГруппы.ТекущаяСтрока;
	Если ТекущаяСтрока <> Неопределено Тогда
		НачальноеЗначениеВыбора = ТекущаяСтрока.Ссылка;
	КонецЕсли; 
	ОписаниеТипов = Новый ОписаниеТипов(ирОбщий.ИмяТипаИзПолногоИмениТаблицыБДЛкс(ПолноеИмяОбъекта));
	ирОбщий.ОткрытьПодборСВыборомТипаЛкс(ЭлементыФормы.ЭлементыТекущейГруппы, ОписаниеТипов, НачальноеЗначениеВыбора);

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

Процедура КоманднаяПанельЗаменаСсылокКонсольОбработки(Кнопка)
	
	ирОбщий.ОткрытьОбъектыИзВыделенныхЯчеекВПодбореИОбработкеОбъектовЛкс(ЭлементыФормы.ПравилаЗаменыСсылок);
	
КонецПроцедуры

Процедура КоманднаяПанельЗаменаСсылокИдентификаторы(Кнопка)
	
	ирОбщий.КнопкаОтображатьПустыеИИдентификаторыНажатиеЛкс(Кнопка);
	ЭлементыФормы.ПравилаЗаменыСсылок.ОбновитьСтроки();
	
КонецПроцедуры

Процедура КоманднаяПанельНастройкиОтчетаИсполняемыйЗапрос(Кнопка)
	
	НастройкиДляОтбора = КомпоновщикСравнения.ПолучитьНастройки();
	ЗапросСОтбором = ирОбщий.ПолучитьЗапросИзКомпоновкиЛкс(мСхемаКомпоновкиОбщая, НастройкиДляОтбора,,, "Ссылка");
	ЗапросПоискаДублей = ПолучитьЗапросПоискаДублей(ЗапросСОтбором);
	ирОбщий.ОтладитьЛкс(ЗапросПоискаДублей);
	
КонецПроцедуры

Процедура ШкалаЦенностиПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	
	ОформлениеСтроки.Ячейки.ЗначениеЦенности.УстановитьТекст(Элемент.Значение.Индекс(ДанныеСтроки) + 1);
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыРазличныеЗначенияКолонки(Кнопка)
	
	ирОбщий.ОткрытьРазличныеЗначенияКолонкиЛкс(ЭлементыФормы.НайденныеГруппы);
	
КонецПроцедуры

Процедура КоманднаяПанельЗаменаСсылокРедакторОбъектаБД(Кнопка)
	
	ирОбщий.ОткрытьСсылкуЯчейкиВРедактореОбъектаБДЛкс(ЭлементыФормы.ПравилаЗаменыСсылок);
	
КонецПроцедуры

Процедура КоманднаяПанельСтруктураФормы(Кнопка)
	
	ирОбщий.ОткрытьСтруктуруФормыЛкс(ЭтаФорма);
	
КонецПроцедуры

Процедура ЗависимыеЗначенияТипЗначенияПриИзменении(Элемент)
	
	ОбновитьСписокВыбораЗависимоеВлияющее();
	
КонецПроцедуры

Процедура ОбновитьСписокВыбораЗависимоеВлияющее()

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


Процедура ПравилаЗависимыхПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки)
	
	ОформлениеСтроки.Ячейки.ТипЗначения.УстановитьТекст(ТипЗнч(ДанныеСтроки.ТипЗначения));
	ОформлениеСтроки.Ячейки.Пометка.ТолькоПросмотр = Не ПравилоЗависимогоЗаполнено(ДанныеСтроки);
	
КонецПроцедуры

Функция ПравилоЗависимогоЗаполнено(ДанныеСтроки)
	
	Возврат Истина
		И ЗначениеЗаполнено(ДанныеСтроки.ПутьКДаннымВлияющего)
		И ЗначениеЗаполнено(ДанныеСтроки.ЗависимоеВлияющее)
		И ДанныеСтроки.ТипЗначения <> Неопределено;

КонецФункции

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

Процедура ОбновитьВлияющееЗависимогоЗначения(Знач СтрокаЗависимогоЗначения = Неопределено)
	
	ТекущееПравило = ЭлементыФормы.ПравилаЗаменыСсылок.ТекущаяСтрока;
	Если ТекущееПравило = Неопределено Тогда
		Возврат;
	КонецЕсли; 
	ЧтоЗаменять = ТекущееПравило.ЧтоЗаменять;
	НаЧтоЗаменять = ТекущееПравило.НаЧтоЗаменять;
	Для Каждого СтрокаЗависимогоЗначения Из ПравилаЗависимых Цикл
		ПутьКДаннымВлияющего = СтрокаЗависимогоЗначения.ПутьКДаннымВлияющего;
		Попытка
			ВлияющееЧтоЗаменять = ЧтоЗаменять[ПутьКДаннымВлияющего];
		Исключение
			ВлияющееЧтоЗаменять = Неопределено;
		КонецПопытки; 
		СтрокаЗависимогоЗначения.ВлияющееЧтоЗаменять = ВлияющееЧтоЗаменять;
		Попытка
			ВлияющееНаЧтоЗаменять = НаЧтоЗаменять[ПутьКДаннымВлияющего];
		Исключение
			ВлияющееНаЧтоЗаменять = Неопределено;
		КонецПопытки; 
		СтрокаЗависимогоЗначения.ВлияющееНаЧтоЗаменять = ВлияющееНаЧтоЗаменять;
	КонецЦикла;
	
КонецПроцедуры

Процедура ЗависимыеЗначенияПутьКДаннымВлияющегоПриИзменении(Элемент)
	
	ОбновитьВлияющееЗависимогоЗначения();
	
КонецПроцедуры

Процедура ПравилаЗависимыхПриАктивизацииСтроки(Элемент)
	
	ОбновитьСписокВыбораЗависимоеВлияющее();
	
КонецПроцедуры

Процедура ЗависимыеЗначенияТипЗначенияНачалоВыбора(Элемент, СтандартнаяОбработка)
	
	ирОбщий.ВыбратьТипСсылкиВПолеВводаЛкс(Элемент, СтандартнаяОбработка, Ложь);
	
КонецПроцедуры

Процедура ПравилаЗависимыхВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)
	
	Если Колонка.ТолькоПросмотр Тогда
		ирОбщий.ЯчейкаТабличногоПоляРасширенногоЗначения_ВыборЛкс(Элемент, СтандартнаяОбработка);
	КонецЕсли; 
	
КонецПроцедуры

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

Процедура ЗависимыеЗначенияНаЧтоЗаменятьНачалоВыбора(Элемент, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	ТекущиеДанные = ЭлементыФормы.ПравилаЗависимых.ТекущиеДанные;
	ирОбщий.ОткрытьФормуСпискаЛкс(ТекущиеДанные.ТипЗначения.Метаданные().ПолноеИмя(), Новый Структура(ТекущиеДанные.ЗависимоеВлияющее,
		мТекущееПравило.НаЧтоЗаменять[ТекущиеДанные.ЗависимоеВлияющее]), Ложь, Элемент, Истина);

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

Процедура КППравилаЗависимыхРедакторОбъектаБД(Кнопка)
	
	ирОбщий.ОткрытьСсылкуЯчейкиВРедактореОбъектаБДЛкс(ЭлементыФормы.ПравилаЗависимых);

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

Процедура ПравилаЗависимыхПриОкончанииРедактирования(Элемент, НоваяСтрока, ОтменаРедактирования)
	
	Если Не ПравилоЗависимогоЗаполнено(Элемент.ТекущаяСтрока) Тогда
		Элемент.ТекущаяСтрока.Пометка = Ложь;
	КонецЕсли; 

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

Процедура КоманднаяПанельЗаменаСсылокВключитьВсе(Кнопка)
	
	ирОбщий.ИзменитьПометкиВыделенныхСтрокЛкс(ЭлементыФормы.ПравилаЗаменыСсылок, , Истина);
	
КонецПроцедуры

Процедура КоманднаяПанельЗаменаСсылокВыключитьВсе(Кнопка)
	
	ирОбщий.ИзменитьПометкиВыделенныхСтрокЛкс(ЭлементыФормы.ПравилаЗаменыСсылок, , Ложь);
	
КонецПроцедуры

Процедура КоманднаяПанельЭлементыТекущейГруппыКонсольОбработки(Кнопка)
	
	ирОбщий.ОткрытьОбъектыИзВыделенныхЯчеекВПодбореИОбработкеОбъектовЛкс(ЭлементыФормы.ЭлементыТекущейГруппы);
	
КонецПроцедуры

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

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

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

Процедура ПроизвольныйЗапросПриИзменении(Элемент)
	
	Если РежимПроизвольногоЗапроса Тогда
		ПроизвольныйЗапросНажатие();
	КонецЕсли; 
	ОбновитьСхемуКомпоновки();
	ОбновитьДоступность();
	
КонецПроцедуры

Процедура ОтборЗначениеНачалоВыбора(Элемент, СтандартнаяОбработка)
	
	ирОбщий.ПолеВводаКолонкиРасширенногоЗначения_НачалоВыбораЛкс(ЭлементыФормы.Отбор, СтандартнаяОбработка,, Истина,, "ПравоеЗначение");
	
КонецПроцедуры

Процедура ОтборПарЗначениеНачалоВыбора(Элемент, СтандартнаяОбработка)
	
	ирОбщий.ПолеВводаКолонкиРасширенногоЗначения_НачалоВыбораЛкс(ЭлементыФормы.ОтборПар, СтандартнаяОбработка,, Истина,, "ПравоеЗначение");
	
КонецПроцедуры

Процедура ПравилаЗаменыСсылокНаЧтоЗаменятьНачалоВыбора(Элемент, СтандартнаяОбработка)
	
	ирОбщий.ПолеВводаКолонкиРасширенногоЗначения_НачалоВыбораЛкс(ЭлементыФормы.ПравилаЗаменыСсылок, СтандартнаяОбработка,, Истина);
	
КонецПроцедуры

Процедура ПравилаЗаменыСсылокЧтоЗаменятьНачалоВыбора(Элемент, СтандартнаяОбработка)

	ирОбщий.ПолеВводаКолонкиРасширенногоЗначения_НачалоВыбораЛкс(ЭлементыФормы.ПравилаЗаменыСсылок, СтандартнаяОбработка,, Истина);
	
КонецПроцедуры

Процедура НастройкаСравненияПередУдалением(Элемент, Отказ)
	
	Если Не Отказ Тогда
		Если "" + Элемент.ТекущиеДанные.Поле = мПутьКДаннымПоляНечеткогоСравнения Тогда
			мПутьКДаннымПоляНечеткогоСравнения = "";
			ОбновитьДоступность();
		КонецЕсли; 
	КонецЕсли; 
	
КонецПроцедуры

Процедура КоманднаяПанельНайденныеГруппыМенеджерТабличногоПоля(Кнопка)
	
	ирОбщий.ОткрытьМенеджерТабличногоПоляЛкс(ЭлементыФормы.НайденныеГруппы, ЭтаФорма);

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

Процедура КоманднаяПанельЭлементыТекущейГруппыМенеджерТабличногоПоля(Кнопка)
	
	ирОбщий.ОткрытьМенеджерТабличногоПоляЛкс(ЭлементыФормы.ЭлементыТекущейГруппы, ЭтаФорма);
	
КонецПроцедуры

Процедура ПолноеИмяОбъектаОткрытие(Элемент, СтандартнаяОбработка)
	
	СтандартнаяОбработка = Ложь;
	ирОбщий.ОткрытьОбъектМетаданныхЛкс(ПолноеИмяОбъекта);
	
КонецПроцедуры

Процедура КоманднаяПанельПараметрыЗаписи(Кнопка)
	
	ирОбщий.ОткрытьОбщиеПараметрыЗаписиЛкс();
	
КонецПроцедуры

ирОбщий.ИнициализироватьФормуЛкс(ЭтаФорма, "Обработка.ирПоискДублейИЗаменаСсылок.Форма.Форма");

ирОбщий.ПодключитьОбработчикиСобытийДоступныхПолейКомпоновкиЛкс(ЭлементыФормы.ДоступныеПоля);
ирОбщий.ПодключитьОбработчикиСобытийДоступныхПолейКомпоновкиЛкс(ЭлементыФормы.ДоступныеПоляПар);
ирОбщий.ПодключитьОбработчикиСобытийДоступныхПолейКомпоновкиЛкс(ЭлементыФормы.ДоступныеПоляДополнительныхПолей);
ЭлементыФормы.Отбор.Колонки.ПравоеЗначениеДляКраткогоОтображенияЭлемента.ЭлементУправления.УстановитьДействие("НачалоВыбора", Новый Действие("ОтборЗначениеНачалоВыбора"));
ЭлементыФормы.ОтборПар.Колонки.ПравоеЗначениеДляКраткогоОтображенияЭлемента.ЭлементУправления.УстановитьДействие("НачалоВыбора", Новый Действие("ОтборПарЗначениеНачалоВыбора"));
мПроизвольныйЗапрос = Новый Запрос;
ДоступныеПараметрыОбработкиЗаменыДанных = "ПравильныйОбъект, НеправильныйОбъект, СтандартнаяОбработка";
ПравилаЗаменыСсылок.Колонки.Добавить("ПравилаЗависимых");
АвтовидимостьКолонокСоставаГруппы = Истина;
мОтборТекущемуПоПравилу = Ложь;
мПутьКДаннымПоляНечеткогоСравнения = "";
мПредставления = Новый Структура;
мСписокРеквизитов = Новый СписокЗначений;
мОбработкаПоискаСсылок = ирОбщий.ПолучитьОбъектПоПолномуИмениМетаданныхЛкс("Обработка.ирРедакторОбъектаБД");
НастройкиПоискаДублей = Новый Соответствие;
//ШкалаЦенности.Колонки.Добавить("НастройкаКомпоновкиXML");
//мПсевдонимТаблицы = мПлатформа.ПолучитьНовоеУникальноеИмя();
мСуффиксСлужбеныхПолей = "3463"; // Для устранения пересечений с именами полей данных
мПсевдонимТаблицы = "Т" + мСуффиксСлужбеныхПолей;
мИмяПоляКоличествоСсылок = "КоличествоСсылок" + мСуффиксСлужбеныхПолей;
мИмяПоляЦенность = "ЦенностьДанных" + мСуффиксСлужбеныхПолей;
мИмяПоляКоличествоЭлементов = "КоличествоЭлементовВГруппе" + мСуффиксСлужбеныхПолей;
мИмяПоляИдентификатор = "Идентификатор" + мСуффиксСлужбеныхПолей;
мИмяПоляНомерГруппы = "НомерГруппы" + мСуффиксСлужбеныхПолей;
мИмяПоляКоличествоСсылок = "КоличествоСсылок" + мСуффиксСлужбеныхПолей;
мИмяПоляНеправильныеСсылки = "НеправильныеСсылки" + мСуффиксСлужбеныхПолей;
мИмяПоляНеправильныйЭлемент = "НеправильныйЭлемент" + мСуффиксСлужбеныхПолей;
мИмяПоляПравильныйЭлемент = "ПравильныйЭлемент" + мСуффиксСлужбеныхПолей;
мИмяПоляПравильныеДанные = "ПравильныеДанные" + мСуффиксСлужбеныхПолей; 
мИмяФлагаПравильныйЭлемент = "ЭтоПравильныйЭлемент" + мСуффиксСлужбеныхПолей;
мИмяФлагаПравильныеДанные = "ЭтоПравильныеДанные" + мСуффиксСлужбеныхПолей;
УстановитьПредставленияСлужебныхПолей();
