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

Дата: 10.10.2026 08:40:56
Справочники
Программирование 1С
Встроенный язык
Обмен данными
Транзакции
УТ 11
Примеры кода
Комментарий:
0
Платформа:
8.3
Конфигурация:
Любая
Формы:
Любые

Создать справочник 1С программно в прикладной задаче — значит добавить в него элемент или группу из кода: товары из прайса поставщика, клиентов с сайта, контрагентов по ИНН из заявки. Схема одна: Справочники.Имя.СоздатьЭлемент() или СоздатьГруппу(), заполнение реквизитов, Записать(). Ниже — готовые функции для платформы 8.3: от одного элемента с проверкой заполнения до массовой загрузки номенклатуры в транзакции с ОбменДанными.Загрузка.

Объекты справочников есть на сервере, в толстом клиенте и во внешнем соединении, но не в тонком и веб-клиенте. Код создания кладут в серверный общий модуль, модуль менеджера или объекта обработки, а форма вызывает его через сервер. До кода посмотрите в конфигураторе свойства справочника: «Вид иерархии», «Владельцы», «Серии кодов», «Контроль уникальности», «Автонумерация», у реквизитов — «Проверка заполнения».

Как создать справочник 1С программно: СоздатьЭлемент и Записать

Универсальная функция ниже позволяет создать элемент справочника программно по имени справочника. Первая структура — то, от чего зависят умолчания, вторая — остальные значения.

// Создаёт и записывает элемент справочника, возвращает ссылку на него.
// ИмяСправочника - Строка - имя из ветки «Справочники» конфигуратора, например "Номенклатура".
// Основные - Структура, Неопределено - реквизиты, от которых зависят умолчания: Владелец,
//   ВидНоменклатуры, Партнер. Ставятся до Заполнить() и передаются в неё как данные заполнения.
// Реквизиты - Структура - остальные значения, в том числе Наименование и Родитель.
Функция СоздатьЭлементСправочника(ИмяСправочника, Основные, Реквизиты) Экспорт

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

	Если Основные <> Неопределено Тогда
		ЗаполнитьЗначенияСвойств(НовыйЭлемент, Основные);
	КонецЕсли;
	// СоздатьЭлемент() не вызывает ОбработкаЗаполнения и не ставит «Значение заполнения»
	НовыйЭлемент.Заполнить(Основные);
	// Свои значения - после умолчаний, иначе заполнение их перезапишет
	ЗаполнитьЗначенияСвойств(НовыйЭлемент, Реквизиты);

	ПроверитьЗаполнениеЭлемента(НовыйЭлемент);

	// Код при включённой автонумерации платформа назначит сама
	НовыйЭлемент.Записать();

	Возврат НовыйЭлемент.Ссылка;

КонецФункции

// Вызывает исключение с причинами, если не заполнены обязательные реквизиты.
// Записать() из кода ОбработкаПроверкиЗаполнения не вызывает: её запускают
// только форма объекта и метод ПроверитьЗаполнение().
Процедура ПроверитьЗаполнениеЭлемента(Элемент) Экспорт

	Было = ПолучитьСообщенияПользователю().Количество();
	Если Элемент.ПроверитьЗаполнение() Тогда
		Возврат;
	КонецЕсли;

	// Причины лежат в очереди сообщений: в фоновом задании их иначе никто не увидит
	Сообщения = ПолучитьСообщенияПользователю();
	Причины = Новый Массив;
	Для Номер = Было По Сообщения.ВГраница() Цикл
		Причины.Добавить(Сообщения[Номер].Текст);
	КонецЦикла;
	Если Причины.Количество() = 0 Тогда
		Причины.Добавить(НСтр("ru = 'не пройдена проверка заполнения'"));
	КонецЕсли;

	ВызватьИсключение СтрШаблон(НСтр("ru = 'Элемент «%1» справочника %2 не записан: %3'"),
		Элемент.Наименование, Элемент.Метаданные().Имя, СтрСоединить(Причины, "; "));

КонецПроцедуры

Вызов для номенклатуры и подчинённого справочника:

// УТ 11.4: товар. Вид номенклатуры - в «Основные»: по нему ОбработкаЗаполнения
// заполнит тип номенклатуры, ставку НДС, единицу хранения и другие реквизиты вида.
Основные = Новый Структура("ВидНоменклатуры", ВидНоменклатуры);
Реквизиты = Новый Структура("Наименование, НаименованиеПолное, Артикул, Родитель",
	"Чайник 1,7 л", "Чайник электрический 1,7 л", "KT-1702", ГруппаЧайники);
Товар = СоздатьЭлементСправочника("Номенклатура", Основные, Реквизиты);

// Подчинённый справочник: владелец - тоже в «Основные», без него запись не пройдёт
Контакт = СоздатьЭлементСправочника("КонтактныеЛицаПартнеров",
	Новый Структура("Владелец", Партнер), Новый Структура("Наименование", ФИО));

Разбор ключевых строк

  • СоздатьЭлемент() даёт объект в памяти: до Записать() в базе его нет, ссылка и код пустые.
  • Заполнить() запускает ОбработкаЗаполнения и стандартное дозаполнение пустых реквизитов «Значением заполнения» из их свойств. Без него номенклатура УТ 11.4 не получит, например, качество «Новый» и реквизиты вида.
  • Порядок «основные → Заполнить() → остальные» важен: у нового товара УТ 11.4 заполнение по виду заменяет единицу и ставку НДС значениями вида, если они там заданы.
  • ЗаполнитьЗначенияСвойств молча пропускает ключи, которых у объекта нет: опечатка в имени реквизита ошибки не даст.
  • Записать() из кода не вызывает ОбработкаПроверкиЗаполнения — это делают только форма и ПроверитьЗаполнение(). Зато он проверяет уникальность кода, назначает код при автонумерации и вызывает ПередЗаписью и ПриЗаписи; любой отказ — исключение.

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

// Изменить существующий элемент: объект читается из базы, правится и записывается
ТоварОбъект = Товар.ПолучитьОбъект();
ТоварОбъект.Артикул = "KT-1702-W";
ТоварОбъект.Записать();

Обязательные реквизиты в УТ 11.4

Что задать в коде, а что заполнят обработчики типовой (сверено по УТ 11.4.14):

СправочникЗадать в кодеЗаполнит типовая
НоменклатураВидНоменклатуры — до Заполнить(); Наименование; ЕдиницаИзмерения, если её нет в виде (услугам и работам не обязательна)Заполнить(): тип, ставка НДС, единица, группа доступа и прочее из вида; ПередЗаписью: Код, КодДляПоиска
ПартнерыНаименование, НаименованиеПолное, ЮрФизЛицо, хотя бы один из флажков Клиент, Поставщик, Конкурент, ПрочиеОтношения; ГруппаДоступа — если включены группы доступаЗаполнить(): ОсновнойМенеджер, ДатаРегистрации; код — при записи
КонтрагентыПартнер — через Заполнить(); ЮрФизЛицо; ИНН и КППЗаполнить(): наименования по партнёру; ПередЗаписью: ЮридическоеФизическоеЛицо, ГоловнойКонтрагент

В ПередЗаписью номенклатуры УТ 11.4 есть и исключения: пустое и неуникальное рабочее наименование (второе — при включённой константе КонтролироватьУникальностьРабочегоНаименованияНоменклатурыИХарактеристик). В КА 2.5 у номенклатуры нет ОбработкаЗаполнения: после Заполнить() вызовите Справочники.Номенклатура.ЗаполнитьРеквизитыПоВидуНоменклатуры(Элемент) — эта экспортная процедура есть в обеих конфигурациях.

Группы и родитель: СоздатьГруппу

ЭтоГруппа только для чтения, поэтому группа создаётся одним способом — СоздатьГруппу(). Место в дереве задаёт Родитель, пустая ссылка — верхний уровень. При виде иерархии «Иерархия групп и элементов» родителем бывает только группа, при «Иерархии элементов» групп нет и родитель — другой элемент (так у партнёров УТ 11.4). Функция находит группу по пути из файла и создаёт недостающие уровни.

// Группа справочника по пути "Бытовая техника/Чайники": недостающие уровни создаются.
// Для справочников с видом иерархии «Иерархия групп и элементов», например Номенклатура.
Функция ГруппаПоПути(ИмяСправочника, Путь) Экспорт

	Менеджер = Справочники[ИмяСправочника];
	Родитель = Менеджер.ПустаяСсылка();

	Для Каждого ЧастьПути Из СтрРазделить(Путь, "/", Ложь) Цикл

		ИмяГруппы = СокрЛП(ЧастьПути);
		Группа = НайтиГруппу(ИмяСправочника, ИмяГруппы, Родитель);

		Если Группа = Неопределено Тогда
			// ЭтоГруппа только для чтения: группу даёт только СоздатьГруппу()
			НоваяГруппа = Менеджер.СоздатьГруппу();
			НоваяГруппа.Наименование = ИмяГруппы;
			НоваяГруппа.Родитель = Родитель;
			НоваяГруппа.Записать();
			Группа = НоваяГруппа.Ссылка;
		КонецЕсли;

		Родитель = Группа;

	КонецЦикла;

	Возврат Родитель;

КонецФункции

// Непомеченная группа с точным наименованием внутри родителя или Неопределено.
Функция НайтиГруппу(ИмяСправочника, Наименование, Родитель)

	Запрос = Новый Запрос(
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Группы.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник." + ИмяСправочника + " КАК Группы
	|ГДЕ
	|	Группы.ЭтоГруппа
	|	И Группы.Родитель = &Родитель
	|	И Группы.Наименование = &Наименование
	|	И НЕ Группы.ПометкаУдаления");
	Запрос.УстановитьПараметр("Родитель", Родитель);
	Запрос.УстановитьПараметр("Наименование", Наименование);

	Выборка = Запрос.Выполнить().Выбрать();
	Возврат ?(Выборка.Следующий(), Выборка.Ссылка, Неопределено);

КонецФункции

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

Владелец: элемент подчинённого справочника

Элемент подчинённого справочника принадлежит владельцу, и без Владелец запись завершится ошибкой. В УТ 11.4 так устроены КонтактныеЛицаПартнеров (владелец — партнёр) и базовые единицы измерения — элементы УпаковкиЕдиницыИзмерения с владельцем НаборыУпаковок.БазовыеЕдиницыИзмерения. Новый элемент справочника программно ищут и создают в пределах владельца:

// УТ 11.4: контактное лицо партнёра. Справочник подчинён справочнику Партнеры,
// поэтому и поиск дубля, и новый элемент - в пределах владельца.
Функция КонтактноеЛицоПартнера(Партнер, ФИО, Должность = "") Экспорт

	// Четвёртый параметр - владелец: у разных партнёров бывают контакты с одинаковыми ФИО
	Найденный = Справочники.КонтактныеЛицаПартнеров.НайтиПоНаименованию(ФИО, Истина, , Партнер);
	Если ЗначениеЗаполнено(Найденный) Тогда
		Возврат Найденный;
	КонецЕсли;

	Контакт = Справочники.КонтактныеЛицаПартнеров.СоздатьЭлемент();
	// ОбработкаЗаполнения типовой: ссылка на партнёра становится владельцем,
	// автор - текущий пользователь, дата регистрации связи - текущая дата
	Контакт.Заполнить(Партнер);
	Контакт.Наименование = ФИО;
	Контакт.ДолжностьПоВизитке = Должность;
	ПроверитьЗаполнениеЭлемента(Контакт);
	Контакт.Записать();

	Возврат Контакт.Ссылка;

КонецФункции

НайтиПоКоду, НайтиПоНаименованию и НайтиПоРеквизиту принимают владельца последним параметром, без него ищут по всему справочнику. Подробнее — в статье как получить ссылку.

Код и автонумерация

Код задавать не нужно: при включённой «Автонумерации» платформа назначит его при записи с учётом «Серий кодов» — во всём справочнике, в пределах подчинения или в пределах подчинения владельцу. Нужен код до записи — вызовите УстановитьНовыйКод(). Для строкового кода можно передать префикс: УстановитьНовыйКод("ИМ-") возьмёт следующий за максимальным кодом с этим префиксом. При «Контроле уникальности» повтор кода в серии не даст записать элемент.

В типовых на БСП к коду добавляется префикс базы: в УТ 11.4 номенклатуре и партнёрам его ставит подписка УстановитьПрефиксИнформационнойБазыКодуСправочника на ПриУстановкеНовогоКода. Поэтому чужие коды в Код не пишите — для них есть Артикул или свой реквизит, а GUID с сайта делают ссылкой нового элемента через УстановитьСсылкуНового().

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

Формы типовых ловят дубли, код — нет: в УТ 11.4 проверка «ИНН и КПП уже указаны для другого контрагента» сидит в ОбработкаПроверкиЗаполнения, и Записать() её не запускает. Прежде чем добавить в справочник программно, ищите сами: контрагента — по ИНН и КПП, товар — по артикулу, контакт — по наименованию у владельца. Наименование — худший ключ: «ООО Ромашка» и «Ромашка ООО» для базы разные строки.

// УТ 11.4: контрагент по ИНН и КПП. Есть в базе - возвращает его, нет - создаёт
// партнёра и контрагента. ГруппаДоступа нужна, если включены группы доступа партнёров.
Функция НайтиИлиСоздатьКонтрагента(ИНН, КПП, Наименование, ГруппаДоступа = Неопределено) Экспорт

	Если ПустаяСтрока(ИНН) Тогда
		// По пустому ИНН нашёлся бы любой контрагент без ИНН
		ВызватьИсключение НСтр("ru = 'Не указан ИНН контрагента'");
	КонецЕсли;

	НачатьТранзакцию();
	Попытка
		// Второй сеанс с тем же ИНН дождётся конца транзакции и найдёт уже созданного
		Блокировка = Новый БлокировкаДанных;
		Блокировка.Добавить("Справочник.Контрагенты");
		Блокировка.Заблокировать();

		Контрагент = КонтрагентПоИНН(СокрЛП(ИНН), СокрЛП(КПП));
		Если Контрагент = Неопределено Тогда
			Контрагент = НовыйКонтрагент(СокрЛП(ИНН), СокрЛП(КПП), Наименование, ГруппаДоступа);
		КонецЕсли;

		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		ВызватьИсключение;
	КонецПопытки;

	Возврат Контрагент;

КонецФункции

// Непомеченный контрагент с этим ИНН и КПП (пустой КПП - поиск только по ИНН),
// головной раньше обособленных подразделений. Неопределено - не нашли.
Функция КонтрагентПоИНН(ИНН, КПП)

	Запрос = Новый Запрос(
	"ВЫБРАТЬ ПЕРВЫЕ 1
	|	Контрагенты.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Контрагенты КАК Контрагенты
	|ГДЕ
	|	Контрагенты.ИНН = &ИНН
	|	И (Контрагенты.КПП = &КПП ИЛИ &КПП = """")
	|	И НЕ Контрагенты.ПометкаУдаления
	|
	|УПОРЯДОЧИТЬ ПО
	|	Контрагенты.ОбособленноеПодразделение");
	Запрос.УстановитьПараметр("ИНН", ИНН);
	Запрос.УстановитьПараметр("КПП", КПП);

	Выборка = Запрос.Выполнить().Выбрать();
	Возврат ?(Выборка.Следующий(), Выборка.Ссылка, Неопределено);

КонецФункции

// Партнёр и контрагент: 10 цифр ИНН - юрлицо, 12 - индивидуальный предприниматель.
Функция НовыйКонтрагент(ИНН, КПП, Наименование, ГруппаДоступа)

	Партнер = Справочники.Партнеры.СоздатьЭлемент();
	// ОбработкаЗаполнения: наименование из структуры, основной менеджер, дата регистрации
	Партнер.Заполнить(Новый Структура("Наименование", Наименование));
	Партнер.НаименованиеПолное = Наименование;
	Партнер.ЮрФизЛицо = Перечисления.КомпанияЧастноеЛицо.Компания;
	Партнер.Клиент = Истина; // хотя бы один вид отношений обязателен
	Если ГруппаДоступа <> Неопределено Тогда
		Партнер.ГруппаДоступа = ГруппаДоступа;
	КонецЕсли;
	ПроверитьЗаполнениеЭлемента(Партнер);
	Партнер.Записать();

	Контрагент = Справочники.Контрагенты.СоздатьЭлемент();
	// По ключу Партнер обработка заполнения возьмёт наименования у партнёра
	Контрагент.Заполнить(Новый Структура("Партнер", Партнер.Ссылка));
	Контрагент.ЮрФизЛицо = ?(СтрДлина(ИНН) = 12,
		Перечисления.ЮрФизЛицо.ИндивидуальныйПредприниматель, Перечисления.ЮрФизЛицо.ЮрЛицо);
	Контрагент.ИНН = ИНН;
	Контрагент.КПП = КПП;
	ПроверитьЗаполнениеЭлемента(Контрагент); // здесь же типовая проверка дубля ИНН и КПП
	// ЮридическоеФизическоеЛицо и ГоловнойКонтрагент заполнит ПередЗаписью типовой
	Контрагент.Записать();

	Возврат Контрагент.Ссылка;

КонецФункции
  • Поиск и создание — в одной транзакции под исключительной блокировкой справочника: второй сеанс с тем же ИНН дождётся первого и найдёт созданного. Заблокировать по ИНН нельзя: у справочника блокируются Ссылка и поля из свойства «Поля блокировки данных», а у контрагентов УТ 11.4 оно пустое. Внутри долгой транзакции функцию не вызывайте (см. конфликт блокировок).
  • ПроверитьЗаполнениеЭлемента — из первого листинга; заодно сработает типовая проверка дубля ИНН и КПП.
  • Запрос поиска удобно отладить в консоли запросов.

Скопировать(): новый элемент по образцу

Если новый товар отличается от существующего парой реквизитов, его проще скопировать:

// Новый элемент по образцу: копия получает реквизиты и табличные части образца.
// Изменения - Структура - чем копия отличается: Наименование, Артикул и т. п.
Функция СоздатьПоОбразцу(Образец, Изменения) Экспорт

	// При копировании вместо ОбработкаЗаполнения вызывается ПриКопировании:
	// там типовые очищают то, что копия наследовать не должна
	Копия = Образец.Скопировать();
	ЗаполнитьЗначенияСвойств(Копия, Изменения);

	// Код - новый, если его не передали явно: не полагаемся на то, что досталось от образца
	МетаданныеСправочника = Копия.Метаданные();
	Если МетаданныеСправочника.ДлинаКода > 0 И МетаданныеСправочника.Автонумерация
		И Не Изменения.Свойство("Код") Тогда
		Копия.УстановитьНовыйКод();
	КонецЕсли;

	ПроверитьЗаполнениеЭлемента(Копия);
	Копия.Записать();

	Возврат Копия.Ссылка;

КонецФункции
// Товар по образцу: другие наименования и артикул, остальное - как у образца
Изменения = Новый Структура("Наименование, НаименованиеПолное, Артикул",
	"Чайник 1,5 л", "Чайник электрический 1,5 л", "KT-1502");
НовыйТовар = СоздатьПоОбразцу(Образец, Изменения);
  • Скопировать() есть у ссылки и у объекта и возвращает незаписанную копию с реквизитами и табличными частями, включая дополнительные реквизиты БСП.
  • Вместо ОбработкаЗаполнения вызывается ПриКопировании: в УТ 11.4 партнёр там получает основным менеджером текущего пользователя и новую дату регистрации, а у контрагента очищается ГоловнойКонтрагент, если образец был головным сам себе.
  • Не копируется то, что лежит вне объекта: штрихкоды, цены, дополнительные сведения (регистры ШтрихкодыНоменклатуры, ЦеныНоменклатуры, ДополнительныеСведения), присоединённые файлы, упаковки и характеристики.
  • Копия контрагента унаследует ИНН и КПП — от дубля спасёт только проверка заполнения.

Массовое создание номенклатуры: транзакция и ОбменДанными.Загрузка

Массовая запись справочника программно упирается в транзакции и режим загрузки. Флаг ОбменДанными.Загрузка = Истина означает «данные уже проверены, запиши как есть». Платформа делает минимум проверок, а по стандарту 1С обработчики ПередЗаписью, ПриЗаписи, ПередУдалением и подписки на них сразу выходят: бизнес-логика пропускается, за целостность данных отвечает вызывающий код. Режим уместен для данных из базы той же конфигурации или правки служебного реквизита у тысяч элементов. Для новых товаров из прайса — только если сделать за типовую пропущенное. В УТ 11.4 при загрузке:

  • номенклатура не получает код и КодДляПоиска из типового ПередЗаписью, шаблоны наименований не применяются, пустое и неуникальное рабочее наименование не проверяется;
  • контрагент остаётся без ЮридическоеФизическоеЛицо и ГоловнойКонтрагент;
  • для партнёра не пишется регистр ИерархияПартнеров;
  • регистрация изменений для обменов БСП работает, отключает её дополнительное свойство ОтключитьМеханизмРегистрацииОбъектов.

Функция создаёт номенклатуру из таблицы значений (её удобно получить загрузкой из Excel) порциями в транзакциях, режим загрузки — параметр.

// УТ 11.4: массовое создание номенклатуры из таблицы значений.
// Товары - ТаблицаЗначений: Наименование, Артикул, Группа (путь вида "Бытовая техника/Чайники").
// Настройки - Структура:
//   ВидНоменклатуры - по нему типовая заполнит тип, ставку НДС, единицу хранения;
//   ЕдиницаИзмерения - если в виде номенклатуры единица не задана;
//   РежимЗагрузки - Истина: запись с ОбменДанными.Загрузка, без логики ПередЗаписью и ПриЗаписи;
//   РазмерПорции - сколько элементов писать в одной транзакции.
// Возвращает структуру: Создано, Пропущено (пустой или занятый артикул), Ошибки (массив строк).
Функция СоздатьНоменклатуру(Товары, Настройки) Экспорт

	Если ТранзакцияАктивна() Тогда
		// После отката порции её строки пишутся заново - во внешней транзакции это невозможно
		ВызватьИсключение НСтр("ru = 'СоздатьНоменклатуру нельзя вызывать внутри транзакции'");
	КонецЕсли;

	Итог = Новый Структура("Создано, Пропущено, Ошибки", 0, 0, Новый Массив);
	Занятые = СуществующиеАртикулы(Товары.ВыгрузитьКолонку("Артикул"));

	// Группы - заранее и вне транзакций порций: откат порции
	// не должен оставить в кэше ссылки на группы, которых нет в базе
	Группы = Новый Соответствие;
	Для Каждого Путь Из Товары.ВыгрузитьКолонку("Группа") Цикл
		Если ЗначениеЗаполнено(Путь) И Группы[Путь] = Неопределено Тогда
			Группы.Вставить(Путь, ГруппаПоПути("Номенклатура", Путь));
		КонецЕсли;
	КонецЦикла;

	Порция = Новый Массив;
	Для Каждого Товар Из Товары Цикл
		Ключ = ВРег(СокрЛП(Товар.Артикул));
		Если ПустаяСтрока(Ключ) Или Занятые[Ключ] <> Неопределено Тогда
			Итог.Пропущено = Итог.Пропущено + 1;
			Продолжить;
		КонецЕсли;
		Занятые.Вставить(Ключ, Истина); // повтор артикула в самом файле тоже пропустим
		Порция.Добавить(Товар);
		Если Порция.Количество() = Настройки.РазмерПорции Тогда
			ЗаписатьПорцию(Порция, Настройки, Группы, Итог);
			Порция.Очистить();
		КонецЕсли;
	КонецЦикла;
	ЗаписатьПорцию(Порция, Настройки, Группы, Итог);

	Возврат Итог;

КонецФункции

// Порция пишется в одной транзакции. Если она откатилась - построчно:
// исправные строки сохранятся, ошибочные попадут в Итог.Ошибки.
Процедура ЗаписатьПорцию(Порция, Настройки, Группы, Итог)

	Если Порция.Количество() = 0 Тогда
		Возврат;
	КонецЕсли;

	НачатьТранзакцию();
	Попытка
		Для Каждого Товар Из Порция Цикл
			ЗаписатьТовар(Товар, Настройки, Группы);
		КонецЦикла;
		ЗафиксироватьТранзакцию();
	Исключение
		ОтменитьТранзакцию();
		Для Каждого Товар Из Порция Цикл
			Попытка
				ЗаписатьТовар(Товар, Настройки, Группы);
				Итог.Создано = Итог.Создано + 1;
			Исключение
				Итог.Ошибки.Добавить(СтрШаблон("%1: %2", Товар.Артикул,
					ОбработкаОшибок.КраткоеПредставлениеОшибки(ИнформацияОбОшибке())));
			КонецПопытки;
		КонецЦикла;
		Возврат;
	КонецПопытки;

	Итог.Создано = Итог.Создано + Порция.Количество();

КонецПроцедуры

Процедура ЗаписатьТовар(Товар, Настройки, Группы)

	Элемент = Справочники.Номенклатура.СоздатьЭлемент();
	Если ЗначениеЗаполнено(Товар.Группа) Тогда
		Элемент.Родитель = Группы[Товар.Группа];
	КонецЕсли;
	Элемент.ВидНоменклатуры = Настройки.ВидНоменклатуры;
	Элемент.Заполнить(Неопределено); // реквизиты по виду и «Значение заполнения»
	Элемент.Наименование = СокрЛП(Товар.Наименование);
	Элемент.НаименованиеПолное = Элемент.Наименование;
	Элемент.Артикул = СокрЛП(Товар.Артикул);
	Если Не ЗначениеЗаполнено(Элемент.ЕдиницаИзмерения) Тогда
		Элемент.ЕдиницаИзмерения = Настройки.ЕдиницаИзмерения;
	КонецЕсли;

	// Загрузка отключает обработчики записи, а не проверку заполнения - проверяем всегда
	ПроверитьЗаполнениеЭлемента(Элемент);

	Если Настройки.РежимЗагрузки Тогда
		// ПередЗаписью номенклатуры при загрузке сразу выходит: код и код для поиска - сами
		Элемент.УстановитьНовыйКод();
		Элемент.КодДляПоиска = ПрефиксацияОбъектовКлиентСервер.НомерНаПечать(Элемент.Код, Истина);
		Элемент.ОбменДанными.Загрузка = Истина;
	КонецЕсли;

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

КонецПроцедуры

// Занятые артикулы: Соответствие "АРТИКУЛ В ВЕРХНЕМ РЕГИСТРЕ" -> ссылка.
Функция СуществующиеАртикулы(Артикулы)

	Очищенные = Новый Массив;
	Для Каждого Артикул Из Артикулы Цикл
		Очищенные.Добавить(СокрЛП(Артикул));
	КонецЦикла;

	Запрос = Новый Запрос(
	"ВЫБРАТЬ
	|	Номенклатура.Артикул КАК Артикул,
	|	Номенклатура.Ссылка КАК Ссылка
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|ГДЕ
	|	Номенклатура.Артикул В (&Артикулы)
	|	И НЕ Номенклатура.ЭтоГруппа");
	Запрос.УстановитьПараметр("Артикулы", Очищенные);

	Результат = Новый Соответствие;
	Выборка = Запрос.Выполнить().Выбрать();
	Пока Выборка.Следующий() Цикл
		Результат.Вставить(ВРег(СокрЛП(Выборка.Артикул)), Выборка.Ссылка);
	КонецЦикла;

	Возврат Результат;

КонецФункции
// Вызов. Единица «шт» в УТ 11.4 - элемент УпаковкиЕдиницыИзмерения с владельцем
// НаборыУпаковок.БазовыеЕдиницыИзмерения (наименование - как в вашей базе)
Штука = Справочники.УпаковкиЕдиницыИзмерения.НайтиПоНаименованию("шт", Истина, ,
	Справочники.НаборыУпаковок.БазовыеЕдиницыИзмерения);
Настройки = Новый Структура("ВидНоменклатуры, ЕдиницаИзмерения, РежимЗагрузки, РазмерПорции",
	ВидНоменклатуры, Штука, Ложь, 100);
Итог = СоздатьНоменклатуру(Товары, Настройки);
  • Занятые артикулы — одним запросом до цикла, а не НайтиПоРеквизиту на строку; Артикул в УТ 11.4 индексирован.
  • Упавшая порция откатывается и пишется построчно: исправные строки сохранятся, ошибки уйдут в Итог.Ошибки. Во внешней транзакции так нельзя — после ошибки её можно только откатить, отсюда проверка ТранзакцияАктивна(). Шаблон — в статье про транзакции.
  • Загрузка отключает обработчики записи, а не ПроверитьЗаполнение(), поэтому проверка работает в обоих режимах. Код и КодДляПоиска при загрузке заполняются так же, как в типовом ПередЗаписью.

Типичные ошибки

  • «Переменная не определена (Справочники)» — код создания в клиентской процедуре формы. Перенесите его в &НаСервере или серверный общий модуль.
  • Товар без качества, единицы или ставки НДС — не вызван Заполнить() или вид номенклатуры задан после него.
  • «Поле "Единица хранения" не заполнено» — ответ ПроверитьЗаполнение() в УТ 11.4: у товара нет единицы, и в виде она не задана. Без проверки товар записался бы без единицы.
  • «Поле "Рабочее наименование" не заполнено», «Значение поля "Рабочее наименование" не уникально» — исключения из ПередЗаписью номенклатуры УТ 11.4. Не обходите их через ОбменДанными.Загрузка — получите дубли.
  • Ошибка вида «Значение поля "Код" не уникально» — код задан вручную или взят из внешней системы и совпал с существующим в серии.
  • Нашёлся не тот элемент — НайтиПоНаименованию() по умолчанию сравнивает начало наименования: «Чайник» найдёт «Чайник 1,7 л». Передавайте ТочноеСоответствие = Истина.
  • «В данной транзакции уже происходили ошибки!» — исключение внутри своей транзакции поймали и продолжили запись. Такую транзакцию можно только откатить.
  • Товары без КодДляПоиска, контрагенты без головного — запись с ОбменДанными.Загрузка без дозаполнения: ошибок нет, данные неполные.

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

Можно ли программно создать сам справочник, а не элемент?

Нет. Справочник — объект метаданных: его добавляют в конфигураторе (ветка «Справочники» → «Добавить») или в расширении и обновляют конфигурацию базы. Код 1С:Предприятия создаёт только данные — элементы и группы.

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

Через сервер: команда формы вызывает процедуру &НаСервере или общий модуль с флажком «Вызов сервера», передаёт строки, числа, ссылки и получает обратно ссылку на новый элемент.

Как узнать код нового элемента до записи?

Вызовите УстановитьНовыйКод(): код появится сразу, с учётом серии кодов, а в типовых на БСП — и префикса базы. Иначе при автонумерации его назначит Записать().

Как создать элемент с GUID из внешней системы?

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

Когда проще заказать

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

По теме

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

Станьте частью сообщества!
Войдите или зарегистрируйтесь, и вы сможете участвовать в обсуждениях.


1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.