Как исправить ошибку «Значение не является значением объектного типа» при программной установке отборов в Универсальном отчете?

Программист 1С v8.3 (Обычные формы)
← На главную

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

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

Рассмотрим стандартную ситуацию. Программист пытается установить отбор по определенному полю (например, «Специализация») следующим образом:


ОтборПоКонтрагенту = Отборы.Найти("Специализация");
ОтборПоКонтрагенту.Значение = Справочники.Специализация.НайтиПоКоду("91");

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

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

Правильный алгоритм установки отбора с проверкой

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

Проанализируем исправленный вариант кода, который учитывает возможность отсутствия элемента в коллекции:


// Получаем коллекцию отборов из универсального отчета
Отборы = ОтчетПродажи.УниверсальныйОтчет.ПостроительОтчета.Отбор;

// Пытаемся найти нужное поле
ОтборПоКонтрагенту = Отборы.Найти("Специализация");

// Если поле не найдено в текущих настройках, добавляем его программно
Если ОтборПоКонтрагенту = Неопределено Тогда
    ОтборПоКонтрагенту = Отборы.Добавить("Специализация");
КонецЕсли;

// Теперь, когда мы уверены, что объект существует, устанавливаем параметры
СпециализацияСсылка = Справочники.Специализация.НайтиПоКоду("91");

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

В данном примере мы используем Справочники.Специализация.НайтиПоКоду("91"). Обратите внимание на важный нюанс: если код в справочнике имеет числовой тип, 1С попытается преобразовать строку "91" в число. Однако, если поиск не даст результата, метод вернет Пустую ссылку. Поэтому проверка СпециализацияСсылка.Пустая() критически важна для логики работы отчета, особенно если он запускается автоматически через регламентное задание.

Особенности очистки отборов в Универсальном отчете

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

Это происходит потому, что коллекция отборов в Построителе отчета часто является фиксированной (определяется метаданными запроса). Вместо удаления элементов, мы должны программно их деактивировать. Разберем, как это сделать правильно:


Для каждого ТекущийОтбор Из ОтчетПродажи.УниверсальныйОтчет.ПостроительОтчета.Отбор Цикл
    ТекущийОтбор.Использование = Ложь;
КонецЦикла;

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

Различия между Построителем отчета и СКД

Многие ошибки возникают из-за путаницы между обычными формами (Построитель отчета) и управляемыми формами (Система компоновки данных — СКД). Выясним основные отличия в свойствах объектов отбора:

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

Работа в регламентных заданиях

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

  1. Избегайте использования методов Показать() или диалоговых окон.
  2. Используйте ЗаписьЖурналаРегистрации для логирования проблем с поиском элементов справочников.
  3. Предусмотрите «аварийный» выход из процедуры, если критический отбор (например, по организации) не смог заполниться.

Подводя итог, можно сказать, что решение проблемы «Значение не является значением объектного типа» заключается в дисциплине программирования: всегда проверяйте результат работы метода Найти() и помните об архитектурных особенностях Универсального отчета. Использование связки Найти() -> Если Неопределено Тогда Добавить() гарантирует стабильную работу вашего кода в любых условиях.

← На главную