Как настроить автоматическое переключение на нужную вкладку формы при выводе ошибки к конкретному полю в 1С?

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

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

В этой статье мы подробно разберем, как сделать работу пользователя максимально комфортной. Мы изучим, как настроить систему так, чтобы при возникновении ошибки платформа не просто выводила предупреждение, но и автоматически переключала вкладку формы на нужную страницу, устанавливая фокус (курсор) прямо на проблемное поле.

Как это должно работать в норме: штатный механизм платформы 1С

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

Если пользователь совершает действие, приводящее к проверке (например, запись объекта), система выводит список ошибок. При нажатии (или двойном клике) на ошибку в панели сообщений платформа выполняет следующие действия:

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

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

Почему автоматическая привязка и переключение страниц не работают?

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

1. Ошибки в синтаксисе параметров функций БСП (Библиотеки Стандартных Подсистем)

Очень часто разработчики используют встроенные функции БСП, например, ОбщегоНазначенияКлиентСервер.СообщитьПользователю, но путают порядок передаваемых аргументов. Рассмотрим типичный ошибочный вызов:


ОбщегоНазначенияКлиентСервер.СообщитьПользователю("Заполните Вид графика", , "Объект.ВидГрафика");

В данном примере строка "Объект.ВидГрафика" передана в качестве третьего параметра функции. Однако, согласно архитектуре БСП, третьим параметром должно выступать чистое имя реквизита (свойство Поле), а путь к объекту должен передаваться четвертым параметром (свойство ПутьКДанным). Из-за этого платформа не может сопоставить сообщение с элементом формы и выводит его «в воздух» — просто как текстовое оповещение в углу экрана, без интерактивной связи.

2. Запуск управляемой формы в режиме «Обычного приложения» (гибридный режим)

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

3. Несоответствие путей к данным и имен элементов

Для успешного позиционирования платформа сопоставляет путь, указанный в свойстве Поле объекта СообщениеПользователю, с официальным свойством ПутьКДанным элементов формы. Если вы ошиблись в имени реквизита (например, указали "ТипГостя" вместо "ВидГрафика") или если элемент на форме переименован вручную и его путь к данным отличается от стандартного, привязка не сработает.

4. Ограничения видимости и доступности

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

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

Вариант 1. Использование стандартного механизма проверки заполнения (без написания кода)

Если вам нужно просто проконтролировать, чтобы поле «Вид графика» обязательно заполнялось перед записью или стартом процесса, лучшим решением будет использование декларативного метода платформы. Это избавит вас от необходимости писать и поддерживать лишний код.

Выполните следующие шаги в конфигураторе:

  1. Откройте дерево метаданных и найдите нужный реквизит объекта (например, реквизит ВидГрафика бизнес-процесса).
  2. Откройте палитру свойств этого реквизита.
  3. Найдите свойство Проверка заполнения и установите его в значение Выдавать ошибку.

После этого платформа 1С автоматически возьмет на себя все заботы по проверке. При попытке записи незаполненного объекта система сама сформирует красивое сообщение, привяжет его к нужному полю, и при клике пользователя безошибочно переключит форму на нужную вкладку.

Вариант 2. Правильное программное использование объекта СообщениеПользователю

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

Реализация на стороне Сервера:

При работе на сервере нам необходимо связать сообщение с контекстом формы. Для этого используется метод УстановитьДанные(). Посмотрим на правильный пример кода:


&НаСервере
Процедура ПроверитьЗаполнениеНаСервере(Отказ)
    
    Если Не ЗначениеЗаполнено(Объект.ВидГрафика) Тогда
        
        Сообщение = Новый СообщениеПользователю;
        // Связываем сообщение с конкретным прикладным объектом формы
        Сообщение.УстановитьДанные(РеквизитФормыВЗначение("Объект"));
        Сообщение.Текст = "Поле 'Вид графика' не заполнено! Пожалуйста, укажите график.";
        // Указываем имя реквизита без префикса "Объект"
        Сообщение.Поле = "ВидГрафика"; 
        Сообщение.Сообщить();
        
        Отказ = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Реализация на стороне Клиента:

Если проверка выполняется непосредственно в клиентской процедуре перед записью, мы используем свойство ПутьКДанным для указания контекста:


&НаКлиенте
Процедура ПроверитьЗаполнениеНаКлиенте(Отказ)
    
    Если Не ЗначениеЗаполнено(Объект.ВидГрафика) Тогда
        
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Необходимо заполнить 'Вид графика' на третьей вкладке!";
        // Указываем имя конкретного реквизита
        Сообщение.Поле = "ВидГрафика";
        // Указываем путь к объекту-владельцу реквизита
        Сообщение.ПутьКДанным = "Объект";
        Сообщение.Сообщить();
        
        Отказ = Истина;
        
    КонецЕсли;
    
КонецПроцедуры

Вариант 3. Правильный вызов функций БСП

Если в вашей конфигурации внедрена Библиотека Стандартных Подсистем (БСП), рекомендуется использовать ее стандартные механизмы. Это делает код более лаконичным и стандартизированным. Давайте исправим ошибку автора из темы форума и напишем правильный вызов:


// Правильный вызов процедуры БСП
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(
    "Пожалуйста, заполните Вид графика на странице параметров!", // 1. Текст сообщения
    ,                                                            // 2. Ключ данных (оставляем пустым)
    "ВидГрафика",                                                // 3. Имя поля
    "Объект",                                                    // 4. Путь к данным объекта
    Отказ                                                        // 5. Переменная Отказ (установится в Истина)
);

Обратите внимание: благодаря передаче переменной Отказ в пятый параметр, БСП автоматически установит ее в значение Истина, предотвращая дальнейшую запись некорректного объекта.

Вариант 4. Программное переключение страниц на клиенте (Самый надежный обходной путь)

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

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


&НаКлиенте
Процедура СтартоватьПроцессВыполнения(Команда)
    
    // 1. Проверяем заполнение реквизита на клиенте
    Если Не ЗначениеЗаполнено(Объект.ВидГрафика) Тогда
        
        // 2. Активизируем нужную страницу формы программно.
        // "ГруппаСтраницыФормы" - это имя элемента формы с видом "Страницы".
        // "СтраницаПараметры" - имя конкретной страницы (вкладки), где лежит наше поле.
        Элементы.ГруппаСтраницыФормы.ТекущаяСтраница = Элементы.СтраницаПараметры; 
        
        // 3. Передаем фокус ввода (курсор) непосредственно в поле с ошибкой
        ТекущийЭлемент = Элементы.ВидГрафика; 
        
        // 4. Выводим сообщение пользователю. 
        // Поскольку вкладка уже активна, сообщение отобразится прямо у нужного поля!
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Поле 'Вид графика' обязательно для заполнения перед стартом процесса!";
        Сообщение.Поле = "Объект.ВидГрафика";
        Сообщение.Сообщить();
        
        Возврат; // Прерываем дальнейшее выполнение процедуры
        
    КонецЕсли;
    
    // Продолжение логики старта бизнес-процесса...
    
КонецПроцедуры

Вариант 5. Универсальная функция для сложных форм с глубокой вложенностью

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

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


&НаКлиенте
Процедура АктивизироватьРодительскуюСтраницуЭлемента(ИмяЭлементаФормы)
    
    Попытка
        ТекущийЭлементФормы = Элементы[ИмяЭлементаФормы];
        РодительЭлемента = ТекущийЭлементФормы.Родитель;
        
        // Будем подниматься вверх по иерархии элементов, пока не достигнем корня формы
        Пока РодительЭлемента <> Неопределено Цикл
            
            // Проверяем, является ли родительский элемент группой страниц
            Если ТипЗнч(РодительЭлемента) = Тип("ГруппаФормы") 
                И РодительЭлемента.Вид = ГруппаФормыВид.Страницы Тогда
                
                // Переключаем группу страниц на ту вкладку, в которой лежит наш элемент
                РодительЭлемента.ТекущаяСтраница = ТекущийЭлементФормы;
                
            КонецЕсли;
            
            // Переходим на уровень выше
            ТекущийЭлементФормы = РодительЭлемента;
            РодительЭлемента = ТекущийЭлементФормы.Родитель;
            
        КонецЦикла;
        
        // Устанавливаем фокус ввода на сам элемент
        ТекущийЭлемент = Элементы[ИмяЭлементаФормы];
        
    Исключение
        // Обработка исключения на случай, если имя элемента передано неверно
        ЗаписьЖурналаРегистрации("ОшибкиИнтерфейса", УровеньЖурналаРегистрации.Предупреждение, , , 
            "Не удалось активировать страницу для элемента: " + ИмяЭлементаФормы);
    КонецПопытки;
    
КонецПроцедуры

Теперь использование этой функции в коде проверки становится невероятно простым и изящным:


&НаКлиенте
Процедура ПроверитьИСтартовать()
    
    Если Не ЗначениеЗаполнено(Объект.ВидГрафика) Тогда
        
        // Вызываем нашу универсальную процедуру по имени элемента формы
        АктивизироватьРодительскуюСтраницуЭлемента("ВидГрафика");
        
        // Сообщаем об ошибке
        Сообщение = Новый СообщениеПользователю;
        Сообщение.Текст = "Пожалуйста, заполните Вид графика!";
        Сообщение.Поле = "Объект.ВидГрафика";
        Сообщение.Сообщить();
        
        Возврат;
    КонецЕсли;
    
КонецПроцедуры

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

Используйте предложенные методики, проектируйте дружелюбные интерфейсы и делайте работу ваших пользователей продуктивной и комфортной!

← На главную