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