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