Как вывести цену и другие данные в колонку динамического списка 1С в зависимости от реквизитов формы

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

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

Почему не стоит использовать событие ПриПолученииДанныхНаСервере

Первое, что приходит на ум многим начинающим разработчикам — использовать обработчик ПриПолученииДанныхНаСервере. Кажется логичным: мы получаем строку, проверяем реквизиты формы и подставляем нужное значение в пустую колонку.

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

Использование произвольного запроса в динамическом списке

Правильным решением является использование произвольного запроса в свойствах динамического списка. Левое соединение таблиц на уровне СУБД отрабатывает в десятки раз быстрее. Настроим наш список так, чтобы источником данных выступал запрос, а не просто основная таблица справочника.

Посмотрим на пример правильного запроса, где основной таблицей является справочник номенклатуры, а данные о ценах мы присоединяем с помощью левого соединения:


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Код КАК Код,
    Номенклатура.Наименование КАК Наименование,
    Номенклатура.Артикул КАК Артикул,
    ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
            ,
            Город = &Город И ТипЦены = &ТипЦены
        ) КАК ЦеныНоменклатурыСрезПоследних
        ПО Номенклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура

Обратим внимание на важную деталь: чтобы при отсутствии цены в регистре в колонке не отображалась пустота (значение NULL), мы оборачиваем поле функцией ЕСТЬNULL. Таким образом, если по каким-то причинам цена отсутствует, в колонку будет подставлен 0.

Решаем проблему пустых списков с помощью расширения языка СКД

Если мы оставим запрос в том виде, в каком он представлен выше, мы столкнемся с проблемой: при открытии формы 1С выдаст ошибку о том, что значения параметров &Город и &ТипЦены не заданы. Либо, если мы установим им пустые значения по умолчанию, список может оказаться совершенно пустым, пока пользователь не заполнит эти реквизиты.

Чтобы избежать этой ошибки элегантно, воспользуемся возможностями Системы Компоновки Данных (СКД). Обернем параметры виртуальной таблицы в фигурные скобки { }. Это сделает условия необязательными.


ВЫБРАТЬ
    Номенклатура.Ссылка КАК Ссылка,
    Номенклатура.Код КАК Код,
    Номенклатура.Наименование КАК Наименование,
    ЕСТЬNULL(ЦеныНоменклатурыСрезПоследних.Цена, 0) КАК Цена
ИЗ
    Справочник.Номенклатура КАК Номенклатура
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(
            ,
            {Город = &Город, ТипЦены = &ТипЦены}
        ) КАК ЦеныНоменклатурыСрезПоследних
        ПО Номенклатура.Ссылка = ЦеныНоменклатурыСрезПоследних.Номенклатура

Теперь, если параметры переданы и включены, СКД автоматически подставит их в запрос. Если они отключены, СКД проигнорирует условие, и справочник будет выведен полностью (просто колонка с ценой может быть пустой или рассчитанной без отбора по городу).

Управление параметрами динамического списка программно

Наконец, выясним, как правильно передать значения реквизитов формы в запрос при их изменении. Разместим на форме обработчики событий изменения для реквизитов «Город» и «Тип цены».

Вместо использования устаревшего или слишком жесткого метода УстановитьЗначениеПараметра, мы будем напрямую управлять элементами параметров компоновки данных. Это позволит нам включать и выключать параметры (свойство Использование) в зависимости от того, заполнен ли реквизит на форме. Рассмотрим код настройки параметров:


&НаСервере
Процедура ОбновитьПараметрыСписка()
    
    // Получаем доступ к параметру Город
    ПараметрГород = Список.Параметры.Элементы.Найти("Город");
    Если ПараметрГород <> Неопределено Тогда
        Если ЗначениеЗаполнено(Город) Тогда
            ПараметрГород.Значение = Город;
            ПараметрГород.Использование = Истина;
        Иначе
            ПараметрГород.Использование = Ложь;
        КонецЕсли;
    КонецЕсли;
    
    // Получаем доступ к параметру ТипЦены
    ПараметрТипЦены = Список.Параметры.Элементы.Найти("ТипЦены");
    Если ПараметрТипЦены <> Неопределено Тогда
        Если ЗначениеЗаполнено(ТипЦены) Тогда
            ПараметрТипЦены.Значение = ТипЦены;
            ПараметрТипЦены.Использование = Истина;
        Иначе
            ПараметрТипЦены.Использование = Ложь;
        КонецЕсли;
    КонецЕсли;

КонецПроцедуры

Этот серверный метод мы должны вызывать в двух местах:

  1. В обработчике формы ПриСозданииНаСервере — чтобы при открытии формы сразу применить текущие (возможно пустые) настройки и избежать ошибки отсутствующих параметров.
  2. В обработчике ПриИзменении соответствующих полей ввода на клиенте, вызывая затем обновление списка на экране.

Пример вызова при изменении на клиенте:


&НаКлиенте
Процедура ГородПриИзменении(Элемент)
    ОбновитьПараметрыСпискаНаСервере();
    Элементы.Список.Обновить(); // Вызываем явное обновление динамического списка
КонецПроцедуры

Резюмируем проделанную работу: мы отказались от ресурсоемких серверных обработчиков строк, перенесли логику на уровень базы данных с помощью левого соединения в произвольном запросе динамического списка. Мы защитили форму от ошибок пустых параметров, используя синтаксис СКД {}, и написали надежный код для управления свойством Использование параметров компоновки данных. Такой подход обеспечивает быструю работу интерфейса и соответствует стандартам разработки 1С.

← На главную