Информационные сообщения в 1С. Как это можно сделать

a84e443a0ce74e80b5833bc74660d3f5.jpg
Здравствуйте.
Сегодня речь пойдет о реализации подсистемы выдачи информационных сообщений пользователю. Стандартный способ проинформировать о чем-либо пользователя — это использование процедуры »Сообщить». Однако в некоторых случаях, хочется создать отдельный список, который не будет замусоривать своим выводом основной список сообщений платформы. Также желательно иметь возможность выделять цветом различные сообщения (в зависимости от их типа, например). В общем, расскажу, как это получилось сделать у меня. Приведенное в статье решение можно встроить в свою программу без какой-либо адаптации.
В свое время, работая с системой контроля версий Perforce, а именно с ее графическими клиентами, я обратил внимание на удобный элемент интерфейса — многострочное поле вывода сообщений внизу главного окна программы. После того, как пользователь выполнял какие-то обращения к серверу системы, в это поле добавлялись текстовые сообщения, описывающие процесс взаимодействия клиента с сервером (какие конкретно действия выполнялись, и результат их выполнения). Не знаю, почему именно Perforce произвел на меня такое впечатление, хотя абсолютно ту же систему я наблюдал до и после в различных графических IDE (Delphi, C++ и т.д.) — окно вывода сообщений той консольной программы (компилятор или клиент системы контроля версий), в качестве оболочки которой выступает графическая программа. Но впрочем, статья вовсе не про Perforce, просто я считаю удобным способ многострочного вывода сообщений в процессе выполнения какой-то длительной работы. Получить большой список сообщений гораздо лучше (информативнее), чем одиночный MessageBox в самом конце этой работы. Подобный подход мы, кстати, видим и в антивирусных программах.

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

В рассматриваемом примере таблица вывода сообщения (элемент интерфейса ТабличноеПоле) выглядит примерно так:
ebac011801a145979913236e346bd309.jpg


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

Нам понадобятся иконки для отображения статусов сообщений. Загрузим из соответствующих BMP-файлов (прилагаются к данной статье) в ресурсы (макеты типа «Двоичные данные»)

Изображение Название исходного файла Название макета
2d642a0013aa44789b19f169d6ae04e2.jpg statok.bmp КартинкаСообщениеСтатусОК
3a32a135fa244a6bb16e445760eb34ca.jpg statwarning.bmp КартинкаСообщениеСтатусПредупреждение
5a9e4d7825ec419e803645f53c511b77.jpg staterror.bmp КартинкаСообщениеСтатусОшибка


Затем нужно будет как-то эти картинки загрузить для использования — превратим их в ресурсы.
Определим в главном модуле глобальную переменную «КоллекцияКартинок» в виде структуры из объектов стандартного класса «Картинка». Напишем подпрограмму «СформироватьКоллекциюКартинок», которая будет инициализировать коллецию. Будем вызывать эту подпрограмму в инициализирующей секции модуля.

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

Название Описание Числовое значение
ТИПСООБЩ_НЕОПРЕД Неопределенное значение 0
ТИПСООБЩ_УРОВЕНЬ1 Уровень вложенности 1 1
ТИПСООБЩ_УРОВЕНЬ2 Уровень вложенности 2 2
ТИПСООБЩ_УРОВЕНЬ3 Уровень вложенности 3 3


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

Название Описание Числовое значение
СТАТСООБЩ_НЕОПРЕД Неопределенное значение 0
СТАТСООБЩ_ОК Уровень вложенности 1 1
СТАТСООБЩ_ПРЕДУПР Уровень вложенности 2 2
СТАТСООБЩ_ОШИБКА Уровень вложенности 3 3


Представим типы и статусы в виде числовых констант, как это делается в С/С++ (#define) или Pascal (const). В 1С будем имитировать константы вставкой их в глобальную переменную-структуру (ключ элемента структуры — это символьное имя константы, а значение элемента структуры — это численное значение константы).

Функция ИнициализацияПрочихКонстант()
        
        Проч = Новый Структура;
        
        // Типы сообщений
        Проч.Вставить("ТИПСООБЩ_НЕОПРЕД", 0);   // Тип неопределен
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ1", 1);  // Сообщение уровня 1
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ2", 2);  // Сообщение уровня 2
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ3", 3);  // Сообщение уровня 3

        // Статусы сообщений
        Проч.Вставить("СТАТСООБЩ_НЕОПРЕД", 0);  // Статус неопределен
        Проч.Вставить("СТАТСООБЩ_ОК", 1);       // Статус "ОК"
        Проч.Вставить("СТАТСООБЩ_ПРЕДУПР", 2);  // Статус "Предупреждение"
        Проч.Вставить("СТАТСООБЩ_ОШИБКА", 3);   // Статус "Ошибка"
        
        Возврат Проч
        
КонецФункции


Еще нам нужно будет получать текущее значение времени в миллисекундах. Используем для этого машину JavaScript в виде глобальной переменной COM-объекта.

Вот что получилось в главном модуле:

Исходный текст
////////////////////////////////////////////////////////////////////////////////
// ПРОЧИЕ КОНСТАНТЫ

Перем Проч Экспорт;                       // Структура с константами

Перем КоллекцияКартинок Экспорт;          // Набор иконок интерфейса


////////////////////////////////////////////////////////////////////////////////
// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ

Перем JavaScript;                         // Машина для работы с JavaScript


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// П О Д П Р О Г Р А М М Ы    И Н И Ц И А Л И З А Ц И И    К О Н С Т А Н Т
//
///////////////////////////////////////////////////////////////////////////////////////////////////

// Инициализирует набор констант общего назначения
//
// Параметры:
//  НЕТ.
//
// Возврат:
//  Структура с полями - константами общего назначения
//
Функция ИнициализацияПрочихКонстант()
        
        Проч = Новый Структура;
        
        // Типы сообщений
        Проч.Вставить("ТИПСООБЩ_НЕОПРЕД", 0);   // Тип неопределен
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ1", 1);  // Сообщение уровня 1
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ2", 2);  // Сообщение уровня 2
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ3", 3);  // Сообщение уровня 3

        // Статусы сообщений
        Проч.Вставить("СТАТСООБЩ_НЕОПРЕД", 0);  // Статус неопределен
        Проч.Вставить("СТАТСООБЩ_ОК", 1);       // Статус "ОК"
        Проч.Вставить("СТАТСООБЩ_ПРЕДУПР", 2);  // Статус "Предупреждение"
        Проч.Вставить("СТАТСООБЩ_ОШИБКА", 3);   // Статус "Ошибка"
        
        Возврат Проч
        
КонецФункции


// Формирует набор картинок, на основании изображений, сохраненных в двоичных
// макетах обработки.
//
// Параметры:
//  НЕТ.
//
// Возврат:
//  Структура с полями - объектами типа Картинка с загруженными картинками
//
Функция СформироватьКоллекциюКартинок()
        
        КоллекцияКартинок = Новый Структура;
        
        КоллекцияКартинок.Вставить("СообщениеСтатусОК", Новый Картинка(ПолучитьМакет("КартинкаСообщениеСтатусОК")));
        КоллекцияКартинок.Вставить("СообщениеСтатусПредупреждение", Новый Картинка(ПолучитьМакет("КартинкаСообщениеСтатусПредупреждение")));
        КоллекцияКартинок.Вставить("СообщениеСтатусОшибка", Новый Картинка(ПолучитьМакет("КартинкаСообщениеСтатусОшибка")));
        
        Возврат КоллекцияКартинок
        
КонецФункции


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// П О Д П Р О Г Р А М М Ы    И Н И Ц И А Л И З А Ц И И    Г Л О Б А Л Ь Н Ы Х    П Е Р Е М Е Н Н Ы Х
//
///////////////////////////////////////////////////////////////////////////////////////////////////

// Создает объект JavaScript и возвращает его в качестве значения
// Формирует набор картинок, на основании изображений, сохраненных в двоичных
// макетах обработки.
//
// Параметры:
//  НЕТ.
//
// Возврат:
//  Ссылка на машину JavaScript или Неопределено, если машина не создана
//
Функция СоздатьОбъектJavaScript()
        
        Рез = Неопределено;
        Попытка
                Рез = Новый COMОбъект("MSScriptControl.ScriptControl");
            Рез.Language = "javascript";      
        Исключение
        КонецПопытки;

    Возврат Рез

КонецФункции


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// П О Д П Р О Г Р А М М Ы    О Б Щ Е Г О    Н А З Н А Ч Е Н И Я
//
///////////////////////////////////////////////////////////////////////////////////////////////////

// Расширяет строку до заданной ширины пробелами, добавляя их слева
//
// Параметры:
//  Стр - исходная строка
//  Ширина - кол-во символов до которого нужно расширить строку
// Возврат:
//  Полученная строка
//
Функция РасширСтрЛев(Стр, Ширина)
        
        Рез = Стр;
        Инд = Ширина - СтрДлина(Рез);
        Пока Инд > 0 Цикл
                Рез = " " + Рез;
                Инд = Инд - 1
        КонецЦикла;
        
        Возврат Рез
        
КонецФункции

// Расширяет строку до заданной ширины пробелами, добавляя их справа
//
// Параметры:
//  Стр - исходная строка
//  Ширина - кол-во символов до которого нужно расширить строку
// Возврат:
//  Полученная строка
//
Функция РасширСтрПрав(Стр, Ширина)
        
        Рез = Стр;
        Инд = Ширина - СтрДлина(Рез);
        Пока Инд > 0 Цикл
                Рез = Рез + " ";
                Инд = Инд - 1
        КонецЦикла;
        
        Возврат Рез
        
КонецФункции


// Возвращает текущую дату и время в миллисекундах
//
// Параметры:
//  НЕТ
// Возврат:
//  Числовое значение или 0, если значение определить не удалось
//
Функция ПолучитьТекущееВремяВМиллисекундах() Экспорт
        
        Время = 0;
        Если JavaScript <> Неопределено Тогда
                Время = JavaScript.Eval("new Date().getTime()");
        КонецЕсли;
        
        Возврат Время;
        
КонецФункции




////////////////////////////////////////////////////////////////////////////////
// ОПЕРАТОРЫ ОСНОВНОЙ ПРОГРАММЫ - НАЧАЛЬНАЯ ИНИЦИАЛИЗАЦИЯ



// ИНИЦИАЛИЗАЦИЯ КОНСТАНТ

// Константы общего назначения
Проч = ИнициализацияПрочихКонстант();

// Коллекция картинок
КоллекцияКартинок = СформироватьКоллекциюКартинок();



// ИНИЦИАЛИЗАЦИЯ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ

// Создать машину JavaScript
JavaScript = СоздатьОбъектJavaScript();



Набор сообщений существует в виде таблицы значений (стандартный класс ТаблицаЗначений) со следующими колонками:

Название колонки Тип данных Назначение
ТипСообщ Число Тип сообщения (уровень) — одна из констант ТИПСООБЩ_
СтатусСообщ Число Статус сообщения — одна из констант СТАТСООБЩ_
ТекстСообщ Строка Основной текст сообщения. Здесь обычно указываем, какое действие выполняется длительным процессом в данный момент.
КомментарийСообщ Строка Дополнительный текст сообщения. Здесь обычно указываем результат выполнения действия, описанного в колонке ТекстСообщ. Если действие завершилось ошибкой, то сообщение об ошибке приводим в этой же колонке


Эта таблица значений уже может отображаться в каких-то элементах интерфейса пользователя (например в объекте класса TaбличноеПоле).

Набор сообщений будет реализован в виде класса, имеющего следующие методы:

Заголовок метода Описание
Функция Сообщения_Конструктор () Начальное создание объекта. Возвращает объект класса «Сообщения».
Процедура Сообщения_УстАтриб (Сообщ, Форма, ТабПоле, ТабЗнач) Установка атрибутов объекта. Нужно передать:
— ссылку на форму (Форма), на которой будет отображаться список сообщений;
— элемент формы типа ТабличноеПоле (ТабПоле), в который будут выводится сообщения;
— ТаблицаЗначений (ТабЗнач), в которой будет храниться собственно список сообщений.
Процедура Сообщения_Инициализация (Сообщ) Будет проинициализирована ТаблицаЗначений (ранее установленная процедурой Сообщения_УстАтриб)
Процедура Сообщения_Обновить (Сообщ) Выполняет принудительную отрисовку списка сообщений на форме (ранее установленная процедурой Сообщения_УстАтриб)
Функция Сообщения_Добавить (Сообщ, ТипСообщ, ТекстСообщ, СтатусСообщ=Неопределено, КомментСообщ=Неопределено) Добавляет в набор новое сообщение с соответствующими атрибутами. Возвращает идентификатор сообщения с помощью которого, к данному сообщению можно будет обращаться в дальнейшем.
Процедура Сообщения_Изменить (Сообщ, ИдСообщ, ТипСообщ=Неопределено, ТекстСообщ=Неопределено, СтатусСообщ=Неопределено, КомментСообщ=Неопределено) Изменяет атрибуты уже существующего сообщения с указанным идентификатором.
Процедура Сообщения_Удалить (Сообщ, ИдСообщ) Удалить ранее добавленное сообщение с соответствующим идентификатором.
Процедура Сообщения_Очистить (Сообщ) Удалить все сообщения набора.
Функция Сообщения_ПолучитьТип (Сообщ, ИдСообщ) Получить атрибут «Тип» для существующего сообщения с указанным идентификатором.
Процедура Сообщения_УстановитьТип (Сообщ, ИдСообщ, ТипСообщ) Установить атрибут «Тип» для существующего сообщения с указанным идентификатором.
Функция Сообщения_ПолучитьСтатус (Сообщ, ИдСообщ) Получить атрибут «Статус» для существующего сообщения с указанным идентификатором.
Процедура Сообщения_УстановитьСтатус (Сообщ, ИдСообщ, СтатусСообщ) Установить атрибут «Статус» для существующего сообщения с указанным идентификатором.
Функция Сообщения_ПолучитьТекст (Сообщ, ИдСообщ) Получить атрибут «Текст сообщения» для существующего сообщения с указанным идентификатором.
Процедура Сообщения_УстановитьТекст (Сообщ, ИдСообщ, ТекстСообщ) Установить атрибут «Текст сообщения» для существующего сообщения с указанным идентификатором.
Функция Сообщения_ПолучитьКоммент (Сообщ, ИдСообщ) Получить атрибут «Комментарий» для существующего сообщения с указанным идентификатором.
Процедура Сообщения_УстановитьКоммент (Сообщ, ИдСообщ, КомментСообщ) Установить атрибут «Комментарий» для существующего сообщения с указанным идентификатором.
Функция Сообщения_ЦветТекста (ТипСообщ, СтатусСообщ) Определить цвет текста сообщения для указанного статуса. Используется при раскраске сообщений в интерфейсе.
Функция Сообщения_ЦветКомментария (ТипСообщ, СтатусСообщ) Определить цвет дополнительного текста (комментария) сообщения для указанного статуса. Используется при раскраске сообщений в интерфейсе.
Функция Сообщения_Картинка (ТипСообщ, СтатусСообщ) Определить иконку для сообщения с указанным статусом. Используется при выводе сообщений в интерфейсе.
Функция Сообщения_СохранитьВФайл (Сообщ) Сохранить набор сообщений в текстовый файл (имя файла запрашивает у пользователя).


Итак, полный текст главного модуля обработки:

Текст модуля
////////////////////////////////////////////////////////////////////////////////
// ПРОЧИЕ КОНСТАНТЫ

Перем Проч Экспорт;                       // Структура с константами

Перем КоллекцияКартинок Экспорт;          // Набор иконок интерфейса


////////////////////////////////////////////////////////////////////////////////
// ГЛОБАЛЬНЫЕ ПЕРЕМЕННЫЕ

Перем JavaScript;                         // Машина для работы с JavaScript


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// П О Д П Р О Г Р А М М Ы    И Н И Ц И А Л И З А Ц И И    К О Н С Т А Н Т
//
///////////////////////////////////////////////////////////////////////////////////////////////////

// Инициализирует набор констант общего назначения
//
// Параметры:
//  НЕТ.
//
// Возврат:
//  Структура с полями - константами общего назначения
//
Функция ИнициализацияПрочихКонстант()
        
        Проч = Новый Структура;
        
        // Типы сообщений
        Проч.Вставить("ТИПСООБЩ_НЕОПРЕД", 0);   // Тип неопределен
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ1", 1);  // Сообщение уровня 1
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ2", 2);  // Сообщение уровня 2
        Проч.Вставить("ТИПСООБЩ_УРОВЕНЬ3", 3);  // Сообщение уровня 3

        // Статусы сообщений
        Проч.Вставить("СТАТСООБЩ_НЕОПРЕД", 0);  // Статус неопределен
        Проч.Вставить("СТАТСООБЩ_ОК", 1);       // Статус "ОК"
        Проч.Вставить("СТАТСООБЩ_ПРЕДУПР", 2);  // Статус "Предупреждение"
        Проч.Вставить("СТАТСООБЩ_ОШИБКА", 3);   // Статус "Ошибка"
        
        Возврат Проч
        
КонецФункции


// Формирует набор картинок, на основании изображений, сохраненных в двоичных
// макетах обработки.
//
// Параметры:
//  НЕТ.
//
// Возврат:
//  Структура с полями - объектами типа Картинка с загруженными картинками
//
Функция СформироватьКоллекциюКартинок()
        
        КоллекцияКартинок = Новый Структура;
        
        КоллекцияКартинок.Вставить("СообщениеСтатусОК", Новый Картинка(ПолучитьМакет("КартинкаСообщениеСтатусОК")));
        КоллекцияКартинок.Вставить("СообщениеСтатусПредупреждение", Новый Картинка(ПолучитьМакет("КартинкаСообщениеСтатусПредупреждение")));
        КоллекцияКартинок.Вставить("СообщениеСтатусОшибка", Новый Картинка(ПолучитьМакет("КартинкаСообщениеСтатусОшибка")));
        
        Возврат КоллекцияКартинок
        
КонецФункции


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// П О Д П Р О Г Р А М М Ы    И Н И Ц И А Л И З А Ц И И    Г Л О Б А Л Ь Н Ы Х    П Е Р Е М Е Н Н Ы Х
//
///////////////////////////////////////////////////////////////////////////////////////////////////

// Создает объект JavaScript и возвращает его в качестве значения
// Формирует набор картинок, на основании изображений, сохраненных в двоичных
// макетах обработки.
//
// Параметры:
//  НЕТ.
//
// Возврат:
//  Ссылка на машину JavaScript или Неопределено, если машина не создана
//
Функция СоздатьОбъектJavaScript()
        
        Рез = Неопределено;
        Попытка
                Рез = Новый COMОбъект("MSScriptControl.ScriptControl");
            Рез.Language = "javascript";      
        Исключение
        КонецПопытки;

    Возврат Рез

КонецФункции


///////////////////////////////////////////////////////////////////////////////////////////////////
//
// П О Д П Р О Г Р А М М Ы    О Б Щ Е Г О    Н А З Н А Ч Е Н И Я
//
///////////////////////////////////////////////////////////////////////////////////////////////////

// Расширяет строку до заданной ширины пробелами, добавляя их слева
//
// Параметры:
//  Стр - исходная строка
//  Ширина - кол-во символов до которого нужно расширить строку
// Возврат:
//  Полученная строка
//
Функция РасширСтрЛев(Стр, Ширина)
        
        Рез = Стр;
        Инд = Ширина - СтрДлина(Рез);
        Пока Инд > 0 Цикл
                Рез = " " + Рез;
                Инд = Инд - 1
        КонецЦикла;
        
        Возврат Рез
        
КонецФункции

// Расширяет строку до заданной ширины пробелами, добавляя их справа
//
// Параметры:
//  Стр - исходная строка
//  Ширина - кол-во символов до которого нужно расширить строку
// Возврат:
//  Полученная строка
//
Функция РасширСтрПрав(Стр, Ширина)
        
        Рез = Стр;
        Инд = Ширина - СтрДлина(Рез);
        Пока Инд > 0 Цикл
                Рез = Рез + " ";
                Инд = Инд - 1
        КонецЦикла;
        
        Возврат Рез
        
КонецФункции


// Возвращает текущую дату и время в миллисекундах
//
// Параметры:
//  НЕТ
// Возврат:
//  Числовое значение или 0, если значение определить не удалось
//
Функция ПолучитьТекущееВремяВМиллисекундах() Экспорт
        
        Время = 0;
        Если JavaScript <> Неопределено Тогда
                Время = JavaScript.Eval("new Date().getTime()");
        КонецЕсли;
        
        Возврат Время;
        
КонецФункции


// Преобразует массив чисел из объекта COMSafeArray в строку символов
//
// Параметры:
//  ОбъектCOMSafeArray - ссылка на массив чисел типа COMSafeArray
//                       (размерность массива должна быть 1)
// Возврат:
//  Полученная строка или "", если операцию выполнить не удалось
//
Функция COMSafeArrayВСтроку(ОбъектCOMSafeArray) Экспорт
        
        Рез = "";
        
        Если ТипЗнч(ОбъектCOMSafeArray) = Тип("COMSafeArray") И
                 (ОбъектCOMSafeArray.GetDimensions() = 1) И
                 (ОбъектCOMSafeArray.GetLength(0) > 0) Тогда
                Массив = ОбъектCOMSafeArray.Выгрузить();
                Для Каждого КодСимв Из Массив Цикл
                        Если ТипЗнч(КодСимв) = Тип("Число") Тогда
                                // Перекодировка символа из Windows-1251 в UTF-8
                                Если (КодСимв >= 192) И (КодСимв <= 223) Тогда
                                        // А - Я
                                        КодСимв = КодСимв + 848
                                ИначеЕсли (КодСимв >= 224) И (КодСимв <= 239) Тогда
                                        // а - п
                                        КодСимв = КодСимв + 848
                                ИначеЕсли (КодСимв >= 240) И (КодСимв <= 255) Тогда
                                        // р - я
                                        КодСимв = КодСимв + 848
                                ИначеЕсли (КодСимв = 184) Тогда
                                        // ё
                                        КодСимв = 1105
                                ИначеЕсли (КодСимв = 168) Тогда
                                        // Ё
                                        КодСимв = 1025
                                ИначеЕсли (КодСимв = 185) Тогда
                                        // №
                                        КодСимв = 8470
                                КонецЕсли;
                                // Добавить символ к строке
                                Рез = Рез + Символ(КодСимв)
                        КонецЕсли
                КонецЦикла
        КонецЕсли;
        
        Возврат Рез
        
КонецФункции



///////////////////////////////////////////////////////////////////////////////////////////////////
//
// К Л А С С Ы    О Б Щ Е Г О    Н А З Н А Ч Е Н И Я
//
///////////////////////////////////////////////////////////////////////////////////////////////////


////////////////////////////////////////////////////////////////////////////////
// Реализация класса СообщенияПрограммы (Сообщения)

// Создание полей объекта в виде структуры.
//
// Параметры:
//  Нет.
// Возврат:
//  Возвращает созданную структуру
//
Функция Сообщения_СоздатьОбъект() Экспорт
        
        Сообщ = Новый Структура;
        // Общие параметры сущности
        Сообщ.Вставить("Форма", Неопределено);      // Форма с табличным полем
        Сообщ.Вставить("ТабПоле", Неопределено);    // Табличное поле на форме
        Сообщ.Вставить("ТабЗнач", Неопределено);    // Таблица значений с сообщениями
        Сообщ.Вставить("ВремяПредОбновл", Неопределено); // Время последн. обновл. формы, мс (INT)
        
        Возврат Сообщ;
        
КонецФункции

// Имитирует конструктор объекта.
//
// Параметры:
//  НЕТ
// Возврат:
//  (Структура) - Структура с полями объекта
//
Функция Сообщения_Конструктор() Экспорт
        
        Сообщ = Сообщения_СоздатьОбъект();
        
        Возврат Сообщ;
        
КонецФункции

// Имитирует деструктор объекта - освобождает память.
//
// Параметры:
//  Сообщ - ссылка на объект
//
Процедура Сообщения_Деструктор(Сообщ) Экспорт
        
КонецПроцедуры

// Устанавливает основные атрибуты для вывода сообщений.
//
// Параметры:
//  Сообщ - ссылка на объект
//  Форма - ссылка на форму, на которой расположено табличное поле списка
//  ТабПоле - ссылка табличное поле списка для вывода сообщений
//  ТабЗнач - таблица значений с сообщениями
//
Процедура Сообщения_УстАтриб(Сообщ, Форма, ТабПоле, ТабЗнач) Экспорт
        
        Сообщ.Форма = Форма;
        Сообщ.ТабПоле = ТабПоле;
        Сообщ.ТабЗнач = ТабЗнач
        
КонецПроцедуры

// Инициализирует таблицу сообщений. Добавляет недостающие колонки
//
// Параметры:
//  Сообщ - ссылка на объект
//
Процедура Сообщения_Инициализация(Сообщ) Экспорт
        
        Если Сообщ.ТабЗнач <> Неопределено Тогда
                КЧ = Новый КвалификаторыЧисла(10, 0);
                КС = Новый КвалификаторыСтроки();
                МассивТипов = Новый Массив;
                МассивТипов.Добавить(Тип("Число"));
                ОписаниеТиповЧисла = Новый ОписаниеТипов(МассивТипов, , ,КЧ);
                МассивТипов.Очистить();
                МассивТипов.Добавить(Тип("Строка"));
                ОписаниеТиповСтроки = Новый ОписаниеТипов(МассивТипов, , КС);
                
                // Колонка "ТипСообщ"
                Если Сообщ.ТабЗнач.Колонки.Найти("ТипСообщ") = Неопределено Тогда
                        Сообщ.ТабЗнач.Колонки.Добавить("ТипСообщ", ОписаниеТиповЧисла, "Тип", 30)
                КонецЕсли;
                // Колонка "СтатусСообщ"
                Если Сообщ.ТабЗнач.Колонки.Найти("СтатусСообщ") = Неопределено Тогда
                        Сообщ.ТабЗнач.Колонки.Добавить("СтатусСообщ", ОписаниеТиповЧисла, "Статус", 30)
                КонецЕсли;
                // Колонка "ТекстСообщ"
                Если Сообщ.ТабЗнач.Колонки.Найти("ТекстСообщ") = Неопределено Тогда
                        Сообщ.ТабЗнач.Колонки.Добавить("ТекстСообщ", ОписаниеТиповСтроки, "Текст", 200)
                КонецЕсли;
                // Колонка "КомментарийСообщ"
                Если Сообщ.ТабЗнач.Колонки.Найти("КомментарийСообщ") = Неопределено Тогда
                        Сообщ.ТабЗнач.Колонки.Добавить("КомментарийСообщ", ОписаниеТиповСтроки, "Комментарий", 200)
                КонецЕсли
        КонецЕсли

КонецПроцедуры

// Выполняет овновление формы, на которой размещено табличное поле
// Тем самым вызывает прорисовку сообщений.
// Выполняет это не чаще заданного интервала, мс
//
// Параметры:
//  Сообщ - ссылка на объект
//
Процедура Сообщения_Обновить(Сообщ) Экспорт
        
        Если Сообщ.Форма <> Неопределено Тогда
                Интервал = 500;  // Интервал обновлений (не чаще), мс
                ВремяТекущОбновл = ПолучитьТекущееВремяВМиллисекундах();
                Если (Сообщ.ВремяПредОбновл = Неопределено) ИЛИ
                         (Сообщ.ВремяПредОбновл = 0) ИЛИ
                         (ВремяТекущОбновл - Сообщ.ВремяПредОбновл >= Интервал) Тогда
                        // Выполняем обновление
                        Сообщ.ВремяПредОбновл = ВремяТекущОбновл;
                        Сообщ.Форма.Обновить()
                КонецЕсли
        КонецЕсли
        
КонецПроцедуры

// Добавляет новое сообщение в таблицу значений
//
// Параметры:
//  Сообщ - ссылка на объект;
//  ТипСообщ - тип добавляемого сообщения;
//  ТекстСообщ - текст добавляемого сообщения;
//  СтатусСообщ - статус добавляемого сообщения;
//  КомментСообщ - комментарий к добавляемому сообщению
// Возврат:
//  Уникальный идентификатор добавленного сообщения. Используется для дальнейшего обращения к сообщению с целью
//  его редактирования. По сути представляет собой порядковый номер строки в таблице Сообщ.ТабЗнач
//
Функция Сообщения_Добавить(Сообщ, ТипСообщ, ТекстСообщ, СтатусСообщ=Неопределено, КомментСообщ=Неопределено) Экспорт
        
        ИдСообщ = Неопределено;
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ТипСообщ <> Неопределено) И
                 (ТипСообщ >= Проч.ТИПСООБЩ_УРОВЕНЬ1) И (ТипСообщ <= Проч.ТИПСООБЩ_УРОВЕНЬ3) И
                 (ТекстСообщ <> Неопределено) Тогда
                НоваяСтрока = Сообщ.ТабЗнач.Добавить();
                НоваяСтрока.ТипСообщ = ТипСообщ;
                // Преобразовать текст
                Если ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ1 Тогда
                        
                ИначеЕсли ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ2 Тогда
                        ТекстСообщ = "  " + ТекстСообщ
                ИначеЕсли ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ3 Тогда
                        ТекстСообщ = "    " + ТекстСообщ
                КонецЕсли;
                // Установить текст
                НоваяСтрока.ТекстСообщ = ТекстСообщ;
                Если (СтатусСообщ <> Неопределено) И
                         (СтатусСообщ >= Проч.СТАТСООБЩ_ОК) И (СтатусСообщ <= Проч.СТАТСООБЩ_ОШИБКА) Тогда
                        НоваяСтрока.СтатусСообщ = СтатусСообщ;
                Иначе
                        НоваяСтрока.СтатусСообщ = Проч.СТАТСООБЩ_НЕОПРЕД;
                КонецЕсли;
                НоваяСтрока.КомментарийСообщ = КомментСообщ;
                Если Сообщ.ТабПоле <> Неопределено Тогда
                        // Изменение текущей строки табличного поля на добавляемую,
                        // чтобы пользователь видел, что добавляется в список в данный момент
                        Сообщ.ТабПоле.ТекущаяСтрока = НоваяСтрока;
                КонецЕсли;
                Сообщения_Обновить(Сообщ);
                 
                ИдСообщ = Сообщ.ТабЗнач.Индекс(НоваяСтрока);
        КонецЕсли;
         
        Возврат ИдСообщ

КонецФункции

// Изменяет атрибуты сообщения с идентификатором ИдСообщ. Те, значение которых не "Неопределено"
//
// Параметры:
//  Сообщ - ссылка на объект;
//  ИдСообщ - идентификатор сообщения (порядковый номер строки);
//  ТипСообщ - тип добавляемого сообщения;
//  ТекстСообщ - текст добавляемого сообщения;
//  СтатусСообщ - статус добавляемого сообщения;
//  КомментСообщ - комментарий к добавляемому сообщению
//
Процедура Сообщения_Изменить(Сообщ, ИдСообщ, ТипСообщ=Неопределено, ТекстСообщ=Неопределено, 
                                                         СтатусСообщ=Неопределено, КомментСообщ=Неопределено) Экспорт
        
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) Тогда
                ФлагИзменения = Ложь; // Признак того, что что-то изменили (хоть один атрибут)
                Если ТипСообщ <> Неопределено Тогда
                        Если (ТипСообщ <> Сообщ.ТабЗнач[ИдСообщ].ТипСообщ) И
                                  (ТипСообщ >= Проч.ТИПСООБЩ_УРОВЕНЬ1) И (ТипСообщ <= Проч.ТИПСООБЩ_УРОВЕНЬ3) Тогда
                                Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = ТипСообщ;
                                ФлагИзменения = Истина
                        КонецЕсли
                КонецЕсли;
                Если ТекстСообщ <> Неопределено Тогда
                        Если ТекстСообщ <> Сообщ.ТабЗнач[ИдСообщ].ТекстСообщ Тогда
                                // Преобразовать текст
                                Если Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ1 Тогда
                        
                                ИначеЕсли Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ2 Тогда
                                        ТекстСообщ = "  " + ТекстСообщ
                                ИначеЕсли Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ3 Тогда
                                        ТекстСообщ = "    " + ТекстСообщ
                                КонецЕсли;
                                // Установить текст
                                Сообщ.ТабЗнач[ИдСообщ].ТекстСообщ = ТекстСообщ;
                                ФлагИзменения = Истина
                        КонецЕсли
                КонецЕсли;
                Если СтатусСообщ <> Неопределено Тогда
                        Если СтатусСообщ <> Сообщ.ТабЗнач[ИдСообщ].СтатусСообщ Тогда
                                Если (СтатусСообщ <> Неопределено) И
                                         (СтатусСообщ >= Проч.СТАТСООБЩ_ОК) И (СтатусСообщ <= Проч.СТАТСООБЩ_ОШИБКА) Тогда
                                        Сообщ.ТабЗнач[ИдСообщ].СтатусСообщ = СтатусСообщ;
                                Иначе
                                        Сообщ.ТабЗнач[ИдСообщ].СтатусСообщ = Проч.СТАТСООБЩ_НЕОПРЕД;
                                КонецЕсли;
                                ФлагИзменения = Истина
                        КонецЕсли
                КонецЕсли;
                Если КомментСообщ <> Неопределено Тогда
                        Если КомментСообщ <> Сообщ.ТабЗнач[ИдСообщ].КомментарийСообщ Тогда
                                Сообщ.ТабЗнач[ИдСообщ].КомментарийСообщ = КомментСообщ;
                                ФлагИзменения = Истина
                        КонецЕсли
                КонецЕсли;
                Если ФлагИзменения = Истина Тогда
                        // Прорисовка, если реально було обновление
                        Сообщения_Обновить(Сообщ)
                КонецЕсли
        КонецЕсли

КонецПроцедуры

// Удаляет сообщение с идентификатором ИдСообщ
//
// Параметры:
//  Сообщ - ссылка на объект
//  ИдСообщ - идентификатор сообщения (порядковый номер строки)
//
Процедура Сообщения_Удалить(Сообщ, ИдСообщ) Экспорт
        
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) Тогда
                Сообщ.ТабЗнач.Удалить(ИдСообщ);
                Сообщения_Обновить(Сообщ)
        КонецЕсли
        
КонецПроцедуры

// Удаляет все сообщения из таблицы
//
// Параметры:
//  Сообщ - ссылка на объект
//
Процедура Сообщения_Очистить(Сообщ) Экспорт
        
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (Сообщ.ТабЗнач.Количество() > 0) Тогда
                Сообщ.ТабЗнач.Очистить();
                Сообщения_Обновить(Сообщ)
        КонецЕсли
        
КонецПроцедуры

// Возвращает тип сообщения с идентификатором ИдСообщ
//
// Параметры:
//  Сообщ - ссылка на объект
//  ИдСообщ - идентификатор сообщения (порядковый номер строки)
// Возврат:
//  Тип сообщения или Неопределено, если сообщение не найдено
//
Функция Сообщения_ПолучитьТип(Сообщ, ИдСообщ) Экспорт
        
        Рез = Неопределено;
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) Тогда
                Рез = Сообщ.ТабЗнач[ИдСообщ].ТипСообщ
        КонецЕсли;
         
        Возврат Рез
        
КонецФункции

// Устанавливает тип сообщения с идентификатором ИдСообщ
//
// Параметры:
//  Сообщ - ссылка на объект
//  ИдСообщ - идентификатор сообщения (порядковый номер строки)
//  ТипСообщ - тип сообщения
//
Процедура Сообщения_УстановитьТип(Сообщ, ИдСообщ, ТипСообщ) Экспорт

        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) И
                 (ТипСообщ <> Сообщ.ТабЗнач[ИдСообщ].ТекстСообщ) И
                 (ТипСообщ >= Проч.ТИПСООБЩ_УРОВЕНЬ1) И (ТипСообщ <= Проч.ТИПСООБЩ_УРОВЕНЬ3) Тогда
                Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = ТипСообщ;
                Сообщения_Обновить(Сообщ)
        КонецЕсли;
         
КонецПроцедуры

// Возвращает статус сообщения с идентификатором ИдСообщ
//
// Параметры:
//  Сообщ - ссылка на объект
//  ИдСообщ - идентификатор сообщения (порядковый номер строки)
// Возврат:
//  Статус сообщения или Неопределено, если сообщение не найдено
//
Функция Сообщения_ПолучитьСтатус(Сообщ, ИдСообщ) Экспорт
        
        Рез = Неопределено;
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) Тогда
                 Рез = Сообщ.ТабЗнач[ИдСообщ].СтатусСообщ
        КонецЕсли;
         
        Возврат Рез
        
КонецФункции

// Устанавливает статус сообщения с идентификатором ИдСообщ
//
// Параметры:
//  Сообщ - ссылка на объект
//  ИдСообщ - идентификатор сообщения (порядковый номер строки)
//  СтатусСообщ - статус сообщения
//
Процедура Сообщения_УстановитьСтатус(Сообщ, ИдСообщ, СтатусСообщ) Экспорт
        
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) И
                 (СтатусСообщ <> Сообщ.ТабЗнач[ИдСообщ].СтатусСообщ) Тогда
                Если (СтатусСообщ <> Неопределено) И
                         (СтатусСообщ >= Проч.СТАТСООБЩ_ОК) И (СтатусСообщ <= Проч.СТАТСООБЩ_ОШИБКА) Тогда
                        Сообщ.ТабЗнач[ИдСообщ].СтатусСообщ = СтатусСообщ;
                Иначе
                        Сообщ.ТабЗнач[ИдСообщ].СтатусСообщ = Проч.СТАТСООБЩ_НЕОПРЕД;
                КонецЕсли;
                Сообщения_Обновить(Сообщ)
        КонецЕсли
        
КонецПроцедуры

// Возвращает текст сообщения с идентификатором ИдСообщ
//
// Параметры:
//  Сообщ - ссылка на объект
//  ИдСообщ - идентификатор сообщения (порядковый номер строки)
// Возврат:
//  Текст сообщения или Неопределено, если сообщение не найдено
//
Функция Сообщения_ПолучитьТекст(Сообщ, ИдСообщ) Экспорт
        
        Рез = Неопределено;
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) Тогда
                Рез = Сообщ.ТабЗнач[ИдСообщ].ТекстСообщ
        КонецЕсли;
         
        Возврат Рез
        
КонецФункции

// Устанавливает текст сообщения с идентификатором ИдСообщ
//
// Параметры:
//  Сообщ - ссылка на объект
//  ИдСообщ - идентификатор сообщения (порядковый номер строки)
//  ТекстСообщ - текст добавляемого сообщения;
//
Процедура Сообщения_УстановитьТекст(Сообщ, ИдСообщ, ТекстСообщ) Экспорт
        
        Если (Сообщ.ТабЗнач <> Неопределено) И
                 (ИдСообщ <> Неопределено) И
                 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) И
                 (ТекстСообщ <> Неопределено) И
                 (ТекстСообщ <> Сообщ.ТабЗнач[ИдСообщ].ТипСообщ) Тогда
                // Преобразовать текст
                Если Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ1 Тогда
                        
                ИначеЕсли Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ2 Тогда
                        ТекстСообщ = "  " + ТекстСообщ
                ИначеЕсли Сообщ.ТабЗнач[ИдСообщ].ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ3 Тогда
                        ТекстСообщ = "    " + ТекстСообщ
                КонецЕсли;
                // Установить текст
                Сообщ.ТабЗнач[ИдСообщ].ТекстСообщ = ТекстСообщ;
                Сообщения_Обновить(Сообщ)
        КонецЕсли
        
КонецПроцедуры

// Возвращает ко
    
            

© Habrahabr.ru