Наверняка многие разработчики сталкивались с непонятным поведением системы: мы пытаемся присвоить значение реквизиту строки таблицы или переменной, код выполняется без ошибок, но при проверке в отладчике значение всё равно равно Неопределено. Разберем по шагам, почему это происходит и как правильно решить эту проблему.
Проанализируем самую частую причину — строгую типизацию. Допустим, мы пытаемся записать ссылку на перечисление в реквизит таблицы (или реквизит формы), который имеет тип Строка, либо составной тип данных, куда ссылка на конкретное перечисление не включена.
В платформе 1С, если колонка таблицы значений, коллекция данных формы или реквизит табличной части имеет строго заданный тип, система при попытке присвоить значение недопустимого типа не всегда выдает критическую ошибку. Зачастую она просто отбрасывает это значение, оставляя поле пустым или записывая Неопределено. В рассмотренном случае разработчик пытался поместить перечисление в реквизит, чей составной тип включал Строку, Число, Дату и Булево, но не Перечисление.
Как исправить ситуацию:
Посмотрим на примеры правильного преобразования значения перечисления в строку. Рекомендуется использовать встроенные функции платформы:
// Использование функции Строка() - простое строковое представление
ДДС = Строка(Перечисления.ВидыОперацийСписаниеДенежныхСредств.ПеречислениеЗП);
// Более надежный вариант для универсальности и обмена данными
ДДС = XMLСтрока(Перечисления.ВидыОперацийСписаниеДенежныхСредств.ПеречислениеЗП);
Также иногда требуется получить именно системное имя (идентификатор) значения перечисления, заданное в конфигураторе. Это можно сделать через метаданные:
ЗначениеП = Перечисления.ВидыОперацийСписаниеДенежныхСредств.ПеречислениеЗП;
ИндексЗначения = Перечисления.ВидыОперацийСписаниеДенежныхСредств.Индекс(ЗначениеП);
ДДС = Метаданные.Перечисления.ВидыОперацийСписаниеДенежныхСредств.ЗначенияПеречисления[ИндексЗначения].Имя;
Иногда проблема кроется вообще не в типах данных, а в банальной ошибке написания алгоритма. Рассмотрим типичный пример с условиями, из-за которого переменная или свойство может остаться не заполненным:
Если Не ЗначениеЗаполнено(СтрокаДокумента.ВидОперации) Тогда
// ... вычисляем ВидОперацииДокумента и ДДС ...
СтрокаДокумента.ВидОперации = ВидОперацииДокумента;
// Присвоение значения в строку происходит ТОЛЬКО здесь
СтрокаДокумента.СтатьяДДС = ДДС;
Иначе
ВидОперацииДокумента = СтрокаДокумента.ВидОперации;
ДДС = СтрокаДокумента.СтатьяДДС;
// ОШИБКА: обратного присвоения в СтрокаДокумента.СтатьяДДС в этой ветке нет!
КонецЕсли;
Проанализируем этот блок: если условие проверки заполненности не выполняется, алгоритм переходит в ветку Иначе. В ней происходит только чтение значения из реквизита в локальную переменную ДДС. Но если мы ожидали, что реквизит СтатьяДДС должен быть обновлен при любых условиях, то в этой ветке мы просто пропустили команду СтрокаДокумента.СтатьяДДС = .... Внимательно проверяйте, чтобы переменная-получатель гарантированно инициализировалась во всех ветвях кода.
Если мы работаем с программно созданными таблицами значений, и тип колонки строго ограничен (например, строкой определенной длины), мы можем использовать специальный метод платформы ПривестиЗначение() объекта ОписаниеТипов. Он позволяет безопасно попытаться преобразовать наше значение к нужному типу, согласно заранее заданным настройкам колонки:
// Получаем описание типов проблемной колонки
ОписаниеТиповКолонки = СтрокаДокумента.Владелец().Колонки.СтатьяДДС.ТипЗначения;
// Безопасно приводим наше значение к типу колонки
ДДС = ОписаниеТиповКолонки.ПривестиЗначение(Перечисления.ВидыОперацийСписаниеДенежныхСредств.ПеречислениеЗП);
СтрокаДокумента.СтатьяДДС = ДДС;
Подводя итоги: если вы столкнулись с тем, что значение упорно остается Неопределено, в первую очередь выясним, совпадают ли типы левой и правой части операции присвоения. Воспользуйтесь табло отладки, чтобы проверить ТипЗнч(). Если типы разные, приведем их друг к другу программно или изменим свойства реквизита в конфигураторе.