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