Настройки пользователей / Модуль менеджера

файл
///////////////////////////////////////////////////////////////////////////////////////////////////////
// Copyright (c) 2024, ООО 1С-Софт
// Все права защищены. Эта программа и сопроводительные материалы предоставляются 
// в соответствии с условиями лицензии Attribution 4.0 International (CC BY 4.0)
// Текст лицензии доступен по ссылке:
// https://creativecommons.org/licenses/by/4.0/legalcode
///////////////////////////////////////////////////////////////////////////////////////////////////////

#Если Сервер Или ТолстыйКлиентОбычноеПриложение Или ВнешнееСоединение Тогда

#Область СлужебныеПроцедурыИФункции

#Область ПроцедурыИФункцииОтвечающиеЗаПолучениеНастроекФорм

// Получить список настроек форм для указанного пользователя Пользователь.
//
// Параметры:
//   ИмяПользователя - Строка - имя пользователя информационной базы, для которого нужно
//                              получить настройки форм.
// 
// Возвращаемое значение
//   СписокЗначений - список форм, для которых у переданного пользователя есть настройки.
//
Функция НастройкиВсехФорм(ИмяПользователя)
	
	СписокФорм = ФормыОбъектовМетаданных();
	
	// Добавление стандартных форм в список.
	СписокФорм.Добавить("ВнешняяОбработка.StandardEventLog.Форма.EventsJournal", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Журнал регистрации'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardEventLog.Форма.EventForm", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Журнал регистрации, Событие'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardEventLog.Форма.EventsJournalFilter", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Журнал регистрации, Настройка отбора событий'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardFindByRef.Форма.MainForm", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Поиск ссылок на объект'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardFullTextSearchManagement.Форма.MainForm", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Управление полнотекстовым поиском'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardDocumentsPosting.Форма.MainForm", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Проведение документов'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardDeleteMarkedObjects.Форма.Form", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Удаление помеченных объектов'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardExternalDataSourceManagement.Форма.Form", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Управление внешними источниками данных'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardTotalsManagement.Форма.MainForm", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Управление итогами'") , Ложь, БиблиотекаКартинок.Форма);
	СписокФорм.Добавить("ВнешняяОбработка.StandardActiveUsers.Форма.ActiveUsersListForm", 
		ПрефиксСтандартныхФорм() + "." + НСтр("ru = 'Активные пользователи'") , Ложь, БиблиотекаКартинок.Форма);
		
	Возврат СписокНастроекФорм(СписокФорм, ИмяПользователя);
	
КонецФункции

Функция ПрефиксСтандартныхФорм()
	
	Возврат НСтр("ru = 'Стандартные'");
	
КонецФункции

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

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

	Возврат СписокФорм;
КонецФункции

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

// Конструктор коллекции настроек форм.
// 
// Возвращаемое значение:
//  ТаблицаЗначений:
//    * Значение - Строка
//    * Представление - Строка
//    * Пометка - Булево
//    * Картинка - Картинка
//    * СписокКлючей - СписокЗначений:
//        ** Значение - Строка
//
Функция ПалитраСвойствСпискаНастроекФорм()
	
	Результат = Новый ТаблицаЗначений;
	
	Результат.Колонки.Добавить("Значение",      Новый ОписаниеТипов("Строка"));
	Результат.Колонки.Добавить("Представление", Новый ОписаниеТипов("Строка"));
	Результат.Колонки.Добавить("Пометка",       Новый ОписаниеТипов("Булево"));
	Результат.Колонки.Добавить("Картинка",      Новый ОписаниеТипов("Картинка"));
	Результат.Колонки.Добавить("СписокКлючей",  Новый ОписаниеТипов("СписокЗначений"));
	
	Возврат Результат
	
КонецФункции

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

Функция ОсновнаяФорма(Форма)
	
	Соответствие = Новый Соответствие;
	Соответствие.Вставить("ФормаГруппы", "ОсновнаяФормаГруппы");
	Соответствие.Вставить("ФормаДляВыбора", "ОсновнаяФормаДляВыбора");
	Соответствие.Вставить("ФормаДляВыбораГруппы", "ОсновнаяФормаДляВыбораГруппы");
	Соответствие.Вставить("ФормаОбъекта", "ОсновнаяФормаОбъекта");
	Соответствие.Вставить("ФормаСписка", "ОсновнаяФормаСписка");
	Соответствие.Вставить("Форма", "ОсновнаяФорма");
	Соответствие.Вставить("ФормаНастроек", "ОсновнаяФормаНастроек");
	Соответствие.Вставить("ФормаВарианта", "ОсновнаяФормаВарианта");
	Соответствие.Вставить("ФормаЗаписи", "ОсновнаяФормаЗаписи");
	
	Возврат Соответствие[Форма];
	
КонецФункции

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

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

#Область ПроцедурыИФункцииОтвечающиеЗаКопированиеИУдалениеВсехНастроекПользователя

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

Процедура УдалитьНастройки(МенеджерНастроек, НастройкиИзХранилища, ИмяПользователя)
	
	Для Каждого Настройка Из НастройкиИзХранилища Цикл
		КлючОбъекта = Настройка.КлючОбъекта;
		КлючНастроек = Настройка.КлючНастроек;
		МенеджерНастроек.Удалить(КлючОбъекта, КлючНастроек, ИмяПользователя);
	КонецЦикла;
	
КонецПроцедуры

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

// Для процедуры УдалитьУстаревшиеНастройкиПользователей.
Функция ИменаТиповОбъектов()
	
	ИменаТиповРусский = "ПланОбмена,КритерийОтбора,Константа,Справочник,
	|Последовательность,Документ,ЖурналДокументов,Перечисление,ПланВидовХарактеристик,
	|ПланСчетов,ПланВидовРасчета,РегистрСведений,РегистрНакопления,
	|РегистрБухгалтерии,РегистрРасчета,БизнесПроцесс,Задача"; // @Non-NLS
	
	ИменаТиповАнглийский = "ExchangePlan,FilterCriterion,Constant,Catalog,
	|Sequence,Document,DocumentJournal,Enum,ChartOfCharacteristicTypes,
	|ChartOfAccounts,ChartOfCalculationTypes,InformationRegister,AccumulationRegister,
	|AccountingRegister,CalculationRegister,BusinessProcess,Task"; // @Non-NLS
	
	Имена = Новый Соответствие;
	
	ЯзыкРусский = Метаданные.ВариантВстроенногоЯзыка
		= Метаданные.СвойстваОбъектов.ВариантВстроенногоЯзыка.Русский;
	
	ДобавитьИменаТиповОбъектов(Имена, ИменаТиповРусский, ЯзыкРусский);
	ДобавитьИменаТиповОбъектов(Имена, ИменаТиповАнглийский, Не ЯзыкРусский);
	
	Возврат Имена;
	
КонецФункции

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

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

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

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

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

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

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

#Область ПроцедурыИФункцииОтвечающиеЗаКопированиеИУдалениеВыбранныхНастроекНастроек

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

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

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

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

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

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

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

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

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

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

#Область ПроцедурыИФункцииДляПолученияСпискаПользователейИГруппПользователей

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

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

Функция ТекстЗапросаСпискаВнешнихПользователей(Очистка)
	
	ТекстЗапроса =
	"ВЫБРАТЬ
	|	ВнешниеПользователи.Ссылка КАК Пользователь,
	|	Неопределено КАК Подразделение,
	|	Неопределено КАК ФизическоеЛицо
	|ИЗ
	|	Справочник.Пользователи КАК ВнешниеПользователи
	|ГДЕ
	|	&КромеНедействительных
	|	И &КромеПомеченныхНаУдаление
	|	И ВнешниеПользователи.Ссылка <> &ПользовательИсточник
	|	И НЕ(ВнешниеПользователи.ИдентификаторПользователяИБ = &ПустойУникальныйИдентификатор
	|				И ВнешниеПользователи.Ссылка <> &НеуказанныйПользователь)";
	
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&КромеПомеченныхНаУдаление",
		?(Очистка, "Истина", "НЕ ВнешниеПользователи.ПометкаУдаления"));
	ТекстЗапроса = СтрЗаменить(ТекстЗапроса, "&КромеНедействительных",
		?(Очистка, "Истина", "НЕ ВнешниеПользователи.Недействителен"));
	Возврат ТекстЗапроса;
	
КонецФункции


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

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

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

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

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

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

#Область ВспомогательныеПроцедурыИФункции

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

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

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

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

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

Процедура ДобавитьТипФормыВПредставлениеАвтогенерируемойФормы(Объект, Форма, ИмяФормы)
	
	Если Форма = "ФормаСписка" Тогда
		ИмяФормы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 (список)'"), ИмяФормы);
	ИначеЕсли Форма = "ФормаДляВыбора" Тогда
		ИмяФормы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 (выбор)'"), ИмяФормы);
	ИначеЕсли Форма = "ФормаДляВыбораГруппы" Тогда
		ИмяФормы = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(НСтр("ru = '%1 (группа)'"), ИмяФормы);
	КонецЕсли;
	
КонецПроцедуры

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

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

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

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

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

Функция ХранилищеНастроекПоИмени(НазваниеХранилища)
	
	Если НазваниеХранилища = "ХранилищеПользовательскихНастроекОтчетов" Тогда
		Возврат ХранилищеПользовательскихНастроекОтчетов;
	ИначеЕсли НазваниеХранилища = "ХранилищеОбщихНастроек" Тогда
		Возврат ХранилищеОбщихНастроек;
	Иначе
		Возврат ХранилищеСистемныхНастроек;
	КонецЕсли;
	
КонецФункции

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

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

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

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

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

#Область ПроцедурыИФункцииДляФормНастройкиПользователейИВыборНастроек

Процедура ЗаполнитьСпискиНастроек(Параметры) Экспорт
	ЗаполнитьСписокНастроекОтчетов(Параметры);
	ЗаполнитьСписокНастроекВнешнегоВида(Параметры);
	ЗаполнитьСписокПрочихНастроек(Параметры);
КонецПроцедуры

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

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

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

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

// Объединяет списки значений.
// 
// Параметры:
//  СписокПриемник - СписокЗначений
//  СписокИсточник - СписокЗначений
//
Процедура ОбъединитьСпискиЗначений(СписокПриемник, СписокИсточник)
	Для Каждого Элемент Из СписокИсточник Цикл
		ЗаполнитьЗначенияСвойств(СписокПриемник.Добавить(), Элемент);
	КонецЦикла;
КонецПроцедуры

// Добавляет строку дерева.
// 
// Параметры:
//  ДеревоЗначений - ДеревоЗначений
//  Настройка - Строка
//  Картинка - Картинка
//  Ключи - СписокЗначений
//  Тип - Строка
//  ТипСтроки - Произвольный
//            - Строка
//
Процедура ДобавитьСтрокуДерева(ДеревоЗначений, Настройка, Картинка, Ключи, Тип = "", ТипСтроки = "")
	
	НоваяСтрока = ДеревоЗначений.Строки.Добавить();
	НоваяСтрока.Настройка = Настройка;
	НоваяСтрока.Картинка = Картинка;
	НоваяСтрока.Тип = Тип;
	НоваяСтрока.ТипСтроки = ?(ТипСтроки <> "", ТипСтроки, Тип);
	НоваяСтрока.Ключи = Ключи.Скопировать();
	
КонецПроцедуры

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

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

#КонецЕсли

Связанные материалы