Добавление элементов в массив на встроенном языке 1С:Предприятия 8.3
Содержание
Чтобы добавить значение в массив 1С, вызовите Массив.Добавить(Значение) — элемент встанет в конец, размер вырастет на единицу. Если элемент нужен в начале или в середине, используйте Массив.Вставить(Индекс, Значение). А Массив.Установить(Индекс, Значение) или запись Массив[Индекс] = Значение ничего не добавляют: они заменяют уже существующий элемент.
Выбор простой. Добавление в конец — основной и самый быстрый путь. Вставка по индексу нужна, когда важен порядок. Замена — когда размер массива задан заранее. Все три метода есть в платформе 8.3 и не зависят от конфигурации: код одинаково работает в Бухгалтерии, ЗУП, УТ и в своих разработках.
Как создать массив перед добавлением значений
Массив в 1С — упорядоченная коллекция с нумерацией с нуля. Тип элементов не фиксирован: в одном массиве могут лежать число, строка, ссылка на справочник и другой массив.
Есть три способа создать массив.
📌 Пустой массив — самый частый вариант, дальше элементы добавляют по одному:
Товары = Новый Массив;
Товары.Добавить("Бумага А4");
Товары.Добавить("Тонер");
// Товары.Количество() = 2
📌 Массив заданного размера — все элементы сразу получают значение Неопределено:
Остатки = Новый Массив(3);
// Остатки[0], Остатки[1], Остатки[2] = Неопределено
Остатки[0] = 120;
Остатки[1] = 45;
Остатки[2] = 0;
📌 Массив из другой коллекции — платформа и типовые конфигурации умеют отдавать готовые массивы:
// Из строки с разделителем (платформа 8.3.6 и новее)
Коды = СтрРазделить("001;002;003", ";", Ложь);
// Из колонки таблицы значений
Номенклатура = ТаблицаТоваров.ВыгрузитьКолонку("Номенклатура");
// Из списка значений
Значения = СписокВыбора.ВыгрузитьЗначения();
// Копия фиксированного массива — уже изменяемая
Изменяемый = Новый Массив(ФиксМассив);
Массив, полученный из ВыгрузитьКолонку или СтрРазделить, обычный: в него можно сразу добавлять элементы методом Добавить.
Многомерный массив создают конструктором с несколькими размерами: Новый Массив(3, 2) — три строки по два элемента. Каждая «строка» — вложенный массив, к ней обращаются так: Матрица[1][0]. Когда размеры строк разные, проще собрать массив массивов вручную — через Добавить на каждом уровне.
Метод Добавить: значение в конец массива
Синтаксис: Массив.Добавить(Значение). Параметр необязательный — если его не передать, в конец ляжет Неопределено.
Метод ничего не возвращает. Индекс нового элемента — Массив.ВГраница() сразу после вызова, или Массив.Количество() - 1.
Суммы = Новый Массив;
Суммы.Добавить(1500);
Суммы.Добавить(2300);
Суммы.Добавить(800);
ИндексПоследнего = Суммы.ВГраница(); // 2
Итого = 0;
Для Каждого Сумма Из Суммы Цикл
Итого = Итого + Сумма;
КонецЦикла;
// Итого = 4600
Добавление значений в массив в цикле
Типичная задача — собрать массив ссылок из результата запроса или из табличной части документа.
МассивКонтрагентов = Новый Массив;
Для Каждого Строка Из Объект.Товары Цикл
Если Строка.Количество > 0 Тогда
МассивКонтрагентов.Добавить(Строка.Поставщик);
КонецЕсли;
КонецЦикла;
Если фильтр не нужен и нужна вся колонка, цикл лишний: Объект.Товары.ВыгрузитьКолонку("Поставщик") вернёт тот же массив одной строкой.
Как добавить значение без дублей
В массиве нет встроенной проверки уникальности. Перед добавлением ищите значение методом Найти — он вернёт индекс или Неопределено:
Если Склады.Найти(Склад) = Неопределено Тогда
Склады.Добавить(Склад);
КонецЕсли;
Для нескольких сотен элементов это нормально. На десятках тысяч Найти начинает тормозить — об этом в разделе про производительность.
Добавить один массив в другой
Встроенного метода «склеить массивы» у платформы нет. Пишут цикл:
Для Каждого Элемент Из МассивИсточник Цикл
МассивПриемник.Добавить(Элемент);
КонецЦикла;
В типовых конфигурациях на БСП (Бухгалтерия 3.0, ЗУП 3.1, УТ 11) есть готовая процедура ОбщегоНазначенияКлиентСервер.ДополнитьМассив(Приемник, Источник, ТолькоУникальные). Третий параметр Истина пропускает значения, которые уже есть в приёмнике. В своей конфигурации без БСП этой процедуры нет — оставьте цикл.
Вставка значения в начало или середину массива
Синтаксис: Массив.Вставить(Индекс, Значение). Значение встаёт на позицию Индекс, а все элементы с этого места сдвигаются на одну позицию вправо.
Этапы = Новый Массив;
Этапы.Добавить("Поступление");
Этапы.Добавить("Реализация");
Этапы.Вставить(1, "Перемещение");
// Поступление, Перемещение, Реализация
Этапы.Вставить(0, "Заказ");
// Заказ, Поступление, Перемещение, Реализация
Что будет, если индекс больше размера
Вставить с индексом, равным Количество(), работает как Добавить — значение уходит в конец.
Если индекс ещё больше, платформа расширяет массив: промежуточные позиции заполняются Неопределено, а переданное значение встаёт по указанному индексу.
Список = Новый Массив;
Список.Добавить("А"); // [0] = "А"
Список.Вставить(3, "Г"); // [0] = "А", [1] и [2] = Неопределено, [3] = "Г"
// Список.Количество() = 4
Такие «дыры» потом ломают обход: код, который ждёт строку или ссылку, получит Неопределено. Если вставляете по вычисленному индексу, проверяйте его до вызова.
Замена элемента: Установить и квадратные скобки
Массив.Установить(Индекс, Значение) и Массив[Индекс] = Значение делают одно и то же — меняют значение существующего элемента. Размер массива не меняется.
Цены = Новый Массив(2);
Цены[0] = 100;
Цены.Установить(1, 250);
Индекс должен быть в диапазоне от 0 до ВГраница(). Выход за границу — ошибка выполнения, расширения массива здесь не будет.
Сравнение методов: Добавить, Вставить, Установить
| Метод | Что делает | Размер массива | Когда выбирать |
|---|---|---|---|
Добавить(Значение) | Кладёт значение в конец | +1 | Сбор данных в цикле, почти всегда |
Вставить(Индекс, Значение) | Ставит значение на позицию, сдвигает хвост вправо | +1 (или больше, если индекс за границей) | Нужен конкретный порядок: в начало, перед найденным элементом |
Установить(Индекс, Значение) | Заменяет существующий элемент | Не меняется | Массив создан с размером заранее |
Массив[Индекс] = Значение | То же, что Установить | Не меняется | Короче запись, тот же результат |
Сопутствующие методы, которые нужны при работе с добавлением:
- 🔢
Количество()— сколько элементов; - 📍
ВГраница()— индекс последнего элемента, у пустого массива равен-1; - 🔍
Найти(Значение)— индекс первого совпадения илиНеопределено; - ✂️
Удалить(Индекс)— удаляет элемент, хвост сдвигается влево; - 🧹
Очистить()— удаляет все элементы.
Ошибки при добавлении в массив и как их обойти
Платформа сообщает об ошибках массива короткими фразами. Вот что стоит за самыми частыми.
Массив[Индекс] или Установить с индексом меньше 0 или больше ВГраница(). Проверьте индекс до обращения: Если Индекс <= Массив.ВГраница() Тогда. Для расширения массива используйте Добавить или Вставить.Массив. Чаще всего это ФиксированныйМассив — например, значение из структуры настроек или из реквизита, который платформа вернула неизменяемым. Сделайте копию: Массив = Новый Массив(ФиксМассив).Неопределено: массив забыли создать через Новый Массив или функция вернула пустое значение. Инициализируйте массив до цикла.Для Каждого по этому же массиву. Соберите новые значения в отдельный массив и добавьте их после цикла.Удаление и добавление в одном проходе
Если в цикле нужно и удалять элементы, идите с конца — индексы ещё не пройденных элементов при этом не сдвигаются:
Всего = Строки.Количество();
Для Сч = 1 По Всего Цикл
Индекс = Всего - Сч;
Если ПустаяСтрока(Строки[Индекс]) Тогда
Строки.Удалить(Индекс);
КонецЕсли;
КонецЦикла;
Граница цикла Всего вычислена один раз до начала. Пересчитывать Строки.Количество() внутри цикла нельзя: после удаления индекс уедет за границу.
Массив на клиенте и на сервере
Массив доступен и на клиенте, и на сервере. В серверную процедуру его передают как параметр — при условии, что внутри лежат значения, которые платформа умеет передавать: примитивные типы, ссылки, вложенные массивы и структуры. Объект документа или запрос в такой массив класть не стоит — вызов сервера упадёт на передаче.
Добавление в массив сложных значений: структуры и вложенные массивы
В массив можно класть не только числа и ссылки. На практике часто собирают массив структур — так удобно описать несколько строк с разными полями без создания таблицы значений.
Ошибки = Новый Массив;
Для Каждого Строка Из Объект.Товары Цикл
Если Строка.Цена = 0 Тогда
Описание = Новый Структура;
Описание.Вставить("НомерСтроки", Строка.НомерСтроки);
Описание.Вставить("Текст", "Не заполнена цена");
Ошибки.Добавить(Описание);
КонецЕсли;
КонецЦикла;
Для Каждого Ошибка Из Ошибки Цикл
Сообщить(СтрШаблон("Строка %1: %2", Ошибка.НомерСтроки, Ошибка.Текст));
КонецЦикла;
СтрШаблон сам приводит номер строки к тексту, поэтому склеивать число со строкой вручную не нужно.
Структура кладётся по ссылке
Одна тонкость ловит многих. Если создать структуру один раз до цикла и в цикле только менять её поля, массив заполнится ссылками на один и тот же объект. В итоге все элементы покажут значения последней итерации.
// Неправильно: все элементы массива — одна и та же структура
Описание = Новый Структура("Код");
Для Каждого Код Из Коды Цикл
Описание.Код = Код;
Результат.Добавить(Описание);
КонецЦикла;
Создавайте Новый Структура внутри цикла — как в примере выше. То же правило действует для вложенных массивов и соответствий.
Массив массивов
Для табличных данных без таблицы значений собирают массив, каждый элемент которого — тоже массив:
Строки = Новый Массив;
Строка1 = Новый Массив;
Строка1.Добавить("Бумага");
Строка1.Добавить(250);
Строки.Добавить(Строка1);
// Строки[0][1] = 250
Производительность: как быстро добавлять тысячи значений
На массивах до нескольких тысяч элементов разница между способами незаметна. Проблемы начинаются на десятках тысяч.
Добавляйте в конец, а не в начало
Добавить не трогает существующие элементы. Вставить(0, …) сдвигает весь массив на каждом вызове. Вставка 50 000 значений в начало в цикле означает сотни миллионов сдвигов — код, который с Добавить работает доли секунды, начинает работать заметно дольше.
Если нужен обратный порядок, добавляйте в конец, а потом соберите перевёрнутую копию одним проходом:
Обратный = Новый Массив;
Всего = Исходный.Количество();
Для Сч = 1 По Всего Цикл
Обратный.Добавить(Исходный[Всего - Сч]);
КонецЦикла;
Уникальность через Соответствие
Найти перебирает массив от начала. При 20 000 элементах проверка «есть ли уже» на каждом шаге превращает сбор в квадратичный алгоритм. Держите рядом Соответствие как индекс:
Уникальные = Новый Массив;
Встречались = Новый Соответствие;
Для Каждого Значение Из Исходные Цикл
Если Встречались[Значение] = Неопределено Тогда
Встречались.Вставить(Значение, Истина);
Уникальные.Добавить(Значение);
КонецЕсли;
КонецЦикла;
Поиск в соответствии по ключу не зависит от размера, а порядок первых появлений в массиве сохраняется.
В БСП для разового удаления дублей есть функция ОбщегоНазначенияКлиентСервер.СвернутьМассив(Массив) — она возвращает новый массив без повторов.
Не собирайте в цикле то, что отдаёт запрос
Самая дорогая ошибка — набивать массив ссылками, а затем в цикле читать по каждой ссылке реквизиты через точку. Лучше передать массив в запрос параметром и получить всё одним обращением к базе:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Номенклатура.Ссылка,
| Номенклатура.Артикул
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|ГДЕ
| Номенклатура.Ссылка В (&Список)";
Запрос.УстановитьПараметр("Список", МассивНоменклатуры);
Результат = Запрос.Выполнить().Выгрузить();
Обратная задача — получить из запроса готовый массив: Результат.ВыгрузитьКолонку("Ссылка").
Короткие правила
- ✅ Создавайте массив до цикла, а не внутри него.
- ✅ Если размер известен заранее —
Новый Массив(N)и заполнение по индексу. - ✅ Для проверки «уже есть» на больших объёмах —
Соответствие, а неНайти. - ✅ Готовые выгрузки (
ВыгрузитьКолонку,СтрРазделить,ВыгрузитьЗначения) вместо ручного цикла. - ❌ Не вставляйте в начало в цикле.
- ❌ Не меняйте массив внутри
Для Каждогопо нему же.
Частые вопросы о добавлении значений в массив
Можно ли добавить в массив значение другого типа?
ТипЗнч(Элемент) = Тип("Число").Как добавить в массив сразу несколько значений одной строкой?
СтрРазделить("а,б,в", ","). Для значений других типов конструктора со списком значений нет: вызывайте Добавить несколько раз или используйте цикл по другой коллекции.Как сделать копию массива, чтобы добавление не меняло оригинал?
Копия = Оригинал копирует ссылку, а не данные: добавление в копию изменит оригинал. Независимую копию дают цикл с Добавить или конструкция Новый Массив(Новый ФиксированныйМассив(Оригинал)).Чем массив отличается от списка значений при добавлении?
Добавить(Значение, Представление) принимает ещё и представление, есть пометка и картинка. Список удобен для форм и выбора пользователем, массив — для обработки данных в коде и передачи в запрос.