К статье
Практический материал

Разработка и Конфигурация · 11 мин

Как получить доступ к табличной части документа 1С

Как обратиться к табличной части документа в 1С: перебор строк, поиск, итоги, выборка запросом. Примеры кода для 8.2 и 8.3, типичные ошибки и FAQ.

Табличная часть документа в 1С — это коллекция строк, связанных с конкретным объектом: товары в накладной, услуги в акте, сотрудники в начислении зарплаты. Обращение к ней — базовая операция при разработке модулей, обработок и расширений. Способ доступа зависит от того, где выполняется код: в модуле объекта, в форме документа, во внешней обработке или в запросе.

Ошибки при работе с табличными частями встречаются чаще всего: путают реквизит объекта с данными формы, пытаются перебрать строки у ссылки, не загрузив объект, или теряют изменения, записывая документ в неправильном режиме. Разобравшись в механике, вы сможете читать, изменять и анализировать строки документов уверенно и без побочных эффектов.

Ниже рассмотрены основные сценарии: обращение через объект и через форму, перебор и поиск строк, получение итогов, выборка запросом и работа с табличными частями в клиент-серверном режиме. Примеры даны на встроенном языке 1С:Предприятие 8.3, но большинство подходов работает и в 8.2.

Что такое табличная часть и где она хранится

Табличная часть — это подчинённая коллекция данных внутри объекта конфигурации. У документа «Реализация товаров и услуг» это обычно табличные части «Товары» и «Услуги», у кадрового приказа — список сотрудников. Физически каждая табличная часть хранится в отдельной таблице базы данных, связанной с документом по ссылке.

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

Имена табличных частей задаются в конфигураторе на закладке «Данные» документа. Чтобы узнать точное имя, откройте конфигуратор, найдите нужный документ и посмотрите список его табличных частей — обращаться в коде нужно именно по этим именам, а не по синонимам, которые видит пользователь.

Обращение к табличной части через объект документа

Самый распространённый сценарий — работа в модуле документа, обработке проведения или серверной процедуре. Здесь табличная часть доступна как свойство объекта. Внутри модуля объекта достаточно написать имя табличной части напрямую, извне — через переменную объекта.

Если у вас есть только ссылка на документ, сначала получите объект. Без этого попытка обратиться к табличной части вызовет ошибку «Поле объекта не обнаружено», потому что у ссылки такого свойства нет.

ДокументОбъект = СсылкаНаДокумент.ПолучитьОбъект();

Для Каждого СтрокаТовары Из ДокументОбъект.Товары Цикл

Сообщить(Строка(СтрокаТовары.Номенклатура) + " — " + СтрокаТовары.Количество);

КонецЦикла;

Внутри модуля самого документа (например, в ОбработкаПроведения) обращение ещё проще — объектом является текущий контекст:

Для Каждого СтрокаТовары Из Товары Цикл

// СтрокаТовары.Номенклатура, СтрокаТовары.Сумма и т.д.

КонецЦикла;

Помните: метод ПолучитьОбъект() загружает документ целиком и открывает его для изменения. Если документ в этот момент редактирует другой пользователь, вы получите ошибку блокировки. Для чтения без изменения часто выгоднее использовать запрос — об этом ниже.

Работа с табличной частью в форме документа

В модуле формы табличная часть доступна через реквизит формы «Объект». Обращение выглядит как Объект.Товары, и тип этой коллекции — ДанныеФормыКоллекция, а не ТабличнаяЧасть. У неё похожие, но не идентичные методы: например, есть Итог() для вычисления суммы по колонке прямо на клиенте.

Типичная задача в форме — пересчитать сумму строки при изменении количества или цены. Для этого используются обработчики событий таблицы формы, а текущая строка получается через Элементы.Товары.ТекущиеДанные:

&НаКлиенте

Процедура ТоварыКоличествоПриИзменении(Элемент)

СтрокаТаблицы = Элементы.Товары.ТекущиеДанные;

Если СтрокаТаблицы = Неопределено Тогда

Возврат;

КонецЕсли;

СтрокаТаблицы.Сумма = СтрокаТаблицы.Количество * СтрокаТаблицы.Цена;

КонецПроцедуры

Обратите внимание на проверку на Неопределено: если таблица пустая или фокус не установлен, ТекущиеДанные вернёт Неопределено, и обращение к полям вызовет ошибку. Это одна из самых частых причин падения клиентских процедур.

Перебор, поиск и добавление строк

Перебор всех строк выполняется циклом «Для Каждого». Если нужно найти строки по условию, используйте метод НайтиСтроки() со структурой отбора — он возвращает массив найденных строк. Для проверки существования хотя бы одной строки удобен метод Найти(), который возвращает строку или Неопределено.

// Поиск строк по отбору

Отбор = Новый Структура("Номенклатура", ИскомыйТовар);

НайденныеСтроки = ДокументОбъект.Товары.НайтиСтроки(Отбор);

Для Каждого СтрокаТовары Из НайденныеСтроки Цикл

СтрокаТовары.Цена = НоваяЦена;

КонецЦикла;

// Добавление новой строки

НоваяСтрока = ДокументОбъект.Товары.Добавить();

НоваяСтрока.Номенклатура = ИскомыйТовар;

НоваяСтрока.Количество = 1;

Для обращения к строке по номеру используйте индекс (нумерация с нуля) или метод Получить(). Методы Количество() и Итог("Сумма") позволяют быстро получить размер коллекции и сумму по числовой колонке без цикла.

Порядок изменения табличной части из внешней обработки
  1. 1
    Получите объект: ДокументОбъект = Ссылка.ПолучитьОбъект()
  2. 2
    Найдите или добавьте нужные строки табличной части
  3. 3
    Измените значения реквизитов строк
  4. 4
    Запишите документ: ДокументОбъект.Записать() или Записать(РежимЗаписиДокумента.Проведение)
  5. 5
    Проверьте результат, открыв документ в пользовательском режиме

Получение данных табличной части запросом

Когда нужно только прочитать данные — для отчёта, анализа или выгрузки — запрос к табличной части эффективнее загрузки объекта. Каждая табличная часть документа доступна в запросе как таблица вида Документ.ИмяДокумента.ИмяТабличнойЧасти.

ВЫБРАТЬ

РеализацияТовары.Номенклатура КАК Номенклатура,

СУММА(РеализацияТовары.Количество) КАК Количество,

СУММА(РеализацияТовары.Сумма) КАК Сумма

ИЗ

Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТовары

ГДЕ

РеализацияТовары.Ссылка = &Ссылка

СГРУППИРОВАТЬ ПО

РеализацияТовары.Номенклатура

Запрос не блокирует документ и не загружает объект в память, поэтому это предпочтительный способ массового чтения. Кроме того, в запросе можно соединить табличную часть со справочниками и регистрами, сразу получив расшифровку по характеристикам, складам или договорам.

Учтите: запросом нельзя изменить данные — для записи всё равно потребуется объект. Смешанный подход тоже рабочий: запросом находите нужные документы и строки, затем загружаете объекты только тех документов, которые реально нужно изменить.

Способы доступа к табличной части

Через объект (ПолучитьОбъект)

Подходит для чтения и изменения. Блокирует документ, медленнее при массовой обработке.

Запрос к табличной части

Быстрое чтение и агрегация без блокировок. Не позволяет изменять данные.

Через форму (Объект.Товары)

Для интерактивной работы пользователя. Только в контексте открытой формы.

Типичные ошибки и как их избежать

Первая и самая частая ошибка — обращение к табличной части через ссылку: Ссылка.Товары. У ссылки такого свойства нет, платформа выдаст «Поле объекта не обнаружено (Товары)». Решение — ПолучитьОбъект() или запрос.

Вторая группа ошибок связана с записью. Если вы изменили строки табличной части, но забыли вызвать Записать(), изменения потеряются без всякого предупреждения. Обратная ситуация — запись проведённого документа методом Записать() без указания режима: платформа попытается выполнить проведение, и при ошибках проведения запись не выполнится. Для технических изменений без перепроведения используйте РежимЗаписиДокумента.Запись.

Третья типичная проблема — удаление строк внутри цикла перебора. При удалении текущей строки индексация сдвигается, и часть строк пропускается. Безопасные варианты: собрать строки для удаления в массив и удалить после цикла, либо перебирать коллекцию в обратном порядке по индексу.

Типичные ошибки
01
Обращение Ссылка.Товары вместо ПолучитьОбъект().Товары — ошибка «Поле объекта не обнаружено»
02
Изменение строк без вызова Записать() — данные теряются молча
03
Удаление строк внутри цикла перебора — часть строк пропускается
04
Обращение к ТекущиеДанные без проверки на Неопределено — падение при пустой таблице
05
Использование ПолучитьОбъект() в цикле по тысячам документов — резкое падение производительности

Проверка результата и границы безопасной работы

После программного изменения табличной части проверьте результат двумя способами. Во-первых, откройте документ в пользовательском режиме и убедитесь, что строки и итоговые суммы соответствуют ожиданиям. Во-вторых, если документ проведён, проверьте движения по регистрам — изменение табличной части без перепроведения приведёт к расхождению данных документа и регистров.

Любые массовые обработки табличных частей сначала тестируйте на копии базы. Особенно это касается обработок, изменяющих цены, количества или удаляющих строки: откатить такие изменения без резервной копии невозможно. Перед запуском массовой обработки в рабочей базе сделайте выгрузку или убедитесь в наличии свежей резервной копии.

В клиент-серверном режиме избегайте передачи всей табличной части между клиентом и сервером в цикле: каждый вызов сервера — это сетевой обмен. Собирайте данные пакетно, выполняйте обработку целиком в серверной процедуре и возвращайте только результат.

Контрольные точки

Как проверить результат

Содержимое табличной части в форме документа
Норма

Строки и суммы соответствуют внесённым изменениям

Тревожный признак

Изменения отсутствуют — вероятно, не вызван Записать()

Движения документа по регистрам
Норма

Проводки соответствуют новому содержимому строк

Тревожный признак

Движения от старой версии — документ не перепроведён

Повторный запуск обработки
Норма

Обработка не вносит дублирующих изменений

Тревожный признак

Строки дублируются — нет проверки существования перед добавлением

Частые вопросы о доступе к табличным частям

Как узнать количество строк в табличной части документа?

Вызовите метод Количество(): ДокументОбъект.Товары.Количество(). В форме аналогично — Объект.Товары.Количество(). Для проверки пустоты удобнее сравнение с нулём, чем перебор строк.

Можно ли обратиться к табличной части документа, не открывая объект?

Да, для чтения используйте запрос к таблице Документ.ИмяДокумента.ИмяТабличнойЧасти с отбором по ссылке. Это быстрее и не блокирует документ. Для изменения данных объект получить придётся — запросы в 1С работают только на чтение.

Почему возникает ошибка «Поле объекта не обнаружено (Товары)»?

Чаще всего вы обращаетесь к табличной части через ссылку, а не через объект, либо имя табличной части указано неверно. Проверьте точное имя в конфигураторе на закладке «Данные» документа и убедитесь, что используете ПолучитьОбъект().

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

Используйте метод Очистить(): ДокументОбъект.Товары.Очистить(), затем запишите документ. Это безопаснее, чем удаление строк в цикле, где легко нарушить индексацию коллекции.

Как получить сумму по колонке табличной части без цикла?

Метод Итог("ИмяКолонки") вернёт сумму по числовой колонке: ДокументОбъект.Товары.Итог("Сумма"). В форме тот же метод доступен у Объект.Товары и работает на клиенте без обращения к серверу.

Чем отличается ТекущиеДанные от ТекущаяСтрока в таблице формы?

ТекущиеДанные — это объект с данными строки, из которого можно читать и в который можно писать значения реквизитов. ТекущаяСтрока — только идентификатор (номер) строки, по которому данные ещё нужно получить через НайтиПоИдентификатору().

Итог

Что важно запомнить

Табличная часть доступна через объект документа (ДокументОбъект.Товары), в форме — через Объект.Товары, для чтения без блокировок — через запрос. Изменения фиксируются методом Записать(), а массовые обработки проводите только после теста на копии базы.