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