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

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

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

Причина ошибки: обращение к коллекции вместо конкретной строки

Выясним причину возникновения ошибки на распространенном примере. Предположим, в справочнике создана табличная часть Сырье с реквизитами Сырье, Количество и Сумма.

Частая ошибка начинающих разработчиков выглядит следующим образом:


ДоговорЗаполнить.Сырье.Очистить();
ДоговорЗаполнить.Сырье.Добавить();
ДоговорЗаполнить.Сырье.Сырье = ВыборкаСубконтоКт1.СубконтоКт1; // Ошибка!
ДоговорЗаполнить.Сырье.Количество = ВыборкаСубконтоКт1.КоличествоКт;

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

Корректный синтаксис добавления строк в табличную часть

Чтобы правильно заполнить табличную часть, метод Добавить() должен возвращать ссылку на созданную строку в переменную. Через эту переменную выполняется заполнение реквизитов конкретной строки.

Разберем правильный вариант написания кода:


// Очищаем табличную часть перед заполнением
ДоговорЗаполнить.Сырье.Очистить();

// Добавляем новую строку и получаем ссылку на нее
НоваяСтрока = ДоговорЗаполнить.Сырье.Добавить();

// Заполняем реквизиты конкретной строки
НоваяСтрока.Сырье = ВыборкаСубконтоКт1.СубконтоКт1;
НоваяСтрока.Количество = ВыборкаСубконтоКт1.КоличествоКт;
НоваяСтрока.Сумма = ВыборкаСубконтоКт1.Сумма;

Рекомендации по именованию объектов метаданных

Именование реквизита табличной части точно так же, как и сама табличная часть (например, табличная часть Сырье и реквизит Сырье внутри нее), считается нежелательной практикой. Это затрудняет чтение кода и может вызывать путаницу при обращении к свойствам объекта. Рекомендуется давать табличной части имя во множественном числе (СырьеИМатериалы или Материалы), а реквизиту — в единственном (Номенклатура или Сырье).

Другие возможные причины ошибки «Поле объекта не обнаружено»

Если синтаксис работы с табличной частью исправлен, но ошибка продолжается, проанализируем следующие возможные факторы:

  1. Несоответствие объектов метаданных. Проверьте, в какой именно справочник была добавлена табличная часть. Например, если ТЧ создана в справочнике Договоры, а в коде используется обращение к Справочники.ДоговорыКонтрагентов, метод ПолучитьОбъект() вернет объект конфигурации, в котором данная табличная часть отсутствует.
  2. Обращение к ненайденному объекту (Неопределено). Если метод поиска (например, НайтиПоКоду()) не находит элемент в базе, он возвращает пустую ссылку. Вызов ПолучитьОбъект() у пустой ссылки возвращает значение Неопределено. Любая попытка обратиться к свойству переменной со значением Неопределено вызывает аналогичную ошибку. Всегда проверяйте результат поиска перед считыванием объекта:
    
    СсылкаНаДоговор = Справочники.ДоговорыКонтрагентов.НайтиПоКоду(КодДоговора);
    Если ЗначениеЗаполнено(СсылкаНаДоговор) Тогда
        ДоговорОбъект = СсылкаНаДоговор.ПолучитьОбъект();
        // Работа с табличной частью
    Иначе
        // Обработка отсутствия элемента
    КонецЕсли;
    
  3. Кэширование метаданных. При изменении структуры справочников в конфигураторе кэш сеанса или сервера приложений 1С может своевременно не обновиться. Запустите клиентское приложение с параметром /ClearCache или очистите локальный кэш пользователя.

Оптимизация работы с объектами базы данных

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

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


// Получаем объект справочника один раз
ДоговорОбъект = СсылкаНаДоговор.ПолучитьОбъект();
ДоговорОбъект.Сырье.Очистить();

Пока Выборка.Следующий() Цикл
    СтрокаТЧ = ДоговорОбъект.Сырье.Добавить();
    СтрокаТЧ.Сырье = Выборка.СубконтоКт1;
    СтрокаТЧ.Количество = Выборка.КоличествоКт;
    СтрокаТЧ.Сумма = Выборка.Сумма;
КонецЦикла;

// Записываем объект один раз после заполнения
ДоговорОбъект.Записать();
← На главную