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