Как исправить ошибку «Поле не найдено» в динамическом списке расширения при использовании составных типов?

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

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

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

Разберем причину: почему «точки» не работают в расширении?

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

В контексте расширений возникают следующие сложности:

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

Способ №1: Использование оператора ВЫРАЗИТЬ

Самым эффективным и правильным с точки зрения архитектуры решением является явное приведение типа. Рассмотрим ситуацию: у нас есть поле Действие, которое может быть ссылкой на пять разных справочников. Нам нужно получить ВидДействия. Чтобы платформа точно знала, из какой таблицы брать данные, мы должны использовать ВЫРАЗИТЬ.

Проанализируем пример трансформации запроса. Вместо прямого обращения:


// Ошибочный вариант в расширении
ВЫБРАТЬ
    ПроцессыДействий.Действие.ВидДействия.Наименование КАК ВидДействияНаименование
ИЗ
    РегистрСведений.ПроцессыДействий КАК ПроцессыДействий

Мы должны написать конструкцию, указывающую на конкретную таблицу справочника. Если поле может содержать разные типы, и нам нужны данные из конкретного, запрос примет следующий вид:


// Правильный вариант с приведением типа
ВЫБРАТЬ
    ВЫРАЗИТЬ(ПроцессыДействий.Действие КАК Справочник.ДействияПоЗадаче).ВидДействия.Наименование КАК ВидДействияНаименование
ИЗ
    РегистрСведений.ПроцессыДействий КАК ПроцессыДействий

Почему это работает? Инструкция ВЫРАЗИТЬ заставляет платформу создать жесткую связь с таблицей Справочник.ДействияПоЗадаче. Теперь системе не нужно гадать, какие объекты входят в ОпределяемыйТип. Она обращается напрямую к реквизитам указанного справочника, что снимает проблему «Поле не найдено».

Способ №2: «Плоский» запрос через явное соединение

Если приведение типа по каким-то причинам не подходит (например, поле ВидДействия есть во всех пяти справочниках, входящих в состав типа, и вам нужны данные по всем), рекомендуется отказаться от использования «точек» в пользу явного ЛЕВОЕ СОЕДИНЕНИЕ в тексте запроса.

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


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

Такой подход считается более тяжелым для написания, но он самый стабильный для динамических списков в расширениях. Вы полностью контролируете выборку данных и не зависите от того, насколько корректно платформа интерпретирует вложенные реквизиты составного типа.

Способ №3: Проверка целостности метаданных в расширении

Если вы все же хотите использовать обращение через точку, необходимо убедиться, что структура метаданных в расширении абсолютно прозрачна для системы. Проанализируем чек-лист необходимых действий:

  1. Определяемый тип: Он должен быть добавлен в расширение. Проверьте список типов, входящих в него в расширении — он должен полностью совпадать с основной конфигурацией или включать все типы, которые вы планируете использовать в запросе.
  2. Справочники-владельцы: Все справочники, которые входят в состав Действия, должны быть добавлены в расширение.
  3. Реквизиты справочников: У этих справочников в расширение должен быть перенесен реквизит ВидДействия.
  4. Справочник-тип реквизита: Сам справочник ВидыДействий и его поле Наименование также должны присутствовать в расширении.

Важный момент: Если вы добавили справочник в расширение, но не добавили в расширение его реквизит, то при попытке обратиться к нему через точку в запросе вы получите ошибку. Платформа «видит» таблицу справочника, но «не знает» о существовании его полей, пока они явно не включены в расширение.

Рекомендации по настройке и оптимизации

Рассмотрим дополнительные аспекты, которые могут влиять на результат:

1. Режим совместимости. Убедитесь, что версия режима совместимости расширения соответствует версии основной конфигурации. Если расширение работает в более старом режиме, механизмы работы с составными типами в динамических списках могут давать сбои, которые в новых версиях платформы уже исправлены.

2. Вычисляемые поля СКД. В некоторых случаях, если запрос в расширении «не поддается», можно попробовать добавить поле не в сам текст запроса, а в раздел «Вычисляемые поля» настройки динамического списка. Однако помните, что это может негативно сказаться на скорости прокрутки списка и возможности фильтрации по этому полю.

3. Основная таблица. Проверьте свойство динамического списка «Основная таблица». Если она указана, платформа пытается оптимизировать запросы, исходя из ее структуры. Иногда временная очистка основной таблицы в свойствах списка помогает локализовать проблему с поиском полей.

Подведем итог. Чтобы победить ошибку «Поле не найдено», мы должны либо явно указать тип через ВЫРАЗИТЬ, либо выполнить соединение таблиц вручную, либо тщательно синхронизировать состав метаданных между основной конфигурацией и расширением. Использование ВЫРАЗИТЬ — самый быстрый и надежный путь для программиста 1С в данной ситуации.

← На главную