При интеграции 1С с внешними системами (сайтами, маркетплейсами или другими базами данных) мы часто сталкиваемся с необходимостью программного заполнения дополнительных реквизитов. В современных конфигурациях, таких как КА 2.5, ERP 2.5 или УТ 11, этот механизм реализован через подсистему «Свойства» Библиотеки стандартных подсистем (БСП). Основным инструментом здесь выступает процедура ЗаписатьСвойстваУОбъекта.
Основная сложность заключается в том, что из внешних источников данные обычно приходят в текстовом формате (строки), в то время как дополнительные реквизиты в 1С могут иметь типы Число, Булево, Дата или ссылаться на справочник ЗначенияСвойствОбъектов. Разберем подробно, как правильно подготовить данные для записи.
Многих разработчиков вводит в заблуждение вопрос: нужно ли создавать несколько таблиц под разные типы данных? Проанализируем механику работы БСП. Процедура ЗаписатьСвойстваУОбъекта ожидает на вход таблицу значений определенной структуры. Нам не нужно создавать отдельные таблицы для чисел или булевых значений. Достаточно одной таблицы, но с правильно настроенными колонками.
Рассмотрим пример создания структуры такой таблицы:
ТаблицаСвойств = Новый ТаблицаЗначений;
ТаблицаСвойств.Колонки.Добавить("Свойство", Новый ОписаниеТипов("ПланВидовХарактеристикСсылка.ДополнительныеРеквизитыИСведения"));
// Для колонки Значение крайне желательно указать составной тип данных
МассивТипов = Новый Массив;
МассивТипов.Добавить(Тип("Число"));
МассивТипов.Добавить(Тип("Строка"));
МассивТипов.Добавить(Тип("Дата"));
МассивТипов.Добавить(Тип("Булево"));
МассивТипов.Добавить(Тип("СправочникСсылка.ЗначенияСвойствОбъектов"));
// Добавьте другие типы, если ваши реквизиты ссылаются на иные справочники
ТаблицаСвойств.Колонки.Добавить("Значение", Новый ОписаниеТипов(МассивТипов));
Важно понимать: процедура записи сама не умеет конвертировать "1" в Истина или "500" в 500 (число). Она просто берет значение из ячейки и пытается записать его в объект. Если тип значения в таблице не совпадает с типом, настроенным для доп. реквизита в ПВХ, вы либо получите ошибку, либо некорректные данные в базе.
Выясним, как наиболее эффективно преобразовать строковые данные, полученные извне, в типы 1С. Самый надежный способ — использовать объект ОписаниеТипов, который уже хранится в самом свойстве. Метод ПривестиЗначение() сделает за нас большую часть работы: уберет лишние символы из чисел и корректно обработает пустые значения.
Рассмотрим алгоритм обработки для каждого значения перед помещением в таблицу:
// Предположим, СвойСсылкаНаПВХ — это ссылка на элемент ПВХ ДополнительныеРеквизитыИСведения
// ЗначениеИзФайла — строка "123.45" или "Да"
ТипРеквизита = СсылкаНаПВХ.ТипЗначения; // Получаем ОписаниеТипов
ПриведенноеЗначение = ТипРеквизита.ПривестиЗначение(ЗначениеИзФайла);
// Теперь добавляем в таблицу
НоваяСтрока = ТаблицаСвойств.Добавить();
НоваяСтрока.Свойство = СсылкаНаПВХ;
НоваяСтрока.Значение = ПриведенноеЗначение;
Важный нюанс для типа Булево: Если во внешнем источнике логическое значение представлено строкой "Да", "Yes" или "1", метод ПривестиЗначение() не всегда поймет это автоматически. В таких случаях рекомендуем использовать простую проверку:
Если ТипРеквизита.СодержитТип(Тип("Булево")) Тогда
Если ВРег(ЗначениеИзФайла) = "ДА" Или ЗначениеИзФайла = "1" Тогда
ПриведенноеЗначение = Истина;
Иначе
ПриведенноеЗначение = Ложь;
КонецЕсли;
КонецЕсли;
Если доп. реквизит имеет тип «Дополнительное значение», то в колонку Значение нужно передавать не строку, а ссылку на справочник ЗначенияСвойствОбъектов. Посмотрим на критическую ошибку, которую часто допускают новички: поиск значения просто по наименованию.
Поскольку справочник ЗначенияСвойствОбъектов является подчиненным (владелец — ПВХ), в нем может быть множество элементов с названием "Красный" для разных свойств (например, для "Цвет ткани" и "Цвет упаковки"). Поэтому поиск должен быть строго с учетом владельца:
Функция НайтиЗначениеСвойства(ВладелецСвойства, НаименованиеЗначения)
ЗначениеСсылка = Справочники.ЗначенияСвойствОбъектов.НайтиПоНаименованию(НаименованиеЗначения, Истина, , ВладелецСвойства);
Если ЗначениеСсылка.Пустая() Тогда
// Если значение не найдено, его можно создать (если это допустимо логикой загрузки)
ОбъектЗначение = Справочники.ЗначенияСвойствОбъектов.СоздатьЭлемент();
ОбъектЗначение.Владелец = ВладелецСвойства;
ОбъектЗначение.Наименование = НаименованиеЗначения;
ОбъектЗначение.Записать();
ЗначениеСсылка = ОбъектЗначение.Ссылка;
КонецЕсли;
Возврат ЗначениеСсылка;
КонецФункции
Когда таблица подготовлена и все типы приведены, вызываем процедуру из модуля УправлениеСвойствами. Обратите внимание, что процедура универсальна: она сама разберется, является ли свойство дополнительным реквизитом (записывается в табличную часть объекта) или дополнительным сведением (записывается в регистр сведений).
// СсылкаНаОбъект — например, СправочникСсылка.Номенклатура
УправлениеСвойствами.ЗаписатьСвойстваУОбъекта(СсылкаНаОбъект, ТаблицаСвойств);
Проанализируем ситуацию с массовой загрузкой данных. Процедура ЗаписатьСвойстваУОбъекта внутри себя выполняет команду Объект.Записать(), если в таблице есть дополнительные реквизиты (те, что в ТЧ). Если вы загружаете 10 000 товаров, и для каждого вызываете эту процедуру, запись будет происходить крайне медленно.
Для оптимизации процесса рекомендуем следующий подход:
ДополнительныеРеквизиты вручную перед вызовом Объект.Записать().XMLЗначение(НужныйТип, СтрокаИзФайла) для более надежной конвертации дат и чисел, если данные приходят в стандартном XML-формате.Помните: чтобы программно "очистить" значение доп. реквизита, его все равно нужно включить в таблицу, передав в колонке Значение пустую ссылку или Неопределено. Если просто исключить свойство из таблицы, процедура ЗаписатьСвойстваУОбъекта оставит старое значение в базе без изменений.
Таким образом, использование ЗаписатьСвойстваУОбъекта — это правильный "стандартный" путь в рамках БСП. Главное — обеспечить предварительную типизацию данных в вашей таблице значений, и тогда процесс интеграции будет работать стабильно и предсказуемо.