Как сообщить пользователю об ошибке 1с

О чем эта статья

Статья продолжает цикл статей «Первые шаги в разработке на 1С».

В ней мы рассмотрим способы информирования пользователя, которые присутствуют в платформе «1С:Предприятие» 8, а также акцентируем ваше внимание на некоторых особенностях работы этих механизмов, эти особенности связаны с режимом использования модальности.

Применимость

В статье рассматривается функциональность:

  • Интерфейса в варианте «Версии 8.2» для конфигурации, разработанной на платформе «1С:Предприятие» 8.2.19.130
  • Интерфейса «Такси» для конфигурации, разработанной на платформе «1С:Предприятие» 8.3.4.496 до 8.3.9+
  • Интерфейса «Такси» для конфигурации, разработанной на платформе «1С:Предприятие» 8.3.10-8.3.11

Как в 1С вывести сообщение пользователю

  1. Ознакомительные сообщения
  2. Механизм оповещений
  3. Терминирующие сообщения
  4. Особенности использования модальных окон в Платформе 8.3
  5. Класс СообщениеПользователю
  6. Уведомление о состоянии процесса

Вывод сообщений в пользовательском режиме решает ряд задач:

  • отражение хода выполнения текущего процесса (показ стадии выполнения процесса; показ расчетных значений, полученных в ходе работы алгоритма);
  • выдача ошибок пользователю для возможного их исправления;
  • выдача рекомендаций;

Типы сообщений:

  • терминирующие, которые останавливают выполнение программы и не дают продолжить ее, пока пользователь не ознакомится с этим сообщением и не выполнит определенные действия. Например, на экран пользователю будет выдан вопрос, на который нужно будет ответить Да или Нет. Пока пользователь не ответит – программа не выполняет дальнейшие действия;
  • ознакомительные сообщения, которые просто выводятся для пользователя и позволяют работать дальше (т.е. используются в режиме оповещения).

Терминирующими сообщениями должны быть сообщения об ошибках, а ознакомительными: рекомендации, сообщения о текущем этапе процесса и показ расчетных значений (отладочная печать).

Ознакомительные сообщения

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

Необходимо, чтобы пользователь с ней обязательно ознакомился и, возможно, предпринял какие-то действия, которые описаны в этом сообщении.

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

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

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

Открепить от формы окно с сообщением нельзя.

Синтаксис функции:

Сообщить (<Текст сообщения>, <Статус>)

Т.е. первым параметром является сам текст.

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

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

В концепции управляемого интерфейса значок всегда в виде восклицательного знака, переопределить его нельзя.

Ознакомительные сообщения

Дело в том, что если сообщение будет формироваться в момент записи элемента справочника, может произойти следующая ситуация.

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

Но форма моментально закрывается, и пользователь не увидит, что для него выводилась какая-то информация.

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

Неправильное использование функции Сообщить

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

В этом случае системе можно сообщить, что форму закрывать не нужно, и показать пользователю, какие ошибки возникают при проведении документа.

Функция Сообщить полностью поддерживается в Платформе 8.3. Ее можно использовать, и она будет работать (и в файловом варианте, и в клиент-серверном).

Но также следует отметить, что у функции Сообщить есть дальнейшее развитие – это класс сообщения пользователю, который позволяет помимо того, что выводить сообщение, привязывать его контекстно к каким-либо элементам формы.

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

Так, программный код в Платформе 8.3 может быть исполнен как на стороне Клиента, так и на стороне Сервера.

При этом клиентский программный код отвечает за взаимодействие с пользователем, т.е. на стороне клиента открываются формы, выводятся отчеты.

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

Но функция Сообщить может быть исполнена как на стороне Клиента, так и на стороне Сервера. При этом использование метода Сообщить на Сервере вовсе не означает, что сообщение будет выводиться именно на Сервере, там их просто некуда выводить.

Это означает, что если мы в серверной процедуре будем выводить сообщение с помощью этого метода, они будут накапливаться в некотором буфере и выведутся они на экран только тогда, когда серверная процедура закончится и произойдет возврат на Клиента.

В этот момент система запросит данные из буфера и выведет их на экран.

Эта же особенность касается и класса СообщениеПользователю. На рисунке приведен пример использования метода Сообщить на стороне Сервера.

НаСервере Сообщить

Дело в том, что если сообщение будет формироваться в момент записи элемента справочника, может произойти следующая ситуация.

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

Но форма моментально закрывается, и пользователь не увидит, что для него выводилась какая-то информация.

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

Неправильное использование функции Сообщить

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

В этом случае системе можно сообщить, что форму закрывать не нужно, и показать пользователю, какие ошибки возникают при проведении документа.

Функция Сообщить полностью поддерживается в Платформе 8.3. Ее можно использовать, и она будет работать (и в файловом варианте, и в клиент-серверном).

Но также следует отметить, что у функции Сообщить есть дальнейшее развитие – это класс сообщения пользователю, который позволяет помимо того, что выводить сообщение, привязывать его контекстно к каким-либо элементам формы.

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

Так, программный код в Платформе 8.3 может быть исполнен как на стороне Клиента, так и на стороне Сервера.

При этом клиентский программный код отвечает за взаимодействие с пользователем, т.е. на стороне клиента открываются формы, выводятся отчеты.

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

Но функция Сообщить может быть исполнена как на стороне Клиента, так и на стороне Сервера. При этом использование метода Сообщить на Сервере вовсе не означает, что сообщение будет выводиться именно на Сервере, там их просто некуда выводить.

Это означает, что если мы в серверной процедуре будем выводить сообщение с помощью этого метода, они будут накапливаться в некотором буфере и выведутся они на экран только тогда, когда серверная процедура закончится и произойдет возврат на Клиента.

В этот момент система запросит данные из буфера и выведет их на экран.

Эта же особенность касается и класса СообщениеПользователю. На рисунке приведен пример использования метода Сообщить на стороне Сервера.

НаСервере Сообщить

В результате использования метода Сообщить на стороне Сервера вывелись сообщения на экран на стороне Клиента.

Сообщения на Клиенте

Механизм оповещений

Механизм оповещений нужен, чтобы информировать пользователя о том, что в системе “что-то” произошло и это “что-то” требует внимания пользователя. Оповещения создаются двумя сценариями:

  1. Самой платформой при интерактивной записи или изменении объекта
  2. Разработчиком при вызове в коде метода ПоказатьОповещениеПользователя().

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

Механизм оповещений

Кроме того, к оповещениям можно обратиться в соответствующей области информационной панели (кнопка “История” слева внизу формы приложения в варианте интерфейса «Версии 8.2»).

Чтобы создавать свои собственные оповещения, необходимо использовать метод глобального контекста ПоказатьОповещениеПользователя(). Его синтаксис до редакции 8.3.10 представлен ниже:

ПоказатьОповещениеПользователя (<Текст>, <НавигационнаяССылка>, <Пояснение>, <Картинка>)

В первом параметре передается текст, который будет выводиться в оповещении.

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

С помощью третьего параметра можно передать пояснение для сообщения, т.е. какое-то расширенное описание.

Также можно присвоить картинку, отображающую статус оповещения.

Следует отметить, что все эти параметры являются необязательными для заполнения. Ниже приведен пример использования данного метода (в конфигураторе и в пользовательском режиме в варианте интерфейса «Версии 8.2»).

Механизм оповещений
Механизм оповещений

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

ПоказатьОповещениеПользователя(<Текст>, <ДействиеПриНажатии>, <Пояснение>, <Картинка>, <СтатусОповещенияПользователя>, <КлючУникальности>)

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

Механизм оповещений

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

Следующий параметр СтатусОповещенияПользователя появился впервые. В нем указывается статус оповещения (Информация или Важное).

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

Механизм оповещений

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

Механизм оповещений

В панели инструментов появилась кнопка с пиктограммой звонка, по которой вызывается упомянутый выше Центр оповещений. В нем накапливаются новые важные оповещения, на которые пользователь пока никак не отреагировал.

Если в Центре есть какие-то оповещения, то рядом с ним появляется маленькая оранжевая точка, чтобы привлечь внимание пользователя. Пользователь может открыть Центр оповещений, прочитать текст и, если необходимо, выполнить какие-то действия.

Механизм оповещений

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

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

Как видим, возможностей, предоставляемых соответствующим методом, стало еще больше! Но это не все изменения в механизме оповещений.

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

Также к новым возможностям относится и одновременное отображение на экране до трех оповещений.

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

Давайте представим такую простую ситуацию: пользователь установил фильтр в каком-то списке для удобства. Допустим, он сделал это в форме списка справочника Номенклатуры. Потом, через какое-то время, решил ввести новый элемент с наименованием “Стул”, который не соответствует установленному ранее фильтру. Вводит его, записывает и…? И не видит его в списке. Что будет делать среднестатистический пользователь? Конечно, введет его второй раз, но опять не увидит. Дальше может последовать третий, четвертый, пятый раз. Когда ему надоест вводить одно и тоже, он, наконец, спросит у вас: а куда все пропадает?

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

Механизм оповещений

Терминирующие сообщения

Терминирующие сообщения – это те сообщения, которые не позволят работать, пока пользователь не произведет определенные действия, т.е. пока он не обработает сообщение.

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

Существуют два метода для выдачи терминирующих сообщений Предупреждение и Вопрос. Предупреждение отличается от Вопроса тем, что у него есть единственная кнопка ОК.

В вопросе могут определяться разные наборы вариантов ответов (ДаНет, ДаНетОтмена, ОК, ОКОтмена, ПовторитьОтмена, ПрерватьПовторитьПропустить), которые задаются с помощью параметра.

Выведем какое-нибудь предупреждение с помощью строки (например, в модуле управляемого приложения):

Предупреждение(“Сейчас будет открыта база”);

Чтобы открыть модуль управляемого приложения, следует в дереве конфигурации выбрать объект Конфигурация, вызвать контекстное меню и выбрать пункт Открыть модуль управляемого приложения.

Открытие модуля управляемого приложения

Механизм оповещений

Механизм оповещений нужен, чтобы информировать пользователя о том, что в системе “что-то” произошло и это “что-то” требует внимания пользователя. Оповещения создаются двумя сценариями:

  1. Самой платформой при интерактивной записи или изменении объекта
  2. Разработчиком при вызове в коде метода ПоказатьОповещениеПользователя().

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

Механизм оповещений

Кроме того, к оповещениям можно обратиться в соответствующей области информационной панели (кнопка “История” слева внизу формы приложения в варианте интерфейса «Версии 8.2»).

Чтобы создавать свои собственные оповещения, необходимо использовать метод глобального контекста ПоказатьОповещениеПользователя(). Его синтаксис до редакции 8.3.10 представлен ниже:

ПоказатьОповещениеПользователя (<Текст>, <НавигационнаяССылка>, <Пояснение>, <Картинка>)

В первом параметре передается текст, который будет выводиться в оповещении.

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

С помощью третьего параметра можно передать пояснение для сообщения, т.е. какое-то расширенное описание.

Также можно присвоить картинку, отображающую статус оповещения.

Следует отметить, что все эти параметры являются необязательными для заполнения. Ниже приведен пример использования данного метода (в конфигураторе и в пользовательском режиме в варианте интерфейса «Версии 8.2»).

Механизм оповещений
Механизм оповещений

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

ПоказатьОповещениеПользователя(<Текст>, <ДействиеПриНажатии>, <Пояснение>, <Картинка>, <СтатусОповещенияПользователя>, <КлючУникальности>)

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

Механизм оповещений

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

Следующий параметр СтатусОповещенияПользователя появился впервые. В нем указывается статус оповещения (Информация или Важное).

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

Механизм оповещений

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

Механизм оповещений

В панели инструментов появилась кнопка с пиктограммой звонка, по которой вызывается упомянутый выше Центр оповещений. В нем накапливаются новые важные оповещения, на которые пользователь пока никак не отреагировал.

Если в Центре есть какие-то оповещения, то рядом с ним появляется маленькая оранжевая точка, чтобы привлечь внимание пользователя. Пользователь может открыть Центр оповещений, прочитать текст и, если необходимо, выполнить какие-то действия.

Механизм оповещений

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

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

Как видим, возможностей, предоставляемых соответствующим методом, стало еще больше! Но это не все изменения в механизме оповещений.

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

Также к новым возможностям относится и одновременное отображение на экране до трех оповещений.

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

Давайте представим такую простую ситуацию: пользователь установил фильтр в каком-то списке для удобства. Допустим, он сделал это в форме списка справочника Номенклатуры. Потом, через какое-то время, решил ввести новый элемент с наименованием “Стул”, который не соответствует установленному ранее фильтру. Вводит его, записывает и…? И не видит его в списке. Что будет делать среднестатистический пользователь? Конечно, введет его второй раз, но опять не увидит. Дальше может последовать третий, четвертый, пятый раз. Когда ему надоест вводить одно и тоже, он, наконец, спросит у вас: а куда все пропадает?

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

Механизм оповещений

Терминирующие сообщения

Терминирующие сообщения – это те сообщения, которые не позволят работать, пока пользователь не произведет определенные действия, т.е. пока он не обработает сообщение.

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

Существуют два метода для выдачи терминирующих сообщений Предупреждение и Вопрос. Предупреждение отличается от Вопроса тем, что у него есть единственная кнопка ОК.

В вопросе могут определяться разные наборы вариантов ответов (ДаНет, ДаНетОтмена, ОК, ОКОтмена, ПовторитьОтмена, ПрерватьПовторитьПропустить), которые задаются с помощью параметра.

Выведем какое-нибудь предупреждение с помощью строки (например, в модуле управляемого приложения):

Предупреждение(“Сейчас будет открыта база”);

Чтобы открыть модуль управляемого приложения, следует в дереве конфигурации выбрать объект Конфигурация, вызвать контекстное меню и выбрать пункт Открыть модуль управляемого приложения.

Открытие модуля управляемого приложения

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

Модальное окно

Аналогичным образом работает и функция Вопрос.

Синтаксис:
Вопрос(<ТекстВопроса>,<Кнопки>,<Таймаут>,<КнопкаПоУмолчанию>,<Заголовок>,
<КнопкаТаймаута>);

Обязательными являются только первые два параметра. Для второго параметра тип данных составной (РежимДиалогаВопрос или СписокЗначений). Третий параметр (<Таймаут>) характеризует интервал времени в секундах, в течение которого система будет ожидать ответа пользователя.

По истечении интервала окно вопроса будет закрыто. Аналогичный параметр(<Таймаут>) есть и у функции Предупреждение.

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

Модуль управляемого приложения

Использование функции Вопрос

Использование функции Вопрос

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

Особенности использования модальных окон в Платформе 8.3

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

В этом случае использование терминирующих сообщений невозможно. В случае необходимости использования терминирующих сообщений (функции Предупреждение и Вопрос) следует изменить значение свойства конфигурации Режим использования модальности на Использовать.

Режим использования модальности

Модальное окно выводится на самый верх и блокирует работу с другими окнами до завершения действий с модальным окном. Кроме того, останавливается выполнение программного кода на том месте, где происходит вызов этого окна. Выполнение кода продолжится только после закрытия модального окна.

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

В настройках браузера по умолчанию всплывающие окна зачастую запрещены. Пользователя приходится заставлять устанавливать разрешение на эти окна.

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

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

Эти методы позволяют вызывать окно, но не останавливать выполнение программного кода. Технически это реализуется формированием псевдоокна внутри родительского окна. Псевдоокно не перекрывает родительское окно. После открытия такого окна код продолжает выполняться.

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

Синтаксис функции ПоказатьПредупреждение:

ПоказатьПредупреждение(<ОписаниеОповещенияОЗавершении>, <ТекстПредупреждения>, <Таймаут>, <Заголовок>)

Параметр <ОписаниеОповещенияОЗавершении> (необязательный)

Тип данных: ОписаниеОповещения.

Содержит описание процедуры, которая будет вызвана после закрытия окна предупреждения.

Синтаксис функции ПоказатьВопрос:

ПоказатьВопрос(<ОписаниеОповещенияОЗавершении>, <ТекстВопроса>, <Кнопки>, <Таймаут>, <КнопкаПоУмолчанию>, <Заголовок>, <КнопкаТаймаута>)

Обязательными являются первые три параметра.

Ниже приведен пример использования функции.

Процедура ОписаниеОповещения

Пример функции оповещения в 1С

Класс СообщениеПользователю

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

Сообщения могут быть привязаны к конкретному экранному элементу. Этот объект доступен и на Сервере.

Следует обратить внимание, что, во-первых, данный объект нужно создавать. Например: Сообщение = Новый СообщениеПользователю;

Таким образом мы создаем экземпляр данного объекта.

Во-вторых, нужно прописывать текст сообщения в отдельном свойстве.

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

Внимание! Для привязки к нужному полю формы обратите внимание на инициализацию свойств ПутьКДанным и КлючДанных. Применительно для документа при размещении кода в модуле объекта можно писать:

Сообщение.ПутьКДанным = “Объект”;
Сообщение.КлючДанных = ЭтотОбъект.Ссылка;

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

Для эксперимента в модуле объекта какого-либо документа разместим код.

Сообщение пользователю

Пример функции оповещения в 1С

Класс СообщениеПользователю

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

Сообщения могут быть привязаны к конкретному экранному элементу. Этот объект доступен и на Сервере.

Следует обратить внимание, что, во-первых, данный объект нужно создавать. Например: Сообщение = Новый СообщениеПользователю;

Таким образом мы создаем экземпляр данного объекта.

Во-вторых, нужно прописывать текст сообщения в отдельном свойстве.

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

Внимание! Для привязки к нужному полю формы обратите внимание на инициализацию свойств ПутьКДанным и КлючДанных. Применительно для документа при размещении кода в модуле объекта можно писать:

Сообщение.ПутьКДанным = “Объект”;
Сообщение.КлючДанных = ЭтотОбъект.Ссылка;

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

Для эксперимента в модуле объекта какого-либо документа разместим код.

Сообщение пользователю

Ниже представлен полученный в пользовательском режиме результат для Платформы 8.3.

Сообщение пользователю в пользовательском режиме 1С

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

Но, во-первых, данные сообщения достаточно заметны. Во-вторых, обычно сообщения пользователю выводятся в момент записи элементов справочников или проведения документов, т.е., когда выполняются какие-то проверки. И если были обнаружены ошибки, то пользователь увидит эти самые сообщения.

Соответственно, в момент обнаружения ошибок отменяется транзакция, т.е. запрещается запись элемента справочника, либо запрещается проведение документа.

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

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

Уведомление о состоянии процесса

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

Синтаксис: Состояние(<ТекстСообщения>, <Прогресс>, <Пояснение>, <Картинка>)
Параметры: <ТекстСообщения> и <Пояснение> – не обязательные, тип – Строка.
Текст выводится на специальную панель состояния.
<Прогресс> параметр тоже необязательный, но наглядный.
Тип: Число. Значение индикатора прогресса (от 1 до 100).
<Картинка> тоже необязательный параметр.
При обработке какого-либо события могут использоваться периодические вызовы функции типа:

Вызов функции

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

Но, во-первых, данные сообщения достаточно заметны. Во-вторых, обычно сообщения пользователю выводятся в момент записи элементов справочников или проведения документов, т.е., когда выполняются какие-то проверки. И если были обнаружены ошибки, то пользователь увидит эти самые сообщения.

Соответственно, в момент обнаружения ошибок отменяется транзакция, т.е. запрещается запись элемента справочника, либо запрещается проведение документа.

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

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

Уведомление о состоянии процесса

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

Синтаксис: Состояние(<ТекстСообщения>, <Прогресс>, <Пояснение>, <Картинка>)
Параметры: <ТекстСообщения> и <Пояснение> – не обязательные, тип – Строка.
Текст выводится на специальную панель состояния.
<Прогресс> параметр тоже необязательный, но наглядный.
Тип: Число. Значение индикатора прогресса (от 1 до 100).
<Картинка> тоже необязательный параметр.
При обработке какого-либо события могут использоваться периодические вызовы функции типа:

Вызов функции

При этом могут меняться надписи, а могут изменяться значения параметра Прогресс.

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

Состояние выполнения процесса

Если вы хотите ознакомиться с механизмом уведомления более подробно, то прямо сейчас прервитесь и прочтите нашу новую статью Отображение прогресса длительных операций в 8.3.10. В ней уже не на уровне новичка объясняются все тонкости и подводные камни работы этого механизма.

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

Хочется еще раз акцентировать ваше внимание на том факте, что если ваша конфигурация (версии 8.3.3+) предполагает работу с помощью веб-клиента, то:

  • на уровне конфигурации должна быть установлена настройка режима модальности «Не использовать»
  • в коде должны использоваться методы асинхронной модели взаимодействия с пользователем. Такие методы начинаются со слов Показать или Начать.

Более подробно об отказе от использования модальных окон в платформе 1С:Предприятие 8.3 можно почитать в финальной статье цикла. А мы идем дальше и, наконец, приступаем к изучению долгожданного интерфейса «Такси», который уже не раз упоминался в наших материалах.

Если вы хотите ознакомиться с механизмом уведомления более подробно, то прямо сейчас прервитесь и прочтите нашу новую статью Отображение прогресса длительных операций в 8.3.10. В ней уже не на уровне новичка объясняются все тонкости и подводные камни работы этого механизма.

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

Хочется еще раз акцентировать ваше внимание на том факте, что если ваша конфигурация (версии 8.3.3+) предполагает работу с помощью веб-клиента, то:

  • на уровне конфигурации должна быть установлена настройка режима модальности «Не использовать»
  • в коде должны использоваться методы асинхронной модели взаимодействия с пользователем. Такие методы начинаются со слов Показать или Начать.

Более подробно об отказе от использования модальных окон в платформе 1С:Предприятие 8.3 можно почитать в финальной статье цикла. А мы идем дальше и, наконец, приступаем к изучению долгожданного интерфейса «Такси», который уже не раз упоминался в наших материалах.

PDF-версия статьи для участников группы ВКонтакте

Мы ведем группу ВКонтакте – http://vk.com/kursypo1c.

Если Вы еще не вступили в группу – сделайте это сейчас и в блоке ниже (на этой странице) появятся ссылка на скачивание материалов.

Статья по программированию - в PDF-формате

Полезные ссылки:

Ссылка доступна для зарегистрированных пользователей)
Ссылка доступна для зарегистрированных пользователей)
Ссылка доступна для зарегистрированных пользователей)

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

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

Примеры вывода сообщений

Если обращение «с сервера», то для вывода сообщения пользователю можно применять следующую процедуру БСП:

ОбщегоНазначения.СообщитьПользователю(«Текст сообщения»);

Если обращение «с клиента», то для вывода сообщения пользователю можно применять следующую процедуру БСП:

ОбщегоНазначенияКлиент.СообщитьПользователю(«Текст сообщения»);

Устаревшая процедура, но которая еще используется в конфигурациях на предыдущих версиях БСП:

ОбщегоНазначенияКлиентСервер.СообщитьПользователю(«Текст сообщения»);

Пример вывода сообщения об ошибке:

Попытка
    ФайлCSV.Прочитать(ПутьКФайлу);
Исключение
    ОбщегоНазначенияКлиент.СообщитьПользователю(«Не удалось загрузить файл: « + ПутьКФайлу + Символы.ПС + ОписаниеОшибки());
КонецПопытки;

Общий синтаксис процедуры:

// Формирует и выводит сообщение, которое
может быть связано с элементом управления формы.
//
// Параметры:
// 
ТекстСообщенияПользователю — Строка — текст сообщения.
// 
КлючДанных — ЛюбаяСсылка — объект или ключ записи информационной базы, к
которому это сообщение относится.
// 
Поле — Строка — наименование реквизита формы.
// 
ПутьКДанным — Строка — путь к данным (путь к реквизиту формы).
// 
Отказ — Булево — выходной параметр, всегда устанавливается в значение
Истина.

Процедура СообщитьПользователю(
    Знач ТекстСообщенияПользователю,
    Знач КлючДанных = Неопределено,
    Знач Поле = «»,
    Знач ПутьКДанным = «»,
    Отказ = Ложь) Экспорт

Примеры:

// 1. Для вывода сообщения у поля
управляемой формы, связанного с реквизитом объекта:
ОбщегоНазначенияКлиент.СообщитьПользователю(НСтр(«ru = ‘Сообщение об ошибке.'»), , «ПолеВРеквизитеФормыОбъект», «Объект»);

// Альтернативный вариант использования в
форме объекта:
ОбщегоНазначенияКлиент.СообщитьПользователю(НСтр(«ru = ‘Сообщение об ошибке.'»), , «Объект.ПолеВРеквизитеФормыОбъект»);

// 2. Для вывода сообщения рядом с полем
управляемой формы, связанным с реквизитом формы:
ОбщегоНазначенияКлиент.СообщитьПользователю(НСтр(«ru = ‘Сообщение об ошибке.'»), , «ИмяРеквизитаФормы»);

// 3. Для вывода сообщения связанного с
объектом информационной базы:
ОбщегоНазначенияКлиент.СообщитьПользователю(НСтр(«ru = ‘Сообщение об ошибке.'»), ОбъектИнформационнойБазы, «Ответственный»,,Отказ);

// 4. Для вывода сообщения по ссылке на
объект информационной базы:
ОбщегоНазначенияКлиент.СообщитьПользователю(НСтр(«ru = ‘Сообщение об ошибке.'»), Ссылка, , , Отказ);

Случаи некорректного использования:

1. Передача одновременно параметров КлючДанных и ПутьКДанным.

2. Передача в параметре КлючДанных значения типа отличного от допустимого.

3. Установка ссылки без установки поля (и/или пути к данным).

Если Вам понравилась статья, пожалуйста, поставьте лайк, сделайте репост или оставьте комментарий. Если у Вас есть какие-либо замечания, также пишите комментарии.

В 1С предполагается, что СообщениеПользователю выводятся для того, чтобы сообщить пользователю об ошибках. 

А для информирования о выполняемом действии рекомендуется использовать метод встроенного языка ПоказатьОповещениеПользователя().


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

Пример вывода сообщения на клиенте:

Код 1C v 8.3

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

При обработке на сервере:

Необходимо зарегистрировать в системе соответствие объекта и имени реквизита формы. Для этого в глобальном контексте реализована функция УстановитьСоответствиеОбъектаИРеквизитаФормы(). Сделать это можно следующим образом:

Код 1C v 8.3

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

В данном фрагменте выполняется преобразование объекта из данных формы в реальный объект и устанавливается его соответствие с реквизитом формы по имени «Объект».

Если в дальнейшем требуется создать сообщение, можно сделать это следующим образом:

Код 1C v 8.3

  &НаСервере
Процедура ДействиеСОбъектом(ОбъектДанных)
    // Какие либо действия, которые требуют создания сообщения

    // Создание сообщения
    Сообщение = Новый СообщениеПользователю();
    Сообщение.Текст = "В строке 11 табличной части ""Номенклатура"" не хватает " + 
                      НедостающееКоличество + " " + ЕдиницаИзмеренияНоменклатуры;
    Сообщение.Поле = "Номенклатура[10].Количество";

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

    // Сообщение выводится пользователю
    Сообщение.Сообщить();
    // в дальнейшем сообщение будет показано в форме и привязано к
    // элементу управления связанного с полем Количество 
    // в 11-й строке табличной части Номенклатура.
КонецПроцедуры;

В этом фрагменте создается новый объект СообщениеПользователю, в котором запоминается Текст сообщения и указывается Поле объекта, ошибка в данных которого вызвала необходимость вывода сообщения. Информация о том, как объект расположен в форме берется из предварительно запомненной пары «Объект/ИмяРеквизитаФормы». В дальнейшем сообщение будет выведено в окно сообщений формы и привязано к соответствующему элементу управления.

Примеры заполнения свойства Поле объекта СообщениеПользователю

Реквизит ИмяРеквизита Контрагент
Табличная часть ИмяТабличнойЧасти Скидки
Реквизит табличной части ИмяТабличнойЧасти[ИндексСтроки].ИмяРеквизита Номенклатура[10].Количество
Реквизит набора записей [ИндексСтроки].ИмяРеквизита [10].Курс

ТипШаблонПример

Еще примеры:

Код 1C v 8.3

 &НаКлиенте
Процедура ДействиеСОбъектомНаКлиенте(ОбъектДанных)
     // Какие либо действия, которые требуют создания сообщения
    // Создание сообщения
    Сообщение = Новый СообщениеПользователю();
    Сообщение.Текст = "В строке 11 табличной части ""Номенклатура"" не хватает " + 
                      НедостающееКоличество + " " + ЕдиницаИзмеренияНоменклатуры;
    Сообщение.Поле = "Номенклатура[10].Количество";

    // Привязка объекта к реквизиту формы "вручную"
    Сообщение.КлючДанных = ОбъектДанных.Ссылка;
    Сообщение.ПутьКДанным = "Объект";

    // Сообщение выводится пользователю
    Сообщение.Сообщить();
КонецПроцедуры;

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

// Показываем сообщение из обработки
// КлючДанных и ПутьКДанным - пустые
   Сообщение = Новый СообщениеПользователю;
   Сообщение.Поле = "Комментарий";
   Сообщение.Текст = "Заполните комментарий";
   Сообщение.Сообщить();

// Показываем сообщение из документа
// КлючДанных - пустой, ПутьКДанным заполнится автоматически
    Сообщение = Новый СообщениеПользователю;
    Сообщение.Поле = "Товары[0].Количество";
    Сообщение.Текст = "Не заполнено количество товара в первой строке!";
    Сообщение.УстановитьДанные(ЭтотОбъект);
    Сообщение.Сообщить();

////////////////////  КОД для ТИПОВЫХ конфигураций, БСП:
//в модуле объекта
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(“Текст ошибки”,                
                        ЭтотОбъект,
                        "Договор",,
                        Отказ);
//в форме объекта
ОбщегоНазначенияКлиентСервер.СообщитьПользователю(НСтр("ru = 'Дублирование пременной'"), ,
"Запросы["+ИдентификаторСтроки+"].ИмяПеременнойЗапроса",//путь к данным
 "Объект", Отказ);   


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

Код 1C v 8.3

 ПоказатьОповещениеПользователя(НСтр("ru = 'Выполнение:'"), ПолучитьНавигационнуюСсылку(Объект), "Выгрузка завершена, все ОК!", БиблиотекаКартинок.ПолнотекстовыйПоискДалее);   

Код 1C v 8.3

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

&НаСервереБезКонтекста
Функция ПолучитьДатуЗапретаРедактирования()
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ
| Константы.ДатаЗапретаРедактирования
|ИЗ
| Константы КАК Константы";
РезультатЗапроса = Запрос.Выполнить();
Возврат РезультатЗапроса.Выгрузить()[0].ДатаЗапретаРедактирования;
КонецФункции  

Время на прочтение
32 мин

Количество просмотров 29K


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

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

В свое время, работая с системой контроля версий 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, а также интерфейс пользователя (форма для редактирования набора профилей подключений)

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

1c:база:оповещение_пользователя

Содержание

Механизмы оповещения пользователя

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

Операторы не останавливающие выполнение

Сообщить

Функция сообщить выводит текст сообщения в табло, снабжая его значком статуса. Синтаксис выглядит следующим образом:

Сообщить(«Текст сообщения», СтатусСообщения) 

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

НужнаяСсылка = Справочники.Сотрудники.НайтиПоНаименованию(«Петров»);
НавСсылка = ПолучитьНавигационнуюСсылку(НужнаяСсылка);
ПоказатьОповещениеПользователя(«Загловок», НавСсылка, «ТекстСсылка»);

СообщениеПользователю

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

Сообщение = Новый СообщениеПользователю;
Сообщение.Текст = "Контрагент должен быть указан";
Сообщение.Поле = "ПолеНаФорме";
Сообщение.Сообщить();

Операторы ожидающие реакции пользователя

Предупреждение

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

Предупреждение("какой то текст");

Вопрос

Команада Вопрос предназначена для получения какого то ответа от пользователя. Эта команда так же выводит модальное окно, но список кнопок можно определить самостоятельно. Для того, что бы это сделать нужно передать набор набор кнопок которые вы хотите видеть в диалоге вторым параметром. Это могут быть:

  1. Значения системного перечисления РежимДиалогаВопрос

    1. Да + Нет

    2. Да + Нет + Отмена

    3. ОК

    4. ОК + Отмена

    5. Повторить + Отмена

    6. Прервать + Повторить + Пропустить

  2. Список значений. В этом случае значение списка будет выступать идентификатором нажатой кнопки, а представление текстом кнопки в диалоге.

Синтаксис следующий:

Если Вопрос("Какой то вопрос", РежимДиалогаВопрос.ДаНет) = КодВозвратаДиалога.Да Тогда
	//Какие то действия
КонецЕсли;

Следует заметить, что методы Предупреждение и Вопрос подразумевают вывод диалоговых окон и как следствие недоступны на сервере.


Ссылки

Только авторизованные участники могут оставлять комментарии.

1c/база/оповещение_пользователя.txt

· Последнее изменение: 2014/10/12 07:11 —

admin

Понравилась статья? Поделить с друзьями:
  • Как сообщить об ошибке фортнайт
  • Как сообщить об ошибке своему системному администратору
  • Как сообщить об ошибке на яндекс маркет
  • Как сообщить об ошибке на сайте яндекс
  • Как сообщить об ошибке на сайте дзен