Почему возникает ошибка «Поле объекта не обнаружено» при установке отбора в наборе записей регистра сведений и как её исправить?

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

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

{Форма(295)}: Поле объекта не обнаружено (ИмяИзмерения)

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

Анализ ситуации и причина ошибки

Проанализируем типовой фрагмент кода, приводящий к ошибке:


НаборЗаписей = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.КлючЗадания.Установить(КлючЗадания);
НаборЗаписей.Прочитать();

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

  1. Независимый: записи вносятся непосредственно в регистр без привязки к документу. В этом случае свойство Отбор набора записей содержит коллекцию всех измерений регистра (а для периодического регистра — еще и поле Период).
  2. Подчинение регистратору: записи формируются при проведении документов-регистраторов. В этом режиме свойство Отбор набора записей содержит только одно поле — Регистратор.

Если для регистра установлено свойство Режим записи = Подчинение регистратору, обращение к любому измерению через НаборЗаписей.Отбор.ИмяИзмерения гарантированно вызовет ошибку Поле объекта не обнаружено. При этом наличие у измерения признаков «Индексировать», «Индексировать с доп. упорядочиванием» или «Ведущее» никак не меняет состав коллекции Отбор у набора записей подчиненного регистра.

Рассмотрим также свойство измерения «Основной отбор»: оно предназначено исключительно для независимых регистров сведений и определяет список измерений для правил регистрации изменений в планах обмена (РИБ). На подчиненные регистры это свойство не распространяется.

Способ 1. Получение данных с помощью запроса (рекомендуемый вариант)

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

Посмотрим на пример реализации выборки через запрос:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |	Регистр.Регистратор КАК Регистратор,
    |	Регистр.Период КАК Период,
    |	Регистр.КлючЗадания КАК КлючЗадания
    |ИЗ
    |	РегистрСведений.ГУ_ЗаданияИнженерамПоДокументам КАК Регистр
    |ГДЕ
    |	Регистр.КлючЗадания = &КлючЗадания";

Запрос.УстановитьПараметр("КлючЗадания", КлючЗадания);
Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл
    // Обработка полученных строк
КонецЦикла;

Способ 2. Использование метода менеджера «Выбрать»

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

Рассмотрим пример использования метода Выбрать():


Отбор = Новый Структура("КлючЗадания", КлючЗадания);
Выборка = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.Выбрать(, , Отбор);

Пока Выборка.Следующий() Цикл
    // Чтение данных строки выборки
КонецЦикла;

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


Отбор = Новый Структура("КлючЗадания", КлючЗадания);
АктуальныеДанные = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.СрезПоследних(ТекущаяДатаСеанса(), Отбор);

Способ 3. Изменение или удаление записей в подчиненном регистре

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

Разберем последовательность действий для такой модификации:

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

Посмотрим на пример программной очистки строк по условию:


// 1. Получаем список регистраторов через запрос
Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ РАЗЛИЧНЫЕ
    |	Регистр.Регистратор КАК Регистратор
    |ИЗ
    |	РегистрСведений.ГУ_ЗаданияИнженерамПоДокументам КАК Регистр
    |ГДЕ
    |	Регистр.КлючЗадания = &КлючЗадания";

Запрос.УстановитьПараметр("КлючЗадания", КлючЗадания);
Результат = Запрос.Выполнить().Выгрузить();

// 2. Обрабатываем каждый набор записей по регистратору
Для Каждого Стр Из Результат Цикл
    НаборЗаписей = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.СоздатьНаборЗаписей();
    НаборЗаписей.Отбор.Регистратор.Установить(Стр.Регистратор);
    НаборЗаписей.Прочитать();
    
    Индекс = НаборЗаписей.Количество() - 1;
    Пока Индекс >= 0 Цикл
        Если НаборЗаписей[Индекс].КлючЗадания = КлючЗадания Тогда
            НаборЗаписей.Удалить(Индекс);
        КонецЕсли;
        Индекс = Индекс - 1;
    КонецЦикла;
    
    НаборЗаписей.Записать();
КонецЦикла;

Способ 4. Изменение режима записи регистра в конфигураторе

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

В дереве метаданных конфигуратора откроем свойства регистра сведений и изменим значение свойства Режим записи с Подчинение регистратору на Независимый. После этого отбор по измерениям через НаборЗаписей.Отбор.ИмяИзмерения.Установить(...) станет доступным и отработает корректно без ошибок.

← На главную