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