При автоматизации бизнес-процессов часто возникает задача формирования красивых исходящих писем. Если у компании уже есть готовые шаблоны в формате Microsoft Word (с таблицами, логотипами и сложным форматированием), встает вопрос: как перенести это содержимое в тело письма Outlook, не потеряв внешний вид. В этой статье мы подробно разберем несколько проверенных методов решения этой задачи, проанализируем их плюсы и минусы, а также выясним, как избежать типичных ошибок при работе с COM-объектами Microsoft Office.
Этот способ является самым быстрым в реализации и наиболее близким к действиям пользователя. Мы программно заставляем Word выделить всё содержимое документа, скопировать его в буфер обмена Windows, а затем вставить в открытое письмо Outlook. Рассмотрим этот алгоритм по шагам.
Для начала нам необходимо создать COM-объекты приложений:
// Создаем объекты Word и Outlook
Попытка
Ворд = Новый COMОбъект("Word.Application");
Аутлук = Новый COMОбъект("Outlook.Application");
Исключение
Сообщить("Ошибка при запуске MS Office: " + ОписаниеОшибки());
Возврат;
КонецПопытки;
// Открываем файл шаблона
Документ = Ворд.Documents.Open(ПутьКФайлуШаблона);
Ворд.Visible = Ложь; // Работаем в фоновом режиме
// Выделяем весь текст и копируем в буфер
Ворд.Selection.WholeStory();
Ворд.Selection.Copy();
// Создаем новое письмо
Письмо = Аутлук.CreateItem(0); // 0 - это константа olMailItem
Письмо.Display(); // Обязательно отображаем письмо перед вставкой
// Получаем объект инспектора и редактора (Outlook использует Word как редактор)
Инспектор = Письмо.GetInspector;
ДокументПисьма = Инспектор.WordEditor;
// Вставляем содержимое из буфера
ДокументПисьма.Range().Paste();
// Закрываем ворд без сохранения изменений
Документ.Close(0); // 0 - wdDoNotSaveChanges
Ворд.Quit();
Важный нюанс: Использование метода Selection.Copy() и Paste() задействует буфер обмена пользователя. Если в момент выполнения кода пользователь сам что-то копирует, данные могут перемешаться. Однако для разовых операций это самое простое решение, сохраняющее 100% форматирования.
Если нам нужно отправить письмо в фоновом режиме без открытия окна Outlook (метод .Send() вместо .Display()), лучше всего использовать свойство HTMLBody. Для этого мы заставим Word сохранить документ как временный HTML-файл, прочитаем его код и передадим в Outlook. Проанализируем этот подход.
Разберем программную реализацию сохранения в HTML:
// Путь для временного файла
ПутьHTML = ПолучитьИмяВременногоФайла("html");
// Сохраняем документ Word как HTML
// Константа 8 соответствует wdFormatHTML, 10 - wdFormatFilteredHTML (более чистый код)
Документ.SaveAs2(ПутьHTML, 10);
Документ.Close();
Ворд.Quit();
// Читаем полученный файл
ТекстHTML = "";
ЧтениеТекста = Новый ЧтениеТекста(ПутьHTML, КодировкаТекста.UTF8);
ТекстHTML = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
// Создаем письмо и подставляем HTML
Письмо = Аутлук.CreateItem(0);
Письмо.HTMLBody = ТекстHTML;
Письмо.Subject = "Тема вашего сообщения";
Письмо.Display();
При использовании этого метода следует помнить, что картинки из документа Word при сохранении в HTML могут выноситься в отдельную папку. Чтобы они корректно отобразились у получателя, их нужно будет прикреплять к письму как вложения и ссылаться на них через Content-ID (cid).
Рассмотрим более профессиональный способ, который не требует использования буфера обмена. Объект письма Outlook MailItem имеет свойство GetInspector.WordEditor. Это, по сути, полноценный документ Word, который является телом письма. Мы можем работать с ним так же, как с обычным файлом .docx.
Выясним, как передать данные напрямую между двумя объектами Word:
Письмо = Аутлук.CreateItem(0);
Письмо.Display();
// Получаем доступ к "телу-документу" письма
ДокументПисьма = Письмо.GetInspector.WordEditor;
// Открываем наш файл-шаблон
Шаблон = Ворд.Documents.Open(ПутьКФайлуШаблона);
// Копируем содержимое Range шаблона в Range письма
// В отличие от Paste, это работает более стабильно в многопоточной среде
Шаблон.Content.Copy();
ДокументПисьма.Content.Paste();
Шаблон.Close(0);
Для продвинутых задач, когда необходимо сформировать письмо полностью программно без привязки к запущенному экземпляру Outlook, можно собрать файл формата .eml. Это текстовый формат, описывающий структуру письма. После создания файла достаточно вызвать команду ЗапуститьПриложение(), и система откроет его в почтовом клиенте по умолчанию.
ИмяФайла = ПолучитьИмяВременногоФайла("eml");
ЗаписьТекста = Новый ЗаписьТекста(ИмяФайла, КодировкаТекста.ANSI);
// Формируем заголовки MIME
ЗаписьТекста.ЗаписатьСтроку("Subject: Тема письма");
ЗаписьТекста.ЗаписатьСтроку("Content-Type: text/html; charset=UTF-8");
ЗаписьТекста.ЗаписатьСтроку(""); // Пустая строка отделяет заголовки от тела
ЗаписьТекста.ЗаписатьСтроку("<html><body>" + ТелоПисьмаВФорматеHTML + "</body></html>");
ЗаписьТекста.Закрыть();
ЗапуститьПриложение(ИмяФайла);
В ходе обсуждения часто возникают вопросы о том, почему письма не сохраняются в папке "Отправленные" или как добавить вложения. Рассмотрим эти моменты подробнее.
Письмо.Send(), письмо уходит автоматически. Если оно при этом не сохраняется в папке "Отправленные", проверьте настройки Outlook или принудительно вызовите Письмо.Save() перед отправкой. Также можно использовать свойство Письмо.DeleteAfterSubmit = Ложь;.Attachments. Проанализируем пример кода:
Письмо.Attachments.Add("C:\Docs\File.pdf");
ФорматированныйДокумент. Он позволяет создавать текст с выделением, цветами и картинками, а затем экспортировать его в HTML методом ПолучитьHTML(), который идеально вставляется в HTMLBody письма.Подведем итог: Самым надежным и качественным способом переноса оформления из Word в Outlook является работа через WordEditor или предварительная конвертация в HTML. Выбор метода зависит от того, должен ли пользователь видеть и редактировать письмо перед отправкой или процесс должен быть полностью скрытым.