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

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

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

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

Причина проблемы: Клиент-серверное разделение

Основная ошибка начинающих разработчиков при попытке закрыть форму отчета заключается в непонимании контекста выполнения кода. Посмотрим на стандартное событие модуля объекта отчета:


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    // Этот код выполняется строго на СЕРВЕРЕ
    // Попытка вызвать здесь клиентские методы формы вызовет ошибку
    ЭтаФорма.Закрыть(); // Ошибка! Переменная "ЭтаФорма" не определена
КонецПроцедуры

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

Для решения задачи нам потребуется связать серверное событие компоновки с клиентским событием формы. Рассмотрим несколько способов реализации.

Решение 1. Закрытие формы на клиенте после компоновки (через расширение формы)

Если вам необходимо закрыть форму сразу после того, как отчет был успешно сформирован, и это решение зависит от установленного пользователем параметра (например, булевого флага «Записывать данные»), мы можем перехватить клиентское событие завершения компоновки.

Для этого в расширении управляемой формы отчета перехватим стандартную команду компоновки с помощью аннотации &После:


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

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

Решение 2. Программное прерывание построения отчета на сервере

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

Вариант А. Сброс стандартной обработки

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


Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
    
    Если ПараметрыНеЗаполнены() Тогда
        СтандартнаяОбработка = Ложь; // Отменяем стандартное формирование
        Возврат; // Прерываем выполнение процедуры
    КонецЕсли;
    
КонецПроцедуры

Вариант Б. Детальный программный вывод (построчный контроль)

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


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

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

Решение 3. Использование штатных механизмов БСП

В современных конфигурациях «1С:Предприятие» (УТ, ERP, КА, БП) отчеты функционируют под управлением Библиотеки Стандартных Подсистем (БСП). Формирование таких отчетов по умолчанию выполняется в **фоновом режиме** (в фоновом задании на сервере), чтобы интерфейс пользователя не зависал. В аналогичном автономном режиме можно выполнять автоматическое обновление и обслуживание нескольких баз по расписанию.

В БСП предусмотрены штатные механизмы перехвата окончания формирования отчетов, что избавляет нас от необходимости писать сложные расширения к формам отчетов:

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

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

&НаКлиенте
Процедура ПослеЗакрытияИлиВыполненияОтчета(Результат, ДополнительныеПараметры) Экспорт
    // Сюда вернется управление, когда отчет закончит работу
    ПоказатьПредупреждение(, "Отчет успешно отработал!");
КонецПроцедуры

Архитектурный стандарт «1С»: Почему нельзя писать данные из отчета?

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

Согласно стандартам архитектуры «1С:Предприятия»:

Если вам требуется сначала показать пользователю результаты расчетов, а затем записать их, реализуйте это правильно:

  1. Создайте объект класса Обработка вместо Отчета.
  2. Разместите на форме обработки табличную часть или динамическую таблицу для демонстрации результатов пользователю.
  3. Создайте явную команду (кнопку) «Записать данные в документ». По ее нажатию выполняйте запись данных на сервере, а затем на клиенте вызывайте метод ЭтаФорма.Закрыть().

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

← На главную