Работа с массивами в 1С:Предприятие — одна из самых востребованных задач при разработке конфигураций, написании отчётов или обработок. Без умения корректно создавать, заполнять и обрабатывать массивы невозможно эффективно работать с данными, будь то списки товаров, остатки на складах или результаты сложных расчётов. Однако у начинающих (и иногда опытных) программистов 1С часто возникают вопросы: как правильно объявить массив, какие методы лучше использовать для его заполнения, и почему в некоторых случаях стандартные функции платформы ведут себя неожиданно.
Эта статья охватывает все актуальные способы получения массивов в 1С 8.3 и 8.2, от простейших конструкций до оптимизированных подходов для работы с большими объёмами данных. Мы разберём не только синтаксис, но и нюансы производительности, типичные ошибки, а также приведём практические примеры кода, которые можно сразу использовать в своих проектах. Особое внимание уделено различиям между старыми и новыми версиями платформы — это поможет избежать распространённых проблем при переносе кода между конфигурациями.
1. Базовые способы создания массивов в 1С
Начнём с фундамента: как вообще объявить массив в языке 1С. В отличие от многих других языков программирования, здесь нет жёсткой типизации — массив может содержать элементы разных типов (числа, строки, объекты и даже другие массивы). Это гибкость, но и потенциальный источник ошибок, если не контролировать типы данных.
Самый простой способ создать пустой массив — использовать функцию Новый Массив(). Она работает во всех версиях платформы, начиная с 8.0, и не требует указания размера заранее. Пример:
МассивЧисел = Новый Массив(); // Пустой массив
МассивСтрок = Новый Массив(3); // Массив с 3 пустыми элементами
Если нужно сразу заполнить массив данными, можно передать значения через запятую:
СписокТоваров = Новый Массив("Молоко", "Хлеб", "Яйца", 100, Истина);
⚠️ Внимание: В версиях 1С 8.2 и ниже функцияНовый Массив()без параметров создаёт массив с одним пустым элементом (Неопределён), а не полностью пустой массив. Это может привести к ошибкам при переборе элементов!
- 📌 Динамическое добавление: Используйте метод
Добавить()для расширения массива. Пример:Массив.Добавить("НовыйЭлемент").- 🔄 Копирование: Чтобы скопировать массив, используйте
Массив2 = Массив1.Скопировать(). Простое присваивание (=) создаст ссылку, а не независимую копию!- 🗑️ Очистка: Метод
Очистить()удаляет все элементы, но сохраняет сам объект массива.2. Заполнение массива данными из источников
На практике массивы редко создаются "вручную" — чаще они формируются на основе данных из базы, результатов запросов или внешних файлов. Рассмотрим типичные сценарии.
Из выборки запроса: Если вы получили результат запроса, его можно преобразовать в массив с помощью метода
Выгрузить(). Это удобно для дальнейшей обработки в коде:Запрос = Новый Запрос;Запрос.Текст = "ВЫБРАТЬ Первые 10 Номенклатура.Наименование КАК Товар ИЗ Справочник.Номенклатура";
Результат = Запрос.Выполнить();
МассивТоваров = Результат.Выгрузить().ВыгрузитьКолонку("Товар");
Из таблицы значений: Аналогично работает выгрузка из
ТаблицаЗначений:ТЗ = Новый ТаблицаЗначений;ТЗ.Колонки.Добавить("Наименование");
ТЗ.Добавить().Наименование = "Товар1";
МассивИзТЗ = ТЗ.ВыгрузитьКолонку("Наименование");
Источник данных Метод получения массива Особенности Результат запроса .Выгрузить().ВыгрузитьКолонку()Подходит для одной колонки. Для нескольких колонок лучше использовать Выгрузить()без параметров.Таблица значений .ВыгрузитьКолонку()Возвращает массив значений указанной колонки. Дерево значений .Выгрузить()Выгружает все строки в массив структур. Файл (JSON, CSV) ЧтениеJSON()/ЧтениеТекста()+ разборТребует предварительной обработки строк. Для работы с JSON-данными в современных версиях платформы (8.3.10+) есть встроенные методы:
JSONСтрока = '[1, 2, {"key": "value"}]';МассивИзJSON = ЧтениеJSON.Прочитать(JSONСтрока);
Если вам нужно получить массив уникальных значений из выборки, используйте конструкцию
ВЫБРАТЬ РАЗЛИЧНЫЕв запросе — это эффективнее, чем фильтрация уже загруженного массива.3. Работа с фиксированными и ассоциативными массивами
В 1С нет встроенного типа "ассоциативный массив" (как в PHP или Python), но его функциональность можно эмулировать с помощью объекта
СоответствиеилиСтруктура. Это полезно, когда нужно хранить данные в формате "ключ-значение".Пример с
Соответствие:АссоцМассив = Новый Соответствие;АссоцМассив.Вставить("код1", "Значение1");
АссоцМассив.Вставить("код2", 100);
Значение = АссоцМассив.Получить("код1"); // Вернёт "Значение1"
Фиксированные массивы (с заранее известным размером) создаются так:
ФиксМассив = Новый Массив(5); // Массив из 5 элементовФиксМассив[0] = "Первый";
ФиксМассив[4] = "Пятый"; // Индексация с 0!
⚠️ Внимание: При обращении к несуществующему индексу фиксированного массива (ФиксМассив[5]в примере выше) 1С не выдаст ошибку, а вернётНеопределён. Это может привести к скрытым багам!
- 🔑 Ключи в
Соответствие: Могут быть любыми типами (строка, число, дата), но сравнение ведётся по значению, а не по ссылке.- 🔍 Поиск: Метод
.СодержитКлюч()проверяет наличие ключа без генерации исключения.- 📊 Производительность: Для больших объёмов данных (10 000+ элементов)
Соответствиеработает быстрее, чем поиск по обычному массиву.4. Оптимизация работы с большими массивами
При обработке массивов с тысячами элементов (например, при выгрузке остатков по всем складам) стандартные методы могут тормозить. Вот несколько приёмов для ускорения:
1. Предварительное выделение памяти: Если известен приблизительный размер массива, создайте его с запасом:
БольшойМассив = Новый Массив(10000); // Резервируем место для 10к элементов2. Минимизация операций добавления: Вместо многократного вызова
Добавить()в цикле лучше заполнять массив пакетами:// Плохо (медленно для 10к итераций)Для Каждого Элемент Из Источник Цикл
Массив.Добавить(Элемент);
КонецЦикла;
// Лучше
Массив = Источник.Выгрузить(); // Если источник поддерживает выгрузку
3. Использование
Пока Поиск(): Для поиска в неотсортированных массивах эффективнее ручной перебор с выходом по условию:Найден = Ложь;Для Инд = 0 По Массив.ВГраница() Цикл
Если Массив[Инд] = ИскомоеЗначение Тогда
Найден = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Использовать предварительное выделение памяти|Избегать вложенных циклов по массивам|Заменять Добавить() на пакетную загрузку|Применять Соответствие для поиска по ключу|Тестировать производительность на реальных данных-->
⚠️ Внимание: В 1С 8.2 методНайти()для массивов работает линейно (перебирает все элементы), поэтому на больших данных (1000+ элементов) его использование неэффективно. В 8.3 алгоритм оптимизирован, но для критических участков кода лучше тестировать оба варианта.5. Типичные ошибки и как их избежать
Даже опытные разработчики иногда сталкиваются с неожиданным поведением массивов. Вот наиболее распространённые ловушки:
1. Путаница с индексацией: В 1С индексация массивов начинается с
0, но методВГраница()возвращает последний индекс, а не количество элементов. Например, для массива из 3 элементовВГраница()вернёт2:Массив = Новый Массив("А", "Б", "В");Сообщить(Массив.ВГраница()); // Выведет 2, а не 3!
2. Копирование по ссылке: Оператор
=не создаёт копию массива, а лишь новую ссылку на тот же объект. Изменения в одном массиве отразятся на другом:Массив1 = Новый Массив(1, 2, 3);Массив2 = Массив1; // Это не копия!
Массив2[0] = 10;
Сообщить(Массив1[0]); // Выведет 10, а не 1!
3. Неявное приведение типов: При добавлении элементов разных типов 1С пытается их автоматически преобразовать, что может привести к потере данных:
Массив = Новый Массив();Массив.Добавить("123");
Массив.Добавить(456);
Результат = Массив[0] + Массив[1]; // Результат будет 579 (строка "123456"), а не 579 (число)!
Почему Массив.Количество() может врёт?
В версиях 1С ниже 8.3.6 метод
Количество()для массивов с "дырками" (например, после удаления элементов) возвращал неактуальное значение. ИспользуйтеВГраница() + 1для точного подсчёта.6. Продвинутые приёмы: генераторы, LINQ, функциональное программирование
С выходом 1С:Предприятие 8.3.14+ появились новые возможности для работы с коллекциями, позаимствованные из современных языков программирования. Рассмотрим самые полезные.
1. Генераторы массивов: Функция
Новый Массив(Количество, Значение)создаёт массив с одинаковыми элементами:МассивНулей = Новый Массив(10, 0); // [0, 0, 0, ..., 0]2. Методы LINQ-подобной обработки: В новых версиях доступны цепочки методов для фильтрации и преобразования:
Результат =Массив
.Где(Функция(Элемент) Возврат Элемент > 10 КонецФункции)
.Выбрать(Функция(Элемент) Возврат Элемент * 2 КонецФункции)
.УпорядочитьПоУбыванию();
3. Функциональные подходы: Использование
Для Каждого...Изс лямбда-выражениями:Сумма = Массив.Сумма(Функция(Элемент) Возврат Элемент.Цена * Элемент.Количество КонецФункции);
Метод Описание Пример Версия 1С .Где()Фильтрация элементов Массив.Где(Функция(Эл) Возврат Эл > 5 КонецФункции)8.3.14+ .Выбрать()Преобразование элементов Массив.Выбрать(Функция(Эл) Возврат Эл.Наименование КонецФункции)8.3.14+ .Сумма()Суммирование значений Массив.Сумма(Функция(Эл) Возврат Эл.Стоимость КонецФункции)8.3.15+ .Агрегировать()Группировка данных Массив.Агрегировать(Функция(Эл) Возврат Эл.Категория КонецФункции)8.3.16+ Использование цепочек методов (как в примере с
.Где().Выбрать()) не только делает код лаконичнее, но и повышает производительность за счёт оптимизаций внутри платформы.7. Обмен данными: массивы и внешние системы
Часто массивы в 1С используются как промежуточный формат при интеграции с другими системами (веб-сервисы, Excel, базы данных). Здесь важно правильно преобразовывать данные.
1. Экспорт в JSON: Для передачи массива во внешнюю систему удобно использовать
ЗаписьJSON:Запись = Новый ЗаписьJSON;Запись.УстановитьСтроку();
Запись.Записать(Массив);
JSONСтрока = Запись.Закрыть();
2. Импорт из CSV: При чтении файла строку можно разбить на массив с помощью
СтрРазделить():ТекстСтроки = "Яблоки;Бананы;Вишня";МассивФруктов = СтрРазделить(ТекстСтроки, ";");
3. Работа с Excel: Для выгрузки массива в таблицу Excel через COM-объект:
Excel = Новый COMОбъект("Excel.Application");Лист = Excel.Workbooks.Add().Worksheets(1);
Для Инд = 0 По Массив.ВГраница() Цикл
Лист.Cells(Инд + 1, 1).Value = Массив[Инд];
КонецЦикла;
⚠️ Внимание: При обмене данными с внешними системами учитывайте кодировки! Например, при чтении CSV-файлов, созданных в Windows-1251, может потребоваться преобразование вUTF-8с помощьюСтрЗаменить()или специализированных функций.8. Отладка и тестирование кода с массивами
Ошибки в работе с массивами часто проявляются только на больших объёмах данных или в специфических сценариях. Вот как их выявить заранее:
1. Логирование: Используйте
Сообщить()илиЗаписьЖурналаРегистрациидля вывода промежуточных значений:Для Каждого Элемент Из Массив ЦиклСообщить(ТипЗнч(Элемент)); // Проверяем типы элементов
КонецЦикла;
2. Юнит-тесты: В 1С можно писать тесты с помощью обработок или специализированных библиотек (например, xUnitFor1C). Пример простого теста:
Процедура ТестСуммыМассива()Массив = Новый Массив(1, 2, 3);
ОжидаемаяСумма = 6;
ФактическаяСумма = Массив.Сумма();
Если ФактическаяСумма <> ОжидаемаяСумма Тогда
ВызватьИсключение "Ошибка в расчёте суммы!";
КонецЕсли;
КонецПроцедуры
3. Профилирование: Для поиска "узких мест" используйте встроенный
Профилировщик(доступен в отладочном режиме 1С:Предприятия). Он покажет, какие операции с массивами занимают больше всего времени.
- 🐞 Типичные баги: Нулевые элементы в конце массива, неверная индексация, потеря ссылок при копировании.
- 🔍 Инструменты: Отладчик 1С,
ВывестиЗначениеВоВнешнююОбработку(), логи в файл.- ⚡ Производительность: Тестируйте код на данных, близких к реальным (не на массиве из 3 элементов!).
Всегда проверяйте граничные случаи: пустой массив, массив с одним элементом, массив с
НеопределёнилиNULLзначениями. Именно они чаще всего ломают логику.FAQ: Частые вопросы по массивам в 1С
Как преобразовать таблицу значений в массив структур?
Используйте метод
Выгрузить()без параметров:МассивСтруктур = ТаблицаЗначений.Выгрузить();// Каждый элемент массива — структура с полями, соответствующими колонкам ТЗ
Почему при добавлении элемента в массив появляется ошибка "Индекс вне границ"?
Это происходит, если вы пытаетесь присвоить значение по индексу, превышающему текущий размер фиксированного массива. Например:
Массив = Новый Массив(2); // Массив на 2 элементаМассив[2] = "Третий"; // Ошибка! Последний индекс — 1.
Решение: используйте
Добавить()для динамических массивов или увеличивайте размер заранее.Как отсортировать массив по нескольким критериям?
В 1С 8.3.14+ можно использовать цепочку
.УпорядочитьПо():МассивСтруктур.УпорядочитьПо("Дата Убыв, Сумма Возр");Для старых версий придётся писать кастомный компаратор:
Массив.Сортировать(Функция(Эл1, Эл2)Если Эл1.Дата > Эл2.Дата Тогда
Возврат 1;
ИначеЕсли Эл1.Дата = Эл2.Дата Тогда
Возврат ?(Эл1.Сумма > Эл2.Сумма, -1, 1);
Иначе
Возврат -1;
КонецЕсли;
КонецФункции);
Можно ли в 1С создать многомерный массив?
Да, но только эмулируя его через массивы массивов:
Матрица = Новый Массив();Для Строка = 1 По 3 Цикл
Матрица.Добавить(Новый Массив(3)); // Добавляем строку из 3 элементов
Для Столбец = 0 По 2 Цикл
Матрица[Строка-1][Столбец] = Строка * Столбец;
КонецЦикла;
КонецЦикла;
Обращайтесь к элементам как
Матрица[индексСтроки][индексСтолбца].Как узнать, есть ли элемент в массиве, не перебирая его полностью?
Для простых массивов — никак (придётся использовать
Найти()или цикл). Но если элементы уникальны и их много, лучше использоватьСоответствие:ПоисковыйИндекс = Новый Соответствие;Для Каждого Элемент Из Массив Цикл
ПоисковыйИндекс.Вставить(Элемент, Истина);
КонецЦикла;
// Проверка наличия:
Если ПоисковыйИндекс.СодержитКлюч(ИскомыйЭлемент) Тогда
// Элемент найден
КонецЕсли;