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

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Разберем детально, почему стандартный метод Заполнить() может не сработать, как правильно копировать данные и почему архитектурно небезопасно создавать ссылочные данные в процедуре ОбработкаПроведения.

Разница между методами Заполнить() и ЗаполнитьЗначенияСвойств()

Проанализируем частую ошибку: попытку заполнить новый объект справочника из структуры с помощью вызова ОбъектЗаписи.Заполнить(ЭлементыОтбора). В платформе 1С метод Заполнить() обращается к встроенному событию ОбработкаЗаполнения в модуле соответствующего объекта. Если в модуле справочника данный обработчик не переопределен разработчиком или не умеет разбирать входящую структуру параметров, реквизиты объекта останутся пустыми.

Для прямого копирования значений между объектами и структурами по совпадающим именам свойств в платформе 1С предусмотрена процедура ЗаполнитьЗначенияСвойств(). Она не требует кода в модуле объекта и сопоставляет поля автоматически.

Посмотрим на корректный пример инициализации и заполнения реквизитов объекта:


Для Каждого СтрокаТЧ Из Товары Цикл
    ЭлементыОтбора = Новый Структура;
    ЭлементыОтбора.Вставить("Код", СтрокаТЧ.Код);
    ЭлементыОтбора.Вставить("Наименование", СтрокаТЧ.Номенклатура);
    ЭлементыОтбора.Вставить("ТипНоменклатуры", СтрокаТЧ.Товар);
    ЭлементыОтбора.Вставить("ВидНоменклатуры", СтрокаТЧ.ВидНоменклатуры);
    ЭлементыОтбора.Вставить("Состояние", СтрокаТЧ.Состояние);
    ЭлементыОтбора.Вставить("База", СтрокаТЧ.База);
    ЭлементыОтбора.Вставить("Склад", Склад); // Реквизит из шапки документа
    ЭлементыОтбора.Вставить("Номер", СтрокаТЧ.Номер);

    ОбъектЗаписи = Справочники.Номенклатура.СоздатьЭлемент();
    ЗаполнитьЗначенияСвойств(ОбъектЗаписи, ЭлементыОтбора);
    
    // Обязательный вызов метода для фиксации в базе данных
    ОбъектЗаписи.Записать();
КонецЦикла;

Важный момент: создание объекта в памяти через СоздатьЭлемент() и заполнение его полей не помещает данные в базу данных до тех пор, пока не будет вызван метод ОбъектЗаписи.Записать().

Особенности формирования уникального составного кода

Если в конфигурации включен контроль уникальности кодов, а сам код формируется программно путем конкатенации нескольких полей (например, Реквизит1 + Реквизит2 + Реквизит3), обратим внимание на следующие правила:

  1. Использование разделителей: при простом сложении строковых представлений комбинации разных значений могут дать одинаковую строку (например, комбинации «1» + «23» и «12» + «3» обе дают «123»). Рекомендуется использовать разделители или приводить значения к фиксированной длине.
  2. Длина реквизита Код: суммарная длина объединяемых значений не должна превышать максимальную длину реквизита Код, заданную в метаданных справочника, иначе строка будет обрезана платформой, что вызовет ошибку уникальности.
  3. Автонумерация: если код формируется полностью вручную, для данного объекта в свойствах метаданных или перед записью следует контролировать отключение стандартной автонумерации.

Почему нельзя создавать справочники внутри процедуры ОбработкаПроведения

Запись ссылочных элементов внутри транзакции проведения документа считается грубой архитектурной ошибкой. Выделим основные риски такого подхода:

  1. Проблема отмены проведения и перепроведения: при отмене проведения документа платформа 1С автоматически очищает только движения регистров. Созданные ранее элементы справочников в базе останутся. При повторном проведении процедура попытается записать их заново, что приведет к ошибке контроля уникальности кода либо к лавинообразному дублированию записей.
  2. Блокировки и падение производительности: транзакция проведения блокирует таблицы и индексы создаваемых справочников. При одновременном проведении документов несколькими пользователями это вызывает взаимные блокировки (deadlocks) и замедляет работу всей системы.
  3. Неоправданное раздувание таблиц: неконтролируемое создание новых элементов справочника на каждую строку документа быстро увеличивает размер таблиц базы данных и замедляет работу автоподбора и полнотекстового поиска.

Правильные варианты реализации задачи

Разберем, как грамотно спроектировать логику системы, избегая создания справочников в момент проведения:

  1. Создание элементов до проведения документа: если новые элементы справочника действительно необходимы, их генерацию следует вызывать на этапе ввода данных пользователем в форме документа (например, по нажатию специальной команды формы «Создать номенклатуру» или при изменении строки табличной части). В таком случае документ оперирует уже готовыми ссылками, а обработка проведения отвечает только за запись движений в регистры.
  2. Использование регистров сведений: если для номенклатуры требуется хранить уникальные комбинации параметров, наилучшим решением выступает регистр сведений. Для регистра сведений с типом подчинения Регистратор платформа 1С берет на себя автоматический контроль: при отмене проведения или изменении документа все связанные записи очищаются и перезаписываются автоматически без создания «мусорных» данных.
  3. Использование характеристик или серий: если базовая номенклатурная позиция одна, а строки документа отличаются только уникальным набором дополнительных реквизитов, целесообразно использовать механизм характеристик или серий номенклатуры вместо создания дублирующих позиций в основном справочнике.
← На главную