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

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

Как заполнить массив в цикле в 1С: практическое руководство

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

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

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

Объявление массива и базовое заполнение в цикле

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

МассивЧисел = Новый Массив;

Для Сч = 1 По 10 Цикл

МассивЧисел.Добавить(Сч * 100);

КонецЦикла;

После выполнения этого кода массив содержит десять элементов: 100, 200, ..., 1000. Проверить результат можно через МассивЧисел.Количество() — метод вернёт 10. Обратите внимание: индексация элементов в 1С начинается с нуля, поэтому первый элемент доступен как МассивЧисел[0], а последний — как МассивЧисел[МассивЧисел.Количество() - 1].

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

bsl
Массив = Новый Массив;
Для Сч = 1 По 5 Цикл
    Массив.Добавить("Элемент " + Сч);
КонецЦикла;
Сообщить(Массив.Количество()); // 5

Заполнение массива при обходе результата запроса

Самая частая практическая задача — собрать в массив значения из выборки запроса, например список ссылок на документы или контрагентов для последующей пакетной обработки. Здесь используется цикл Пока Выборка.Следующий() Цикл.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| РеализацияТоваровУслуг.Ссылка КАК Ссылка

|ИЗ

| Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг

|ГДЕ

| РеализацияТоваровУслуг.Дата МЕЖДУ &НачалоПериода И &КонецПериода";

Запрос.УстановитьПараметр("НачалоПериода", НачалоМесяца(ТекущаяДатаСеанса()));

Запрос.УстановитьПараметр("КонецПериода", КонецМесяца(ТекущаяДатаСеанса()));

МассивДокументов = Новый Массив;

Выборка = Запрос.Выполнить().Выбрать();

Пока Выборка.Следующий() Цикл

МассивДокументов.Добавить(Выборка.Ссылка);

КонецЦикла;

Если нужны только уникальные значения, проще не фильтровать массив вручную, а добавить в текст запроса ключевое слово РАЗЛИЧНЫЕ — это снимает дубликаты на стороне СУБД, что быстрее и надёжнее. Альтернатива — проверка Если Массив.Найти(Значение) = Неопределено Тогда перед добавлением, но на больших объёмах такой поиск внутри цикла заметно замедляет выполнение.

Заполнение массива из табличной части и таблицы значений

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

МассивНоменклатуры = Новый Массив;

Для Каждого СтрокаТовары Из ДокументОбъект.Товары Цикл

Если СтрокаТовары.Количество > 0 Тогда

МассивНоменклатуры.Добавить(СтрокаТовары.Номенклатура);

КонецЕсли;

КонецЦикла;

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

Для таблицы значений существует альтернатива без явного цикла: метод ВыгрузитьКолонку("ИмяКолонки") возвращает готовый массив значений колонки. Это короче и быстрее, но не позволяет применять условия отбора — для фильтрации придётся сначала использовать НайтиСтроки() или Скопировать() с отбором.

Способы получить массив из таблицы значений

Цикл Для Каждого + Добавить

Гибкий вариант: можно фильтровать строки и преобразовывать значения. Подходит для сложной логики отбора.

ВыгрузитьКолонку()

Одна строка кода, но без условий отбора. Подходит, когда нужны все значения колонки как есть.

Запрос с РАЗЛИЧНЫЕ

Оптимален для данных из базы: уникальность и отбор выполняются на стороне СУБД.

Заполнение массива фиксированного размера и методы Вставить и Установить

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

КоличествоСтрок = ТаблицаДанных.Количество();

МассивСумм = Новый Массив(КоличествоСтрок);

Для Индекс = 0 По КоличествоСтрок - 1 Цикл

МассивСумм[Индекс] = ТаблицаДанных[Индекс].Сумма * 1.2;

КонецЦикла;

Метод Вставить(Индекс, Значение) вставляет элемент в произвольную позицию, сдвигая последующие элементы вправо. Он полезен, когда порядок формируется по ходу обхода: например, нужно собрать массив, где каждый новый элемент добавляется в начало. Однако частая вставка в середину большого массива — дорогая операция; если порядок не критичен, дешевле добавлять в конец, а затем при необходимости отсортировать.

Метод УстановитьГраницу(НовыйРазмер) изменяет размер уже существующего массива: при увеличении новые элементы получают значение Неопределено, при уменьшении лишние элементы отбрасываются. Это удобно, когда размер вычисляется после частичного заполнения.

Типичные ошибки
01
Обращение к Массив[Индекс] до добавления элемента — возникает ошибка «Индекс находится за границами массива». Сначала Добавить(), потом обращение по индексу.
02
Цикл Для Индекс = 1 По Количество() — в 1С индексация с нуля, поэтому корректный диапазон от 0 до Количество()-1.
03
Добавление дубликатов без проверки — массив не контролирует уникальность, в отличие от соответствия или запроса с РАЗЛИЧНЫЕ.
04
Проверка Найти() внутри цикла на больших массивах — квадратичная сложность, на десятках тысяч элементов код заметно тормозит.

Двумерные массивы и вложенные циклы

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

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

Для Строка = 1 По 5 Цикл

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

Для Колонка = 1 По 5 Цикл

СтрокаМатрицы.Добавить(Строка * Колонка);

КонецЦикла;

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

КонецЦикла;

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

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

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

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

Если МассивДокументов.Количество() = 0 Тогда

ВызватьИсключение "Не найдено документов для обработки";

КонецЕсли;

Для Каждого Элемент Из МассивДокументов Цикл

Сообщить(Элемент);

КонецЦикла;

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

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

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

Количество элементов
Норма

Массив.Количество() равно числу ожидаемых записей

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

Количество 0 при непустом источнике — цикл не выполняется или условие отбора отсекает все строки

Тип элементов
Норма

Все элементы одного ожидаемого типа (ссылка, число, строка)

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

Смешение типов или Неопределено — значит, источник отдаёт незаполненные значения

Дубликаты
Норма

Каждое значение встречается один раз, если требуется уникальность

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

Повторы при требовании уникальности — нет РАЗЛИЧНЫЕ в запросе или проверки Найти()

Производительность и ограничения

Массивы в 1С хранятся в оперативной памяти, поэтому при обработке очень больших выборок (сотни тысяч и более записей) стоит оценивать объём данных. Если массив нужен лишь как промежуточный контейнер для передачи в запрос, рассмотрите временные таблицы и пакетные запросы — они обрабатываются на сервере СУБД и не расходуют память сеанса.

Ещё одно ограничение: массив не имеет встроенных методов сортировки и уникализации. Для сортировки используют либо сортировку на уровне запроса (УПОРЯДОЧИТЬ ПО), либо перенос данных в таблицу значений с методом Сортировать(), либо объект СписокЗначений, у которого есть СортироватьПоЗначению(). Выбор структуры данных под задачу часто важнее оптимизации самого цикла.

Маршрут решения

Как выбрать подход

Нужно собрать значения из базы с отбором и уникальностьюИспользуйте запрос с РАЗЛИЧНЫЕ и цикл Пока Выборка.Следующий() с Добавить()
Нужны все значения одной колонки таблицы значенийИспользуйте ВыгрузитьКолонку() без цикла
Нужна фильтрация строк по условиюИспользуйте Для Каждого с Если внутри и Добавить()
Размер известен заранее и важна позиция элементаСоздайте массив фиксированной длины и заполняйте по индексу
Нужна сортировка или работа по ключуРассмотрите СписокЗначений или Соответствие вместо массива
Итог

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

Базовый шаблон: Новый Массив → цикл → Добавить(). Индексация с нуля, дубликаты не контролируются, вложенные массивы создаются заново на каждой итерации. Для данных из базы фильтрацию и уникальность лучше выполнять в запросе, а для колонок таблицы значений использовать ВыгрузитьКолонку().

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

Как добавить элемент в начало массива, а не в конец?

Используйте метод Массив.Вставить(0, Значение) — он помещает элемент в позицию с индексом 0, сдвигая остальные вправо. Учтите, что при частых вставках в начало большого массива производительность снижается; иногда проще добавлять в конец, а затем обходить массив в обратном порядке.

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

Вызовите Массив.Найти(Значение): если метод вернул Неопределено, значения в массиве нет и его можно добавлять. На больших объёмах вместо массива с такой проверкой лучше использовать соответствие — поиск в нём выполняется значительно быстрее.

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

Ошибка появляется при обращении к элементу, которого ещё нет: например, к Массив[0] у пустого массива или при цикле от 1 до Количество() вместо диапазона от 0 до Количество()-1. Сначала добавьте элементы методом Добавить() и только потом обращайтесь по индексу.

Можно ли заполнить массив значениями по умолчанию без цикла?

Да. Конструктор Новый Массив(10) создаёт массив из десяти элементов со значением Неопределено. Затем можно присвоить нужные значения по индексам. Однако заполнить все элементы одним конкретным значением без цикла штатными средствами нельзя — потребуется цикл либо метод Установить().

Что быстрее: массив или соответствие для накопления значений в цикле?

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

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

Вызовите метод Массив.Очистить() — он удаляет все элементы, сохраняя сам объект. Это предпочтительнее, чем присваивание переменной нового массива, если на исходный массив есть другие ссылки в коде, которые должны видеть очищенное состояние.