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