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

от автора


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

Предыстория.

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

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

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

Описание реализации.

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

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

Изображение Название исходного файла Название макета
statok.bmp КартинкаСообщениеСтатусОК
statwarning.bmp КартинкаСообщениеСтатусПредупреждение
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 Тогда 			ТекстСообщ = "    " + ТекстСообщ 		КонецЕсли; 		// Установить текст 		Сообщ.ТабЗнач[ИдСообщ].ТекстСообщ = ТекстСообщ; 		Сообщения_Обновить(Сообщ) 	КонецЕсли 	 КонецПроцедуры  // Возвращает комментарий к сообщению с идентификатором ИдСообщ // // Параметры: //  Сообщ - ссылка на объект //  ИдСообщ - идентификатор сообщения (порядковый номер строки) // Возврат: //  Комментарий сообщения или Неопределено, если сообщение не найдено // Функция Сообщения_ПолучитьКоммент(Сообщ, ИдСообщ) Экспорт 	 	Рез = Неопределено; 	Если (Сообщ.ТабЗнач <> Неопределено) И 		 (ИдСообщ <> Неопределено) И 		 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) Тогда 		Рез = Сообщ.ТабЗнач[ИдСообщ].КомментарийСообщ 	КонецЕсли; 	  	Возврат Рез 	 КонецФункции  // Устанавливает комментарий к сообщению с идентификатором ИдСообщ // // Параметры: //  Сообщ - ссылка на объект //  ИдСообщ - идентификатор сообщения (порядковый номер строки) //  КомментСообщ - комментарий к сообщению // Процедура Сообщения_УстановитьКоммент(Сообщ, ИдСообщ, КомментСообщ) Экспорт 	 	Если (Сообщ.ТабЗнач <> Неопределено) И 		 (ИдСообщ <> Неопределено) И 		 (ИдСообщ >= 0) И (ИдСообщ < Сообщ.ТабЗнач.Количество()) И 		 (КомментСообщ <> Сообщ.ТабЗнач[ИдСообщ].КомментарийСообщ) Тогда 		Сообщ.ТабЗнач[ИдСообщ].КомментарийСообщ = КомментСообщ; 		Сообщения_Обновить(Сообщ) 	КонецЕсли 	 КонецПроцедуры  // В зависимости от типа сообщения и статуса определяет цвет текста сообщения // // Параметры: //  ТипСообщ - тип сообщения //  СтатусСообщ - статус сообщения // Возврат: //  Цвет текста сообщения // Функция Сообщения_ЦветТекста(ТипСообщ, СтатусСообщ) Экспорт 	 	Рез = Неопределено; 	Если ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ1 Тогда 		Рез = WebЦвета.Черный 	ИначеЕсли ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ2 Тогда 		Рез = WebЦвета.Черный 	ИначеЕсли ТипСообщ = Проч.ТИПСООБЩ_УРОВЕНЬ3 Тогда 		Рез = WebЦвета.Черный 	КонецЕсли; 	 	Возврат Рез 	 КонецФункции  // В зависимости от типа сообщения и статуса определяет цвет текста комментария // // Параметры: //  ТипСообщ - тип сообщения //  СтатусСообщ - статус сообщения // Возврат: //  Цвет текста комментария // Функция Сообщения_ЦветКомментария(ТипСообщ, СтатусСообщ) Экспорт 	 	Рез = Неопределено; 	Если СтатусСообщ = Проч.СТАТСООБЩ_ОК Тогда 		Рез = WebЦвета.Зеленый 	ИначеЕсли СтатусСообщ = Проч.СТАТСООБЩ_ПРЕДУПР Тогда 		Рез = WebЦвета.Оранжевый 	ИначеЕсли СтатусСообщ = Проч.СТАТСООБЩ_ОШИБКА Тогда 		Рез = WebЦвета.Красный 	КонецЕсли; 	 	Возврат Рез 	 КонецФункции  // В зависимости от типа сообщения и статуса определяет картинку статуса сообщения // // Параметры: //  ТипСообщ - тип сообщения //  СтатусСообщ - статус сообщения // Возврат: //  Картинка статуса сообщения // Функция Сообщения_Картинка(ТипСообщ, СтатусСообщ) Экспорт 	 	Рез = Неопределено; 	Если СтатусСообщ = Проч.СТАТСООБЩ_ОК Тогда 		Рез = КоллекцияКартинок.СообщениеСтатусОК 	ИначеЕсли СтатусСообщ = Проч.СТАТСООБЩ_ПРЕДУПР Тогда 		Рез = КоллекцияКартинок.СообщениеСтатусПредупреждение 	ИначеЕсли СтатусСообщ = Проч.СТАТСООБЩ_ОШИБКА Тогда 		Рез = КоллекцияКартинок.СообщениеСтатусОшибка 	КонецЕсли; 	 	Возврат Рез  КонецФункции  // Запрашивает имя файла и сохраняет набор сообщений в текстовый файл // // Параметры: //  Сообщ - ссылка на объект // Возврат: //  Истина, если сохранение выполнено и Ложь - в противном случае // Функция Сообщения_СохранитьВФайл(Сообщ) Экспорт 	 	Рез = Ложь;	// Еще ничего не сохранили 	 	Если Сообщ.ТабЗнач = Неопределено  Тогда 		// Неверные параметры 		Возврат Рез 	КонецЕсли; 	 	// Создать диалог и выбрать файл для сохранения 	ДиалогВыбораФайла								=	Новый ДиалогВыбораФайла(РежимДиалогаВыбораФайла.Сохранение); 	 	ДиалогВыбораФайла.Фильтр						=	"Текстовые файлы (*.txt)|*.txt" + 														"|Все файлы (*.*)|*.*"; 	ДиалогВыбораФайла.Заголовок						=	"Сохранение сообщений"; 	ДиалогВыбораФайла.МножественныйВыбор            =   Ложь; 	ДиалогВыбораФайла.ПредварительныйПросмотр		=	Ложь; 	ДиалогВыбораФайла.Расширение					=	"txt"; 	ДиалогВыбораФайла.ИндексФильтра					=	0; 	ДиалогВыбораФайла.ПроверятьСуществованиеФайла	=	Истина; 	 	Если ДиалогВыбораФайла.Выбрать() Тогда 		// Выполнить сохранение 		Попытка 			// Открыть файл 			ЗаписьТекста = Новый ЗаписьТекста(ДиалогВыбораФайла.ПолноеИмяФайла, КодировкаТекста.ANSI); 			 			// Сформировать и записать в файл строки сообщений  			// Выяснить максимальные длины строк в сообщениях 			ДлинаТекстаМакс = 0; 			ДлинаКомментМакс = 0; 			Для Каждого СтрокаТЗ Из Сообщ.ТабЗнач Цикл 				ДлинаТекстаТек = СтрДлина(СтрокаТЗ.ТекстСообщ); 				Если ДлинаТекстаТек > ДлинаТекстаМакс Тогда 					ДлинаТекстаМакс = ДлинаТекстаТек; 				КонецЕсли; 				ДлинаКомментТек = СтрДлина(СтрокаТЗ.КомментарийСообщ); 				Если ДлинаКомментТек > ДлинаКомментМакс Тогда 					ДлинаКомментМакс = ДлинаКомментТек; 				КонецЕсли; 			КонецЦикла; 			// Выполнить запись строк 			Для Каждого СтрокаТЗ Из Сообщ.ТабЗнач Цикл 				Дист = "  ";  // Разделитель элементов строки 				Стр = ""; 				 				// Записать в строку статус сообщения 				Если (СтрокаТЗ.СтатусСообщ <> Неопределено) И 					 (СтрокаТЗ.СтатусСообщ <> Проч.СТАТСООБЩ_НЕОПРЕД) Тогда 					СтатусСтр = ""; 					Если СтрокаТЗ.СтатусСообщ = Проч.СТАТСООБЩ_ОК Тогда 						СтатусСтр = "ОК"; 					ИначеЕсли СтрокаТЗ.СтатусСообщ = Проч.СТАТСООБЩ_ПРЕДУПР Тогда 						СтатусСтр = "ПРЕДУПРЕЖДЕНИЕ"; 					ИначеЕсли СтрокаТЗ.СтатусСообщ = Проч.СТАТСООБЩ_ОШИБКА Тогда 						СтатусСтр = "ОШИБКА"; 					КонецЕсли; 					Если Стр <> "" Тогда 						Стр = Стр + Дист 					КонецЕсли; 					Стр = Стр + РасширСтрПрав(СтатусСтр, 14); 				КонецЕсли; 				// Записать в строку текст сообщения 				Если (СтрокаТЗ.ТекстСообщ <> Неопределено) И 					 (СтрокаТЗ.ТекстСообщ <> "") Тогда 					Если Стр <> "" Тогда 						Стр = Стр + Дист 					КонецЕсли; 					Стр = Стр + РасширСтрПрав(СтрокаТЗ.ТекстСообщ, ДлинаТекстаМакс); 				КонецЕсли; 				// Записать в строку текст комментария 				Если (СтрокаТЗ.КомментарийСообщ <> Неопределено) И 					 (СтрокаТЗ.КомментарийСообщ <> "") Тогда 					Если Стр <> "" Тогда 						Стр = Стр + Дист 					КонецЕсли; 					Стр = Стр + РасширСтрПрав(СтрокаТЗ.КомментарийСообщ, ДлинаКомментМакс); 				КонецЕсли; 				// Записать строку в файл 				Если Стр <> "" Тогда 					ЗаписьТекста.ЗаписатьСтроку(Стр) 				КонецЕсли 			КонецЦикла; 			 			// Закрыть файл 			ЗаписьТекста.Закрыть(); 			 			Рез = Истина	// Операция выполнена успешно 		Исключение 			// Сообщение об ошибке 			Предупреждение("Ошибка сохранения сообщений:" + Символы.ПС + 							ИнформацияОбОшибке().Описание); 		КонецПопытки 	КонецЕсли;  	Возврат Рез 	 КонецФункции     //////////////////////////////////////////////////////////////////////////////// // ОПЕРАТОРЫ ОСНОВНОЙ ПРОГРАММЫ - НАЧАЛЬНАЯ ИНИЦИАЛИЗАЦИЯ    // ИНИЦИАЛИЗАЦИЯ КОНСТАНТ  // Константы общего назначения Проч = ИнициализацияПрочихКонстант();  // Коллекция картинок КоллекцияКартинок = СформироватьКоллекциюКартинок();    // ИНИЦИАЛИЗАЦИЯ ГЛОБАЛЬНЫХ ПЕРЕМЕННЫХ  // Создать машину JavaScript JavaScript = СоздатьОбъектJavaScript(); 

Обратите внимание на то, что при выполнении длительного процесса в цикле, интерфейс пользователя блокируется, и поэтому факт добавления или изменения сообщений не будет виден пользователю – прорисовки не будет. Для принудительного выполнения прорисовки, нужно вызвать метод Обновить() формы, отображающей сообщения. Но частый вызов этого метода затормозит работу, поэтому вызывать его нужно лишь иногда (хоть и с небольшим интервалом, чтобы пользователь не заметил лагов – в данной реализации интервал обновления не чаще чем 1 раз в 0,5сек). Для реализации обновления служит метод класса Сообщения_Обновить.

Пример использования.

В данном примере форма, отображающая набор сообщений выглядит вот так:

Вместо кнопки «Запустить процесс», в реальности должно быть что-то более полезное – какой-то пользовательский интерфейс. Кнопка «Запустить процесс» имитирует заполнение списка сообщений, демонстрируя то, как могли бы выводиться сообщения в процессе реального выполнения какого-либо длительного действия.
В качестве реквизитов формы создана ТаблицаЗначений — «Сообщения». Мы ее никак не инициализируем, а просто передаем в качестве параметров соответствующим методам класса «Сообщения_», а они уже создают нужные колонки:

ОбъектСообщ = Сообщения_Конструктор(); Сообщения_УстАтриб(ОбъектСообщ, ЭтаФорма, ЭлементыФормы.ТабличноеПолеСообщения, Сообщения); Сообщения_Инициализация(ОбъектСообщ); 

Для отображения ТаблицыЗначений «Сообщения», на форме размещен визуальный компонент типа «ТабличноеПоле» — «ТабличноеПолеСообщения». При создании колонок в ТабличномПоле, учитываем следующие колонки ТаблицыЗначений (описывались ранее):
ТипСообщ;
СтатусСообщ;
ТекстСообщ;
КомментарийСообщ.

Текст модуля главной формы обработки (отображающей сообщения):

Текст модуля формы

//////////////////////////////////////////////////////////////////////////////// // ОСНОВНОЕ ОКНО ПРОГРАММЫ  Перем ОбъектСообщ;          // Объект для вывода сообщений в таблицу знач. и отобр. в табл. поле   //////////////////////////////////////////////////////////////////////////////// // ОБРАБОТЧИКИ СОБЫТИЙ ФОРМЫ  // Процедура - обработчик события "При открытии" формы. Данное событие // возникает при открытии формы, до показа окна пользователю. // // Параметры: //  Нет. // Процедура ПриОткрытии() 	 	// Создание объекта сообщений и инициализация таблицы сообщений 	ОбъектСообщ = Сообщения_Конструктор(); 	Сообщения_УстАтриб(ОбъектСообщ, ЭтаФорма, ЭлементыФормы.ТабличноеПолеСообщения, Сообщения); 	Сообщения_Инициализация(ОбъектСообщ); 	 КонецПроцедуры  // Процедура - обработчик события "При закрытии" формы. Данное событие // возникает после закрытия формы. // Освобождение занятых ресурсов. // // Параметры: //  Нет. // Процедура ПриЗакрытии() 	 	// Завершить работу с объектом вывода сообщений 	Сообщения_Деструктор(ОбъектСообщ) 	 КонецПроцедуры   // Процедура - обработчик события "Нажатие" кнопки КнопкаЗапуститьПроцесс. // Имитирует операцию, в процессе выполнения которой выводятся сообщения. // // Параметры: //  Элемент - кнопка. // Процедура КнопкаЗапуститьПроцессНажатие(Элемент) 	 	// Подготовка данных к началу операции 	ГСЧ = Новый ГенераторСлучайныхЧисел();     ВсегоОбъектов = ГСЧ.СлучайноеЧисло(1, 100); 	// Запросить согласие пользователя на выполнение операции 	РезВопр = Вопрос("Выполнить обработку данных?", 			 		 РежимДиалогаВопрос.ДаНет, 				 	 , 					 , 				 	 "Обработка данных"); 	Если РезВопр = КодВозвратаДиалога.Да Тогда 		// Подготовка интерфейса к запуску процесса 		ErrMsg = ""; 		Сообщения_Очистить(ОбъектСообщ); 		// Сообщение о начале операции 		Сообщения_Добавить(ОбъектСообщ, Проч.ТИПСООБЩ_УРОВЕНЬ1, "*** НАЧАЛО ОБРАБОТКИ ДАННЫХ ***"); 		Рез = Ложь; 		КолОбрОб = 0; 		Попытка 			// Выполнять обработку объектов 			Для Инд=1 По ВсегоОбъектов Цикл 				// Вывести сообщение о том, что началась обработка очередного объекта 				ИдСообщУр2 = Сообщения_Добавить(ОбъектСообщ, Проч.ТИПСООБЩ_УРОВЕНЬ2, "Обработка объекта " + Формат(Инд, "ЧГ=0; ЧН=''")); 				 				// ****************************** 				// Здесь собственно выполняется сама операция над текущим объектом 				Если ГСЧ.СлучайноеЧисло(0, ВсегоОбъектов) > 0 Тогда 					// Считаем, что операция над текущим объектом выполнена успешно 					Рез = Истина 				Иначе 					// Считаем, что операция над текущим объектом выполнена с ошибкой 					Рез = Ложь 				КонецЕсли; 				// ****************************** 				 				// Установить результат операции над текущим объектом в окне сообщений 				СтатСообщ = Проч.СТАТСООБЩ_НЕОПРЕД; 				КоммСообщ = ""; 				Если Рез Тогда 					// Операция завершена удачно 					СтатСообщ = Проч.СТАТСООБЩ_ОК; 					КоммСообщ = "ОК" 				Иначе 					// Ошибки при выполнении операции 					СтатСообщ = Проч.СТАТСООБЩ_ОШИБКА; 					КоммСообщ = "ОШИБКА" 				КонецЕсли; 				Сообщения_Изменить(ОбъектСообщ, ИдСообщУр2, , , СтатСообщ, КоммСообщ); 								    				// Анализируем результат текущей итерации														   				Если НЕ Рез Тогда 					// Ошибка - прервать работу 					Прервать 				КонецЕсли; 				КолОбрОб = КолОбрОб + 1 			КонецЦикла 		Исключение 			// Возникло исключение - ошибка 			ErrMsg = ИнформацияОбОшибке().Описание; 			Рез = Ложь 		КонецПопытки; 		// Сообщение об окончании операции 		Если Рез Тогда 			// Операция завершена успешно 			Сообщения_Добавить(ОбъектСообщ, Проч.ТИПСООБЩ_УРОВЕНЬ1, "*** ОБРАБОТКА ДАННЫХ ЗАВЕРШЕНА ***"); 		Иначе 			// Операция прервана 			Сообщения_Добавить(ОбъектСообщ, Проч.ТИПСООБЩ_УРОВЕНЬ1, "*** ОБРАБОТКА ДАННЫХ ПРЕРВАНА ***", Проч.СТАТСООБЩ_ОШИБКА, ErrMsg) 		КонецЕсли;     	// Установка интерфейса по окончанию загрузки 		ТекстСообщ = ""; 		Если Рез Тогда 			ТекстСообщ = "Обработка выполнена успешно" 		Иначе 			ТекстСообщ = "Обработка выполнена с ошибками" 		КонецЕсли; 		ТекстСообщ = ТекстСообщ + Символы.ПС; 		ТекстСообщ = ТекстСообщ + "Обработано " + Формат(КолОбрОб, "ЧГ=0; ЧН=''") + " объектов."; 		Предупреждение(ТекстСообщ, , "Обработка данных") 	КонецЕсли КонецПроцедуры  // Процедура - обработчик события "ПриВыводеСтроки" табличного поля // ТабличноеПолеСообщения. Данное событие происходит при выводе каждой строки. // // Параметры: //  Элемент - табличное поле; //  ОформлениеСтроки - объект настройки визуального оформления строки //  ДанныеСтроки - набор данных строки табличного поля. // Процедура ТабличноеПолеСообщенияПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) 	 	// Оформление ячейки "Статус" 	ОформлениеСтроки.Ячейки.КолонкаСтатусСообщения.ОтображатьТекст = Ложь; 	КартинкаСтатуса = Сообщения_Картинка(ДанныеСтроки.ТипСообщ, ДанныеСтроки.СтатусСообщ); 	Если КартинкаСтатуса <> Неопределено Тогда 		ОформлениеСтроки.Ячейки.КолонкаСтатусСообщения.ОтображатьКартинку = Истина; 		ОформлениеСтроки.Ячейки.КолонкаСтатусСообщения.Картинка = КартинкаСтатуса; 	КонецЕсли; 	// Оформление ячейки "Текст" 	Если (ДанныеСтроки.ТекстСообщ <> Неопределено) И 		 (ДанныеСтроки.ТекстСообщ <> "") Тогда 		ЦветТекста = Сообщения_ЦветТекста(ДанныеСтроки.ТипСообщ, ДанныеСтроки.СтатусСообщ); 		Если ЦветТекста <> Неопределено Тогда 			ОформлениеСтроки.Ячейки.КолонкаТекстСообщения.ЦветТекста = ЦветТекста 		КонецЕсли 	КонецЕсли; 	// Оформление ячейки "Комментарий" 	Если (ДанныеСтроки.КомментарийСообщ <> Неопределено) И 		 (ДанныеСтроки.КомментарийСообщ <> "") Тогда 		ЦветКомментария = Сообщения_ЦветКомментария(ДанныеСтроки.ТипСообщ, ДанныеСтроки.СтатусСообщ); 		Если ЦветКомментария <> Неопределено Тогда 			ОформлениеСтроки.Ячейки.КолонкаКомментарийСообщения.ЦветТекста = ЦветКомментария 		КонецЕсли 	КонецЕсли 	 КонецПроцедуры  // Процедура - обработчик события "Нажатие" кнопки КнопкаСообщенияОткрытьВНовомОкне. // Открывает текущий список сообщений в новом окне. // // Параметры: //  Элемент - кнопка. // Процедура КнопкаСообщенияОткрытьВНовомОкнеНажатие(Элемент)  	ФормаПросмотраСообщений = ЭтотОбъект.ПолучитьФорму("ФормаПросмотраСообщений", ЭтаФорма); 	ФормаПросмотраСообщений.ShowMessagesDlg(ОбъектСообщ) 	 КонецПроцедуры  // Процедура - обработчик события "Нажатие" кнопки КнопкаСообщенияСохранить. // Сохранить текущий набор сообщений в файл. // // Параметры: //  Элемент - кнопка. // Процедура КнопкаСообщенияСохранитьНажатие(Элемент)  	Сообщения_СохранитьВФайл(ОбъектСообщ); 	 КонецПроцедуры 

Форма просмотра сообщений.

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

Выглядит форма примерно следующим образом:

Код модуля формы совсем несложный. Вот такой:

Текст модуля формы

//////////////////////////////////////////////////////////////////////////////// // ДИАЛОГ ДЛЯ ОТОБРАЖЕНИЯ СПИСКА СООБЩЕНИЙ В ОТДЕЛЬНОМ ОКНЕ  Перем ОбъектСообщ;      // Объект для работы с сообщениями    //////////////////////////////////////////////////////////////////////////////// // ОБРАБОТЧИКИ СОБЫТИЙ ФОРМЫ  // Процедура - обработчик события "Действие" элемента меню КоманднаяПанельМенюСохранитьВФайл. // Сохранить текущий набор сообщений в файл. // // Параметры: //  Кнопка - элемент меню. // Процедура КоманднаяПанельМенюСохранитьВФайл(Кнопка) 	 	Сообщения_СохранитьВФайл(ОбъектСообщ);  КонецПроцедуры  // Процедура - обработчик события "ПриВыводеСтроки" табличного поля // ТабличноеПолеСообщения. Данное событие происходит при выводе каждой строки. // // Параметры: //  Элемент - табличное поле; //  ОформлениеСтроки - объект настройки визуального оформления строки //  ДанныеСтроки - набор данных строки табличного поля. // Процедура ТабличноеПолеСообщенияПриВыводеСтроки(Элемент, ОформлениеСтроки, ДанныеСтроки) 	 	// Оформление ячейки "Статус" 	ОформлениеСтроки.Ячейки.КолонкаСтатусСообщения.ОтображатьТекст = Ложь; 	КартинкаСтатуса = Сообщения_Картинка(ДанныеСтроки.ТипСообщ, ДанныеСтроки.СтатусСообщ); 	Если КартинкаСтатуса <> Неопределено Тогда 		ОформлениеСтроки.Ячейки.КолонкаСтатусСообщения.ОтображатьКартинку = Истина; 		ОформлениеСтроки.Ячейки.КолонкаСтатусСообщения.Картинка = КартинкаСтатуса; 	КонецЕсли; 	// Оформление ячейки "Текст" 	Если (ДанныеСтроки.ТекстСообщ <> Неопределено) И 		 (ДанныеСтроки.ТекстСообщ <> "") Тогда 		ЦветТекста = Сообщения_ЦветТекста(ДанныеСтроки.ТипСообщ, ДанныеСтроки.СтатусСообщ); 		Если ЦветТекста <> Неопределено Тогда 			ОформлениеСтроки.Ячейки.КолонкаТекстСообщения.ЦветТекста = ЦветТекста 		КонецЕсли 	КонецЕсли; 	// Оформление ячейки "Комментарий" 	Если (ДанныеСтроки.КомментарийСообщ <> Неопределено) И 		 (ДанныеСтроки.КомментарийСообщ <> "") Тогда 		ЦветКомментария = Сообщения_ЦветКомментария(ДанныеСтроки.ТипСообщ, ДанныеСтроки.СтатусСообщ); 		Если ЦветКомментария <> Неопределено Тогда 			ОформлениеСтроки.Ячейки.КолонкаКомментарийСообщения.ЦветТекста = ЦветКомментария 		КонецЕсли 	КонецЕсли 	 КонецПроцедуры   //////////////////////////////////////////////////////////////////////////////// // ПОДПРОГРАММЫ ВНЕШНЕГО ИНТЕРФЕЙСА   // Вызов диалога просмотра списка сообщений // // Параметры: //  ОбъектСообщения - объект для работы с сообщениями. // Процедура ShowMessagesDlg(ОбъектСообщений) Экспорт;  	Если ОбъектСообщений <> Неопределено Тогда 		// Выполнить начальную установку параметров 		ОбъектСообщ = ОбъектСообщений; 		ЭлементыФормы.ТабличноеПолеСообщения.Значение = ОбъектСообщ.ТабЗнач; 		// Вызвать диалог 		ЭтаФорма.ОткрытьМодально() 	КонецЕсли 	 КонецПроцедуры 

Скачать исходные тексты подсистемы сообщений и рассмотренный пример (обработка для 1С 8.2) можно здесь.

На этом все. Всем удачи. До встречи.

P.S.

В следующей статье я планирую рассказать о работе с сервером (базами) FireBird из 1С.
Мы выясним:
— как корректно подключаться к серверу (базе) и отключаться;
— как выполнять запросы: передавать и получать данные;
— как работать с бинарными полями и строками в различной кодировке;
— как вызывать хранимые процедуры и получать результаты их работы;
— как обойти такую неприятность, как автоматический разрыв клиентского соединения со стороны сервера FireBird (простой и понятный способ, который почему-то нигде не описан в Интернете).

Мы создадим обособленные и переносимые наборы подпрограмм («классов»):
— для подключения к базе (сможем подключаться к серверу, базе и выполнять запросы);
— для работы с параметрами запроса (можно будет задавать и устанавливать параметры почти как в Delphi);
А также:
— для работы с множествами целых чисел и строк (удобно задавать множественные параметры для запросов);
— удобное хранилище профилей подключений к различным базам FireBird, а также интерфейс пользователя (форма для редактирования набора профилей подключений)

В общем, думаю, что будет интересно. Еще раз, удачи…

ссылка на оригинал статьи https://habrahabr.ru/post/278521/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *