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

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

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

Разбираем ошибку контекста: Объект и ТекущийОбъект

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


Запрос.УстановитьПараметр("ФизическоеЛицо", Объект.Состав.ФизическоеЛицо.Выгрузить());

Эта ошибка возникает из-за непонимания архитектуры управляемых форм. В контексте управляемой формы реквизит Объект имеет тип ДанныеФормыСтруктура. Это легковесное представление данных, предназначенное для клиент-серверного взаимодействия, и оно не поддерживает методы реальных прикладных объектов базы данных, такие как выгрузка колонок.

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


Запрос.УстановитьПараметр("ФизическоеЛицо", ТекущийОбъект.Состав.ВыгрузитьКолонку("ФизическоеЛицо"));

Используя ТекущийОбъект, мы получаем полноценный доступ к методу ВыгрузитьКолонку табличной части, формируем массив физических лиц и передаем его параметром в запрос.

Особенности использования метода НайтиСтроки

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


ИскомыеСтроки = ТекущийОбъект.Зарплата.НайтиСтроки("ФизическоеЛицо", Выборка.ФизическоеЛицо);

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


ИскомыеСтроки = ТекущийОбъект.Зарплата.НайтиСтроки(Новый Структура("ФизическоеЛицо", Выборка.ФизическоеЛицо));

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

Оптимизация запросов и фильтрация виртуальных таблиц

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

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

  1. Фильтрация через параметры виртуальной таблицы. Никогда не накладывайте фильтр по измерениям в секции ГДЕ основного запроса, если обращаетесь к виртуальным таблицам (остатки, срезы). В противном случае платформа сначала получит весь массив данных из базы, а только потом обрежет его. Правильно передавать условия внутрь параметров таблицы: РегистрСведений.КадроваяИсторияСотрудников.СрезПоследних(, ФизическоеЛицо В (&ФизическоеЛицо)).
  2. Обработка дублей в Срезе последних. Срез последних вычисляет актуальные записи в разрезе всех измерений регистра. Если у регистра есть дополнительные измерения (например, зарплатный проект или организация), и по одному физическому лицу есть записи с разными проектами, срез вернет их все. Группировка СГРУППИРОВАТЬ ПО в конце запроса не спасет от задвоения. Необходимо либо указывать точные условия отбора по всем лишним измерениям, либо получать уникальные записи с помощью дополнительных временных таблиц и функции МАКСИМУМ по периоду.
  3. Обработка пустых значений при соединениях. При использовании левого соединения ЛЕВОЕ СОЕДИНЕНИЕ, если записи в подчиненной таблице (например, счетах) не найдены, платформа вернет NULL. Чтобы в коде не выпадали ошибки несовпадения типов, используйте функцию ЕСТЬNULL в запросе: ЕСТЬNULL(Таблица.Поле, ЗначениеПоУмолчанию).

Итоговый алгоритм обработки

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


Пока Выборка.Следующий() Цикл
    Если ТекущийОбъект.ЗарплатныйПроект <> Выборка.МестоВыплаты Тогда
        Отказ = Истина;
        Сообщить("Место выплаты не совпадает для сотрудника: " + Выборка.ФизическоеЛицо);
    Иначе
        ИскомыеСтроки = ТекущийОбъект.Зарплата.НайтиСтроки(Новый Структура("ФизическоеЛицо", Выборка.ФизическоеЛицо));
        Для Каждого ИскомаяСтрока Из ИскомыеСтроки Цикл
            Если ИскомаяСтрока.НомерЛицевогоСчета <> Выборка.НомерЛицевогоСчета Тогда
                Отказ = Истина;
                Сообщить("Лицевой счет не используется! Указан неверный счет: " + ИскомаяСтрока.НомерЛицевогоСчета);
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
КонецЦикла;

Обратите внимание на использование конструкции Иначе вместо избыточного ИначеЕсли при поиске строк. Это позволяет сделать код чище и логичнее. Следуя этим рекомендациям, вы сможете создавать надежные проверки объектов перед их записью в базу данных, избегая стандартных подводных камней платформы 1С.

← На главную