При разработке отчетов на схеме компоновки данных (СКД) разработчики часто сталкиваются с задачей ограничения ввода периода. Типичный пример: отчет должен формироваться строго по годам, и пользователю не нужно выбирать конкретные дни или месяцы. Стандартный выбор даты открывает интерактивный календарь, в котором отображаются дни, месяцы и годы. Если пользователь выбирает дату, например, "31.05.2014", а в интерфейсе требуется видеть просто "2014", это вызывает визуальный шум и путаницу.
В этой статье мы подробно разберем, как решить эту задачу изящно и профессионально. Мы рассмотрим несколько эффективных способов: от полностью визуальной настройки в конструкторе СКД (без написания кода) до программных методов с использованием событий модуля отчета.
Этот способ является наиболее красивым и архитектурно правильным, так как он не требует изменения кода модулей и создания кастомных форм. Мы позволим пользователю выбирать простое четырехзначное число (год), а реальные параметры начала и конца периода СКД вычислит автоматически.
Рассмотрим пошагово, как это реализовать:
ВыбранныйГод. Установим для него тип данных Число с длиной 4 и точностью 0. Именно этот параметр мы сделаем доступным для пользователя и выведем в быстрые настройки.НачалоПериода и КонецПериода, которые используются в тексте запроса, установим флаг Ограничение доступности. Это скроет их из пользовательского интерфейса, чтобы не путать бухгалтера или аналитика.Для параметра НачалоПериода запишем следующее выражение:
ДобавитьКДате(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), "ГОД", &ВыбранныйГод - 1)
Разберем логику этого выражения: функция ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0) возвращает базовую дату начала нашей эры (0001-01-01). С помощью системной функции СКД ДобавитьКДате мы прибавляем к ней количество лет, равное выбранному году минус один год. На выходе мы получаем ровно 1 января выбранного пользователем года (например, 01.01.2014 0:00:00).
Для параметра КонецПериода запишем выражение, которое вернет нам последнюю секунду уходящего года:
КонецПериода(ДобавитьКДате(ДАТАВРЕМЯ(1, 1, 1, 0, 0, 0), "ГОД", &ВыбранныйГод - 1), "ГОД")
Функция КонецПериода с параметром "ГОД" автоматически преобразует полученную дату начала года в конец дня 31 декабря (например, 31.12.2014 23:59:59). Это гарантирует, что все документы и движения за весь выбранный год гарантированно попадут в отчет.
Иногда разработчики пытаются настроить только формат отображения даты через условное оформление или стандартное форматирование параметров с помощью строки ДФ=yyyy. Проблема заключается в том, что при попытке интерактивного изменения значения в режиме предприятия платформа 1С все равно открывает стандартный календарь с днями.
Чтобы обойти это поведение и сделать ввод года максимально удобным, выполним следующие настройки в свойствах параметров СКД:
ДФ=yyyy. Это позволит пользователю вводить год непосредственно с клавиатуры без лишних символов разделения дат.В режиме пользователя такое поле превратится в удобный выпадающий список. Пользователь сможет выбрать год в один клик, при этом сохраняется возможность ручного ввода любого другого года с клавиатуры, что решает проблему жесткого ограничения доступных значений.
Если логика отчета требует сложного анализа вводимых пользователем данных или если вы хотите динамически определять границы периодов на сервере, можно прибегнуть к программной предобработке в модуле отчета. Для этого мы перехватим стандартный процесс компоновки результата.
Выполним следующие шаги:
Число: ГодНачала и ГодОкончания.НачалоПериода и КонецПериода.ПриКомпоновкеРезультата.Вставим следующий код в обработчик:
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
// Получаем настройки компоновщика
Настройки = КомпоновщикНастроек.Настройки;
// Получаем значения пользовательских числовых параметров
ПараметрГодНачала = Настройки.ПараметрыДанных.Элементы.Найти("ГодНачала");
ПараметрГодОкончания = Настройки.ПараметрыДанных.Элементы.Найти("ГодОкончания");
Если ПараметрГодНачала <> Неопределено И ПараметрГодНачала.Использование Тогда
ГодЧислом = ПараметрГодНачала.Значение;
// Формируем дату начала года
ДатаНачала = Дата(ГодЧислом, 1, 1, 0, 0, 0);
// Устанавливаем значение скрытого параметра СКД
ПараметрНачало = Настройки.ПараметрыДанных.Элементы.Find("НачалоПериода");
Если ПараметрНачало <> Неопределено Тогда
ПараметрНачало.Значение = ДатаНачала;
ПараметрНачало.Использование = Истина;
КонецЕсли;
КонецЕсли;
Если ПараметрГодОкончания <> Неопределено И ПараметрГодОкончания.Использование Тогда
ГодЧислом = ПараметрГодОкончания.Value;
// Формируем дату конца года (последняя секунда 31 декабря)
ДатаОкончания = КонецДня(Дата(ГодЧислом, 12, 31));
// Устанавливаем значение скрытого параметра СКД
ПараметрКонец = Настройки.ПараметрыДанных.Элементы.Найти("КонецПериода");
Если ПараметрКонец <> Неопределено Тогда
ПараметрКонец.Значение = ДатаОкончания;
ПараметрКонец.Использование = Истина;
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот способ дает разработчику полный контроль над процессом. Например, если пользователь случайно введет некорректный год или оставит поле пустым, мы сможем программно подставить текущий год или вывести предупреждающее сообщение.
Если вы ведете разработку в типовой конфигурации на базе Библиотеки стандартных подсистем (БСП), например, в 1С:ERP, 1С:Комплексная автоматизация или 1С:Бухгалтерия, вы можете использовать встроенные интерфейсные решения БСП.
В составе БСП есть общая форма ВыборПериода. При вызове этой формы через стандартные обработчики платформы можно передать структуру параметров, ограничивающую выбор. Свойство формы РежимВыбораПериода поддерживает значение "ГОД". При использовании этой настройки пользователю откроется штатное диалоговое окно БСП, адаптированное под выбор конкретного года, в котором выбор месяцев и дней будет полностью заблокирован.
Изучив предложенные методы, вы сможете выбрать наиболее подходящий вариант для решения вашей задачи. Если отчет простой и хочется обойтись без кода — используйте выражения СКД (Способ 1). Если требуется гибкость и детальный контроль за действиями пользователя — используйте перехват компоновки результата (Способ 3).