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

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

Как программно создать группу номенклатуры в 1С

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

Группа номенклатуры — это элемент-«папка» справочника «Номенклатура», внутри которого размещаются товары и услуги. Программное создание групп требуется при загрузке данных из Excel и внешних систем, при обмене между базами, при первоначальном заполнении справочника или массовой реорганизации каталога. Во всех этих случаях ручное заведение папок отнимает время и провоцирует ошибки в иерархии.

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

Ниже разобраны готовые фрагменты кода для типовых конфигураций (УТ, ERP, Бухгалтерия), способы поиска и назначения родительской группы, проверка на дубли, а также типичные ошибки, из-за которых группы не создаются или «теряются» в иерархии.

Базовый код создания группы номенклатуры

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

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

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

НоваяГруппа.Записать();

Сообщить("Создана группа: " + НоваяГруппа.Ссылка);

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

Обратите внимание: у группы недоступна часть реквизитов элемента. Попытка заполнить, например, ВидНоменклатуры или ЕдиницаИзмерения у объекта-группы либо вызовет ошибку, либо будет проигнорирована — зависит от конфигурации. Заполняйте только общие реквизиты: Наименование, Родитель, Описание и пользовательские реквизиты, для которых в конфигураторе разрешено использование у групп.

Создание группы внутри родительской папки

На практике группы почти всегда вложены друг в друга: «Товары → Электроника → Ноутбуки». Чтобы создать подгруппу, нужно сначала получить ссылку на родительскую группу — поиском по наименованию или по известному коду — и присвоить её свойству Родитель.

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

Если РодительскаяГруппа.Пустая() Тогда

ВызватьИсключение "Родительская группа не найдена";

КонецЕсли;

Если Не РодительскаяГруппа.ЭтоГруппа Тогда

ВызватьИсключение "Найден элемент, а не группа";

КонецЕсли;

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

НоваяГруппа.Наименование = "Ноутбуки";

НоваяГруппа.Родитель = РодительскаяГруппа;

НоваяГруппа.Записать();

Второй параметр НайтиПоНаименованию со значением Истина означает поиск по точному совпадению. Без него платформа ищет по началу наименования, что при похожих названиях («Электроника» и «Электроника промышленная») может вернуть не ту папку. Для надёжности всегда используйте точный поиск либо ищите по коду, если коды ведутся осмысленно.

Если родительская группа ещё не создана, логично добавить функцию «получить или создать»: сначала искать, при отсутствии — создавать и возвращать ссылку. Такой подход делает загрузку иерархии устойчивой к порядку следования данных.

Порядок действий
  1. 1
    Найдите родительскую группу через НайтиПоНаименованию с точным совпадением
  2. 2
    Проверьте, что найденный объект не пустой и ЭтоГруппа = Истина
  3. 3
    Создайте объект методом СоздатьГруппу() и заполните Наименование
  4. 4
    Присвойте свойству Родитель ссылку на родительскую группу
  5. 5
    Вызовите Записать() и проверьте, что Ссылка заполнена
  6. 6
    Откройте справочник в интерфейсе и убедитесь, что группа появилась в нужной ветке

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

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

Простой вариант — поиск по наименованию с учётом родителя. Метод НайтиПоНаименованию принимает третьим параметром ссылку на родителя, что позволяет различать одинаковые папки в разных ветках:

Функция ПолучитьИлиСоздатьГруппу(Наименование, Родитель = Неопределено)

Найденная = Справочники.Номенклатура.НайтиПоНаименованию(

Наименование, Истина, Родитель);

Если Не Найденная.Пустая() И Найденная.ЭтоГруппа Тогда

Возврат Найденная;

КонецЕсли;

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

НоваяГруппа.Наименование = Наименование;

Если Родитель <> Неопределено Тогда

НоваяГруппа.Родитель = Родитель;

КонецЕсли;

НоваяГруппа.Записать();

Возврат НоваяГруппа.Ссылка;

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

Для обменов с внешними системами надёжнее искать не по наименованию, а по уникальному внешнему идентификатору — например, хранить GUID источника в дополнительном реквизите или в регистре соответствия. Наименования в источнике могут меняться, и поиск по ним начнёт плодить дубли.

Типичные ошибки
01
Поиск родителя без точного совпадения — группа создаётся не в той ветке из-за похожих наименований
02
Отсутствие проверки ЭтоГруппа — попытка назначить родителем обычный элемент приводит к ошибке записи
03
Создание групп без проверки дублей при повторном запуске обработки — справочник зарастает одинаковыми папками
04
Заполнение реквизитов элемента (вид номенклатуры, единица измерения) у группы — ошибка или молча потерянные данные
05
Запись большого пакета групп без транзакции — при сбое остаётся наполовину построенная иерархия

Массовое создание групп из таблицы данных

Типовая задача — построить иерархию из таблицы значений, загруженной из Excel или CSV, где для каждой строки указаны наименование группы и наименование её родителя. Ключевой момент: родительская группа должна существовать к моменту создания дочерней, поэтому данные либо сортируют по уровню вложенности, либо обрабатывают рекурсивно.

Удобный приём — кэшировать уже созданные группы в соответствии, чтобы не искать одну и ту же папку запросом много раз. Это заметно ускоряет обработку на объёмах в тысячи позиций:

КэшГрупп = Новый Соответствие;

Для Каждого Строка Из ТаблицаГрупп Цикл

Ключ = Строка.Родитель + "/" + Строка.Наименование;

Если КэшГрупп[Ключ] <> Неопределено Тогда

Продолжить;

КонецЕсли;

СсылкаГруппы = ПолучитьИлиСоздатьГруппу(

Строка.Наименование, КэшГрупп[Строка.Родитель]);

КэшГрупп.Вставить(Ключ, СсылкаГруппы);

КонецЦикла;

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

Отличия в управляемых формах и на сервере

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

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

В конфигурациях с подсистемой БСП (Библиотека стандартных подсистем) наименование может формироваться обработчиками заполнения, а запись — проходить проверки заполнения. Если группа не записывается без видимой причины, посмотрите текст исключения: часто там сообщение о незаполненном обязательном реквизите, добавленном доработкой.

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

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

Группа видна в списке справочника
Норма

Папка отображается в нужной ветке иерархии

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

Группа есть в поиске, но не в ожидаемой папке — ошибка в Родителе

Свойство ЭтоГруппа у созданной ссылки
Норма

ЭтоГруппа = Истина

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

Ложь — создан элемент, а не группа, товары в него не сгруппируются

Повторный запуск обработки
Норма

Дублей не появляется, используются существующие группы

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

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

Запись под рабочим пользователем
Норма

Записывается без исключений

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

Ошибка нарушения прав доступа — нужно настроить роли

Альтернативные способы получения иерархии

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

Сравнение вариантов

Ручное создание

Подходит для нескольких папок; не масштабируется и требует ручной выверки иерархии

Типовая загрузка из табличного документа

Подходит для разовой загрузки из Excel без доработок; гибкость ограничена настройками обработки

Программное создание

Подходит для обменов, регулярных загрузок и сложной логики; требует разработки и тестирования на копии

Выбор зависит от частоты задачи. Разовая структура на десяток папок не оправдывает написания обработки. Регулярный обмен с сайтом или поставщиком, наоборот, требует устойчивого программного механизма с поиском по внешнему идентификатору и журналированием ошибок.

Итог

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

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

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

Чем группа отличается от элемента справочника «Номенклатура»?

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

Почему Записать() выдаёт ошибку при назначении родителя?

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

Можно ли создать группу вне транзакции при массовой загрузке?

Можно, и часто так делают намеренно: если обработка построена по принципу «найти или создать», повторный запуск после сбоя просто продолжит с места остановки. Транзакция нужна, когда требуется «всё или ничего» — например, при финансово значимой реорганизации справочника.

Как найти группу, если наименования в базе и в файле отличаются регистром или пробелами?

НайтиПоНаименованию с точным совпадением чувствителен к строке, поэтому перед поиском нормализуйте обе стороны: СокрЛП() для удаления лишних пробелов и при необходимости ВРег() для сравнения без учёта регистра. Надёжнее всего сопоставлять по внешнему коду или GUID, а не по наименованию.

Работает ли этот код во внешней обработке на управляемых формах?

Да, но код создания должен выполняться в серверной процедуре (директива &НаСервере), поскольку объекты справочников недоступны на тонком клиенте. Из клиентской части передавайте на сервер только строки и таблицы значений, а ссылки получайте обратно как результат вызова.

Как удалить ошибочно созданные группы?

Группу можно пометить на удаление через ПолучитьОбъект() и УстановитьПометкуУдаления(Истина), если в ней нет элементов и подгрупп. Если иерархия большая, сначала переместите содержимое в правильные папки, затем пометьте лишние группы и выполните штатное удаление помеченных объектов с контролем ссылочной целостности.