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

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

Обращение к строке табличной части по индексу в 1С

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

Табличная часть в 1С — это коллекция строк, встроенная в объект (документ, справочник, план видов характеристик и другие). Каждая строка имеет нулевой индекс и номер строки, который начинается с единицы. Чтобы обратиться к конкретной строке по индексу, используется оператор квадратных скобок: Объект.Товары[0] вернёт первую строку табличной части «Товары».

Такое обращение нужно, когда известна позиция строки: например, при программном заполнении данных из внешнего источника, при синхронизации двух табличных частей или при обработке результата запроса, где порядок строк совпадает с порядком в табличной части. Важно понимать разницу между индексом (от 0) и номером строки (от 1), потому что путаница между ними — самая частая причина ошибок «Индекс находится за границами массива».

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

Базовый синтаксис обращения по индексу

Объект табличной части поддерживает обращение к строкам через оператор квадратных скобок, как обычная коллекция. Индексация начинается с нуля: первая строка имеет индекс 0, вторая — 1 и так далее.

// Чтение значения из первой строки табличной части "Товары"

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

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

// Изменение значения во второй строке

Объект.Товары[1].Цена = 1500;

Обращение возвращает объект типа «Строка табличной части», через который доступны все реквизиты строки. Можно читать и изменять значения, вызывать методы, связанные со строкой. Изменения вносятся в объект в памяти — чтобы сохранить их в базе, объект нужно записать.

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

Разница между индексом и номером строки

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

// Пользователь указал номер строки 3

НомерОтПользователя = 3;

Индекс = НомерОтПользователя - 1; // обязательная корректировка

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

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

КонецЕсли;

Обратное преобразование тоже часто нужно: при выводе сообщений об ошибках лучше показывать пользователю номер строки, а не индекс, потому что «строка 0» в интерфейсе не существует и вызовет недоумение.

Безопасная проверка границ перед обращением

Перед тем как взять строку по индексу, убедитесь, что табличная часть вообще содержит нужное количество строк. Метод Количество() возвращает число строк, и допустимые индексы лежат в диапазоне от 0 до Количество() - 1.

Функция ПолучитьСтрокуПоИндексу(ТабличнаяЧасть, Индекс)

Если Индекс < 0 Или Индекс >= ТабличнаяЧасть.Количество() Тогда

Возврат Неопределено;

КонецЕсли;

Возврат ТабличнаяЧасть[Индекс];

КонецФункции

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

Порядок безопасного обращения к строке
  1. 1
    Получите количество строк: Всего = Объект.Товары.Количество()
  2. 2
    Проверьте, что индекс в диапазоне от 0 до Всего - 1
  3. 3
    Обратитесь к строке: СтрокаТЧ = Объект.Товары[Индекс]
  4. 4
    Измените или прочитайте реквизиты строки
  5. 5
    Запишите объект, если изменения должны сохраниться в базе

Обращение по индексу в цикле

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

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

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

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

КонецЦикла;

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

// Удаление строк с нулевым количеством — обход с конца

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

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

Если Объект.Товары[ТекИндекс].Количество = 0 Тогда

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

КонецЕсли;

КонецЦикла;

Обращение к строке на управляемой форме

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

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

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

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

ИндексСтроки = Объект.Товары.Индекс(ТекущиеДанные);

// ИндексСтроки — позиция с нуля

КонецЕсли;

Учитывайте, что при включённом отборе строк на форме индекс в отображаемой таблице и индекс в коллекции данных могут не совпадать. Опирайтесь на идентификаторы строк, а не на визуальную позицию.

Альтернативы обращению по индексу

Прямое обращение по индексу — не единственный и не всегда лучший способ получить строку. В зависимости от задачи подходят другие методы коллекции табличной части.

ЗадачаСпособОграничение
Известна позиция строкиТовары[Индекс]Требует проверки границ
Нужна строка с конкретным значением реквизитаТовары.Найти(Значение, "Номенклатура")Возвращает только первую найденную строку
Нужны все строки по условиюТовары.НайтиСтроки(ПараметрыОтбора)Возвращает массив, а не одну строку
Обработать каждую строкуДля Каждого ... ЦиклНет доступа к позиции без дополнительного счётчика
Строка, выбранная пользователем на формеЭлементы.Товары.ТекущиеДанныеРаботает только в контексте формы

Метод НайтиСтроки() с параметрами отбора (структурой «ИмяРеквизита — Значение») обычно предпочтительнее ручного цикла с условиями: он короче и выполняется на уровне платформы. Обращение по индексу оставьте для случаев, когда позиция строки действительно несёт смысл — например, при построчной синхронизации с внешней таблицей значений.

Когда какой способ выбрать

Обращение по индексу Товары[Индекс]

Подходит, когда позиция строки известна и значима: обход по номеру, синхронизация с внешним массивом. Требует проверки границ.

Найти / НайтиСтроки

Подходит для поиска по значениям реквизитов. Не зависит от порядка строк, но не даёт позиции без дополнительного вызова Индекс().

Для Каждого

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

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

Ошибки при работе с индексами строк повторяются из проекта в проект. Большинство из них легко предотвратить, если понимать устройство коллекции табличной части.

Типичные ошибки
01
Использование номера строки как индекса: Товары[СтрокаТЧ.НомерСтроки] — обращение идёт на одну позицию дальше, а для последней строки вызывает исключение. Вычитайте единицу.
02
Обращение к пустой табличной части: Товары[0] при нуле строк сразу падает с ошибкой. Проверяйте Количество() > 0.
03
Удаление строк в прямом цикле по индексу — коллекция сжимается, часть строк пропускается. Обходите с конца.
04
Попытка обратиться по индексу к ТекущиеДанные формы — это отдельный объект, а не коллекция; индекс вычисляется через Индекс() от коллекции Объект.Товары.
05
Изменение строки без записи объекта — правки остаются только в памяти и теряются.

Отдельная группа проблем — обращение к табличной части объекта, полученного через ссылку. Запись Ссылка.Товары[0] на сервере работает (данные читаются из базы), но изменить строку так нельзя: для модификации нужно получить объект через Ссылка.ПолучитьОбъект(), внести изменения и записать.

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

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

ДокОбъект.Товары[0].Количество = 5;

ДокОбъект.Записать();

КонецЕсли;

Проверка результата после изменения строки

После программного изменения строки по индексу убедитесь, что правка применилась и сохранилась. Минимальная проверка — прочитать значение сразу после присвоения и после записи объекта заново из базы.

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

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

Значение реквизита строки сразу после присвоения
Норма

Содержит новое значение

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

Старое значение — присвоение выполнялось не для той строки

Данные после Записать() и повторного чтения объекта
Норма

Изменения присутствуют в базе

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

Изменений нет — объект не был записан или запись откатилась

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

Нумерация непрерывна от 1

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

Пропуски или сдвиг — индексация сбилась в цикле

В отладчике удобно смотреть коллекцию целиком: добавьте в табло выражение Объект.Товары.Количество() и саму строку Объект.Товары[Индекс] — так видно и границы, и содержимое конкретной позиции без пошагового обхода.

Итог

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

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

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

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

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

Чем отличается Товары[Индекс] от Товары.Получить(Индекс)?

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

Почему возникает ошибка «Индекс находится за границами диапазона»?

Индекс меньше нуля или больше либо равен количеству строк. Чаще всего причина в использовании номера строки вместо индекса (номер начинается с 1), в обращении к пустой табличной части или в изменении коллекции внутри цикла. Добавьте проверку Индекс < Товары.Количество() перед обращением.

Как узнать индекс строки, найденной через Найти()?

Передайте найденную строку в метод коллекции Индекс(): ИндексСтроки = Объект.Товары.Индекс(НайденнаяСтрока). Если строка не принадлежит коллекции, метод вернёт -1 — это тоже стоит учитывать в логике.

Можно ли обратиться к строке по индексу в запросе?

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

Работает ли обращение по индексу на тонком клиенте?

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