Как программно открыть штатный отчет в УТ 11 с отборами, расшифровкой и изменением группировок?

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

В процессе разработки и кастомизации конфигураций на платформе «1С:Предприятие 8.3» (таких как «Управление торговлей 11», «ERP Управление предприятием» или «Комплексная автоматизация») программисты часто сталкиваются с необходимостью открывать штатные отборы напрямую из документов. Типичный пример — открытие отчета «Остатки и доступность товаров» прямо из строки табличной части документа (будь то «Заказ клиента» или «Реализация товаров и услуг»), минуя открытие карточки номенклатуры.

Простая попытка вызвать форму отчета стандартным методом ОткрытьФорму часто приводит к тому, что отчет открывается в урезанном («ущербном») виде: без условного оформления, без раскраски ячеек, а главное — без возможности интерактивной расшифровки. В этой статье мы подробно разберем, как решить эту задачу правильно, используя штатные механизмы БСП (Библиотеки стандартных подсистем), передать нужные параметры и даже программно изменить группировки отчета при его открытии.

Причина проблемы: почему стандартный вызов ломает отчет?

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

Чтобы решить эту проблему, необходимо передавать параметры так, как это делает сама система при вызове команд из стандартных интерфейсов. Рассмотрим несколько рабочих способов реализации этой задачи.

Способ 1. Программное открытие через параметры команды (решение с форума)

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

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


Процедура ОткрытьОтчетОстаткиИДоступностьТоваровИзДокумента(ФормаВладелец, Товар) Экспорт

    ПараметрыОткрытия = Новый Структура;
    ПараметрыОткрытия.Вставить("ВидимостьКомандВариантовОтчетов", Ложь);
    ПараметрыОткрытия.Вставить("КлючВарианта", "ПоНоменклатуреКонтекст");
    ПараметрыОткрытия.Вставить("ПараметрКоманды", Товар);
    ПараметрыОткрытия.Вставить("СформироватьПриОткрытии", Истина);
    
    Отбор = Новый Структура;
    Отбор.Вставить("Номенклатура", Товар);
    
    Если Отбор.Количество() > 0 Тогда
        ПараметрыОткрытия.Вставить("Отбор", Отбор);
    КонецЕсли;
    
    ОткрытьФорму("Отчет.ОстаткиИДоступностьТоваров.Форма", ПараметрыОткрытия, ФормаВладелец, Истина);

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

Что здесь происходит:

  1. Мы передаем параметр КлючВарианта со значением "ПоНоменклатуреКонтекст". Это указывает системе, какой именно предопределенный вариант отчета нужно использовать.
  2. Параметр ПараметрКоманды передает ссылку на товар, что позволяет БСП корректно инициализировать расшифровки.
  3. Флаг СформироватьПриОткрытии автоматически запускает расчет отчета сразу после вывода формы на экран, избавляя пользователя от необходимости нажимать кнопку «Сформировать».
  4. Мы передаем ФормуВладельца и признак уникальности открытия формы (последний параметр Истина), чтобы при повторном нажатии открывалось новое или обновлялось текущее окно.

Способ 2. Рекомендованный вызов через API БСП

Хотя прямой вызов ОткрытьФорму работает, в современных версиях конфигураций 1С рекомендуется использовать штатный программный интерфейс БСП. Это гарантирует стабильность работы при обновлениях конфигурации. Для этого предназначен метод ВариантыОтчетовКлиент.ОткрытьФормуОтчета.

Давайте разберем, как будет выглядеть вызов в этом случае:


ПараметрыОтчета = Новый Структура;
ПараметрыОтчета.Вставить("Отбор", Новый Структура("Номенклатура", ВыбранныйТовар));
ПараметрыОтчета.Вставить("СформироватьПриОткрытии", Истина);

// Ищем ссылку на предопределенный вариант отчета
ВариантОтчета = ВариантыОтчетов.ПолучитьВариант("Отчет.ОстаткиИДоступностьТоваров", "ПоНоменклатуреКонтекст");

Если ЗначениеЗаполнено(ВариантОтчета) Тогда
    ВариanteОтчетовКлиент.ОткрытьФормуОтчета(ФормаВладелец, ВариантОтчета, ПараметрыОтчета);
КонецЕсли;

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

Способ 3. Передача отборов в область «Пользовательских настроек»

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

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

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


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

Использование общего модуля КомпоновкаДанныхКлиентСервер позволяет корректно связать элементы отбора схемы компоновки данных с пользовательскими настройками формы. При таком подходе пользователь сможет легко очистить или изменить отбор непосредственно на панели быстрых настроек отчета.

Программное изменение структуры группировок (Глубокая кастомизация)

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

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


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

&НаСервере
Функция НайтиГруппировкуПоИмениПоля(КоллекцияСтруктурыКД, ИмяПоля)
    
    Если КоллекцияСтруктурыКД = Неопределено Тогда
        Возврат Неопределено;
    КонецЕсли;
    
    ИскомоеПоле = Новый ПолеКомпоновкиДанных(ИмяПоля);
    
    Для Каждого ЭлементСтруктуры Из КоллекцияСтруктурыКД Цикл
        
        Если Тип(ЭлементСтруктуры) <> Тип("ГруппировкаКомпоновкиДанных") Тогда
            Продолжить;
        КонецЕсли;
        
        Для Каждого ПолеГруппировки Из ЭлементСтруктуры.ПоляГруппировки.Элементы Цикл
            Если Тип(ПолеГруппировки) <> Тип("ПолеГруппировкиКомпоновкиДанных") Тогда
                Продолжить;
            КонецЕсли;
            
            Если ПолеГруппировки.Поле = ИскомоеПоле Тогда
                Возврат ЭлементСтруктуры;
            КонецЕсли;
        КонецЦикла;
        
        // Рекурсивный обход вложенных уровней структуры компоновщика
        РезультатПоиска = НайтиГруппировкуПоИмениПоля(ЭлементСтруктуры.Структура, ИмяПоля);
        Если РезультатПоиска <> Неопределено Тогда
            Возврат РезультатПоиска;
        КонецЕсли;
        
    КонецЦикла;
    
    Возврат Неопределено;
    
КонецФункции

Важная деталь: При изменении настроек в компоновщике через события расширения, если вы не видите визуальных изменений на форме, попробуйте сбросить настройки отчета к стандартным через меню «Еще -> Установить стандартные настройки». Платформа кэширует пользовательские настройки, и это действие очистит устаревший кэш.

Резюме

Для успешного решения задачи программного открытия штатных отчетов в среде УТ 11 / ERP следуйте трем простым правилам:

  1. Всегда передавайте ПараметрКоманды для сохранения работоспособности интерактивных расшифровок БСП.
  2. Для простых отборов используйте готовые методы общего модуля КомпоновкаДанныхКлиентСервер, чтобы отборы попадали в область пользовательских настроек, а не блокировали интерфейс.
  3. Если требуется сложная модификация структуры компоновки (группировки, сортировки) перед выводом, используйте точки расширения ПередЗагрузкойНастроекВКомпоновщик в модулях объектов отчетов.
← На главную