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

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

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

Причина возникновения ошибки при обращении к ТекущиеДанные

Проанализируем строку кода, на которой происходит аварийное завершение программы:

ЭлементыФормы.ТабличноеПоле1.ТекущиеДанные.Срок = КонецДня(ТекущаяДата());

Ошибка времени выполнения сообщает о том, что программа пытается обратиться через точку к реквизиту Срок у объекта, который на самом деле объектом не является. В данном случае свойство ЭлементыФормы.ТабличноеПоле1.ТекущиеДанные вернуло значение Неопределено.

Выясним причину, почему ТекущиеДанные содержат Неопределено:

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

Способ 1. Проверка текущих данных на Неопределено

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

Посмотрим на пример безопасной обработки события:


Процедура ТабличноеПоле1ПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    
    СтрокаТабличнойЧасти = ЭлементыФормы.ТабличноеПоле1.ТекущиеДанные;
    
    // Проверяем, существует ли активная строка
    Если СтрокаТабличнойЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если НоваяСтрока И НЕ Копирование Тогда
        Если ТекущаяДата() + 6*3600 < КонецДня(ТекущаяДата()) Тогда
            СтрокаТабличнойЧасти.Срок = КонецДня(ТекущаяДата());
        Иначе
            СтрокаТабличнойЧасти.Срок = КонецДня(ТекущаяДата()) + 10*3600;
        КонецЕсли;
    КонецЕсли;

КонецПроцедуры

Обратите внимание на конструкцию условий: вместо двух раздельных проверок со знаками < и > используем связку Если ... Иначе. Это предотвращает возникновение пограничной ситуации, когда время в точности совпадает с границей условия и ни одна ветка не отрабатывает.

Способ 2. Правильное программное заполнение без вызова событий формы (Рекомендуемый)

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

Разберем по шагам правильную архитектуру программного заполнения:

  1. Выносим бизнес-логику в отдельную процедуру. Создадим процедуру расчета срока, которая принимает строку табличной части как параметр.
  2. Работаем напрямую с коллекцией строк объекта. При программном добавлении или загрузке из файла добавляем строку в саму табличную часть документа (ЭтотОбъект.ИмяТабличнойЧасти), а не манипулируем визуальными элементами формы.

Посмотрим на реализацию разделения логики:


// Универсальная процедура заполнения срока в переданной строке
Процедура ЗаполнитьСрокВСтроке(СтрокаТЧ)
    
    // Вычисляем срок в зависимости от текущего времени
    Если Час(ТекущаяДата()) < 18 Тогда
        СтрокаТЧ.Срок = КонецДня(ТекущаяДата());
    Иначе
        // Перенос на следующий день до 10:00
        СтрокаТЧ.Срок = НачалоДня(ТекущаяДата() + 86400) + 10 * 3600;
    КонецЕсли;

КонецПроцедуры

// Обработчик интерактивного ввода пользователя
Процедура ТабличноеПоле1ПриНачалеРедактирования(Элемент, НоваяСтрока, Копирование)
    
    СтрокаТабличнойЧасти = ЭлементыФормы.ТабличноеПоле1.ТекущиеДанные;
    Если СтрокаТабличнойЧасти = Неопределено Тогда
        Возврат;
    КонецЕсли;
    
    Если НоваяСтрока И НЕ Копирование Тогда
        ЗаполнитьСрокВСтроке(СтрокаТабличнойЧасти);
    КонецЕсли;

КонецПроцедуры

// Программная загрузка или добавление по кнопке
Процедура ПривязатьНовыйНажатие(Элемент)
    
    // Добавляем новую строку напрямую в данные табличной части документа
    НоваяСтрока = ЭтотОбъект.ТабличнаяЧасть1.Добавить();
    
    // Вызываем логику заполнения реквизитов
    ЗаполнитьСрокВСтроке(НоваяСтрока);
    
    // При необходимости позиционируем курсор на новой строке
    ЭлементыФормы.ТабличноеПоле1.ТекущаяСтрока = НоваяСтрока;

КонецПроцедуры

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

← На главную