Почему не отображается Наименование в Динамическом списке с произвольным запросом?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При разработке интерфейсов на управляемых формах в платформе «1С:Предприятие 8.3» одним из самых часто используемых инструментов является Динамический список. Этот элемент управления позволяет быстро и эффективно выводить списки данных из базы данных с поддержкой автоматической постраничной подгрузки, сортировки, отборов и группировок. Однако начинающие разработчики часто сталкиваются с неприятной проблемой: после перевода динамического списка в режим произвольного запроса и связывания его с другими таблицами (например, с регистрами остатков или оборотов) стандартные колонки, такие как Наименование или Код, визуально становятся абсолютно пустыми. При этом сам список успешно функционирует, строки создаются, а при двойном щелчке по пустой строке стандартно открывается нужная карточка элемента.

В данной статье мы подробно проанализируем, почему так происходит, как устроен механизм оптимизации динамических списков в платформе 1С, детально разберем причины пропадания данных и рассмотрим правильные, архитектурно верные способы решения этой задачи.

Выясняем причину: как динамический список оптимизирует запросы

Для того чтобы понять природу проблемы, нам необходимо заглянуть во внутренние механизмы работы платформы 1С. Когда у динамического списка (объект ДинамическийСписок) заполнено свойство Основная таблица (например, в нем указан справочник Справочник.Товары), система включает встроенный механизм автоматической оптимизации:

  1. Запрос только ключевого поля: Платформа не выполняет ваш запрос целиком для всех строк базы данных. Вместо этого для построения видимой на экране части списка она извлекает из СУБД только уникальные идентификаторы — ссылки (поле Ссылка).
  2. Background-дозапрос данных: Уже имея на руках порцию ссылок для отображения на экране (обычно около 30-45 строк), платформа отдельными быстрыми запросами автоматически получает значения стандартных полей (таких как Наименование, Код, ПометкаУдаления, Предопределенный) напрямую из основной таблицы по этим ссылкам.

Когда мы пишем произвольный запрос с левым соединением основной таблицы с таблицей остатков регистра, нарушается уникальность ключевого поля. Рассмотрим классический некорректный запрос:


ВЫБРАТЬ
    Товары.Наименование КАК Наименование
ИЗ
    РегистрНакопления.ОжидаемыеЗаказы.Остатки КАК ОжидаемыеЗаказыОстатки
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Товары КАК Товары
    ПО ОжидаемыеЗаказыОстатки.Товар = Товары.Ссылка

В этой конструкции левое соединение начинается с таблицы остатков регистра. Проанализируем, к каким критическим последствиям это приводит:

  1. Дублирование ключевых полей (ссылок): Если в регистре остатков по какому-то товару есть несколько записей (например, остатки числятся по разным складам), то левое соединение вернет несколько строк с одинаковой ссылкой на один и тот же товар. Платформа ожидает, что поле Ссылка основной таблицы будет уникальным ключом для каждой строки динамического списка. При обнаружении дублей механизм оптимизации "теряется", связь между строками списка и данными ломается, из-за чего колонки Наименование и Код перестают заполняться и отображаются пустыми.
  2. Отсутствие ключевого поля в выборке: В исходном запросе автора полностью отсутствует выбор поля Ссылка. Если у динамического списка задана основная таблица, но в тексте запроса не выбрано поле Ссылка, система компоновки данных не может сопоставить строки выборки с записями в базе данных.

Разбор "костыльного" решения: почему Товары.Ссылка КАК Наименование работает, но так делать нельзя

В процессе обсуждения проблемы на форуме было предложено временное решение: заменить поле выбора в запросе на следующую конструкцию:


ВЫБРАТЬ
    Товары.Ссылка КАК Наименование
...

Рассмотрим подробнее, почему этот прием визуально решает проблему, но является грубейшей ошибкой проектирования. Поле Ссылка имеет ссылочный тип данных (в нашем случае СправочникСсылка.Товары). Когда платформа выводит ссылочное поле в элемент формы (ячейку таблицы), предназначенный для отображения строки, она автоматически пытается получить его текстовое представление.

Представлением для справочника по умолчанию является его наименование. Таким образом, на экране мы действительно увидим красивый текст — название товара. Однако под капотом тип данных в этой колонке остался ссылочным. Это повлечет за собой целый ряд серьезных проблем при эксплуатации системы пользователями:

Правильные способы решения проблемы

Рассмотрим по шагам профессиональные подходы к исправлению данной ситуации в зависимости от бизнес-требований к форме списка.

Способ 1. Использование правильного левого соединения и группировки (с сохранением Основной таблицы)

Если вам обязательно нужно сохранить функциональность основной таблицы динамического списка (чтобы работали стандартные команды создания, копирования, пометки на удаление, перетаскивания строк drag-and-drop), мы должны гарантировать уникальность поля Ссылка в результате запроса. Для этого таблица справочника должна быть ведущей (находиться слева при соединении), а данные из регистра остатков должны быть предварительно сгруппированы, чтобы исключить дублирование ссылок.

Проанализируем пример правильного запроса динамического списка:


ВЫБРАТЬ
    СправочникТовары.Ссылка КАК Ссылка,
    СправочникТовары.Код КАК Код,
    СправочникТовары.Наименование КАК Наименование,
    ЕСТЬNULL(ОстаткиТоваров.КоличествоОстаток, 0) КАК Остаток
ИЗ
    Справочник.Товары КАК СправочникТовары
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            ОжидаемыеЗаказыОстатки.Товар КАК Товар,
            СУММА(ОжидаемыеЗаказыОстатки.КоличествоОстаток) КАК КоличествоОстаток
        ИЗ
            РегистрНакопления.ОжидаемыеЗаказы.Остатки КАК ОжидаемыеЗаказыОстатки
        СГРУППИРОВАТЬ ПО
            ОжидаемыеЗаказыОстатки.Товар
    ) КАК ОстатокТоваров
    ПО СправочникТовары.Ссылка = ОстатокТоваров.Товар

В этом примере мы решили сразу три проблемы:

  1. В качестве левой (основной) таблицы мы выбрали Справочник.Товары. Теперь список гарантированно отобразит все товары, даже те, по которым нет остатков в регистре.
  2. Мы свернули (сгруппировали) остатки регистра по полю Товар во вложенном запросе. Это исключает дублирование строк справочника в списке. Каждому товару соответствует ровно одна запись остатка.
  3. Мы явно выбрали ключевое поле Ссылка и назначили ему и остальным полям понятные псевдонимы через оператор КАК.

Способ 2. Отказ от использования "Основной таблицы" в настройках Динамического списка

Бывают ситуации, когда логика вашего списка не привязана к конкретному справочнику. Например, вы проектируете сложный отчётный список или виртуальную таблицу, где строки могут дублироваться (например, вывод товаров в разрезе складов, где одна и та же позиция должна выводиться несколько раз с разными складами и остатками). В таком случае механизм сопоставления по уникальной ссылке справочника работать не сможет.

Для решения этой задачи выполним следующие действия:

  1. Откроем свойства реквизита Список на управляемой форме.
  2. Найдем свойство Основная таблица и полностью очистим его значение (оно должно стать пустым).
  3. В тексте произвольного запроса динамического списка мы обязаны явно выбрать абсолютно все поля, которые планируем отображать на форме (так как платформа больше не будет автоматически дозапрашивать их по ссылке):

ВЫБРАТЬ
    ОжидаемыеЗаказыОстатки.Товар КАК ТоварСсылка,
    Товары.Код КАК Код,
    Товары.Наименование КАК Наименование,
    ОжидаемыеЗаказыОстатки.Склад КАК Склад,
    ОжидаемыеЗаказыОстатки.КоличествоОстаток КАК Остаток
ИЗ
    РегистрНакопления.ОжидаемыеЗаказы.Остатки КАК ОжидаемыеЗаказыОстатки
    ЛЕВОЕ СОЕДИНЕНИЕ Справочник.Товары КАК Товары
    ПО ОжидаемыеЗаказыОстатки.Товар = Товары.Ссылка

При отключенной основной таблице динамический список начинает работать как классический плоский запрос к базе данных. Платформа перестает применять алгоритмы фоновой оптимизации получения представлений. Все данные, переданные в секцию ВЫБРАТЬ, напрямую транслируются в соответствующие колонки таблицы формы.

Важное примечание: При очистке свойства "Основная таблица" на форме перестанут автоматически работать стандартные кнопки командной панели списка (Создать, Изменить, Удалить). Если они необходимы, вам придется реализовать их обработчики программно в модуле управляемой формы.

Важность явного указания псевдонимов при программной подмене запроса

В сообщении №27 темы автор столкнулся с еще одной интересной особенностью платформы. При программном изменении текста запроса через свойство Список.ТекстЗапроса на сервере поля могут пропадать, если им не заданы жесткие псевдонимы.

Выясним причину этого поведения. Когда мы пишем в запросе просто:

СправочникТовары.Наименование

платформа 1С при компиляции запроса внутри системы компоновки данных (СКД) может сгенерировать автоматический псевдоним (например, на английском языке или с добавлением порядкового номера). В то же время на управляемой форме элемент поля таблицы (колонка) жестко связан с конкретным именем через свойство ПутьКДанным (например, Список.Наименование).

Если автогенерируемый псевдоним поля в программно установленном запросе не совпадет с тем, что ожидает колонка формы в ПутьКДанным, данные в этой колонке будут стерты и строка окажется пустой. Чтобы этого избежать, всегда пишите псевдонимы полей в произвольных запросах явно:


СправочникТовары.Наименование КАК Наименование
СправочникТовары.Код КАК Код

Явное указание псевдонима через ключевое слово КАК жестко фиксирует имя колонки в результирующей выборке СКД, гарантируя стабильное отображение информации на форме при любых динамических изменениях программного кода.

← На главную