При работе с программным изменением данных в 1С программисты часто сталкиваются с ситуацией, когда код, успешно работающий для одного объекта, внезапно выдает ошибку на другом. Типичный пример — работа с табличной частью ДополнительныеРеквизиты. В этой статье мы подробно разберем, почему возникает ошибка «Значение не является значением объектного типа (Значение)», проанализируем механизмы работы свойств и предложим несколько вариантов надежного решения задачи.
Давайте проанализируем ситуацию, описанную в теме. Программист пытается найти строку в табличной части дополнительных реквизитов объекта Номенклатура по ссылке на свойство. Ошибка происходит на строке присвоения значения:
ДопРек1.Значение = Строка.КодВБ;
Система сообщает, что ДопРек1 не является объектом. Это происходит потому, что метод Найти(), использованный ранее, не обнаружил подходящей строки в табличной части и вернул стандартное значение Неопределено. Пытаясь обратиться к свойству Значение через точку от Неопределено, мы закономерно получаем исключение.
Почему строки может не быть в табличной части? Рассмотрим основные причины:
НайтиПоНаименованию для поиска самого свойства (ПВХ) может вернуть пустую ссылку, если наименование указано с ошибкой или в базе есть дубли.Самый простой и надежный способ избежать ошибки при ручном манипулировании объектом — это проверка результата поиска и добавление новой строки в случае необходимости. Давайте разберем по шагам, как должен выглядеть правильный код.
Вместо прямого присвоения мы должны реализовать следующую логику:
ДополнительныеРеквизиты.Неопределено.Добавить() и установить в ней свойство.Пример исправленного кода:
// Сначала получаем ссылку на свойство (лучше не по наименованию)
Парам1 = ПланыВидовХарактеристик.ДополнительныеРеквизитыИСведения.НайтиПоНаименованию("Код для WB");
Если Не Парам1.Пустая() Тогда
// Ищем строку в табличной части объекта
ДопРек1 = НашаНоменклатура.ДополнительныеРеквизиты.Найти(Парам1, "Свойство");
// Если строки нет, создаем ее
Если ДопРек1 = Неопределено Тогда
ДопРек1 = НашаНоменклатура.ДополнительныеРеквизиты.Добавить();
ДопРек1.Свойство = Парам1;
КонецЕсли;
// Теперь обращение к .Значение безопасно
ДопРек1.Значение = Строка.КодВБ;
КонецЕсли;
В современных конфигурациях (таких как УТ 11, ERP 2, КА 2 или БП 3.0), построенных на базе Библиотеки стандартных подсистем (БСП), прямое редактирование табличной части через ПолучитьОбъект() считается «плохим тоном». Это может привести к нарушению логики работы кэша свойств или записи некорректных типов данных.
Проанализируем преимущества использования общего модуля УправлениеСвойствами. Программный интерфейс этой подсистемы позволяет записывать значения дополнительных реквизитов одной командой, не заботясь о поиске или создании строк.
Рассмотрим пример использования функции для записи значений:
// Подготовим структуру со значениями реквизитов
СвойстваДляЗаписи = Новый Структура;
СвойстваДляЗаписи.Вставить(Парам1, Строка.КодВБ);
// Используем метод БСП для записи в объект
// Это автоматически создаст нужные строки и проверит типы
УправлениеСвойствами.ЗаписатьЗависимыеРеквизиты(НашаНоменклатура.Ссылка, СвойстваДляЗаписи);
Важно: Методы БСП сами заботятся о проверке типов. Если ваш доп. реквизит имеет тип «Число», а вы передаете строку, БСП может выдать ошибку или корректно преобразовать данные, в зависимости от версии.
Посмотрим на ситуацию шире. Если вы выполняете загрузку данных (например, из Excel или по API маркетплейса) для тысяч позиций номенклатуры, постоянный вызов Записать() в цикле существенно замедлит работу системы.
Рассмотрим несколько советов по оптимизации:
Записать(). Это сэкономит время на транзакциях и не будет лишний раз очищать кэш полнотекстового поиска.ОбменДанными.Загрузка = Истина. Это отключит прикладные проверки в модуле объекта и ускорит процесс.Пример оптимизированного удаления пустой строки:
Если ПустаяСтрока(Строка.КодВБ) Тогда
СтрокаДляУдаления = НашаНоменклатура.ДополнительныеРеквизиты.Найти(Парам1, "Свойство");
Если СтрокаДляУдаления <> Неопределено Тогда
НашаНоменклатура.ДополнительныеРеквизиты.Удалить(СтрокаДляУдаления);
КонецЕсли;
Иначе
// Логика добавления/изменения, описанная выше
КонецЕсли;
Мы выяснили, что ошибка «Значение не является значением объектного типа» в данном контексте — это лишь следствие отсутствия данных в табличной части. Чтобы ваш код был надежным, всегда учитывайте возможность отсутствия строки в коллекции. Используйте проверку на Неопределено при ручной обработке или доверьте эту работу механизмам УправлениеСвойствами из состава БСП, что является наиболее современным и правильным подходом в разработке на платформе 1С:Предприятие 8.3.