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

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

При разработке интерфейсов на управляемых формах часто возникает задача отобразить в динамическом списке вычисляемое поле со сложным форматированием — например, представить числовой срок использования или стаж в виде понятной строки: «9 лет 5 месяцев 3 дня». Реализовать подобное строковое форматирование средствами одного лишь языка запросов СУБД крайне затруднительно или неэффективно.

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

Шаг 1. Добавление фиктивного поля в запрос динамического списка

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


ВЫБРАТЬ
    СправочникОС.Ссылка КАК Ссылка,
    СправочникОС.Наименование КАК Наименование,
    СправочникОС.СрокПолезногоИспользования КАК Стаж,
    "" КАК СтажСтрокой
ИЗ
    Справочник.ОсновныеСредства КАК СправочникОС

После изменения текста запроса добавим колонку СтажСтрокой из состава реквизита списка в таблицу на форме.

Шаг 2. Заполнение значений в обработчике «ПриПолученииДанныхНаСервере»

Начиная с платформы 8.3.8, для динамических списков доступно событие ПриПолученииДанныхНаСервере. Этот обработчик выполняется строго на сервере без контекста формы (&НаСервереБезКонтекста) и вызывается только для тех строк, которые непосредственно отображаются на экране пользователя.

Подключим событие динамического списка в свойствах формы и напишем процедуру обхода строк:


&НаСервереБезКонтекста
Процедура СписокПриПолученииДанныхНаСервере(ИмяЭлемента, Настройки, Строки)
    
    Для Каждого Эл Из Строки Цикл
        // Обращаемся к структуре данных текущей строки
        ЗначениеСтажа = Эл.Значение.Данные.Стаж;
        Эл.Значение.Данные.СтажСтрокой = РаботаСоСтроками.ДатаПрописьюГодМесяцДень(ЗначениеСтажа);
    КонецЦикла;
    
КонецПроцедуры

Шаг 3. Реализация алгоритма формирования представления срока

Разберем пример функции, преобразующей числовое значение срока (в месяцах) в развернутую строку с правильными склонениями («год», «года», «лет», «месяц», «месяца», «дней»). Эту функцию удобно разместить в общем модуле (например, РаботаСоСтроками с флагом «Сервер»):


Функция ДатаПрописьюГодМесяцДень(СрокПолезногоИспользования) Экспорт
    
    РасшифровкаСрокаПолезногоИспользования = "";
    
    Если ЗначениеЗаполнено(СрокПолезногоИспользования) Тогда
        ЧастьМесяца = СрокПолезногоИспользования - Цел(СрокПолезногоИспользования);
        ЧислоДней = Цел(30 * ЧастьМесяца);
        Суффикс = "";
        
        Если ЧислоДней <> 0 Тогда
            Суффикс = ЧислоПрописью(ЧислоДней, "НД = Ложь", "#$ень, #$ня, #$ней, м,,,,,0");
            ПозицияПослеПрописи = Найти(Суффикс, "#$");
            Суффикс = Сред(Суффикс, ПозицияПослеПрописи);
            Суффикс = " " + СокрЛП(ЧислоДней) + " " + Суффикс;
        КонецЕсли;
        
        ЧислоЛет = Цел(СрокПолезногоИспользования / 12);
        ЧислоМесяцев = Цел(СрокПолезногоИспользования % 12);
        ЧислоЛетМесяцев = ЧислоЛет + ЧислоМесяцев / 100;
        
        Если ЧислоЛет = 0 Тогда
            СтрокаЧислоЛетМесяцев = ЧислоПрописью(ЧислоМесяцев, "НД = Ложь", "месяц, месяца, месяцев, м,,,,,0");
            СтрокаПоиска = "месяц";
        Иначе
            СтрокаЧислоЛетМесяцев = ЧислоПрописью(ЧислоЛетМесяцев, ?(ЧислоМесяцев = 0, "НД = Ложь", "НД = Истина"), "год, года, лет, м" + ?(ЧислоМесяцев = 0, ",,,,,0", ", месяц, месяца, месяцев, м, 2"));
            СтрокаПоиска = "год";
        КонецЕсли;
        
        ПозицияПослеЛет = Найти(СтрокаЧислоЛетМесяцев, СтрокаПоиска);
        Если ПозицияПослеЛет = 0 Тогда
            ПозицияПослеЛет = Найти(СтрокаЧислоЛетМесяцев, "лет");
        КонецЕсли;
        
        Если ПозицияПослеЛет > 0 Тогда
            РасшифровкаСрокаПолезногоИспользования = СокрЛП(?(ЧислоЛет = 0, ЧислоМесяцев, ЧислоЛет)) + " " + Сред(СтрокаЧислоЛетМесяцев, ПозицияПослеЛет);
            РасшифровкаСрокаПолезногоИспользования = СтрЗаменить(РасшифровкаСрокаПолезногоИспользования, " 0", " ") + СтрЗаменить(Суффикс, "#$", "д");
        КонецЕсли;
    КонецЕсли;
    
    Возврат РасшифровкаСрокаПолезногоИспользования;
КонецФункции

Важные особенности и возможные ошибки

Проанализируем ключевые нюансы работы данного механизма:

  1. Ограничения поиска и сортировки: Поскольку колонка рассчитывается динамически в момент отрисовки строк на клиенте, стандартный платформенный поиск, отборы и сортировка по сформированному значению СтажСтрокой работать на уровне базы данных не будут. Сортировку и фильтрацию следует выполнять по исходному числовому полю Стаж.
  2. Ошибка нарушения ключа записи: Если при изменении текста запроса динамического списка возникает ошибка о нарушении ключа записи, выясним причину: это происходит, когда в результате соединений таблиц (например, ЛЕВОЕ СОЕДИНЕНИЕ) возникают дубликаты ключевых полей (ссылок), либо если в настройках списка не задана или некорректно указана Основная таблица.
  3. Оптимизация производительности: Если для вычисления отображаемого значения требуются дополнительные запросы к базе данных, ни в коем случае не выполняйте запросы внутри цикла по строкам. Сначала соберите массив всех ссылок или ключей из переданной коллекции Строки, выполните один пакетный запрос на всю видимую порцию, а затем раздайте полученные данные по строкам.
  4. Управление оформлением ячеек: Через коллекцию Строки в обработчике ПриПолученииДанныхНаСервере можно управлять не только структурой Данные, но и коллекцией Оформление (свойства Текст, ЦветФона, ЦветТекста, Шрифт), что позволяет задавать форматированный текст ячейки без непосредственного изменения значения.
← На главную