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