Как программно открыть отчет СКД с отбором и сразу сформировать его в 1С 8.3?

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

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

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

Выясняем причину: почему старый подход больше не работает?

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


ОтчетПоДепозитам = Отчеты.ОтчётПоДепозитам.Создать();
ФормаОтчета = ОтчетПоДепозитам.ПолучитьФорму("ФормаОтчета");
ФормаОтчета.Открыть();

В управляемом приложении (тонкий и веб-клиент) этот код вызывает ошибку по нескольким причинам:

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

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

Рассмотрим по шагам основные способы решения этой задачи в зависимости от сложности требуемого отбора.

Способ 1. Простой отбор с помощью структуры «Отбор»

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

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

Рассмотрим пример кода, который выполняется на клиенте:


&НаКлиенте
Процедура ОткрытьОтчетСПростымОтбором(СсылкаНаДепозит)
    
    // Шаг 1. Создаем структуру отбора.
    // Ключ структуры должен в точности совпадать с именем поля в схеме компоновки данных (СКД).
    СтруктураОтбора = Новый Структура;
    СтруктураОтбора.Вставить("Депозит", СсылкаНаДепозит); 
    
    // Шаг 2. Формируем параметры для открытия формы отчета
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("Отбор", СтруктураОтбора);
    
    // Параметр "СформироватьПриОткрытии" указывает платформе, что отчет нужно заполнить сразу
    ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
    
    // Шаг 3. Открываем форму отчета. Объект отчета создается платформой автоматически.
    ОткрытьФорму("Отчет.ОтчетПоДепозитам.Форма.ФормаОтчета", ПараметрыФормы);
    
КонецПроцедуры

Этот метод чрезвычайно эффективен: он не требует серверных вызовов со стороны разработчика, не загромождает код и отрабатывает максимально быстро.

Способ 2. Сложные отборы через «ФиксированныеНастройки»

Что делать, если простого сравнения на равенство недостаточно? Например, если перед нами стоит задача установить отбор по списку значений (вид сравнения ВСписке), интервалу дат или сделать отбор по иерархии справочника.

Для таких сценариев стандартный параметр Отбор не подойдет. Вместо него мы будем использовать другой параметр формы — ФиксированныеНастройки. В него передается объект типа НастройкиКомпоновкиДанных, содержащий нужные нам элементы отбора.

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

Разберем по шагам, как реализовать этот подход на клиенте:


&НаКлиенте
Процедура ОткрытьОтчетСоСложнымОтбором(МассивДепозитов)
    
    // Шаг 1. Инициализируем настройки компоновки данных
    НастройкиКомпоновки = Новый НастройкиКомпоновкиДанных;
    
    // Шаг 2. Создаем и заполняем элемент отбора
    ЭлементОтбора = НастройкиКомпоновки.Отбор.Элементы.Добавить(Тип("ЭлементОтбораКомпоновкиДанных"));
    
    // Указываем левое значение (поле СКД)
    ЭлементОтбора.ЛевоеЗначение = Новый ПолеКомпоновкиДанных("Депозит");
    
    // Задаем вид сравнения - в нашем случае это "В списке"
    ЭлементОтбора.ВидСравнения = ВидСравненияКомпоновкиДанных.ВСписке;
    
    // Указываем правое значение (массив или список значений)
    ЭлементОтбора.ПравоеЗначение = МассивДепозитов;
    ЭлементОтбора.Использование = Истина;
    
    // Шаг 3. Подготавливаем параметры открытия формы
    ПараметрыФормы = Новый Структура;
    ПараметрыФормы.Вставить("ФиксированныеНастройки", НастройкиКомпоновки);
    ПараметрыФормы.Вставить("СформироватьПриОткрытии", Истина);
    
    // Шаг 4. Открываем форму отчета
    ОткрытьФорму("Отчет.ОтчетПоДепозитам.Форма.ФормаОтчета", ПараметрыФормы);
    
КонецПроцедуры

Способ 3. Перехват параметров внутри самой формы отчета

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

Для этого откроем модуль формы нашего отчета ОтчетПоДепозитам и обратимся к событию ПриСозданииНаСервере. Здесь мы можем проанализировать переданные параметры и принудительно включить автоформирование:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяОбработка)
    
    // Проверяем, передан ли наш специфический параметр извне
    Если Параметры.Свойство("МойСпециальныйПараметр") Тогда
        // Устанавливаем признак автоматического формирования
        Параметры.СформироватьПриОткрытии = Истина;
    КонецЕсли;
    
КонецПроцедуры

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

Альтернативный вариант: формирование отчета на сервере без вывода формы

Стоит упомянуть важное замечание из обсуждения на форуме (сообщение 6): "на сервере не нужно форму создавать. нужно отчет делать таким чтоб он без формы мог формироваться".

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

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


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

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

Резюме

Мы подробно разобрали, как решить проблему «замкнутого круга» при работе с отчетами в управляемых формах 1С 8.3. Подведем итоги:

← На главную