Почему не открывается запрос в Конструкторе запросов 1С и как это исправить

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

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

Выясним причину ошибки при открытии запроса в конструкторе

Проанализируем фрагмент BSL-кода, вызывающий ошибку синтаксического анализа:


Запрос.Текст = 
    "ВЫБРАТЬ
    |    Док.Номенклатура КАК Номенклатура,
    |    Док.Количество КАК Количество,
    |    " + ?(ЕстьЦена, "&Валюта", "ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)") + " КАК Валюта
    |ИЗ
    |    (ВЫБРАТЬ
    |        Док.Номенклатура КАК Номенклатура,
    |        " + ?(ЕстьХарактеристика, "Док.ХарактеристикаНоменклатуры", "ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)") + " КАК Характеристика
    |    ИЗ
    |        Документ." + ИмяДокумента + ".Товары КАК Док
    |    ГДЕ
    |        Док.Ссылка = &Док
    |    ) КАК Док";

В данном тексте сочетаются сразу несколько факторов, из-за которых парсер платформы не может построить визуальное дерево запроса:

  1. Динамическая склейка строк и тернарные операторы: Вставки BSL-кода вид " + ?(...) + " разрывают единый строковый литерал. Конструктор запросов выполняет исключительно статический синтаксический анализ и не умеет вычислять выражения встроенного языка во время разработки.
  2. Составные имена объектов метаданных: Подстановка имени таблицы через переменную (Документ." + ИмяДокумента + ".Товары) не позволяет платформе определить, к какому объекту конфигурации идет обращение.
  3. Использование комментариев BSL внутри строк: Символы //, вставленные внутрь склеиваемой строки, воспринимаются синтаксическим анализатором запросов как ошибка, так как в самом языке запросов 1С для комментариев применяется двойной дефис --.

Способы решения и редактирования динамических запросов

Рассмотрим несколько проверенных вариантов работы с такими запросами, от временных правок до полного рефакторинга кода.

Вариант 1. Временная замена динамических вставок статическим текстом

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

  1. Временно заменяем все тернарные операторы и склейки строк на конкретные объекты или параметры. Например, вместо Документ." + ИмяДокумента + ".Товары подставим реальную таблицу Документ.РеализацияТоваровУслуг.Товары.
  2. Заменяем BSL-условия статическими выражениями или параметрами (например, &Валюта КАК Валюта).
  3. Удаляем из текста строки с BSL-комментариями //.
  4. Открываем текст в конструкторе запросов, вносим необходимые изменения в поля, соединения или группировки и сохраняем запрос.
  5. Возвращаем обратно динамические BSL-выражения и конкатенацию строк.

Вариант 2. Отладка и использование внешней консоли запросов

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

  1. Установим точку останова в режиме отладки непосредственно перед выполнением метода Запрос.Выполнить().
  2. Запустим конфигурацию и перейдем в точку останова.
  3. Откроем табло отладки и вычислим значение свойства Запрос.Текст. На этом этапе платформа уже сформировала итоговый цельный текст запроса со всеми подставленными именами таблиц и условиями.
  4. Скопируем полученный текст из табло и вставим его во внешнюю консоль запросов. В консоли собранный текст легко открывается конструктором и поддается отладке.

Вариант 3. Рефакторинг кода: перенос логики внутрь языка запросов

Чтобы избежать синтаксических ошибок и сохранить возможность отладки конструктором, перепишем динамическую сборку текста на стандарты языка запросов 1С.

Вместо BSL-оператора ?() используем встроенную конструкцию ВЫБОР КОГДА ... ТОГДА ... КОНЕЦ, а опциональные реквизиты и валюту передадим через параметры запроса:


Запрос.Текст = 
    "ВЫБРАТЬ
    |    Док.Номенклатура КАК Номенклатура,
    |    Док.Количество КАК Количество,
    |    ВЫБОР
    |        КОГДА &ЕстьЦена ТОГДА &Валюта
    |        ИНАЧЕ ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)
    |    КОНЕЦ КАК Валюта,
    |    Док.Характеристика КАК Характеристика,
    |    Док.Серия КАК Серия
    |ИЗ
    |    (ВЫБРАТЬ
    |        Док.Номенклатура КАК Номенклатура,
    |        Док.Количество КАК Количество,
    |        ВЫБОР
    |            КОГДА &ЕстьХарактеристика ТОГДА Док.ХарактеристикаНоменклатуры
    |            ИНАЧЕ ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
    |        КОНЕЦ КАК Характеристика,
    |        ВЫБОР
    |            КОГДА &ЕстьСерия ТОГДА Док.СерияНоменклатуры
    |            ИНАЧЕ ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)
    |        КОНЕЦ КАК Серия
    |    ИЗ
    |        Документ.РеализацияТоваровУслуг.Товары КАК Док
    |    ГДЕ
    |        Док.Ссылка = &Док) КАК Док";

Запрос.УстановитьПараметр("ЕстьЦена", ЕстьЦена);
Запрос.УстановитьПараметр("Валюта", Валюта);
Запрос.УстановитьПараметр("ЕстьХарактеристика", ЕстьХарактеристика);
Запрос.УстановитьПараметр("ЕстьСерия", ЕстьСерия);
Запрос.УстановитьПараметр("Док", СсылкаНаДокумент);

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

← На главную