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