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

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

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

В этой статье мы подробно разберем, как решить эту задачу, используя программный подход. Мы рассмотрим основные методы и объекты 1С, которые помогут нам добиться желаемого результата, и создадим ощущение совместной работы.

Программная установка параметров СКД в процедуре "ПриКомпоновкеРезультата"

Основной и наиболее универсальный способ передачи произвольного значения в параметр СКД — это его программная установка. Этот подход реализуется в процедуре ПриКомпоновкеРезультата модуля объекта отчета. Давайте разберем по шагам, как это работает.

  1. Выясним причину: Стандартный механизм формирования отчета на СКД сначала применяет настройки, затем компонует макет и выводит результат. Процедура ПриКомпоновкеРезультата вызывается как раз перед окончательным формированием результата, что дает нам возможность "перехватить" и изменить настройки компоновщика.
  2. Получим текущие настройки: Нам нужно получить объект настроек компоновщика, чтобы внести в него изменения. Для этого мы используем свойство КомпоновщикНастроек и метод ПолучитьНастройки().
    
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
  3. Определимся со значением: Прежде чем установить параметр, нам нужно получить то самое значение, которое мы хотим передать. Это может быть значение из табличной части, результат запроса или любая другая логика. Давайте посмотрим на пример функции, которая может получить такое значение. Мы можем назвать её, например, ПолучитьЗначениеДляПараметра().
    
    // Функция, которая получает нужное значение
    Функция ПолучитьЗначениеДляПараметра()
        // Здесь может быть логика получения значения:
        // - Выполнение запроса к базе данных
        // - Обращение к данным табличной части какого-либо объекта
        // - Расчет по определенным правилам
        // - Значение, переданное из формы отчета
    
        // Пример: Получение значения из запроса
        Запрос = Новый Запрос;
        Запрос.Текст = "ВЫБРАТЬ ПЕРВЫЕ 1
                       |    Документ.Товары.Номенклатура КАК Номенклатура
                       |ИЗ
                       |    Документ.РеализацияТоваровУслуг.Товары КАК ДокументТовары
                       |ГДЕ
                       |    ДокументТовары.Ссылка = &СсылкаДокумента";
    
        // Предположим, что мы знаем ссылку на документ, из которого берем табличную часть
        // В реальной ситуации СсылкаДокумента может быть получена из параметра отчета
        // или из глобального контекста, если это отчет по конкретному документу
        СсылкаДокумента = Справочники.РеализацииТоваровУслуг.НайтиПоКоду("000000001"); 
        Если СсылкаДокумента = Неопределено Тогда
            Возврат Неопределено;
        КонецЕсли;
    
        Запрос.УстановитьПараметр("СсылкаДокумента", СсылкаДокумента);
    
        РезультатЗапроса = Запрос.Выполнить();
        Если НЕ РезультатЗапроса.Пустой() Тогда
            Выборка = РезультатЗапроса.Выбрать();
            Выборка.Следующий();
            Возврат Выборка.Номенклатура;
        Иначе
            Возврат Неопределено;
        КонецЕсли;
    КонецФункции
    

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

  4. Установим значение параметра: Теперь, когда у нас есть настройки и необходимое значение, мы можем установить его для нашего параметра СКД. Для этого мы обращаемся к коллекции ПараметрыДанных объекта Настройки и используем метод УстановитьЗначениеПараметра().
    
    // Устанавливаем значение параметра СКД
    // "ИмяТвоегоПараметра" - это имя параметра, которое вы задали в схеме СКД
    Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ИмяТвоегоПараметра", ПолучитьЗначениеДляПараметра());
    

    Метод УстановитьЗначениеПараметра() принимает два аргумента: имя параметра (строка) и значение, которое мы хотим присвоить.

  5. Загрузим измененные настройки: После того как мы внесли изменения в объект Настройки, нам необходимо "вернуть" их компоновщику, чтобы он использовал их при формировании отчета.
    
    КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);
    

Вся эта логика должна быть размещена в процедуре ПриКомпоновкеРезультата модуля объекта отчета. Давайте проанализируем ситуацию и соберем полный пример:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    // Отменяем стандартную обработку, чтобы полностью контролировать процесс
    СтандартнаяОбработка = Ложь; 
    
    // Получаем текущие настройки компоновщика
    Настройки = КомпоновщикНастроек.ПолучитьНастройки();
    
    // Получаем значение, которое хотим передать в параметр
    ЗначениеПараметра = ПолучитьЗначениеДляПараметра();
    
    // Проверяем, что значение получено и не является Неопределено
    Если ЗначениеПараметра <> Неопределено Тогда
        // Устанавливаем значение для нашего параметра СКД
        // Замените "ИмяТвоегоПараметра" на фактическое имя параметра в вашей схеме СКД
        Настройки.ПараметрыДанных.УстановитьЗначениеПараметра("ИмяТвоегоПараметра", ЗначениеПараметра);
        
        // Также важно убедиться, что параметр используется, если он был отключен ранее
        // Это особенно актуально, если параметр изначально не был помечен как "Использовать"
        Для Каждого ЭлементПараметра Из Настройки.ПараметрыДанных.Элементы Цикл
            Если ЭлементПараметра.Параметр = "ИмяТвоегоПараметра" Тогда
                ЭлементПараметра.Использование = Истина;
                Прервать;
            КонецЕсли;
        КонецЦикла;
    КонецЕсли;
    
    // Загружаем измененные настройки обратно в компоновщик
    КомпоновщикНастроек.ЗагрузитьНастройки(Настройки);

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

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

// Функция, которая получает нужное значение (как описано выше)
Функция ПолучитьЗначениеДляПараметра()
    // ... ваша логика получения значения ...
    Возврат "ПримерЗначения"; 
КонецФункции

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

Использование собственной формы для выбора значения параметра

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

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

    После того как пользователь сделал свой выбор или ввел данные, мы получаем итоговое значение.

  3. Передача значения в параметры СКД: Когда пользователь нажимает кнопку "Сформировать" на нашей кастомной форме, мы вызываем формирование отчета. При этом полученное на форме значение мы передаем в процедуру ПриКомпоновкеРезультата (или другую процедуру, которая вызывает формирование отчета). Это можно сделать, например, через параметры процедуры или через свойства самого отчета, если форма является формой объекта отчета.
    
    // Пример кода в модуле формы отчета (при нажатии кнопки "Сформировать")
    
    // Получаем значение, выбранное пользователем на форме
    ЗначениеВыбранноеНаФорме = ЭлементыФормы.ПолеВыбораНоменклатуры.Значение;
    
    // Передаем это значение в объект отчета, который затем его использует
    // в процедуре ПриКомпоновкеРезультата
    ОтчетОбъект.ВременныйПараметрДляСКД = ЗначениеВыбранноеНаФорме;
    
    // Вызываем стандартное формирование отчета
    СформироватьОтчет(); 
    

    А в процедуре ПриКомпоновкеРезультата мы можем получить это значение так:

    
    Функция ПолучитьЗначениеДляПараметра()
        // Значение было передано через свойство объекта отчета из формы
        Возврат ЭтотОбъект.ВременныйПараметрДляСКД;
    КонецФункции
    

Этот подход дает максимальную гибкость в интерфейсе для пользователя и позволяет реализовать практически любую логику получения значения для параметра СКД.

Таким образом, мы видим, что, хоть СКД и является мощным инструментом, всегда есть способы расширить её функциональность с помощью программного кода, когда стандартных средств оказывается недостаточно. Мы разобрали, как это сделать, используя процедуру ПриКомпоновкеРезультата и, при необходимости, собственную форму отчета.

← К списку