Как вывести небольшую таблицу отчета в тело электронного письма из 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

При автоматизации бизнес-процессов часто возникает задача оперативного информирования пользователей или руководства. Отправлять полноценный отчет в формате Excel или PDF во вложении не всегда удобно, особенно если адресат читает почту со смартфона. Гораздо эффективнее вывести краткую выжимку или небольшую таблицу отчета непосредственно в тело электронного письма. В данной статье мы подробно разберем, как решить эту задачу в 1С, избежав искажения оформления в различных почтовых клиентах.

Базовый метод: Конвертация табличного документа в HTML

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

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


// 1. Создаем и заполняем табличный документ
ТабДок = Новый ТабличныйДокумент;
// Здесь код построения вашего отчета (например, вывод макета или СКД)
// ...

// 2. Записываем его во временный файл в формате HTML
ПутьКФайлу = ПолучитьИмяВременногоФайла("html");
ТабДок.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.HTML);

// 3. Читаем полученный HTML-код в текстовую строку
ТекстовыйДокумент = Новый ТекстовыйДокумент;
ТекстовыйДокумент.Прочитать(ПутьКФайлу, КодировкаТекста.UTF8);
ТекстПисьмаHTML = ТекстовыйДокумент.ПолучитьТекст();

// 4. Удаляем временный файл с диска
Попытка
    УдалитьФайлы(ПутьКФайлу);
Исключение
    // Запись лога об ошибке удаления файла при необходимости
КонецПопытки;

Этот метод прост в реализации, однако он имеет существенные недостатки, которые могут полностью испортить результат:

Современный подход: Использование потоков в памяти

Прежде чем перейти к исправлению верстки, давайте избавимся от создания временных файлов на диске. Начиная с версии платформы 1С 8.3, разработчикам доступен объект ПотокВПамяти. С его помощью мы можем получить HTML-код напрямую в оперативную память, что значительно повышает производительность и стабильность работы кода на сервере.

Рассмотрим, как реализовать этот алгоритм:


ТабДок = Новый ТабличныйДокумент;
// Код заполнения ТабДока
// ...

// Записываем табличный документ в поток памяти
Поток = Новый ПотокВПамяти();
ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.HTML);

// Извлекаем двоичные данные из потока и закрываем его
ДвоичныеДанныеHTML = Поток.ЗакрытьИПолучитьДвоичныеДанные();

// Преобразуем двоичные данные в строку с кодировкой UTF-8
ТекстHTML = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанныеHTML, КодировкаТекста.UTF8);

Этот способ работает гораздо быстрее, так как исключает накладные расходы на дисковые операции ввода-вывода (I/O) и полностью безопасен при работе в многопоточной серверной среде.

Решаем проблему со стилями: Ручное формирование HTML (Рекомендуется)

Чтобы таблица гарантированно отображалась во всех почтовых клиентах (включая мобильные приложения и веб-интерфейсы), все стили должны быть инлайновыми (Inline CSS). Это значит, что параметры оформления должны быть прописаны непосредственно внутри тегов <td> и <tr> с помощью атрибута style.

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


// Предположим, у нас есть ТаблицаЗначений с данными отчета
ТаблицаДанных = Новый ТаблицаЗначений;
ТаблицаДанных.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("Строка"));
ТаблицаДанных.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
ТаблицаДанных.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));

// Заполним тестовыми данными
НоваяСтрока = ТаблицаДанных.Добавить();
НоваяСтрока.Номенклатура = "Кирпич строительный красный";
НоваяСтрока.Количество = 1500;
НоваяСтрока.Сумма = 45000;

НоваяСтрока = ТаблицаДанных.Добавить();
НоваяСтрока.Номенклатура = "Цемент М500 (мешок 50кг)";
НоваяСтрока.Количество = 50;
НоваяСтрока.Сумма = 22500;

// Начинаем сборку HTML-кода
HTML_Код = "<html><body>";
HTML_Код = HTML_Код + "<p>Уважаемые коллеги, направляем вам сводный отчет по продажам:</p>";

// Инициализируем таблицу с инлайновыми стилями и явной границей для старых клиентов
HTML_Код = HTML_Код + "<table border=""1"" cellpadding=""5"" cellspacing=""0"" style=""border-collapse: collapse; width: 100%; max-width: 600px; font-family: Arial, sans-serif; font-size: 14px;"">";

// Формируем шапку таблицы
HTML_Код = HTML_Код + "<tr style=""background-color: #f2f2f2; font-weight: bold; text-align: left;"">";
HTML_Код = HTML_Код + "<th style=""border: 1px solid #cccccc; padding: 8px;"">Товар</th>";
HTML_Код = HTML_Код + "<th style=""border: 1px solid #cccccc; padding: 8px; text-align: right;"">Кол-во</th>";
HTML_Код = HTML_Код + "<th style=""border: 1px solid #cccccc; padding: 8px; text-align: right;"">Сумма, руб.</th>";
HTML_Код = HTML_Код + "</tr>";

// Заполняем строки данными
Для Каждого СтрокаДанных Из ТаблицаДанных Цикл
    HTML_Код = HTML_Код + "<tr>";
    HTML_Код = HTML_Код + "<td style=""border: 1px solid #cccccc; padding: 8px;"">" + СтрокаДанных.Номенклатура + "</td>";
    HTML_Код = HTML_Код + "<td style=""border: 1px solid #cccccc; padding: 8px; text-align: right;"">" + СтрокаДанных.Количество + "</td>";
    HTML_Код = HTML_Код + "<td style=""border: 1px solid #cccccc; padding: 8px; text-align: right;"">" + Формат(СтрокаДанных.Сумма, "ЧДЦ=2; ЧГ=3") + "</td>";
    HTML_Код = HTML_Код + "</tr>";
КонецЦикла;

HTML_Код = HTML_Код + "</table>";
HTML_Код = HTML_Код + "<p>Отчет сформирован автоматически из системы 1С.</p>";
HTML_Код = HTML_Код + "</body></html>";

Проанализируем ключевые особенности этой верстки:

  1. Использование свойства border-collapse: collapse; позволяет получить аккуратную тонкую одинарную рамку вместо стандартной двойной HTML-границы.
  2. Параметр max-width: 600px; гарантирует, что таблица будет отлично смотреться как на больших мониторах, так и на экранах смартфонов, сужаясь до ширины экрана без появления горизонтального скролла.
  3. Для каждого тега <td> и <th> стили рамки border: 1px solid #cccccc; продублированы явно. Почтовый клиент гарантированно отобразит эти границы.

Альтернатива: Программный разбор стилей через DOM

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

Мы можем сгенерировать стандартный HTML-код с помощью платформы 1С, загрузить полученную строку в объект ДокументHTML через ПостроительDOM, а затем программно перенести все стили из заголовка таблицы непосредственно в атрибуты style каждого узла ячейки. Этот процесс называется CSS-инлайнингом.

Ниже представлена концептуальная схема такого парсинга:


// Читаем сгенерированный платформой HTML в DOM-документ
ЧтениеHTML = Новый ЧтениеHTML;
ЧтениеHTML.УстановитьСтроку(ТекстHTML_Из_1С);
Построитель = Новый ПостроительDOM;
ДокументHTML = Построитель.Прочитать(ЧтениеHTML);

// Получаем все элементы ячеек "td"
Ячейки = ДокументHTML.ПолучитьЭлементыПоИмени("td");
Для Каждого Ячейка Из Ячейки Цикл
    // Программный анализ класса ячейки и замена его на инлайновый стиль
    // Здесь разработчик может сопоставить имя класса с таблицей стилей из тега <style>
    // и применить метод: Ячейка.УстановитьАтрибут("style", "border: 1px solid #ccc; ...");
КонецЦикла;

Как обрабатывать картинки и логотипы компании

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

Существует два надежных способа интеграции графики в письма:

Когда HTML-таблица не подходит

Если перед вами стоит задача отправить сложный финансовый или аналитический отчет, содержащий большое количество колонок, группировок, иерархических уровней или диаграмм, то попытка поместить его непосредственно в тело письма обречена на неудачу. Сложная верстка неизбежно «развалится» на смартфонах или в некоторых веб-клиентах.

В таких ситуациях рекомендуется использовать следующую архитектуру:

  1. Конвертируйте табличный документ в формат PDF с помощью конструкции: ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.PDF). Этот формат гарантирует абсолютную точность отображения шрифтов, цветов и разметки независимо от используемого устройства.
  2. В тело самого письма поместите микро-таблицу с ключевыми показателями (например, "Итого выручка", "Отклонение от плана %", "Топ-3 продаваемых товара"), сформированную простым HTML-кодом, как мы разобрали в Способе 3.
  3. Прикрепите сформированный PDF-файл к отправляемому сообщению ИнтернетПочтовоеСообщение во вложения.

Благодаря такому подходу, получатель сможет прямо из превью-экрана почты оценить ключевые цифры отчета, а при необходимости детального анализа — открыть вложенный файл PDF в исходном оформлении.

← На главную