При разработке отчетов и обработок в платформе 1С:Предприятие часто возникает задача получить строковое имя или синоним значения перечисления непосредственно в запросе. Однако разработчики сталкиваются с тем, что стандартные конструкции не позволяют работать с полученным результатом как с полноценной строкой.
Разберем подробнее, почему возникают сложности со стандартными функциями языка запросов и какие существуют надежные способы преобразования перечисления в строковый тип данных.
Выясним причину поведения платформы при вызове стандартных функций:
ПРЕДСТАВЛЕНИЕ() и ПРЕДСТАВЛЕНИЕССЫЛКИ() не вычисляются средствами СУБД на уровне базы данных. Платформа 1С подставляет строковое представление объекта уже после выполнения запроса, на этапе формирования выборки результата. По этой причине поля с представлением нельзя использовать в секциях ГДЕ, ПО, СГРУППИРОВАТЬ ПО, УПОРЯДОЧИТЬ ПО, а также передавать их в строковые функции (например, ПОДСТРОКА или оператор ПОДОБНО).ВЫРАЗИТЬ(ПРЕДСТАВЛЕНИЕ(Поле) КАК СТРОКА(100)) вызывает синтаксическую ошибку, так как результат работы функции представления имеет специальный внутренний служебный тип, не подлежащий прямому приведению к примитивным типам данных СУБД.Если со строкой перечисления требуется выполнять дальнейшие манипуляции внутри одного запроса (соединять, фильтровать или анализировать подстроки), необходимо использовать альтернативные подходы.
Рассмотрим наиболее универсальный и масштабируемый способ, при котором сопоставление ссылок перечисления и их строковых имен формируется программно на основе метаданных и передается в запрос в качестве параметра.
Разберем по шагам реализацию этого механизма:
ТаблицаЗначений.ЛЕВОЕ СОЕДИНЕНИЕ основной таблицы данных с временной таблицей по ссылке перечисления.Посмотрим на пример программного кода вспомогательной функции:
Функция ТаблицаИменПеречисления(ИмяПеречисления)
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Значение", Новый ОписаниеТипов("ПеречислениеСсылка." + ИмяПеречисления));
Таблица.Колонки.Добавить("Имя", ОбщегоНазначения.ПолучитьОписаниеТиповСтроки(100));
Для Каждого ЗнПереч Из Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления Цикл
НовСтр = Таблица.Добавить();
НовСтр.Значение = Перечисления[ИмяПеречисления][ЗнПереч.Имя];
НовСтр.Имя = ЗнПереч.Имя;
КонецЦикла;
Возврат Таблица;
КонецФункции
Теперь рассмотрим, как использовать подготовленную таблицу в тексте основного запроса:
Процедура ВыполнитьЗапросСИменамиПеречислений()
ПеречНДС = ТаблицаИменПеречисления("СтавкиНДС");
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Таб.Имя КАК Имя,
| Таб.Значение КАК Значение
|ПОМЕСТИТЬ ТабПеречНДС
|ИЗ
| &ПеречНДС КАК Таб
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| Номенклатура.Ссылка КАК Ссылка,
| Номенклатура.СтавкаНДС КАК СтавкаНДС,
| ЕСТЬNULL(ТабПеречНДС.Имя, """") КАК ИмяПереч,
| Номенклатура.Код КАК Код
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ ТабПеречНДС КАК ТабПеречНДС
| ПО Номенклатура.СтавкаНДС = ТабПеречНДС.Значение";
Запрос.УстановитьПараметр("ПеречНДС", ПеречНДС);
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить(Выборка.Код + " - " + Выборка.ИмяПереч);
КонецЦикла;
КонецПроцедуры
Преимущество данного способа заключается в том, что поле ТабПеречНДС.Имя становится полноценным строковым полем на уровне СУБД. К нему можно применять любые строковые операторы и условия.
Если перечисление содержит фиксированное и небольшое количество значений, либо текст запроса генерируется динамически, можно использовать явное сопоставление через конструкцию ВЫБОР КОГДА ... ТОГДА ....
Проанализируем пример такого фрагмента в запросе:
ВЫБРАТЬ
Номенклатура.Ссылка,
ВЫБОР
КОГДА Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС20) ТОГДА "НДС20"
КОГДА Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.НДС10) ТОГДА "НДС10"
КОГДА Номенклатура.СтавкаНДС = ЗНАЧЕНИЕ(Перечисление.СтавкиНДС.БезНДС) ТОГДА "БезНДС"
ИНАЧЕ ""
КОНЕЦ КАК ИмяСтавкиСтрокой
ИЗ
Справочник.Номенклатура КАК Номенклатура
При большом количестве элементов конструкцию ВЫБОР можно быстро сформировать программно в цикле по коллекции Метаданные.Перечисления[ИмяПеречисления].ЗначенияПеречисления и встроить полученную подстроку в текст запроса перед его выполнением.
Если строковое представление не требуется непосредственно для фильтрации или группировки внутри СУБД, а нужно лишь для последующего вывода или интеграции, эффективнее получить строковые идентификаторы во встроенном языке 1С после выполнения запроса.
Для этого применяются встроенные методы платформы:
XMLСтрока(ЗначениеПеречисления) — возвращает точное имя идентификатора перечисления на латинице/кириллице без пробелов (например, "НДС20").Строка(ЗначениеПеречисления) — возвращает пользовательский синоним перечисления (например, "20%").Пример программной обработки выборки:
Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
ИмяИдентификатора = XMLСтрока(Выборка.СтавкаНДС);
ПользовательскийСиноним = Строка(Выборка.СтавкаНДС);
Сообщить(ИмяИдентификатора + " | " + ПользовательскийСиноним);
КонецЦикла;
Если отчет разрабатывается на базе СКД, задача решается без усложнения текста запроса:
Строка(СтавкаНДС).