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

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

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

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

Почему стандартные события СКД не поддерживают «Отказ»?

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

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

Решение 1. Полное переопределение интерфейса выбора вариантов (Рекомендуемый подход)

Если отчет спроектирован как редактируемый АРМ, наиболее надежный и контролируемый способ — заблокировать для пользователя стандартные интерактивные элементы БСП и реализовать собственные кнопки переключения вариантов.

Рассмотрим пошагово, как это сделать:

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

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

Если пользователь выбирает «Да», мы запускаем процедуру сохранения данных и затем переключаем вариант. Если «Нет» — переключаем без сохранения. Если «Отмена» — мы просто остаемся на текущем варианте, полностью предотвращая его смену.

Решение 2. Асинхронный откат (Rollback) через обработчик ожидания

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

Давайте разберем алгоритм реализации:

  1. В реквизитах формы сохраняем текущее значение варианта в переменную ПредыдущийКлючВарианта.
  2. В обработчике события ПередЗагрузкойВариантаНаСервере анализируем, изменился ли ключ варианта по сравнению с сохраненным. Если ключ изменился и в форме взведен флаг модифицированности, мы фиксируем этот факт во временной переменной формы: ТребуетсяПодтверждениеСменыВарианта = Истина.
  3. Поскольку мы не можем прервать серверный вызов диалогом, мы подключаем на клиенте однократный обработчик ожидания с минимальным интервалом времени:

&НаКлиенте
Процедура ПослеЗагрузкиВарианта()
    Если ТребуетсяПодтверждениеСменыВарианта Тогда
        ПодключитьОбработчикОжидания("ПроверитьНесохраненныеДанныеПриСменеВарианта", 0.1, Истина);
    КонецЕсли;
КонецПроцедуры

В процедуре ПроверитьНесохраненныеДанныеПриСменеВарианта мы выводим пользователю стандартный вопрос. Если пользователь нажимает «Отмена», мы программно возвращаем старый вариант, используя метод УстановитьТекущийВариант(ПредыдущийКлючВарианта).

Решение 3. Тонкости программного переключения вариантов

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

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


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

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

Решение 4. Использование новых возможностей платформы (8.3.25 и выше)

Если вы работаете на современных версиях платформы «1С:Предприятие» (начиная с версии 8.3.25), управление интерактивными процессами в отчетах стало значительно проще. В платформу было добавлено клиентское событие формы отчета ПриИзмененииНастроек с параметром СтандартнаяОбработка.

Давайте посмотрим, как это упрощает нашу задачу:

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

← На главную