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

Эта статья охватывает все актуальные способы получения массивов в 1С 8.3 и 8.2, от простейших конструкций до оптимизированных подходов для работы с большими объёмами данных. Мы разберём не только синтаксис, но и нюансы производительности, типичные ошибки, а также приведём практические примеры кода, которые можно сразу использовать в своих проектах. Особое внимание уделено различиям между старыми и новыми версиями платформы — это поможет избежать распространённых проблем при переносе кода между конфигурациями.

1. Базовые способы создания массивов в 1С

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

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

МассивЧисел = Новый Массив(); // Пустой массив

МассивСтрок = Новый Массив(3); // Массив с 3 пустыми элементами

Если нужно сразу заполнить массив данными, можно передать значения через запятую:

СписокТоваров = Новый Массив("Молоко", "Хлеб", "Яйца", 100, Истина);
⚠️ Внимание: В версиях 1С 8.2 и ниже функция Новый Массив() без параметров создаёт массив с одним пустым элементом (Неопределён), а не полностью пустой массив. Это может привести к ошибкам при переборе элементов!

  • 📌 Динамическое добавление: Используйте метод Добавить() для расширения массива. Пример: Массив.Добавить("НовыйЭлемент").
  • 🔄 Копирование: Чтобы скопировать массив, используйте Массив2 = Массив1.Скопировать(). Простое присваивание (=) создаст ссылку, а не независимую копию!
  • 🗑️ Очистка: Метод Очистить() удаляет все элементы, но сохраняет сам объект массива.
📊 Какую версию 1С вы используете для разработки?
8.3 (последняя)
8.2
8.1 или старше
Не знаю

2. Заполнение массива данными из источников

На практике массивы редко создаются "вручную" — чаще они формируются на основе данных из базы, результатов запросов или внешних файлов. Рассмотрим типичные сценарии.

Из выборки запроса: Если вы получили результат запроса, его можно преобразовать в массив с помощью метода Выгрузить(). Это удобно для дальнейшей обработки в коде:

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

Запрос.Текст = "ВЫБРАТЬ Первые 10 Номенклатура.Наименование КАК Товар ИЗ Справочник.Номенклатура";

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

МассивТоваров = Результат.Выгрузить().ВыгрузитьКолонку("Товар");

Из таблицы значений: Аналогично работает выгрузка из ТаблицаЗначений:

ТЗ = Новый ТаблицаЗначений;

ТЗ.Колонки.Добавить("Наименование");

ТЗ.Добавить().Наименование = "Товар1";

МассивИзТЗ = ТЗ.ВыгрузитьКолонку("Наименование");

Источник данныхМетод получения массиваОсобенности
Результат запроса.Выгрузить().ВыгрузитьКолонку()Подходит для одной колонки. Для нескольких колонок лучше использовать Выгрузить() без параметров.
Таблица значений.ВыгрузитьКолонку()Возвращает массив значений указанной колонки.
Дерево значений.Выгрузить()Выгружает все строки в массив структур.
Файл (JSON, CSV)ЧтениеJSON() / ЧтениеТекста() + разборТребует предварительной обработки строк.

Для работы с JSON-данными в современных версиях платформы (8.3.10+) есть встроенные методы:

JSONСтрока = '[1, 2, {"key": "value"}]';

МассивИзJSON = ЧтениеJSON.Прочитать(JSONСтрока);

💡

Если вам нужно получить массив уникальных значений из выборки, используйте конструкцию ВЫБРАТЬ РАЗЛИЧНЫЕ в запросе — это эффективнее, чем фильтрация уже загруженного массива.

3. Работа с фиксированными и ассоциативными массивами

В нет встроенного типа "ассоциативный массив" (как в PHP или Python), но его функциональность можно эмулировать с помощью объекта Соответствие или Структура. Это полезно, когда нужно хранить данные в формате "ключ-значение".

Пример с Соответствие:

АссоцМассив = Новый Соответствие;

АссоцМассив.Вставить("код1", "Значение1");

АссоцМассив.Вставить("код2", 100);

Значение = АссоцМассив.Получить("код1"); // Вернёт "Значение1"

Фиксированные массивы (с заранее известным размером) создаются так:

ФиксМассив = Новый Массив(5); // Массив из 5 элементов

ФиксМассив[0] = "Первый";

ФиксМассив[4] = "Пятый"; // Индексация с 0!

⚠️ Внимание: При обращении к несуществующему индексу фиксированного массива (ФиксМассив[5] в примере выше) не выдаст ошибку, а вернёт Неопределён. Это может привести к скрытым багам!

  • 🔑 Ключи в Соответствие: Могут быть любыми типами (строка, число, дата), но сравнение ведётся по значению, а не по ссылке.
  • 🔍 Поиск: Метод .СодержитКлюч() проверяет наличие ключа без генерации исключения.
  • 📊 Производительность: Для больших объёмов данных (10 000+ элементов) Соответствие работает быстрее, чем поиск по обычному массиву.

4. Оптимизация работы с большими массивами

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

1. Предварительное выделение памяти: Если известен приблизительный размер массива, создайте его с запасом:

БольшойМассив = Новый Массив(10000); // Резервируем место для 10к элементов

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

// Плохо (медленно для 10к итераций)

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

Массив.Добавить(Элемент);

КонецЦикла;

// Лучше

Массив = Источник.Выгрузить(); // Если источник поддерживает выгрузку

3. Использование Пока Поиск(): Для поиска в неотсортированных массивах эффективнее ручной перебор с выходом по условию:

Найден = Ложь;

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

Если Массив[Инд] = ИскомоеЗначение Тогда

Найден = Истина;

Прервать;

КонецЕсли;

КонецЦикла;

Использовать предварительное выделение памяти|Избегать вложенных циклов по массивам|Заменять Добавить() на пакетную загрузку|Применять Соответствие для поиска по ключу|Тестировать производительность на реальных данных-->

⚠️ Внимание: В 1С 8.2 метод Найти() для массивов работает линейно (перебирает все элементы), поэтому на больших данных (1000+ элементов) его использование неэффективно. В 8.3 алгоритм оптимизирован, но для критических участков кода лучше тестировать оба варианта.

5. Типичные ошибки и как их избежать

Даже опытные разработчики иногда сталкиваются с неожиданным поведением массивов. Вот наиболее распространённые ловушки:

1. Путаница с индексацией: В индексация массивов начинается с 0, но метод ВГраница() возвращает последний индекс, а не количество элементов. Например, для массива из 3 элементов ВГраница() вернёт 2:

Массив = Новый Массив("А", "Б", "В");

Сообщить(Массив.ВГраница()); // Выведет 2, а не 3!

2. Копирование по ссылке: Оператор = не создаёт копию массива, а лишь новую ссылку на тот же объект. Изменения в одном массиве отразятся на другом:

Массив1 = Новый Массив(1, 2, 3);

Массив2 = Массив1; // Это не копия!

Массив2[0] = 10;

Сообщить(Массив1[0]); // Выведет 10, а не 1!

3. Неявное приведение типов: При добавлении элементов разных типов пытается их автоматически преобразовать, что может привести к потере данных:

Массив = Новый Массив();

Массив.Добавить("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. Обмен данными: массивы и внешние системы

Часто массивы в используются как промежуточный формат при интеграции с другими системами (веб-сервисы, 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. Юнит-тесты: В можно писать тесты с помощью обработок или специализированных библиотек (например, xUnitFor1C). Пример простого теста:

Процедура ТестСуммыМассива()

Массив = Новый Массив(1, 2, 3);

ОжидаемаяСумма = 6;

ФактическаяСумма = Массив.Сумма();

Если ФактическаяСумма <> ОжидаемаяСумма Тогда

ВызватьИсключение "Ошибка в расчёте суммы!";

КонецЕсли;

КонецПроцедуры

3. Профилирование: Для поиска "узких мест" используйте встроенный Профилировщик (доступен в отладочном режиме 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][Столбец] = Строка * Столбец;

КонецЦикла;

КонецЦикла;

Обращайтесь к элементам как Матрица[индексСтроки][индексСтолбца].

Как узнать, есть ли элемент в массиве, не перебирая его полностью?

Для простых массивов — никак (придётся использовать Найти() или цикл). Но если элементы уникальны и их много, лучше использовать Соответствие:

ПоисковыйИндекс = Новый Соответствие;

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

ПоисковыйИндекс.Вставить(Элемент, Истина);

КонецЦикла;

// Проверка наличия:

Если ПоисковыйИндекс.СодержитКлюч(ИскомыйЭлемент) Тогда

// Элемент найден

КонецЕсли;