При работе с типовыми конфигурациями или при разработке собственных модулей разработчики 1С часто сталкиваются с ситуацией, когда при нажатии кнопки Конструктор запроса система выдает синтаксическую ошибку и отказывается открывать визуальный редактор. Разберем, с чем связано такое поведение платформы, проанализируем синтаксис исходного кода и рассмотрим практические способы редактирования подобных запросов.
Проанализируем фрагмент BSL-кода, вызывающий ошибку синтаксического анализа:
Запрос.Текст =
"ВЫБРАТЬ
| Док.Номенклатура КАК Номенклатура,
| Док.Количество КАК Количество,
| " + ?(ЕстьЦена, "&Валюта", "ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)") + " КАК Валюта
|ИЗ
| (ВЫБРАТЬ
| Док.Номенклатура КАК Номенклатура,
| " + ?(ЕстьХарактеристика, "Док.ХарактеристикаНоменклатуры", "ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)") + " КАК Характеристика
| ИЗ
| Документ." + ИмяДокумента + ".Товары КАК Док
| ГДЕ
| Док.Ссылка = &Док
| ) КАК Док";
В данном тексте сочетаются сразу несколько факторов, из-за которых парсер платформы не может построить визуальное дерево запроса:
" + ?(...) + " разрывают единый строковый литерал. Конструктор запросов выполняет исключительно статический синтаксический анализ и не умеет вычислять выражения встроенного языка во время разработки.Документ." + ИмяДокумента + ".Товары) не позволяет платформе определить, к какому объекту конфигурации идет обращение.//, вставленные внутрь склеиваемой строки, воспринимаются синтаксическим анализатором запросов как ошибка, так как в самом языке запросов 1С для комментариев применяется двойной дефис --.Рассмотрим несколько проверенных вариантов работы с такими запросами, от временных правок до полного рефакторинга кода.
Если необходимо быстро изменить структуру запроса через удобный интерфейс конструктора, выполним следующие шаги:
Документ." + ИмяДокумента + ".Товары подставим реальную таблицу Документ.РеализацияТоваровУслуг.Товары.&Валюта КАК Валюта).//.Когда запрос собирается из множества условий в разных частях модуля, проанализировать его вручную сложно. В этом случае поступим следующим образом:
Запрос.Выполнить().Запрос.Текст. На этом этапе платформа уже сформировала итоговый цельный текст запроса со всеми подставленными именами таблиц и условиями.Чтобы избежать синтаксических ошибок и сохранить возможность отладки конструктором, перепишем динамическую сборку текста на стандарты языка запросов 1С.
Вместо BSL-оператора ?() используем встроенную конструкцию ВЫБОР КОГДА ... ТОГДА ... КОНЕЦ, а опциональные реквизиты и валюту передадим через параметры запроса:
Запрос.Текст =
"ВЫБРАТЬ
| Док.Номенклатура КАК Номенклатура,
| Док.Количество КАК Количество,
| ВЫБОР
| КОГДА &ЕстьЦена ТОГДА &Валюта
| ИНАЧЕ ЗНАЧЕНИЕ(Справочник.Валюты.ПустаяСсылка)
| КОНЕЦ КАК Валюта,
| Док.Характеристика КАК Характеристика,
| Док.Серия КАК Серия
|ИЗ
| (ВЫБРАТЬ
| Док.Номенклатура КАК Номенклатура,
| Док.Количество КАК Количество,
| ВЫБОР
| КОГДА &ЕстьХарактеристика ТОГДА Док.ХарактеристикаНоменклатуры
| ИНАЧЕ ЗНАЧЕНИЕ(Справочник.ХарактеристикиНоменклатуры.ПустаяСсылка)
| КОНЕЦ КАК Характеристика,
| ВЫБОР
| КОГДА &ЕстьСерия ТОГДА Док.СерияНоменклатуры
| ИНАЧЕ ЗНАЧЕНИЕ(Справочник.СерииНоменклатуры.ПустаяСсылка)
| КОНЕЦ КАК Серия
| ИЗ
| Документ.РеализацияТоваровУслуг.Товары КАК Док
| ГДЕ
| Док.Ссылка = &Док) КАК Док";
Запрос.УстановитьПараметр("ЕстьЦена", ЕстьЦена);
Запрос.УстановитьПараметр("Валюта", Валюта);
Запрос.УстановитьПараметр("ЕстьХарактеристика", ЕстьХарактеристика);
Запрос.УстановитьПараметр("ЕстьСерия", ЕстьСерия);
Запрос.УстановитьПараметр("Док", СсылкаНаДокумент);
При таком подходе запрос становится полностью статическим (за исключением ситуаций, когда имя таблицы действительно зависит от типа документа), легко читается и без проблем открывается стандартным Конструктором запросов 1С.