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