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

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

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

Анализ базовой структуры цикла по таблице значений

Для начала рассмотрим стандартный способ обхода таблицы значений. Когда нам нужно проверить условие в каждой строке и, например, пропустить выполнение дальнейших действий для определенных строк, мы используем конструкцию Для Каждого ... Из ... Цикл. Проанализируем пример кода, который часто вызывает затруднения у новичков:


Для Каждого СтрТЗ Из ТЗ Цикл
    Если СтрТЗ.СуммаОстаток > 0 Тогда
        Продолжить;
    КонецЕсли;
    // Дальнейшая логика обработки строки
КонецЦикла;

В данном примере СтрТЗ — это переменная, в которую на каждой итерации помещается объект СтрокаТаблицыЗначений. Обращение к колонке СуммаОстаток происходит через точку. Именно на этом этапе чаще всего возникает ошибка объектного типа.

Выясним причину ошибки «Значение не является значением объектного типа»

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

  1. Некорректная переменная таблицы: Если сама переменная ТЗ по какой-то причине приняла значение Неопределено или Число еще до начала цикла, система может выдать ошибку при попытке входа в цикл или при обращении к элементам внутри него.
  2. Отсутствие колонки: Если в объекте ТаблицаЗначений физически отсутствует колонка с именем СуммаОстаток, обращение СтрТЗ.СуммаОстаток может привести к сбою, хотя чаще 1С выдает «Поле объекта не обнаружено». Однако в сложных выражениях или при использовании оберток ошибка может маскироваться под «объектный тип».
  3. Обращение через точку к примитивному типу: Самая распространенная причина — когда программист пытается «пробросить» обращение дальше. Например, если в колонке лежит число, а код написан так: СтрТЗ.СуммаОстаток.Валюта. Поскольку у числа нет свойства Валюта, возникнет именно эта ошибка.

Диагностика данных в колонках таблицы

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


Для Каждого СтрТЗ Из ТЗ Цикл
    // Проверяем, что за данные в колонке
    ТипДанных = ТипЗнч(СтрТЗ.СуммаОстаток);
    Сообщить("В строке обнаружен тип: " + ТипДанных);
    
    Если СтрТЗ.СуммаОстаток > 0 Тогда
        Продолжить;
    КонецЕсли;
КонецЦикла;

Особое внимание стоит уделить значениям NULL и Неопределено. Если таблица значений была заполнена результатом запроса с использованием ЛЕВОГО СОЕДИНЕНИЯ, то в колонках часто оказывается NULL. Попытка сравнить NULL > 0 не всегда вызывает ошибку «объектного типа», но может привести к логическим сбоям в программе.

Безопасное сравнение и приведение типов

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

Рассмотрим пример с явным приведением типа:


Для Каждого СтрТЗ Из ТЗ Цикл
    // Если в колонке может быть NULL, преобразуем его в 0 для сравнения
    ТекущаяСумма = ?(СтрТЗ.СуммаОстаток = NULL, 0, СтрТЗ.СуммаОстаток);
    
    Если ТекущаяСумма > 0 Тогда
        Продолжить;
    КонецЕсли;
КонецЦикла;

Также хорошей практикой является использование функции Число(), если вы ожидаете числовые данные из текстовых полей, или ЗначениеЗаполнено() для проверки ссылочных типов.

Альтернативные методы работы с таблицей значений

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

Метод Итог()

Если ваша задача — просто получить сумму по колонке, чтобы понять, есть ли там остатки, нет смысла писать цикл. Используйте метод Итог(). Это работает значительно быстрее на больших объемах данных:


// Вместо цикла
ОбщаяСумма = ТЗ.Итог("СуммаОстаток");
Если ОбщаяСумма > 0 Тогда
    // Делаем что-то, если сумма положительная
КонецЕсли;

Метод НайтиСтроки()

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


ПараметрыОтбора = Новый Структура;
ПараметрыОтбора.Вставить("СуммаОстаток", 0);
НужныеСтроки = ТЗ.НайтиСтроки(ПараметрыОтбора);

Для Каждого Стр Из НужныеСтроки Цикл
    // Обрабатываем только строки с нулевым остатком
КонецЦикла;

Рекомендации по созданию таблиц значений

Чтобы избежать ошибок в будущем, проанализируем важность явной типизации колонок. Когда вы создаете таблицу значений программно, старайтесь всегда указывать описание типов для каждой колонки. Это гарантирует, что система не позволит записать в колонку «Сумма» строку или Неопределено, что автоматически снимет проблему ошибок при сравнении в циклах.

Посмотрим на пример правильного создания колонки:


КвалификаторыЧисла = Новый КвалификаторыЧисла(15, 2);
ОписаниеТипаЧисло = Новый ОписаниеТипов("Число", , , КвалификаторыЧисла);
ТЗ.Колонки.Добавить("СуммаОстаток", ОписаниеТипаЧисло);

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

← На главную