Как исправить ошибку «Ожидается выражение» при проверке новизны объекта в 1С?

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

При разработке и доработке конфигураций на платформе «1С:Предприятие» программисты часто сталкиваются с необходимостью разграничения прав доступа или выполнения определенных действий в зависимости от того, записан ли текущий объект в базу данных или он только создается. Одной из классических ошибок начинающих разработчиков является неверное использование зарезервированных ключевых слов для проверки новизны записи.

В этой статье мы подробно проанализируем ситуацию, когда при попытке запустить код конфигуратор выдает критическую ошибку «Ожидается выражение», выясним фундаментальную причину ее возникновения и разберем наиболее надежные и профессиональные способы ее решения как для обычных, так и для управляемых форм.

Почему возникает ошибка «Ожидается выражение»?

Давайте рассмотрим исходный фрагмент кода, который вызвал сбой в работе программы:


Если Не Новый () Тогда
    Если Не РазрешитьПросмотрЧужихДокументов(Автор) Тогда                               
        Предупреждение("Недостаточно полномочий для просмотра документов других пользователей!");                              
        Отказ = Истина;                              
    КонецЕсли;                                                                   
КонецЕсли;

Платформа ругается на конструкцию Если Не Новый() Тогда, указывая на скобки символом указания ошибки <<?>>. Чтобы понять причину, обратимся к синтаксису встроенного языка.

В системе «1С:Предприятие» слово Новый (или английский аналог New) является **оператором**, предназначенным исключительно для создания и инициализации новых объектов ссылочных или служебных типов данных (например, таблиц значений, массивов, запросов, структур и т.д.). Компилятор ожидает, что после ключевого слова Новый обязательно последует указание конкретного типа данных или параметров конструктора.

Когда мы пишем Новый() с пустыми скобками, синтаксический анализатор платформы не находит обязательного описания типа и выдает ошибку «Ожидается выражение». Использовать данный оператор для проверки того, записан ли текущий документ или элемент справочника в базу данных, категорически нельзя.

Решение проблемы в обычном приложении (Обычные формы)

Если разработка ведется в рамках обычного приложения (толстый клиент), контекстом формы является сам прикладной объект (например, ДокументОбъект или СправочникОбъект). Для проверки статуса записи в базу данных у таких объектов существует предопределенный метод ЭтоНовый().

Этот метод возвращает логическое значение Истина, если объект еще ни разу не был записан в базу данных, и Ложь, если запись уже существует в СУБД.

Давайте перепишем процедуру ПриОткрытии правильно, исправив допущенную ошибку:


Процедура ПриОткрытии(Отказ)
    // Корректно проверяем, что документ уже существует в базе данных
    Если Не ЭтоНовый() Тогда 
        Если Не РазрешитьПросмотрЧужихДокументов(Автор) Тогда                               
            Предупреждение("Недостаточно полномочий для просмотра документов других пользователей!");                              
            Отказ = Истина;                              
        КонецЕсли;                                                                   
    КонецЕсли;
КонецПроцедуры

Обратите внимание, что обращение к методу ЭтоНовый() можно осуществлять как напрямую, так и явно указывая контекст объекта: ЭтотОбъект.ЭтоНовый(). Оба варианта будут работать абсолютно идентично и корректно пройдут синтаксический контроль платформы.

Важный технический нюанс: подводные камни проверки через «Ссылка.Пустая()»

Иногда на форумах или в старых учебниках можно встретить альтернативный совет для проверки новизны объекта — анализировать заполненность его уникального идентификатора (ссылки). Код такой проверки обычно выглядит следующим образом: Если Ссылка.Пустая() Тогда ....

Проанализируем эту ситуацию глубже. Действительно, у абсолютно нового документа ссылка в базе данных еще отсутствует, поэтому метод Ссылка.Пустая() вернет значение Истина. Однако в профессиональной разработке полагаться исключительно на этот метод небезопасно.

Дело в том, что в 1С существует специализированный метод УстановитьСсылкуНового(). Он применяется, когда разработчику необходимо программно назначить объекту конкретный уникальный идентификатор (GUID) еще до момента физической записи объекта в базу данных. Это часто требуется при интеграции с внешними системами, генерации штрихкодов или при создании связанных аналитических записей.

Если для нового документа был вызван метод УстановитьСсылкуНового(), то:

  1. Свойство Ссылка перестает быть пустым.
  2. Вызов метода Ссылка.Пустая() вернет значение Ложь (как будто документ уже записан в базу).
  3. Вызов правильного метода ЭтоНовый() все равно вернет Истина, так как физической записи в таблицах СУБД по-прежнему нет.

Вывод: для точной проверки новизны объекта в обычном приложении всегда следует отдавать предпочтение методу ЭтоНовый(), избегая проверки на пустоту ссылки.

Решение проблемы в управляемом приложении (1С 8.3)

В современных конфигурациях 1С, работающих на управляемом интерфейсе, логика взаимодействия клиента и сервера строго разделена. На клиенте в управляемой форме мы не имеем прямого доступа к прикладному объекту базы данных — вместо него используется специализированный тип данных ДанныеФормыСтруктура (обычно представленный реквизитом Объект).

По этой причине вызвать метод Объект.ЭтоНовый() напрямую в клиентском коде не удастся. Рассмотрим по шагам три основных сценария проверки новизны в управляемых формах.

Вариант А. Проверка на сервере при создании формы (Рекомендуемый способ)

Наиболее правильным архитектурным решением является перенос проверок прав доступа на серверную сторону в момент инициализации формы. На сервере мы можем легко определить новизну открываемого объекта, проанализировав параметр формы Ключ. Если документ уже записан, параметр Ключ будет содержать заполненную ссылку на него. Если документ создается с нуля — ключ будет пустым.


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Если параметр "Ключ" не заполнен, значит открывается новый документ
    Если ЗначениеЗаполнено(Параметры.Ключ) Тогда
        // Документ уже существует в базе. Выполняем проверку прав доступа.
        Если Не РазрешитьПросмотрЧужихДокументов(Объект.Автор) Тогда
            ВызватьИсключение "Недостаточно полномочий для просмотра чужих документов!";
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Вариант Б. Проверка непосредственно на клиенте

Если вам критически важно выполнить проверку именно на стороне тонкого клиента (например, в процедуре ПриОткрытии на управляемой форме), то здесь допускается использование анализа заполненности ссылки реквизита формы:


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Проверяем заполненность ссылки на клиенте
    Если ЗначениеЗаполнено(Объект.Ссылка) Тогда
        // Ссылка заполнена, значит документ уже записан в базу данных
        Если Не РазрешитьПросмотрЧужихДокументов(Объект.Автор) Тогда
            ПоказатьПредупреждение(, "Недостаточно полномочий для просмотра документа!");
            Отказ = Истина;
        КонецЕсли;
    КонецЕсли;
КонецПроцедуры

Вариант В. Использование серверного контекста для точной проверки

В редких случаях, когда на управляемой форме задействован механизм предварительной установки ссылки и проверка по Объект.Ссылка может выдать ложный результат, можно временно преобразовать данные управляемой формы в реальный объект базы данных на сервере:


&НаСервере
Функция ДокументЯвляетсяНовым()
    // Преобразуем данные формы во временный прикладной объект
    ТекущийОбъект = РеквизитФормыВЗначение("Объект");
    Возврат ТекущийОбъект.ЭтоНовый();
КонецФункции

&НаКлиенте
Процедура ПриОткрытии(Отказ)
    // Вызываем серверную функцию для надежной проверки новизны
    Если Не ДокументЯвляетсяНовым() Тогда
        // Логика проверки прав доступа...
    КонецЕсли;
КонецПроцедуры

Обратите внимание, что метод РеквизитФормыВЗначение является ресурсоемким, так как выполняет полную сериализацию данных формы на сервер и инициализацию объекта. Используйте данный подход только тогда, когда проверка через параметры формы или заполненность ссылки гарантированно не решает вашу задачу.

← На главную