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