Как вывести сообщение на клиенте в 1С:Предприятие 8.3

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

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

Проблема: Вызов серверного метода и вывод окна

Часто в процедуре ПриИзменении какого-либо реквизита (например, «Сотрудник») требуется проверить, не занят ли он уже в других документах. Если использовать стандартный метод Сообщить() внутри серверной процедуры, сообщение просто появится в нижней панели сообщений, что бухгалтер или другой пользователь может пропустить. Для того чтобы «заставить» систему показать полноценное модальное (или асинхронное) окно, нам необходимо вернуть результат проверки на сторону клиента.

Решение 1: Возврат значения из серверной функции

Разберем базовый и самый понятный способ. Вместо процедуры на сервере мы будем использовать функцию, которая возвращает строку с текстом ошибки или пустую строку, если проверка пройдена. Посмотрим на пример реализации:


&НаСервере
Функция ПроверитьСотрудникаНаСервере()
    
    Запрос = Новый Запрос;
    Запрос.Текст = 
        "ВЫБРАТЬ РАЗЛИЧНЫЕ
        |   СведенияОСотрудниках.Регистратор КАК Регистратор
        |ИЗ
        |   РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках
        |ГДЕ
        |   СведенияОСотрудниках.Сотрудник = &Сотрудник
        |   И СведенияОСотрудниках.Работает"; // Прямая проверка булева поля
    
    Запрос.УстановитьПараметр("Сотрудник", Объект.Сотрудник);
    
    РезультатЗапроса = Запрос.Выполнить();
    Выборка = РезультатЗапроса.Выбрать();
    
    ТекстПредупреждения = "";
    Пока Выборка.Следующий() Цикл
        ТекстПредупреждения = ТекстПредупреждения + Выборка.Регистратор + Символы.ПС;
    КонецЦикла;
    
    // Если нашли нарушения, очищаем данные на сервере
    Если ЗначениеЗаполнено(ТекстПредупреждения) Тогда
        Объект.Сотрудник = Справочники.Сотрудники.ПустаяСсылка();
        // Можно также очистить связанные ТЧ
        // Объект.ТабличнаяЧасть1.Очистить();
    КонецЕсли;
    
    Возврат ТекстПредупреждения;
    
КонецФункции

&НаКлиенте
Процедура СотрудникПриИзменении(Элемент)
    
    ТекстСообщения = ПроверитьСотрудникаНаСервере();
    
    Если Не ПустаяСтрока(ТекстСообщения) Тогда
        // Используем современный асинхронный метод
        ПоказатьПредупреждение(, "Данный сотрудник уже числится в документах:" + Символы.ПС + ТекстСообщения, 20);
    КонецЕсли;
    
КонецПроцедуры

Проанализируем этот код. Мы перенесли ответственность за отображение окна на клиента, а серверу оставили только логику поиска данных. Метод ПоказатьПредупреждение является предпочтительным в управляемом приложении, так как он не блокирует выполнение потока в веб-клиенте так жестко, как старый метод Предупреждение().

Анализ типичных ошибок в запросах

Обратим внимание на важные детали в написании кода 1С, которые часто вызывают улыбку у опытных коллег, но являются критичными для производительности и чистоты кода:

  1. Параметр для ИСТИНА: Не нужно писать УстановитьПараметр("ИСТИНА", ИСТИНА). В языке запросов 1С слово ИСТИНА является зарезервированным литералом.
  2. Сравнение булевых полей: Вместо ГДЕ Работает = &ПараметрИстина лучше использовать лаконичное ГДЕ Работает. Если поле ложно, условие не выполнится.
  3. Группировка vs Различные: Если вам нужно просто перечислить уникальные регистраторы, используйте ключевое слово РАЗЛИЧНЫЕ, это читается проще, чем СГРУППИРОВАТЬ ПО.

Решение 2: Использование объекта СообщениеПользователю

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

Рассмотрим, как это работает. При вызове метода Сообщить() у этого объекта, система не просто выводит текст внизу, а рисует красное «облако» над реквизитом Сотрудник. Это гораздо удобнее для пользователя.


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

Важный нюанс: Проверка «самого себя»

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

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


Запрос.Текст = 
    "ВЫБРАТЬ ПЕРВЫЕ 1
    |   1
    |ИЗ
    |   РегистрСведений.СведенияОСотрудниках КАК СведенияОСотрудниках
    |ГДЕ
    |   СведенияОСотрудниках.Сотрудник = &Сотрудник
    |   И СведенияОСотрудниках.Регистратор <> &Ссылка
    |   И СведенияОСотрудниках.Работает";
    
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);

Использование ВЫБРАТЬ ПЕРВЫЕ 1 существенно ускоряет работу базы данных, так как системе не нужно сканировать весь регистр — достаточно найти хотя бы одно совпадение, чтобы понять, что сотрудник уже занят.

Выбор метода уведомления: итоги

Разберем по шагам, когда и какой метод использовать:

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

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

← На главную