В практике разработчика 1С часто возникает задача передачи печатных форм во внешние системы: CRM-системы, почтовые сервисы или мобильные приложения. Самый универсальный способ сделать это — преобразовать ТабличныйДокумент в формат HTML. Однако просто сохранить файл на диск часто недостаточно, так как внешнему сервису требуется именно текстовое содержимое файла с сохранением всех HTML-тегов и стилей. В этой статье мы разберем, как правильно реализовать этот механизм, избегая типичных ошибок, и как оптимизировать процесс для работы на сервере.
Проанализируем базовый подход, который предложил автор темы. Он заключается в том, чтобы сохранить ТабличныйДокумент во временный файл, а затем прочитать его содержимое. Этот метод является наиболее стабильным и поддерживается практически всеми версиями платформы 1С:Предприятие 8.
Рассмотрим пошагово, как реализовать этот алгоритм. Сначала мы генерируем табличный документ, затем сохраняем его на диск, используя перечисление ТипФайлаТабличногоДокумента.HTML, и считываем текст обратно.
// Предположим, ТабДок уже сформирован
ИмяФайла = КаталогВременныхФайлов() + "Document.html";
ТабДок.Записать(ИмяФайла, ТипФайлаТабличногоДокумента.HTML);
// Читаем полученный файл в строку
ТекстHTML = "";
ЧтениеТекста = Новый ЧтениеТекста(ИмяФайла, КодировкаТекста.UTF8);
ТекстHTML = ЧтениеТекста.Прочитать();
ЧтениеТекста.Закрыть();
// Удаляем временный файл после использования
УдалитьФайлы(ИмяФайла);
В исходном сообщении автор использовал ПостроительDOM и ЗаписьDOM. Выясним причину, почему это избыточно: объект ЧтениеТекста при методе Прочитать() возвращает весь текст файла целиком, включая все теги <html>, <head>, <style> и <body>. Использование DOM-модели оправдано только в том случае, если вам нужно программно изменить структуру документа (например, добавить свои классы или атрибуты в таблицу).
Современные версии платформы (начиная с 8.3.9) позволяют работать с данными в оперативной памяти без обращения к файловой системе. Это значительно ускоряет работу, особенно если преобразование происходит в цикле при массовой рассылке документов. Для этого мы будем использовать ПотокВПамяти.
Разберем пример реализации через потоки:
// Создаем поток в памяти
Поток = Новый ПотокВПамяти();
// Записываем табличный документ непосредственно в поток
ТабДок.Записать(Поток, ТипФайлаТабличногоДокумента.HTML);
// Получаем двоичные данные из потока
ДвоичныеДанные = Поток.ЗакрытьИПолучитьДвоичныеДанные();
// Преобразуем двоичные данные в строку HTML
ТекстHTML = ПолучитьСтрокуИзДвоичныхДанных(ДвоичныеДанные, КодировкаТекста.UTF8);
Этот способ является наиболее предпочтительным для серверных вызовов, так как он не создает нагрузки на дисковую подсистему и не требует управления правами доступа к временным папкам.
При записи табличного документа важно выбрать правильный формат. Платформа 1С поддерживает несколько вариантов выгрузки. Посмотрим на основные различия:
Важный момент, который часто упускают разработчики: если в вашем ТабличныйДокумент есть картинки (логотипы компаний, факсимиле, печати), то при записи в HTML 1С создаст отдельную папку с этими изображениями. В итоговом HTML-тексте теги <img> будут ссылаться на локальные файлы, которые внешний сервис (например, почтовый клиент получателя) не сможет увидеть. Для формирования исходного макета с графическими элементами подойдёт пример внешней печатной формы с печатью и подписями на БСП.
Чтобы решить эту проблему, проанализируем ситуацию и применим технику Base64. Нам необходимо заменить пути к файлам на само содержимое картинок. Рассмотрим алгоритм действий:
ДвоичныеДанные и преобразуем в строку Base64 с помощью функции Base64Строка().src="путь_к_файлу" и заменяем его на src="data:image/png;base64,СтрокаBase64".Только после такой манипуляции HTML-документ станет по-настоящему автономным и готовым к передаче во внешние системы.
1С генерирует достаточно громоздкий HTML-код с большим количеством CSS-стилей в секции <style>. Если вам нужно передать не весь документ, а только саму таблицу данных, можно воспользоваться строковыми функциями для обрезки лишнего. Выясним, как оставить только содержимое тега <table>.
НачалоТаблицы = Найти(ТекстHTML, "<table");
КонецТаблицы = Найти(ТекстHTML, "</table>");
Если НачалоТаблицы > 0 И КонецТаблицы > 0 Тогда
ЧистыйHTMLТаблицы = Сред(ТекстHTML, НачалоТаблицы, КонецТаблицы - НачалоТаблицы + 8);
КонецЕсли;
Важно: При таком подходе вы потеряете стили (цвета шрифтов, границы ячеек), которые были описаны в секции <head>. Чтобы сохранить оформление, необходимо использовать более сложные инструменты, такие как XSL-трансформация или библиотеки для «инлайнинга» CSS (переноса стилей из заголовка непосредственно в атрибуты style каждого тега), что в рамках чистого 1С реализовать довольно трудоемко.
Если задача выполняется на клиенте (в тонком или толстом клиенте) и форма с документом открыта, можно воспользоваться свойством формы ПолеHTMLДокумента. Проанализируем этот вариант:
Элементы.ПолеHTML.Документ.documentElement.innerHTML.Этот метод дает самый точный результат «как видит пользователь», но он абсолютно неприменим для регламентных заданий или серверного кода, так как требует наличия графического интерфейса.
Мы рассмотрели несколько способов преобразования ТабличныйДокумент в HTML-строку. Для простых задач идеально подходит метод с ЧтениеТекста, а для высоконагруженных систем — работа с ПотокВПамяти. Не забывайте о нюансах с кодировкой (всегда используйте UTF-8) и о необходимости обработки вложенных изображений, если они присутствуют в вашей печатной форме.