Почему возникает ошибка «Реквизит недоступен для изменения» при работе с табличной частью справочника в 1С

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

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

Рассмотрим конкретную ситуацию, проанализируем причину её возникновения и изучим варианты исправления данной проблемы.

Анализ проблемы и симптомов

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

Исходный код обработки выглядит следующим образом:


&НаСервере
Процедура КопироватьНаСервере()
    
    Для Каждого Стр Из ЭтотОбъект.КудаКопировать Цикл
        ОбТовар = Стр.Значение.ПолучитьОбъект();
        ОбТовар.СкладСрокПоставки.Очистить();
        
        Для Каждого СтрОткуда Из ЭтотОбъект.ОткудаКопировать.СкладСрокПоставки Цикл
            Нстр = ОбТовар.СкладСрокПоставки.Добавить();
            ЗаполнитьЗначенияСвойств(Нстр, СтрОткуда);
        КонецЦикла;    
        
        ОбТовар.Записать();
    КонецЦикла;    
    
КонецПроцедуры

При выполнении строки ОбТовар.СкладСрокПоставки.Очистить(); система сбивается и выдает ошибку. При этом в отладчике тип переменной ОбТовар отображается как СправочникОбъект.Номенклатура, однако табличная часть блокируется для изменения.

Главная причина ошибки

В иерархических справочниках платформы 1С для каждого реквизита и табличной части в Конфигураторе предусмотрено свойство «Использование» (Использование). Оно определяет, для каких типов узлов иерархии доступно данное поле:

  1. Для элемента — табличная часть или реквизит существуют и доступны для редактирования только у элементов справочника (где ЭтоГруппа = Ложь).
  2. Для группы — табличная часть доступна только у групп справочника (где ЭтоГруппа = Истина).
  3. Для элемента и группы — реквизит или табличная часть создается для всех узлов справочника.

Если у табличной части установлена настройка «Для элемента», а алгоритм пытается записать данные в объект-группу, платформа 1С блокирует изменение коллекции, так как физически структура табличной части для групп не создана. Именно это вызывает исключение «Реквизит недоступен для изменения».

Варианты решения проблемы

Решение 1. Изменение свойств метаданных в Конфигураторе

Если табличная часть по логике приложения действительно должна храниться у групп номенклатуры, необходимо скорректировать настройки в конфигураторе:

  1. Откроем дерево метаданных и найдем справочник Номенклатура.
  2. Раскроем ветку Табличные части и откроем палитру свойств нужной табличной части.
  3. Найдем свойство Использование и установим значение «Для элемента и группы» или «Для группы».
  4. Сохраним и обновим конфигурацию базы данных.

Решение 2. Программная проверка типа узла иерархии

Если табличная часть должна заполняться только у конечных элементов, а в списке могут присутствовать группы, добавим в код условие с методом ЭтоГруппа():


&НаСервере
Процедура КопироватьНаСервере()
    
    Для Каждого Стр Из ЭтотОбъект.КудаКопировать Цикл
        ОбТовар = Стр.Значение.ПолучитьОбъект();
        
        // Пропускаем группы, если табличная часть задана только для элементов
        Если ОбТовар.ЭтоГруппа() Тогда
            Продолжить;
        КонецЕсли;
        
        ОбТовар.СкладСрокПоставки.Очистить();
        
        Для Каждого СтрОткуда Из ЭтотОбъект.ОткудаКопировать.СкладСрокПоставки Цикл
            Нстр = ОбТовар.СкладСрокПоставки.Добавить();
            ЗаполнитьЗначенияСвойств(Нстр, СтрОткуда);
        КонецЦикла;    
        
        ОбТовар.Записать();
    КонецЦикла;    
    
КонецПроцедуры

Решение 3. Выборка элементов иерархии через запрос

Если задача состоит в том, чтобы при выборе группы распространить данные на все входящие в нее товары, сформируем запрос с условием ГДЕ Ссылка В ИЕРАРХИИ (&ВыбраннаяГруппа) И НЕ ЭтоГруппа:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Номенклатура.Ссылка КАК Ссылка
    |ИЗ
    |	Справочник.Номенклатура КАК Номенклатура
    |ГДЕ
    |	Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
    |	И НЕ Номенклатура.ЭтоГруппа";

Запрос.УстановитьПараметр("Группа", ВыбраннаяГруппа);
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();

Пока Выборка.Следующий() Цикл
    ОбТовар = Выборка.Ссылка.ПолучитьОбъект();
    ОбТовар.СкладСрокПоставки.Очистить();
    
    Для Каждого СтрОткуда Из ЭтотОбъект.ОткудаКопировать.СкладСрокПоставки Цикл
        Нстр = ОбТовар.СкладСрокПоставки.Добавить();
        ЗаполнитьЗначенияСвойств(Нстр, СтрОткуда);
    КонецЦикла;
    
    ОбТовар.Записать();
КонецЦикла;

Таким образом, перед написанием кода групповой обработки данных всегда следует проверять свойство Использование реквизитов и табличных частей иерархических справочников.

← На главную