Как открыть форму документа и спозиционироваться на конкретной строке в 1С?

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

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

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

Почему стандартный ОткрытьФорму не срабатывает при повторном вызове?

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

Посмотрим на примеры решения этой задачи в зависимости от ваших целей.

Способ 1: Использование механизма оповещений (самый универсальный)

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

  1. В исходной форме (откуда мы хотим открыть документ и передать строку) вместо стандартного открытия мы генерируем оповещение с нужными данными.
  2. В открытой форме документа мы ловим это оповещение и меняем текущую строку.

Посмотрим на пример кода для вызывающей формы:


// Если мы знаем, что форма открыта, просто шлем оповещение
Оповестить("ПозиционированиеСтроки", ИдентификаторНужнойСтроки, ЭтаФорма);

В модуле формы самого документа необходимо переопределить стандартный обработчик:


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

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

Способ 2: Поиск открытого окна и вызов экспортного метода

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

  1. Перебираем коллекцию окон в цикле.
  2. Проверяем, соответствует ли содержимое окна нужной нам ссылке на документ.
  3. Если окно найдено, обращаемся к его контексту и вызываем экспортную клиентскую процедуру.

В модуле формы документа должна быть написана экспортная процедура:


&НаКлиенте
Процедура СпозиционироватьсяНаСтроке(НомерИлиИдентификаторСтроки) Экспорт
    Элементы.ИмяВашейТабличнойЧасти.ТекущаяСтрока = НомерИлиИдентификаторСтроки;
КонецПроцедуры

Способ 3: Принудительное открытие нового окна (Ключ уникальности)

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

В метод ОткрытьФорму четвертым параметром передается КлючУникальности:


ПараметрыФормы = Новый Структура("Ключ, ТекущаяСтрока", СсылкаНаДокумент, ИдентификаторСтроки);
// Передаем новый GUID в качестве ключа уникальности
ОткрытьФорму("Документ.ИмяДокумента.Форма.ФормаДокумента", 
             ПараметрыФормы, 
             ЭтаФорма, 
             Новый УникальныйИдентификатор);

В таком случае система создаст независимый экземпляр формы документа.

Важный технический нюанс: Идентификатор строки против Номера строки

Разберем типичную ошибку при работе со свойством ТекущаяСтрока. Многие разработчики пытаются передать туда порядковый номер (индекс) строки. Однако для элементов формы типа "Таблица" (связанных с табличной частью) свойство ТекущаяСтрока ожидает внутренний идентификатор строки коллекции.

Получить его можно заранее:


ИдентификаторСтроки = СсылкаНаДокумент.ТабличнаяЧасть[Индекс].ПолучитьИдентификатор();

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


&НаКлиенте
Процедура ПриОткрытии(Отказ)
    Если Параметры.Свойство("МояПереданнаяСтрока") Тогда
        Элементы.ИмяТабличнойЧасти.ТекущаяСтрока = Параметры.МояПереданнаяСтрока;
    КонецЕсли;
КонецПроцедуры

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

← На главную