Разработка и Конфигурация · 12 мин
Как в 1С получить имя ключа структуры
Как в 1С получить имя ключа структуры: перебор через «Для каждого», проверка существования ключа методом Свойство(), работа с КлючИЗначение, типовые ошибки и примеры кода.
Структура в 1С — это коллекция пар «ключ — значение», где ключ всегда строка. Задача получить имя ключа возникает при обходе произвольных параметров, разборе ответа из HTTP-сервиса, передаче настроек между процедурами и отладке. Встроенный язык даёт два основных способа: перебор элементов структуры через конструкцию «Для каждого … Из … Цикл» с объектом КлючИЗначение и проверку конкретного ключа методом Свойство().
Важно понимать ограничение платформы: у структуры нет метода вида «ПолучитьИмяКлючаПоИндексу», и обращение по индексу невозможно — только по имени ключа или перебором. Поэтому все приёмы сводятся к обходу коллекции и чтению свойств Ключ и Значение у каждого элемента.
Ниже разобраны рабочие приёмы: перебор всех ключей, проверка существования ключа без исключения, получение списка имён в массив или строку, поиск ключа по значению, а также отличия структуры от соответствия, которые влияют на выбор способа.
Как устроена структура и что такое ключ
Структура создаётся конструктором Новый Структура("Код, Наименование, Цена") или с инициализацией значений: Новый Структура("Код, Цена", "А-001", 1500). Каждый ключ — это строка-идентификатор, поэтому к нему применяются правила имён переменных: ключ не может начинаться с цифры и содержать пробелы, если задаётся через конструктор строкой.
Обращение к значению выполняется через точку (Структура.Цена) или через квадратные скобки со строкой (Структура["Цена"]). Второй вариант незаменим, когда имя ключа заранее неизвестно и хранится в переменной: Структура[ИмяКлюча]. Именно этот приём лежит в основе всех универсальных обходов.
Если обратиться к несуществующему ключу через точку, платформа вызовет исключение «Поле объекта не обнаружено». Поэтому перед чтением по динамическому имени ключ проверяют методом Свойство() — это безопасная альтернатива попытке чтения.
Перебор структуры и получение всех имён ключей
Основной способ получить имена ключей — цикл «Для каждого». На каждой итерации переменная цикла содержит объект КлючИЗначение, из которого читаются свойства Ключ и Значение:
СтруктураДанных = Новый Структура("Организация, Склад, Контрагент", "ООО Ромашка", "Основной", "ИП Иванов");
Для Каждого Элемент Из СтруктураДанных Цикл
ИмяКлюча = Элемент.Ключ; // "Организация", "Склад", "Контрагент"
ЗначениеКлюча = Элемент.Значение; // значение соответствующего ключа
Сообщить(ИмяКлюча + " = " + ЗначениеКлюча);
КонецЦикла;
Порядок перебора не гарантируется платформой и не совпадает с порядком объявления ключей в конструкторе. Если порядок важен — например, для вывода печатной формы, — соберите имена в массив и отсортируйте, либо используйте соответствие с явным контролем последовательности через отдельный массив ключей.
Для сбора всех имён в одну строку удобен массив с последующим соединением:
ИменаКлючей = Новый Массив;
Для Каждого Элемент Из СтруктураДанных Цикл
ИменаКлючей.Добавить(Элемент.Ключ);
КонецЦикла;
СписокКлючей = СтрСоединить(ИменаКлючей, ", ");
Для Каждого Элемент Из СтруктураДанных Цикл
Сообщить(Элемент.Ключ + " = " + Элемент.Значение);
КонецЦикла;Проверка существования ключа методом Свойство()
Метод Свойство(ИмяСвойства, НайденноеЗначение) — штатный способ узнать, есть ли ключ в структуре, не вызывая исключения. Он возвращает Истина, если ключ найден, и во второй параметр помещает значение. Второй параметр необязателен: если нужно только проверить наличие, вызовите Структура.Свойство("ИмяКлюча").
ЗначениеЦены = Неопределено;
Если СтруктураДанных.Свойство("Цена", ЗначениеЦены) Тогда
// ключ есть, работаем со значением
ИтоговаяЦена = ЗначениеЦены;
Иначе
// ключа нет — задаём поведение по умолчанию
ИтоговаяЦена = 0;
КонецЕсли;
Тонкость: если ключ существует, но его значение равно Неопределено, метод всё равно вернёт Истина. Поэтому Свойство() корректно отличает «ключа нет» от «ключ есть, но пустой» — в отличие от проверки результата чтения на Неопределено, которая для структуры вообще невозможна без исключения.
Поиск имени ключа по известному значению
Обратная задача — узнать, под каким ключом лежит конкретное значение. Прямого метода нет, поэтому выполняют перебор со сравнением. Учтите, что значений с одинаковым содержимым может быть несколько, и цикл найдёт только первый подходящий ключ:
Функция НайтиКлючПоЗначению(СтруктураПоиска, ИскомоеЗначение)
Для Каждого Элемент Из СтруктураПоиска Цикл
Если Элемент.Значение = ИскомоеЗначение Тогда
Возврат Элемент.Ключ;
КонецЕсли;
КонецЦикла;
Возврат Неопределено; // значение не найдено
КонецФункции;
Сравнение через «=» корректно работает для примитивных типов и ссылок. Для таблиц значений, массивов и других составных объектов сравнение проверяет ссылочную идентичность, а не поэлементное совпадение — в этом случае пишите собственную функцию сравнения.
Динамическое обращение к ключу по имени из переменной
Когда имя ключа приходит как строка — из параметра, файла настроек или пользовательского ввода, — обращение через точку невозможно. Используйте квадратные скобки в сочетании с предварительной проверкой:
ИмяКлюча = "Склад"; // получено динамически
Если СтруктураДанных.Свойство(ИмяКлюча) Тогда
Значение = СтруктураДанных[ИмяКлюча];
КонецЕсли;
// запись по динамическому имени
СтруктураДанных.Вставить(ИмяКлюча, НовоеЗначение);
Метод Вставить(Ключ, Значение) добавляет новый ключ или перезаписывает существующий. Это безопасный способ наполнения структуры в цикле, когда набор ключей формируется программно и заранее неизвестен.
Структура или соответствие: что выбрать для работы с ключами
Соответствие — родственная коллекция, где ключом может быть значение любого типа, а не только строка. Приём перебора идентичен: «Для каждого Элемент Из Соответствие Цикл» с тем же объектом КлючИЗначение. Различия влияют на выбор коллекции:
| Критерий | Структура | Соответствие |
|---|---|---|
| Тип ключа | Только строка-идентификатор | Любой тип, включая ссылки |
| Обращение через точку | Да | Нет |
| Проверка ключа | Метод Свойство() | Чтение через [Ключ], отсутствие даёт Неопределено |
| Типовое применение | Параметры, настройки, передача данных между процедурами | Кэши, индексы по ссылкам, счётчики |
Если ключами должны быть ссылки на справочники или документы, структура не подойдёт — используйте соответствие. Если данные передаются как именованные параметры между процедурами и функциями, структура удобнее: она читается через точку и сериализуется в JSON методом ЗаписатьJSON без дополнительных преобразований.
Сравнение вариантов
Универсальный способ получить все имена ключей. Подходит, когда набор ключей неизвестен. Минус — порядок не гарантирован.
Проверка конкретного ключа без исключения. Подходит, когда имя известно или пришло динамически. Не перечисляет ключи.
Чтение и запись по строковому имени из переменной. Требует предварительной проверки, иначе исключение.
Типовые ошибки и как их избежать
Наиболее частая ошибка — попытка обратиться к ключу по индексу: Структура[0]. Структура не индексируется, такой код вызовет исключение. Если нужен порядковый доступ, перенесите ключи в массив перебором и работайте с массивом.
Вторая ошибка — изменение структуры внутри цикла её перебора. Вставка или удаление ключей во время «Для каждого» приводит к непредсказуемому поведению. Сначала соберите ключи для удаления в отдельный массив, затем удаляйте после цикла методом Удалить(ИмяКлюча).
Третья группа ошибок связана с регистром и строковым сравнением. Платформа считает ключи «Цена» и «цена» одинаковыми, но оператор «=» для строк — нет. При сопоставлении имён ключей с внешними данными приводите обе стороны к одному регистру функциями ВРег() или НРег().
Как проверить результат
В сообщении перечислены все ожидаемые ключи, значения соответствуют
Ключей меньше, чем задано в конструкторе — проверьте, не перезаписаны ли они Вставить()
Метод возвращает Истина для существующего ключа при любом регистре имени
Возвращает Ложь для заведомо существующего ключа — проверьте лишние пробелы в строке имени
Функция возвращает имя ключа или Неопределено при отсутствии
Возвращается Неопределено при точно существующем значении — сравниваются объекты по ссылке, а не по содержимому
Практический порядок действий
Соберите типовой сценарий в последовательность: определите, известно ли имя ключа заранее. Если известно — проверьте его через Свойство() и читайте значение. Если неизвестно — переберите структуру циклом и обработайте каждый элемент. Если имя приходит динамически — обязательно валидируйте его перед чтением и записью.
- 1Определите задачу: перебрать все ключи, проверить конкретный или найти ключ по значению
- 2Для перебора используйте «Для каждого Элемент Из Структура Цикл» и читайте Элемент.Ключ
- 3Для проверки конкретного ключа вызовите Структура.Свойство(Имя, Значение)
- 4Для динамического имени обращайтесь через Структура[ИмяКлюча] только после проверки
- 5Проверьте результат выводом в журнал или отладчиком до переноса кода в рабочую базу
Отлаживайте код на копии базы или в тестовой обработке. Структуры часто несут параметры обмена и проведения документов, и ошибочная запись по динамическому ключу может молча перезаписать нужное значение — такие дефекты сложно отследить в продуктивной среде.
Что важно запомнить
Имя ключа структуры получают перебором через КлючИЗначение или проверяют методом Свойство(). Индексного доступа нет, регистр имён не учитывается платформой, изменять структуру внутри цикла её перебора нельзя. Для динамических имён — квадратные скобки плюс обязательная проверка существования ключа.
Частые вопросы
Можно ли получить ключ структуры по порядковому номеру?
Нет, структура не поддерживает индексацию. Обходной путь — перебрать структуру циклом, сложить значения Элемент.Ключ в массив и далее обращаться к массиву по индексу. Порядок элементов при этом не гарантирован платформой.
Чем отличается проверка Свойство() от сравнения значения с Неопределено?
Чтение несуществующего ключа структуры вызывает исключение, поэтому «проверить на Неопределено» без перехвата ошибки невозможно. Свойство() возвращает Истина или Ложь без исключения и корректно различает «ключа нет» и «ключ есть, значение Неопределено». У соответствия поведение иное: чтение отсутствующего ключа возвращает Неопределено без ошибки.
Учитывается ли регистр в именах ключей структуры?
Нет. Ключи «Цена», «ЦЕНА» и «цена» для платформы идентичны — обращение и Свойство() сработают при любом регистре. Но строковое сравнение имён оператором «=» регистр учитывает, поэтому при сопоставлении с внешними строками применяйте ВРег() или НРег() к обеим сторонам.
Как удалить ключ из структуры во время перебора?
Напрямую внутри цикла «Для каждого» удалять нельзя — это нарушает итерацию. Соберите имена удаляемых ключей в массив внутри цикла, а после его завершения пройдите по массиву и вызовите Структура.Удалить(ИмяКлюча) для каждого элемента.
Как выгрузить имена ключей структуры в JSON?
Структура сериализуется штатно: создайте ЗаписьJSON, вызовите ЗаписатьJSON(Запись, Структура) — имена ключей станут именами свойств JSON-объекта. Для обратного разбора используйте ПрочитатьJSON с параметром ПрочитатьВСоответствие = Ложь, тогда результатом будет именно структура, а не соответствие.
Что выбрать, если ключами должны быть ссылки на документы?
Структура не подходит — её ключи только строковые идентификаторы. Используйте соответствие: оно принимает ключи любого типа, включая ссылки. Перебор работает так же через КлючИЗначение, а проверка наличия ключа выполняется чтением Соответствие[Ключ] и сравнением с Неопределено.