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