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

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

Как определить размер массива в 1С

Как определить размер массива в 1С: методы Количество() и ВГраница(), обход массива в цикле, типичные ошибки с индексами и проверка результата.

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

Во встроенном языке 1С размер массива определяется двумя методами: Количество() возвращает число элементов, а ВГраница() — индекс последнего элемента. Оба метода просты, но между ними есть принципиальная разница, из-за которой у начинающих разработчиков возникают ошибки обращения за границы массива. Ниже разобраны оба способа, типовые сценарии их применения и контрольные точки для проверки корректности кода.

Метод Количество(): основной способ узнать размер массива

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

Товары = Новый Массив;

Товары.Добавить("Клавиатура");

Товары.Добавить("Мышь");

Товары.Добавить("Монитор");

Размер = Товары.Количество(); // вернёт 3

Если массив только что создан и в него ничего не добавляли, Количество() вернёт 0. Это нормальная ситуация, а не ошибка: пустой массив — валидный объект, и проверка на ноль — стандартный приём перед началом обработки.

Типичный шаблон защитной проверки выглядит так:

Если Товары.Количество() = 0 Тогда

Сообщить("Список товаров пуст, обработка не требуется");

Возврат;

КонецЕсли;

Метод ВГраница(): зачем нужен индекс последнего элемента

Индексация массивов в 1С начинается с нуля: первый элемент имеет индекс 0, второй — 1 и так далее. Поэтому индекс последнего элемента всегда на единицу меньше количества элементов. Метод ВГраница() возвращает именно этот индекс — верхнюю границу массива.

Товары = Новый Массив;

Товары.Добавить("Клавиатура");

Товары.Добавить("Мышь");

Товары.Добавить("Монитор");

ПоследнийИндекс = Товары.ВГраница(); // вернёт 2

ПоследнийЭлемент = Товары[ПоследнийИндекс]; // "Монитор"

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

Количество() или ВГраница()

Количество()

Подходит для проверки на пустоту, подсчёта элементов, вывода в сообщения и отчёты. Возвращает фактическое число элементов.

ВГраница()

Подходит для классического цикла с индексом и для доступа к последнему элементу. Возвращает индекс последнего элемента, для пустого массива — -1.

Обход массива в цикле с использованием размера

Классический цикл со счётчиком строится на ВГраница(): счётчик пробегает от 0 до индекса последнего элемента включительно.

Для Индекс = 0 По Товары.ВГраница() Цикл

Сообщить("Элемент " + Индекс + ": " + Товары[Индекс]);

КонецЦикла;

Если использовать в условии цикла Количество() без поправки, последняя итерация обратится к несуществующему элементу. Например, цикл Для Индекс = 0 По Товары.Количество() при трёх элементах попытается прочитать Товары[3], а такого индекса нет — платформа выдаст ошибку «Индекс находится за границами массива».

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

Для Каждого Товар Из Товары Цикл

Сообщить(Товар);

КонецЦикла;

Типичные ошибки
01
Использовать Количество() как верхнюю границу цикла — последняя итерация обращается к несуществующему индексу и вызывает ошибку.
02
Обращаться к элементу Товары[0] без проверки, что массив не пуст, — для пустого массива это ошибка времени выполнения.
03
Удалять элементы внутри прямого цикла по индексу — размер меняется на ходу, часть элементов пропускается.
04
Путать размер массива с индексом последнего элемента при построении сообщений и логов.

Удаление элементов и пересчёт размера

Методы Удалить() и Очистить() немедленно уменьшают размер массива. После Удалить(Индекс) все последующие элементы сдвигаются на одну позицию влево, и Количество() возвращает уже новое значение. Метод Очистить() удаляет всё, и размер становится равным нулю.

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

// Обход с конца — удаление не ломает индексацию

Для Индекс = 0 По Товары.ВГраница() Цикл

ТекущийИндекс = Товары.ВГраница() - Индекс;

Если Товары[ТекущийИндекс] = "" Тогда

Товары.Удалить(ТекущийИндекс);

КонецЕсли;

КонецЦикла;

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

Размер массива, полученного из запроса или выгрузки

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

Результат = Запрос.Выполнить();

Если Результат.Пустой() Тогда

Возврат;

КонецЕсли;

Выборка = Результат.Выгрузить();

ЧислоСтрок = Выборка.Количество();

Метод НайтиСтроки() таблицы значений и табличной части как раз возвращает настоящий массив структур с отобранными строками. Здесь Количество() применяется напрямую и сразу показывает, нашлось ли что-то по условию отбора:

Найденные = ТаблицаДокументов.НайтиСтроки(Новый Структура("Проведен", Истина));

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

Сообщить("Проведённых документов: " + Найденные.Количество());

КонецЕсли;

Многомерные массивы и вложенные структуры

В 1С нет специального типа «многомерный массив» — многомерность эмулируется массивом массивов. Внешний массив хранит ссылки на внутренние, и у каждого уровня собственный размер.

Матрица = Новый Массив;

Строка1 = Новый Массив;

Строка1.Добавить(1);

Строка1.Добавить(2);

Матрица.Добавить(Строка1);

ЧислоСтрок = Матрица.Количество(); // 1

ЧислоКолонок = Матрица[0].Количество(); // 2

При обходе такой структуры размер внутреннего массива нужно запрашивать отдельно для каждой строки — вложенные массивы могут иметь разную длину. Предполагать, что все строки одинаковые, без проверки нельзя: обращение к Матрица[1][5] при короткой второй строке вызовет ошибку.

Как безопасно определить и использовать размер массива
  1. 1
    Убедитесь, что переменная инициализирована как массив (Новый Массив) или получена из метода, который гарантированно возвращает массив.
  2. 2
    Вызовите Массив.Количество() и проверьте результат на ноль, если пустой массив требует отдельной обработки.
  3. 3
    Для цикла по индексам используйте ВГраница(), для простого перебора — Для Каждого.
  4. 4
    После удаления или добавления элементов запросите размер заново — старое сохранённое значение уже неактуально.
  5. 5
    Проверьте код в отладчике: поставьте точку останова и посмотрите значение Количество() в табло.

Проверка результата и диагностика ошибок

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

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

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

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

Значение Количество() в отладчике
Норма

Совпадает с числом элементов, видимых при раскрытии массива в табло

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

Значение больше или меньше фактического числа элементов — переменная переиспользуется или массив изменён ранее

Верхняя граница цикла
Норма

Цикл завершается без ошибок и обрабатывает последний элемент

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

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

Поведение на пустом массиве
Норма

Код корректно отрабатывает ветку с нулём элементов

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

Ошибка при обращении к элементу [0] или ВГраница() используется без проверки на -1

Итог

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

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

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

Чем отличается Количество() от ВГраница()?

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

Что вернёт Количество() для пустого массива?

Ноль. Пустой массив — это корректный объект, и вызов метода не вызовет ошибки. При этом ВГраница() для пустого массива вернёт -1, что тоже является нормальным значением, а не сбоем.

Как узнать размер массива, если переменная может быть Неопределено?

Сначала проверьте тип: Если ТипЗнч(Переменная) = Тип("Массив") Тогда ... КонецЕсли. Вызов Количество() у значения Неопределено приведёт к ошибке «Метод объекта не обнаружен», поэтому проверка типа обязательна, когда источник данных не гарантирует массив.

Можно ли задать размер массива заранее при создании?

Нет, массив в 1С динамический. Конструктор Новый Массив не принимает размер — элементы добавляются методами Добавить() и Вставить(), а размер растёт автоматически. Зарезервировать фиксированную длину, как в некоторых других языках, нельзя.

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

В языке запросов 1С нет операции «размер массива», потому что массивов там нет. Если массив передан в запрос как параметр для условия В(&Массив), число его элементов вычисляется в коде до выполнения запроса — обычным вызовом Количество(). Число строк результата запроса определяется уже после выполнения через Пустой() или Количество() у выгруженной таблицы.

Почему после удаления элементов Количество() показывает старое значение?

Так не бывает: метод всегда возвращает актуальное число элементов. Если вы видите устаревшее значение, скорее всего, размер был сохранён в переменную до удаления и используется старая копия. Запросите Количество() заново после всех изменений массива.