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