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

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

С какого значения начинается индексирование элементов коллекции в 1С

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

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

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

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

Как устроена индексация в 1С

Встроенный язык 1С использует нулевую (zero-based) индексацию: отсчёт позиций в коллекции ведётся от нуля. Это соглашение закреплено на уровне платформы и одинаково работает в толстом, тонком и веб-клиенте, а также на сервере.

Для любой коллекции, поддерживающей доступ по индексу, действует формула: допустимые индексы лежат в диапазоне от 0 до Количество() - 1. Попытка обратиться к элементу с индексом, равным количеству элементов, вызовет ошибку выполнения.

bsl
Массив = Новый Массив;
Массив.Добавить("Первый");
Массив.Добавить("Второй");
Массив.Добавить("Третий");

Сообщить(Массив[0]); // "Первый"
Сообщить(Массив[2]); // "Третий"
Сообщить(Массив.ВГраница()); // 2 — индекс последнего элемента

Индексация в основных коллекциях

Правило «с нуля» действует единообразно, но способы обращения к элементам различаются в зависимости от типа коллекции.

Массив

Доступ по квадратным скобкам: Массив[0] — первый элемент. Метод ВГраница() возвращает индекс последнего элемента, что удобно для циклов от конца к началу. Методы Вставить() и Удалить() также принимают индекс с отсчётом от нуля.

Таблица значений и табличная часть

Строки таблицы значений доступны по индексу: ТаблицаЗначений[0] — первая строка. То же справедливо для табличных частей документов и справочников: Документ.Товары[0] — первая строка табличной части. При этом свойство НомерСтроки у этой же строки будет равно 1.

Список значений и дерево значений

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

Индекс и номер строки: в чём разница

Главный источник ошибок — смешение программного индекса и пользовательского номера строки. НомерСтроки у строки табличной части начинается с 1 и отображается пользователю в интерфейсе. Индекс этой же строки в коллекции — 0. Связь простая: НомерСтроки = Индекс + 1, но полагаться на неё стоит осторожно.

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

Индекс против номера строки

Индекс (с 0)

Используется в коде для доступа к элементу: Таблица[0]. Всегда отражает текущую позицию в коллекции.

НомерСтроки (с 1)

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

Индекс() метод

ТаблицаЗначений.Индекс(Строка) возвращает позицию строки с отсчётом от 0 или -1, если строка не найдена.

Безопасное обращение к элементам по индексу

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

Порядок безопасного обращения
  1. 1
    Проверьте, что коллекция существует и заполнена: Количество() > 0.
  2. 2
    Убедитесь, что индекс в диапазоне от 0 до Количество() - 1.
  3. 3
    Для поиска элемента используйте Найти() или НайтиСтроки() — они не выбрасывают исключение при отсутствии результата.
  4. 4
    При обходе предпочитайте цикл Для Каждого — он исключает ошибки индексации.
  5. 5
    Если нужен цикл по индексу, используйте Для Инд = 0 По Коллекция.Количество() - 1 Цикл.
bsl
Если ТаблицаТоваров.Количество() > 0 Тогда
    ПерваяСтрока = ТаблицаТоваров[0];
КонецЕсли;

// Обход по индексу с конца (для безопасного удаления строк)
Для Инд = 0 По ТаблицаТоваров.Количество() - 1 Цикл
    Строка = ТаблицаТоваров[ТаблицаТоваров.Количество() - 1 - Инд];
    Если Строка.Сумма = 0 Тогда
        ТаблицаТоваров.Удалить(Строка);
    КонецЕсли;
КонецЦикла;

Типичные ошибки при работе с индексами

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

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

Как проверить корректность кода

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

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

Обход коллекции в цикле
Норма

Обработаны все элементы, включая первый и последний

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

Первый элемент пропущен или ошибка на последней итерации — цикл начат с 1

Удаление строк
Норма

Удалены все строки, удовлетворяющие условию

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

Часть подходящих строк осталась — удаление шло в прямом цикле по индексу

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

Перед обращением есть проверка границ

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

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

Работа с табличной частью
Норма

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

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

Строка определяется через НомерСтроки - 1 без проверки сортировки

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

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

С какого значения начинается индекс массива в 1С?

С нуля. Первый элемент — Массив[0], последний — Массив[Массив.ВГраница()]. Метод ВГраница() возвращает именно индекс последнего элемента, а не количество.

Почему номер строки табличной части начинается с 1, а индекс с 0?

НомерСтроки — это пользовательский реквизит, он показывается в интерфейсе и хранится в данных. Индекс — внутренняя позиция строки в коллекции в памяти. Это разные механизмы, и в коде для доступа к строке нужно использовать индекс.

Что вернёт метод Индекс(), если элемент не найден?

Метод Индекс() у таблицы значений и массива вернёт -1, если переданный элемент в коллекции отсутствует. Это значение обязательно нужно проверять перед использованием результата как индекса.

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

Либо обходите коллекцию с конца (от Количество() - 1 до 0), либо сначала соберите строки для удаления через НайтиСтроки() в отдельный массив, а затем удаляйте их циклом «Для Каждого». Удаление в прямом цикле по индексу пропускает элементы из-за сдвига.

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

Нет. Структура и соответствие — коллекции «ключ-значение» без гарантированного порядка. Квадратные скобки у них принимают ключ, а не позицию: Соответствие[0] ищет элемент с ключом 0, а не первый по порядку.

Одинаково ли работает индексация на клиенте и на сервере?

Да, правило нулевой индексации едино для всех контекстов выполнения: тонкий клиент, веб-клиент, толстый клиент и сервер. Различий в поведении коллекций между контекстами в этом вопросе нет.

Итог

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

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