//ирПортативный Перем ирПортативный Экспорт;
//ирПортативный Перем ирОбщий Экспорт;
//ирПортативный Перем ирСервер Экспорт;
//ирПортативный Перем ирКэш Экспорт;
//ирПортативный Перем ирКлиент Экспорт;

Перем мСервисныйПроцессор Экспорт; // Для программного вызова из Интеграции
Перем ТаблицаСсылок Экспорт;

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

Процедура лСостояние(Текст)
	//#Если Клиент Тогда
	//Состояние(Текст);
	//#КонецЕсли
КонецПроцедуры	

Процедура лСостояниеПоиск(Текст)
	//#Если Клиент Тогда
	//Состояние("Поиск в "+Текст);
	//#КонецЕсли
КонецПроцедуры

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

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

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

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

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

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

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

// Добавить массив объектов в удаляемые объекты
//
// Параметры:
//  МассивОбъектов				 - Массив, ВыделенныеСтроки - 
//  ЭтаФорма					 - см. ПолучитьФорму - 
//  УстанавливатьТекущуюСтроку	 - 	 - 
//  ПредлагатьПомечатьНаУдаление - 	 - 
// 
// Возвращаемое значение:
//   - 
//
Функция ДобавитьМассивОбъектовВУдаляемыеОбъекты(МассивОбъектов, ЭтаФорма = Неопределено, УстанавливатьТекущуюСтроку = Ложь, ПредлагатьПомечатьНаУдаление = Ложь) Экспорт 
	
	ВМассивеБылиНовыеПодходящиеОбъекты = Ложь;
	ТаблицаОбъектов = УдаляемыеОбъекты.ВыгрузитьКолонки();
	#Если Клиент Тогда
		ЭтоСсылкиНаКандидаты = ТипЗнч(МассивОбъектов) = Тип("ВыделенныеСтрокиТабличногоПоля");
	#Иначе
		ЭтоСсылкиНаКандидаты = Ложь;
	#КонецЕсли
	Для Каждого Объект Из МассивОбъектов Цикл
		Если ЭтоСсылкиНаКандидаты Тогда 
			Объект = Объект.Данные; 
		КонецЕсли;
		Если ирОбщий.ЛиТипСсылкиБДЛкс(ТипЗнч(Объект)) Тогда
			СтрокаОбъекта = ТаблицаОбъектов.Добавить();
			СтрокаОбъекта.Ссылка = Объект;
			Если СтрокаОбъекта.Ссылка <> Объект Тогда
				// Это тип из расширения конфигурации http://www.hostedredmine.com/issues/886337
				ТаблицаОбъектов.Удалить(СтрокаОбъекта);
			КонецЕсли; 
		КонецЕсли; 
	КонецЦикла;
	Если ТаблицаОбъектов.Количество() = 0 Тогда
		Возврат ВМассивеБылиНовыеПодходящиеОбъекты;
	КонецЕсли; 
	ОбновитьДанныеКандидатов(ТаблицаОбъектов);
	СписокБылПустым = УдаляемыеОбъекты.Количество() = 0;
	СоответствиеТипаКМетаданному = Новый Соответствие;
	Если ПредлагатьПомечатьНаУдаление Тогда
		ПомечатьНаУдаление = Неопределено;
	Иначе
		ПомечатьНаУдаление = Ложь;
	КонецЕсли; 
	#Если Клиент Тогда
	Индикатор = ирОбщий.ПолучитьИндикаторПроцессаЛкс(ТаблицаОбъектов.Количество(), "Добавление кандидатов");
	#КонецЕсли
	Для Каждого СтрокаОбъекта Из ТаблицаОбъектов Цикл
		#Если Клиент Тогда
		ирОбщий.ОбработатьИндикаторЛкс(Индикатор);
		#КонецЕсли
		//Если СтрокаОбъекта.Предопределенный Тогда
		//	ирОбщий.СообщитьЛкс("Предопределенный объект """ + СтрокаОбъекта.Представление + """ нельзя добавлять в кандидаты");
		//	Продолжить;
		//КонецЕсли; 
		Если Не СписокБылПустым Тогда
			СтрокаКандидата = УдаляемыеОбъекты.Найти(СтрокаОбъекта.Ссылка, "Ссылка");
		Иначе
			СтрокаКандидата = Неопределено;
		КонецЕсли; 
		Если СтрокаКандидата = Неопределено Тогда
			#Если Клиент Тогда
			Если ПомечатьНаУдаление = Неопределено И Не СтрокаОбъекта.ПометкаУдаления Тогда
				Ответ = Вопрос("Хотите пометить на удаление добавляемые кандидаты?", РежимДиалогаВопрос.ДаНет);
				ПомечатьНаУдаление = Ответ = КодВозвратаДиалога.Да;
			КонецЕсли; 
			#КонецЕсли
			Если ПомечатьНаУдаление = Истина И Не СтрокаОбъекта.ПометкаУдаления Тогда
				СтруктураОбъекта = ирОбщий.ОбъектБДПоКлючуЛкс(, СтрокаОбъекта.Ссылка);
				ирОбщий.УстановитьПометкуУдаленияОбъектаЛкс(СтруктураОбъекта.Методы,, Истина);
				СтрокаОбъекта.ПометкаУдаления = Истина;
			КонецЕсли; 
			СтрокаКандидата = УдаляемыеОбъекты.Добавить();
			СтрокаКандидата.Ссылка = СтрокаОбъекта.Ссылка;
			ОбновитьСтрокуУдаляемогоОбъекта(ЭтаФорма, СтрокаКандидата, СоответствиеТипаКМетаданному, СтрокаОбъекта.ПометкаУдаления, СтрокаОбъекта.Представление, СтрокаОбъекта.Предопределенный, СтрокаОбъекта.ИндексКартинки);
			ВМассивеБылиНовыеПодходящиеОбъекты = Истина;
		КонецЕсли; 
	КонецЦикла;
	#Если Клиент Тогда
	ирОбщий.ОсвободитьИндикаторПроцессаЛкс();
	#КонецЕсли
	Если Истина
		И ЭтаФорма <> Неопределено
		И УстанавливатьТекущуюСтроку 
		И СтрокаКандидата <> Неопределено
	Тогда
		ЭтаФорма.ЭлементыФормы.УдаляемыеОбъекты.ТекущаяСтрока = СтрокаКандидата;
	КонецЕсли; 
	Если ВМассивеБылиНовыеПодходящиеОбъекты Тогда
		Если ЭтаФорма <> Неопределено Тогда
			ЭтаФорма.НеобходимоВыполнитьКонтроль = Истина;
			Если ЭтаФорма.Открыта() Тогда
				ЭтаФорма.ПодключитьОбработчикОжидания("ПослеИзмененияСоставаКандидатов", 0.1, Истина);
			КонецЕсли; 
		КонецЕсли; 
	КонецЕсли; 
	Возврат ВМассивеБылиНовыеПодходящиеОбъекты;

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

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

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

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

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

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

Функция НайтиПомеченныеНаУдалениеЛкс(Параметры) Экспорт 
	ирОбщий.СостояниеЛкс("Выполняется поиск объектов, помеченных на удаление...");
	Попытка
		//Если ирКэш.НомерИзданияПлатформыЛкс() = "83" Тогда
		//	// Баг платформы 8.3 https://partners.v8.1c.ru/forum/t/1438019/m/1438019
		//	ПомеченныеОбъекты = НайтиПомеченныеНаУдаление(, ЗначениеВыбора);
		//Иначе
		ПомеченныеОбъекты = НайтиПомеченныеНаУдаление();
		//КонецЕсли; 
	Исключение
		ирОбщий.СообщитьЛкс(ОписаниеОшибки(), СтатусСообщения.Внимание);
	КонецПопытки;
	Результат = Новый Структура;
	Результат.Вставить("ПомеченныеОбъекты", ПомеченныеОбъекты);
	Результат.Вставить("МассивРазрешенныхТипов", Параметры.МассивРазрешенныхТипов);
	Возврат Результат;
КонецФункции

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

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

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

Процедура ДобавитьКолонкуТаблицыСвязи(Знач НайденныеСсылки)
	
	НайденныеСсылки.Колонки.Добавить("ТаблицаСвязи", Новый ОписаниеТипов("Строка",,Новый КвалификаторыСтроки(100)));

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

Процедура ЗакончитьЗамерТаблицы(Знач ЗамерПоиска, Знач МоментНачалаТаблицы, Знач ИмяТаблицы)
	
	ДлительностьТаблицы = ТекущаяДата() - МоментНачалаТаблицы;
	Если ДлительностьТаблицы > 19 Тогда
		ирОбщий.СообщитьЛкс(ирОбщий.СтрШаблонЛкс("Поиск по таблице %1 выполнен за %2 секунд", ИмяТаблицы, ДлительностьТаблицы));
	КонецЕсли;
	Если ДлительностьТаблицы > 4 Тогда
		СтрокаЗамера = ЗамерПоиска.Добавить();
		СтрокаЗамера.Таблица = ИмяТаблицы;
		СтрокаЗамера.Длительность = ДлительностьТаблицы;
	КонецЕсли;

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

Функция ОбновитьДанныеКандидатов(ТаблицаОбъектов = Неопределено, МинимизироватьТипы = Истина, ДополнительноеПоле = "") Экспорт 
	
	Если ТаблицаОбъектов = Неопределено Тогда
		ТаблицаОбъектов = УдаляемыеОбъекты.Выгрузить();
	КонецЕсли; 
	Если МинимизироватьТипы Тогда
		ТаблицаОбъектов = ирОбщий.СузитьТипыКолонокТаблицыБезПотериДанныхЛкс(ТаблицаОбъектов); // Так будет меньше неявных соединений в запросе
	КонецЕсли; 
	Запрос = Новый Запрос;
	ТекстЗапроса = "
	|ВЫБРАТЬ РАЗЛИЧНЫЕ * ПОМЕСТИТЬ ТЗ ИЗ &ТЗ КАК ТЗ;
	|ВЫБРАТЬ ТЗ.Разрешен, ТЗ.Удаляется, ТЗ.НеудаляемыхСсылок, ТЗ.Ссылок, ТЗ.Метаданные, ТЗ.Ссылка, ЕСТЬNULL(ТЗ.Ссылка.ПометкаУдаления, ИСТИНА) КАК ПометкаУдаления,
	|Представление(ТЗ.Ссылка) КАК Представление, ЕСТЬNULL(ТЗ.Ссылка.Предопределенный, Ложь) КАК Предопределенный,
	|ВЫБОР КОГДА ЕСТЬNULL(ТЗ.Ссылка.ПометкаУдаления, ИСТИНА) ТОГДА 1 КОГДА ЕСТЬNULL(ТЗ.Ссылка.Предопределенный, Ложь) ТОГДА 2 ИНАЧЕ 0 КОНЕЦ КАК ИндексКартинки ";
	Если ЗначениеЗаполнено(ДополнительноеПоле)  Тогда
		ТекстЗапроса = ТекстЗапроса + "
		|, ТЗ.Ссылка." + ДополнительноеПоле + " КАК " + ДополнительноеПоле;
	КонецЕсли; 
	ТекстЗапроса = ТекстЗапроса + "
	|ИЗ ТЗ КАК ТЗ";
	Запрос.Текст = ТекстЗапроса;
	Запрос.УстановитьПараметр("ТЗ", ТаблицаОбъектов);
	
	// Проверяем наличие хотя бы одного типа с полем Предопределенный
	ПроверочныйЗапрос = Новый ПостроительЗапроса;
	ПроверочныйЗапрос.Текст = ирОбщий.ЗапросИмитаторКоллекцииПолейЛкс(ТаблицаОбъектов.Колонки);
	ПроверочныйЗапрос.ЗаполнитьНастройки();
	Если ПроверочныйЗапрос.ДоступныеПоля.Ссылка.Поля.Найти("Предопределенный") = Неопределено Тогда 
		Запрос.Текст = СтрЗаменить(Запрос.Текст, "ТЗ.Ссылка.Предопределенный", "Ложь");
	КонецЕсли; 
	// Может происходить ошибка платформы 8.3.10 "Несовместимые типы" https://partners.v8.1c.ru/forum/t/1617826/m/1617826
	// Если она произошла, то попробуйте обрабатывать кандидатов мелкими порциями
	ТаблицаОбъектов = Запрос.Выполнить().Выгрузить();
	Возврат ТаблицаОбъектов;

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

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

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

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

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

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

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

ЭтотОбъект.ВыполнятьНаСервере = ирОбщий.РежимОбъектыНаСервереПоУмолчаниюЛкс(Ложь);
