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

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

Структура как элемент массива в 1С

Как хранить структуры в массиве 1С: создание, обход, поиск, сортировка и типовые ошибки. Практические примеры кода на встроенном языке 1С.

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

Структура в массиве особенно полезна, когда данные временные, не нуждаются в типизации колонок и должны быстро передаваться между процедурами и функциями. В отличие от таблицы значений, структура легче по накладным расходам, а её ключи доступны как свойства объекта, что делает код короче и читабельнее.

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

Как создать массив структур

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

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

СтрокаТовара = Новый Структура("Номенклатура, Количество, Цена");

СтрокаТовара.Номенклатура = Справочники.Номенклатура.НайтиПоКоду("000001");

СтрокаТовара.Количество = 5;

СтрокаТовара.Цена = 1200;

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

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

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

Обход элементов и доступ к полям

Обход выполняется циклом Для Каждого ... Из ... Цикл — на каждой итерации переменная цикла содержит структуру, и её поля доступны через точку. Если нужен индекс, используйте классический цикл со счётчиком от нуля до Массив.Количество() - 1.

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

Сумма = Элемент.Количество * Элемент.Цена;

Сообщить(Строка(Элемент.Номенклатура) + ": " + Сумма);

КонецЦикла;

Перед обращением к полю, которого может не быть, проверяйте его наличие через Свойство("ИмяКлюча", Значение). Прямое обращение к несуществующему ключу вызывает ошибку «Поле объекта не обнаружено» и прерывает выполнение кода.

Типичные ошибки
01
Обращение к ключу без проверки — ошибка «Поле объекта не обнаружено», если у части элементов ключ отсутствует
02
Изменение структуры внутри цикла Для Каждого с ожиданием, что меняется копия — на самом деле меняется исходный объект в массиве
03
Добавление одной структуры несколько раз — все элементы оказываются ссылками на один объект

Поиск элемента в массиве структур

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

Функция НайтиТоварПоКоду(МассивТоваров, ИскомыйКод)

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

Если Элемент.Код = ИскомыйКод Тогда

Возврат Элемент;

КонецЕсли;

КонецЦикла;

Возврат Неопределено;

КонецФункции

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

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

Как выбрать способ поиска

Поиск разовый и элементов немногоИспользуйте простой перебор циклом с условием
Поиск выполняется многократно по одному полюПостройте соответствие ключ → структура для быстрого доступа
Нужны сложные отборы и сортировкиПреобразуйте массив структур в таблицу значений

Сортировка и преобразование в таблицу значений

Массив не имеет встроенного метода сортировки по полю структуры. Практичный путь — перенести данные в таблицу значений, отсортировать её методом Сортировать() и при необходимости собрать массив обратно. Это же решение подходит, когда данные нужно показать пользователю в табличном поле формы.

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

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

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

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

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

СтрокаТЗ = ТЗ.Добавить();

ЗаполнитьЗначенияСвойств(СтрокаТЗ, Элемент);

КонецЦикла;

ТЗ.Сортировать("Цена Убыв");

Метод ЗаполнитьЗначенияСвойств копирует значения по совпадающим именам, поэтому имена колонок таблицы должны совпадать с ключами структуры. Если в структуре есть лишние ключи, перечислите копируемые свойства вторым параметром, иначе получите ошибку о несоответствии свойств.

Передача между клиентом и сервером

Структура и массив сериализуются платформой, поэтому массив структур можно возвращать из серверной процедуры в клиентскую и передавать параметром. Это делает его удобным контейнером для обмена данными между контекстами без создания объектов метаданных.

Ограничение касается значений внутри структуры: вложенные значения должны быть сериализуемыми. Ссылки, примитивные типы, даты, массивы и структуры передаются без проблем, а вот, например, объекты типа Запрос или ТабличныйДокумент в таком виде передать нельзя.

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

При передаче большого массива структур с клиента на сервер и обратно каждый вызов сериализует данные заново. Если массив нужен в нескольких серверных вызовах, храните его на сервере (например, в реквизите формы типа ТаблицаЗначений), а не гоняйте туда-обратно.
ПЗ
Практическое замечание

Когда массив структур — не лучший выбор

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

Сравнение вариантов

Массив структур

Временные данные, передача между процедурами и контекстами. Нет сортировки, поиска по значению и вывода в форму

Таблица значений

Нужны сортировка, поиск, свёртка, вывод на форму, передача в запрос как временная таблица. Тяжелее по памяти

Соответствие

Нужен быстрый доступ по ключу. Нет порядка обхода и дублирования ключей

Список значений

Нужно представление для пользователя и пометки, например в диалогах выбора

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

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

Как проверить корректность кода

Состав ключей у всех элементов
Норма

Все структуры содержат одинаковый набор ключей

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

У части элементов ключи отсутствуют — обращение к полю падает с ошибкой

Независимость элементов
Норма

Изменение одного элемента не влияет на другие

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

Все элементы меняются одновременно — это ссылки на одну структуру

Передача на сервер
Норма

Все вложенные значения сериализуемы, вызов выполняется

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

Ошибка сериализации при вызове серверной процедуры

Ответы на частые вопросы

Можно ли добавить в массив структуры с разным набором ключей?

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

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

Создайте новую структуру с тем же списком ключей через конструктор Новый Структура("Ключ1,Ключ2") и заполните её значениями из исходной, либо используйте сериализацию через ЗначениеВСтрокуВнутр и обратно. Простое присваивание переменной копирует только ссылку, а не данные.

Как удалить элемент из массива структур?

Методом Удалить(Индекс), если индекс известен, либо сначала найдите нужную структуру перебором, затем получите её позицию через Найти() — он сработает, потому что у вас та же самая ссылка. При удалении внутри цикла обходите массив с конца, чтобы индексы не сдвигались.

Можно ли передать массив структур в запрос?

Напрямую — нет, запрос не принимает массив структур как таблицу. Сначала преобразуйте данные в таблицу значений, затем передайте её параметром и используйте конструкцию «ПОМЕСТИТЬ» с выборкой из параметра-таблицы.

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

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

Итог

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

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