Как отправить руководителю единое письмо со списком отпусков всех сотрудников подразделения?

Программист 1С v8.3 (Обычные формы) Управленческий учет
← На главную

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

Анализ исходной проблемы: почему приходят отдельные письма?

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

Вторая критическая ошибка находится внутри самой процедуры формирования текста. Посмотрим на этот фрагмент:


Для Каждого Строка ИЗ мОтобранныеСтроки Цикл;
    ТелоТекста = Строка.Сотрудник + " - запланирован отпуск с " + ...
КонецЦикла;

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

Решение №1: Накопление текста и правильная группировка

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


ТелоТекста = ""; 
Для Каждого Строка ИЗ мОтобранныеСтроки Цикл
    // Накапливаем строки, добавляя перевод строки в конце каждой записи
    ТелоТекста = ТелоТекста + Строка.Сотрудник + " - запланирован отпуск с " 
               + Формат(Строка.ДатаНачала, "ДФ=dd.MM.yyyy") + " по " 
               + Формат(Строка.ДатаОкончания, "ДФ=dd.MM.yyyy") + Символы.ВК;
КонецЦикла;

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

  1. Создадим копию таблицы ТЗ1 и свернем ее по колонке ТекущееПодразделение, чтобы получить список уникальных отделов.
  2. Запустим цикл по этой свернутой таблице.
  3. Внутри цикла сделаем отбор строк из основной таблицы по конкретному подразделению.
  4. Передадим отобранные строки в процедуру отправки письма.

Решение №2: Использование HTML-разметки для создания таблиц

Текстовые письма выглядят сухо и трудночитаемы при большом количестве данных. Гораздо профессиональнее формировать тело письма в формате HTML. Это позволит нам создать красивую таблицу с границами и заголовками. Разберем по шагам, как сформировать такой текст.

Сначала подготовим "шапку" письма и начало таблицы:


ТекстПисьма = "<html><body>";
ТекстПисьма = ТекстПисьма + "<p>Здравствуйте! Скоро начинается отпуск у сотрудников вашего подразделения:</p>";
ТекстПисьма = ТекстПисьма + "<table border='1' cellpadding='5' style='border-collapse: collapse;'>";
ТекстПисьма = ТекстПисьма + "<tr bgcolor='#f2f2f2'><th>ФИО</th><th>Дата начала</th><th>Дата окончания</th></tr>";

Затем пройдемся циклом по строкам и добавим данные в ячейки таблицы <td>:


Для каждого Строка Из мОтобранныеСтроки Цикл
    ТекстПисьма = ТекстПисьма + "<tr>";
    ТекстПисьма = ТекстПисьма + "<td>" + Строка.Сотрудник + "</td>";
    ТекстПисьма = ТекстПисьма + "<td align='center'>" + Формат(Строка.ДатаНачала, "ДФ=dd.MM.yyyy") + "</td>";
    ТекстПисьма = ТекстПисьма + "<td align='center'>" + Формат(Строка.ДатаОкончания, "ДФ=dd.MM.yyyy") + "</td>";
    ТекстПисьма = ТекстПисьма + "</tr>";
КонецЦикла;

В завершение закроем теги таблицы и документа, после чего установим тип текста письма:


ТекстПисьма = ТекстПисьма + "</table>";
ТекстПисьма = ТекстПисьма + "<p>Просим проконтролировать передачу заявлений.</p></body></html>";

// При отправке обязательно указываем тип текста
ПараметрыПисьма.Вставить("Тело", ТекстПисьма);
ПараметрыПисьма.Вставить("ТипТекста", ТипТекстаПочтовогоСообщения.HTML);

Оптимизация производительности: Индексы и сворачивание

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

ТЗ2.Индексы.Добавить("ТекущееПодразделение");

Это значительно ускорит выполнение метода НайтиСтроки(). Также, вместо создания структуры отбора на каждой итерации, эффективнее использовать один объект структуры, просто меняя в нем значение свойства.

Рекомендации по автоматизации

Для того чтобы сделать механизм рассылки надежным, стоит рассмотреть следующие дополнения:

  1. Регламентные задания: Не запускайте рассылку вручную. Используйте объект РегламентныеЗадания, чтобы система сама проверяла график отпусков, например, каждый понедельник в 9:00.
  2. Библиотека стандартных подсистем (БСП): Если вы работаете в современной конфигурации, используйте общий модуль РаботаСПочтовымиСообщениями. Это позволит избежать низкоуровневой настройки ИнтернетПочтовыйПрофиль и обеспечит ведение журнала отправок.
  3. Обработка ошибок: Оберните вызов процедуры отправки в блок Попытка...Исключение. Это гарантирует, что если у одного руководителя указан неверный e-mail, рассылка не прервется и остальные адресаты получат свои уведомления.

Таким образом, мы проанализировали основные ошибки при формировании рассылок и разобрали два способа решения задачи: от простого накопления текста до создания полноценных HTML-отчетов. Использование таблиц делает информацию наглядной, а правильная группировка данных снижает нагрузку на почтовые серверы и не раздражает руководителей лишними письмами.

← На главную