Разработка и Конфигурация · 11 мин
Как найти значение перечисления по синониму в 1С
Как программно найти значение перечисления 1С по синониму: обход метаданных, сравнение с учётом регистра, типовые ошибки и готовый код процедуры.
При обмене данными, загрузке из Excel или обработке внешних файлов часто возникает задача: по текстовому представлению, которое совпадает с синонимом перечисления, получить само значение перечисления. Встроенного метода «найти по синониму» в платформе нет, поэтому задачу решают обходом метаданных перечисления и сравнением синонима каждого значения с искомой строкой.
Решение сводится к циклу по коллекции Метаданные.Перечисления.ИмяПеречисления.ЗначенияПеречисления: у каждого элемента есть свойства Имя и Синоним, а через метод Перечисления.ИмяПеречисления[ИмяЗначения] получают само значение ссылки. Ниже разобраны типовая процедура, варианты сравнения, обработка неоднозначности и частые ошибки.
Как устроены синонимы перечислений в метаданных
Каждое значение перечисления в конфигураторе имеет два ключевых свойства: имя — идентификатор на встроенном языке, который используется для обращения в коде, и синоним — пользовательское представление, которое видно в интерфейсе, отчётах и печатных формах. Именно синоним чаще всего приходит из внешних систем, файлов обмена и ручного ввода пользователей.
Получить доступ к этим свойствам можно только через объект метаданных. Конструкция вида Перечисления.СтавкиНДС.НДС20 возвращает само значение, но не даёт доступа к синониму напрямую. Для чтения синонима используют либо метаданные, либо строковое представление значения — функцию Строка(ЗначениеПеречисления), которая по умолчанию возвращает именно синоним (или имя, если синоним не заполнен).
Важно понимать, что синоним зависит от языка конфигурации. Если в конфигурации настроено несколько языков, свойство Синоним в коде возвращает значение для основного языка встроенного языка, а мультиязычные представления хранятся отдельно. В большинстве типовых конфигураций используется один язык, и это различие не влияет на решение.
Типовая функция поиска по синониму
Базовая реализация — функция, которая принимает имя перечисления и строку синонима, перебирает значения метаданных и возвращает найденное значение или Неопределено. Такой вариант универсален и работает с любым перечислением конфигурации.
Функция НайтиЗначениеПеречисленияПоСинониму(ИмяПеречисления, ИскомыйСиноним) Экспорт
МетаданныеПеречисления = Метаданные.Перечисления.Найти(ИмяПеречисления);
Если МетаданныеПеречисления = Неопределено Тогда
Возврат Неопределено;
КонецЕсли;
Для Каждого ЗначениеМетаданных Из МетаданныеПеречисления.ЗначенияПеречисления Цикл
Если ЗначениеМетаданных.Синоним = ИскомыйСиноним Тогда
Возврат Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя];
КонецЕсли;
КонецЦикла;
Возврат Неопределено;
КонецФункции
Обратите внимание на двойное обращение через квадратные скобки: Перечисления[ИмяПеречисления] возвращает менеджер перечисления по его имени, а вторая пара скобок с именем значения — само значение ссылки. Это стандартный приём для работы с перечислениями, когда имя известно только в виде строки.
Вызов выглядит так: Ставка = НайтиЗначениеПеречисленияПоСинониму("СтавкиНДС", "НДС 20%");. Если синоним найден, в переменной окажется ссылка на значение перечисления, которую можно записывать в реквизиты документов и справочников.
Ставка = НайтиЗначениеПеречисленияПоСинониму("СтавкиНДС", "НДС 20%");
Если Ставка = Неопределено Тогда
Сообщить("Значение не найдено");
КонецЕсли;Сравнение без учёта регистра и лишних пробелов
На практике строка из внешнего источника редко совпадает с синонимом символ в символ: отличается регистр букв, появляются лишние пробелы в начале или в конце, встречаются неразрывные пробелы. Жёсткое сравнение через «равно» в таких случаях возвращает «не найдено», хотя человек различий не видит.
Устойчивый вариант сравнения — привести обе строки к одному регистру и обрезать пробелы:
Если НРег(СокрЛП(ЗначениеМетаданных.Синоним)) = НРег(СокрЛП(ИскомыйСиноним)) Тогда
Возврат Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя];
КонецЕсли;
Если данные приходят из Excel или веб-форм, дополнительно имеет смысл заменить неразрывный пробел (символ с кодом 160) на обычный: СтрЗаменить(Строка, Символ(160), " "). Эта неочевидная причина — один из лидеров среди «необъяснимых» случаев, когда поиск не срабатывает.
Поиск по имени, синониму и представлению одновременно
Часто источник данных непредсказуем: в одном файле приходит имя значения («НДС20»), в другом — синоним («НДС 20%»), в третьем — сокращение. Универсальная функция проверяет строку последовательно по нескольким критериям: сначала точное совпадение с именем, затем с синонимом, затем с представлением значения.
Для Каждого ЗначениеМетаданных Из МетаданныеПеречисления.ЗначенияПеречисления Цикл
ЗначениеСсылки = Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя];
Если НРег(СокрЛП(ЗначениеМетаданных.Имя)) = НРег(СокрЛП(ИскомаяСтрока))
Или НРег(СокрЛП(ЗначениеМетаданных.Синоним)) = НРег(СокрЛП(ИскомаяСтрока))
Или НРег(СокрЛП(Строка(ЗначениеСсылки))) = НРег(СокрЛП(ИскомаяСтрока)) Тогда
Возврат ЗначениеСсылки;
КонецЕсли;
КонецЦикла;
Порядок проверок имеет значение: имя проверяют первым, потому что оно уникально и стабильно, а синонимы теоретически могут дублироваться. Если совпадение по синониму найдено у нескольких значений, функция вернёт первое по порядку следования в конфигураторе — это нужно учитывать при проектировании обмена.
Как обработать отсутствие и дублирование совпадений
Корректная обработка «не найдено» важнее самого поиска. Если функция возвращает Неопределено, вызывающий код должен явно это проверить: записать в журнал регистрации, добавить строку в протокол загрузки или сообщить пользователю. Молчаливая запись пустого значения в реквизит документа приводит к ошибкам в учёте, которые обнаруживают значительно позже.
Альтернатива Неопределено — возврат пустой ссылки перечисления через Перечисления[ИмяПеречисления].ПустаяСсылка(). Такой вариант удобен, когда вызывающий код ожидает именно значение перечисления, а проверка заполненности выполняется стандартно через ЗначениеЗаполнено().
Для контроля дублей можно не прерывать цикл на первом совпадении, а собирать все совпадения в массив. Если массив содержит больше одного элемента — ситуация неоднозначна, и автоматический выбор недопустим: загрузку такой строки следует остановить и передать на ручную обработку.
Как выбрать действие
Производительность и оптимизация при массовой загрузке
Перебор метаданных — быстрая операция, но при загрузке десятков тысяч строк, где для каждой строки вызывается поиск, накладные расходы становятся заметными. Классическая оптимизация — построить соответствие один раз перед циклом загрузки и дальше получать значения из него мгновенно.
Функция СоответствиеСинонимов(ИмяПеречисления)
Результат = Новый Соответствие;
Для Каждого ЗначениеМетаданных Из Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления Цикл
Ключ = НРег(СокрЛП(ЗначениеМетаданных.Синоним));
Результат.Вставить(Ключ, Перечисления[ИмяПеречисления][ЗначениеМетаданных.Имя]);
КонецЦикла;
Возврат Результат;
КонецФункции
Дальше в цикле загрузки поиск сводится к одной строке: Значение = КэшСинонимов[НРег(СокрЛП(СтрокаИзФайла))];. Такой подход на порядки снижает время обработки больших файлов и считается стандартной практикой при разработке обменов.
- 1Перед циклом загрузки постройте соответствие «синоним → значение» для нужного перечисления
- 2В цикле нормализуйте строку из файла: СокрЛП, НРег, замена неразрывных пробелов
- 3Получите значение из соответствия по нормализованному ключу
- 4Если значение не найдено — запишите строку в протокол ошибок, не прерывая загрузку
- 5После загрузки выведите протокол и передайте нераспознанные строки на ручную обработку
Проверка результата и отладка
Проверить корректность поиска проще всего в консоли кода или через отладчик: вызовите функцию с заведомо известным синонимом и сравните результат с ожидаемым значением. Дополнительно полезно вывести Строка(НайденноеЗначение) — представление должно совпадать с исходной строкой.
Если поиск «не находит» заведомо существующее значение, последовательно проверьте: точное написание синонима в конфигураторе (откройте палитру свойств значения перечисления), наличие неразрывных пробелов в исходной строке, правильность имени перечисления и то, что поиск выполняется в той же информационной базе, где актуальна конфигурация. Отдельный случай — расширения: если перечисление добавлено расширением, метаданные доступны, но только при подключённом расширении в текущем сеансе.
Как проверить результат
Возвращается ожидаемое значение перечисления
Возвращается Неопределено — проверяйте написание синонима и пробелы
ЗначениеЗаполнено(Результат) = Истина
Пустая ссылка или Неопределено записывается в реквизит без контроля
Значение находится после нормализации
Поиск не срабатывает — добавьте СокрЛП и замену Символ(160)
Что важно запомнить
Поиск значения перечисления по синониму выполняется перебором метаданных и сравнением свойства Синоним. Нормализуйте строки (СокрЛП, НРег, неразрывные пробелы), всегда обрабатывайте случай «не найдено», а при массовой загрузке стройте соответствие заранее. Для интеграций надёжнее искать по имени значения — синонимы могут меняться.
Частые вопросы
Можно ли найти значение перечисления по синониму запросом?
Нет, язык запросов работает с данными, а синонимы хранятся в метаданных конфигурации. В запросе можно получить представление значения через функцию ПРЕДСТАВЛЕНИЕ, но отбор по синониму таким способом организовать нельзя — используйте перебор метаданных во встроенном языке.
Что вернёт функция Строка() для значения перечисления?
Она вернёт синоним значения, если он заполнен в конфигураторе, или имя значения, если синоним пуст. Это удобно для сравнения, но помните: представление зависит от настроек конфигурации и может отличаться от ожидаемого в мультиязычных решениях.
Что делать, если синонимы двух значений перечисления совпадают?
Платформа не запрещает одинаковые синонимы. В этом случае поиск по синониму неоднозначен: собирайте все совпадения и либо выбирайте по дополнительному признаку, либо передавайте строку на ручную обработку. По возможности исправьте конфигурацию, сделав синонимы различимыми.
Работает ли поиск по синониму в управляемых формах и на клиенте?
Обращение к метаданным доступно только на сервере. В управляемом приложении функцию поиска следует размещать в серверном общем модуле и вызывать с клиента через серверный вызов. В тонком клиенте прямой перебор Метаданных недоступен.
Чем поиск по синониму хуже поиска по имени значения?
Имя значения — стабильный идентификатор, который меняют крайне редко, а синоним могут отредактировать ради интерфейса в любой момент, и обмен silently перестанет работать. Для интеграций передавайте имя или отдельный код, а поиск по синониму оставьте для пользовательских данных и файлов ручной подготовки.
Как найти значение, если известна только часть синонима?
Используйте функцию СтрНайти для поиска подстроки в синониме внутри цикла перебора. Учтите, что частичное совпадение может вернуть несколько значений, поэтому такой подход годится для подсказки пользователю, но не для автоматической записи без контроля.