К статье
Практический материал

Разработка и Конфигурация · 12 мин

Как создать справочник в 1С программно

Как программно создать справочник в 1С: работа с менеджером справочника, создание элементов и групп, заполнение реквизитов, типовые ошибки и примеры кода.

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

Работа ведётся через менеджер справочника — объект вида Справочники.ИмяСправочника. Через него создаются новые элементы и группы, выполняется поиск существующих значений и проверяются дубли. Ключевые методы — СоздатьЭлемент(), СоздатьГруппу(), НайтиПоНаименованию() и НайтиПоКоду().

Важно понимать разницу между созданием объекта в памяти и его записью в базу данных. Новый элемент существует только в оперативной памяти до вызова метода Записать(). Если метод не вызван или запись завершилась ошибкой, данные в информационную базу не попадут — это одна из самых распространённых причин «потерянных» элементов у начинающих разработчиков.

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

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

Менеджер возвращает два типа объектов. СправочникОбъект — полноценный объект с возможностью изменения и записи, его возвращают методы СоздатьЭлемент(), СоздатьГруппу() и ПолучитьОбъект() у ссылки. СправочникСсылка — лёгкий объект-указатель на существующий элемент, пригодный только для чтения данных и сравнения.

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

Базовый сценарий: создание простого элемента

Минимальный код создания элемента выглядит так: получаем менеджер, вызываем СоздатьЭлемент(), заполняем реквизиты, записываем. После успешной записи у объекта появляется ссылка, которую можно использовать для связи с другими объектами.

НовыйКонтрагент = Справочники.Контрагенты.СоздатьЭлемент();

НовыйКонтрагент.Наименование = "ООО Ромашка";

НовыйКонтрагент.ИНН = "7712345678";

НовыйКонтрагент.Записать();

СсылкаНаКонтрагента = НовыйКонтрагент.Ссылка;

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

После вызова Записать() платформа выполняет проверку заполнения обязательных реквизитов, контроль уникальности кода (если он включён в свойствах справочника) и обработчики событий ПередЗаписью и ПриЗаписи. Ошибка на любом из этих этапов прерывает запись и вызывает исключение.

Порядок создания элемента
  1. 1
    Получите менеджер: Справочники.ИмяСправочника
  2. 2
    Вызовите СоздатьЭлемент() или СоздатьГруппу()
  3. 3
    Заполните наименование и обязательные реквизиты
  4. 4
    При необходимости укажите родителя и владельца
  5. 5
    Вызовите Записать() и обработайте возможное исключение
  6. 6
    Проверьте результат через Ссылка и поиск в базе

Создание групп и работа с иерархией

Если справочник иерархический, элементы можно распределять по папкам. Группа создаётся методом СоздатьГруппу(), а привязка элемента к группе выполняется через реквизит Родитель, которому присваивается ссылка на группу.

Группа = Справочники.Номенклатура.СоздатьГруппу();

Группа.Наименование = "Материалы";

Группа.Записать();

Товар = Справочники.Номенклатура.СоздатьЭлемент();

Товар.Наименование = "Краска белая";

Товар.Родитель = Группа.Ссылка;

Товар.Записать();

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

Нельзя записать элемент, ссылающийся на ещё не записанную группу: у незаписанного объекта нет ссылки. Поэтому порядок строго определён — сначала Записать() для группы, затем создание дочерних элементов. При загрузке многоуровневой иерархии из файла группы записывают по уровням, от корня к листьям.

Проверка дублей перед созданием

Создание элемента без проверки существования — типичный источник задвоенной номенклатуры и контрагентов. Перед созданием следует искать элемент по ключевым признакам: коду, наименованию или естественному ключу (ИНН для контрагентов, артикулу для товаров).

ИскомыйИНН = "7712345678";

Найденный = Справочники.Контрагенты.НайтиПоРеквизиту("ИНН", ИскомыйИНН);

Если Найденный.Пустая() Тогда

Новый = Справочники.Контрагенты.СоздатьЭлемент();

Новый.Наименование = "ООО Ромашка";

Новый.ИНН = ИскомыйИНН;

Новый.Записать();

Иначе

Сообщить("Контрагент уже существует: " + Найденный.Наименование);

КонецЕсли;

Методы поиска: НайтиПоНаименованию(Наименование, ТочноеСоответствие), НайтиПоКоду(Код), НайтиПоРеквизиту(ИмяРеквизита, Значение). Все они возвращают ссылку; если ничего не найдено — пустую ссылку, которую проверяют методом Пустая(). Учтите, что поиск по наименованию без флага точного соответствия ищет по началу строки.

Подчинённые справочники, табличные части и дополнительные реквизиты

Если справочник подчинён другому (например, «Договоры контрагентов» подчинены «Контрагентам»), при создании обязательно указывается реквизит Владелец. Без него запись будет невозможна или элемент окажется недоступен в интерфейсе владельца.

Договор = Справочники.ДоговорыКонтрагентов.СоздатьЭлемент();

Договор.Владелец = СсылкаНаКонтрагента;

Договор.Наименование = "Договор поставки № 15";

Договор.Записать();

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

В типовых конфигурациях на платформе 8.3 значительная часть свойств хранится не в реквизитах, а в механизме дополнительных реквизитов и сведений (БСП). Простое присваивание Объект.Цвет = ... для такого свойства вызовет ошибку — значения записываются через табличную часть ДополнительныеРеквизиты с указанием ссылки на свойство из плана видов характеристик.

Типичные ошибки
01
Забыли вызвать Записать() — элемент остался только в памяти и не попал в базу
02
Присвоили Родителя до записи группы — ссылка пустая, иерархия не построилась
03
Не заполнили Владельца у подчинённого справочника — ошибка записи или «потерянный» элемент
04
Ищут дубли по наименованию без точного соответствия — находятся чужие элементы со схожим началом названия
05
Игнорируют обработчики ПередЗаписью в типовых конфигурациях — запись падает с непонятной ошибкой из-за незаполненных служебных реквизитов

Массовое создание: транзакции и производительность

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

НачатьТранзакцию();

Попытка

Для Каждого СтрокаДанных Из ДанныеЗагрузки Цикл

Элемент = Справочники.Номенклатура.СоздатьЭлемент();

Элемент.Наименование = СтрокаДанных.Наименование;

Элемент.Записать();

КонецЦикла;

ЗафиксироватьТранзакцию();

Исключение

ОтменитьТранзакцию();

ВызватьИсключение ОписаниеОшибки();

КонецПопытки;

У монолитной транзакции есть обратная сторона: сбой на последнем элементе отменит всю загрузку. Альтернатива — порционная фиксация, например каждые 500–1000 элементов. Такой подход сочетает приемлемую скорость с умеренными потерями при ошибке.

Дополнительные приёмы ускорения: отключить использование итогов там, где это применимо, загружать данные порциями через запросы вместо построчного чтения, а при обмене использовать ОбменДанными.Загрузка = Истина — этот режим отключает проверки и обработчики записи. Применять его стоит осознанно: отключается и контроль корректности данных.

Способы записи при загрузке

Записать() в каждой итерации

Просто и надёжно, ошибка затрагивает один элемент. Медленно при больших объёмах.

Одна транзакция на всю загрузку

Максимальная скорость и целостность, но сбой откатывает всё и держит блокировки дольше.

Порционные транзакции

Компромисс: фиксация каждые несколько сотен элементов, потеря ограничена одной порцией.

ОбменДанными.Загрузка = Истина

Быстрее за счёт отключения проверок, но ответственность за корректность данных ложится на код загрузки.

Проверка результата и отладка

После выполнения кода убедитесь, что элементы реально появились в базе. Простейший способ — открыть список справочника в режиме предприятия. Программно проверку делают поиском по созданному значению или запросом с подсчётом количества.

Полезные приёмы отладки: вывод созданной ссылки через Сообщить(), проверка НовыйЭлемент.ЭтоНовый() до записи (должно быть Истина), анализ текста исключения — платформа обычно указывает, какой реквизит не заполнен или какое правило нарушено. В конфигураторе удобно поставить точку останова на строке Записать() и посмотреть состояние объекта в табло.

Контрольные точки

Как проверить результат

Элемент в списке справочника
Норма

Новая строка видна в режиме предприятия с корректным наименованием

Тревожный признак

Элемента нет — вероятно, не вызван Записать() или произошло исключение

Ссылка после записи
Норма

Свойство Ссылка заполнено, ЭтоНовый() возвращает Ложь

Тревожный признак

Ссылка пустая — запись не выполнена

Иерархия
Норма

Элемент отображается внутри нужной группы

Тревожный признак

Элемент в корне списка — не заполнен Родитель или группа не была записана

Дубли
Норма

Поиск по ключу находит ровно один элемент

Тревожный признак

Несколько одинаковых записей — отсутствовала проверка перед созданием

Частые вопросы

Чем отличается СоздатьЭлемент() от ПолучитьОбъект()?

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

Как создать элемент справочника в фоновом задании?

Код создания тот же, но в фоновом задании недоступен интерактивный интерфейс: нельзя открывать формы и показывать диалоги. Сообщения пользователю заменяют записью в журнал регистрации или передачей результата через параметры фонового задания.

Можно ли задать код элемента вручную?

Да, свойству Код можно присвоить значение до записи, если в конфигураторе для справочника включён ручной ввод кодов. При автонумерации платформа присвоит код сама, а ручная установка может нарушить последовательность нумерации.

Что делать, если Записать() вызывает ошибку в типовой конфигурации?

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

Как создать элемент, если справочник вводится на основании другого объекта?

Справочники редко вводятся на основании, но если механизм настроен, используйте метод Заполнить(ДанныеЗаполнения) после СоздатьЭлемент(): объект сам заполнит реквизиты по данным основания через обработчик ОбработкаЗаполнения.

Почему поиск НайтиПоНаименованию не находит существующий элемент?

Наиболее вероятные причины: лишние пробелы или разный регистр не влияют, но поиск без второго параметра Истина ищет по началу наименования, а не по полному совпадению. Также проверьте, не помечен ли элемент на удаление — по умолчанию такие элементы тоже находятся, но логика вашего кода может их отфильтровывать.

Итог

Что важно запомнить

Элемент справочника создаётся цепочкой: СоздатьЭлемент() → заполнение реквизитов (включая Родителя и Владельца) → Записать(). Перед созданием проверяйте дубли по уникальному ключу, при массовой загрузке используйте транзакции, а результат всегда проверяйте через ссылку и поиск в базе.