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

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

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

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

Почему стандартное окно сообщений нельзя перевернуть?

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

Единственное упоминание направления сортировки сообщений на уровне платформы присутствует в механизме Системы взаимодействия. Там используется объект ОтборСообщенийСистемыВзаимодействия и его свойство НаправлениеСортировки, принимающее системное перечисление НаправлениеСортировки.Убыв. Однако для классического окна сообщений управляемой формы этот метод неприменим. Поэтому мы будем использовать альтернативные варианты построения лога.

Решение 1: Использование системного Центра оповещений

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

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

Рассмотрим пример вызова важного оповещения:


ОписаниеОповещения = Новый ОписаниеОповещения("ПослеОбработкиОповещения", ЭтотОбъект);
ПоказатьОповещениеПользователя(
    "Выполнена обработка данных", 
    "e1cib/data/Документ.РеализацияТоваровУслуг?ref=...", 
    "Документ успешно проведен!", 
    БиблиотекаКартинок.ВажнаяИнформация, 
    СтатусОповещенияПользователя.Важное,
    ОписаниеОповещения
);

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

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

Решение 2: Текстовый лог на управляемой форме с добавлением в начало

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

  1. Создадим реквизит формы с именем ТекстЛога и типом Строка (длина неограничена).
  2. Перетащим его на форму и установим для элемента вид Поле ввода.
  3. В свойствах элемента управления включим флаг Многострочный режим и снимем флаг Редактирование, чтобы пользователь мог только читать лог.

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


&НаКлиенте
Процедура ДобавитьСообщениеВЛог(ТекстСобытия)
    
    ТекущееВремя = Формат(ТекущаяДата(), "ДФ=ЧЧ:мм:сс");
    НоваяСтрока = ТекущееВремя + " - " + ТекстСобытия;
    
    // Добавляем новое сообщение НАВЕРХ, разделяя строки переносом
    Если ЗначениеЗаполнено(Объект.ТекстЛога) Тогда
        Объект.ТекстЛога = НоваяСтрока + Символы.ПС + Объект.ТекстЛога;
    Иначе
        Объект.ТекстЛога = НоваяСтрока;
    КонецЕсли;
    
КонецПроцедуры

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

Недостатки: весь текст выводится одним шрифтом и цветом. Мы не сможем выделить важную ошибку красным цветом или предупреждение — оранжевым. Также отсутствует интерактивность (нельзя кликнуть по строке для перехода к документу).

Решение 3: Таблица значений на форме с сортировкой или вставкой со смещением

Для создания интерактивного и структурированного лога отлично подойдет использование таблицы значений, выведенной на управляемую форму. Этот метод позволяет не просто выводить строки, но и разделять их по колонкам (например: «Время», «Тип», «Текст ошибки», «Объект»).

Создадим реквизит формы ТаблицаСообщений с типом ТаблицаЗначений. Добавим в нее колонки:

Разберем два алгоритма обеспечения обратного порядка вывода сообщений в такой таблице.

Вариант А: Использование метода Вставить()
Вместо стандартного добавления строки в конец коллекции с помощью метода Добавить(), мы будем принудительно вставлять строку на самую первую позицию (с индексом 0). Все остальные строки при этом будут автоматически смещаться вниз.


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

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


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

Для того чтобы сделать эту таблицу интерактивной, настроим обработчик события Выбор у элемента формы «ТаблицаСообщений». Напишем код, который будет открывать форму объекта при двойном клике на строку:


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

Решение 4: Поле HTML-документа и CSS Flexbox (Наиболее гибкий и современный метод)

Рассмотрим самый технологичный подход, который позволяет кастомизировать интерфейс лога без ограничений платформы 1С. Мы будем использовать элемент формы Поле HTML-документа. В современных версиях платформы этот элемент работает на базе веб-движка Chromium, что открывает перед разработчиком возможности HTML5, CSS3 и JavaScript.

Для того чтобы автоматически отображать новые сообщения сверху без лишней траты ресурсов на перезапись больших объемов строк, мы применим современное свойство верстки CSS Flexbox с обратным направлением осей.

Выполним пошаговую настройку:

  1. Добавим на форму реквизит ТекстHTML с типом Строка.
  2. Разместим его на форме и установим вид Поле HTML-документа.
  3. При создании формы программно инициализируем базовую разметку HTML с CSS-стилями.

Посмотрим на код инициализации структуры документа:


&НаСервере
Процедура ПриСозданииНаСервере(Отказ, СтандартнаяЗапись)
    
    // Инициализируем HTML-документ с контейнером, работающим в режиме column-reverse
    Объект.ТекстHTML = 
        "<html>" +
        "<head>" +
        "<style>" +
        "   body { font-family: Arial, sans-serif; background-color: #f4f4f4; margin: 10px; }" +
        "   .message-container {" +
        "       display: flex;" +
        "       flex-direction: column-reverse; /* Последние добавленные элементы будут визуально сверху */" +
        "       max-height: 400px;" +
        "       overflow-y: auto;" +
        "       border: 1px solid #ccc;" +
        "       background: #fff;" +
        "       padding: 10px;" +
        "   }" +
        "   .msg { padding: 6px; margin-bottom: 5px; border-bottom: 1px solid #eee; border-radius: 4px; }" +
        "   .info { background-color: #e3f2fd; border-left: 4px solid #2196f3; }" +
        "   .warning { background-color: #fff3e0; border-left: 4px solid #ff9800; }" +
        "   .error { background-color: #ffebee; border-left: 4px solid #f44336; color: #c62828; }" +
        "   .time { font-size: 0.8em; color: #777; margin-right: 10px; }" +
        "</style>" +
        "</head>" +
        "<body>" +
        "   <div id='log' class='message-container'></div>" +
        "</body>" +
        "</html>";
        
КонецПроцедуры

Теперь напишем процедуру добавления нового сообщения. Чтобы динамически добавлять элементы в HTML-документ без перезагрузки всей страницы, мы будем использовать DOM-манипуляции через JavaScript, вызываемый из кода 1С:


&НаКлиенте
Процедура ДобавитьСообщениеHTML(ТекстСообщения, Тип)
    
    // Поддерживаемые типы: info, warning, error
    ТекущееВремя = Формат(ТекущаяДата(), "ДФ=ЧЧ:мм:сс");
    
    // Экранируем спецсимволы в тексте сообщения
    БезопасныйТекст = СтрЗаменить(ТекстСообщения, "'", "\'");
    
    // Формируем JS-код, который создаст новый элемент div и добавит его в контейнер
    СкриптJS = 
        "var container = document.getElementById('log');" +
        "var newDiv = document.createElement('div');" +
        "newDiv.className = 'msg " + Тип + "';" +
        "newDiv.innerHTML = '<span class=""time"">" + ТекущееВремя + "</span>" + БезопасныйТекст + "';" +
        "container.appendChild(newDiv);"; // appendChild добавит элемент в конец DOM, но CSS отобразит его сверху!
        
    // Выполняем скрипт в контексте Поля HTML-документа
    Элементы.ТекстHTML.Документ.defaultView.eval(СкриптJS);
    
КонецПроцедуры

Преимущества: невероятно красивый и современный внешний вид логов. Цветовое кодирование сообщений разного уровня критичности. Автоматическая прокрутка и идеальное позиционирование благодаря технологии Flexbox (свойство flex-direction: column-reverse).

Недостатки: требует базовых навыков верстки веб-страниц и понимания взаимодействия между 1С и JavaScript.

Резюме и рекомендации

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

  1. Если вам нужно просто выводить информацию о фоновых процессах без привязки к форме — используйте Центр оповещений.
  2. Для простых отчетов и обработок, где важна скорость разработки — используйте Текстовый реквизит с добавлением строк в начало через оператор +.
  3. Если требуется интерактивность, выборка объектов и возможность открывать документы по клику — создавайте Таблицу значений с обратной сортировкой по числовому индексу.
  4. Для крупных корпоративных решений, где важен качественный UI/UX дизайн и гибкое оформление ошибок — внедряйте Поле HTML-документа со свойствами CSS Flexbox.
← На главную