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

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

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

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

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

Динамический список работает принципиально иначе: он считывает данные напрямую из базы с помощью SQL-запроса порциями по мере прокрутки таблицы на клиенте. Список документов физически не имеет доступа к объектам контекста формы конкретного документа. Создание дополнительного реквизита объекта в метаданных для хранения расчетной строки также не всегда оправдано: реквизит в базе данных требует постоянного контроля актуализации при любых изменениях связанных документов. Поэтому правильный путь — получать данные непосредственно из базы при формировании списка.

Вариант 1. Модификация запроса динамического списка

Рассмотрим основной и наиболее универсальный метод — включение необходимых данных в текст запроса самого динамического списка. В конфигурации «Бухгалтерия предприятия 3.0» информация о счетах-фактурах хранится в подчиненных документах, ссылающихся на документ-основание через табличную часть ДокументыОснования.

Разберем по шагам порядок настройки:

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

Посмотрим на пример текста запроса для динамического списка документов «Корректировка поступления»:


ВЫБРАТЬ
    ДокументКорректировка.Ссылка КАК Ссылка,
    ДокументКорректировка.ПометкаУдаления КАК ПометкаУдаления,
    ДокументКорректировка.Номер КАК Номер,
    ДокументКорректировка.Дата КАК Дата,
    ДокументКорректировка.Проведен КАК Проведен,
    ДокументКорректировка.Контрагент КАК Контрагент,
    ДокументКорректировка.СуммаДокумента КАК СуммаДокумента,
    ВложенныйЗапрос.ПредставлениеСФ КАК ПредставлениеСФ
ИЗ
    Документ.КорректировкаПоступления КАК ДокументКорректировка
    ЛЕВОЕ СОЕДИНЕНИЕ (
        ВЫБРАТЬ
            СФОснования.ДокументОснование КАК ДокументОснование,
            МАКСИМУМ(СФ.Номер + " от " + ФОРМАТ(СФ.Дата, "ДФ=dd.MM.yyyy")) КАК ПредставлениеСФ
        ИЗ
            Документ.СчетФактураПолученный.ДокументыОснования КАК СФОснования
            ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.СчетФактураПолученный КАК СФ
                ПО СФОснования.Ссылка = СФ.Ссылка
                И НЕ СФ.ПометкаУдаления
        СГРУППИРОВАТЬ ПО
            СФОснования.ДокументОснование
    ) КАК ВложенныйЗапрос
    ПО ВложенныйЗапрос.ДокументОснование = ДокументКорректировка.Ссылка

Преимущества подхода с запросом:

  1. По добавленному полю платформа сохраняет возможность выполнять стандартный поиск, сортировку и установку пользовательских отборов.
  2. Получение данных выполняется за один запрос к СУБД вместе со всей порцией строк списка.

Вариант 2. Использование обработчика события «ПриПолученииДанныхНаСервере»

Если логика формирования надписи слишком сложна для языка запросов (например, вызывает типовые функции подсистемы НДС с множеством проверок статусов), рассмотрим программное заполнение строк на сервере.

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

Разберем по шагам реализацию этого метода:

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

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


&НаСервере
Процедура СписокПриПолученииДанныхНаСервере(Элемент, ОформленияСтрок)
    
    МассивСсылок = ОформленияСтрок.ПолучитьКлючи();
    Если МассивСсылок.Количество() = 0 Тогда
        Возврат;
    КонецЕсли;
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ
        |    СФОснования.ДокументОснование КАК ДокументОснование,
        |    СФ.Ссылка КАК СчетФактура,
        |    СФ.Номер КАК Номер,
        |    СФ.Дата КАК Дата,
        |    СФ.Проведен КАК Проведен
        |ИЗ
        |    Документ.СчетФактураПолученный.ДокументыОснования КАК СФОснования
        |    ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.СчетФактураПолученный КАК СФ
        |        ПО СФОснования.Ссылка = СФ.Ссылка
        |ГДЕ
        |    СФОснования.ДокументОснование В(&МассивСсылок)
        |    И НЕ СФ.ПометкаУдаления";
    
    Запрос.УстановитьПараметр("МассивСсылок", МассивСсылок);
    Выборка = Запрос.Выполнить().Выбрать();
    
    СоответствиеДанных = Новый Соответствие;
    Пока Выборка.Следующий() Цикл
        ТекстНадписи = "№ " + СокрЛП(Выборка.Номер) + " от " + Формат(Выборка.Дата, "ДФ=dd.MM.yyyy");
        СоответствиеДанных.Вставить(Выборка.ДокументОснование, ТекстНадписи);
    КонецЦикла;
    
    Для Каждого Оформление Из ОформленияСтрок Цикл
        ЗначениеНадписи = СоответствиеДанных[Оформление.Ключ];
        Если ЗначениеНадписи <> Неопределено Тогда
            Ячейка = Оформление.Значение.Ячейки.НадписьСчетФактура;
            Ячейка.УстановитьТекст(ЗначениеНадписи);
        КонецЕсли;
    КонецЦикла;
    
КонецПроцедуры

Сравнение методов и рекомендации

Проанализируем оба решения для выбора оптимального:

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

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

← На главную