Ошибка при использовании функции ПредопределенноеЗначение: почему 1С не видит объект?

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

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

Разбираем основную причину: единственное и множественное число

Проанализируем типичную ситуацию. Разработчик пишет код для добавления элемента перечисления в массив:


ТипыНоменклатуры.Добавить(ПредопределенноеЗначение("Перечисления.ТипыНоменклатуры.Товар"));

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

Рассмотрим правильные варианты написания для различных объектов:

Интересно заметить, что встроенный помощник (Ctrl+Space) иногда может вводить в заблуждение, предлагая путь через множественное число, если разработчик начинает писать его вручную. Однако при выполнении кода платформа ожидает строгого соответствия правилам внутреннего языка.

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

Давайте систематизируем знания о том, как правильно обращаться к различным объектам через функцию ПредопределенноеЗначение. Этот синтаксис полностью совпадает с оператором ЗНАЧЕНИЕ, который мы используем в запросах. Разберем по шагам доступные типы:

  1. Справочники (Catalog): Используется для получения ссылок на предопределенные элементы. Пример: ПредопределенноеЗначение("Справочник.Валюты.Рубль").
  2. Перечисления (Enum): Самый частый случай использования. Пример: ПредопределенноеЗначение("Перечисление.СтатусыЗаказов.Согласован").
  3. Планы видов характеристик (ChartOfCharacteristicTypes): ПредопределенноеЗначение("ПланВидовХарактеристик.ДополнительныеРеквизитыИСведения.Цвет").
  4. Планы счетов (ChartOfAccounts) и Планы видов расчета (ChartOfCalculationTypes): Аналогично справочникам.
  5. Пустые ссылки: Для документов и задач можно получить пустую ссылку. Пример: ПредопределенноеЗначение("Документ.РеализацияТоваровУслуг.ПустаяСсылка").

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

Альтернативный способ: ОписаниеТипов и получение пустой ссылки

Иногда задача стоит не в получении конкретного предопределенного значения, а в получении пустой ссылки нужного типа на стороне клиента. Рассмотрим ситуацию: нам нужно инициализировать переменную пустой ссылкой справочника Банки, не обращаясь лишний раз к серверу. Многие разработчики пытаются использовать ПредопределенноеЗначение, но есть более элегантный способ через ОписаниеТипов.

Проанализируем пример кода:


// Получение пустой ссылки на клиенте
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("СправочникСсылка.Банки"));
НужныйТип = Новый ОписаниеТипов(МассивТипов);
ПустаяСсылкаБанка = НужныйТип.ПривестиЗначение();

Метод ПривестиЗначение() без параметров возвращает значение по умолчанию для данного типа. Для ссылочных типов это всегда будет пустая ссылка. Этот метод работает на клиенте молниеносно и не требует контекстных вызовов сервера.

Оптимизация: кэширование и производительность

Часто возникает вопрос: насколько «дорого» использовать ПредопределенноеЗначение внутри циклов на стороне клиента? Разберем, как платформа обрабатывает этот вызов.

Клиентское кэширование: При самом первом вызове функции с определенной строкой параметра (например, «Перечисление.Типы.Товар») система действительно выполняет скрытый вызов сервера, чтобы получить внутренний идентификатор объекта. Однако результат этого вызова кэшируется в памяти клиентского приложения. Все последующие вызовы с этой же строкой будут выполняться мгновенно, обращаясь к локальному кэшу сеанса.

Тем не менее, если в коде формы встречается 20 разных вызовов этой функции для разных значений, это может привести к 20 микро-запросам к серверу при открытии. В таких случаях мы рекомендуем получить все нужные значения один раз на сервере (например, в процедуре ПриСозданииНаСервере), поместить их в структуру и передать на клиент в составе параметров формы или реквизитов.

Сравним два подхода:

Подход №1 (Неоптимальный):


&НаКлиенте
Процедура Обработка()
    ТипТовар = ПредопределенноеЗначение("Перечисление.ТипыНоменклатуры.Товар");
    ТипУслуга = ПредопределенноеЗначение("Перечисление.ТипыНоменклатуры.Услуга");
    // Каждый вызов в первый раз инициирует серверный запрос
КонецПроцедуры

Подход №2 (Рекомендуемый):


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    // Значения доступны на сервере напрямую через точку
    КэшЗначений.Вставить("Товар", Перечисления.ТипыНоменклатуры.Товар);
    КэшЗначений.Вставить("Услуга", Перечисления.ТипыНоменклатуры.Услуга);
КонецПроцедуры

Проблемы при обновлении и «битые» ссылки

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

Сравнение с оператором ЗНАЧЕНИЕ в запросах

Важно понимать разницу между функцией ПредопределенноеЗначение() во встроенном языке и оператором ЗНАЧЕНИЕ() в языке запросов. Рассмотрим ключевые отличия:

1. Момент проверки: Оператор ЗНАЧЕНИЕ() проверяется на этапе компиляции запроса. Если вы ошибетесь в написании, конфигуратор выдаст ошибку сразу. Функция ПредопределенноеЗначение() проверяется только в момент выполнения (Runtime). Это значит, что опечатка может «выстрелить» у пользователя спустя долгое время.

2. Гибкость: В функцию ПредопределенноеЗначение() можно передать переменную, содержащую строку. В оператор ЗНАЧЕНИЕ() можно передать только статичную строку в кавычках.

Выясним, когда что лучше использовать. Если вы работаете в коде и вам нужно сравнить значение реквизита с константой, лучше использовать ПредопределенноеЗначение (на клиенте) или прямое обращение через метаданные (на сервере). Если же вы пишете запрос, всегда используйте ЗНАЧЕНИЕ, так как это работает эффективнее на уровне СУБД.

Особенности мобильной платформы

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

В завершение подчеркнем: внимательность к деталям (таким как единственное число в названии типов) и понимание того, где выполняется код (клиент или сервер), позволяют избежать большинства трудноуловимых ошибок при разработке на платформе 1С:Предприятие 8.3.

← На главную