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

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

1С: как перебрать структуру — циклы, методы и примеры кода

Как перебрать структуру в 1С: цикл Для Каждого, методы Свойство, Вставить и Удалить, поиск ключей, типичные ошибки и примеры готового кода на встроенном языке.

Структура в 1С — это коллекция пар «ключ-значение», где ключ всегда строка, а значение может быть любого типа: числом, ссылкой, другой структурой или массивом. Разработчики используют структуры для передачи параметров между процедурами, хранения настроек формы, группировки данных отчётов и обмена с внешними системами. Рано или поздно возникает задача обойти все элементы такой коллекции — и здесь важно понимать, какие инструменты даёт встроенный язык и где их границы.

Главная особенность структуры в том, что у неё нет индексов: обратиться к элементу можно только по имени ключа. Поэтому классический цикл Для Сч = 1 По N к структуре неприменим — используется итератор Для Каждого, который возвращает объекты типа КлючИЗначение. Ниже разобраны все рабочие способы перебора, проверки и изменения структуры с готовыми примерами кода.

Как устроена структура и почему её перебирают иначе, чем массив

Структура создаётся конструктором Новый Структура с необязательным списком ключей: Новый Структура("Имя, Возраст", "Иван", 30). Внутри платформа хранит пары «ключ-значение», и доступ к значению возможен двумя способами: через точку (Структура.Имя) или через квадратные скобки со строкой (Структура["Имя"]). Второй вариант незаменим, когда имя ключа заранее неизвестно и хранится в переменной.

У структуры есть метод Количество(), но нумерации элементов нет. Попытка написать Структура[0] приведёт к ошибке, потому что платформа будет искать ключ со строковым именем «0». Порядок обхода элементов в цикле соответствует порядку добавления ключей, однако закладываться на него в бизнес-логике не стоит — структура по смыслу является неупорядоченной коллекцией.

Базовый перебор циклом «Для Каждого»

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

bsl
ПараметрыОтбора = Новый Структура("Организация, Склад, Период", ОрганизацияСсылка, СкладСсылка, ТекущаяДатаСеанса());

Для Каждого Элемент Из ПараметрыОтбора Цикл
	Сообщить("Ключ: " + Элемент.Ключ + ", значение: " + Строка(Элемент.Значение));
КонецЦикла;

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

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

Проверка наличия ключа и безопасное чтение значений

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

bsl
Если СтруктураПараметров.Свойство("Организация", НайденноеЗначение) Тогда
	// ключ есть, НайденноеЗначение заполнено
Иначе
	// ключа нет — задаём значение по умолчанию
	НайденноеЗначение = Неопределено;
КонецЕсли;

Важный нюанс: если ключ существует, но значение не заполнено, Свойство() вернёт Истина, а в переменной окажется Неопределено или пустое значение. Поэтому после проверки существования ключа часто добавляют проверку ЗначениеЗаполнено(НайденноеЗначение). Пропуск этой проверки — частая причина ошибок вида «обращение к пустой ссылке».

Изменение структуры: что можно и что нельзя делать в цикле

Методы Вставить(Ключ, Значение) и Удалить(Ключ) позволяют менять состав структуры. Вставить добавляет ключ или перезаписывает значение существующего, Удалить убирает пару целиком. Менять значение существующего ключа прямо внутри цикла перебора допустимо: Элемент.Значение = НовоеЗначение не сработает (свойство доступно только для чтения), но Структура[Элемент.Ключ] = НовоеЗначение выполнится корректно.

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

bsl
КлючиКУдалению = Новый Массив;
Для Каждого Элемент Из Настройки Цикл
	Если Не ЗначениеЗаполнено(Элемент.Значение) Тогда
		КлючиКУдалению.Добавить(Элемент.Ключ);
	КонецЕсли;
КонецЦикла;

Для Каждого Ключ Из КлючиКУдалению Цикл
	Настройки.Удалить(Ключ);
КонецЦикла;
Типичные ошибки
01
Удаление или вставка ключей прямо внутри цикла Для Каждого — платформа прерывает выполнение с ошибкой изменения коллекции
02
Попытка присвоить Элемент.Значение в цикле — свойство только для чтения, нужно писать Структура[Элемент.Ключ] = Значение
03
Обращение к ключу через точку без проверки Свойство() — исключение, если ключа нет
04
Ожидание строгого порядка обхода и построение на этом логики — порядок не гарантирован контрактом платформы

Структура или соответствие: что выбрать для перебора

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

КритерийСтруктураСоответствие
Тип ключаТолько строка, допустимая как имя переменнойЛюбой тип: ссылка, число, дата
Обращение через точкуДаНет, только квадратные скобки
Передача в типовые механизмыШироко используется (параметры форм, отборы)Реже, в основном внутри прикладного кода
Ключи-ссылки (например, товары)НевозможноОсновной сценарий

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

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

Структура

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

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

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

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

Подходит, когда нужен строгий порядок строк и перебор по индексу. Ограничение: поиск конкретной записи требует полного обхода.

Практические сценарии перебора

Формирование строки параметров или текста запроса

Частая задача — собрать из структуры строку вида «Ключ1=Значение1; Ключ2=Значение2» для лога или HTTP-запроса. Цикл накапливает фрагменты в массив, а затем они объединяются через СтрСоединить — это быстрее и чище, чем конкатенация строк в цикле.

Сравнение двух структур

Чтобы проверить, совпадают ли настройки, обойдите первую структуру и для каждого ключа проверяйте его наличие и равенство значения во второй через Свойство(). Не забудьте отдельно сравнить Количество() — иначе лишние ключи во второй структуре останутся незамеченными.

Рекурсивный обход вложенных структур

Если значениями могут быть другие структуры (например, дерево настроек), перебор оборачивают в рекурсивную процедуру: при обнаружении значения типа «Структура» процедура вызывает сама себя. Проверка типа выполняется через ТипЗнч(Элемент.Значение) = Тип("Структура"). Задавайте разумное ограничение глубины, если структура строится из внешних данных, — это защитит от зацикливания на некорректных данных.

Порядок действий при типовом переборе
  1. 1
    Создайте или получите структуру, убедитесь, что переменная инициализирована (не Неопределено)
  2. 2
    Напишите цикл Для Каждого Элемент Из Структура Цикл
  3. 3
    Внутри цикла работайте с Элемент.Ключ и Элемент.Значение
  4. 4
    Если нужно удалить часть ключей — соберите их в массив и удалите после цикла
  5. 5
    Проверьте результат: выведите Количество() и содержимое в журнал или через Сообщить

Проверка результата и отладка

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

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

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

Как проверить результат

Количество итераций цикла
Норма

Совпадает со значением Структура.Количество()

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

Цикл выполняется меньше или больше раз — возможно, коллекция меняется внутри цикла

Значения внутри цикла
Норма

Каждое значение имеет ожидаемый тип и заполнено

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

Встречаются Неопределено или неожиданные типы — проверьте источник заполнения структуры

Поведение на пустой структуре
Норма

Код отрабатывает без ошибок, цикл не выполняется

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

Ошибка до цикла — переменная не инициализирована или равна Неопределено

Часто задаваемые вопросы

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

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

Гарантирован ли порядок элементов при переборе?

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

Как скопировать одну структуру в другую?

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

Чем перебор структуры отличается от перебора соответствия?

Синтаксис цикла идентичен: Для Каждого с объектом КлючИЗначение. Различия в самой коллекции: у соответствия ключи любого типа, чтение значения выполняется методом Получить(Ключ) или через скобки, а проверка существования ключа — сравнением результата Получить() с Неопределено.

Как узнать, пустая ли структура?

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

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

Да, структура сериализуется платформой и свободно передаётся между клиентскими и серверными вызовами, если все её значения относятся к сериализуемым типам. Учтите, что ссылки на объекты базы передаются корректно, а вот объекты типа «Запрос» или «ТабличныйДокумент» внутри структуры передаче не подлежат.

Итог

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

Структура перебирается только циклом Для Каждого через объект КлючИЗначение. Существование ключа проверяйте методом Свойство(), значение меняйте через Структура[Ключ], а состав ключей не изменяйте внутри цикла — сначала соберите их в массив. Для ключей-ссылок вместо структуры используйте соответствие с тем же синтаксисом обхода.