В процессе разработки на платформе 1С часто возникает задача отобразить в динамическом списке информацию не в стандартном виде, а в кастомном, более удобном для пользователя. Например, для поля Номенклатура вместо стандартного наименования мы хотим видеть строку вида "Артикул + Наименование". Стандартные свойства колонки или попытка установить представление для всего поля целиком через код не дают нужного результата для всех строк списка.
Рассмотрим два основных и наиболее эффективных способа решения этой задачи на управляемых формах.
Этот метод является наиболее производительным и правильным с точки зрения архитектуры платформы. Суть его заключается в том, чтобы добавить в запрос, на котором построен динамический список, новое вычисляемое поле. Это поле будет содержать уже сформированную строку нужного нам вида. Затем на форме мы будем отображать именно это новое поле, а не исходное поле-ссылку.
Разберем по шагам:
ОсновнаяТаблица. Это имя таблицы, из которой динамический список получает данные.ПроизвольныйЗапрос. Если оно уже установлено, отлично. Если нет, установим флаг и нажмем "Открыть" для редактирования текста запроса.+) или функцию языка запросов ВЫРАЗИТЬ. Важно также предусмотреть ситуацию, когда один из реквизитов (например, Артикул) может быть не заполнен. Для этого используем функцию ЕСТЬNULL.Посмотрим на пример. Исходный запрос мог выглядеть так:
ВЫБРАТЬ
ДокументТовары.Ссылка,
ДокументТовары.Номер,
ДокументТовары.Дата,
ДокументТовары.Номенклатура
ИЗ
Документ.ПоступлениеТоваров.Товары КАК ДокументТовары
Мы изменим его, добавив новое поле НоменклатураПредставление:
ВЫБРАТЬ
ДокументТовары.Ссылка,
ДокументТовары.Номер,
ДокументТовары.Дата,
ДокументТовары.Номенклатура,
ЕСТЬNULL(ДокументТовары.Номенклатура.Артикул, "") + " " + ЕСТЬNULL(ДокументТовары.Номенклатура.Наименование, "") КАК НоменклатураПредставление
ИЗ
Документ.ПоступлениеТоваров.Товары КАК ДокументТовары
Важный момент: Мы обращаемся к реквизитам номенклатуры через точку (ДокументТовары.Номенклатура.Артикул). Платформа автоматически построит необходимые соединения (JOIN).
ПутьКДанным выберем наше свежесозданное поле Список.НоменклатураПредставление.Номенклатура можно либо удалить из таблицы, либо просто скрыть, сняв для нее флажок видимости.Преимущества этого способа:
ПриПолученииДанныхЭтот способ заключается в программной обработке данных уже после того, как они были получены из базы данных, но перед их отображением на форме. Мы перехватываем событие ПриПолученииДанных у динамического списка и меняем текст в нужной ячейке.
Этот метод стоит использовать, если логика формирования представления очень сложная и ее невозможно или затруднительно реализовать в запросе, или если список гарантированно содержит небольшое количество записей.
Разберем по шагам:
ПриПолученииДанных. Создадим для него обработчик на сервере.Элемент и ОформленияСтрок. Нас интересует второй параметр — ОформленияСтрок. Это коллекция, содержащая данные и настройки оформления для каждой строки, которая будет отображена на экране.Пример кода для обработчика:
&НаСервере
Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
// Получаем доступ к данным текущей строки
ДанныеСтроки = ОформлениеСтроки.ДанныеСтроки;
// Получаем ссылку на номенклатуру
НоменклатураСсылка = ДанныеСтроки.Номенклатура;
// Проверяем, что ссылка не пустая
Если НЕ ЗначениеЗаполнено(НоменклатураСсылка) Тогда
Продолжить;
КонецЕсли;
// Получаем объект, чтобы прочитать его реквизиты.
// ВАЖНО: это создает дополнительную нагрузку!
НоменклатураОбъект = НоменклатураСсылка.ПолучитьОбъект();
// Формируем новую строку представления
НовоеПредставление = НоменклатураОбъект.Артикул + " (" + НоменклатураОбъект.Наименование + ")";
// Находим нужную ячейку (колонку) и устанавливаем ей текст
// "Номенклатура" - это имя колонки в таблице на форме
Ячейка = ОформлениеСтроки.Ячейки.Номенклатура;
Ячейка.УстановитьТекст(НовоеПредставление);
КонецЦикла;
КонецПроцедуры
Важное замечание по производительности: В приведенном выше примере используется метод ПолучитьОбъект(). Это очень ресурсоемкая операция, которая для каждой строки списка будет выполнять отдельный запрос к базе данных. Это может катастрофически сказаться на производительности при больших списках. Чтобы этого избежать, необходимые для представления реквизиты (например, Артикул) нужно заранее добавить в сам запрос динамического списка, а в обработчике события просто считывать их из ДанныеСтроки.
Улучшенный вариант без ПолучитьОбъект() (предполагается, что поля НоменклатураАртикул и НоменклатураНаименование добавлены в запрос списка):
&НаСервере
Процедура СписокПриПолученииДанных(Элемент, ОформленияСтрок)
Для Каждого ОформлениеСтроки Из ОформленияСтрок Цикл
ДанныеСтроки = ОформлениеСтроки.ДанныеСтроки;
// Формируем строку из уже полученных данных
ТекАртикул = ДанныеСтроки.НоменклатураАртикул;
ТекНаименование = ДанныеСтроки.НоменклатураНаименование;
НовоеПредставление = ТекАртикул + " (" + ТекНаименование + ")";
// Устанавливаем текст
ОформлениеСтроки.Ячейки.Номенклатура.УстановитьТекст(НовоеПредставление);
КонецЦикла;
КонецПроцедуры
Недостатки этого способа:
Проанализируем оба варианта. Первый способ (модификация запроса) является предпочтительным в 99% случаев. Он обеспечивает наилучшую производительность, корректную работу всех стандартных механизмов списков (сортировка, поиск, отбор) и является идеологически верным решением для платформы 1С.
Второй способ (событие ПриПолученииДанных) следует рассматривать как исключение. Он может быть полезен, когда логика формирования представления требует сложных вычислений, которые невозможно или нерационально выполнять на языке запросов. Но даже в этом случае следует позаботиться о производительности и заранее включить все необходимые данные в запрос списка, чтобы избежать вызова ПолучитьОбъект() внутри цикла.