При разработке в среде 1С:Предприятие 7.7 программисты часто сталкиваются с проблемой управления окнами. Типичный сценарий: пользователь создает новый элемент справочника (например, «Контрагенты»), вводит данные, и в этот момент система обнаруживает, что такой контрагент уже существует. Логичным действием будет закрыть форму создания нового элемента и перевести фокус на уже имеющуюся запись в открытой форме списка. Однако стандартный метод ОткрытьФорму часто порождает второе окно списка вместо активации первого. Рассмотрим подробно, как решить эту задачу эффективно и элегантно.
Представим ситуацию: открыта основная форма списка справочника. Пользователь нажимает «Новый», открывается форма элемента. После ввода ИНН срабатывает проверка. Если дубликат найден, нам нужно:
Проблема заключается в том, что в 1С 7.7 программный вызов ОткрытьФорму("Справочник.Контрагенты.ФормаСписка") может создать новый экземпляр окна, если не соблюдены определенные условия. Разберем по шагам, как управлять этим процессом.
Проанализируем наиболее надежный способ, к которому пришел автор обсуждения. Суть заключается в сохранении ссылки на контекст открытой формы списка в глобальную переменную, чтобы иметь к ней доступ из любой точки конфигурации.
Для начала в Глобальном модуле необходимо объявить переменную, которая будет доступна всем формам:
Перем КонтОткрФормы Экспорт;
Затем в форме списка справочника (например, «Контрагенты») в предопределенной процедуре ПриОткрытии мы фиксируем текущий контекст:
Процедура ПриОткрытии()
// Сохраняем контекст этой формы в глобальную переменную
КонтОткрФормы = Контекст;
// Если форма открывается с параметром (ссылкой на элемент),
// сразу позиционируемся на нем
Если ПустоеЗначение(Форма.Параметр) = 0 Тогда
АктивизироватьОбъект(Форма.Параметр);
КонецЕсли;
КонецПроцедуры
Теперь рассмотрим логику внутри формы элемента, где происходит проверка на дубликаты. Когда мы нашли существующего контрагента, выполняем следующий код:
// Предположим, переменная "Спр" содержит ссылку на найденного контрагента
Если Спр.НайтиЭлемент(НайденныйКонтрагент) = 1 Тогда
Предупреждение("Такой контрагент уже существует в базе!");
// Закрываем текущую форму нового элемента без сохранения
СтатусВозврата(0);
Форма.Закрыть(0);
// Пытаемся работать с сохраненным контекстом формы списка
Если ТипЗначенияСтр(КонтОткрФормы) = "СписокЗначений" Или ТипЗначенияСтр(КонтОткрФормы) = "ГрупповойКонтекст" Тогда
// Сначала закрываем старую форму (если хотим ее обновить)
// или просто активизируем объект в ней
КонтОткрФормы.Закрыть();
КонецЕсли;
// Открываем форму списка заново, передавая найденный элемент как параметр
ОткрытьФорму("Справочник.Контрагенты.ФормаСписка", Спр.ТекущийЭлемент());
КонецЕсли;
Проанализируем встроенный механизм платформы 7.7. В формах существует предопределенная процедура ПриПовторномОткрытии(Параметр). Она должна срабатывать, когда система обнаруживает попытку открыть уже открытую форму.
Однако стоит учитывать важный нюанс: программный вызов ОткрытьФорму часто игнорирует этот механизм, создавая новое окно. Чтобы процедура сработала, идентификатор формы и набор параметров должны совпадать с уже открытым окном. Рассмотрим пример реализации в форме списка:
Процедура ПриПовторномОткрытии(Конт)
// Конт — это параметр, переданный при вызове ОткрытьФорму
Если ПустоеЗначение(Конт) = 0 Тогда
АктивизироватьОбъект(Конт);
КонецЕсли;
КонецПроцедуры
Этот способ более «чистый», но он менее стабилен в среде 1С 7.7, так как поведение системы при открытии форм сильно зависит от настроек интерфейса и способа вызова метода.
Выясним, как работает механизм уникальности окон. В 1С 7.7 в методе ОткрытьФорму можно использовать символ # в конце названия формы.
Если вызвать ОткрытьФорму("Справочник.Контрагенты.ФормаСписка#Основная"), система будет искать окно именно с таким уникальным идентификатором. Если оно уже открыто, новое создано не будет, а фокус перейдет на существующее. Это позволяет избежать «плодящихся» окон без использования глобальных переменных.
Если вы используете внешнюю компоненту Formex, возможности управления окнами значительно расширяются. Разберем, как можно активизировать объект без закрытия и повторного открытия формы, что избавляет пользователя от неприятного «моргания» интерфейса.
Используя объект Сервис из Formex, можно перебирать открытые окна и находить нужное по заголовку или типу объекта. Получив контекст окна, мы можем напрямую вызвать метод АктивизироватьОбъект(). Это самый профессиональный способ, так как он сохраняет все установленные пользователем фильтры и сортировки в списке.
Рассмотрим техническое ограничение метода АктивизироватьОбъект(). В 1С 7.7 этот метод успешно переместит курсор на элемент только в том случае, если этот элемент видим в текущем списке.
Проанализируем ситуацию: если в форме списка установлен отбор (например, по группе или по какому-то реквизиту), а найденный дубликат не удовлетворяет условиям этого отбора, то активация не произойдет. Перед программным позиционированием рекомендуется сбрасывать фильтры через контекст формы, если это критично для бизнес-логики.
Часто программисты хотят выделить кнопку «Поиск по ИНН» или «Создать по ИНН» цветом. В стандартной поставке 1С 7.7 кнопки не поддерживают смену цвета шрифта. Как отмечалось в обсуждении, компонента Formex также имеет ограничения на раскраску стандартных кнопок Windows.
Рекомендуемое решение:
Таким образом, комбинируя хранение контекста в глобальных переменных и правильное использование параметров метода ОткрытьФорму, мы добиваемся бесшовной работы интерфейса, повышая удобство работы пользователей и предотвращая замусоривание базы дублирующимися записями.