Как отправить печатную форму с картинками в XLS через Outlook в 1С без искажений

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

При работе в системе 1С:Предприятие (особенно на платформе 8.1 и 8.2 при использовании обычных форм) программисты часто сталкиваются со следующей проблемой: подготовленная печатная форма, содержащая логотипы, факсимиле, штрихкоды или другие картинки, при сохранении в файл Excel стандартным методом ТабДок.Записать(ПутьФайла, ТипФайлаТабличногоДокумента.XLS) отображается некорректно. Картинки смещаются, накладываются на текст, растягиваются или вовсе исчезают. При последующей отправке такого файла в качестве вложения через почтовый клиент MS Outlook получатель видит сломанную верстку.

В этой статье мы подробно разберем причины такого поведения платформы 1С и рассмотрим несколько эффективных способов решения проблемы: от настройки свойств картинок в самом макете до конвертации файлов с помощью COM-объектов MS Excel.

Выясняем техническую причину искажений

Почему же стандартный механизм экспорта в формат XLS так сильно искажает графические элементы? Дело в архитектурных особенностях старого движка экспорта 1С. Когда выполняется метод сохранения табличного документа в формат XLS (Excel 97-2003), платформа пытается сопоставить экранные координаты картинок с координатной сеткой ячеек Excel. Если в вашей печатной форме присутствуют объединенные ячейки разной высоты и ширины, алгоритм пересчета координат сбивается. Картинка теряет жесткую привязку к своей позиции и «уплывает».

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

---

Решение 1. Тонкая настройка свойств картинки в макете 1С

Прежде чем приступать к написанию сложного кода конвертации, попробуем решить проблему «малой кровью», правильно настроив свойства самого объекта Рисунок в макете табличного документа.

Рассмотрим ключевые правила позиционирования графики в макете:

  1. Свойство «Размер картинки»: Рекомендуется программно или в свойствах макета установить для картинки режим отображения Растянуть (в коде это соответствует свойству РазмерКартинки.Растянуть). Практика показывает, что именно этот режим наиболее стабильно транслирует исходное разрешение картинки в Excel, не ломая ее пропорций. Режимы «Авторазмер» и «Пропорционально» часто приводят к непредсказуемым результатам при экспорте.
  2. Строгая привязка к сетке: Картинка не должна свободно позиционироваться на листе. Ее необходимо жестко привязать к конкретным ячейкам (области). Программно это реализуется с помощью метода Расположить().

Посмотрим на пример кода, который подготавливает картинку в печатной форме перед отправкой:


// Получаем область с картинкой из макета
ОбластьПодвал = Макет.ПолучитьОбласть("Подвал");
Рисунок = ОбластьПодвал.Рисунки.Найти("Логотип");

Если Рисунок <> Неопределено Тогда
    // Задаем режим вывода
    Рисунок.ВыводитьНаПечать = Истина;
    // Устанавливаем режим растягивания для сохранения качества
    Рисунок.РазмерКартинки = РазмерКартинки.Растянуть;
    
    // Альтернативно можно позиционировать рисунок по ячейкам области
    // Рисунок.Расположить(ОбластьПодвал.Область("R1C1:R5C4"));
КонецЕсли;

---

Решение 2. Конвертация HTML в XLS через COM-соединение Excel (Самый надежный способ)

Поскольку в бизнес-сценарии автора темы на компьютерах пользователей гарантированно установлен пакет MS Office (так как отправка писем идет через COM-объект Outlook.Application), мы можем использовать сам табличный процессор Microsoft Excel для сборки корректного файла.

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

Разберем по шагам реализацию этого алгоритма:


// 1. Формируем уникальные имена для временных файлов
ИмяВременногоКаталога = КаталогВременныхФайлов();
ВременныйФайлHTML = ИмяВременногоКаталога + "temp_act_" + Формат(ТекущаяДата(), "ДФ=yyyyMMddHHmmss") + ".html";
ИтоговыйФайлXLS = ИмяВременногоКаталога + "Акт_Сверки.xls";

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

// 3. Конвертируем HTML в XLS с помощью MS Excel через COM
Попытка
    ExcelПриложение = Новый COMОбъект("Excel.Application");
    ExcelПриложение.DisplayAlerts = Ложь; // Отключаем диалоговые окна
    
    // Открываем сохраненный HTML-файл
    Книга = ExcelПриложение.Workbooks.Open(ВременныйФайлHTML);
    
    // Сохраняем книгу в формате Excel 97-2003 (код формата 56)
    // Параметр 56 соответствует константе xlExcel8
    Книга.SaveAs(ИтоговыйФайлXLS, 56);
    
    // Закрываем книгу и приложение
    Книга.Close(Ложь);
    ExcelПриложение.Quit();
    
    Сообщить("Конвертация файла успешно завершена.");
Исключение
    Сообщить("Ошибка при работе с Excel: " + ОписаниеОшибки());
    // В случае сбоя попытаемся высвободить COM-объект
    Если ExcelПриложение <> Неопределено Тогда
        ExcelПриложение.Quit();
    КонецЕсли;
КонецПопытки;

Теперь полученный файл по пути ИтоговыйФайлXLS содержит в себе идеально сверстанную таблицу с картинками. Мы можем прикрепить его к письму Outlook и отправить адресату.

---

Решение 3. Быстрый обходной путь с подменой расширения (HTML под видом XLS)

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

Мы можем записать табличный документ в формате HTML, но принудительно задать файлу расширение .xls. Современные версии Microsoft Excel при открытии такого файла автоматически распознают HTML-разметку и корректно отобразят документ вместе со всеми встроенными картинками.

Посмотрим на пример реализации данного трюка:


// Назначаем файлу расширение XLS, но записываем его как HTML
ФайлВложения = КаталогВременныхФайлов() + "акт.xls";
ТабДок.Записать(ФайлВложения, ТипФайлаТабличногоДокумента.HTML);

// Теперь этот файл можно прикреплять к письму Outlook.
// Единственный нюанс: при открытии файла Excel может выдать предупреждение 
// о несоответствии расширения файла его реальному формату. 
// Пользователю достаточно нажать "Да", чтобы открыть документ.

---

Решение 4. Отправка картинок внутри тела письма (HTML + CID)

Иногда задача стоит иначе: необходимо вывести картинку не во вложенном файле XLS, а непосредственно в теле отправляемого электронного письма (например, логотип компании в подписи или графический отчет). Для этого используется механизм связывания картинок через идентификаторы CID (Content-ID).

Проанализируем пример кода, выполняющий такую отправку с использованием встроенного почтового клиента 1С:


// Создаем объект Интернет-почты и сообщение
ПочтовоеСообщение = Новый ИнтернетПочтовоеСообщение;
ПочтовоеСообщение.Тема = "Акт сверки взаиморасчетов";
ПочтовоеСообщение.Получатели.Добавить("client@email.com");

// Формируем уникальный идентификатор для картинки
УникальныйИдентификаторКартинки = Новый УникальныйИдентификатор;
ИдентификаторКартинкиСтрокой = Строка(УникальныйИдентификаторКартинки);

// Получаем картинку из макета (двоичные данные)
КартинкаЛоготип = ПолучитьМакет("ЛоготипИзображение"); // Двоичный макет с картинкой PNG/JPG

// Добавляем картинку во вложения письма и связываем через Идентификатор
Вложение = ПочтовоеСообщение.Вложения.Добавить(КартинкаЛоготип, "logo.png");
Вложение.Идентификатор = ИдентификаторКартинкиСтрокой;

// Формируем HTML-текст письма, ссылаясь на картинку через "cid:"
ТекстHTML = "<html>" +
            "<body>" +
            "<h3>Добрый день!</h3>" +
            "<p>Высылаем вам акт сверки.</p>" +
            "<p><img src=""cid:" + ИдентификаторКартинкиСтрокой + """ alt=""Логотип фирмы""></p>" +
            "<p>С уважением, Администрация.</p>" +
            "</body>" +
            "</html>";

ПочтовоеСообщение.Тексты.Добавить(ТекстHTML, ТипТекстаПочтовогоСообщения.HTML);

// Отправка через ИнтернетПочту...
// ИнтернетПочта = Новый ИнтернетПочта;
// ИнтернетПочта.Подключиться(Профиль);
// ИнтернетПочта.Послать(ПочтовоеСообщение);

---

Собираем все вместе: Формирование вложения и отправка через Outlook

Теперь объединим полученные знания и напишем готовый блок кода для формирования печатной формы, конвертации ее через Excel COM и отправки готового вложения через почтовый клиент MS Outlook:


// 1. Формируем печатную форму (ТабличныйДокумент)
ТабДок = СформироватьПечатнуюФормуАкта(); // Ваша функция генерации документа

// 2. Определяем пути к файлам
ВременнаяПапка = КаталогВременныхФайлов();
ФайлHTML = ВременнаяПапка + "temp_print_form.html";
ФайлXLS = ВременнаяПапка + "Акт_Заказа_" + СокрЛП(ЭтотОбъект.НомерЗаказа) + ".xls";

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

// 3. Конвертируем в честный XLS через Excel Application
Попытка
    ExcelApp = Новый COMОбъект("Excel.Application");
    ExcelApp.DisplayAlerts = Ложь;
    КнигаExcel = ExcelApp.Workbooks.Open(ФайлHTML);
    КнигаExcel.SaveAs(ФайлXLS, 56); // Формат Excel 97-2003
    КнигаExcel.Close(Ложь);
    ExcelApp.Quit();
Исключение
    Сообщить("Не удалось выполнить точную конвертацию в XLS. Отправляем исходную копию.", СтатусСообщения.Внимание);
    // В случае сбоя используем более простой механизм записи (или переименования)
    ТабДок.Записать(ФайлXLS, ТипФайлаТабличногоДокумента.XLS);
КонецПопытки;

// 4. Инициализируем Outlook и отправляем письмо
Попытка
    Outlook = Новый COMОбъект("Outlook.Application");
    Письмо = Outlook.CreateItem(0); // 0 = mailItem
    
    Письмо.Subject = "Акт заказа № " + ЭтотОбъект.НомерЗаказа + " от " + Формат(ЭтотОбъект.Дата, "ДФ=dd.MM.yyyy");
    
    // Заполняем получателей
    Для Каждого СтрокаАдреса Из ТаблицаПолучателей Цикл
        Если СтрокаАдреса.Использовать Тогда
            Письмо.Recipients.Add(СтрокаАдреса.Email);
        КонецЕсли;
    КонецЦикла;
    
    // Прикрепляем сконвертированный XLS-файл с красивыми картинками
    Письмо.Attachments.Add(ФайлXLS);
    
    // Текст письма
    Письмо.Body = "Здравствуйте! Во вложении к письму находится сформированный акт заказа.";
    
    // Выводим окно письма пользователю на экран для проверки перед отправкой
    Письмо.Display();
    
    // Или отправляем сразу программно
    // Письмо.Send();
    
Исключение
    Сообщить("Произошла ошибка при интеграции с Outlook: " + ОписаниеОшибки(), СтатусСообщения.Важное);
КонецПопытки;

// 5. Очищаем временные файлы
Попытка
    УдалитьФайлы(ФайлHTML);
    // Файл XLS удалять сразу нельзя, если используется метод Display(), 
    // так как Outlook должен успеть прочитать его с диска. 
    // Удаление лучше производить при закрытии формы или в фоновом режиме.
Исключение
    // Игнорируем ошибки удаления временных файлов
КонецПопытки;

Применение любого из описанных выше методов позволит вам избавиться от проблем искажения верстки графических объектов в файлах Excel при экспорте из системы 1С:Предприятие.

← На главную