Разработка и Конфигурация · 12 мин
Как получить предопределенный элемент справочника в 1С
Как получить предопределенный элемент справочника в 1С: методы ПредопределенноеЗначение, НайтиПоИмениПредопределенныхДанных, особенности, ошибки и примеры кода.
Предопределенные элементы справочников создаются в конфигураторе и нужны разработчику как «якоря»: на них можно ссылаться в коде, не опасаясь, что пользователь переименует или удалит запись. Типичные примеры — ставки НДС, валюта «Рубль», виды номенклатуры, типы контрагентов. Получить такой элемент в коде можно несколькими способами, и выбор зависит от того, работаете вы на сервере или на клиенте, в обычном или управляемом приложении.
Основные инструменты — метод ПредопределенноеЗначение() глобального контекста и метод менеджера справочника НайтиПоИмениПредопределенныхДанных(). Первый работает быстро и без запроса к базе, второй выполняет поиск по данным и был актуален в ранних версиях платформы 8.3. Ниже разобраны оба подхода, их отличия, типичные ошибки и особенности поведения в разных режимах.
Неправильное обращение к предопределенным элементам — частая причина ошибок вида «Предопределенный элемент отсутствует в данных» после обновления конфигурации или переноса данных. Поэтому важно не только знать синтаксис, но и понимать, как платформа хранит связь между именем в конфигураторе и записью в базе.
Что такое предопределенный элемент и как он хранится
Предопределенный элемент — это запись справочника или плана видов характеристик, созданная разработчиком в конфигураторе на закладке «Прочее» → «Предопределенные» (или через свойство «Предопределенные» объекта метаданных). У такого элемента есть имя, заданное в конфигураторе, которое не видно пользователю, но доступно в коде.
Начиная с платформы 8.3 предопределенные элементы хранятся как обычные записи таблицы справочника, а связь с именем из конфигурации обеспечивается служебным полем ИмяПредопределенныхДанных. В более ранних версиях использовался отдельный механизм с хранением вне таблицы, из-за чего и существовало два разных метода поиска.
Пользователь может изменить код и наименование предопределенного элемента (если это не запрещено настройками объекта), но не может изменить служебное имя. Именно поэтому в коде всегда обращаются по имени предопределенных данных, а не по коду или наименованию — это гарантирует устойчивость программы к правкам данных.
Основной способ: метод ПредопределенноеЗначение()
Метод ПредопределенноеЗначение() — универсальный и рекомендуемый способ. Он принимает строку вида "Справочник.ИмяСправочника.ИмяЭлемента" и возвращает ссылку на элемент. Метод не обращается к базе данных запросом — значение разрешается через кэш метаданных, поэтому работает быстро и доступен на тонком клиенте, в том числе в клиентских процедурах.
ВалютаРубль = ПредопределенноеЗначение("Справочник.Валюты.Рубль");
СтавкаНДС20 = ПредопределенноеЗначение("Справочник.СтавкиНДС.НДС20");
ВидНоменклатуры = ПредопределенноеЗначение("Справочник.ВидыНоменклатуры.Товар");Если элемент с указанным именем отсутствует в данных (например, удален или не создан при обновлении), метод возвращает пустую ссылку соответствующего типа, а не ошибку. Это важно учитывать: код не упадет, но дальнейшая логика может получить пустое значение там, где ожидалась реальная ссылка.
Метод применим не только к справочникам: он работает с планами счетов, планами видов расчета, планами видов характеристик, перечислениями и системными перечислениями (например, ПредопределенноеЗначение("Перечисление.ВидыЦен.Оптовая") или ПредопределенноеЗначение("ДвижениеДенежныхСредств.Приход")).
Обращение через менеджер справочника на сервере
В серверном коде (модули объектов, общие модули с признаком «Сервер») доступна сокращенная форма: Справочники.Валюты.Рубль. Платформа сама находит предопределенный элемент по имени и возвращает ссылку. Такая запись короче и проверяется компилятором: если имя указано неверно, ошибка проявится еще при проверке модуля.
// Серверный код
СсылкаНаЭлемент = Справочники.Валюты.Рубль;
// Эквивалент через ПредопределенноеЗначение
СсылкаНаЭлемент = ПредопределенноеЗначение("Справочник.Валюты.Рубль");Ограничение: обращение через точку от менеджера справочника недоступно на тонком и веб-клиенте — там нет менеджеров объектов. Поэтому в общих модулях с признаками «Клиент» или «Клиент (обычное приложение)» используйте только ПредопределенноеЗначение(). Если модуль компилируется и на сервере, и на клиенте, единственный безопасный вариант — именно этот метод.
Сравнение способов получения элемента
Работает на сервере и клиенте, не требует запроса к базе, возвращает пустую ссылку при отсутствии элемента. Универсальный вариант.
Короткая запись, проверяется компилятором, но доступна только на сервере и толстом клиенте.
Устаревший метод, выполняет запрос к базе. Оправдан только при совместимости со старыми версиями платформы.
Устаревший метод НайтиПоИмениПредопределенныхДанных()
Метод НайтиПоИмениПредопределенныхДанных("ИмяЭлемента") вызывается у менеджера справочника и выполняет поиск записи по полю ИмяПредопределенныхДанных. Он появился, когда предопределенные элементы перенесли в таблицы базы, как переходный инструмент.
СсылкаНаЭлемент = Справочники.Валюты.НайтиПоИмениПредопределенныхДанных("Рубль");
Если СсылкаНаЭлемент = Неопределено Тогда
// Элемент не найден в данных
КонецЕсли;В отличие от ПредопределенноеЗначение(), этот метод выполняет реальный запрос к базе данных, то есть медленнее, и возвращает Неопределено, если элемент не найден (а не пустую ссылку). В новых разработках использовать его не рекомендуется, но встретить метод можно в типовых конфигурациях и старом коде.
Как проверить результат и обработать отсутствие элемента
Типовая ситуация: после обновления конфигурации или загрузки данных из другой базы предопределенный элемент оказался «отвязан» от имени или вовсе отсутствует. Чтобы код не работал с пустыми ссылками, добавляйте проверку.
ВалютаРубль = ПредопределенноеЗначение("Справочник.Валюты.Рубль");
Если ВалютаРубль.Пустая() Тогда
ВызватьИсключение "Не найден предопределенный элемент справочника Валюты: Рубль";
КонецЕсли;Для диагностики состояния предопределенных элементов в базе полезен запрос по полю ИмяПредопределенныхДанных. Он показывает, какие записи связаны с именами из конфигуратора, а какие остались без связи (обычно после обмена данными).
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Валюты.Ссылка КАК Ссылка,
| Валюты.Наименование КАК Наименование,
| Валюты.ИмяПредопределенныхДанных КАК ИмяПредопределенныхДанных
|ИЗ
| Справочник.Валюты КАК Валюты
|ГДЕ
| Валюты.ИмяПредопределенныхДанных <> """;
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Наименование + " -> " + Выборка.ИмяПредопределенныхДанных);
КонецЦикла;Как проверить результат
Непустая ссылка нужного типа справочника
Пустая ссылка или Неопределено — элемент не найден
У записи заполнено имя, совпадающее с конфигуратором
Поле пустое или имя не совпадает — связь потеряна
Элементы созданы автоматически при первом запуске
Ошибки «предопределенный элемент отсутствует» в журнале регистрации
Проблемы при обмене данными и обновлении
Самая частая проблема — дублирование или потеря связи предопределенных элементов после обмена между базами. Если в двух базах элементы создавались независимо, при обмене могут появиться две записи «Рубль» с разными ссылками, а имя предопределенных данных окажется только у одной из них. Код будет работать с одной записью, а пользователи — с другой.
Вторая типичная ситуация — режим совместимости. В конфигурациях с режимом совместимости «Не использовать» предопределенные элементы создаются платформой автоматически при обновлении. Если режим старый, создание и привязка могут отличаться, и при переходе на новый режим потребуется обработка по привязке существующих записей к именам.
При переносе данных между базами безопаснее сопоставлять предопределенные элементы по имени предопределенных данных, а не по GUID или наименованию. В типовых планах обмена для этого предусмотрены соответствующие настройки конвертации.
Типичные ошибки разработчиков
Отдельно стоит упомянуть опечатки в строковом имени. Поскольку ПредопределенноеЗначение() принимает строку, платформа не может проверить её на этапе компиляции. Чтобы снизить риск, выносите имена предопределенных элементов в константы кода или используйте серверное обращение через точку там, где это возможно, — оно проверяется компилятором.
Практический порядок действий
- 1Откройте справочник в конфигураторе и убедитесь, что нужный предопределенный элемент существует, запомните его имя
- 2В коде вызовите ПредопределенноеЗначение("Справочник.ИмяСправочника.ИмяЭлемента") — на клиенте только этот вариант
- 3На сервере при желании используйте краткую форму Справочники.ИмяСправочника.ИмяЭлемента
- 4Добавьте проверку результата на пустую ссылку с понятным текстом исключения
- 5Проверьте работу кода после обновления конфигурации и после тестового обмена данными
- 6При диагностике выполните запрос по полю ИмяПредопределенныхДанных, чтобы увидеть фактические привязки
Если предопределенного элемента еще нет, создайте его в конфигураторе: свойства справочника → «Предопределенные» → добавить элемент с именем, кодом и наименованием. После обновления конфигурации базы платформа создаст соответствующую запись в данных автоматически.
Если предопределенный элемент нужен в запросе, передавайте его как параметр (Запрос.УстановитьПараметр("Валюта", ПредопределенноеЗначение(...))), а не вставляйте имя в текст запроса. Так запрос остается читаемым, а значение вычисляется один раз до выполнения.
Итог
Что важно запомнить
Используйте ПредопределенноеЗначение("Справочник.Имя.ИмяЭлемента") как универсальный способ на сервере и клиенте. На сервере допустима краткая форма Справочники.Имя.ИмяЭлемента. Всегда проверяйте результат на пустую ссылку и не ищите предопределенные элементы по наименованию. При обменах и обновлениях контролируйте поле ИмяПредопределенныхДанных.
Частые вопросы
Почему ПредопределенноеЗначение() возвращает пустую ссылку?
Чаще всего элемент с указанным именем отсутствует в данных: он был удален, не создан при обновлении или потерял связь с именем после обмена. Проверьте запросом поле ИмяПредопределенныхДанных у записей справочника и сверьте имя с конфигуратором. Если записи нет — создайте её и привяжите имя обработкой или повторным обновлением конфигурации.
Можно ли получить предопределенный элемент на тонком клиенте?
Да, но только через ПредопределенноеЗначение(). Обращение через менеджер (Справочники.Имя.ИмяЭлемента) на тонком клиенте недоступно, поскольку менеджеры объектов существуют только на сервере. В клиентских общих модулях всегда применяйте первый вариант.
Чем отличается пустая ссылка от Неопределено в этих методах?
ПредопределенноеЗначение() при отсутствии элемента возвращает пустую ссылку типа справочника — проверяйте через .Пустая(). Устаревший НайтиПоИмениПредопределенныхДанных() возвращает Неопределено — проверяйте через сравнение с Неопределено. Смешивать проверки нельзя.
Что делать, если после обмена появились два одинаковых предопределенных элемента?
Определите запросом, у какой записи заполнено поле ИмяПредопределенныхДанных — именно её видит код. Для второй записи выполните поиск и замену ссылок на основную запись во всех документах и регистрах, затем пометьте дубль на удаление. Работу выполняйте на копии базы.
Можно ли пользователю переименовать предопределенный элемент?
Да, наименование и код пользователь менять может — на работу кода это не влияет, так как обращение идет по служебному имени. Удалить предопределенный элемент пользователю обычно запрещено настройками объекта или правами, и делать этого не следует: код, ссылающийся на элемент, начнет получать пустую ссылку.
Работает ли ПредопределенноеЗначение() для перечислений и других объектов?
Да. Метод универсален: он возвращает значения перечислений, предопределенные элементы справочников, планов счетов, планов видов характеристик, планов видов расчета, а также значения системных перечислений платформы — например, видов движения накопления или видов счета.