При разработке печатных форм разработчики 1С чаще всего используют стандартный табличный документ (ТабличныйДокумент). Однако в ряде задач требуется сформировать документ именно в формате HTML — например, для встраивания интерактивных элементов, отправки письма в формате HTML или вывода информации в поле HTML-документа на форме. Нередко возникает ситуация, когда при попытке вывести список строк табличной части (например, сотрудников из документа КадровоеПеремещение) в результирующем документе отображается только одна строка. Выясним причину этой проблемы и рассмотрим несколько надежных способов правильного формирования HTML-печатной формы.
В отличие от табличного документа, где секции выводятся построчно через именованные области (Область), текстовый макет HTML требует соблюдения строгой иерархии тегов и корректной сборки строки. Ошибки обычно связаны со следующими факторами:
</td> или </tr>, а также пропущенные кавычки в атрибутах приводят к тому, что парсер браузера скрывает последующие строки таблицы.СтрЗаменить без разбивки макета на шапку, повторяемую строку и подвал, то заменится только одно вхождение.Разберем базовый и наиболее прямолинейный подход, при котором HTML-разметка динамически формируется во встроенном языке 1С. Для обеспечения корректного отображения во всех браузерах и встроенных компонентах рендеринга важно соблюдать базовую структуру документа с тегами <html> и <body>.
Посмотрим на пример кода формирования таблицы по табличной части документа:
ТекстHTML = "<html>
|<head>
| <meta http-equiv=""Content-Type"" content=""text/html; charset=utf-8"">
|</head>
|<body>
|<table border='1' cellpadding='4' cellspacing='0' style='border-collapse: collapse; width: 100%;'>
| <tr style='background-color: #f2f2f2;'>
| <th>№</th>
| <th>Сотрудник</th>
| <th>Должность</th>
| </tr>";
НомерСтроки = 0;
Для Каждого Стр Из СсылкаНаОбъект.Сотрудники Цикл
НомерСтроки = НомерСтроки + 1;
ТекстHTML = ТекстHTML + "
| <tr>
| <td align='center'>" + НомерСтроки + "</td>
| <td>" + Стр.Сотрудник + "</td>
| <td>" + Стр.Должность + "</td>
| </tr>";
КонецЦикла;
ТекстHTML = ТекстHTML + "
|</table>
|</body>
|</html>";
// Вывод сформированного текста в поле HTML-документа
ЭлементыФормы.ПолеHTML.УстановитьТекст(ТекстHTML);
Обратим внимание на ключевой момент: шапка таблицы создается до начала цикла, тело таблицы наполняется строками <tr> на каждой итерации цикла, а закрывающие теги таблицы и документа добавляются строго после завершения обхода коллекции.
Если макет печатной формы сложный, хранить весь HTML-код внутри модуля неудобно. В этом случае создадим текстовый или HTML-макет в конфигурации и разделим его специальными маркерами в комментариях: <!--ШАПКА-->, <!--СТРОКА-->, <!--ПОДВАЛ-->.
Рассмотрим, как прочитать макет, разделить его на блоки и собрать результирующий документ:
МакетТекст = ПолучитьМакет("МакетПечати").ПолучитьТекст();
// Находим позиции разделителей секций
ПозСтрокаНачало = СтрНайти(МакетТекст, "<!--СТРОКА-->");
ПозСтрокаКонец = СтрНайти(МакетТекст, "<!--/СТРОКА-->");
Шапка = Лев(МакетТекст, ПозСтрокаНачало - 1);
ШаблонСтроки = Сред(МакетТекст, ПозСтрокаНачало + 13, ПозСтрокаКонец - (ПозСтрокаНачало + 13));
Подвал = Сред(МакетТекст, ПозСтрокаКонец + 14);
ВсеСтроки = "";
Для Каждого Стр Из ТабличнаяЧасть Цикл
ТекущаяСтрокаHTML = ШаблонСтроки;
ТекущаяСтрокаHTML = СтрЗаменить(ТекущаяСтрокаHTML, "[Сотрудник]", Стр.Сотрудник);
ТекущаяСтрокаHTML = СтрЗаменить(ТекущаяСтрокаHTML, "[Подразделение]", Стр.Подразделение);
ВсеСтроки = ВсеСтроки + ТекущаяСтрокаHTML;
КонецЦикла;
ИтоговыйHTML = Шапка + ВсеСтроки + Подвал;
ЭлементыФормы.ПолеHTML.УстановитьТекст(ИтоговыйHTML);
Для предотвращения ошибок синтаксиса и автоматического контроля закрытия тегов платформа 1С предоставляет специализированный объект ЗаписьHTML. Проанализируем пример его использования:
Запись = Новый ЗаписьHTML;
Запись.УстановитьСтроку();
Запись.ЗаписатьНачалоЭлемента("html");
Запись.ЗаписатьНачалоЭлемента("body");
Запись.ЗаписатьНачалоЭлемента("table");
Запись.ЗаписатьАтрибут("border", "1");
Для Каждого Стр Из ТабличнаяЧасть Цикл
Запись.ЗаписатьНачалоЭлемента("tr");
Запись.ЗаписатьНачалоЭлемента("td");
Запись.ЗаписатьТекст(Строка(Стр.Сотрудник));
Запись.ЗаписатьКонецЭлемента(); // td
Запись.ЗаписатьКонецЭлемента(); // tr
КонецЦикла;
Запись.ЗаписатьКонецЭлемента(); // table
Запись.ЗаписатьКонецЭлемента(); // body
Запись.ЗаписатьКонецЭлемента(); // html
РезультатHTML = Запись.Закрыть();
Если макет уже реализован в виде классического табличного документа с именованными областями, нет необходимости переписывать всю логику вручную. Сформируем стандартный ТабличныйДокумент и сохраним его в HTML:
ТабДок = Новый ТабличныйДокумент;
Макет = ПолучитьМакет("ПечатьКадровогоПеремещения");
ОбластьШапка = Макет.ПолучитьОбласть("Шапка");
ТабДок.Вывести(ОбластьШапка);
ОбластьСтрока = Макет.ПолучитьОбласть("Строка");
Для Каждого Стр Из ДокументОбъект.РаботникиОрганизации Цикл
ОбластьСтрока.Параметры.Заполнить(Стр);
ТабДок.Вывести(ОбластьСтрока);
КонецЦикла;
ВременныйФайл = ПолучитьИмяВременногоФайла("html");
ТабДок.Записать(ВременныйФайл, ТипФайлаТабличногоДокумента.HTML5);
ТекстHTML = Новый ЧтениеТекста(ВременныйФайл, КодировкаТекста.UTF8);
ЭлементыФормы.ПолеHTML.УстановитьТекст(ТекстHTML.Прочитать());
ТекстHTML.Закрыть();
УдалитьФайлы(ВременныйФайл);
Если печатная форма кадрового перемещения требует вывода каждого сотрудника на отдельном листе, используем специальные стили CSS. Вставим между записями блок с разрывом страницы:
ТекстHTML = ТекстHTML + "<div style='page-break-after: always;'></div>";
При отправке сформированного документа на печать браузер или компонент формы автоматически разобьет печатный документ на отдельные листы в указанных местах.