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

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

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

Проблема использования функций в динамическом списке

Рассмотрим ситуацию: у нас есть справочник Пользователи с реквизитом Ставка и константа Оклад. Нам нужно в списке пользователей вывести колонку «Получает», которая равна произведению этих величин. Многие начинающие разработчики пытаются решить это через событие ПриАктивизацииСтроки или попытку вызвать функцию в оформлении строки. Однако динамический список — это прежде всего запрос к базе данных. Прямой вызов программных функций в каждой строке списка привел бы к катастрофическому падению производительности, так как список считывает данные порциями (динамически) при прокрутке.

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

Решение 1. Использование параметров запроса (Рекомендуемый способ)

Этот метод считается наиболее производительным и чистым с точки зрения архитектуры. Мы передаем значение константы в запрос как параметр. Проанализируем, как это реализовать по шагам.

Во-первых, нам необходимо настроить текст запроса в свойствах динамического списка (установив флаг «Произвольный запрос»). В тексте запроса мы добавим вычисляемое поле:


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

Обратите внимание на конструкцию &Оклад. Это именованный параметр. Чтобы система знала, что туда подставить, нам нужно инициализировать его при создании формы на сервере. Разберем код в модуле формы:


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

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

Решение 2. Прямое соединение с таблицей констант в запросе

Если вы не хотите программно передавать параметры, можно обратиться к таблице констант прямо в тексте запроса. Посмотрим на пример реализации такого запроса:


ВЫБРАТЬ
    СправочникДанные.Ссылка,
    СправочникДанные.Наименование,
    СправочникДанные.Ставка,
    СправочникДанные.Ставка * Оклад.Значение КАК Получает
ИЗ
    Справочник.Данные КАК СправочникДанные,
    Константа.Оклад КАК Оклад

Рассмотрим подробнее, как это работает. В блоке ИЗ мы перечисляем две таблицы через запятую. В языке запросов 1С это означает «Левое соединение» или создание декартова произведения. Поскольку в таблице константы всегда ровно одна строка, каждая строка справочника будет дополнена значением из этой строки. Это удобно, но есть нюанс: если значение константы не задано (в таблице 0 записей или значение NULL), то весь список может оказаться пустым. Для надежности лучше использовать функцию ЕСТЬNULL.


ВЫБРАТЬ
    СправочникДанные.Ссылка,
    СправочникДанные.Ставка * ЕСТЬNULL(Оклад.Значение, 0) КАК Получает
ИЗ
    Справочник.Данные КАК СправочникДанные,
    Константа.Оклад КАК Оклад

Оптимизация типов данных

При выполнении математических операций в запросах (особенно умножения и деления) платформа 1С автоматически определяет тип результата. Однако иногда это может привести к потере точности или ошибкам отображения. Проанализируем ситуацию: если Ставка — это число (10, 2), а Оклад — (15, 0), результат может иметь избыточную или недостаточную разрядность. Хорошим тоном считается использование функции ВЫРАЗИТЬ.

Пример использования функции для контроля разрядности:


ВЫБРАТЬ
    СправочникПользователи.Ссылка,
    ВЫРАЗИТЬ(СправочникПользователи.Ставка * &Оклад КАК ЧИСЛО(15, 2)) КАК Получает
ИЗ
    Справочник.Пользователи КАК СправочникПользователи

Типичные ошибки при работе с динамическим списком

Рассмотрим ситуацию из обсуждения, где автор пытался добавить условие ГДЕ СправочникДанные.Наименование = &Наименование в динамический список основной формы справочника. Это критическая ошибка, если вы хотите видеть весь список объектов. Такое условие оставит в списке только одну строку, соответствующую параметру. Динамический список сам управляет отборами пользователя через настройки компоновки данных. Если вам нужно просто посчитать колонку для всех элементов, секция ГДЕ с жестким фильтром по конкретному элементу не нужна.

Также не стоит использовать функции общих модулей внутри запроса динамического списка. Запрос выполняется на уровне СУБД (SQL), и сервер базы данных «не знает» о существовании ваших функций в 1С. Все расчеты должны быть выполнены либо стандартными средствами языка запросов (+, -, *, /, ВЫБОР КОГДА...), либо переданы заранее рассчитанными параметрами.

Подведение итогов

Подводя итог, мы можем выделить основной алгоритм добавления расчетной колонки:

  1. Переведите динамический список в режим произвольного запроса.
  2. Добавьте в текст запроса арифметическое выражение, используя поля таблиц или параметры.
  3. Используйте ЕСТЬNULL для обработки пустых значений, чтобы расчет не возвращал пустоту вместо нуля.
  4. Если используете параметры (&ИмяПараметра), не забудьте установить их в процедуре ПриСозданииНаСервере через Список.Параметры.УстановитьЗначениеПараметра.
  5. Выведите новое поле в список элементов формы через вкладку «Путь к данным» или просто перетащив новое поле из списка доступных полей в дерево элементов.

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

← На главную