Способ 1
Подходит для типовых конфигураций последних версий, в которых используется БСП (Библиотека стандартных подсистем). Преимущество способа в том, что не требуется доработка конфигурации. Для решения задачи используется подсистема "Свойства" (Дополнительные реквизиты и сведения). Продемонстрирую на примере конфигурации Бухгалтерия предприятия, редакция 3.0 (3.0.115.15). Использовалась версия платформы 1С:Предприятие 8.3 (8.3.17.1851).
К примеру, справочник "Контрагенты" имеет следующую структуру:
Отчет, в который выводится этот справочник с иерархией, будет иметь такую-же структуру:
Отчет выводит иерархию, которая создана в справочнике.
А нам нужна другая иерархия в отчете, к примеру такая:
Элементы справочника в отчете относятся совсем к другим "Группам". К примеру, "Покупатель 1" находится в группе "1 Проверенные покупатели". И другие элементы находятся в других группах.
Самый простой способ - изменить иерархию самого справочника. Но это не всегда возможно. Поэтому рассмотрим другой способ.
Для реализации необходимо добавить для справочника "Контрагенты" дополнительный реквизит (или дополнительное свойство) с типом значения "Дополнительное значение (иерархия)". В качестве значений создать элементы нашей "Альтернативной" иерархии, и затем присвоить эти значения нужным элементам справочника контрагенты.
Значения дополнительных реквизитов для объектов хранятся в табличной части самих объектов. Дополнительные свойства хранятся в отдельном регистре. В случае, когда справочник содержит большое количество элементов, наверное, будет лучше использовать свойство, чтобы минимизировать нагрузку на базу. С другой стороны, реквизит указывается прямо в карточке контрагента, что на мой взгляд удобнее для пользователя.
Далее будем использовать дополнительный реквизит.
Затем в запросе, на основании которого строится отчет, нужно помимо ссылки на элемент справочника "Контрагенты" выбрать поле со значением дополнительного реквизита, отвечающего за альтернативную иерархию. После чего, это поле нужно использовать в качестве группировки верхнего уровня, в настройках СКД.
Пример создания "альтернативной" иерархии:
Раздел "Администрирование" - "Общие настройки" - "Дополнительные реквизиты и сведения". Устанавливаем одноименную галочку, если не установлена. Далее "Дополнительные реквизиты". В левом окне ищем элемент "Справочник "Контрагенты", выделяем его. Нажимаем "Добавить - Новый". В поле "Наименование" пишем название новой иерархии (это название затем понадобится в качестве параметра запроса). Нужно выбрать уникальное наименование, которое не использовалось и не будет использоваться для других дополнительных реквизитов или свойств. Тип значения выбираем "Дополнительное значение (иерархия)". Записываем, и на закладке "Значения" создаем нужную иерархию. После чего, нажимаем "Записать и закрыть".
После чего, заполняем значение дополнительного реквизита у нужных контрагентов:
Пример запроса к базе данных и настройки СКД:
Дополнительные реквизиты хранятся в одноименной табличной части справочника, в реквизите "Значение". Поэтому для получения данных идет обращение именно к табличной части. Дополнительно нужно поставить отбор по наименованию свойства.
ВЫБРАТЬ
КонтрагентыДополнительныеРеквизиты.Значение КАК АльтернативнаяИерархия,
КонтрагентыДополнительныеРеквизиты.Ссылка КАК Контрагент,
КонтрагентыДополнительныеРеквизиты.Ссылка.Наименование КАК Наименование
ИЗ
Справочник.Контрагенты.ДополнительныеРеквизиты КАК КонтрагентыДополнительныеРеквизиты
ГДЕ
КонтрагентыДополнительныеРеквизиты.Свойство.Наименование = "АльтернативнаяИерархия"
В настройках СКД нужно выбрать поле "АльтернативнаяИерархия" в качестве группировки первого уровня, с типом группировки "Иерархия". Далее пойдут детальные записи:
Нужно иметь в виду, что в выборку попадут только те контрагенты, у которых дополнительный реквизит заполнен. Что делать с остальными контрагентами? Возможны 2 варианта.
1. Заполнить значения для всех контрагентов, установить признак "Заполнять обязательно" в форме редактирования дополнительного реквизита. Тогда при добавлении нового контрагента (по крайне мере) в пользовательском режиме система будет контролировать заполнение реквизита.
2. Дописать запрос таким образом, чтобы контрагенты с незаполненным значением реквизита попадали в одну из "Групп" альтернативной иерархии.
Пример запроса, в который попадут все контрагенты:
ВЫБРАТЬ
КонтрагентыДополнительныеРеквизиты.Значение КАК АльтернативнаяИерархия,
КонтрагентыДополнительныеРеквизиты.Ссылка КАК Контрагент
ПОМЕСТИТЬ ВТ_КонтрагентыСДопРеквизитом
ИЗ
Справочник.Контрагенты.ДополнительныеРеквизиты КАК КонтрагентыДополнительныеРеквизиты
ГДЕ
КонтрагентыДополнительныеРеквизиты.Свойство.Наименование = "АльтернативнаяИерархия"
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
ЗначенияСвойствОбъектовИерархия.Ссылка КАК АльтернативнаяИерархия
ПОМЕСТИТЬ ВТ_ВсеКонтрагенты
ИЗ
Справочник.Контрагенты КАК Контрагенты,
Справочник.ЗначенияСвойствОбъектовИерархия КАК ЗначенияСвойствОбъектовИерархия
ГДЕ
ЗначенияСвойствОбъектовИерархия.Наименование = "3 В работе"
И НЕ Контрагенты.ЭтоГруппа
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ВсеКонтрагенты.Контрагент КАК Контрагент,
ВТ_ВсеКонтрагенты.АльтернативнаяИерархия КАК АльтернативнаяИерархия
ПОМЕСТИТЬ ВТ_КонтрагентыБезДопРеквизита
ИЗ
ВТ_ВсеКонтрагенты КАК ВТ_ВсеКонтрагенты
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_КонтрагентыСДопРеквизитом КАК ВТ_КонтрагентыСДопРеквизитом
ПО ВТ_ВсеКонтрагенты.Контрагент = ВТ_КонтрагентыСДопРеквизитом.Контрагент
ГДЕ
ВТ_КонтрагентыСДопРеквизитом.Контрагент ЕСТЬ NULL
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_КонтрагентыСДопРеквизитом.АльтернативнаяИерархия КАК АльтернативнаяИерархия,
ВТ_КонтрагентыСДопРеквизитом.Контрагент КАК Контрагент,
ВТ_КонтрагентыСДопРеквизитом.Контрагент.Наименование КАК КонтрагентНаименование
ИЗ
ВТ_КонтрагентыСДопРеквизитом КАК ВТ_КонтрагентыСДопРеквизитом
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ВТ_КонтрагентыБезДопРеквизита.АльтернативнаяИерархия,
ВТ_КонтрагентыБезДопРеквизита.Контрагент,
ВТ_КонтрагентыБезДопРеквизита.Контрагент.Наименование
ИЗ
ВТ_КонтрагентыБезДопРеквизита КАК ВТ_КонтрагентыБезДопРеквизита
1. Во временную таблицу ВТ_КонтрагентыСДопРеквизитом выбираем ссылки на контрагентов, для которых доп реквизит заполнен, и ссылку на значение доп реквизита.
2. Во временную таблицу ВТ_ВсеКонтрагенты выбираем ссылки на всех контрагентов, и ссылку на значение доп реквизита, который дальше будем использовать для тех контрагентов, у которых доп реквизит не заполнен.
3. Во временную таблицу ВТ_КонтрагентыБезДопРеквизита выбираем ссылки на тех контрагентов у которых доп реквизит не заполнен, и ссылку на значение доп реквизита, который дальше будем использовать для тех контрагентов, у которых доп реквизит не заполнен.
4. Объединяем временные таблицы ВТ_КонтрагентыСДопРеквизитом и ВТ_КонтрагентыБезДопРеквизита
В результате контрагенты с незаполненным реквизитом альтернативной иерархии попали в "Группу" "3 В работе":
Как связать получившуюся таблицу альтернативной иерархии с таблицей регистра в котором содержаться показатели для вывода в отчет? Очень просто: левым или внутренним соединением. Левым - в случае если нужно вывести всех контрагентов, даже без показателей. Внутренним - если в отчет должны попасть только те контрагенты, по которым есть показатели.
Пример запроса, в котором происходит соединение альтернативной иерархии с таблицей регистра
ВЫБРАТЬ
КонтрагентыДополнительныеРеквизиты.Значение КАК АльтернативнаяИерархия,
КонтрагентыДополнительныеРеквизиты.Ссылка КАК Контрагент
ПОМЕСТИТЬ ВТ_КонтрагентыСДопРеквизитом
ИЗ
Справочник.Контрагенты.ДополнительныеРеквизиты КАК КонтрагентыДополнительныеРеквизиты
ГДЕ
КонтрагентыДополнительныеРеквизиты.Свойство.Наименование = "АльтернативнаяИерархия"
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Контрагенты.Ссылка КАК Контрагент,
ЗначенияСвойствОбъектовИерархия.Ссылка КАК АльтернативнаяИерархия
ПОМЕСТИТЬ ВТ_ВсеКонтрагенты
ИЗ
Справочник.Контрагенты КАК Контрагенты,
Справочник.ЗначенияСвойствОбъектовИерархия КАК ЗначенияСвойствОбъектовИерархия
ГДЕ
ЗначенияСвойствОбъектовИерархия.Наименование = "3 В работе"
И НЕ Контрагенты.ЭтоГруппа
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_ВсеКонтрагенты.Контрагент КАК Контрагент,
ВТ_ВсеКонтрагенты.АльтернативнаяИерархия КАК АльтернативнаяИерархия
ПОМЕСТИТЬ ВТ_КонтрагентыБезДопРеквизита
ИЗ
ВТ_ВсеКонтрагенты КАК ВТ_ВсеКонтрагенты
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_КонтрагентыСДопРеквизитом КАК ВТ_КонтрагентыСДопРеквизитом
ПО ВТ_ВсеКонтрагенты.Контрагент = ВТ_КонтрагентыСДопРеквизитом.Контрагент
ГДЕ
ВТ_КонтрагентыСДопРеквизитом.Контрагент ЕСТЬ NULL
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_КонтрагентыСДопРеквизитом.АльтернативнаяИерархия КАК АльтернативнаяИерархия,
ВТ_КонтрагентыСДопРеквизитом.Контрагент КАК Контрагент,
ВТ_КонтрагентыСДопРеквизитом.Контрагент.Наименование КАК КонтрагентНаименование
ПОМЕСТИТЬ ВТ_АльтернативнаяИерархия
ИЗ
ВТ_КонтрагентыСДопРеквизитом КАК ВТ_КонтрагентыСДопРеквизитом
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ВТ_КонтрагентыБезДопРеквизита.АльтернативнаяИерархия,
ВТ_КонтрагентыБезДопРеквизита.Контрагент,
ВТ_КонтрагентыБезДопРеквизита.Контрагент.Наименование
ИЗ
ВТ_КонтрагентыБезДопРеквизита КАК ВТ_КонтрагентыБезДопРеквизита
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВТ_АльтернативнаяИерархия.АльтернативнаяИерархия КАК АльтернативнаяИерархия,
ХозрасчетныйОстатки.СуммаОстатокДт КАК СуммаОстатокДт,
ВТ_АльтернативнаяИерархия.Контрагент КАК Контрагент,
ВТ_АльтернативнаяИерархия.КонтрагентНаименование КАК КонтрагентНаименование
ИЗ
ВТ_АльтернативнаяИерархия КАК ВТ_АльтернативнаяИерархия
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Хозрасчетный.Остатки(, Счет = &Счет, &ВидСубконтоКонтрагенты, ) КАК ХозрасчетныйОстатки
ПО ВТ_АльтернативнаяИерархия.Контрагент = ХозрасчетныйОстатки.Субконто1
1. Собираются данные для построения альтернативной иерархии, по аналогии с предыдущим запросом. Отличие в том, что они помещаются во временную таблицу ВТ_АльтернативнаяИерархия, а не выводятся в отчет.
2. Временная таблица ВТ_АльтернативнаяИерархия соединяется с виртуальной таблицей "Остатки" регистра бухгалтерии "Хозрасчетный".
Настройки структуры отчета СКД остались прежние. Разве что добавились параметры.
Отчет примет следующий вид:
Справочник "Контрагенты" представлен в отчете в "другой" иерархии, отличной от той, что определена в самом справочнике. В отчет выводятся показатели, полученные из регистров системы.
Дополнительная информация:
Объекты метаданных, связанные с данным способом реализации:
- Справочник.НаборыДополнительныхРеквизитовИСведений - в предопределённом элементе справочника с наименованием "Справочник "Контрагенты"" хранится информация о том, что у справочника "Контрагенты" имеется дополнительный реквизит.
- ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения - в элементе плана видов характеристик хранится такая информация о доп реквизите как его наименование, тип значения, признак обязательно заполнения и прочие
- Справочник.ЗначенияСвойствОбъектовИерархия - в справочнике хранятся значения дополнительных реквизитов, подчинен плану видов характеристик "ДополнительныеРеквизитыИСведения", без привязки к элементам справочника контрагенты. Просто значения нашей иерархии.
- Справочник.Контрагенты.ДополнительныеРеквизиты - в табличной части каждого элемента справочника контрагенты хранится значение его дополнительного реквизита (если установлен).
Пример отчета прилагается.
Способ 2
Предположим, первый способ вам не подходит: нет БСП, но можно вносить изменения в конфигурацию. Тогда можно заняться хардкодом. Пусть справочник контрагентов имеет такую же структуру как в способе 1, и нам нужно вывести в отчет другую.
Решение: создаем новый справочник, в котором будет описана иерархия, назовём его например "АльтернативнаяИерархия".
Пример структуры нового справочника:
В справочник "Контрагенты" добавляем новый реквизит "АльтернативнаяИерархия" с типом значения "СправочникСсылка.АльтернативнаяИерархия". В качестве значений реквизита будут выступать ЭЛЕМЕНТЫ нижних уровней справочника "АльтернативнаяИерархия".
Запрос в таком решении может быть довольно простым. Достаточно выбрать подходящую виртуальную таблицу регистра, выбрать поле контрагент, новый реквизит контрагента "АльтернативнаяИерархия" и необходимые ресурсы.
ВЫБРАТЬ
ПродажиОбороты.Контрагент КАК Контрагент,
ПродажиОбороты.Контрагент.АльтернативнаяИерархия КАК КонтрагентАльтернативнаяИерархия,
ПродажиОбороты.СуммаОборот КАК СуммаОборот
ИЗ
РегистрНакопления.Продажи.Обороты КАК ПродажиОбороты
В настройках отчета первой группировкой будет наш новый реквизит "АльтернативнаяИерархия", второй - контрагент. Ну и про ресурсы нужно не забыть.
Настройки отчета и выходная форма:
Пример отчета в составе простой конфигурации прилагается.