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