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

Например, справочник товаров может быть сгруппирован по виду товаров (как это обычно и делается) - Промтовары, Бакалея, Алкоголь и т.п., но может быть сгруппирован и по производителям товаров, т.е. Наши товары, Импортные товары, Российские, Китайские и т.п.

Ожидания не оправдались, однако восьмерка легко позволяет сделать такую иерархию самостоятельно. Единственное неудобство - это не делается автоматически, системой.

Моделирование нескольких иерархий

Имеются иерархические (с группами) справочники товаров Номенклатура и производителей Производители.

Для иерархии по производителям в справочнике Номенклатура заведем реквизит Производитель типа СправочникСсылка.Производители.

Заведем новую форму списка для Номенклатуры. На ней разместим поле ДереваЗначений "МастерДерево" и поле ТаблицыЗначений "ПодчТаблица":

В МастерДерево будет отображаться группы текущей иерархии. А в ПодчТаблица будут выводиться только те товары, которые попадают в группу иерархии. В надписи НадпГруппа будет отображаться текущая выбранная группа МастерДерево, а в надписи НадписьОтбор - список элементов текущей иерархии, входящих в эту группу.

Для учебных целей мы рассмотрим только отбор по иерархии Производители. Можно конечно в дереве делать иерархию на выбор - по Производителю, по группам номенклатуры, по поставщику и т.п. Было бы желание.

Вот как выглядит форма, когда мы просматриваем товары отечественных производителей:

А вот так, когда просматриваем импортных производителей:

 

А вот просмотр только по одному производителю:

Когда пользователь выбирает группу из дерева (щелкает дважды мышью или нажимает Enter, происходит событие Выбор объекта формы МастерДерево). В обработчике этого события содержится код, который отображает ПодчТаблица согласно выбранной группе:

Процедура СправочникДеревоВыбор(Элемент, ВыбраннаяСтрока, Колонка, СтандартнаяОбработка)

	//Находим отбор по производителю
	//Внимание! Его может и не быть...
	ТекОтбор=ЭлементыФормы.ПодчТаблица.Значение.Отбор["Производитель"];

	//Если группа в дереве не выбрана (в начале)
	Если  ЭлементыФормы.МастерДерево.ТекущиеДанные=Неопределено Тогда
		МастерГруппа=Неопределено;
		ТекОтбор.Использование=Ложь;
	Иначе
	
		МастерГруппа=ЭлементыФормы.МастерДерево.ТекущиеДанные.Ссылка;

		//Формируем список производителей, которые входят
		//в группу МастерГруппа                    
		
		Список=Новый СписокЗначений;	//Создаем список значений

		ТекстЗапроса=" //Условие запроса - элемент входит в группу
		|ВЫБРАТЬ
		|	МастерСправочник.Ссылка КАК Элемент
		|ИЗ
		|  	Справочник.Производители КАК МастерСправочник
		|ГДЕ
		|  	МастерСправочник.Ссылка В ИЕРАРХИИ (&ГруппаИерархии)
		|";

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

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

		//Устанавливаем отбор
		//Вид - в списке, значение - наш список
		ТекОтбор.ВидСравнения=ВидСравнения.ВСписке;
		ТекОтбор.Значение=Список;


		//Включаем отбор
		ТекОтбор.Использование=Истина;
	КонецЕсли;


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

Дополнительно нужно завести реквизиты формы:

МастерСправочник - служит источником записей для МастерДерево, а ПодчСправочник - источником записей для ПодчТаблица.

При выборе производителя в МастерДерево в ПодчТаблица устанавливается отбор по производителям, входящим в выбранную группу производителя, или (если выбран элемент) с выбранным производителем.

Объект, к которому привязано табличное поле в 1С8 имеет возможность использовать отбор. Отборов может быть несколько, причем различных (по коду, наименованию, диапазону значений, подчинению группе, вхождению в список). Получить привязанный объект можно через ЭлементыФормы.ПодчТаблица.Значение, а элемент отбора по производителю через ЭлементыФормы.ПодчТаблица.Значение.Отбор["Производитель"]. Отбор и элемент отбора - это тоже объекты и описания их можно прочитать в RTFM.

Так как фильтра вхождения реквизита в группу не существует, формируем простой запрос, который выдает нам список элементов, соответствующих выбранному производителю (иерархически входящих в выбранную группу). И по данному списку устанавливаем отбор, затем его включаем.

Если производитель не выбран, отбор отключается.

Код простой и сердитый. Можете брать за основу.

Вывод в формы произвольной таблицы значений

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

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

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

Приведенный ниже код формирует список элементов справочника Номенклатура и выводит его в таблицу значений Таб а затем в табличное поле ТабПоле на форме, используя реквизит формы ТабПолеДанные:

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

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