При разработке отчетов и выборок в 1С часто возникает задача получить составное строковое представление периода (например, соединить месяц и год в виде «02.2017» или «2. 2017»). Попытка решить эту задачу непосредственно в тексте запроса с помощью функции ПРЕДСТАВЛЕНИЕ приводит к синтаксической ошибке. Разберем причины такого поведения платформы, проанализируем ограничения языка запросов и рассмотрим правильные варианты решения задачи.
Выясним причину, по которой конструкция ПРЕДСТАВЛЕНИЕ(...) + ". " + ПРЕДСТАВЛЕНИЕ(...) вызывает ошибку:
ПРЕДСТАВЛЕНИЕ в языке запросов возвращает специальный системный тип, предназначенный исключительно для визуального отображения данных пользователю. К результату этой функции нельзя применять операции со строками (конкатенацию через оператор +, функцию ПОДСТРОКА и т. д.).ВЫРАЗИТЬ(Поле КАК Строка(...)) не выполняет конвертацию типа: она предназначена только для ограничения длины существующих строковых полей переменной длины или уточнения ссылочных типов.В большинстве сценариев формировать строковое представление периода непосредственно в теле запроса не требуется. Гораздо эффективнее и правильнее оставить в запросе исходное поле даты или отдельные числовые поля, а строковый вид задать на этапе постобработки или вывода.
Рассмотрим, как отформатировать дату при обходе выборки результата запроса с помощью метода Формат:
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
// Преобразование даты в формат "ММ.гггг" (например, "02.2017")
ПериодСтрокой = Формат(Выборка.Период, "ДФ=ММ.гггг");
// Преобразование даты в формат "М. гггг" (например, "2. 2017")
ПериодСПробелом = Формат(Выборка.Период, "ДФ=''М. гггг''");
КонецЦикла;
Если в запросе были выбраны отдельные числа для месяца и года, их можно объединить во встроенном языке оператором сложения строк:
СтроковоеПредставление = Строка(Выборка.Месяц) + ". " + Строка(Выборка.Год);
Если отчет строится на базе СКД, модифицировать текст запроса строковыми преобразованиями также не нужно. Рассмотрим два способа настройки представления полей:
Для поля Период в колонке Выражение представления укажем:
Формат(Период, "ДФ=''М. гггг''")
При таком подходе значение останется датой (что сохраняет корректную сортировку и группировку), но пользователю будет выводиться требуемая строка.
На вкладке Вычисляемые поля можно добавить новое поле и задать в колонке Выражение:
Строка(Месяц) + ". " + Строка(Год)
Если по техническим требованиям строковое поле обязательно должно формироваться непосредственно на уровне SQL-запроса, можно использовать манипуляции со строковыми константами и функцией ПОДСТРОКА.
Посмотрим на пример получения двухзначного номера месяца строкой из даты:
ВЫБРАТЬ
ПОДСТРОКА("010203040506070809101112", (МЕСЯЦ(Продажи.Период) - 1) * 2 + 1, 2) КАК МесяцСтрокой
ИЗ
РегистрНакопления.Продажи КАК Продажи
Аналогично для получения цифры от 0 до 9 по числовому значению используется сдвиг позиции по строке "0123456789":
ПОДСТРОКА("0123456789", ЧисловоеПоле + 1, 1)
Для преобразования произвольных числовых значений в строки внутри запроса можно заранее сформировать таблицу соответствий во встроенном языке и передать ее как параметр.
Разберем по шагам реализацию этого механизма:
// 1. Формируем таблицу сопоставления чисел и строк
ТаблицаСоответствий = Новый ТаблицаЗначений;
ТаблицаСоответствий.Колонки.Добавить("ЧислоМесяца", Новый ОписаниеТипов("Число"));
ТаблицаСоответствий.Колонки.Добавить("СтрокаМесяца", Новый ОписаниеТипов("Строка", Новый КвалификаторыСтроки(10)));
Для Номер = 1 По 12 Цикл
СтрокаТЗ = ТаблицаСоответствий.Добавить();
СтрокаТЗ.ЧислоМесяца = Номер;
СтрокаТЗ.СтрокаМесяца = Формат(Номер, "ЧЦ=2; ЧВН=");
КонецЦикла;
// 2. Передаем таблицу в запрос и связываем с основными данными
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Т.ЧислоМесяца КАК ЧислоМесяца,
| Т.СтрокаМесяца КАК СтрокаМесяца
|ПОМЕСТИТЬ ВТ_Соответствия
|ИЗ
| &ТаблицаСоответствий КАК Т
|;
|
|////////////////////////////////////////////////////////////////////////////////
|ВЫБРАТЬ
| ВТ_Соответствия.СтрокаМесяца КАК МесяцСтрокой,
| Продажи.СуммаОборот КАК Сумма
|ИЗ
| РегистрНакопления.Продажи.Обороты КАК Продажи
| ЛЕВОЕ СОЕДИНЕНИЕ ВТ_Соответствия КАК ВТ_Соответствия
| ПО (МЕСЯЦ(Продажи.Период) = ВТ_Соответствия.ЧислоМесяца)";
Запрос.УстановитьПараметр("ТаблицаСоответствий", ТаблицаСоответствий);
Результат = Запрос.Выполнить();
Итог: Прямая конкатенация представлений в запросе не поддерживается платформой 1С. Оптимальным решением является передача исходных типизированных данных (чисел и дат) на уровень клиентского кода или СКД с последующим форматированием функцией Формат.