Как исправить ошибку «Метод объекта не обнаружен (ПолучитьОбъект)» при программном изменении Номенклатуры

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

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

Разбор причины возникновения ошибки

Проанализируем ситуацию. Ошибка возникает тогда, когда мы пытаемся вызвать метод ПолучитьОбъект() у того, что объектом или ссылкой не является, либо когда мы обращаемся к метаданным напрямую. В коде автора из примера были допущены следующие критические ошибки:

  1. Обращение к перечислению: Попытка вызвать Перечисления.СтавкиНдс.ПолучитьОбъект() лишена смысла, так как перечисления — это объекты метаданных, значения которых задаются в Конфигураторе. Их нельзя программно изменять или «получать как объект» в режиме «Предприятие».
  2. Обращение к реквизиту вместо ссылки: Попытка вызвать метод у Номенклатура.СтавкаНДС ошибочна, так как СтавкаНДС — это уже конкретное значение (ссылка на перечисление), а не ссылка на элемент справочника номенклатуры.
  3. Отсутствие выборки: Результат запроса — это таблица. Чтобы изменить данные, нам нужно перебрать каждую строку этой таблицы, получить ссылку на конкретный товар и уже у этой ссылки вызвать ПолучитьОбъект().

Правильный алгоритм массового изменения реквизитов

Для того чтобы корректно изменить ставку НДС во всей номенклатуре (или ее части), мы должны придерживаться строгого алгоритма: сформировать запрос, получить ссылку, преобразовать ее в объект, изменить реквизит и записать объект. Рассмотрим пошагово реализацию этой задачи на сервере.

Проанализируем исправленный код, который решает поставленную задачу:


&НаСервере
Процедура УстановитьСтавкуНДСНаСервере()
    
    // 1. Создаем запрос для получения ссылок на элементы справочника
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    Номенклатура.Ссылка КАК Ссылка
        |ИЗ
        |    Справочник.Номенклатура КАК Номенклатура
        |ГДЕ
        |    Номенклатура.ЭтоГруппа = ЛОЖЬ
        |    И Номенклатура.СтавкаНДС <> &СтавкаНДС"; // Выбираем только те, где ставка еще не совпадает
    
    // СтавкаНДС в параметре — это значение из реквизита формы (выбор пользователя)
    Запрос.УстановитьПараметр("СтавкаНДС", Объект.СтавкаНДС);    
    
    РезультатЗапроса = Запрос.Выполнить();
    
    // 2. Начинаем обход выборки
    Выборка = РезультатЗапроса.Выбрать();
    
    Пока Выборка.Следующий() Цикл
        
        // 3. Получаем объект из ссылки для возможности редактирования
        ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект();
        
        // 4. Устанавливаем новое значение реквизита
        ОбъектНоменклатура.СтавкаНДС = Объект.СтавкаНДС;
        
        // 5. Записываем изменения в базу данных
        Попытка
            ОбъектНоменклатура.Записать();
        Исключение
            Сообщить("Не удалось записать объект: " + Выборка.Ссылка + " Ошибка: " + ОписаниеОшибки());
        КонецПопытки;
        
    КонецЦикла;
    
    Сообщить("Обработка завершена успешно!");

КонецПроцедуры

Важные технические нюансы и оптимизация

При написании подобных обработок важно учитывать несколько профессиональных аспектов, которые сделают ваш код надежным и быстрым.

Исключение групп: В справочнике Номенклатура обычно используется иерархия. У папок (групп) может не быть реквизита СтавкаНДС или его изменение для групп не имеет смысла. Поэтому в запросе мы добавили условие ГДЕ Номенклатура.ЭтоГруппа = ЛОЖЬ.

Использование режима записи «Загрузка»: Если вы уверены в данных и не хотите, чтобы при записи срабатывали сложные проверки (например, проверка заполнения артикула или веса, которые могут заблокировать запись старых позиций), используйте свойство ОбменДанными.Загрузка. Рассмотрим пример:


ОбъектНоменклатура = Выборка.Ссылка.ПолучитьОбъект();
ОбъектНоменклатура.СтавкаНДС = Объект.СтавкаНДС;
// Отключаем проверки в модуле объекта для ускорения и обхода ошибок заполнения
ОбъектНоменклатура.ОбменДанными.Загрузка = Истина; 
ОбъектНоменклатура.Записать();

Работа с транзакциями: Если справочник содержит десятки тысяч элементов, запись каждого объекта по отдельности может занять много времени. Однако запись всех объектов в одной транзакции может привести к блокировке всей таблицы для других пользователей. Оптимальным решением будет фиксация транзакции порциями по 500-1000 элементов.

Альтернативное решение: Групповое изменение реквизитов

Выясним причину, по которой иногда вообще не стоит писать свой код. В большинстве современных типовых конфигураций 1С (УТ 11, БП 3.0, ERP) уже встроена мощная обработка «Групповое изменение реквизитов».

Если ваша задача разовая, рассмотрите следующий путь:

  1. Перейдите в раздел Администрирование — Обслуживание — Корректировка данных.
  2. Выберите Групповое изменение реквизитов.
  3. Выберите объект Номенклатура.
  4. Настройте фильтр (если нужно изменить ставку только в определенной группе).
  5. Найдите в списке реквизит Ставка НДС, установите новое значение и нажмите Изменить реквизиты.

Этот способ безопаснее, так как он использует отлаженные механизмы библиотеки стандартных подсистем (БСП) и позволяет избежать написания лишнего кода, в котором легко допустить ошибку ПолучитьОбъект().

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

← На главную