В процессе разработки на платформе 1С:Предприятие 8.3 часто возникает задача разделения интерфейса. Например, для одного и того же документа могут существовать разные формы: одна — стандартная для бухгалтерии, другая — упрощенная для менеджеров или специфическая для определенных бизнес-процессов. Распространенная проблема заключается в том, что при попытке программно открыть «свою» форму из списка, система открывает ее пустой, как будто создается новый объект, вместо того чтобы подтянуть данные существующего документа.
В этой статье мы подробно разберем, почему так происходит, и рассмотрим несколько способов решения этой задачи: от простого вызова в форме списка до глобальной подмены формы через модуль менеджера.
Проанализируем ситуацию: когда мы используем метод ОткрытьФорму, платформа должна понимать, какой именно объект мы хотим отредактировать. Если мы просто передаем имя формы, например, Документ.РеализацияТоваровУслуг.Форма.МояФорма, система создает новый экземпляр формы. Чтобы форма «поняла», что ей нужно отобразить данные конкретного документа, ей необходимо передать уникальный идентификатор (ссылку) в параметрах под специальным ключом Ключ.
Без этого параметра форма переходит в режим создания нового объекта, что и наблюдал автор вопроса на форуме. Выясним, как это исправить правильно.
Рассмотрим самый быстрый способ. Чаще всего подмена формы требуется при двойном клике по строке списка или при нажатии кнопки «Изменить». Для этого нам понадобится обработать событие Выбор или ПередНачаломИзменения в таблице формы списка.
Разберем по шагам реализацию этого метода:
Список на форме списка документа.Выбор и создадим обработчик на клиенте.Посмотрим на пример кода, который решает задачу:
&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
// 1. Отменяем стандартное открытие формы, чтобы не открылись две формы сразу
СтандартнаяОбработка = Ложь;
// 2. Формируем структуру параметров.
// "Ключ" — это зарезервированное имя параметра, куда передается ссылка на документ.
ПараметрыФормы = Новый Структура("Ключ", ВыбраннаяСтрока);
// 3. Открываем нашу специфическую форму
ОткрытьФорму("Документ.НазваниеВашегоДокумента.Форма.ВашаФормаДокумента", ПараметрыФормы);
КонецПроцедуры
Обратите внимание на параметр СтандартнаяОбработка = Ложь;. Если его не установить, платформа сначала выполнит ваш код и откроет кастомную форму, а затем выполнит свое стандартное действие и откроет форму по умолчанию поверх вашей. В итоге пользователь увидит два окна.
Проанализируем более продвинутый и «чистый» с точки зрения архитектуры способ. Метод с формой списка хорош, если вам нужно открывать форму только из одного конкретного списка. Но что делать, если документ открывается из отчета, из навигационной ссылки или из другого документа? В таких случаях лучше использовать механизм подмены формы в модуле менеджера.
Для этого используется обработчик ОбработкаПолученияФормы. Этот метод позволяет перехватить запрос системы на получение любой формы объекта и подставить свою логику.
Рассмотрим, как это реализовать в модуле менеджера документа:
Процедура ОбработкаПолученияФормы(ВидФормы, Параметры, ВыбраннаяФорма, ДополнительнаяИнформация, СтандартнаяОбработка)
// Проверяем, что запрашивается именно форма объекта (не списка и не выбора)
Если ВидФормы = "ФормаОбъекта" Тогда
// Здесь можно добавить условие, например, проверку реквизита документа
// Если Параметры.Свойство("Ключ") Тогда
// ДокументСсылка = Параметры.Ключ;
// Если ДокументСсылка.ТипОперации = Перечисления.ТипыОпераций.Специфическая Тогда
ВыбраннаяФорма = "Документ.НазваниеВашегоДокумента.Форма.ВашаКастомнаяФорма";
СтандартнаяОбработка = Ложь;
// КонецЕсли;
// КонецЕсли;
КонецЕсли;
КонецПроцедуры
Этот способ предпочтительнее, так как он централизует логику выбора интерфейса. Вам не придется прописывать код в каждой форме списка или журнале документов.
При реализации открытия форм важно понимать различие между ТекущаяСтрока и ТекущиеДанные, так как в коде на форумах часто встречаются оба варианта.
Элементы.Список.ТекущаяСтрока — этот параметр возвращает только Ссылку (UUID) на объект в базе данных. Для передачи в параметр Ключ метода ОткрытьФорму этого абсолютно достаточно. Система сама найдет объект в базе и заполнит форму данными.
Элементы.Список.ТекущиеДанные — возвращает структуру всех данных, которые физически отображены в строке списка прямо сейчас. Это полезно, если вы хотите проверить какое-то условие (например, «Проведен» документ или нет), не обращаясь к серверу лишний раз. Но помните: если какой-то реквизит не выведен в колонки списка, в ТекущиеДанные его не будет.
Рассмотрим пример использования ТекущиеДанные для проверки условия перед открытием:
&НаКлиенте
Процедура СписокВыбор(Элемент, ВыбраннаяСтрока, Поле, СтандартнаяОбработка)
ДанныеСтроки = Элемент.ТекущиеДанные;
Если ДанныеСтроки <> Неопределено Тогда
Если ДанныеСтроки.СуммаДокумента > 100000 Тогда
СтандартнаяОбработка = Ложь;
ПараметрыФормы = Новый Структура("Ключ", ДанныеСтроки.Ссылка);
ОткрытьФорму("Документ.НашДокумент.Форма.ФормаДляКрупныхСделок", ПараметрыФормы);
КонецЕсли;
КонецЕсли;
КонецПроцедуры
Метод ОткрытьФорму обладает мощным функционалом, который часто недооценивают. Помимо ссылки под ключом Ключ, мы можем передавать и другие параметры, влияющие на поведение открываемого окна.
ОткрытьФорму. Если вы передадите туда Ссылку документа, то при повторном клике на этот же документ система не создаст новое окно, а просто активирует уже существующее. Это защищает рабочий стол пользователя от «гирлянды» одинаковых окон.Выясним, как выглядит полный вызов с учетом уникальности:
// Использование ссылки в качестве ключа уникальности
ОткрытьФорму("Документ.Тестовый.Форма.Моя", ПараметрыФормы, , ПараметрыФормы.Ключ);
Если вы работаете в старой конфигурации (на обычных формах), логика ОткрытьФорму с ключом там не сработает. Рассмотрим, как это делалось раньше, чтобы понимать разницу:
Объект = Ссылка.ПолучитьОбъект();Форма = Объект.ПолучитьФорму("НужнаяФорма");Форма.Открыть();Однако в современных управляемых приложениях на платформе 8.3 использование ОткрытьФорму с передачей структуры — это стандарт индустрии и наиболее эффективный метод с точки зрения производительности клиент-серверного взаимодействия.
Мы проанализировали ситуацию с открытием кастомных форм и выяснили, что ключ к успеху — правильная передача параметра Ключ в структуру параметров формы. Если задача разовая — используйте событие Выбор в списке. Если же вы хотите внедрить системное решение — используйте ОбработкаПолученияФормы в модуле менеджера. Не забывайте отключать СтандартнаяОбработка, чтобы избежать дублирования окон, и всегда следите за контекстом вызова.