При разработке отчетов и форм фильтрации в системе 1С разработчики часто сталкиваются с удобным интерфейсным механизмом компоновки данных. В отборах системы компоновки данных (СКД) при выборе даты пользователь может указать не только жестко зафиксированный календарный день, но и относительное значение: «Начало этого дня», «Начало этой недели», «Начало этого месяца» или «Начало этого года». При этом от разработчика часто требуется перенести такое же поведение на обычную управляемую форму вне СКД, причем для выбора одной даты, а не двух дат интервала.
Разберем по шагам, какие инструменты платформы «1С:Предприятие 8.3» позволяют решить данную задачу, как устроен специализированный тип данных и как правильно организовать хранение выбранных настроек в базе данных.
Для работы с интервалами в платформе существует объект СтандартныйПериод, состоящий из двух дат: даты начала и даты окончания. Однако когда в интерфейсе требуется задать только одну дату со списком типовых относительных периодов, использовать целый период избыточно. Для такой задачи разработчики платформы предусмотрели отдельный системный объект — СтандартнаяДатаНачала.
Рассмотрим структуру данного объекта. У него есть два ключевых свойства:
ВариантСтандартнойДатыНачала (например, НачалоЭтогоДня, НачалоЭтойНедели, НачалоЭтогоМесяца, НачалоЭтогоГода, ПроизвольнаяДата и другие).ПроизвольнаяДата, то свойство содержит явно введенную пользователем дату. Если выбран любой относительный вариант, платформа рассчитывает и возвращает актуальную дату на текущий момент времени.Проанализируем базовый сценарий реализации интерфейса, полностью повторяющего поведение отбора СКД.
Пошаговый порядок действий в конфигураторе:
ПериодОтчета или ДатаФильтра).СтандартнаяДатаНачала.В пользовательском режиме такое поле ввода предоставляет стандартную кнопку выбора. При нажатии на нее открывается системное выпадающее меню со списком предустановленных относительных значений. Если пользователь выбирает конкретную дату, он переключается в режим произвольной даты и выбирает значение из календаря.
Посмотрим на пример программной инициализации реквизита при открытии формы:
&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
// Устанавливаем относительный вариант по умолчанию
ДатаФильтра = Новый СтандартнаяДатаНачала(ВариантСтандартнойДатыНачала.НачалоЭтогоМесяца);
КонецПроцедуры
Когда в коде алгоритма требуется получить фактическую дату для формирования запроса или выборки данных, достаточно обратиться к свойству Дата:
&НаСервере
Процедура ВыполнитьОбработкуДанных()
ФактическаяДата = ДатаФильтра.Дата;
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Данные.Ссылка КАК Ссылка
|ИЗ
| Документ.ВходящийДокумент КАК Данные
|ГДЕ
| Данные.Дата >= &ДатаНачала";
Запрос.УстановитьПараметр("ДатаНачала", ФактическаяДата);
// Выполнение запроса...
КонецПроцедуры
Важно учитывать ограничение платформы: тип СтандартнаяДатаНачала является объектом оперативной работы интерфейса и не может быть назначен напрямую реквизиту объекта метаданных (справочника, документа, регистра сведений). Способ сохранения зависит от поставленной задачи:
Дата. При записи в него помещается значение РеквизитФормы.Дата. При этом при следующем открытии формы значение восстановится как конкретная дата, а не как динамический сдвиг.Разберем пример сохранения и восстановления относительного варианта через строковое представление перечисления:
&НаСервере
Процедура СохранитьНастройкуВРеквизитСтроки(СтроковыйРеквизит)
СтроковыйРеквизит = XMLСтрока(ДатаФильтра.Вариант);
КонецПроцедуры
&НаСервере
Процедура ВосстановитьНастройкуИзСтроки(СтроковыйРеквизит)
Если ЗначениеЗаполнено(СтроковыйРеквизит) Тогда
ИмяВарианта = XMLЗначение(Тип("ВариантСтандартнойДатыНачала"), СтроковыйРеквизит);
ДатаФильтра = Новый СтандартнаяДатаНачала(ИмяВарианта);
Иначе
ДатаФильтра = Новый СтандартнаяДатаНачала(ВариантСтандартнойДатыНачала.НачалоЭтогоДня);
КонецЕсли;
КонецПроцедуры
Также объект СтандартнаяДатаНачала поддерживает сериализацию XDTO, благодаря чему структуру можно сохранить в реквизит с типом ХранилищеЗначения или преобразовать в XML через СериализаторXDTO.
Если нет необходимости использовать отдельный составной объект платформы, аналогичное поведение можно смоделировать на стандартном реквизите типа Дата. Для этого у поля ввода на форме настраивается список выбора:
Истина или настраиваем кнопку выбора.СписокВыбора текстовыми представлениями периодов.ПриИзменении рассчитываем фактическую дату с помощью стандартных встроенных функций.Посмотрим на пример заполнения списка выбора и вычисления значений:
&НаКлиенте
Процедура ПриОткрытии(Отказ)
Элементы.ПолеДата.СписокВыбора.Очистить();
Элементы.ПолеДата.СписокВыбора.Добавить("НачалоДня", "Начало этого дня");
Элементы.ПолеДата.СписокВыбора.Добавить("НачалоНедели", "Начало этой недели");
Элементы.ПолеДата.СписокВыбора.Добавить("НачалоМесяца", "Начало этого месяца");
КонецПроцедуры
&НаКлиенте
Процедура ПолеДатаОбработкаВыбора(Элемент, ВыбранноеЗначение, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
ТекущаяДата = ТекущаяДатаСеанса();
Если ВыбранноеЗначение = "НачалоДня" Тогда
РеквизитДата = НачалоДня(ТекущаяДата);
ИначеЕсли ВыбранноеЗначение = "НачалоНедели" Тогда
РеквизитДата = НачалоНедели(ТекущаяДата);
ИначеЕсли ВыбранноеЗначение = "НачалоМесяца" Тогда
РеквизитДата = НачалоМесяца(ТекущаяДата);
КонецЕсли;
КонецПроцедуры
Использование встроенного платформенного типа СтандартнаяДатаНачала предпочтительнее, так как оно дает полностью идентичный СКД интерфейс, не требует ручной поддержки списка вариантов и самостоятельно рассчитывает актуальную дату в свойстве Дата.