При разработке в среде 1С, особенно в конфигурациях на обычных формах (таких как ЗУП 2.5), начинающие программисты часто сталкиваются с ошибкой "Поле объекта не обнаружено" при попытке получить данные из табличной части документа. Ситуация осложняется тем, что видимые названия закладок на форме могут не совпадать с реальными именами табличных частей в метаданных. В этой статье мы подробно разберем, как правильно обращаться к данным строк, как находить нужные имена реквизитов и как отслеживать изменения значений.
Разберем типичную ошибку. Программист пытается обратиться к реквизиту напрямую через точку от табличной части, например: СсылкаНаОбъект.РаботникиОрганизации.Подразделение. Это действие всегда приводит к ошибке. Почему так происходит? Проанализируем ситуацию: табличная часть — это коллекция строк. У всей коллекции в целом нет реквизита Подразделение; этот реквизит есть у каждой конкретной строки этой коллекции.
Следовательно, прежде чем обратиться к значению, нам нужно получить саму строку. Это можно сделать несколькими способами: перебором в цикле, по индексу или через текущие данные формы.
Если нам нужно проанализировать все строки документа (например, чтобы проверить подразделения у всех сотрудников), мы используем цикл Для каждого. Рассмотрим пример кода, который корректно обращается к реквизитам каждой строки:
// Док - это ссылка на документ или сам объект документа
Для каждого СтрокаТЧ Из Док.РаботникиОрганизации Цикл
ТекущееПодразделение = СтрокаТЧ.Подразделение;
// Здесь можно выполнять проверку или условия
Сообщить("Сотрудник: " + СтрокаТЧ.Сотрудник + ", Подразделение: " + ТекущееПодразделение);
КонецЦикла;
В данном примере СтрокаТЧ на каждой итерации цикла становится объектом типа СтрокаТабличнойЧасти, у которого уже доступны все реквизиты, заданные в конфигураторе (Подразделение, Сотрудник, ТабельныйНомер и т.д.).
Если задача стоит в контексте работы пользователя с формой (например, при нажатии кнопки на форме или в событии изменения ячейки), нам нужно получить строку, на которой в данный момент установлен курсор. В обычных формах для этого используется объект ЭлементыФормы.
Проанализируем шаги для получения данных:
ТекущиеДанные.
// Код внутри модуля формы
ДанныеСтроки = ЭлементыФормы.ТабличноеПолеРаботники.ТекущиеДанные;
Если ДанныеСтроки <> Неопределено Тогда
Подразделение = ДанныеСтроки.Подразделение;
// Дальнейшая логика
КонецЕсли;
Важный момент: всегда проверяйте ТекущиеДанные на Неопределено. Если табличная часть пуста или ни одна строка не выбрана, попытка обращения к реквизиту вызовет аварийное завершение программы.
Часто программисты не могут найти реквизит из-за путаницы в именах. Например, в документе "Прием на работу в организацию" закладка может называться "Сотрудники", а в дереве метаданных эта табличная часть называется РаботникиОрганизации. Реквизит подразделения также может называться ПодразделениеОрганизации.
Чтобы выяснить точное имя, проделаем следующее:
Метаданные():
// Проверим, какие реквизиты есть в ТЧ "РаботникиОрганизации"
Для каждого Реквизит Из Метаданные.Документы.ПриемНаРаботуВОрганизацию.ТабличныеЧасти.РаботникиОрганизации.Реквизиты Цикл
Сообщить(Реквизит.Имя);
КонецЦикла;
Этот метод позволяет точно определить, к какому полю нужно обращаться, и избежать ошибки "Поле объекта не обнаружено".
Рассмотрим ситуацию, когда необходимо узнать, изменилось ли подразделение у сотрудника. Для этого нам нужно сравнить текущее значение в оперативной памяти (в объекте формы) со значением, которое сохранено в базе данных.
Выполним сравнение по следующему алгоритму:
// Предположим, ТекущаяСтрока - это строка, которую мы сейчас редактируем
// Ссылка - это состояние документа в базе данных до записи изменений
Если ЗначениеЗаполнено(Ссылка) Тогда
// Ищем ту же строку в базе по уникальному идентификатору или сотруднику
ПараметрыОтбора = Новый Структура("Сотрудник", ТекущаяСтрока.Сотрудник);
НайденныеСтроки = Ссылка.РаботникиОрганизации.НайтиСтроки(ПараметрыОтбора);
Если НайденныеСтроки.Количество() > 0 Тогда
СтароеПодразделение = НайденныеСтроки[0].Подразделение;
Если ТекущаяСтрока.Подразделение <> СтароеПодразделение Тогда
Сообщить("Подразделение изменилось с " + СтароеПодразделение + " на " + ТекущаяСтрока.Подразделение);
КонецЕсли;
КонецЕсли;
КонецЕсли;
Иногда требуется проверить, встречается ли конкретное подразделение хотя бы в одной строке таблицы. Вместо полного цикла можно использовать метод ВыгрузитьКолонку(). Это более лаконичный способ работы с данными табличной части.
// Получаем массив всех подразделений из ТЧ
МассивПодразделений = ЭтотОбъект.РаботникиОрганизации.ВыгрузитьКолонку("Подразделение");
// Ищем конкретное подразделение в массиве
Индекс = МассивПодразделений.Найти(НужноеПодразделение);
Если Индекс <> Неопределено Тогда
// Подразделение найдено в таблице
КонецЕсли;
Мы выяснили, что для успешного обращения к реквизиту табличной части необходимо:
СсылкаНаОбъект (данные в базе) и Объект (данные в памяти).Найти() или НайтиСтроки() для поиска данных в коллекции.Соблюдение этих правил позволит вам писать надежный код и быстро находить причины ошибок при работе с табличными частями в любых конфигурациях 1С.