Полезные процедуры по работе с СКД и динамическими списками (часть 3)

Публикация № 944933

Разработка - Практика программирования

процедуры процедура функции функция СКД отбор отборы Компоновка Схема универсальные универсальная компоновки библиотечные универсальная

Еще пара приемов в копилку разработчика.

1. Копирование настроек СКД и динамических списков

Приведенная ниже функция позволяет скопировать любой элемент коллекции СКД со всеми вложенными в него элементами. Умеет копировать все элементы, перечисленные в таблицах в другой моей публикации.

Варианты использования:

  • Вариант 1. На форме есть динамический список с отбором. Необходимо при открытии этой формы восстанавливать отборы, настроенные пользователем ранее.
  • Вариант 2. Необходимо полностью или частично перенести настройки между схемами компоновки, компоновщиками настроек, динамическими списками.

Пример сохранения отборов для динамического списка.
- Создадим на форме динамический список СписокКонтрагенты.
- Выведем отбор списка в виде поля
- Создадим реквизит формы СписокКонтрагентыОтборСохранение с типом Произвольный

 

- При изменении отбора будем записывать новый отбор в реквизит СписокКонтрагентыОтборСохранение
- При восстановлении настроек будем заполнять отбор из сохраненного реквизита

&НаКлиенте
Процедура СписокКонтрагентыОтборПриИзменении(Элемент)
	СписокКонтрагентыОтборСохранение = СписокКонтрагенты.Отбор;
КонецПроцедуры

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

 

Это демонстрация использования функции копирования на примере отборов динамических списков. Но она универсальна и применялась мною для программной работы с настройками СКД.

 

2. Предопределенные отборы динамических списков

Пусть на форме есть два динамических списка Контрагенты и Договоры. 
Необходимо при двойном щелчке по первому списку, устанавливать отбор во втором списке. 
При этом пользователь имеет возможность установить дополнительные условия в отборе второго списка и они должны сохраняться.
Например, пользователь может установить условие, чтобы отображались только договоры с покупателем. А при щелчке по контрагенту, необходимо, чтобы в отборе изменился контрагент, но не удалился отбор по типу договора. 
В нашем упрощенном примере предопределенное условие только одно. Но предопределенных условий может быть и несколько, например, еще по периоду, если это выборка по документам контрагента.

Пример решения.
- Все предопределенные условия помещаем в группу "И". 
- У этой группы задаем некое предопределенное представление
- Перед установкой отбора ищем предопределенную группу и удаляем ее
- Затем создааем ее снова и помещаем в нее все необходимые условия

&НаКлиенте
Процедура СписокКонтрагентыВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
	СтандартнаяОбработка = Ложь;
	СписокКонтрагентыВыборНаСервере(ВыбраннаяСтрока);
КонецПроцедуры

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

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

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

 

Применение метода рассматривается на примере отборов динамических списков, но этот же принцип можно использовать для работы с настройками СКД.

 

Заключение

Тестировалось на платформе 8.3.8+, режим совместимости 8.2.13+. Но описанные приемы должны работать и на более ранних версиях 1С 8.
 

Специальные предложения

Комментарии
Избранное Подписка Сортировка: Древо
1. VmvLer 19.11.18 17:19 Сейчас в теме
Такая подача материала характеризуется очень просто - "в час по чайной ложе".
Если быть честным до конце, то это просто халтура.

мое мнение может не совпадать ...бла бла бла.
2. json 2571 19.11.18 21:23 Сейчас в теме
(1) Тролли всегда найдут до чего докопаться. Их мнение меня слабо интересует
3. al_zzz 151 20.11.18 08:04 Сейчас в теме
(1) Сказал человек, имеющий нулевой вклад в сообщество...
denis_aka_wolf; +1 Ответить
4. oleg-x 14 20.11.18 18:56 Сейчас в теме
(1) Верну тебе один минус, но все же. Может и по чайной ложке, но из таких маленьких статей, потом можно собрать всю необходимую информации. Если сделать конкретный запрос, получишь ссылку на статью (если она есть) с конкретным ответом. И не придется листать огромную статью, в поисках нужного материала.
А если модераторы пропустили статью, значит какое то право на жизнь она имеет.
5. triviumfan 13 20.11.18 21:13 Сейчас в теме
Ребят, это же все есть в БСП...
КомпоновкаДанныхКлиентСервер.СкопироватьЭлементы();
КомпоновкаДанныхКлиентСервер.ДобавитьОтбор();
...
rpgshnik; mitia.mackarevich; +2 Ответить
6. oleg-x 14 20.11.18 21:17 Сейчас в теме
(5) А если я не пользуюсь БСП и не хочу копаться в этом монстре? :-)
7. json 2571 20.11.18 21:19 Сейчас в теме
(5) в 2.4?
В 2.3.5 я такого не нашел
8. mitia.mackarevich 28 21.11.18 02:55 Сейчас в теме
(7) Плюсану, но "Не нашел как добавить отбор в элемент"????? что же такое творится то !!!
ОбщегоНазначенияКлиентСервер - живет там не первый год вместе со всем остальным
по поводу первого - сериализатором XDTО не проще воспользоваться для сохранения настроек и всего прочего - благо все сериализуется? Все равно если реквизит сохранятеся в хранилище настроек форм - там то он хранится в сериализованном виде
11. json 2571 21.11.18 07:09 Сейчас в теме
(8) настройки динамических списков не сохраняются. Нет там галочки Сохранение, посмотрите повнимательнее.
Если же их сериализовать, то чтобы потом вставить в динамический список, нужна функция копирования отборов. Я такой функции в типовых конфигурациях не встречал. Если встречали вы, то просьба скинуть в каком модуле она лежит и как называется

И кстати, предложенная мною функция копирует не только отборы, а любые элементы настроек. Отборы приведены в качестве примера
20. mitia.mackarevich 28 21.11.18 10:09 Сейчас в теме
(11)
) настройки динамических списков не сохраняются.

Я про реквизиты формы в целом писал - предварительная сериализация проходит, как еще они иначе храняться=)
21. json 2571 21.11.18 10:11 Сейчас в теме
(20)
да, прошу прощения, неправильно понял. С телефона читал.
9. json 2571 21.11.18 06:41 Сейчас в теме
(5)
(8)
Коллеги, позвольте уточнить, что во второй части публикации основная мысль не "как добавить отбор", а "как установить служебный отбор в списке, в котором уже могут присутствовать ручные и служебные отборы". Я этот служебный отбор назвал Предопределенным. Моя идея в том, чтобы собрать их в группу, а группу узнавать по представлению. Тогда служебные отборы будут жить вместе с ручными и мы не удалим лишнего при переключении служебного отбора.
Подумаю, как лучше сформулировать эту мысль в публикации, чтобы не возникало таких двусмысленностей.
12. VmvLer 21.11.18 09:07 Сейчас в теме
(9) эта идея - велик, причем устаревшей модели

а вопящите тут, мол, "чайная ложка" это класс - просто лентяи.

Конечно, можно отдать свой мозг во власть поисковых гагантов и по малейшему поводу
вяло шептать "ок, гугл найди на инфостар ченить по отборам"

А можно использовать мозг по назначению - изучить общие модули и всегда быть на коне
полученных знаний.
13. json 2571 21.11.18 09:19 Сейчас в теме
(12)
эта идея - велик, причем устаревшей модели

это вы как обычно троллите?
Или сможете привести доказательство, что вы это уже где-нибудь встречали?

А можно использовать мозг по назначению - изучить общие модули и всегда быть на коне
полученных знаний.

Слова человека, который прикипел к одной конфигурации и не представляет себе ситуации, когда разработчик может поддерживать десять и более конфигураций одновременно, с разными версиями БСП, с разными режимами совместимости.
14. VmvLer 21.11.18 09:30 Сейчас в теме
(13) могу, но зачем я буду тратить время на очевидное, пролистайте общие модули современных конфигураций и вам станет ясно насколько банальна эта тема.
15. json 2571 21.11.18 09:36 Сейчас в теме
(14) если бы могли, то сделали.
А если не хотите тратить свое время - то что вы тут комментируете тогда.
Дело не во времени, а в том, что вы сначала написали, а потом не можете подтвердить свои слова. Так делают обычные балаболы
Dmitri93; the1; +2 Ответить
16. VmvLer 21.11.18 09:47 Сейчас в теме
(15) "лечить" наивность труд неблагодарный, вы должны сами все найти и усвоить, тогда будет толк. Лучший способ это сделать - балаболить.

"хотите про это поговорить?"
17. json 2571 21.11.18 09:50 Сейчас в теме
(16) спасибо за ваши советы, о великий разработчик, зарегестрированный 1,5 года назад даже без аватара.
Буду счастлив, если вы избавите меня от своих комментариев
18. VmvLer 21.11.18 09:58 Сейчас в теме
(17) это ж хорошо, если мои слова делают вас счастливее, а ум пытливым

будет отлично - если вы избавитесь от привычки уходить от темы на личности.
19. json 2571 21.11.18 10:00 Сейчас в теме
(18)
а дело не в личности, а в вашей компетенции.
Сколько я ни пытаюсь, не могу понять, почему ваши слова достойны внимания. Что вы из себя представляете как специалист. Чем вы отличаетесь от тролля

С любого конкретного вопроса вы съезжаете. Типа нет времени или еще какая причина.
Но зато грязь подливаете вы охотно, причем не только в мою публикацию
10. json 2571 21.11.18 06:50 Сейчас в теме
(5)
Немного неточно сформулировал мой вопрос.
Я не могу найти модуль КомпоновкаДанныхКлиентСервер и метод СкопироватьЭлементы().

Установил ещё БСП 3, но не оказалось на компе платформы 12. Чуть позже поковыряюсь. Интересно что там нового появилось.

Спасибо за комментарий. Возможно действительно велосипед, но я ее писал полтора года назад, когда ещё не было новых БСП
22. triviumfan 13 21.11.18 11:19 Сейчас в теме
(10) У меня УТ11, я эти модули видел ещё пару лет назад.
УТ11.3.4.228 используетверсию 2.3.6.196 стандартной подсистемы, но этот модуль появился ещё хз когда... но очень давно.

КомпоновкаДанныхКлиентСервер
////////////////////////////////////////////////////////////­////////////////////
//МОДУЛЬ СОДЕРЖИТ ПРОЦЕДУРЫ И ФУНКЦИИ ДЛЯ РАБОТЫ С СКД
//
////////////////////////////////////////////////////////////­////////////////////

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

// Добавляет в коллекцию оформляемых полей компоновки данных новое поле
//
// Параметры:
//  КоллекцияОформляемыхПолей 	- Массив - коллекция оформляемых полей КД
//  ИмяПоля						- Строка - имя поля
//
// Возвращаемое значение:
//  ОформляемоеПолеКомпоновкиДанных - созданное поле
//
// Пример:
//  Форма.УсловноеОформление.Элементы[0].Поля
//
Функция ДобавитьОформляемоеПоле(КоллекцияОформляемыхПолей, ИмяПоля) Экспорт
	
	ПолеЭлемента 		= КоллекцияОформляемыхПолей.Элементы.Добавить();
	ПолеЭлемента.Поле 	= Новый ПолеКомпоновкиДанных(ИмяПоля);

	Возврат ПолеЭлемента;
	
КонецФункции

// Добавляет в коллекцию отбора новую группу указанного типа.
//
// Параметры:
//	КоллекцияЭлементовОтбора - КоллекцияЭлементовОтбораКомпоновкиДанных - элементы отбора
//	ТипГруппы - ГруппаЭлементовОтбораКомпоновкиДанных - ГруппаИ или ГруппаИли
//
// Возвращаемое значение:
//	ГруппаЭлементовОтбораКомпоновкиДанных - добавленная группа
//
Функция ДобавитьГруппуОтбора(КоллекцияЭлементовОтбора, ТипГруппы) Экспорт

	ГруппаЭлементовОтбора			 = КоллекцияЭлементовОтбора.Добавить(Тип("ГруппаЭлементовОтбораКомпоновкиДанных"));
	ГруппаЭлементовОтбора.ТипГруппы  = ТипГруппы;
	
	Возврат ГруппаЭлементовОтбора;

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

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

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

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

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

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

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

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

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

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

	КонецЦикла;
	
	Возврат ЕстьПоле;
	
КонецФункции //НайтиПоле()

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

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

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

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

Показать
23. json 2571 21.11.18 11:23 Сейчас в теме
(22) выглядит солидно.
Спасибо большое, чуть позже поразбираюсь.
Возможно вы правы, и велосипед имеет место быть))
Оставьте свое сообщение

См. также

Программная работа с настройками СКД

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Нюансы программной работы с настройками системы компоновки данных в отчетах и динамических списках. Обзор всех видов настроек компоновки. Что в каких случаях правильно применять. В качестве примера рассмотрена работа с отборами и группировками.

27.01.2020    4857    ids79    25       

Готовые переносы данных из различных конфигураций 1C Промо

Рекомендуем готовые решения для переноса данных из различных конфигураций 1C. C техподдержкой от разработчиков и гарантией от Инфостарт.

[СКД] Программное создание схемы компоновки данных

Статья Программист Стажер Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Сделаем отчет на СКД полностью программно, без использования макета "схема компоновки данных".

15.01.2020    6865    John_d    20       

1C:Предприятие для программистов: Запросы и отчеты. Второй поток. Онлайн-интенсив с 17 марта по 16 апреля 2020 г. Промо

Данный онлайн-курс предусматривает углубленное изучение языка запросов и возможностей системы компоновки данных, которые понадобятся при разработке отчетов, работающих на платформе “1С:Предприятие” в рамках различных прикладных решений. Курс предназначен для тех, кто уже имеет определенные навыки конфигурирования и программирования в системе “1С:Предприятие”, а также для опытных пользователей различных прикладных решений, которые используют в своей работе отчеты разного назначения.

6500 рублей

СКД не только для отчетов

Статья Программист Нет файла v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

СКД позволяет получать данные из информационной базы не только для вывода в отчеты, но и для других целей. Пример такого использования рассматривается в настоящей статье.

18.09.2019    11460    YPermitin    31       

Базовый курс по управлению ИТ-проектами. Курс проходит с 26 февраля по 22 апреля 2020 года. Промо

Отличительная черта курса - органичное сочетание трех вещей: 1.Теория проектного управления (PMI®+Agile Alliance+Российские ГОСТ+Методологии от 1С); 2. Опыт внедрения продуктов 1С (опыт франчайзи и успешных компаний + тренды Infostart Event и Agile Days); 3. Разбор реальных проблем и рекомендации экспертов по проектам слушателей. Мы будем фиксироваться на тех инструментах, которые реально оказываются полезными в практике руководителей проектов внедрения. Ведущая курса - Мария Темчина.

от 11000 рублей

Агрегатные функции СКД, о которых мало кто знает

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Пользуетесь ли Вы всеми возможными агрегатными функциями, которые предоставляет система компоновки данных? Если Вы используете только: СУММА, КОЛИЧЕСТВО, МИНИМУМ, МАКСИМУМ, СРЕДНЕЕ, то эта статья для Вас.

05.09.2019    23455    ids79    45       

Голосование за доклады на INFOSTART MEETUP Kazan - до 25 февраля. Промо

Выбирайте и голосуйте за самые интересные доклады! Лучшие из лучших попадут в окончательную программу казанского митапа. Оставить свой голос можно до 25 февраля 2020 года.

Три костыля. Сказ про фокусы в коде

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования

Три интересных (или странных) костыля в коде, которые могут помочь в повседневных и не очень задачах.

03.09.2019    13876    YPermitin    70       

INFOSTART MEETUP Krasnodar. 14 февраля 2020 г. Промо

Краснодар станет первым в 2020 году местом, где пройдет региональная встреча IT-специалистов сообщества Инфостарт. Тема мероприятия - управление и технологии автоматизации учета на платформе "1С: Предприятие". Стоимость участия - 5000 рублей. Цена действительна до 26.12.2019.

Отслеживание выполнения фонового задания

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Универсальные функции Разработка

Запуск фонового задания из модуля внешней обработки. Отслеживание выполнения задания в виде прогресса, расположенного на форме.

17.08.2019    17865    ids79    16       

Функции СКД: ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Подробное описание и использование внутренних функций системы компоновки данных: Вычислить, ВычислитьВыражение, ВычислитьВыражениеСГруппировкойМассив, ВычислитьВыражениеСГруппировкойТаблицаЗначений.

08.08.2019    31985    ids79    36       

Сдача регламентированной отчетности из программ 1С Промо

Сдача регламентированной отчетности из программ "1С" во все контролирующие органы без выгрузок и загрузок в другие программы. Для групп компаний действуют специальные предложения.

от 1500 руб.

Фоновое выполнение кода в 1С - это просто

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования

Как легко запускать выполнение в фоне, не прибегая к долгому описанию фоновых процедур.

02.08.2019    17962    avalakh    21       

СКД - наборы данных и связи между ними, создание собственной иерархии, вложенные отчеты

Статья Программист Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования

Набор данных объект. Использование в схеме компоновки нескольких наборов данных. Различные варианты связи наборов: объединение, соединение. Использование иерархии в отчетах на СКД. Создание собственной иерархии, иерархия детальных записей. Использование вложенных схем в отчетах на СКД.

26.07.2019    26279    ids79    9       

Программы для исполнения 488-ФЗ: Маркировка товаров Промо

1 января 2019 года вступил в силу ФЗ от 25.12.2018 № 488-ФЗ о единой информационной системе маркировки товаров с использованием контрольных (идентификационных) знаков, который позволяет проследить движение товара от производителя до конечного потребителя. Инфостарт предлагает подборку программ, связанных с применением 488-ФЗ и маркировкой товаров.

СКД - использование расширений языка запросов, секция ХАРАКТЕРИСТИКИ

Статья Программист Нет файла v8 v8::СКД Бесплатно (free) Инструментарий разработчика Практика программирования

Автоматическое и не автоматическое заполнение полей компоновки данных. Использование расширений языка запросов для СКД «{…}», секция ВЫБРАТЬ, секция ГДЕ, параметры виртуальных таблиц. Автоматизированное использование дополнительных данных в запросе: секция ХАРАКТЕРИСТИКИ.

17.07.2019    19104    ids79    27       

Регистры сведений. За кулисами

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Разработка

Небольшие заметки по внутреннему устройству регистров сведений.

09.07.2019    14555    YPermitin    12       

1C:Предприятие для программистов: Расчетные задачи (зарплата). Онлайн-интенсив с 01 по 17 июня 2020 г. Промо

Данный онлайн-курс предусматривает изучение механизмов платформы “1С:Предприятие”, которые предназначены для автоматизации периодических расчетов, а именно - для расчета зарплаты. Курс предназначен для тех, кто уже имеет определенные навыки конфигурирования и программирования в системе “1С:Предприятие”, а также для опытных пользователей прикладного решения “1С:Зарплата и управление персоналом” и прочих прикладных решений, в которых реализован функционал расчета зарплаты.

4900 рублей

"Меньше копипаста!", или как Вася универсальную процедуру писал

Статья Программист Стажер Нет файла v8 v8::СКД 1cv8.cf Бесплатно (free) Практика программирования Разработка

Программист Вася разбирает подход создания универсальных методов на примере программного вывода СКД.

04.07.2019    11965    SeiOkami    49       

Создание отчетов с помощью СКД - основные понятия и элементы

Статья Программист Нет файла v8 v8::СКД Бесплатно (free) Практика программирования Математика и алгоритмы

Основные принципы работы СКД. Понятия схемы компоновки и макета компоновки. Описание основных элементов схемы компоновки: наборы данных, поля, вычисляемые поля, ресурсы, параметры.

25.06.2019    31219    ids79    17       

Открыто голосование за доклады на INFOSTART MEETUP Krasnodar Промо

Выбирайте и голосуйте за самые интересные доклады, лучшие из них попадут в окончательную программу митапа. Голосование продлится до 30 января 2020 года.

Многопоточное ускорение однопользовательских нагрузок в 1С + Microsoft SQL Server 2017

Статья Программист Нет файла v8 v8::Запросы Бесплатно (free) Практика программирования Разработка

Взаимодействие с Microsoft SQL Server нередко вызывает трудности у 1С-ников, а потому интересны любые моменты, связанные с его использованием. О своем опыте работы с новым SQL Server 2017 участникам конференции Infostart-2018 рассказал директор ООО «Аналитика софт» Дмитрий Дудин.

11.06.2019    16723    dmurk    144       

Регистры накопления. Структура хранения в базе данных

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Разработка

Структура хранения регистров накопления в базе данных для платформы 1С:Предприятие 8.x. Первая часть в серии публикаций.

16.05.2019    26769    YPermitin    27       

Управление ИТ-проектами. Модуль 2: продвинутый онлайн-курс по классическим методам управления проектами. Вебинары проходят с 12 марта по 11 июня 2020 года. Промо

Продвинутый онлайн-курс по классическому управлению ИТ-проектами позволит слушателям освоить инструменты из PMBoK® и 1С:Технологии корпоративного внедрения и научиться их применять для проектов любого масштаба. Курс включает в себя 12 вебинаров и 12 видеолекции, разбор кейсов и рекомендации экспертов по проектам слушателей. Ведущая курса - Мария Темчина.

от 13000 рублей

Выполнение внешней обработки в фоновом задании

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Разработка

Подробное описание подхода к созданию длительной операции на основе внешней обработки. Реализация протестирована на 1С 8.3.12.1714 (x64).

11.05.2019    16976    Eret1k    23       

Выгрузка документа по условию

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Разработка

Что делать, если документы нужно выгружать не все подряд, а по какому-то фильтру: статусу, дате, набору условий... А что если он соответствовал этим условиям, а потом перестал? А если потом опять начал? Такие ситуации заставили попотеть не одного программиста.

25.04.2019    9189    m-rv    2       

Подборка программ для взаимодействия с ЕГАИС Промо

ЕГАИС (Единая государственная автоматизированная информационная система) - автоматизированная система, предназначенная для государственного контроля за объёмом производства и оборота этилового спирта, алкогольной и спиртосодержащей продукции. Инфостарт рекомендует подборку проверенных решений для взаимодействия с системой.

Как прикрутить ГУИД к регистру сведений

Статья Программист Нет файла v8 Бесплатно (free) Практика программирования Перенос данных из 1C8 в 1C8 Разработка

... и немного теории обмена данными. В частности, разберем боль всех, кто пишет небанальные обмены данными: как набору записей регистра сведений назначить гуид и далее использовать его в обмене для идентификации этого набора.

16.04.2019    12296    m-rv    16       

О расширениях замолвите слово...

Статья Программист Стажер Нет файла v8 Бесплатно (free) Практика программирования Разработка

О чём стоит задуматься при принятии решения о создании расширения конфигурации…

07.04.2019    23080    ellavs    125       

Подборка решений для взаимодействия со ФГИС «Меркурий» Промо

С 1 июля 2019 года все компании, участвующие в обороте товаров животного происхождения, должны перейти на электронную ветеринарную сертификацию (ЭВС) через ФГИС «Меркурий». Инфостарт предлагает подборку программ, связанных с этим изменением.

Git-репозитории для 1С-кода (опыт использования при небольших проектах)

Статья Программист Стажер Нет файла v8 Windows Бесплатно (free) Практика программирования Разработка

Инструкции по взаимодействию с Git-репозиторием, которые писались для тех наших программистов, которые вообще никогда не работали с Git (руководства в духе "Как получить код из git-репозитория?", "Как отправить код в git-репозиторий")...

28.03.2019    18315    ellavs    83       

Трюки с внешними источниками данных

Статья Программист Нет файла v8 1cv8.cf Бесплатно (free) Практика программирования Разработка

Некоторые трюки для преодоления ограничений внешних источников данных.

14.03.2019    20135    YPermitin    53