При программной работе с регистрами сведений разработчики часто используют объект РегистрСведенийНаборЗаписей для чтения, перезаписи или очистки данных. Однако при попытке установить отбор по измерению можно столкнуться с ошибкой выполнения:
{Форма(295)}: Поле объекта не обнаружено (ИмяИзмерения)
Разберем по шагам, почему возникает эта ошибка, какие ограничения накладывает платформа «1С:Предприятие 8» на работу с наборами записей и какие существуют альтернативные способы получения и модификации данных.
Проанализируем типовой фрагмент кода, приводящий к ошибке:
НаборЗаписей = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.КлючЗадания.Установить(КлючЗадания);
НаборЗаписей.Прочитать();
Причина ошибки заключается в режиме записи регистра сведений. В платформе 1С регистры сведений могут иметь один из двух режимов записи:
Отбор набора записей содержит коллекцию всех измерений регистра (а для периодического регистра — еще и поле Период).Отбор набора записей содержит только одно поле — Регистратор.Если для регистра установлено свойство Режим записи = Подчинение регистратору, обращение к любому измерению через НаборЗаписей.Отбор.ИмяИзмерения гарантированно вызовет ошибку Поле объекта не обнаружено. При этом наличие у измерения признаков «Индексировать», «Индексировать с доп. упорядочиванием» или «Ведущее» никак не меняет состав коллекции Отбор у набора записей подчиненного регистра.
Рассмотрим также свойство измерения «Основной отбор»: оно предназначено исключительно для независимых регистров сведений и определяет список измерений для правил регистрации изменений в планах обмена (РИБ). На подчиненные регистры это свойство не распространяется.
Если задача заключается только в чтении записей регистра по определенному значению измерения, наиболее эффективным и правильным решением является использование механизма запросов. Запрос не блокирует избыточные данные и обращается непосредственно к таблице базы данных.
Посмотрим на пример реализации выборки через запрос:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Регистр.Регистратор КАК Регистратор,
| Регистр.Период КАК Период,
| Регистр.КлючЗадания КАК КлючЗадания
|ИЗ
| РегистрСведений.ГУ_ЗаданияИнженерамПоДокументам КАК Регистр
|ГДЕ
| Регистр.КлючЗадания = &КлючЗадания";
Запрос.УстановитьПараметр("КлючЗадания", КлючЗадания);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
// Обработка полученных строк
КонецЦикла;
Если требуется получить выборку записей без написания текста запроса, воспользуемся методом менеджера регистра Выбрать(). В отличие от набора записей, данный метод принимает структуру отбора, в которую можно передавать отборы по любым измерениям даже для подчиненных регистров.
Рассмотрим пример использования метода Выбрать():
Отбор = Новый Структура("КлючЗадания", КлючЗадания);
Выборка = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.Выбрать(, , Отбор);
Пока Выборка.Следующий() Цикл
// Чтение данных строки выборки
КонецЦикла;
Если подчиненный регистр является периодическим и необходимо получить актуальные значения ресурсов на определенную дату, аналогичную структуру отбора можно передать в методы СрезПоследних() или СрезПервых():
Отбор = Новый Структура("КлючЗадания", КлючЗадания);
АктуальныеДанные = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.СрезПоследних(ТекущаяДатаСеанса(), Отбор);
Когда требуется не просто прочитать, а программно изменить или удалить конкретные строки в подчиненном регистре, важно помнить правило платформы: записи подчиненного регистра перезаписываются только целиком по регистратору.
Разберем последовательность действий для такой модификации:
НаборЗаписей и устанавливаем отбор по Регистратор.Прочитать(), модифицируем или удаляем нужные строки в коллекции и вызываем Записать().Посмотрим на пример программной очистки строк по условию:
// 1. Получаем список регистраторов через запрос
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ РАЗЛИЧНЫЕ
| Регистр.Регистратор КАК Регистратор
|ИЗ
| РегистрСведений.ГУ_ЗаданияИнженерамПоДокументам КАК Регистр
|ГДЕ
| Регистр.КлючЗадания = &КлючЗадания";
Запрос.УстановитьПараметр("КлючЗадания", КлючЗадания);
Результат = Запрос.Выполнить().Выгрузить();
// 2. Обрабатываем каждый набор записей по регистратору
Для Каждого Стр Из Результат Цикл
НаборЗаписей = РегистрыСведений.ГУ_ЗаданияИнженерамПоДокументам.СоздатьНаборЗаписей();
НаборЗаписей.Отбор.Регистратор.Установить(Стр.Регистратор);
НаборЗаписей.Прочитать();
Индекс = НаборЗаписей.Количество() - 1;
Пока Индекс >= 0 Цикл
Если НаборЗаписей[Индекс].КлючЗадания = КлючЗадания Тогда
НаборЗаписей.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
НаборЗаписей.Записать();
КонецЦикла;
Если бизнес-логика проектируемой подсистемы предполагает автономное хранение записей, управление которыми должно выполняться построчно или пакетами по конкретным измерениям (без жесткой привязки к проведению документов), проанализируем архитектуру метаданных.
В дереве метаданных конфигуратора откроем свойства регистра сведений и изменим значение свойства Режим записи с Подчинение регистратору на Независимый. После этого отбор по измерениям через НаборЗаписей.Отбор.ИмяИзмерения.Установить(...) станет доступным и отработает корректно без ошибок.