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

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

Как найти значение в структуре 1С

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

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

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

Поиск значения по ключу через метод Свойство()

Основной и рекомендуемый способ — метод Свойство(). Он принимает имя ключа строкой и, опционально, переменную, в которую будет помещено найденное значение. Метод возвращает Истина, если ключ существует, и Ложь в противном случае. Это позволяет объединить проверку и чтение в одной конструкции без риска исключения.

Значение = Неопределено;

Если Структура.Свойство("СуммаДокумента", Значение) Тогда

Сообщить("Найдено значение: " + Значение);

Иначе

Сообщить("Ключ отсутствует в структуре");

КонецЕсли;

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

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

Порядок безопасного поиска по ключу
  1. 1
    Объявите переменную для результата и инициализируйте её (например, Неопределено)
  2. 2
    Вызовите Структура.Свойство("ИмяКлюча", Переменная)
  3. 3
    Проверьте возвращённое булево значение
  4. 4
    При Истина работайте с переменной, при Ложь — выполните ветку обработки отсутствия ключа
  5. 5
    При необходимости дополнительно проверьте, что значение не равно Неопределено

Безопасное чтение со значением по умолчанию

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

Функция ЗначениеИзСтруктуры(Структура, ИмяКлюча, ПоУмолчанию = Неопределено)

Результат = ПоУмолчанию;

Если ТипЗнч(Структура) = Тип("Структура")

И Структура.Свойство(ИмяКлюча) Тогда

Структура.Свойство(ИмяКлюча, Результат);

КонецЕсли;

Возврат Результат;

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

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

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

Перебор структуры и поиск по значению

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

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

Для Каждого Элемент Из Структура Цикл

Если Элемент.Значение = Искомое Тогда

Сообщить("Значение найдено по ключу: " + Элемент.Ключ);

Прервать;

КонецЕсли;

КонецЦикла;

При сравнении значений учитывайте типы: сравнение ссылочных типов идёт по равенству ссылок, а не реквизитов. Если в структуре лежат числа или строки, следите за типом — строка «100» не равна числу 100. При необходимости приводите типы явно или сравнивайте через ЗначениеЗаполнено() и строковое представление.

Если поиск по значению выполняется часто и структура большая, имеет смысл пересмотреть архитектуру: структура не индексируется по значениям, и каждый поиск — полный перебор. Для таких задач лучше подходит соответствие с обратным направлением «значение → ключ» или отдельная таблица значений с индексом.

Проверка наличия нескольких ключей сразу

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

ОбязательныеКлючи = СтрРазделить("Организация,Период,Склад", ",");

Отсутствующие = "";

Для Каждого ИмяКлюча Из ОбязательныеКлючи Цикл

Если Не Структура.Свойство(ИмяКлюча) Тогда

Отсутствующие = Отсутствующие + ИмяКлюча + "; ";

КонецЕсли;

КонецЦикла;

Если Отсутствующие <> "" Тогда

ВызватьИсключение "В структуре нет ключей: " + Отсутствующие;

КонецЕсли;

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

Отличия при работе с соответствием и вложенными структурами

Соответствие — близкая коллекция, но ключом в нём может быть значение любого типа, а не только строка. Метода Свойство() у соответствия нет: чтение выполняется через Соответствие[Ключ], и если ключ отсутствует, возвращается Неопределено без ошибки. Это удобно, но опасно: отсутствие ключа и значение Неопределено неотличимы, поэтому при необходимости проверяйте наличие через перебор или сравнение с заранее известным «пустым» маркером.

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

Промежуточная = Неопределено;

Если Структура.Свойство("Параметры", Промежуточная)

И ТипЗнч(Промежуточная) = Тип("Структура") Тогда

Если Промежуточная.Свойство("Склад", Склад) Тогда

// работаем со значением

КонецЕсли;

КонецЕсли;

Способы поиска в коллекциях 1С

Структура + Свойство()

Универсально для строковых ключей; безопасно, но нет поиска по значению без перебора

Прямое обращение Структура.Ключ

Коротко и быстро, но ошибка при отсутствии ключа; только для гарантированно заполненных структур

Соответствие[Ключ]

Ключ любого типа, отсутствие ключа даёт Неопределено без ошибки; нельзя отличить «нет ключа» от «значение Неопределено»

Цикл Для Каждого

Единственный способ поиска по значению; полный перебор, медленно на больших коллекциях

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

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

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

Типичные ошибки
01
Чтение Структура.Ключ без проверки — исключение «Поле объекта не обнаружено» при отсутствии ключа
02
Ожидание, что Свойство() вернёт Ложь при значении Неопределено — метод проверяет наличие ключа, а не заполненность
03
Изменение структуры внутри цикла Для Каждого — ошибка коллекции; сначала соберите ключи, потом удаляйте
04
Сравнение значений разных типов без приведения — строка "100" не равна числу 100
05
Использование Попытка/Исключение вместо Свойство() — медленнее и скрывает реальные дефекты данных
Контрольные точки

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

Вызов Свойства() с двумя параметрами
Норма

Возвращает Истина, переменная содержит значение из структуры

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

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

Поиск по значению в цикле
Норма

Элемент найден, цикл прерван по Прервать

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

Цикл завершился без находки — проверьте типы сравниваемых значений

Валидация обязательных ключей
Норма

Список отсутствующих пуст, обработка продолжается

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

Исключение со списком недостающих ключей — источник данных неполон

Производительность и выбор подхода

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

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

Итог

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

Используйте Свойство("Ключ", Переменная) как стандартный способ проверки и чтения. Прямое обращение к ключу допустимо только при гарантированном наличии. Поиск по значению — только перебором; при частом использовании стройте обратное соответствие. Проверяйте типы при сравнении и не изменяйте коллекцию внутри цикла.

Частые вопросы

Чем отличается Структура.Свойство("Ключ") от Структура.Свойство("Ключ", Переменная)?

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

Что будет, если обратиться к несуществующему ключу напрямую?

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

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

Штатного метода нет. Переберите структуру в цикле и проверяйте имя ключа функциями работы со строками, например СтрНайти(Элемент.Ключ, "Сумма") > 0.

Чувствительны ли ключи структуры к регистру?

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

Как найти значение в структуре, полученной из JSON?

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

Как проверить, что структура вообще пустая?

Используйте свойство Количество(): если Структура.Количество() = 0, коллекция пуста. Это надёжнее, чем перебор с флагом.