Разработка и Конфигурация · 12 мин
Как программно создать предопределенный элемент справочника в 1С
Разбираем, как программно создать предопределенный элемент справочника в 1С: методы ПолучитьСсылку, работа с ИмяПредопределенныхДанных, типичные ошибки и проверка результата.
Предопределенные элементы справочников — это элементы, описанные в конфигураторе на этапе разработки и автоматически создаваемые платформой при обновлении информационной базы. Они нужны там, где код конфигурации жёстко опирается на конкретные значения: валюта рубль, ставка НДС, вид расчёта, типовая организация. Проблема в том, что в файловых базах, при выгрузке данных или при ручном удалении такие элементы иногда отсутствуют, и разработчику требуется создать их программно — с сохранением связи между именем предопределённых данных и реальным объектом базы.
Создать предопределённый элемент «в лоб» через обычный СоздатьЭлемент() недостаточно: объект получит наименование и реквизиты, но не будет связан с предопределённым именем из конфигурации. Обращение вида Справочники.Валюты.USD по-прежнему вернёт ошибку или пустую ссылку. Ниже разобраны рабочие способы создать предопределённый элемент программно, их ограничения и способы проверки результата.
Как платформа хранит и создаёт предопределённые элементы
При обновлении конфигурации базы данных платформа автоматически создаёт в таблицах данных объекты для всех предопределённых элементов, описанных в конфигураторе. Каждому такому объекту присваивается значение поля «Имя предопределённых данных», а платформа поддерживает служебную таблицу соответствия между предопределёнными именами и ссылками. Именно по этой таблице работает обращение Справочники.Валюты.НайтиПредопределенный() и точечный синтаксис Справочники.Валюты.USD.
Автоматическое создание срабатывает не всегда. В файловых базах, восстановленных из выгрузки, в копиях баз, где предопределённые элементы были удалены пользователем, в узлах РИБ после определённых манипуляций связь может отсутствовать. Тогда при обращении к предопределённому элементу возникает ошибка «Предопределенный элемент отсутствует в данных» или возвращается битая ссылка.
Важно понимать: у предопределённого элемента два идентификатора — обычная уникальная ссылка и строковое имя предопределённых данных. Программное создание сводится к тому, чтобы создать объект и корректно прописать ему это имя до записи в базу.
Способ 1. Создание объекта с установкой ИмяПредопределенныхДанных
Основной программный приём — создать объект справочника, заполнить реквизиты и перед записью присвоить свойству ИмяПредопределенныхДанных имя, заданное в конфигураторе. Свойство доступно у объекта справочника и доступно для изменения, если справочник не находится в режиме автоматического обновления предопределённых данных, блокирующего ручную установку.
НовыйЭлемент = Справочники.Валюты.СоздатьЭлемент();
НовыйЭлемент.Наименование = "USD";
НовыйЭлемент.НаименованиеПолное = "Доллар США";
НовыйЭлемент.ИмяПредопределенныхДанных = "USD";
НовыйЭлемент.Записать();
После записи платформа регистрирует соответствие, и обращение Справочники.Валюты.USD начнёт возвращать ссылку на созданный объект. Если в базе уже существует элемент с таким же предопределённым именем, запись завершится ошибкой — дубли предопределённых имён платформа не допускает.
В управляемых приложениях и при обновлении через БСП (библиотеку стандартных подсистем) ручная установка ИмяПредопределенныхДанных может быть заблокирована: при записи свойство сбрасывается, и элемент остаётся обычным. В таком случае используют второй способ — обновление предопределённых данных штатными средствами.
Способ 2. Обновление предопределённых данных штатными средствами
Более безопасный путь — заставить платформу саму пересоздать отсутствующие предопределённые элементы. Для этого у менеджера справочника есть метод ОбновитьПредопределенныеДанные() в некоторых версиях платформы, а также глобальный механизм обновления, запускаемый при обновлении конфигурации базы данных. В типовых конфигурациях на БСП обновление выполняется процедурами подсистемы обновления информационной базы.
Справочники.Валюты.ОбновитьПредопределенныеДанные();
Метод проходит по всем предопределённым элементам, описанным в конфигураторе, и создаёт недостающие объекты с корректной привязкой имён. Это предпочтительный вариант, когда отсутствует сразу несколько предопределённых элементов или когда ручная установка имени заблокирована настройками конфигурации.
Дополнительно существует параметр запуска конфигуратора ОбновитьПредопределенныеДанные в составе команд обновления, а в режиме предприятия — стандартная обработка обновления при первом запуске после изменения конфигурации. Эти механизмы эквивалентны: итогом всегда является создание объектов и заполнение служебной таблицы соответствия.
Сравнение способов
Подходит для точечного создания одного элемента и заполнения его реквизитов. Ограничение: может блокироваться настройками конфигурации и требует, чтобы дублей имени не существовало.
Подходит для массового восстановления всех предопределённых элементов справочника. Ограничение: создаёт элементы со значениями по умолчанию, реквизиты придётся заполнять отдельно.
Штатный путь при развёртывании и обновлении. Не подходит для оперативного восстановления в работающей базе без остановки пользователей.
Проверка существования и поиск предопределённого элемента
Перед созданием всегда проверяйте, нет ли уже элемента с нужным предопределённым именем. Для этого служит метод НайтиПредопределенный() менеджера справочника — он возвращает ссылку или пустую ссылку, если элемент отсутствует. Полагаться на поиск по наименованию нельзя: наименование пользователь мог изменить, а связь с предопределённым именем при этом сохраняется.
СсылкаUSD = Справочники.Валюты.НайтиПредопределенный("USD");
Если СсылкаUSD.Пустая() Тогда
// создаём элемент и привязываем имя
КонецЕсли;
Обратная проверка — узнать имя предопределённых данных у существующей ссылки — выполняется методом ИмяПредопределенныхДанных у объекта или через функцию ПолучитьИмяПредопределенного() в некоторых контекстах. Это полезно при диагностике: если у «правильного» на вид элемента имя пустое, значит, привязка утеряна и код, обращающийся по имени, работать не будет.
Также полезно помнить про свойство Предопределенный у объекта: оно показывает, связан ли элемент с предопределёнными данными вообще. Сочетание Предопределенный = Истина и корректного имени — признак здорового состояния.
Как проверить результат
Возвращает непустую ссылку на созданный элемент
Возвращает пустую ссылку — привязка не создана
Истина, имя предопределённых данных совпадает с конфигуратором
Ложь или пустое имя — элемент обычный
Возвращает ссылку без исключений
Ошибка обращения или битая ссылка
Особенности для планов счетов, ПВХ и планов видов расчёта
Механизм предопределённых данных един для четырёх типов объектов: справочников, планов видов характеристик, планов счетов и планов видов расчёта. Программное создание отличается только менеджером объекта и набором обязательных реквизитов. У плана счетов, например, перед записью нужно заполнить код, вид счёта и признаки учёта, иначе запись не пройдёт проверку заполнения.
НовыйСчет = ПланыСчетов.Хозрасчетный.СоздатьСчет();
НовыйСчет.Код = "10.01";
НовыйСчет.Наименование = "Сырье и материалы";
НовыйСчет.Вид = ВидСчета.Активный;
НовыйСчет.ИмяПредопределенныхДанных = "СырьеИМатериалы";
НовыйСчет.Записать();
Для планов видов расчёта дополнительно проверяйте заполнение базовых и ведущих видов расчёта: если предопределённый вид расчёта ссылается на другие предопределённые, их нужно создать в правильном порядке — сначала те, на которые есть ссылки, потом зависимые. Нарушение порядка приводит к ошибкам записи или к «висячим» ссылкам в таблицах базы.
Работа в распределённых базах и при обмене
В узлах РИБ предопределённые элементы имеют особое поведение: их создание и изменение контролируется главным узлом, а попытка программно создать предопределённый элемент в подчинённом узле может привести к конфликтам при обмене. Если предопределённый элемент отсутствует в подчинённом узле, правильное решение — получить его обменом из главного узла, а не создавать локально.
При выгрузке и загрузке данных через универсальные механизмы (XML-обмен, выгрузка в файлы) предопределённая связь переносится вместе со ссылкой, если правила обмена корректно обрабатывают поле имени предопределённых данных. При сбоях обмена в базе-приёмнике элемент может появиться как обычный — тогда применяют ОбновитьПредопределенныеДанные() или перепривязку имени вручную на копии.
Типичные ошибки и как их избежать
Самая частая ошибка — создание элемента без установки ИмяПредопределенныхДанных и ожидание, что обращение по имени заработает. Второе место занимает попытка присвоить имя уже записанному объекту без учёта блокировок конфигурации: свойство молча сбрасывается, и разработчик долго ищет причину. Проверяйте значение свойства после записи, а не до неё.
Третья группа ошибок — дубли. Если предопределённый элемент был удалён, а затем создан заново вручную пользователем с тем же наименованием, при обновлении конфигурации платформа может создать второй объект с тем же предопределённым именем, что приведёт к конфликту. Перед обновлением стоит проверить базу обработкой поиска дублей по предопределённым именам.
- 1Сделайте резервную копию базы или работайте на копии
- 2Проверьте наличие элемента через НайтиПредопределенный(Имя)
- 3Если элемента нет — попробуйте ОбновитьПредопределенныеДанные() для справочника
- 4Если обновление недоступно — создайте объект, заполните реквизиты и установите ИмяПредопределенныхДанных до записи
- 5Запишите объект и проверьте свойство Предопределенный и имя после записи
- 6Проверьте обращение по имени из кода и работу зависимых механизмов
Частые вопросы
Почему ИмяПредопределенныхДанных сбрасывается при записи?
Обычно это означает, что конфигурация переведена в режим, где изменение предопределённых данных разрешено только платформе при обновлении. В таком случае используйте ОбновитьПредопределенныеДанные() или обновление конфигурации базы вместо ручной установки свойства.
Можно ли привязать предопределённое имя к уже существующему элементу?
Да, если имя ещё не занято другим объектом и конфигурация не блокирует изменение: получите объект по ссылке, установите ИмяПредопределенныхДанных и запишите. Если имя уже занято, сначала нужно освободить его у старого объекта, что безопаснее делать на копии базы.
Чем НайтиПредопределенный отличается от обращения через точку?
НайтиПредопределенный("Имя") возвращает пустую ссылку при отсутствии элемента и удобен для проверок. Обращение Справочники.Валюты.USD при отсутствии элемента вызывает исключение, поэтому в защищённом коде предпочтителен первый вариант.
Создадутся ли предопределённые элементы автоматически при загрузке dt?
При загрузке выгрузки платформа восстанавливает данные как есть. Если в выгрузке предопределённые элементы были удалены, они не появятся сами — потребуется ОбновитьПредопределенныеДанные() или обновление конфигурации базы данных.
Как перенести предопределённые элементы между базами без обмена?
Надёжнее всего выгрузить элементы с сохранением ссылок (например, через XML-обмен с режимом выгрузки по ссылке) и после загрузки выполнить ОбновитьПредопределенныеДанные() в базе-приёмнике, чтобы платформа восстановила служебную таблицу соответствия имён и ссылок.
Что делать, если появились два элемента с одним предопределённым именем?
Это конфликтная ситуация, возникающая после сбоев обмена или ручного создания дублей. На копии базы определите, какая ссылка используется в данных, у лишнего объекта очистите ИмяПредопределенныхДанных или удалите его с контролем ссылочной целостности, затем проверьте работу обращений по имени.
Что важно запомнить
Предопределённый элемент — это объект плюс привязка имени предопределённых данных. Создавайте его либо установкой ИмяПредопределенныхДанных до записи, либо через ОбновитьПредопределенныеДанные(), всегда проверяйте результат через НайтиПредопределенный и работайте на копии базы.