Разработка и Конфигурация · 12 мин
Как создать справочник 1С программно
Как программно создать элемент и группу справочника в 1С: методы СоздатьЭлемент, СоздатьГруппу, поиск дублей, запись, типичные ошибки и готовые примеры кода.
Программное создание элементов справочника — одна из базовых задач при разработке и доработке конфигураций 1С. Она встречается при загрузке данных из файлов, обмене с внешними системами, первоначальном заполнении базы и в обработчиках бизнес-процессов. Встроенный язык платформы даёт для этого понятный объектный интерфейс: менеджер справочника, методы создания и записи.
Важно сразу разделить две разные задачи. Первая — создать сам объект метаданных «Справочник» в конфигураторе, то есть описать новый вид справочника. Вторая — программно создать элемент уже существующего справочника, например добавить новую номенклатурную позицию или контрагента. Чаще всего под «создать каталог 1С программно» понимают именно вторую задачу, и основная часть материала посвящена ей, но оба сценария рассмотрены ниже.
Все примеры написаны на встроенном языке 1С и подходят для управляемых и обычных форм, для серверного и клиентского контекста с учётом ограничений, которые указаны отдельно. Перед запуском кода на рабочей базе сделайте резервную копию и сначала проверьте логику на тестовой копии.
Что понадобится перед началом работы
Для программной работы со справочником нужно знать его имя в конфигурации — именно то, которое задано в конфигураторе, а не синоним, видимый пользователю. Например, справочник с синонимом «Номенклатура» обычно имеет имя «Номенклатура», но в доработанных конфигурациях имена могут отличаться. Посмотреть имя можно в конфигураторе: откройте дерево конфигурации, найдите ветку «Справочники» и проверьте свойство «Имя».
Также понадобятся права. Пользователь, под которым выполняется код, должен иметь право «Добавление» и «Изменение» на конкретный справочник. При выполнении кода в привилегированном режиме (УстановитьПривилегированныйРежим) проверка прав отключается — это удобно для служебных обработок, но требует аккуратности, чтобы не создать данные, недоступные для контроля обычными пользователями.
Наконец, определите, где будет выполняться код: во внешней обработке, в общем модуле, в регламентном задании или в обработчике события. От этого зависят доступные директивы компиляции и возможность интерактивных действий вроде вывода сообщений пользователю.
Как создать элемент справочника: базовый код
Минимальный сценарий состоит из четырёх шагов: получить менеджер справочника, вызвать метод СоздатьЭлемент(), заполнить реквизиты и записать объект. Метод СоздатьЭлемент() создаёт объект в памяти — в базе данных он появится только после вызова Записать().
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Кабель ВВГнг 3х2.5";
НовыйЭлемент.Артикул = "KB-325";
НовыйЭлемент.ЕдиницаИзмерения = Справочники.ЕдиницыИзмерения.НайтиПоКоду("796");
НовыйЭлемент.Записать();
Сообщить("Создан элемент: " + НовыйЭлемент.Ссылка);
Обратите внимание на типы реквизитов. Строковые и числовые реквизиты присваиваются напрямую, а реквизиты ссылочного типа должны получать именно ссылку на объект другого справочника или документа, а не строку с его названием. Если присвоить строку туда, где ожидается ссылка, платформа либо выдаст ошибку преобразования типа, либо запишет пустое значение — поведение зависит от контекста, и обе ситуации нежелательны.
Если у справочника есть табличные части, они заполняются после создания объекта и до записи: каждая строка добавляется методом Добавить() к табличной части объекта. Незаполненные обязательные реквизиты (у которых включена проверка заполнения) приведут к ошибке при записи, поэтому полезно заранее посмотреть в конфигураторе, какие поля обязательны.
Как создать группу справочника
Если справочник иерархический (в конфигураторе установлен вид иерархии «Список групп и элементов» или «Группы и элементы»), для создания папки используется отдельный метод СоздатьГруппу(). Группа отличается от элемента свойством ЭтоГруппа, которое устанавливается автоматически и не может быть изменено вручную.
НоваяГруппа = Справочники.Номенклатура.СоздатьГруппу();
НоваяГруппа.Наименование = "Кабельная продукция";
НоваяГруппа.Записать();
// Создание элемента внутри группы
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = "Провод ПВС 2х0.75";
НовыйЭлемент.Родитель = НоваяГруппа.Ссылка;
НовыйЭлемент.Записать();
Ключевой момент — реквизит Родитель. Чтобы элемент попал в нужную папку, ему присваивается ссылка на группу до записи. Если группа ещё не записана, ссылки у неё нет, поэтому группу всегда записывают первой. Вложенность не ограничивается жёстко: можно строить многоуровневые иерархии, каждый раз указывая родителем ранее созданную группу.
Как избежать дублей при создании
Самая частая проблема массового программного создания — дубли. Обработка загрузки, запущенная дважды, создаст два одинаковых элемента, если не предусмотреть поиск существующих. Для этого у менеджера справочника есть методы НайтиПоНаименованию, НайтиПоКоду и НайтиПоРеквизиту.
ИскомоеНаименование = "Кабель ВВГнг 3х2.5";
НайденнаяСсылка = Справочники.Номенклатура.НайтиПоНаименованию(ИскомоеНаименование, Истина);
Если НайденнаяСсылка.Пустая() Тогда
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = ИскомоеНаименование;
НовыйЭлемент.Записать();
Иначе
Сообщить("Элемент уже существует: " + НайденнаяСсылка);
КонецЕсли;
Поиск по наименованию ненадёжен, если названия могут отличаться регистром, лишними пробелами или сокращениями. Более устойчивый вариант — искать по уникальному реквизиту: артикулу, ИНН, внешнему идентификатору. Для этого реквизит должен быть проиндексирован в конфигураторе, иначе поиск по большому справочнику будет медленным.
Если справочник подчинён владельцу (например, «Договоры контрагентов» подчинены «Контрагентам»), поиск и создание выполняются с обязательным заполнением реквизита Владелец. Без него запись завершится ошибкой проверки заполнения.
Массовое создание элементов и транзакции
При загрузке сотен или тысяч элементов важны две вещи: скорость и целостность. По скорости основное правило — минимизировать лишние обращения к базе: искать ссылки на связанные объекты один раз и кэшировать их в соответствии, а не выполнять НайтиПоКоду для каждой строки файла.
По целостности есть два подхода. Первый — обернуть всю загрузку в одну транзакцию: тогда при любой ошибке база откатится к исходному состоянию, и не останется наполовину загруженных данных. Второй — записывать каждый элемент в собственной мини-транзакции и протоколировать ошибки, продолжая загрузку. Первый вариант безопаснее, второй удобнее, когда часть строк исходного файла заведомо содержит ошибки.
НачатьТранзакцию();
Попытка
Для Каждого СтрокаДанных Из ДанныеЗагрузки Цикл
НовыйЭлемент = Справочники.Номенклатура.СоздатьЭлемент();
НовыйЭлемент.Наименование = СтрокаДанных.Наименование;
НовыйЭлемент.Артикул = СтрокаДанных.Артикул;
НовыйЭлемент.Записать();
КонецЦикла;
ЗафиксироватьТранзакцию();
Исключение
ОтменитьТранзакцию();
ВызватьИсключение "Загрузка прервана: " + ОписаниеОшибки();
КонецПопытки;
Дополнительно полезно отключать на время загрузки обмен данными и подписки на события, если они не нужны: установите у объекта ОбменДанными.Загрузка = Истина перед записью. Это ускоряет запись и отключает проверки заполнения, но используйте приём осознанно — вместе с проверками отключается и защита от некорректных данных.
Как создать новый вид справочника в конфигураторе
Если задача — добавить в конфигурацию собственный справочник, это делается в конфигураторе, а не кодом. Откройте конфигурацию для редактирования, в дереве конфигурации нажмите правой кнопкой на ветку «Справочники» и выберите «Добавить». Далее задайте имя, синоним, длину кода и наименования, вид иерархии, подчинённость владельцу и состав реквизитов.
После описания структуры обновите конфигурацию базы данных (клавиша F7 или меню «Конфигурация — Обновить конфигурацию базы данных»). Только после этого новый справочник станет доступен и пользователям, и программному коду. Учтите, что изменение структуры конфигурации требует монопольного доступа или выполняется в режиме фонового обновления в клиент-серверном варианте.
Программно изменить структуру метаданных штатными средствами встроенного языка нельзя — это осознанное ограничение платформы. Расширения конфигурации позволяют добавлять собственные справочники без изменения основной конфигурации, что удобно для типовых решений на поддержке.
Способы создания элементов
Подходит для загрузок, интеграций и обработчиков. Требует аккуратности с типами, дублями и транзакциями
Подходит для разового переноса данных из Excel без программирования, но с ограниченным контролем дублей
Подходит для регулярных интеграций между базами; требует настройки, но даёт контроль соответствия объектов
Как проверить результат и исправить ошибки
После выполнения кода убедитесь, что элементы реально записались: откройте список справочника в режиме предприятия и проверьте наличие новых позиций, корректность родителя и заполненность ключевых реквизитов. Программно факт записи проверяется через НовыйЭлемент.Ссылка.Пустая() после Записать() — у записанного объекта ссылка не пустая.
Если запись завершилась исключением, читайте текст ошибки: чаще всего это незаполненный обязательный реквизит, нарушение уникальности кода или номера, либо ошибка в подписке на событие «ПриЗаписи». Подписки на события — частый источник неочевидных сбоев: код создания корректен, но обработчик в конфигурации выполняет дополнительные проверки и отказывает в записи.
Для отладки удобно записывать первый элемент в интерактивном режиме с выводом всех значений реквизитов через Сообщить(), а уже потом запускать полный цикл. Это позволяет поймать проблемы типов и обязательных полей на одном элементе, а не на середине большой загрузки.
Как проверить результат
Ссылка не пустая, элемент открывается в списке
Исключение при записи или пустая ссылка
Элемент отображается внутри нужной группы
Элемент в корне списка при заданном родителе
Поля содержат реальные ссылки, открываемые по клику
Поля пустые или содержат битые ссылки
Повторный запуск не создаёт новых копий
Количество элементов растёт при каждом запуске
Частые вопросы
Чем СоздатьЭлемент() отличается от интерактивного добавления?
Результат тот же — новый объект в базе. Разница в том, что программное создание не открывает форму, не вызывает обработчики, связанные с интерактивным вводом, и выполняется быстрее. Все серверные обработчики записи (ПриЗаписи, ОбработкаПроверкиЗаполнения) при этом срабатывают как обычно.
Можно ли создать элемент справочника на клиенте?
В тонком клиенте методы создания и записи доступны только в серверном контексте. Из клиентского кода вызывают серверную процедуру общего модуля с директивой &НаСервере, которая выполняет создание и возвращает результат. В толстом клиенте обычного приложения такого ограничения нет.
Как задать код нового элемента вручную?
Присвойте значение свойству Код до вызова Записать(), но сначала отключите автонумерацию в свойствах справочника в конфигураторе, иначе платформа перезапишет код при записи. При ручной нумерации ответственность за уникальность кодов ложится на ваш код.
Что делает ОбменДанными.Загрузка = Истина и когда его применять?
Этот приём отключает проверку заполнения реквизитов и большинство подписок на события при записи, что ускоряет массовую загрузку. Применять его стоит только для проверенных данных при начальном заполнении или миграции: некорректные значения пройдут в базу без контроля.
Как создать элемент подчинённого справочника?
Последовательность та же, что для обычного, но обязательно заполните реквизит Владелец ссылкой на объект-владелец до записи. Без владельца запись завершится ошибкой. Например, для справочника договоров владельцем будет ссылка на конкретного контрагента.
Как удалить ошибочно созданные элементы?
Получите объект через Ссылка.ПолучитьОбъект() и вызовите Удалить() — это удаление без контроля ссылочной целостности. Безопаснее установить пометку удаления через УстановитьПометкуУдаления(Истина), а затем выполнить штатное удаление помеченных объектов, которое проверит наличие ссылок на эти элементы.
Что важно запомнить
Элемент создаётся через СоздатьЭлемент(), заполняется и записывается методом Записать(); для папки используется СоздатьГруппу() с записью до назначения её родителем. Перед созданием проверяйте дубли, при массовой загрузке используйте транзакции и обязательно тестируйте код на копии базы.