Разработка и Конфигурация · 10 мин
Как в 1С проверить, есть ли реквизит в запросе
Способы проверить, есть ли реквизит в результате запроса 1С: выборка, колонки, обработка ошибок, типовые приёмы и примеры кода для разработчика.
При разработке на платформе 1С:Предприятие часто возникает ситуация: запрос сформирован динамически или берётся из внешнего источника, и перед обращением к полю результата нужно убедиться, что такой реквизит (колонка) там вообще есть. Обращение к несуществующему полю выборки приводит к ошибке исполнения и остановке кода, поэтому проверка — обязательный элемент надёжной обработки данных.
Проверить наличие реквизита можно на нескольких уровнях: через коллекцию колонок результата запроса, через метаданные объекта до построения запроса, через попытку обращения с обработкой исключения или через конструктор запроса в конфигураторе. Выбор способа зависит от того, где именно нужна проверка — в момент выполнения кода или на этапе разработки.
Что именно нужно проверить: колонку результата или реквизит объекта
Прежде чем выбирать метод, важно различить две разные задачи. Первая — проверить, есть ли колонка в уже выполненном запросе (в результате запроса или в таблице значений, полученной из него). Вторая — проверить, существует ли реквизит у объекта конфигурации (справочника, документа) до того, как вы включите его в текст запроса.
Эти задачи решаются разными инструментами. Для колонок результата используется коллекция Колонки объекта РезультатЗапроса или ТаблицаЗначений. Для реквизитов метаданных — объектная модель метаданных конфигурации. Смешивание этих подходов — частая причина ошибок у начинающих разработчиков.
Проверка колонки в результате запроса
После выполнения запроса у объекта результата есть свойство Колонки — коллекция объектов КолонкаРезультатаЗапроса. У коллекции есть метод Найти(ИмяКолонки), который возвращает объект колонки или Неопределено, если колонки с таким именем нет. Это основной и самый быстрый способ проверки.
Типовой фрагмент кода выглядит так:
Результат = Запрос.Выполнить();
Если Результат.Колонки.Найти("Артикул") = Неопределено Тогда
// Колонки нет — выполняем альтернативную логику
Возврат;
КонецЕсли;
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
ЗначениеАртикула = Выборка.Артикул;
КонецЦикла;
Если результат уже выгружен в таблицу значений методом Выгрузить(), проверка выполняется аналогично — через Таблица.Колонки.Найти("Артикул"). У таблицы значений метод Найти у колонок работает так же: возвращает колонку или Неопределено.
Если Результат.Колонки.Найти("Артикул") <> Неопределено Тогда
Сообщить("Колонка найдена");
Иначе
Сообщить("Колонки нет в результате");
КонецЕсли;Важный нюанс: имя колонки в результате запроса совпадает с псевдонимом, заданным в тексте запроса через КАК. Если псевдоним не указан, платформа формирует имя автоматически — обычно по имени поля. Поэтому проверять нужно именно то имя, под которым поле фигурирует в результате, а не имя реквизита в метаданных.
Проверка реквизита объекта метаданных до построения запроса
Если текст запроса формируется динамически и имя реквизита приходит извне (из настроек, файла, пользовательского ввода), безопаснее проверить существование реквизита до выполнения запроса. Иначе запрос с несуществующим полем завершится ошибкой ещё на этапе выполнения.
Для этого используется объектная модель метаданных. У объекта метаданных есть коллекции Реквизиты, СтандартныеРеквизиты, ТабличныеЧасти, у каждой — метод Найти(Имя):
МетаДок = Метаданные.Документы.РеализацияТоваровУслуг;
Если МетаДок.Реквизиты.Найти("Соглашение") = Неопределено Тогда
// Реквизита нет — не включаем его в текст запроса
КонецЕсли;
Учтите, что стандартные реквизиты (Ссылка, Дата, Номер, Проведен и другие) хранятся в отдельной коллекции СтандартныеРеквизиты, поэтому для полной проверки имеет смысл искать в обеих коллекциях. Также реквизиты табличных частей находятся через МетаДок.ТабличныеЧасти.Найти("Товары").Реквизиты.Найти("Цена").
Проверка через попытку обращения к полю
Альтернативный подход — конструкция Попытка ... Исключение ... КонецПопытки. Код обращается к полю выборки напрямую, а при ошибке выполняется запасная ветка. Этот способ проще в написании, но у него есть ограничения.
Выборка = Результат.Выбрать();
Пока Выборка.Следующий() Цикл
Попытка
Значение = Выборка.Артикул;
Исключение
Значение = Неопределено;
КонецПопытки;
КонецЦикла;
Минус подхода в том, что исключение срабатывает на каждой итерации цикла, если колонки нет, — это медленнее и засоряет журнал регистрации при включённой записи ошибок. Конструкцию Попытка/Исключение разумно применять, когда проверка колонки по какой-то причине недоступна, а не как замену методу Найти().
Сравнение вариантов
Основной способ. Быстро, явно, без исключений. Требует, чтобы запрос уже был выполнен.
Подходит при динамическом формировании текста запроса. Проверяет реквизит объекта, а не колонку результата.
Запасной вариант. Простой код, но медленнее при массовых ошибках и маскирует реальные проблемы.
Проверка на этапе разработки в конфигураторе
Когда запрос статический и пишется в модуле, проверка наличия реквизита выполняется визуально через конструктор запроса. В левой части конструктора отображается дерево таблиц с полным списком доступных полей: реквизитов, стандартных реквизитов, табличных частей и виртуальных полей.
Если поле отсутствует в дереве, запрос с ним не пройдёт проверку — конструктор подчеркнёт ошибку. Дополнительно помогает контекстная подсказка в редакторе модуля: при наборе обращения к полю выборки платформа показывает список колонок, если текст запроса объявлен литералом и платформа смогла его проанализировать.
Для проверки состава реквизитов объекта без запроса откройте свойства объекта конфигурации в дереве метаданных — там видны все реквизиты, их типы и принадлежность к табличным частям.
- 1Получите имя реквизита из внешнего источника (настройки, параметра)
- 2Проверьте существование реквизита через Метаданные.Найти()
- 3Сформируйте текст запроса только с существующими полями
- 4Выполните запрос и при необходимости проверьте колонки результата через Колонки.Найти()
- 5Обращайтесь к полям выборки только после успешной проверки
Типичные ошибки и ограничения
Самая распространённая ошибка — проверять имя реквизита метаданных, а обращаться к колонке по псевдониму запроса, или наоборот. Если в запросе написано Товары.Номенклатура КАК Товар, то в результате колонка называется «Товар», и поиск по имени «Номенклатура» вернёт Неопределено.
Вторая частая проблема — обращение к полям через точку в выборке. Конструкция Выборка.Контрагент.ИНН в запросе даёт колонку с автоматическим именем, которое может отличаться от ожидаемого. Всегда задавайте явные псевдонимы через КАК для таких полей.
Третья ошибка — попытка проверить колонки у результата пакетного запроса без указания индекса. Если запрос содержит несколько операторов ВЫБРАТЬ, метод ВыполнитьПакет() возвращает массив результатов, и проверять колонки нужно у конкретного элемента массива.
Проверка результата и границы самостоятельной работы
После внедрения проверки убедитесь, что код корректно работает в обоих сценариях: когда реквизит есть и когда его нет. Для этого временно измените текст запроса или настройку, поставляющую имя поля, и прогоните обработку. Отсутствие падения и корректная отработка альтернативной ветки — признак правильной реализации.
При работе в чужой или доработанной конфигурации учитывайте, что состав реквизитов может отличаться от типового. Проверка через метаданные делает код переносимым между конфигурациями, но любые изменения лучше сначала тестировать на копии базы, особенно если обработка запускается регламентным заданием и ошибка останется незамеченной.
Как проверить результат
Поле читается, данные обрабатываются
Проверка Найти() возвращает Неопределено — неверное имя или псевдоним
Срабатывает альтернативная ветка без ошибки
Исключение при обращении к выборке — проверка не сработала
Реквизит найден в метаданных и включён в текст
Ошибка выполнения запроса — поле добавлено без проверки
Что важно запомнить
Для проверки колонки результата запроса используйте Результат.Колонки.Найти(Имя) — метод возвращает колонку или Неопределено. Для проверки реквизита объекта до построения запроса — Метаданные с коллекциями Реквизиты и СтандартныеРеквизиты. Всегда задавайте псевдонимы через КАК и проверяйте именно их. Конструкцию Попытка/Исключение применяйте только как запасной вариант.
Частые вопросы
Как проверить колонку, если запрос выгружен в таблицу значений?
У таблицы значений есть собственная коллекция Колонки с тем же методом Найти(). Вызовите Таблица.Колонки.Найти("ИмяКолонки") — если вернулось Неопределено, колонки нет. Логика полностью совпадает с проверкой результата запроса.
Регистр букв важен при поиске колонки или реквизита?
Нет, метод Найти() у коллекций колонок и метаданных нечувствителен к регистру. Имена «Артикул», «артикул» и «АРТИКУЛ» будут найдены одинаково. Но опечатки в имени по-прежнему приводят к результату Неопределено.
Как проверить реквизит табличной части документа?
Сначала найдите табличную часть: Метаданные.Документы.ИмяДокумента.ТабличныеЧасти.Найти("Товары"). Если она найдена, проверьте реквизит внутри неё: .Реквизиты.Найти("Цена"). Каждый уровень проверяйте отдельно, чтобы избежать обращения к Неопределено.
Что делать, если запрос пакетный и результатов несколько?
Метод ВыполнитьПакет() возвращает массив результатов запросов. Обратитесь к нужному элементу по индексу, например Результаты[1], и у него уже проверяйте Колонки.Найти(). Помните, что временные таблицы тоже занимают позиции в массиве.
Почему проверка Найти() возвращает Неопределено, хотя поле есть в запросе?
Чаще всего причина в псевдониме: в тексте запроса поле переименовано через КАК, а проверяется исходное имя реквизита. Проверьте точное имя колонки в результате — например, выведите список всех колонок циклом по Результат.Колонки.
Можно ли проверить наличие поля в СКД или динамическом списке?
Для СКД состав полей определяется схемой компоновки и настройками, а не колонками результата запроса. Там проверку выполняют через коллекции полей набора данных или настроек компоновщика. Для динамического списка состав полей задаётся текстом запроса, поэтому применимы те же приёмы с метаданными.