При разработке в среде 1С:Предприятие 8 часто возникает необходимость собрать данные из документа в один контейнер, например, в Структура, для последующей передачи на сервер, в другую функцию или для формирования параметров печати. Однако попытка прямого обращения к реквизиту табличной части через точку от имени самой таблицы часто приводит к ошибке «Поле объекта не обнаружено». В этой статье мы подробно разберем, почему это происходит, и рассмотрим правильные способы получения данных.
Разберем ситуацию, с которой столкнулся автор темы. Попытка выполнить код Структура.Вставить("Math", Док_Курсы.Летние.Математика) ошибочна по своей сути. Проанализируем структуру объектов 1С:
Док_Курсы — это объект (или ссылка) документа.Летние — это табличная часть, которая представляет собой коллекцию строк.Математика — это реквизит строки этой табличной части.Когда мы обращаемся к Док_Курсы.Летние, платформа возвращает нам всю коллекцию (таблицу) целиком. У самой таблицы (объекта коллекции) нет свойства Математика, оно есть только у конкретных строк, входящих в эту таблицу. Представьте себе таблицу в Excel: вы не можете спросить у всей таблицы «какое значение в колонке B?», не уточнив номер строки. Именно поэтому система выдает ошибку, так как пытается найти поле Математика непосредственно в объекте коллекции ТабличнаяЧасть.
Если нашей задачей является получение всех значений из определенной колонки табличной части и сохранение их в структуру, мы должны использовать специализированные методы для работы с коллекциями. Самым простым и эффективным методом для ДокументОбъект является ВыгрузитьКолонку(). Этот метод создает Массив, содержащий все значения указанного поля.
Рассмотрим пример правильного кода:
// Предположим, что Док_Курсы — это объект документа
МассивЗначений = Док_Курсы.Летние.ВыгрузитьКолонку("Математика");
Структура.Вставить("Math", МассивЗначений);
В данном случае в структуре под ключом Math будет храниться объект типа Массив. Это важно учитывать при дальнейшем чтении данных из структуры.
Иногда при использовании метода ВыгрузитьКолонку() разработчик может столкнуться с новой ошибкой: «Метод объекта не обнаружен (ВыгрузитьКолонку)». Выясним причину этой ситуации. В 1С существует принципиальная разница между типами ДокументСсылка и ДокументОбъект.
У переменной типа Ссылка доступ к табличной части ограничен. Мы можем перебрать строки таблицы в цикле Для каждого, но у коллекции табличной части в контексте ссылки отсутствуют методы манипуляции данными, такие как Выгрузить() или ВыгрузитьКолонку(). Чтобы воспользоваться этими методами, необходимо получить объект документа.
Разберем по шагам, как это сделать:
// Если у нас есть только ссылка на документ
ДокСсылка = СсылкаНаДокумент;
// Получаем объект документа (внимание: это требует обращения к БД и занимает ресурсы)
ДокОбъект = ДокСсылка.ПолучитьОбъект();
// Теперь метод ВыгрузитьКолонку будет доступен
МассивДанных = ДокОбъект.Летние.ВыгрузитьКолонку("Математика");
Структура.Вставить("Math", МассивДанных);
Важный совет: Если вам нужно только прочитать данные одной колонки, получение всего объекта (ПолучитьОбъект()) является избыточным и непроизводительным. В таких случаях рекомендуется использовать запросы.
Проанализируем ситуацию, если код выполняется в модуле управляемой формы. В этом контексте табличная часть представлена типом ДанныеФормыКоллекция. У этого типа данных нет метода ВыгрузитьКолонку().
Если нам нужно собрать данные из таблицы на клиенте или в серверном методе формы без обращения к базе данных, мы можем использовать обход в цикле:
МассивЗначений = Новый Массив;
Для Каждого СтрокаТЧ Из Объект.Летние Цикл
МассивЗначений.Добавить(СтрокаТЧ.Математика);
КонецЦикла;
Структура.Вставить("Math", МассивЗначений);
Этот способ универсален и работает как на клиенте, так и на сервере, независимо от того, является ли переменная объектом или данными формы.
Для получения данных из табличных частей наиболее правильным с точки зрения производительности считается использование запросов. Это позволяет избежать загрузки лишних данных в память (весь документ со всеми ТЧ) и сразу получить нужный результат.
Посмотрим на пример реализации:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| КурсыЛетние.Математика КАК ЗначениеПоля
|ИЗ
| Документ.Курсы.Летние КАК КурсыЛетние
|ГДЕ
| КурсыЛетние.Ссылка = &Ссылка";
Запрос.УстановитьПараметр("Ссылка", Док_Курсы_Ссылка);
РезультатЗапроса = Запрос.Выполнить();
// Выгружаем результат в массив через промежуточную таблицу значений
МассивМатематика = РезультатЗапроса.Выгрузить().ВыгрузитьКолонку("ЗначениеПоля");
Структура.Вставить("Math", МассивМатематика);
Этот метод работает максимально быстро, особенно если в табличной части документа сотни или тысячи строк.
Подведем итоги нашего анализа. Чтобы успешно записать данные табличной части в структуру, нужно четко понимать, в каком контексте исполняется код и какой объем данных требуется получить.
Основные правила:
ТЧ.ИмяРеквизита — ошибка).ДокументОбъект используйте ТЧ.ВыгрузитьКолонку("Имя").ДокументСсылка, либо получите объект через ПолучитьОбъект(), либо используйте Запрос.ДанныеФормыКоллекция) используйте цикл Для каждого для заполнения массива.Структура при такой записи попадает Массив. Если вам нужно только одно значение (например, из первой строки), обращайтесь по индексу: Док_Курсы.Летние[0].Математика.Используя эти методы, вы сможете гибко управлять данными документов и избегать распространенных ошибок типизации в 1С.