При разработке в 1С часто возникает ситуация, когда нужно вывести дополнительные данные в форму списка документов. Для этого используется механизм динамического списка с произвольным запросом. Однако, при работе с расширениями конфигурации и сложными запросами можно столкнуться с ошибкой "Ошибка получения информации набора данных. Поле не найдено...", которую необходимо уметь диагностировать. При этом парадокс заключается в том, что тот же самый запрос отлично выполняется в пользовательском режиме (например, в консоли запросов), но вызывает ошибку в Конфигураторе при сохранении формы. Разберем, почему так происходит и как это исправить. Для тестирования и отладки запросов в режиме «Предприятие» пригодится инженерная консоль запросов для 1С.
Проанализируем типичный сценарий: вы создаете расширение, добавляете в него форму списка документа, открываете настройку динамического списка и пишете запрос с соединениями и вложенными конструкциями. При нажатии "ОК" система выдает ошибку, хотя вы уверены, что все поля существуют. Давайте выясним причины.
Существует две основные причины, которые часто действуют в связке и приводят к такой ошибке. Рассмотрим их подробно.
1. Контекст выполнения в расширениях
Ключевое различие — это контекст, в котором выполняется проверка запроса.
Это первая и самая частая причина. Перед тем как искать более сложные проблемы, всегда проверяйте, что все таблицы и поля, используемые в запросе, добавлены в ваше расширение. Для автоматической проверки состава расширений пригодится инструмент анализа конфигураций и состава расширений.
2. Проблема с составными типами данных
Это более тонкий момент, который и стал решающим в обсуждаемой теме. Ошибка "Поле не найдено" может возникать, когда вы пытаетесь получить реквизит через поле, имеющее составной тип данных.
Предположим, в вашем запросе есть обращение вида Таблица.ПолеСоставногоТипа.Реквизит. Если поле ПолеСоставногоТипа может содержать ссылки на объекты разных типов (например, на `Документ.ЗаявкаНаРасходованиеДенежныхСредств` и `Документ.КорректировкаЗадолженности`), то система на этапе проверки запроса не может однозначно определить, из метаданных какого именно объекта ей нужно взять реквизит Реквизит. Она не знает, существует ли этот реквизит у всех возможных типов данных. Это и приводит к ошибке.
В исходной теме проблема была именно в этом. Запрос содержал строку:
...СписаниеБезналичныхДенежныхСредствРасшифровкаПлатежа.ЗаявкаНаРасходованиеДенежныхСредств.ДокументОснование...
Здесь поле ЗаявкаНаРасходованиеДенежныхСредств, очевидно, имеет составной тип. Платформа не может "заглянуть" внутрь него, чтобы найти реквизит ДокументОснование, и сообщает об ошибке.
Для решения проблемы с составными типами в языке запросов 1С существует специальная функция — ВЫРАЗИТЬ(). Она работает аналогично оператору `CAST` в SQL и позволяет явно указать системе, к какому типу следует привести поле в данном конкретном месте запроса.
Как это работает?
Мы "помогаем" системе, говоря ей: "В этой строке запроса считай, что в поле ПолеСоставногоТипа находится ссылка на объект конкретного типа". После такого указания система может спокойно обратиться к метаданным этого типа и найти нужный реквизит.
Посмотрим на пример исправления.
Проблемный код:
ВЫБРАТЬ
...
СписаниеБезналичныхДенежныхСредствРасшифровкаПлатежа.ЗаявкаНаРасходованиеДенежныхСредств.ДокументОснование КАК ДокументОснование
ИЗ
...
Правильный код с использованием ВЫРАЗИТЬ():
ВЫБРАТЬ
...
ВЫРАЗИТЬ(СписаниеБезналичныхДенежныхСредствРасшифровкаПлатежа.ЗаявкаНаРасходованиеДенежныхСредств КАК Документ.ЗаявкаНаРасходованиеДенежныхСредств).ДокументОснование КАК ДокументОснование
ИЗ
...
Что мы сделали? Мы обернули поле ЗаявкаНаРасходованиеДенежныхСредств в функцию ВЫРАЗИТЬ() и явно указали тип Документ.ЗаявкаНаРасходованиеДенежныхСредств. Теперь платформа точно знает, что нужно искать реквизит ДокументОснование именно у этого документа, и ошибка исчезает. Этот прием является стандартным решением для подобных задач.
Чтобы минимизировать проблемы при работе с произвольными запросами в динамических списках, следуйте нескольким простым советам по оптимизации произвольных запросов динамического списка.
Таким образом, столкнувшись с ошибкой "Поле не найдено", в первую очередь проверьте, все ли объекты заимствованы в расширение, а затем внимательно посмотрите, нет ли в вашем запросе обращений к реквизитам через поля с составным типом. Если есть — смело используйте функцию ВЫРАЗИТЬ() для явного указания типа.