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