Почему возникает ошибка "Значение не является значением объектного типа (Отбор)" при работе с набором записей регистра сведений?

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

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

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


Процедура КонтрагентПриИзмененииНаСервере()
    РС = РегистрыСведений.Цены.СоздатьНаборЗаписей;
    РС.Отбор.Контрагент.Установить(Объект.Контрагент);
    СтрокаДанных = РС.Добавить();
    СтрокаДанных.Контрагент = Объект.Контрагент;
    РС.Записать();
КонецПроцедуры

Причина 1: Синтаксическая ошибка при вызове метода

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

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

Исправленный вариант инициализации:

РС = РегистрыСведений.Цены.СоздатьНаборЗаписей();

Причина 2: Специфика отборов в подчиненных регистрах

Посмотрим на ошибку Поле объекта не обнаружено (Контрагент). Если после добавления скобок вы получаете такое сообщение, необходимо проверить настройки самого регистра сведений в конфигураторе.

Если в свойствах регистра установлен режим записи Подчинение регистратору, платформа жестко ограничивает доступные поля в коллекции отбора. Для подчиненного регистра физически доступно только одно поле для отбора — это Регистратор. Обратиться к измерению напрямую через РС.Отбор.Контрагент невозможно, даже если такое измерение существует. Отбор записей в таких регистрах осуществляется исключительно по документу-регистратору.

Причина 3: Развеиваем мифы об индексировании измерений

В обсуждениях разработчиков иногда можно встретить мнение, что отбор в наборе записей независимого регистра можно установить только по тем измерениям, у которых стоит галочка Индексировать или Ведущее. Это утверждение ошибочно!

Проанализируем ситуацию: при работе с набором записей независимого регистра сведений программную установку отбора можно применять по любому измерению. Галочка индексирования влияет исключительно на физическую структуру таблиц в базе данных и скорость выполнения запросов, но она никак не ограничивает права разработчика на использование свойства Отбор.

Причина 4: Логическая ошибка при записи данных

Проанализируем логику приведенного кода. Разработчик устанавливает отбор по контрагенту, добавляет новую строку методом РС.Добавить() и сразу вызывает метод РС.Записать(). Что произойдет в базе данных?

Если код оставить в таком виде, платформа затрет (удалит) все существующие записи по этому контрагенту в регистре и запишет вместо них только одну новую добавленную строку. Если наша цель — именно дописать новую информацию к уже существующей, мы обязаны прочитать текущие данные после установки отбора.

Рассмотрим правильный пример добавления записи к существующему набору:


Процедура КонтрагентПриИзмененииНаСервере()
    // 1. Создаем набор записей со скобками
    РС = РегистрыСведений.Цены.СоздатьНаборЗаписей();
    
    // 2. Устанавливаем отбор
    РС.Отбор.Контрагент.Установить(Объект.Контрагент);
    
    // 3. Читаем текущие записи из базы по данному отбору
    РС.Прочитать();
    
    // 4. Добавляем новую строку в прочитанный набор
    СтрокаДанных = РС.Добавить();
    СтрокаДанных.Контрагент = Объект.Контрагент;
    // ... заполнение остальных полей (ресурсов) ...
    
    // 5. Записываем обновленный набор в базу
    РС.Записать();
КонецПроцедуры

Особенности работы отладчика 1С

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

Это стандартное поведение табло. Когда в длинной цепочке вызовов одно из промежуточных свойств (в данном случае Контрагент) недоступно или не существует, отладчик не может корректно интерпретировать следующий за ним метод (Установить()) и "сваливает" вину на предыдущий доступный объект (Отбор). Это лишь подтверждает тот факт, что в текущем контексте (например, из-за подчинения регистратору) нужного измерения в отборе просто нет.

Подведем итоги. Для успешной работы с наборами записей всегда проверяйте:

  1. Наличие скобок при вызове методов СоздатьНаборЗаписей(), Добавить(), Записать().
  2. Режим записи регистра (независимый или подчиненный регистратору).
  3. Наличие метода Прочитать(), если вы хотите дополнить данные, а не полностью их перезаписать.
  4. Контекст выполнения кода: доступны ли реквизиты объекта (например, Объект.Контрагент) на сервере в данный момент времени.
← На главную