Почему возникает ошибка "Поле не найдено" в запросе динамического списка и как ее исправить?

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

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

Проанализируем типичный сценарий: вы создаете расширение, добавляете в него форму списка документа, открываете настройку динамического списка и пишете запрос с соединениями и вложенными конструкциями. При нажатии "ОК" система выдает ошибку, хотя вы уверены, что все поля существуют. Давайте выясним причины.

Анализ причин ошибки

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

1. Контекст выполнения в расширениях

Ключевое различие — это контекст, в котором выполняется проверка запроса.

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

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

2. Проблема с составными типами данных

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

Предположим, в вашем запросе есть обращение вида Таблица.ПолеСоставногоТипа.Реквизит. Если поле ПолеСоставногоТипа может содержать ссылки на объекты разных типов (например, на `Документ.ЗаявкаНаРасходованиеДенежныхСредств` и `Документ.КорректировкаЗадолженности`), то система на этапе проверки запроса не может однозначно определить, из метаданных какого именно объекта ей нужно взять реквизит Реквизит. Она не знает, существует ли этот реквизит у всех возможных типов данных. Это и приводит к ошибке.

В исходной теме проблема была именно в этом. Запрос содержал строку:


...СписаниеБезналичныхДенежныхСредствРасшифровкаПлатежа.ЗаявкаНаРасходованиеДенежныхСредств.ДокументОснование...

Здесь поле ЗаявкаНаРасходованиеДенежныхСредств, очевидно, имеет составной тип. Платформа не может "заглянуть" внутрь него, чтобы найти реквизит ДокументОснование, и сообщает об ошибке.

Решение: используем функцию ВЫРАЗИТЬ()

Для решения проблемы с составными типами в языке запросов 1С существует специальная функция — ВЫРАЗИТЬ(). Она работает аналогично оператору `CAST` в SQL и позволяет явно указать системе, к какому типу следует привести поле в данном конкретном месте запроса.

Как это работает?

Мы "помогаем" системе, говоря ей: "В этой строке запроса считай, что в поле ПолеСоставногоТипа находится ссылка на объект конкретного типа". После такого указания система может спокойно обратиться к метаданным этого типа и найти нужный реквизит.

Посмотрим на пример исправления.

Проблемный код:


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

Правильный код с использованием ВЫРАЗИТЬ():


ВЫБРАТЬ
    ...
    ВЫРАЗИТЬ(СписаниеБезналичныхДенежныхСредствРасшифровкаПлатежа.ЗаявкаНаРасходованиеДенежныхСредств КАК Документ.ЗаявкаНаРасходованиеДенежныхСредств).ДокументОснование КАК ДокументОснование
ИЗ
    ...

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

Дополнительные рекомендации

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

  1. Отлаживайте запрос в консоли. Это золотое правило. Всегда составляйте и проверяйте сложные запросы в консоли запросов в режиме "Предприятие". Когда вы убедитесь, что запрос возвращает нужные данные и не содержит синтаксических ошибок, просто скопируйте его текст в Конфигуратор. Это сэкономит массу времени и нервов.
  2. Указывайте основную таблицу. Для корректной и быстрой работы динамического списка очень важно на соответствующей вкладке указать основную таблицу. Платформа использует ее ключевые поля (обычно поле `Ссылка`) для идентификации строк и порционной подгрузки данных. Без этого динамическое считывание может не работать, и система будет пытаться загрузить все данные сразу.
  3. Не усложняйте запросы. Динамические списки не предназначены для сверхсложной аналитики. Избегайте большого количества соединений (более 4-5 таблиц), соединений с виртуальными таблицами регистров с большим количеством параметров, а также использования временных таблиц. Такие запросы могут сильно замедлять работу интерфейса.

Таким образом, столкнувшись с ошибкой "Поле не найдено", в первую очередь проверьте, все ли объекты заимствованы в расширение, а затем внимательно посмотрите, нет ли в вашем запросе обращений к реквизитам через поля с составным типом. Если есть — смело используйте функцию ВЫРАЗИТЬ() для явного указания типа.

← На главную