При разработке алгоритмов оповещения пользователей при начале работы программы разработчики часто сталкиваются с ситуацией, когда процедура отрабатывает без явных синтаксических ошибок, однако метод Сообщить() ничего не выводит на экран, а результирующий массив данных оказывается пустым. Разберем по шагам, почему возникает эта проблема, как быстро локализовать ошибку с помощью встроенных инструментов отладки платформы 1С:Предприятие 8.3 и как правильно переписать алгоритм с точки зрения производительности и стандартов разработки.
Рассмотрим типовой пример, когда при запуске приложения в модуле управляемого приложения вызывается экспортная функция общего модуля для формирования списка именинников:
// В общем модуле:
Функция ПолучитьСписокИменинников() Экспорт
ТДДень = День(ТекущаяДата());
ТДМесяц = Месяц(ТекущаяДата());
Массив = Новый Массив;
Выборка = Справочники.Сотрудники.Выбрать();
Пока Выборка.Следующий() Цикл
ДРДень = День(Выборка.ДатаРождения);
ДРМесяц = Месяц(Выборка.ДатаРождения);
Если ДРМесяц = ТДМесяц И ДРДень = ТДМесяц Тогда
Массив.Добавить(Выборка.Наименование);
КонецЕсли;
КонецЦикла;
Возврат Массив;
КонецФункции
// В модуле управляемого приложения:
Процедура ПриНачалеРаботыСистемы()
СписокИменинников = ОбщиеМеханизмы.ПолучитьСписокИменинников();
Для Каждого ЭлементМассива Из СписокИменинников Цикл
Сообщить("Сегодня ДР у " + ЭлементМассива);
КонецЦикла;
КонецПроцедуры
Проанализируем приведенный код. На первый взгляд кажется, что перебор элементов справочника Справочники.Сотрудники происходит штатно. Однако в результирующий массив ничего не попадает, цикл обхода массива в процедуре ПриНачалеРаботыСистемы не выполняется ни разу, и вызов Сообщить() не происходит.
Причина кроется в банальной опечатке в блоке проверки условия:
Если ДРМесяц = ТДМесяц И ДРДень = ТДМесяц Тогда
Вместо сравнения переменной ДРДень с переменной ТДДень выполняется сравнение с переменной ТДМесяц. Таким образом, условие станет истинным только в том редком случае, когда номер текущего дня месяца совпадает с номером текущего месяца (например, 5 мая или 12 декабря). Во все остальные дни условие всегда возвращает Ложь, строка добавления в массив не выполняется, и на клиент возвращается пустая коллекция.
Исправленный вариант условия должен выглядеть следующим образом:
Если ДРМесяц = ТДМесяц И ДРДень = ТДДень Тогда
Массив.Добавить(Выборка.Наименование);
КонецЕсли;
Чтобы избежать долгих поисков причин пустого результата, разберем по шагам порядок действий при отладке подобных участков кода:
Если, а также внутри самого блока условия на строке Массив.Добавить(...). Если точка останова внутри блока условия не срабатывает ни для одной записи — проверяем логику самого выражения.ДРДень, ДРМесяц, ТДДень и ТДМесяц.Использование метода Справочники.Сотрудники.Выбрать() в реальных конфигурациях крайне не рекомендуется, так как объектная выборка последовательно считывает все записи таблицы из базы данных в память сервера, включая группы справочника и помеченные на удаление элементы. На больших базах это приводит к значительным задержкам при старте системы.
Перепишем функцию с использованием языка запросов 1С и функции ТекущаяДатаСеанса() для корректного учета часового пояса пользователя:
Функция ПолучитьСписокИменинников() Экспорт
ТекущаяДата = ТекущаяДатаСеанса();
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Сотрудники.Наименование КАК Сотрудник
|ИЗ
| Справочник.Сотрудники КАК Сотрудники
|ГДЕ
| НЕ Сотрудники.ПометкаУдаления
| И НЕ Сотрудники.ЭтоГруппа
| И ДЕНЬ(Сотрудники.ДатаРождения) = &День
| И МЕСЯЦ(Сотрудники.ДатаРождения) = &Месяц";
Запрос.УстановитьПараметр("День", День(ТекущаяДата));
Запрос.УстановитьПараметр("Месяц", Месяц(ТекущаяДата));
РезультатЗапроса = Запрос.Выполнить();
Выборка = РезультатЗапроса.Выбрать();
Массив = Новый Массив;
Пока Выборка.Следующий() Цикл
Массив.Добавить(Выборка.Сотрудник);
КонецЦикла;
Возврат Массив;
КонецФункции
При реализации оповещений в управляемом интерфейсе важно помнить о нескольких ключевых правилах:
ПриНачалеРаботыСистемы выполняется исключительно в контексте НаКлиенте. Для того чтобы функция чтения данных из базы была доступна для вызова, в свойствах общего модуля ОбщиеМеханизмы должны быть установлены флаги «Сервер» и «Вызов сервера».Сообщить() выводит текст в системное окно сообщений, которое пользователь может не заметить при открытии начальной страницы. Для вывода всплывающих уведомлений в управляемом интерфейсе эффективнее применять метод ПоказатьОповещениеПользователя():
Процедура ПриНачалеРаботыСистемы()
СписокИменинников = ОбщиеМеханизмы.ПолучитьСписокИменинников();
Для Каждого Сотрудник Из СписокИменинников Цикл
ПоказатьОповещениеПользователя(
"День рождения!",
,
"Сегодня празднует день рождения: " + Сотрудник,
БиблиотекаКартинок.Информация
);
КонецЦикла;
КонецПроцедуры
Использование запросов, строгий контроль переменных в условиях и переход на современные методы оповещения обеспечивают стабильную и быструю работу пользовательского интерфейса при запуске конфигурации.