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

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

Как найти значение перечисления по синониму в 1С

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

При обмене данными, загрузке из Excel или обработке внешних файлов часто возникает задача: по текстовому представлению, которое совпадает с синонимом перечисления, получить само значение перечисления. Встроенного метода «найти по синониму» в платформе нет, поэтому задачу решают обходом метаданных перечисления и сравнением синонима каждого значения с искомой строкой.

Решение сводится к циклу по коллекции Метаданные.Перечисления.ИмяПеречисления.ЗначенияПеречисления: у каждого элемента есть свойства Имя и Синоним, а через метод Перечисления.ИмяПеречисления[ИмяЗначения] получают само значение ссылки. Ниже разобраны типовая процедура, варианты сравнения, обработка неоднозначности и частые ошибки.

Как устроены синонимы перечислений в метаданных

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

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

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

Типовая функция поиска по синониму

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

Функция НайтиЗначениеПеречисленияПоСинониму(ИмяПеречисления, ИскомыйСиноним) Экспорт

МетаданныеПеречисления = Метаданные.Перечисления.Найти(ИмяПеречисления);

Если МетаданныеПеречисления = Неопределено Тогда

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

КонецЕсли;

Для Каждого ЗначениеМетаданных Из МетаданныеПеречисления.ЗначенияПеречисления Цикл

Если ЗначениеМетаданных.Синоним = ИскомыйСиноним Тогда

Возврат Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя];

КонецЕсли;

КонецЦикла;

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

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

Обратите внимание на двойное обращение через квадратные скобки: Перечисления[ИмяПеречисления] возвращает менеджер перечисления по его имени, а вторая пара скобок с именем значения — само значение ссылки. Это стандартный приём для работы с перечислениями, когда имя известно только в виде строки.

Вызов выглядит так: Ставка = НайтиЗначениеПеречисленияПоСинониму("СтавкиНДС", "НДС 20%");. Если синоним найден, в переменной окажется ссылка на значение перечисления, которую можно записывать в реквизиты документов и справочников.

1c
Ставка = НайтиЗначениеПеречисленияПоСинониму("СтавкиНДС", "НДС 20%");
Если Ставка = Неопределено Тогда
	Сообщить("Значение не найдено");
КонецЕсли;

Сравнение без учёта регистра и лишних пробелов

На практике строка из внешнего источника редко совпадает с синонимом символ в символ: отличается регистр букв, появляются лишние пробелы в начале или в конце, встречаются неразрывные пробелы. Жёсткое сравнение через «равно» в таких случаях возвращает «не найдено», хотя человек различий не видит.

Устойчивый вариант сравнения — привести обе строки к одному регистру и обрезать пробелы:

Если НРег(СокрЛП(ЗначениеМетаданных.Синоним)) = НРег(СокрЛП(ИскомыйСиноним)) Тогда

Возврат Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя];

КонецЕсли;

Если данные приходят из Excel или веб-форм, дополнительно имеет смысл заменить неразрывный пробел (символ с кодом 160) на обычный: СтрЗаменить(Строка, Символ(160), " "). Эта неочевидная причина — один из лидеров среди «необъяснимых» случаев, когда поиск не срабатывает.

Поиск по имени, синониму и представлению одновременно

Часто источник данных непредсказуем: в одном файле приходит имя значения («НДС20»), в другом — синоним («НДС 20%»), в третьем — сокращение. Универсальная функция проверяет строку последовательно по нескольким критериям: сначала точное совпадение с именем, затем с синонимом, затем с представлением значения.

Для Каждого ЗначениеМетаданных Из МетаданныеПеречисления.ЗначенияПеречисления Цикл

ЗначениеСсылки = Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя];

Если НРег(СокрЛП(ЗначениеМетаданных.Имя)) = НРег(СокрЛП(ИскомаяСтрока))

Или НРег(СокрЛП(ЗначениеМетаданных.Синоним)) = НРег(СокрЛП(ИскомаяСтрока))

Или НРег(СокрЛП(Строка(ЗначениеСсылки))) = НРег(СокрЛП(ИскомаяСтрока)) Тогда

Возврат ЗначениеСсылки;

КонецЕсли;

КонецЦикла;

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

Типичные ошибки
01
Сравнение синонима без СокрЛП и НРег — поиск не срабатывает из-за регистра или пробелов
02
Обращение Перечисления.Имя[Строка] без проверки существования значения — возникает ошибка выполнения
03
Игнорирование результата Неопределено — в реквизит записывается пустое значение без контроля
04
Поиск по синониму вместо имени при программной интеграции — синоним могут переименовать, и обмен сломается

Как обработать отсутствие и дублирование совпадений

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

Альтернатива Неопределено — возврат пустой ссылки перечисления через Перечисления[ИмяПеречисления].ПустаяСсылка(). Такой вариант удобен, когда вызывающий код ожидает именно значение перечисления, а проверка заполненности выполняется стандартно через ЗначениеЗаполнено().

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

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

Как выбрать действие

Данные приходят из управляемого источника с фиксированным форматомИспользуйте точное сравнение с синонимом или именем без смягчения условий
Строки вводят пользователи или приходят из ExcelДобавьте СокрЛП, НРег и замену неразрывных пробелов
Синонимы могут дублироватьсяСобирайте все совпадения и передавайте неоднозначность на ручную обработку
Перечисление часто меняется в конфигурацииИщите по имени значения, а не по синониму — имя меняют гораздо реже

Производительность и оптимизация при массовой загрузке

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

Функция СоответствиеСинонимов(ИмяПеречисления)

Результат = Новый Соответствие;

Для Каждого ЗначениеМетаданных Из Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления Цикл

Ключ = НРег(СокрЛП(ЗначениеМетаданных.Синоним));

Результат.Вставить(Ключ, Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя]);

КонецЦикла;

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

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

Дальше в цикле загрузки поиск сводится к одной строке: Значение = КэшСинонимов[НРег(СокрЛП(СтрокаИзФайла))];. Такой подход на порядки снижает время обработки больших файлов и считается стандартной практикой при разработке обменов.

Порядок действий при загрузке файла
  1. 1
    Перед циклом загрузки постройте соответствие «синоним → значение» для нужного перечисления
  2. 2
    В цикле нормализуйте строку из файла: СокрЛП, НРег, замена неразрывных пробелов
  3. 3
    Получите значение из соответствия по нормализованному ключу
  4. 4
    Если значение не найдено — запишите строку в протокол ошибок, не прерывая загрузку
  5. 5
    После загрузки выведите протокол и передайте нераспознанные строки на ручную обработку

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

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

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

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

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

Вызов функции с известным синонимом
Норма

Возвращается ожидаемое значение перечисления

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

Возвращается Неопределено — проверяйте написание синонима и пробелы

Результат поиска
Норма

ЗначениеЗаполнено(Результат) = Истина

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

Пустая ссылка или Неопределено записывается в реквизит без контроля

Поведение на строке с лишними пробелами
Норма

Значение находится после нормализации

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

Поиск не срабатывает — добавьте СокрЛП и замену Символ(160)

Итог

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

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

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

Можно ли найти значение перечисления по синониму запросом?

Нет, язык запросов работает с данными, а синонимы хранятся в метаданных конфигурации. В запросе можно получить представление значения через функцию ПРЕДСТАВЛЕНИЕ, но отбор по синониму таким способом организовать нельзя — используйте перебор метаданных во встроенном языке.

Что вернёт функция Строка() для значения перечисления?

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

Что делать, если синонимы двух значений перечисления совпадают?

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

Работает ли поиск по синониму в управляемых формах и на клиенте?

Обращение к метаданным доступно только на сервере. В управляемом приложении функцию поиска следует размещать в серверном общем модуле и вызывать с клиента через серверный вызов. В тонком клиенте прямой перебор Метаданных недоступен.

Чем поиск по синониму хуже поиска по имени значения?

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

Как найти значение, если известна только часть синонима?

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