Почему при вызове ПолучитьФорму срабатывает ПриАктивизацииСтроки до ПриОткрытии и как это исправить

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

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

Если в процедуре активизации строки используются переменные модуля формы, инициализируемые только при открытии, система завершает работу с аварийной ошибкой. Причем ошибка часто воспроизводится выборочно — только у одного конкретного пользователя, в то время как у остальных пользователей и на тестовых копиях базы всё открывается штатно. Разберем детально механизм возникновения этой проблемы и рассмотрим все варианты её решения.

Анализ жизненного цикла обычной формы и причин поведения

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

  1. Разделение создания и открытия формы. Метод ПолучитьФорму() полностью конструирует объект формы и создает все связанные с ней элементы интерфейса в памяти. Однако обработчик ПриОткрытии() вызывается только при непосредственном отображении окна на экране (после вызова Форма.Открыть() или Форма.ОткрытьМодально()). До этого момента модуль формы уже существует, а графические элементы управления уже связаны с источниками данных.
  2. Восстановление настроек пользователя. При создании формы платформа автоматически восстанавливает индивидуальные сохраненные настройки текущего пользователя: последнюю активную страницу панели, текущую строку списков, состав и ширину колонок. Если у пользователя ранее была активна вкладка с табличным полем, платформа восстанавливает позицию курсора на этой строке.
  3. Генерация событий при связывании данных. Как только табличное поле связывается со списком данных и восстанавливает позицию курсора, платформа генерирует событие ПриАктивизацииСтроки. Если форма содержит сохраненную строку, событие отрабатывает непосредственно внутри вызова ПолучитьФорму().
  4. Особенности платформы 8.3 при работе с обычными формами. При переводе конфигураций с платформы 8.2 на 8.3 изменилась строгость и последовательность инициализации табличных полей. Восстановление состояния и связывание данных в релизах 8.3 происходят раньше по стеку вызовов, из-за чего события обхода строк и списков гарантированно вызываются до отображения окна.

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

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

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

  1. Интерактивное удаление настроек. В режиме «1С:Предприятие» под правами администратора откроем список пользователей или форму управления настройками (меню «Сервис» — «Настройки пользователя» или через администрирование пользователей). Найдем проблемного пользователя и удалим сохраненные настройки для формы, вызывающей ошибку (например, Обработка.CRM_РабочийСтол.Форма.ФормаАРМ).
  2. Программный сброс настроек через внешнюю обработку. Если в интерфейсе нет прямого доступа к очистке нужного элемента, воспользуемся стандартным хранилищем системных настроек. Создадим внешнюю обработку и выполним код:

ИмяПользователяДляСброса = "ИвановИИ";
КлючОбъекта = "Обработка.CRM_РабочийСтол.Форма.ФормаАРМ";

ХранилищеСистемныхНастроек.Удалить(КлючОбъекта, , ИмяПользователяДляСброса);

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

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

Решение 2. Защита от преждевременного выполнения в коде формы

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

Рассмотрим, как правильно защитить обработчик от обращения к неинициализированным данным:

  1. Использование флага готовности формы. Объявим переменную уровня модуля и установим проверку в процедуре активизации:

// В начале модуля формы объявляем переменную:
Перем мФормаИнициализирована;

Процедура ЗадачаСписокПриАктивизацииСтроки(Элемент)
    // Прерываем выполнение, если форма еще не открыта и переменные не заполнены
    Если Не мФормаИнициализирована Тогда
        Возврат;
    КонецЕсли;

    // Основной алгоритм обработки строки
    ОбработатьВыборЗадачи();
КонецПроцедуры

Процедура ПриОткрытии()
    // Инициализация основных переменных и структур данных
    ИнициализироватьДанныеФормы();

    // Разрешаем выполнение обработчиков элементов управления
    мФормаИнициализирована = Истина;
КонецПроцедуры

// В теле модуля (вне процедур) задаем начальное значение
мФормаИнициализирована = Ложь;

Решение 3. Перенос инициализации переменных в тело модуля или событие ПередОткрытием

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

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

// Тело модуля формы (выполняется непосредственно при вызове ПолучитьФорму)
мСписокПараметров = Новый Структура;
мСписокПараметров.Вставить("РежимРаботы", 1);
мСписокПараметров.Вставить("ТекущийСтатус", Неопределено);

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

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


Процедура ЗадачаСписокПриАктивизацииСтроки(Элемент)
    // Сбрасываем предыдущий вызов, если пользователь быстро перемещается по списку
    ОтключитьОбработчикОжидания("ВыполнитьАктивизациюСтрокиОтложено");
    
    // Подключаем однократный вызов с минимальной задержкой
    ПодключитьОбработчикОжидания("ВыполнитьАктивизациюСтрокиОтложено", 0.1, Истина);
КонецПроцедуры

Процедура ВыполнитьАктивизациюСтрокиОтложено()
    // Данный код выполнится уже после полной отрисовки окна и завершения всех процедур открытия
    Если ЭлементыФормы.ЗадачаСписок.ТекущаяСтрока <> Неопределено Тогда
        ОбновитьПодчиненныеДанные(ЭлементыФормы.ЗадачаСписок.ТекущиеДанные);
    КонецЕсли;
КонецПроцедуры

Такой подход полностью устраняет конфликт последовательности вызовов в платформе 1С:Предприятие 8.3 и гарантирует корректную работу формы у всех пользователей независимо от сохраненных настроек интерфейса.

← На главную