При разработке учетных решений в 1С часто возникает задача автоматического создания элементов справочников (например, Номенклатура) на основании строк табличной части первичного документа. Начинающие разработчики нередко сталкиваются с двумя типами проблем: синтаксическими ошибками при заполнении и записи объекта, а также серьезными архитектурными ошибками, связанными с выполнением этих действий в транзакции проведения документа.
Разберем детально, почему стандартный метод Заполнить() может не сработать, как правильно копировать данные и почему архитектурно небезопасно создавать ссылочные данные в процедуре ОбработкаПроведения.
Проанализируем частую ошибку: попытку заполнить новый объект справочника из структуры с помощью вызова ОбъектЗаписи.Заполнить(ЭлементыОтбора). В платформе 1С метод Заполнить() обращается к встроенному событию ОбработкаЗаполнения в модуле соответствующего объекта. Если в модуле справочника данный обработчик не переопределен разработчиком или не умеет разбирать входящую структуру параметров, реквизиты объекта останутся пустыми.
Для прямого копирования значений между объектами и структурами по совпадающим именам свойств в платформе 1С предусмотрена процедура ЗаполнитьЗначенияСвойств(). Она не требует кода в модуле объекта и сопоставляет поля автоматически.
Посмотрим на корректный пример инициализации и заполнения реквизитов объекта:
Для Каждого СтрокаТЧ Из Товары Цикл
ЭлементыОтбора = Новый Структура;
ЭлементыОтбора.Вставить("Код", СтрокаТЧ.Код);
ЭлементыОтбора.Вставить("Наименование", СтрокаТЧ.Номенклатура);
ЭлементыОтбора.Вставить("ТипНоменклатуры", СтрокаТЧ.Товар);
ЭлементыОтбора.Вставить("ВидНоменклатуры", СтрокаТЧ.ВидНоменклатуры);
ЭлементыОтбора.Вставить("Состояние", СтрокаТЧ.Состояние);
ЭлементыОтбора.Вставить("База", СтрокаТЧ.База);
ЭлементыОтбора.Вставить("Склад", Склад); // Реквизит из шапки документа
ЭлементыОтбора.Вставить("Номер", СтрокаТЧ.Номер);
ОбъектЗаписи = Справочники.Номенклатура.СоздатьЭлемент();
ЗаполнитьЗначенияСвойств(ОбъектЗаписи, ЭлементыОтбора);
// Обязательный вызов метода для фиксации в базе данных
ОбъектЗаписи.Записать();
КонецЦикла;
Важный момент: создание объекта в памяти через СоздатьЭлемент() и заполнение его полей не помещает данные в базу данных до тех пор, пока не будет вызван метод ОбъектЗаписи.Записать().
Если в конфигурации включен контроль уникальности кодов, а сам код формируется программно путем конкатенации нескольких полей (например, Реквизит1 + Реквизит2 + Реквизит3), обратим внимание на следующие правила:
Код, заданную в метаданных справочника, иначе строка будет обрезана платформой, что вызовет ошибку уникальности.Запись ссылочных элементов внутри транзакции проведения документа считается грубой архитектурной ошибкой. Выделим основные риски такого подхода:
Разберем, как грамотно спроектировать логику системы, избегая создания справочников в момент проведения:
Регистратор платформа 1С берет на себя автоматический контроль: при отмене проведения или изменении документа все связанные записи очищаются и перезаписываются автоматически без создания «мусорных» данных.