Как исправить ошибку мутабельных значений и проверить пустую ссылку при загрузке данных в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При работе с обработкой «Загрузка данных из табличного документа» и написании произвольных алгоритмов на встроенном языке 1С разработчики часто сталкиваются с ошибками вида Проверка мутабельных значений на заполненность не поддерживается или Переменная не определена (Справочник). В этой статье мы подробно разберем причины возникновения этих ошибок и рассмотрим проверенные способы их решения.

Причины возникновения ошибки мутабельных значений

Рассмотрев механизмы платформы 1С, выясним, почему возникает данное исключение при вычислении выражений в обработках загрузки.

Во встроенном языке 1С типы данных делятся на ссылочные и объектные (мутабельные):

  1. Мутабельные типы (объекты) — это типы данных, состояние которых можно изменять прямо в памяти (например, СправочникОбъект, ДокументОбъект, ТаблицаЗначения). Они служат для создания и модификации записей.
  2. Ссылочные типы — это ссылки на существующие или создаваемые записи в базе данных (например, СправочникСсылка.НоменклатураПоставщиков). Они являются неизменяемыми значениями.

В обработке загрузки данных в поле вычисления переменная Результат ожидает получить именно ссылку на элемент справочника. Если присвоить переменной Результат сам объект (типа СправочникОбъект), платформа при попытке записать его в реквизит или проверить на заполненность вызовет исключение мутабельности.

Проанализируем ошибочный фрагмент кода:


НоваяНоменклатура = Справочники.НоменклатураПоставщиков.СоздатьЭлемент();
НоваяНоменклатура.Наименование = ТекстыЯчеек[22];
НоваяНоменклатура.Записать();

// ОШИБКА: передается мутабельный объект СправочникОбъект
Результат = НоваяНоменклатура; 

Для исправления ошибки необходимо явным образом получить ссылку созданного объекта через свойство Ссылка:


НоваяНоменклатура = Справочники.НоменклатураПоставщиков.СоздатьЭлемент();
НоваяНоменклатура.Наименование = ТекстыЯчеек[22];
НоваяНоменклатура.Записать();

// ПРАВИЛЬНО: передается ссылка СправочникСсылка
Результат = НоваяНоменклатура.Ссылка; 

Заполнение подчиненных реквизитов и реквизита Владелец

Схожее правило действует и при заполнении реквизитов подчинения. Например, реквизиту Владелец объекта справочника должно быть присвоено значение типа СправочникСсылка.

Методы поиска НайтиПоКоду() или НайтиПоНаименованию() у менеджера справочника всегда возвращают ссылочный тип. Поэтому результат поиска владельца можно присваивать напрямую:


Витта = Справочники.Партнеры.НайтиПоКоду("00-00000009");
НоваяНоменклатура.Владелец = Витта; // Витта уже является ссылкой

Как правильно проверять ссылку на пустоту во встроенном языке 1С

Разберем распространенную ошибку, когда при проверке пустой ссылки пытаются использовать синтаксис ЗНАЧЕНИЕ(Справочник.Имя.ПустаяСсылка). Конструкция ЗНАЧЕНИЕ(...) применяется исключительно в языке запросов и системе компоновки данных (СКД). При вызове в коде BSL она приводит к ошибке компиляции Переменная не определена (Справочник).

Рассмотрим 4 корректных способа проверки ссылок на пустоту во встроенном языке 1С:

  1. Использование метода менеджерa справочника ПустаяСсылка():

    
    Если НомПос = Справочники.НоменклатураПоставщиков.ПустаяСсылка() Тогда
        // Ссылка пустая
    КонецЕсли;
    
  2. Использование метода самого ссылочного значения Пустая():

    
    Если НомПос.Пустая() Тогда
        // Ссылка пустая
    КонецЕсли;
    
  3. Использование глобальной функции ЗначениеЗаполнено():

    
    Если Не ЗначениеЗаполнено(НомПос) Тогда
        // Значение не заполнено или содержит пустую ссылку
    КонецЕсли;
    
  4. Использование системной функции ПредопределенноеЗначение():

    
    Если НомПос = ПредопределенноеЗначение("Справочник.НоменклатураПоставщиков.ПустаяСсылка") Тогда
        // Ссылка пустая
    КонецЕсли;
    

Итоговый пример корректного выражения

Посмотрим на итоговый исправленный алгоритм поиска и создания элемента в обработке загрузки данных из табличного документа:


НомПос = Справочники.НоменклатураПоставщиков.НайтиПоНаименованию(ТекстыЯчеек[21]);

Если Не ЗначениеЗаполнено(НомПос) Тогда
    Витта = Справочники.Партнеры.НайтиПоКоду("00-00000009");
    
    НоваяНоменклатура = Справочники.НоменклатураПоставщиков.СоздатьЭлемент();
    НоваяНоменклатура.Наименование = ТекстыЯчеек[22];
    НоваяНоменклатура.Владелец = Витта;
    НоваяНоменклатура.Записать();
    
    Результат = НоваяНоменклатура.Ссылка;
Иначе
    Результат = НомПос;
КонецЕсли;
← На главную