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

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

Как получить строку табличной части в 1С

Как получить строку табличной части в 1С: обращение по индексу, поиск по условию, перебор строк, работа с текущей строкой на форме. Примеры кода и типичные ошибки.

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

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

Ниже разобраны основные способы с примерами кода на встроенном языке, особенности работы в управляемых и обычных формах, а также проверки, которые стоит выполнять до и после обращения к строке.

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

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

// Получение первой строки табличной части "Товары"

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

СуммаСтроки = СтрокаТЧ.Сумма;

// Получение последней строки

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

СтрокаТЧ = Объект.Товары[ИндексПоследней];

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

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

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

Иначе

// Табличная часть пуста — обрабатываем ситуацию

КонецЕсли;

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

Поиск строки по условию

Когда известно значение одного или нескольких реквизитов, строку находят методом НайтиСтроки(). Он принимает структуру с отбором и возвращает массив всех подходящих строк — даже если подошла только одна.

Отбор = Новый Структура;

Отбор.Вставить("Номенклатура", ИскомаяНоменклатура);

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

Если НайденныеСтроки.Количество() > 0 Тогда

СтрокаТЧ = НайденныеСтроки[0];

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

Иначе

// Строки с такой номенклатурой нет — можно добавить новую

КонецЕсли;

Частая ошибка — обращаться к НайденныеСтроки[0] без проверки, что массив не пуст. Если совпадений нет, такая попытка завершится ошибкой. Метод Найти() для табличных частей работает иначе: он ищет по одному значению в одной колонке и возвращает строку или Неопределено.

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

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

// Строка найдена, работаем с ней

КонецЕсли;

Типичные ошибки
01
Обращение к НайденныеСтроки[0] без проверки Количество() — ошибка при пустом результате поиска
02
Использование Найти() и сравнение результата с нулём вместо Неопределено — условие работает непредсказуемо
03
Поиск по индексу строки, полученному на форме, после пересортировки табличной части — индекс уже указывает на другую строку

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

Если обработать нужно каждую строку, используйте цикл Для Каждого. Это самый читаемый и безопасный способ обхода коллекции, когда не требуется знать индекс строки.

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

СтрокаТЧ.СуммаНДС = СтрокаТЧ.Сумма * 20 / 120;

КонецЦикла;

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

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

СтрокаТЧ = Объект.Товары[Индекс];

Сообщить("Строка " + (Индекс + 1) + ": " + СтрокаТЧ.Номенклатура);

КонецЦикла;

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

Получение текущей строки на форме

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

&НаКлиенте

Процедура ТоварыПриАктивизацииСтроки(Элемент)

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

Если ТекущаяСтрока = Неопределено Тогда

Возврат; // Таблица пуста, активной строки нет

КонецЕсли;

Сообщить("Выбран товар: " + ТекущаяСтрока.Номенклатура);

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

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

Разница между данными формы и объектом

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

Добавление новой строки и получение ссылки на неё

Метод Добавить() возвращает созданную строку, поэтому отдельно «получать» её не нужно — ссылка на строку сохраняется в переменную сразу при добавлении.

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

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

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

На форме после программного добавления полезно установить новую строку активной, чтобы пользователь видел результат. Для этого элементу формы присваивают идентификатор добавленной строки через метод ПолучитьИдентификатор() для данных формы.

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

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

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

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

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

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

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

Результат НайтиСтроки()
Норма

Массив содержит хотя бы один элемент, реквизиты строки соответствуют отбору

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

Массив пуст или строка найдена, но реквизиты отличаются от условия поиска

ТекущиеДанные на форме
Норма

Значение отлично от Неопределено, реквизиты читаются без ошибок

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

Неопределено при пустой таблице или снятом фокусе

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

Индекс в диапазоне от 0 до Количество()-1

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

Ошибка «Индекс находится за границами массива»

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

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

У строки табличной части объекта есть свойство НомерСтроки, доступное в цикле или после поиска. Нумерация начинается с единицы. Если строка получена по индексу, номер равен индексу плюс один.

Чем отличается Найти() от НайтиСтроки()?

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

Почему ТекущиеДанные равно Неопределено?

Это происходит, когда таблица пуста, фокус находится не в ней или строки ещё не загружены. Всегда проверяйте ТекущиеДанные на Неопределено перед обращением к реквизитам строки.

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

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

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

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

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

Используйте свойство Элементы.Товары.ВыделенныеСтроки — оно содержит массив идентификаторов. По каждому идентификатору данные строки получают методом Объект.Товары.НайтиПоИдентификатору().

Итог

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

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