Как реализовать автопрокрутку лога сообщений в управляемых формах 1С?

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

Многие разработчики, переходящие с платформы 1С 7.7 или использующие обычные формы 1С 8.2, сталкиваются с неприятной особенностью управляемого приложения: системное окно, вызываемое методом Сообщить(), перестает автоматически прокручиваться вниз при накоплении большого количества строк. В результате пользователь видит только начало лога, а самые актуальные сообщения остаются «за кадром», что критично для длительных процессов обработки данных. Разберем подробно, почему это происходит и как реализовать удобный, прокручиваемый лог своими силами.

Почему системный метод Сообщить() работает именно так?

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

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

Решение 1: Использование Поля текстового документа с программной прокруткой

Это наиболее популярный и простой способ создания собственного лога. Мы добавим на форму реквизит с типом ТекстовыйДокумент и выведем его на форму как ПолеТекстовогоДокумента. Чтобы текст всегда прокручивался вниз, воспользуемся методом установки границ выделения.

Разберем по шагам реализацию этого метода:

  1. Создадим на форме реквизит ЛогСобытий (тип: ТекстовыйДокумент).
  2. Вынесем его на форму.
  3. Напишем процедуру добавления строки, которая будет принудительно перемещать курсор в конец текста.

Посмотрим на пример кода:


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

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

Решение 2: Динамический буфер через Список Значений

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


&НаКлиенте
Процедура ВывестиСообщениеСУдалениемСтарых(Текст, СписокЛога)
    
    МаксимальныйРазмер = 50; // Храним только последние 50 строк
    
    СписокЛога.Добавить(Текст);
    
    Пока СписокЛога.Количество() > МаксимальныйРазмер Цикл
        СписокЛога.Удалить(0); // Удаляем самую старую строку
    КонецЦикла;
    
    // Очищаем стандартное окно и выводим обновленный список
    ОчиститьСообщения();
    Для Каждого Стр Из СписокЛога Цикл
        Сообщить(Стр.Значение);
    КонецЦикла;
    
КонецПроцедуры

Этот метод позволяет поддерживать окно сообщений в «чистом» виде, отображая только актуальную информацию, однако он постоянно вызывает ОчиститьСообщения(), что может привести к мерцанию интерфейса.

Решение 3: Логирование через фоновые задания (профессиональный подход)

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

Рассмотрим алгоритм реализации:

  1. Запускаем процедуру на сервере через ФоновыеЗадания.Выполнить().
  2. На клиенте подключаем обработчик ожидания через ПодключитьОбработчикОжидания() с интервалом 1–2 секунды.
  3. В обработчике ожидания вызываем метод ПолучитьСообщенияПользователю(Истина).

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

Решение 4: Использование Поля HTML-документа для «красивого» лога

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

Проанализируем пример формирования HTML-строки:


&НаКлиенте
Процедура ОбновитьHTMLLog(НовоеСообщение)
    
    // Добавляем текст и скрипт автопрокрутки вниз
    JSСкрипт = "<script>window.scrollTo(0, document.body.scrollHeight);</script>";
    ТекстHTML = ТекстHTML + "<p>" + НовоеСообщение + "</p>" + JSСкрипт;
    
КонецПроцедуры

При обновлении содержимого поля HTML браузерный движок внутри 1С исполнит скрипт window.scrollTo, и страница автоматически «упадет» в самый низ. Это наиболее эстетичный вариант, который очень нравится пользователям.

Рекомендации по оптимизации

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

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

← На главную