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