Как открыть историю периодического реквизита справочника из таблицы на переднем плане в 1С 7.7

Программист 1С v7.7 IT и автоматизация бизнеса
← На главную

При формировании отчетов и печатных форм в платформе 1С:Предприятие 7.7 нередко требуется предоставить пользователю возможность просматривать изменения периодических реквизитов прямо из ячейки таблицы. Однако при вызове функции открытия истории через механизм расшифровки разработчики часто сталкиваются с неприятным поведением интерфейса: окно истории открывается на заднем плане, оказываясь под сформированной таблицей, из-за чего пользователю приходится переключаться комбинацией клавиш Ctrl + Tab.

Разберем детально механизм возникновения этой проблемы и рассмотрим несколько надежных способов вывести окно истории на передний план.

Выясним причину ухода окна на задний план

Проанализируем последовательность действий, которую выполняет платформа 1С 7.7 при интерактивном взаимодействии с табличным документом:

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

Осложняет ситуацию и особенность платформы при работе со специальными формами: при вызове ОткрытьФорму() для истории периодического реквизита контекст созданной формы не возвращается во второй параметр метода. Соответственно, мы не можем применить стандартный метод Активизировать() программно.

Способ 1. Использование модального режима открытия

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

Посмотрим на пример реализации:


Функция ИсторияОткрыть()
    Если Контрагент.Выбран() = 1 Тогда
        ОткрытьФормуМодально("История.Справочник.Контрагенты.ИстПримечания", Контрагент, ТекущаяДата());
    КонецЕсли;    
КонецФункции

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

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

Способ 2. Штатная обработка расшифровки через ОбработкаЯчейкиТаблицы

Рассмотрим наиболее правильный с точки зрения архитектуры платформы 1С 7.7 подход. Вместо прямого вызова функции из ячейки таблицы задействуем предопределенную процедуру ОбработкаЯчейкиТаблицы в модуле формы отчета или обработки.

Разберем по шагам порядок настройки:

  1. В свойствах ячейки таблицы в поле Расшифровка укажем не вызов функции, а само значение объекта, по которому требуется просматривать историю (например, переменную Контрагент или строку-идентификатор).
  2. В модуле формы отчета опишем предопределенную процедуру ОбработкаЯчейкиТаблицы.
  3. Внутри процедуры обязательно сбросим параметр Флаг = 0. Это сообщит платформе о том, что стандартную обработку клика выполнять не нужно, благодаря чему таблица не будет возвращать себе фокус.

Посмотрим на пример кода в модуле формы:


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

При таком подходе окно открывается немодально и сразу оказывается на переднем плане, так как внутренний механизм возврата фокуса в таблицу подавляется параметром Флаг = 0.

Способ 3. Отложенный запуск через ОбработкаОжидания

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

Идея заключается в том, чтобы дать таблице полностью завершить цикл обработки события нажатия кнопки мыши и лишь затем открыть новое окно.

Разберем реализацию этого механизма:


Перем глКонтрагентДляИстории;

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

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

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

Совет: предотвращение залипания окон через уникальный идентификатор

При активной работе с историей периодических реквизитов для разных элементов справочника полезно использовать суффикс уникальности окна. Если в строке вызова формы в конце указать символ решетки #, платформа 1С 7.7 создаст независимый экземпляр окна:


ОткрытьФорму("История.Справочник.Контрагенты.ИстПримечания#", , Значение, ТекущаяДата());

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

← На главную