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

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

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

Как обратиться к строке и ячейке табличной части документа 1С: перебор строк, доступ по индексу, методы Найти, Итог, примеры кода и типичные ошибки.

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

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

Ниже разобраны все основные приёмы с рабочими примерами кода на встроенном языке 1С, указаны ограничения каждого подхода и типичные ошибки, которые приводят к падению кода или неверным данным.

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

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

Количество строк определяется методом Количество(), индексация начинается с нуля. Первая строка — ДокОбъект.Товары[0], последняя — ДокОбъект.Товары[ДокОбъект.Товары.Количество() - 1]. Обращение по несуществующему индексу вызывает ошибку выполнения, поэтому перед прямым доступом всегда проверяйте, что строки вообще есть.

Каждая строка — объект типа «Строка табличной части», у которого есть реквизиты, объявленные в метаданных, и служебные свойства, например НомерСтроки (нумерация с единицы, в отличие от индекса). Значения читаются и записываются одинаково: Строка.Сумма = Строка.Количество * Строка.Цена;.

Перебор всех строк в цикле

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

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

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

КонецЦикла;

Изменения, внесённые в переменную цикла, сохраняются в объекте, потому что переменная ссылается на саму строку коллекции, а не на её копию. Это важно: присваивать результат не нужно, достаточно изменить реквизиты строки.

Если внутри цикла нужно удалять строки, перебирайте коллекцию с конца по индексу, иначе удаление сдвинет индексы и часть строк будет пропущена:

Для Инд = 1 По ДокОбъект.Товары.Количество() Цикл

Строка = ДокОбъект.Товары[ДокОбъект.Товары.Количество() - Инд];

Если Строка.Количество = 0 Тогда

ДокОбъект.Товары.Удалить(Строка);

КонецЕсли;

КонецЦикла;

Обращение к строке по индексу

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

Если ДокОбъект.Товары.Количество() > 0 Тогда

ПерваяСтрока = ДокОбъект.Товары[0];

ПерваяСтрока.Цена = 100;

КонецЕсли;

Помните о разнице между индексом и номером строки: НомерСтроки начинается с единицы, индекс — с нуля. Чтобы получить строку по её видимому номеру, вычитайте единицу: ДокОбъект.Товары[НомерСтроки - 1].

Поиск строки по условию: Найти и НайтиСтроки

Когда нужна строка с конкретным значением реквизита, используйте встроенные методы поиска. Найти(Значение, ИмяРеквизита) возвращает первую подходящую строку или Неопределено, если ничего не найдено:

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

Если Строка <> Неопределено Тогда

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

КонецЕсли;

Метод НайтиСтроки(СтруктураОтбора) возвращает массив всех строк, подходящих под отбор. Отбор задаётся структурой, где ключ — имя реквизита, а значение — искомое значение:

Отбор = Новый Структура("Склад, СтавкаНДС", СкладОсновной, Ставка20);

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

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

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

КонецЦикла;

Оба метода сравнивают значения на точное равенство — частичное совпадение строк или сравнение «больше/меньше» ими не поддерживается. Для таких условий используйте перебор в цикле с собственной проверкой.

Маршрут решения

Как выбрать действие

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

Агрегирование: итоги, выгрузка и сортировка

Для подсчёта суммы по колонке у коллекции есть метод Итог("ИмяКолонки"). Он работает быстро и не требует цикла:

СуммаДокумента = ДокОбъект.Товары.Итог("Сумма");

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

ТЗ = ДокОбъект.Товары.Выгрузить();

ТЗ.Свернуть("Номенклатура", "Количество, Сумма");

Обратный приём — Загрузить(ТЗ) — полностью заменяет содержимое табличной части данными таблицы значений. Состав колонок должен совпадать с реквизитами табличной части, лишние колонки вызовут ошибку.

Доступ к табличной части в форме документа

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

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

Если ТекущиеДанные <> Неопределено Тогда

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

КонецЕсли;

В тонком клиенте и веб-клиенте действует разделение контекстов: код с директивой &НаКлиенте работает с данными формы, но не может выполнять запросы к базе. Для обращения к серверным данным создают процедуру &НаСервере и передают в неё нужные значения. Идентификатор текущей строки (Элементы.Товары.ТекущаяСтрока) позволяет найти строку на сервере: Объект.Товары.НайтиПоИдентификатору(ИдентификаторСтроки).

Порядок действий
  1. 1
    Откройте конфигуратор и найдите имя табличной части в метаданных документа
  2. 2
    В коде обратитесь к коллекции: ДокОбъект.ИмяТабличнойЧасти
  3. 3
    Выберите способ доступа: цикл, индекс, Найти() или НайтиСтроки()
  4. 4
    Измените или прочитайте реквизиты строки через точку
  5. 5
    Вызовите ДокОбъект.Записать(), если изменения нужно сохранить в базе
  6. 6
    Проверьте результат, открыв документ в пользовательском режиме

Проверка результата и типичные ошибки

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

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

Типичные ошибки
01
Обращение по индексу без проверки Количество() — ошибка выполнения на пустой табличной части
02
Отсутствие проверки результата Найти() на Неопределено — падение при обращении к реквизиту
03
Удаление строк в прямом цикле Для Каждого — пропуск строк из-за сдвига индексов
04
Использование синонима вместо имени табличной части из метаданных — ошибка 'Поле не обнаружено'
05
Изменение строк без вызова Записать() — данные не сохраняются в базе
06
Путаница между НомерСтроки (с 1) и индексом (с 0) — изменяется не та строка
Контрольные точки

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

Значения в строках документа
Норма

Данные соответствуют внесённым изменениям

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

Строки не изменились — объект не записан

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

Движения пересчитаны после перепроведения

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

Движения устарели и не совпадают с табличной частью

Поведение кода на пустой табличной части
Норма

Код завершается без ошибок

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

Ошибка обращения по индексу

Частые вопросы

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

Откройте конфигуратор, найдите нужный документ в дереве метаданных и разверните ветку «Табличные части». В коде используется именно имя (идентификатор), а не синоним, который виден пользователю. Имена вроде «Товары», «Услуги», «Оплата» — типичные примеры.

Чем отличается НомерСтроки от индекса строки?

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

Почему Найти() возвращает Неопределено, хотя значение в строке есть?

Метод сравнивает значения на строгое равенство с учётом типа. Частые причины — различие в типах (строка против числа), лишние пробелы в строковом значении или поиск ссылки по её строковому представлению вместо самой ссылки.

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

Технически объект можно открыть, изменить и записать в режиме Записать(), но движения по регистрам при этом не обновятся. Корректный путь — изменить строки и перепровести документ методом Записать(РежимЗаписиДокумента.Проведение), чтобы движения пересчитались.

Как обратиться к табличной части документа, который ещё не записан?

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

Можно ли обратиться к табличной части через запрос?

Да, в запросе табличная часть доступна как виртуальная таблица вида Документ.РеализацияТоваровУслуг.Товары. Это удобно для чтения и анализа, но запрос не может изменять данные — для модификации используется объектная модель.

Итог

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

Строки табличной части доступны через ДокОбъект.ИмяТабличнойЧасти: перебор циклом, по индексу (с нуля, с проверкой Количество), поиском Найти() или НайтиСтроки(). Реквизиты строки читаются и меняются через точку, а результат сохраняется только после Записать() с последующим перепроведением, если затронуты движения.