Как в СКД 1С выразить число как название месяца строкой

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Выясняем причину: почему не работает стандартная функция Дата()

Начинающие разработчики часто пытаются применить в вычисляемых полях СКД конструкцию, аналогичную встроенному языку 1С:

Формат(Дата(2020, НомерМесяца, 1), "ДФ=ММММ")

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

Для работы с датами в языке выражений СКД предусмотрены свои специфические функции, такие как ДАТАВРЕМЯ() и ДОБАВИТЬКДАТЕ(). При этом функция ДАТАВРЕМЯ() принимает на вход только жестко заданные константы (литералы) и не может использовать значения полей в качестве параметров.

Решение проблемы: правильный расчет даты в СКД

Проанализируем рабочую схему преобразования. Чтобы получить из числа название месяца, нам нужно динамически сформировать любую корректную дату, попадающую на этот месяц, а затем применить к ней форматирование. Для этого мы можем взять некоторую опорную (базовую) дату и прибавить к ней нужное количество месяцев с помощью функции ДОБАВИТЬКДАТЕ().

Рассмотрим два наиболее точных варианта формулы для поля «Выражение» в вычисляемом поле СКД.

Вариант 1. Смещение относительно начала года (с вычитанием единицы)

В качестве базовой даты возьмем первое января любого года. Если мы просто прибавим к январю номер месяца (например, 3 для марта), то в результате сложения получим апрель (1-й месяц + 3 месяца = 4-й месяц). Чтобы избежать этого смещения, необходимо вычесть единицу из исходного числа месяцев:

ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(2000, 1, 1), "Месяц", Месяц_Просрочки - 1)

Если Месяц_Просрочки равен 1 (Январь), формула прибавит 0 месяцев к 1 января 2000 года, и мы получим исходную дату в январе. Если равен 3 (Март) — прибавится 2 месяца, что вернет дату в марте.

Вариант 2. Смещение относительно декабря предыдущего года (без вычитания)

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

ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1999, 12, 1), "Месяц", Месяц_Просрочки)

В этом случае при Месяц_Просрочки равном 1, к 1 декабря 1999 года прибавится 1 месяц, и система вернет дату 1 января 2000 года, то есть именно январь.

Важный нюанс: обход проблемы с алфавитной сортировкой

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

Формат(ДОБАВИТЬКДАТЕ(...), "ДФ=ММММ")

Внимание! Делать так крайне не рекомендуется. Если ваше вычисляемое поле вернет строковое значение («Январь», «Февраль», «Март»), то СКД при выводе отчета и группировке будет сортировать эти строки по алфавиту. В итоге в отчете вы увидите последовательность: «Август», «Апрель», «Декабрь»... вместо хронологического порядка.

Разберем по шагам, как решить эту проблему правильно:

  1. В поле «Выражение» вычисляемого поля СКД запишите только формулу расчета даты (без использования функции Формат). Например:
    ДОБАВИТЬКДАТЕ(ДАТАВРЕМЯ(1999, 12, 1), "Месяц", Месяц_Просрочки)
  2. В колонке «Тип значения» для этого поля укажите тип Дата (состав даты — только дата).
  3. Перейдите в колонку «Оформление» данного вычисляемого поля. Найдите параметр «Формат» и введите в строку формата выражение: ДФ=ММММ (или выберите «Формат даты» -> «Локальный формат даты» и настройте вывод только названия месяца).

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

Альтернативный вариант №1: Использование условной конструкции ВЫБОР

Если по каким-то причинам вы не хотите работать с преобразованием дат, или вам требуется вывести названия месяцев в специфическом падеже, можно воспользоваться стандартной конструкцией ВЫБОР языка выражений СКД. Этот метод абсолютно надежен, хотя и более громоздок:


ВЫБОР 
    КОГДА Месяц_Просрочки = 1 ТОГДА "Январь"
    КОГДА Месяц_Просрочки = 2 ТОГДА "Февраль"
    КОГДА Месяц_Просрочки = 3 ТОГДА "Март"
    КОГДА Месяц_Просрочки = 4 ТОГДА "Апрель"
    КОГДА Месяц_Просрочки = 5 ТОГДА "Май"
    КОГДА Месяц_Просрочки = 6 ТОГДА "Июнь"
    КОГДА Месяц_Просрочки = 7 ТОГДА "Июль"
    КОГДА Месяц_Просрочки = 8 ТОГДА "Август"
    КОГДА Месяц_Просрочки = 9 ТОГДА "Сентябрь"
    КОГДА Месяц_Просрочки = 10 ТОГДА "Октябрь"
    КОГДА Месяц_Просрочки = 11 ТОГДА "Ноябрь"
    КОГДА Месяц_Просрочки = 12 ТОГДА "Декабрь"
    ИНАЧЕ ""
КОНЕЦ

Помните: при использовании этого варианта вы получите строковое поле. Чтобы отчет сортировался правильно, вам потребуется в настройках СКД на вкладке «Настройки» -> «Сортировка» указать сортировку не по этому новому текстовому полю, а по исходному числовому полю Месяц_Просрочки.

Альтернативный вариант №2: Вызов экспортной функции общего модуля

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

В поле «Выражение» вычисляемого поля напишем:

РаботаСДатамиКлиентСервер.ПолучитьНазваниеМесяца(Месяц_Просрочки)

А в самом общем модуле разместим следующий код:


Функция ПолучитьНазваниеМесяца(НомерМесяца) Экспорт
    Если НомерМесяца >= 1 И НомерМесяца <= 12 Тогда
        Возврат Формат(ДобавитьМесяц('00010101', НомерМесяца - 1), "ДФ=ММММ");
    КонецЕсли;
    Возврат "";
КонецФункции

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

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

← На главную