Как создать вычисляемый реквизит в форме списка справочника в 1С 8.3?

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

При разработке прикладных решений в 1С часто возникает задача отображения в списке справочника данных, которые не хранятся в базе данных в явном виде, а рассчитываются динамически. Классический пример — вычисление текущего курса студенческой группы на основе года поступления и текущей даты. Хранить такие значения в реквизитах самого справочника нецелесообразно, так как они регулярно изменяются во времени и требуют постоянного обновления данных объекта.

Разберем основные подходы к решению этой задачи на платформе 1С:Предприятие 8.3 с управляемыми формами, рассмотрим особенности построения запросов и выясним, как правильно передавать параметры времени сеанса.

Способ 1. Настройка динамического списка с произвольным запросом

Основным и наиболее производительным способом отображения расчетных данных в управляемых формах является использование динамического списка с включенным свойством Произвольный запрос. Главное преимущество такого подхода — платформа 1С автоматически обеспечивает возможность сортировки, группировки, поиска и фильтрации по полученному вычисляемому полю.

Пошагово разберем настройку динамического списка:

  1. Откроем форму списка справочника в конфигураторе.
  2. Перейдем на вкладку Реквизиты и выделим основной реквизит формы Список (тип ДинамическийСписок).
  3. В палитре свойств установим флаг Произвольный запрос и нажмем кнопку открытия текста запроса.
  4. Составим текст запроса, добавив вычисляемое поле.

Проанализируем специфику предметной логики: в учебных заведениях новый курс начинается не с 1 января, а с 1 сентября. Если использовать простое вычитание годов, с января по август номер курса будет некорректным. Поэтому в запросе используем конструкцию ВЫБОР с проверкой месяца текущей даты.

Посмотрим на пример текста запроса для динамического списка:


ВЫБРАТЬ
    СпрГруппы.Ссылка КАК Ссылка,
    СпрГруппы.ПометкаУдаления КАК ПометкаУдаления,
    СпрГруппы.Код КАК Код,
    СпрГруппы.Наименование КАК Наименование,
    СпрГруппы.Факультет КАК Факультет,
    СпрГруппы.Специальность КАК Специальность,
    СпрГруппы.ГодПоступления КАК ГодПоступления,
    ВЫБОР
        КОГДА МЕСЯЦ(&ТекущаяДатаСеанса) >= 9 ТОГДА
            ГОД(&ТекущаяДатаСеанса) - СпрГруппы.ГодПоступления + 1
        ИНАЧЕ
            ГОД(&ТекущаяДатаСеанса) - СпрГруппы.ГодПоступления
    КОНЕЦ КАК Курс
ИЗ
    Справочник.Группы КАК СпрГруппы

После изменения текста запроса в списке доступных полей реквизита Список появится новое поле Курс. Перетащим его в элементы формы — в таблицу списка.

Далее нам необходимо инициализировать параметр &ТекущаяДатаСеанса. Для этого создадим обработчик события формы ПриСозданииНаСервере. Рекомендуется использовать именно функцию ТекущаяДатаСеанса(), а не ТекущаяДата(), чтобы расчет производился с учетом часового пояса пользователя.

Разберем пример программного кода модуля формы:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Передаем текущую дату сеанса в параметры динамического списка
    Список.Параметры.УстановитьЗначениеПараметра(
        "ТекущаяДатаСеанса", 
        ТекущаяДатаСеанса()
    );
    
КонецПроцедуры

Способ 2. Расчет в обработчике ПриПолученииДанныхНаСервере

Второй вариант вывода расчетных данных заключается в использовании события таблицы формы ПриПолученииДанныхНаСервере. Этот механизм позволяет программно заполнить или визуально оформить ячейки для порции строк, которые в данный момент отображаются на экране пользователя.

Рассмотрим порядок реализации данного метода:

  1. В реквизит формы Список (или непосредственно в элементы таблицы формы) добавим новую колонку, например КурсРасчетный, указав нужный тип данных (Число).
  2. Для таблицы формы создадим обработчик события ПриПолученииДанныхНаСервере.
  3. В теле процедуры выполним обход переданных строк и вычислим значение.

Посмотрим на пример реализации данного обработчика:


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(Элемент, ОформленияСтрок)
    
    ТекущаяДата = ТекущаяДатаСеанса();
    МесяцДаты   = Месяц(ТекущаяДата);
    ГодДаты     = Год(ТекущаяДата);
    
    Для Каждого Оформление Из ОформленияСтрок Цикл
        // Получаем год поступления из данных текущей строки
        ГодПоступления = Оформление.ДанныеСтроки.ГодПоступления;
        
        Если ЗначениеЗаполнено(ГодПоступления) И ГодПоступления > 0 Тогда
            Если МесяцДаты >= 9 Тогда
                РасчетныйКурс = ГодДаты - ГодПоступления + 1;
            Иначе
                РасчетныйКурс = ГодДаты - ГодПоступления;
            КонецЕсли;
            
            // Заполняем текст ячейки
            Оформление.Ячейки.КурсРасчетный.УстановитьТекст(Строка(РасчетныйКурс));
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

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

Ограничение значений и учет завершения обучения

При простом математическом расчете разности лет для архивных групп, поступивших много лет назад, курс будет принимать нереалистичные значения (например, 20 или 30 курс). Чтобы предотвратить такие ситуации, в конфигурацию часто добавляют реквизит СрокОбучения в справочник Специальности.

Тогда в тексте запроса динамического списка мы можем сравнить расчетный номер курса с максимальным сроком обучения:


ВЫБРАТЬ
    СпрГруппы.Ссылка КАК Ссылка,
    СпрГруппы.Наименование КАК Наименование,
    СпрГруппы.Специальность КАК Специальность,
    СпрГруппы.ГодПоступления КАК ГодПоступления,
    ВЫБОР
        КОГДА (ВЫБОР 
                КОГДА МЕСЯЦ(&ТекущаяДатаСеанса) >= 9 ТОГДА ГОД(&ТекущаяДатаСеанса) - СпрГруппы.ГодПоступления + 1
                ИНАЧЕ ГОД(&ТекущаяДатаСеанса) - СпрГруппы.ГодПоступления 
               КОНЕЦ) > СпрГруппы.Специальность.СрокОбучения ТОГДА
            "Выпускники"
        ИНАЧЕ
            ВЫБОР 
                КОГДА МЕСЯЦ(&ТекущаяДатаСеанса) >= 9 ТОГДА ГОД(&ТекущаяДатаСеанса) - СпрГруппы.ГодПоступления + 1
                ИНАЧЕ ГОД(&ТекущаяДатаСеанса) - СпрГруппы.ГодПоступления 
            КОНЕЦ
    КОНЕЦ КАК ПредставлениеКурса
ИЗ
    Справочник.Группы КАК СпрГруппы

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

← На главную