При изучении разработки на платформе «1С:Предприятие 8.3» по практическому пособию М.Г. Радченко, создание алгоритма проведения документа ОказаниеУслуг является одним из ключевых и сложных этапов. Начинающие программисты часто сталкиваются с ошибкой выполнения метода Выполнить(), сопровождающейся сообщением: «Ожидается выражение "ВЫБРАТЬ"». В этой статье мы подробно разберем, почему возникает эта проблема, проанализируем синтаксис запросов и научимся правильно структурировать код для корректного проведения документа.
Рассмотрим сообщение об ошибке, которое выдает конфигуратор: {(17, 2)}: Ожидается выражение "ВЫБРАТЬ". Числа в скобках указывают на точное место возникновения проблемы: строка 17, позиция 2 в тексте самого запроса.
Давайте проанализируем ситуацию: платформа 1С воспринимает точку с запятой ; внутри текста запроса как разделитель между частями пакетного запроса. Если вы поставили точку с запятой, система ожидает, что следом начнется новый полноценный запрос, начинающийся с ключевого слова ВЫБРАТЬ. Если же после точки с запятой сразу идет название поля или таблицы, возникает синтаксическая ошибка.
В примере из темы мы видим следующую конструкцию в блоке группировки:
| СГРУППИРОВАТЬ ПО
| ОказаниеУслугПереченьНоменклатуры.Номенклатура,
| ОказаниеУслугПереченьНоменклатуры.Номенклатура.ВидНоменклатуры,
| ОказаниеУслугПереченьНоменклатуры.Номенклатуры.НаборСвойств; // ОШИБКА ЗДЕСЬ!
| ОказаниеУслугПереченьНоменклатуры.СуммаВДокументе";
Здесь точка с запятой разрывает текст запроса на полуслове. Платформа думает, что первый запрос закончился на поле НаборСвойств, а строка ОказаниеУслугПереченьНоменклатуры.СуммаВДокументе — это начало нового запроса, где пропущено слово ВЫБРАТЬ. Для решения этой проблемы необходимо удалить лишнюю точку с запятой внутри блока СГРУППИРОВАТЬ ПО.
Проанализируем текст запроса на наличие опечаток, которые также часто становятся причиной остановки работы программы. 1С крайне чувствительна к именам объектов метаданных. Рассмотрим типичные ошибки, допущенные в примере:
ОказаниеУслугиПереченьНоменклатуры (лишняя «и»), а в другом — ОказаниеУслугПереченьНоменклатуры. Необходимо убедиться, что название документа в конфигураторе точно соответствует написанию в коде. Обычно это ОказаниеУслуг.ОказаниеУслугПереченьНоменклатуры.Номенклатуры.НаборСвойств. Если в справочнике Номенклатура поле называется в единственном числе, то обращение Номенклатуры (во множественном числе) приведет к ошибке «Поле не найдено».НаборСвойств в свойствах справочника. Если этот реквизит не был создан на предыдущих занятиях по книге, запрос не сможет к нему обратиться.Выясним причину, по которой простая замена строки Сумма на СУММА(Сумма) не всегда помогает сразу. При использовании предложения СГРУППИРОВАТЬ ПО в языке запросов 1С действуют строгие правила:
Все поля, перечисленные после слова ВЫБРАТЬ, должны либо входить в список группировки (блок СГРУППИРОВАТЬ ПО), либо находиться внутри агрегатной функции (такой как СУММА(), МАКСИМУМ(), КОЛИЧЕСТВО()).
Рассмотрим правильный подход к группировке данных из табличной части документа:
"ВЫБРАТЬ
| ОказаниеУслугПереченьНоменклатуры.Номенклатура КАК Номенклатура,
| ОказаниеУслугПереченьНоменклатуры.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры,
| СУММА(ОказаниеУслугПереченьНоменклатуры.Количество) КАК КоличествоВДокументе,
| СУММА(ОказаниеУслугПереченьНоменклатуры.Сумма) КАК СуммаВДокументе
|ПОМЕСТИТЬ НоменклатураДокумента
|ИЗ
| Документ.ОказаниеУслуг.ПереченьНоменклатуры КАК ОказаниеУслугПереченьНоменклатуры
|ГДЕ
| ОказаниеУслугПереченьНоменклатуры.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
| ОказаниеУслугПереченьНоменклатуры.Номенклатура,
| ОказаниеУслугПереченьНоменклатуры.Номенклатура.ВидНоменклатуры";
В этом примере поля Номенклатура и ВидНоменклатуры являются измерениями группировки, а Количество и Сумма — ресурсами, которые суммируются. Это критически важно, если в документе одна и та же номенклатура указана в нескольких строках.
Разберем подробнее логику использования временных таблиц, которую предлагает Радченко. Оператор ПОМЕСТИТЬ создает временную таблицу в оперативной памяти (в данном случае НоменклатураДокумента).
Важный нюанс: если вы используете ПОМЕСТИТЬ, то результатом выполнения такого запроса (через метод Запрос.Выполнить()) будет не выборка данных, а состояние создания таблицы. В методике Радченко этот запрос является лишь первой частью пакета запросов. После создания временной таблицы обычно ставится точка с запятой (уже законная!), и пишется второй запрос, который соединяет данные из НоменклатураДокумента с остатками на регистрах.
Если ваш код обрывается сразу после создания временной таблицы, вы не сможете получить данные для дальнейшей обработки проведения. Структура должна выглядеть так:
Запрос.Текст =
"ВЫБРАТЬ ... ПОМЕСТИТЬ ВТ_Данные ... ;
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ * ИЗ ВТ_Данные КАК ВТ_Данные ...";
Проанализируем еще несколько факторов, которые могут влиять на результат, даже если синтаксис запроса верен:
Запрос.УстановитьПараметр("Ссылка", ЭтотОбъект.Ссылка);.ОказаниеУслуг проверьте свойство «Удаление движений». По методике учебника оно должно стоять в значении «Удалять автоматически». Это гарантирует, что при перепроведении запросы к остаткам не будут учитывать старые записи этого же документа («самосписание»).Подводя итог, можно сказать, что решение проблемы кроется в внимательном отношении к каждому символу. Проверьте отсутствие лишних знаков ; в середине запроса, убедитесь в наличии слова ВЫБРАТЬ после каждого разделителя пакета и тщательно сверьте имена полей с деревом конфигурации. Программирование в 1С требует точности, и такие ошибки — отличный способ научиться понимать «диалог» системы с разработчиком через сообщения об ошибках.