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

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

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

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

Анализ типичных ошибок

Рассмотрим код, с которого часто начинаются затруднения:


Результат = Запрос.Выполнить();
ЭлементыФормы.ДеревоЗначений.Значение = Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

// Ошибочная попытка получить значение:
ЭтаФорма.ДокументОбъект.ФактПолуфабрикаты = ЭлементыФормы.ДеревоЗначений.Значение.Колонки.КоличествоПродажПФ;

Выясним причину ошибки: обращение к свойству Колонки возвращает объект метаданных колонки таблицы или дерева (объект типа КолонкаДереваЗначений), а не само числовое значение строки. Чтобы передать число в реквизит, необходимо обратиться к конкретной строке или вычислить итог по всей коллекции строк.

Также обратим внимание на частые ошибки в тексте самого запроса:

  1. Сравнение ссылки со строкой: если поле ЦеноваяГруппа является ссылкой на справочник, выражение ЦеноваяГруппа = "Полуфабрикаты рубленные, в тесте" всегда вернет Ложь. Необходимо либо передавать ссылку в параметре запроса, либо обращаться к строковому наименованию через точку: ЦеноваяГруппа.Наименование = "...".
  2. Отсутствие ветки ИНАЧЕ: конструкция ВЫБОР КОГДА ... ТОГДА ... КОНЕЦ без ветки ИНАЧЕ 0 возвращает значение NULL для всех строк, не подошедших под условие, что может вызвать ошибки при расчете числовых сумм.

Способ 1. Получение итогового значения напрямую из результата запроса

Если требуется получить общую сумму по условию и не зависеть от визуального дерева на форме, оптимально рассчитать итог средствами самого запроса. Для этого используем секцию ИТОГИ или группировку.

Посмотрим на пример правильного формирования запроса и выборки данных:


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ТЗ.Номенклатура КАК Номенклатура,
    |    ТЗ.ЦеноваяГруппа КАК ЦеноваяГруппа,
    |    ТЗ.КоличествоПродаж КАК КоличествоПродаж,
    |    ЕСТЬNULL(ВЫБОР
    |        КОГДА ТЗ.ЦеноваяГруппа = &ЦеноваяГруппаПФ
    |            ТОГДА ТЗ.КоличествоПродаж
    |        ИНАЧЕ 0
    |    КОНЕЦ, 0) КАК КоличествоПродажПФ
    |ИЗ
    |    ВременнаяТаблица КАК ТЗ
    |ИТОГИ
    |    СУММА(КоличествоПродаж),
    |    СУММА(КоличествоПродажПФ)
    |ПО
    |    ОБЩИЕ";

Запрос.УстановитьПараметр("ЦеноваяГруппаПФ", НужнаяЦеноваяГруппаСсылка);
Результат = Запрос.Выполнить();

// Выгружаем иерархию в элемент управления на форме
ЭлементыФормы.ДеревоЗначений.Значение = Результат.Выгрузить(ОбходРезультатаЗапроса.ПоГруппировкамСИерархией);

// Получаем общую сумму напрямую из корневой выборки
Выборка = Результат.Выбрать(ОбходРезультатаЗапроса.ПоГруппировкам);
Если Выборка.Следующий() Тогда
    ЭтаФорма.ДокументОбъект.ФактПолуфабрикаты = Выборка.КоличествоПродажПФ;
КонецЕсли;

Способ 2. Использование метода Итог() у коллекции строк дерева

Если дерево значений уже сформировано и выгружено на форму, мы можем воспользоваться встроенным методом коллекции строк Итог(). Разберем важную особенность: у объекта КоллекцияСтрокДереваЗначений данный метод принимает второй параметр ВключаяПодчиненные.

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


Дерево = ЭлементыФормы.ДеревоЗначений.Значение;

// Второй параметр Истина позволяет рассчитать сумму по всем уровням иерархии
СуммаПФ = Дерево.Строки.Итог("КоличествоПродажПФ", Истина);

ЭтаФорма.ДокументОбъект.ФактПолуфабрикаты = СуммаПФ;

Важно: для корректной работы метода Итог() в колонке дерева не должно быть значений NULL, а все пустые значения должны быть инициализированы нулями.

Способ 3. Группировка дерева по ценовым группам

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

Разберем по шагам, как найти нужную строку в дереве и получить значение:


Дерево = ЭлементыФормы.ДеревоЗначений.Значение;

// Вариант 1: Прямой поиск строки верхнего уровня через цикл
Для Каждого СтрокаГруппы Из Дерево.Строки Цикл
    Если СтрокаГруппы.ЦеноваяГруппа = НужнаяЦеноваяГруппаСсылка Тогда
        ЭтаФорма.ДокументОбъект.ФактПолуфабрикаты = СтрокаГруппы.КоличествоПродаж;
        Прервать;
    КонецЕсли;
КонецЦикла;

// Вариант 2: Использование метода НайтиСтроки с рекурсивным поиском
Отбор = Новый Структура("ЦеноваяГруппа", НужнаяЦеноваяГруппаСсылка);
НайденныеСтроки = Дерево.Строки.НайтиСтроки(Отбор, Истина);

Если НайденныеСтроки.Количество() > 0 Тогда
    ЭтаФорма.ДокументОбъект.ФактПолуфабрикаты = НайденныеСтроки[0].КоличествоПродаж;
КонецЕсли;

Особенности отображения данных на форме

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

Если реквизит создан непосредственно в самой форме (без привязки к реквизитам документа), то присвоение выполняется напрямую по имени реквизита:

ФактПолуфабрикаты = СуммаПФ;

← На главную