Ошибка "Поле не найдено" в запросе динамического списка при работе в расширении: причины и методы исправления

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

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

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

Суть проблемы и диагностика

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

Текст ошибки выглядит примерно так: Поле не найдено ХодОбработки.Действие.<?>ВидДействия.Наименование.

Почему это происходит?

  1. Контекст Расширения: Конструктор запросов в режиме конфигуратора (Design-time) работает в контексте метаданных расширения. Если вы обращаетесь к реквизитам объектов (справочников, документов), которые явно не добавлены (не заимствованы) в расширение, конструктор может «терять» цепочку типов после первой или второй точки. Система видит, что есть поле ХодОбработки, но может не понять структуру объекта, который в нем хранится, если этот тип данных не описан в расширении.
  2. Сложное разыменование: Обращение через несколько точек (например, Реквизит1.Реквизит2.Наименование) требует от платформы неявного построения левых соединений. В динамических списках, особенно внутри расширений, этот механизм иногда дает сбой на этапе валидации схемы компоновки данных.

Решение 1: Использование явных соединений (Рекомендуемое)

Самый надежный способ избежать подобных ошибок и одновременно оптимизировать запрос — отказаться от обращения к полям через точку в пользу явных соединений (JOIN). Это делает структуру запроса прозрачной для компилятора и конструктора.

Вместо того чтобы писать:


ВЫБРАТЬ
    ХодОбработки.Действие.ВидДействия.Наименование
ИЗ
    РегистрСведений.ХодОбработки КАК ХодОбработки

Нам следует разбить эту цепочку на последовательные соединения. Давайте перепишем проблемный участок запроса:


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

При таком подходе мы явно указываем таблицы, с которыми работаем. Конструктору запросов больше не нужно "угадывать" типы данных скрытых полей.

Решение 2: Заимствование метаданных в расширение

Если переписывать запрос не хочется, или цепочка слишком длинная, существует второй способ. Он заключается в том, чтобы «познакомить» расширение со структурой используемых объектов.

Для этого необходимо:

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

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

Анализ и исправление логических ошибок в запросе

Помимо технической проблемы с конструктором, в рассматриваемом коде есть и логические ошибки, которые могут привести к падению кода уже в режиме Предприятия (Runtime error). Давайте их разберем.

Ошибка с пометкой удаления у регистра сведений

В исходном запросе встречается условие:


ГДЕ
    ДанныеДокументовПредприятия.ПометкаУдаления = ЛОЖЬ

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

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


// Если ДокументыПредприятия - это Справочник
И ДокументыПредприятия.ПометкаУдаления = ЛОЖЬ 

Оптимизация: Временные таблицы в Динамическом списке

В исходном примере используется конструкция ПОМЕСТИТЬ ВТ_ДокументыПредприятия, а затем выборка из этой временной таблицы. Рассмотрим, почему это не лучшая практика для динамических списков.

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

  1. Платформа вынуждена выполнять полный запрос (создание ВТ) при каждом обновлении списка или скроллинге, что может негативно сказаться на производительности.
  2. Системе сложнее определить Основную таблицу (Main Table), что критически важно для работы стандартных команд (Добавить, Изменить, Удалить) и корректного наложения отборов.

Рекомендация: Постарайтесь объединить запрос в один пакет без использования ПОМЕСТИТЬ. В большинстве случаев левые соединения позволяют получить тот же результат. Если же логика слишком сложная, убедитесь, что в настройках динамического списка правильно задана «Основная таблица».

Использование параметров вместо литералов

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

Плохо:

ГДЕ ХодОбработки.Действие.ВидДействия.Наименование = "Согласование: ЗГД"

Хорошо:

ГДЕ ХодОбработки.Действие.ВидДействия = &ВидДействияСогласование

Использование поиска по наименованию (строке) ненадежно: название могут изменить, пробел могут поставить лишний, и код перестанет работать. Кроме того, сравнение ссылок работает быстрее сравнения строк. Значение параметра следует устанавливать в модуле формы в событии ПриСозданииНаСервере, используя метод расширения или обработчик:


// Пример установки параметра динамического списка
ОбщегоНазначенияКлиентСервер.УстановитьПараметрДинамическогоСписка(
    Список, 
    "ВидДействияСогласование", 
    Справочники.ВидыДействий.НайтиПоНаименованию("Согласование: ЗГД") // А лучше - предопределенный элемент
);

Итоговый алгоритм действий

Чтобы исправить ошибку и сделать код надежным, выполним следующие шаги:

  1. Убираем разыменование через точку в секциях ВЫБРАТЬ и ГДЕ для полей, вызывающих ошибку конструктора. Заменяем их на явные ЛЕВОЕ СОЕДИНЕНИЕ.
  2. Проверяем наличие объектов в расширении. Если соединения не помогают, добавляем участвующие в запросе справочники в расширение.
  3. Исправляем ошибку с пометкой удаления. Убираем обращение к свойству ПометкаУдаления у регистра сведений.
  4. Избавляемся от временной таблицы (по возможности), объединяя запрос в один.
  5. Заменяем поиск по строке на параметры.

Пример исправленного фрагмента запроса (без временной таблицы и с явными соединениями):


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

ГДЕ
    // Используем параметр вместо строки
    СпрВидыДействия.Ссылка = &ВидДействияДляОтбора 
    И ХодОбработки.Результат = &Результат
    // Проверяем пометку удаления у Справочника, а не у Регистра
    И СпрОбработки.ПометкаУдаления = ЛОЖЬ

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

← На главную