В процессе разработки конфигураций на платформе 1С:Предприятие 8.3 программистам часто приходится работать с хранением форматированного текста, содержащего стили, списки и внедренные изображения. Для этого используется специальный объект ФорматированныйДокумент. Однако при необходимости выгрузки такого содержимого на печать разработчики сталкиваются со сложностями: прямой вывод объекта ФорматированныйДокумент в печатную форму или ТабличныйДокумент платформой штатно не предусмотрен.
Разберем подробно, какие существуют варианты вывода форматированного документа на печать, проанализируем возможные ошибки при работе с изображениями и рассмотрим готовые примеры программного кода на встроенном языке 1С.
Проанализируем сначала устройство самого объекта. ФорматированныйДокумент предназначен для работы с текстом, содержащим шрифтовое и абзацное форматирование, а также вложенные картинки. Чаще всего он хранится в базе данных внутри реквизитов с типом ХранилищеЗначения.
При извлечении данных из реквизита мы получаем объект, состоящий из элементов различных типов: текстовых блоков (ТекстФорматированногоДокумента) и графических объектов (КартинкаФорматированногоДокумента). Основная проблема вывода заключается в том, что печатный макет 1С строится на базе объекта ТабличныйДокумент, который требует явного заполнения ячеек или добавления графических рисунков.
Рассмотрим первый метод вывода — прямой обход структуры документа с последовательным заполнением печатной формы. Этот вариант подходит, если требуется выводить текст и картинки в стандартный табличный документ 1С.
Выясним алгоритм действий:
ФорматированныйДокумент из хранилища значений.ПолучитьЭлементы().Посмотрим на пример реализации данного алгоритма:
ФорматированныйДокумент = Выборка.Содержание.Получить();
ЭлементыФорматированногоДокумента = ФорматированныйДокумент.ПолучитьЭлементы();
Для Каждого Элемент ИЗ ЭлементыФорматированногоДокумента Цикл
Если ТипЗнч(Элемент) = Тип("ТекстФорматированногоДокумента") Тогда
ОбластьТекст.Параметры.Содержание = Элемент.Текст;
ТабДок.Вывести(ОбластьТекст);
Иначе
// Создаем рисунок в области табличного документа
КартинкаПечать = ОбластьКартинка.Рисунки.Добавить(ТипРисункаТабличногоДокумента.Картинка);
КартинкаПечать.Картинка = Элемент.Картинка;
// Настраиваем позиционирование и размеры
КартинкаПечать.Верх = 0;
КартинкаПечать.Лево = 0;
КартинкаПечать.Высота = Элемент.Высота / 4;
КартинкаПечать.Ширина = Элемент.Ширина / 4;
// Отключаем отображение границ рисунка
КартинкаПечать.ГраницаСверху = Ложь;
КартинкаПечать.ГраницаСлева = Ложь;
КартинкаПечать.ГраницаСправа = Ложь;
КартинкаПечать.ГраницаСнизу = Ложь;
КартинкаПечать.РазмерКартинки = РазмерКартинки.АвтоРазмер;
ТабДок.Вывести(ОбластьКартинка);
КонецЕсли;
КонецЦикла;
Обратите внимание на деление размеров Элемент.Высота и Элемент.Ширина на коэффициент. Это необходимый шаг, так как единицы измерения размеров в форматированном документе (пиксели) и в рисунках табличного документа (миллиметры) отличаются. Подбором коэффициента можно добиться корректного пропорционального отображения.
В процессе работы с форматированными документами разработчики часто сталкиваются с ошибкой при попытке присвоения КартинкаПечать.Картинка = Элемент.Картинка. Ошибка возникаем в случаях, когда свойство Элемент.Картинка возвращает не объект Картинка, а текстовую строку Data URL, начинающуюся с префикса data:image/png;base64,....
Разберем, как правильно преобразовать данную строку в объект Картинка для корректной передачи в печатную форму. Нам потребуется отсечь служебный заголовок Data URL, декодировать чистый код Base64 в двоичные данные с помощью функции Base64Значение() и сформировать новый объект.
Рассмотрим универсальный фрагмент кода для обработки изображений:
Если ТипЗнч(Элемент.Картинка) = Тип("Строка") Тогда
СтрокаBase64 = Элемент.Картинка;
// Находим позицию запятой, отделяющей заголовок "data:image/png;base64," от данных
ПозицияЗапятой = СтрНайти(СтрокаBase64, ",");
Если ПозицияЗапятой > 0 Тогда
// Получаем кодированную строку без префикса
ЧистыйBase64 = Сред(СтрокаBase64, ПозицияЗапятой + 1);
// Преобразуем Base64 в ДвоичныеДанные
ДвоичныеДанные = Base64Значение(ЧистыйBase64);
// Инициализируем объект Картинка
ОбъектКартинка = Новый Картинка(ДвоичныеДанные);
КартинкаПечать.Картинка = ОбъектКартинка;
КонецЕсли;
ИначеЕсли ТипЗнч(Элемент.Картинка) = Тип("Картинка") Тогда
// Если объект уже имеет нужный тип
КартинкаПечать.Картинка = Элемент.Картинка;
КонецЕсли;
Хотя поэлементный обход позволяет выводить текст и графику в ТабличныйДокумент, у этого способа есть существенный недостаток: при получении свойства .Текст теряется исходное оформление (полужирный шрифт, курсив, подчёркивания, цвета, выравнивание и списки).
Если необходимо сохранить 100% исходного форматирования и верстки, разберем альтернативный и наиболее эффективный подход — использование встроенного метода ПолучитьHTML().
Рассмотрим пошагово процесс подготовки форматированного документа к печати через HTML:
ПолеHTMLДокумента.Посмотрим на программную реализацию выгрузки HTML:
ТекстHTML = "";
СтруктураКартинок = Новый Структура;
// Экспортируем HTML-код и извлекаем картинки
ФорматированныйДокумент.ПолучитьHTML(ТекстHTML, СтруктураКартинок);
// Обрабатываем картинки из структуры и подготавливаем их для отображения
Для Каждого КлючИЗначение Из СтруктураКартинок Цикл
ИмяФайла = КлючИЗначение.Ключ;
ОбъектКартинка = КлючИЗначение.Значение;
// Сохраняем картинки во временный каталог или кодируем в Base64 прямо в src
Двоичные = ОбъектКартинка.ПолучитьДвоичныеДанные();
СтрокаBase64 = Base64Строка(Двоичные);
// Заменяем имя файла на Data URL в HTML коде
ТекстHTML = СтрЗаменить(ТекстHTML, ИмяФайла, "data:image/png;base64," + СтрокаBase64);
КонецЦикла;
// Выводим полученный код в реквизит формы типа Строка (связанный с Полем HTML документа)
Элементы.ПолеHTML.Документ.open();
Элементы.ПолеHTML.Документ.write(ТекстHTML);
Элементы.ПолеHTML.Документ.close();
После того как страница сформирована в элементе формы, можно вызвать команду печати из контекста документа:
// Вызов диалога печати для поля HTML
Элементы.ПолеHTML.Документ.execCommand("Print");
Проанализируем сильные и слабые стороны каждого решения, чтобы выбрать оптимальный подход под конкретную задачу:
Таким образом, выбор метода зависит от требований к печатной форме. Для простых текстов с картинками достаточно использовать обход элементов с проверкой типов данных, а для сложных документов с богатым версточным оформлением рекомендуется применять экспортирование в HTML.