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