Skip to content

Блочное формирование HTML-писем

#Область ПрограммныйИнтерфейс
// Функция - Сообщение HTML
//
// Параметры:
// Заголовок - Строка - Строка, которая будет отображаться в шапке письма крупным шрифтом
// МассивБлоковHTMLСообщения - Массив Из Строка - Массив строк, сформированных функциями "БлокHMTLСообщения_..."
// ПараметрыОформления - Структура - см. ПараметрыОформленияHTMLСообщения. Если неопределено создаются параметры по умолчанию
//
// БлокОбъектов = Новый Массив;
// // Абзац
// БлокОбъектов.Добавить(ОбработкаОбъект.БлокHTMLСообщения_Абзац("Скажи-ка, дядя, ведь<>%$"""" ' недаром, Москва..." + Символы.ПС + "tot;ladkflasdhkf;as"));
//
// // Абзац с гиперссылкой
// ПараметрыГиперссылки = Новый Соответствие;
// ПараметрыГиперссылки.Вставить("с гиперссылкой", "https://www.google.com");
// ПараметрыГиперссылки.Вставить("еще одной", "https://www.google.com");
// БлокОбъектов.Добавить(ОбработкаОбъект.БлокHTMLСообщения_АбзацСГиперссылками("Абзацы можно добавлять [с гиперссылкой] и, если хочется, [еще одной]. Количество не ограничено", ПараметрыГиперссылки));
//
// БлокОбъектов.Добавить(ОбработкаОбъект.БлокHTMLСообщения_Абзац("Так будет выглядеть список. Формируется из массива"));
//
// // Список пунктов
// МассивПунктов = Новый Массив;
// МассивПунктов.Добавить("Пункт 1");
// МассивПунктов.Добавить("Пункт 2");
//
// МассивПодпунктов = Новый Массив;
// МассивПодпунктов.Добавить("Подпункт 1");
// МассивПодпунктов.Добавить("Подпункт 2");
//
// МассивПодпунктов1 = Новый Массив;
// МассивПодпунктов1.Добавить("Подпункт 1");
// МассивПодпунктов1.Добавить("Подпункт 2");
// МассивПодпунктов.Добавить(МассивПодпунктов1);
//
// МассивПунктов.Добавить(МассивПодпунктов);
// МассивПунктов.Добавить("Пункт 3");
//
// БлокОбъектов.Добавить(ОбработкаОбъект.БлокHTMLСообщения_СписокНенумерованный(МассивПунктов));
//
// // В результате такая структура
// // Пункт 1
// // Пункт 2
// // Подпункт 1
// // Подпункт 2
// // Подпункт 1
// // Подпункт 2
// // Пункт 3
//
//
// // Таблица
// ТЗ = Новый ТаблицаЗначений;
// ТЗ.Колонки.Добавить("НомерПоПорядку", , "№", 5); // ширину задаем, если нужна разная ширина колонок
// ТЗ.Колонки.Добавить("Номенклатура");
// ТЗ.Колонки.Добавить("Характеристика");
// ТЗ.Колонки.Добавить("Количество", , "Кол-во" , 10);
//
// НоваяСтрока = ТЗ.Добавить();
// НоваяСтрока.НомерПоПорядку = "1";
// НоваяСтрока.Номенклатура = "Номенклатура 1";
// НоваяСтрока.Характеристика = "";
// НоваяСтрока.Количество = 10;
//
// НоваяСтрока = ТЗ.Добавить();
// НоваяСтрока.НомерПоПорядку = "2";
// НоваяСтрока.Номенклатура = "Номенклатура 2";
// НоваяСтрока.Характеристика = "с характеристикой";
// НоваяСтрока.Количество = "15";
//
// БлокОбъектов.Добавить(ОбработкаОбъект.БлокHTMLСообщения_Таблица(ТЗ));
//
// // Цитата
// БлокОбъектов.Добавить(ОбработкаОбъект.БлокHTMLСообщения_Цитата("Это цитата"));
//
// Результат = ОбработкаОбъект.СообщениеHTML("Добрый день", БлокОбъектов);
// Возвращаемое значение:
// Строка - сообщение, оформленное в HTML
//
Функция СообщениеHTML(Заголовок, МассивБлоковHTMLСообщения, ПараметрыОформления = Неопределено) Экспорт
Шаблон = ШаблонHTMLСообщения(ПараметрыОформления);
ПараметрыЗаполнения = Новый Структура("ТелоСообщения", СтрСоединить(МассивБлоковHTMLСообщения, Символы.ПС));
ПараметрыЗаполнения.Вставить("Заголовок", НормализованныйТекстДляHTML(Заголовок));
Результат = СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, ПараметрыЗаполнения);
Возврат Результат;
КонецФункции
// Функция - Параметры оформления HTMLСообщения. Содержит значения плейсхолдеров инлайновых стилей CSS в шаблоне.
// Обязательны все для формирования работы метода СообщениеHTML.
//
// Возвращаемое значение:
// Структура -
// ТелоЦветЗаднегоФона - Строка - background. По умолчанию "rgb(245, 245, 245)"
// ТелоШрифт - Строка - font-family. По умолчанию "Arial, sans-serif"
//
// АбзацВнутреннийОтступ - Строка - padding. По умолчанию "2px"
// АбзацРазмерШрифта - Строка - font-size. По умолчанию "14px"
// АбзацМежстрочныйИнтервал - Строка - line-height. По умолчанию "1.6"
// АбзацЦветТекста - Строка - color. По умолчанию "rgb(51, 51, 51)"
// АбзацВнешнийОтступ - Строка - margin. По умолчанию "5px"
//
// КонтейнерВнешнийОтступ - Строка - margin. По умолчанию "40px"
// КонтейнерЦветФона - Строка - background. По умолчанию "rgb(255, 255, 255)"
// КонтейнерВнутреннийОтступ - Строка - padding. По умолчанию "20px"
// КонтейнерСкругление - Строка - border-radius. По умолчанию "6px"
// КонтейнерТень - Строка - box-shadow. По умолчанию "0 2px 4px rgba(0, 0, 0, 0.1)"
//
// ЗаголовокЦветТекста - Строка - color. По умолчанию "rgb(118, 34, 40)"
// ЗаголовокВнутреннийОтступ - Строка - padding. По умолчанию "0px"
// ЗаголовокВнешнийОтступ - Строка - margin. По умолчанию "10px"
//
// КонтентШирина - Строка - width. По умолчанию "1000"
// КонтентВнутреннийОтступ - Строка - padding. По умолчанию "5px"
// КонтентРазмерШрифта - Строка - font-size. По умолчанию "14px"
// КонтентМежстрочныйИнтервал - Строка - line-height. По умолчанию "1.6"
// КонтентЦветТекста - Строка - color. По умолчанию "rgb(51, 51, 51)"
//
// ТаблицаШирина - Строка - width. По умолчанию "960". ВНИМАНИЕ, Всегда указывайте как строковое представление числа, без "px, em" и пр.
// ТаблицаВнешнийОтступ - Строка - margin. По умолчанию "10px"
// ЯчейкаГраница - Строка - border. По умолчанию "1px solid rgb(204, 204, 204)"
// ТаблицаЦветФонаЗаголовка - Строка - background. По умолчанию "rgb(230, 230, 230)"
// ТаблицаЦветТекстаЗаголовка - Строка - color. По умолчанию "rgb(118, 34, 40)"
//
// СсылкаЦветТекста - Строка - color. По умолчанию "rgb(118, 34, 40)"
// СсылкаЦветФона - Строка - background. По умолчанию "rgb(249, 249, 249)"
//
// ЦитатаВнутреннийОтступ - Строка - padding. По умолчанию "10px"
// ЦитатаЦветФона - Строка - background. По умолчанию "rgb(249, 249, 249)"
// ЦитатаГраницаСлева - Строка - border-left. По умолчанию "4px solid rgb(118, 34, 40)"
//
// ПодвалОтступСверху - Строка - padding-top. По умолчанию "20px"
// ПодвалРазмерШрифта - Строка - font-size. По умолчанию "11px"
// ПодвалЦветТекста - Строка - color. По умолчанию "rgb(119, 119, 119)"
//
Функция ПараметрыОформленияHTMLСообщения() Экспорт
ПараметрыОформления = Новый Структура;
ПараметрыОформления.Вставить("ТелоЦветЗаднегоФона", "rgb(245, 245, 245)");
ПараметрыОформления.Вставить("ТелоШрифт", "Arial, sans-serif");
ПараметрыОформления.Вставить("АбзацВнутреннийОтступ", "2px");
ПараметрыОформления.Вставить("АбзацРазмерШрифта", "14px");
ПараметрыОформления.Вставить("АбзацМежстрочныйИнтервал", "1.6");
ПараметрыОформления.Вставить("АбзацЦветТекста", "rgb(51, 51, 51)");
ПараметрыОформления.Вставить("АбзацВнешнийОтступ", "5px");
ПараметрыОформления.Вставить("КонтейнерВнешнийОтступ", "40px");
ПараметрыОформления.Вставить("КонтейнерЦветФона", "rgb(255, 255, 255)");
ПараметрыОформления.Вставить("КонтейнерВнутреннийОтступ", "20px");
ПараметрыОформления.Вставить("КонтейнерСкругление", "6px");
ПараметрыОформления.Вставить("КонтейнерТень", "0 2px 4px rgba(0, 0, 0, 0.1)");
ПараметрыОформления.Вставить("ЗаголовокЦветТекста", "rgb(118, 34, 40)");
ПараметрыОформления.Вставить("ЗаголовокВнутреннийОтступ", "0px");
ПараметрыОформления.Вставить("ЗаголовокВнешнийОтступ", "10px");
ПараметрыОформления.Вставить("КонтентШирина", "1000");
ПараметрыОформления.Вставить("КонтентВнутреннийОтступ", "5px");
ПараметрыОформления.Вставить("КонтентРазмерШрифта", "14px");
ПараметрыОформления.Вставить("КонтентМежстрочныйИнтервал", "1.6");
ПараметрыОформления.Вставить("КонтентЦветТекста", "rgb(51, 51, 51)");
ПараметрыОформления.Вставить("ТаблицаШирина", "960");
ПараметрыОформления.Вставить("ТаблицаВнешнийОтступ", "10px auto");
ПараметрыОформления.Вставить("ЯчейкаГраница", "1px solid rgb(204, 204, 204)");
ПараметрыОформления.Вставить("ТаблицаЦветФонаЗаголовка", "rgb(230, 230, 230)");
ПараметрыОформления.Вставить("ТаблицаЦветТекстаЗаголовка", "rgb(118, 34, 40)");
ПараметрыОформления.Вставить("СсылкаЦветТекста", "rgb(118, 34, 40)");
ПараметрыОформления.Вставить("СсылкаЦветФона", "rgb(249, 249, 249)");
ПараметрыОформления.Вставить("ЦитатаВнутреннийОтступ", "10px");
ПараметрыОформления.Вставить("ЦитатаЦветФона", "rgb(249, 249, 249)");
ПараметрыОформления.Вставить("ЦитатаГраницаСлева", "4px solid rgb(118, 34, 40)");
ПараметрыОформления.Вставить("ПодвалОтступСверху", "20px");
ПараметрыОформления.Вставить("ПодвалРазмерШрифта", "11px");
ПараметрыОформления.Вставить("ПодвалЦветТекста", "rgb(119, 119, 119)");
Возврат ПараметрыОформления;
КонецФункции
// Функция - Блок HTMLСообщения заголовок
//
// Параметры:
// ТекстЗаголовка - Строка - Текст, выводимый в блоке
// Уровень - Число - уровень заголовка от 1 до 6. Рекомендуется использовать от 2 до 4.
// ПараметрыОформления - Структура - см. ПараметрыОформленияHTMLСообщения
//
// Возвращаемое значение:
// Строка - Блок вида <h1...></h...>
//
Функция БлокHTMLСообщения_Заголовок(ТекстЗаголовка, Уровень = 2, ПараметрыОформления = Неопределено) Экспорт
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
Если Уровень < 1 Или Уровень > 6 Тогда
Уровень = 2;
КонецЕсли;
ШаблонЗаголовка = "<h%1 style=""margin: [ЗаголовокВнешнийОтступ]; padding: [ЗаголовокВнутреннийОтступ]; font-family: [ТелоШрифт]; color: [ЗаголовокЦветТекста]"">%2</h%1>
|";
Результат = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(ШаблонЗаголовка,
Формат(Уровень, "ЧДЦ=0; ЧГ="),
НормализованныйТекстДляHTML(ТекстЗаголовка));
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Результат, ПараметрыОформления);
КонецФункции
// Функция - Блок HTMLСообщения абзац
//
// Параметры:
// ТекстАбзаца - Строка - Текст, который будет выведен в абзаце
// ПараметрыОформления - Структура, Неопределено - см. ПараметрыОформленияHTMLСообщения().
// Нормализовать - Булево - Служебный, определяет необходимость экранирования спец.символов
//
// Возвращаемое значение:
// Строка - Блок вида <p style="">Текст</p>
//
Функция БлокHTMLСообщения_Абзац(ТекстАбзаца, ПараметрыОформления = Неопределено, Нормализовать = Истина) Экспорт
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
Результат = СтрШаблон("<p style=""margin: [АбзацВнешнийОтступ]; font-family: [ТелоШрифт]; padding: [АбзацВнутреннийОтступ]; font-size: [АбзацРазмерШрифта]; line-height: [АбзацМежстрочныйИнтервал]; color: [АбзацЦветТекста];"">%1</p>
|",
?(Нормализовать, НормализованныйТекстДляHTML(ТекстАбзаца), ТекстАбзаца));
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Результат, ПараметрыОформления);
КонецФункции
// Функция - Абзац сообщения с гиперссылками
//
// Параметры:
// ШаблонАбзаца - Строка - Шаблон вида "Нажмите [на эту ссылку], чтобы узнать больше". [на эту ссылку] - ключ соответствия СписокСсылок
// СписокСсылок - Соответствие -
// * Ключ - Строка - представление ссылки в письме. Т.е. ключ "на эту ссылку" заменит строку "[на эту ссылку]" в шаблоне
// * Значение - Строка - ссылка для вставки
// ПараметрыОформления - Структура, Неопределено - см. ПараметрыОформленияHTMLСообщения(). Если неопределено создаются параметры по умолчанию
//
// Возвращаемое значение:
// Строка - Блок вида <p style="">Текст до ссылки <a href="Ссылка" style="">Представление ссылки</a> Текст после ссылки</p>
//
Функция БлокHTMLСообщения_АбзацСГиперссылками(Знач ШаблонАбзаца, СписокСсылок, ПараметрыОформления = Неопределено) Экспорт
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
ШаблонАбзаца = НормализованныйТекстДляHTML(ШаблонАбзаца);
Для Каждого КлючЗначение Из СписокСсылок Цикл
Ключ = КлючЗначение.Ключ;
Значение = КлючЗначение.Значение;
СсылкаДляВставки = СтрШаблон("<a href=""%1"" style=""font-family: [ТелоШрифт]; color: [СсылкаЦветТекста]; background: [СсылкаЦветФона]; text-decoration: underline; padding: [КонтентВнутреннийОтступ]; font-size: [КонтентРазмерШрифта]; line-height: [КонтентМежстрочныйИнтервал];"">%2</a>",
Значение,
Ключ);
ШаблонАбзаца = СтрЗаменить(ШаблонАбзаца,
СтрШаблон("[%1]", Ключ),
СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(СсылкаДляВставки, ПараметрыОформления));
КонецЦикла;
Возврат БлокHTMLСообщения_Абзац(ШаблонАбзаца, ПараметрыОформления, Ложь);
КонецФункции
// Функция - Список ненумерованный
//
// Параметры:
// МассивЗначений - Массив Из Строка, Массив Из Массив - Список элементов. Если нужен иерархический список, то добавляем не строку, а новый массив строк
// Например, для массива [Привет, Вася, Как, Дела] будет сформирован список
// * Привет
// * Вася
// * Как
// * Дела
// Если в этом массиве будет еще один, то список получится иерархический, Например
// для массива [Привет, Вася, Как, Дела, [Все, Хорошо]]
// * Привет
// * Вася
// * Как
// * Дела
// ** Все
// ** Хорошо
//
// Возвращаемое значение:
// Строка -
//
Функция БлокHTMLСообщения_СписокНенумерованный(МассивЗначений, ПараметрыОформления = Неопределено) Экспорт
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
Текст = "";
СформироватьСписокНенумерованныйHTMLРекурсивно(МассивЗначений, Текст, ПараметрыОформления);
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Текст, ПараметрыОформления);
КонецФункции
// Функция - Блок HTMLСообщения цитата
//
// Параметры:
// ТекстЦитаты - Строка - Выводимый текст
// ПараметрыОформления - Структура, Неопределено - см. ПараметрыОформленияHTMLСообщения(). Если неопределено создаются параметры по умолчанию
//
// Возвращаемое значение:
// Строка - Блок, оформленный в виде цитаты
//
Функция БлокHTMLСообщения_Цитата(ТекстЦитаты, ПараметрыОформления = Неопределено) Экспорт
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
Шаблон = "<table width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"">
| <tr>
| <td style=""font-family: [ТелоШрифт]; padding: [ЦитатаВнутреннийОтступ]; background: [ЦитатаЦветФона]; border-left: [ЦитатаГраницаСлева]; font-style: italic;"">
| %1
| </td>
| </tr>
|</table>";
Результат = СтроковыеФункцииКлиентСервер.ПодставитьПараметрыВСтроку(Шаблон, НормализованныйТекстДляHTML(ТекстЦитаты));
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Результат, ПараметрыОформления);
КонецФункции
// Функция - Блок HTMLСообщения таблица
//
// Параметры:
// ТаблицаЗначений - ТаблицаЗначений - Выводимая таблица. Если не заполнен заголовок, в шапке будет выведено имя,
// если не заполнена ширина, то устанавливается ширина по умолчанию
//
// Возвращаемое значение:
// Строка - Таблица в HTML
//
Функция БлокHTMLСообщения_Таблица(ТаблицаЗначений, ПараметрыОформления = Неопределено) Экспорт
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
ОбщаяШиринаТаблицыСтрокой = ОбщегоНазначенияКлиентСервер.СвойствоСтруктуры(ПараметрыОформления, "ТаблицаШирина", "960");
ОбщаяШиринаТаблицы = Число(ОбщаяШиринаТаблицыСтрокой);
ЗначениеШириныКолонок = АбсолютнаяШиринаКолонок(ТаблицаЗначений, ОбщаяШиринаТаблицы);
// Устанавливаем абсолютные значения ширины колонок
Для Каждого ЗначениеШирины Из ЗначениеШириныКолонок Цикл
ТаблицаЗначений.Колонки[ЗначениеШирины.Колонка].Ширина = ЗначениеШирины.ШиринаПикселей;
КонецЦикла;
// Подготавливаем заголовок таблицы
ДанныеЯчеекЗаголовкаТаблицы = Новый Массив;
Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
ТекстЗаполнения = ?(ЗначениеЗаполнено(Колонка.Заголовок), Колонка.Заголовок, Колонка.Имя);
ДанныеЯчеекЗаголовкаТаблицы.Добавить(ЯчейкаЗаголовкаТаблицыHTML(ТекстЗаполнения, Колонка.Ширина));
КонецЦикла;
Заголовок = ЗаголовокТаблицыHTML(ДанныеЯчеекЗаголовкаТаблицы);
// Подготавливаем строки
ДанныеСтрокТаблицы = Новый Массив;
Для Каждого Строка Из ТаблицаЗначений Цикл
ДанныеЯчеекСтроки = Новый Массив;
Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
ДанныеЯчеекСтроки.Добавить(ЯчейкаСтрокиОсновныхДанныхHTML(Строка[Колонка.Имя], Колонка.Ширина));
КонецЦикла;
ДанныеСтрокТаблицы.Добавить(СтрокаТаблицыHTML(ДанныеЯчеекСтроки));
КонецЦикла;
Таблица = ТаблицаHTML(Заголовок, ДанныеСтрокТаблицы);
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Таблица, ПараметрыОформления);
КонецФункции
#КонецОбласти
#Область СлужебныйПрограммныйИнтерфейс
Функция ШаблонHTMLСообщения(ПараметрыОформления = Неопределено) Экспорт
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
Шаблон =
"<!DOCTYPE html>
|<html lang=""ru"">
|<head>
| <meta charset=""UTF-8"">
| <title>HTML Email</title>
|</head>
|<body style=""margin: 0; padding: 0; background: [ТелоЦветЗаднегоФона]; font-family: [ТелоШрифт];"">
// Основной контейнер
| <table width=""100%"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""background: [ТелоЦветЗаднегоФона];"">
| <tr>
| <td align=""center"">
// Обертка
| <table cellpadding=""0"" cellspacing=""0"" border=""0"">
| <tr>
| <td align=""center"">
// Начало контента
| <table width=""[КонтентШирина]"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""font-family: [ТелоШрифт]; background: [КонтейнерЦветФона]; padding: [КонтейнерВнутреннийОтступ]; border-radius: [КонтейнерСкругление]; box-shadow: [КонтейнерТень];"">
| <tr>
| <td style=""margin: 20px; font-family: [ТелоШрифт]; padding: [КонтентВнутреннийОтступ]; font-size: [КонтентРазмерШрифта]; line-height: [КонтентМежстрочныйИнтервал]; color: [КонтентЦветТекста];"">
| <h1 align=""center"" style=""margin: [ЗаголовокВнешнийОтступ]; padding: [ЗаголовокВнутреннийОтступ]; font-family: [ТелоШрифт]; color: [ЗаголовокЦветТекста]"">[Заголовок]</h1>
| [ТелоСообщения]
| </td>
| </tr>
//
// Отчерк
| <tr>
| <td height=""1"" style=""font-size: 1px; line-height: 1px; font-size: 0"">&nbsp;</td>
| </tr>
| <tr>
| <td style=""padding: 1px 0 0 0; border-top: 3px solid [ЗаголовокЦветТекста]; font-size: 0; line-height: 0;"">&nbsp;</td>
| </tr>
// Конец отчерка
//
// Подпись и лого (insert base64 to src img)
| <tr>
| <td align=""center"" style=""font-family: [ТелоШрифт]; padding-top: [ПодвалОтступСверху]; font-size: [ПодвалРазмерШрифта]; color: [ПодвалЦветТекста];"">
| Это письмо сформировано автоматически. Пожалуйста, не отвечайте на него.
| </td>
| </tr>
| <tr>
| <td align=""center"" style=""line-height: 0; padding: 0; margin: 0;"">
| <img src=""""
| alt=""Logo""
| border=""0""
| style=""border: 0; display: block; margin: 0 auto;"">
| </td>
| </tr>
// Конец подписи и лого
| </table>
// Конец контента
| </td>
| </tr>
| </table>
| </td>
| </tr>
| </table>
|</body>
|</html>";
Результат = СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, ПараметрыОформления);
Возврат Результат;
КонецФункции
// Функция - Нормализованный текст для HTML. Исплользуется в методах "БлокHTMLСообщения_.."
//
// Параметры:
// Текст - Строка -
//
// Возвращаемое значение:
// Строка - Текст с экранированными спец.символами
//
Функция НормализованныйТекстДляHTML(Знач Текст) Экспорт
Текст = СтрЗаменить(Текст, "&", "&amp;");
Текст = СтрЗаменить(Текст, "<", "&lt;");
Текст = СтрЗаменить(Текст, ">", "&gt;");
Текст = СтрЗаменить(Текст, """", "&quot;");
Текст = СтрЗаменить(Текст, "'", "&#39;");
Текст = СтрЗаменить(Текст, Символы.ПС, "<br>");
Текст = СтрЗаменить(Текст, Символы.ВК, "<br>");
Текст = СтрЗаменить(Текст, Символы.Таб, " ");
Возврат Текст;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
Процедура СформироватьСписокНенумерованныйHTMLРекурсивно(МассивЗначений, ТекстHTML = Неопределено, ПараметрыОформления = Неопределено)
Если ТекстHTML = Неопределено Тогда
ТекстHTML = "";
КонецЕсли;
Если ПараметрыОформления = Неопределено Тогда
ПараметрыОформления = ПараметрыОформленияHTMLСообщения();
КонецЕсли;
ТекстHTML = ТекстHTML
+ СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(НачалоНенумерованногоСпискаHTML(), ПараметрыОформления)
+ Символы.ПС;
Для Каждого ЭлементМассива Из МассивЗначений Цикл
Если ТипЗнч(ЭлементМассива) = Тип("Массив") Тогда
СформироватьСписокНенумерованныйHTMLРекурсивно(ЭлементМассива, ТекстHTML, ПараметрыОформления);
Иначе
ТекстHTML = ТекстHTML + ЭлементНенумерованногоСпискаHTML(ЭлементМассива) + Символы.ПС;
КонецЕсли
КонецЦикла;
ТекстHTML = ТекстHTML + "</ul>" + Символы.ПС;
КонецПроцедуры
Функция НачалоНенумерованногоСпискаHTML()
Возврат "<ul style=""margin-left: 10px; padding-left: 10px; list-style-position: inside; font-family: [ТелоШрифт]; font-size: [КонтентРазмерШрифта]; line-height: [КонтентМежстрочныйИнтервал]; color: [КонтентЦветТекста];"">";
КонецФункции
Функция ЭлементНенумерованногоСпискаHTML(ТекстЗаполнения)
Шаблон = "<li style=""font-family: [ТелоШрифт]; font-size: [КонтентРазмерШрифта]; line-height: [КонтентМежстрочныйИнтервал]; color: [КонтентЦветТекста];"">
| [ТекстЗаполнения]
|</li>";
НормализованныйТекст = НормализованныйТекстДляHTML(ТекстЗаполнения);
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, Новый Структура("ТекстЗаполнения", НормализованныйТекст));
КонецФункции
Функция ТаблицаHTML(СтрокаЗаголовкаТаблицы, ДанныеСтрокТаблицы)
Шаблон =
"<p style=""font-size: 5px; line-height: 5px; margin: 0;"">&nbsp;</p>
|<table width=""[ТаблицаШирина]"" align=""center"" cellpadding=""0"" cellspacing=""0"" border=""0"" style=""margin: [ТаблицаВнешнийОтступ]; border-collapse: collapse;"">
| <thead>
| [СтрокаЗаголовкаТаблицы]
| </thead>
| <tbody>
| [ДанныеСтрокТаблицы]
| </tbody>
|</table>
|<p style=""font-size: 5px; line-height: 5px; margin: 0;"">&nbsp;</p>
|";
ТекстЗаполненияСтрокТаблицы = СтрСоединить(ДанныеСтрокТаблицы, Символы.ПС);
ПараметрыЗаполнения = Новый Структура;
ПараметрыЗаполнения.Вставить("СтрокаЗаголовкаТаблицы", СтрокаЗаголовкаТаблицы);
ПараметрыЗаполнения.Вставить("ДанныеСтрокТаблицы", ТекстЗаполненияСтрокТаблицы);
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, ПараметрыЗаполнения);
КонецФункции
Функция ЗаголовокТаблицыHTML(ДанныеЯчеекЗаголовка)
Шаблон = "<tr style=""background: [ТаблицаЦветФонаЗаголовка]; color: [ТаблицаЦветТекстаЗаголовка];"">
| [ДанныеЯчеекЗаголовкаТаблицы]
|</tr>";
ДанныеЗаполнения = Новый Структура;
ДанныеЗаполнения.Вставить("ДанныеЯчеекЗаголовкаТаблицы", СтрСоединить(ДанныеЯчеекЗаголовка, Символы.ПС));
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, ДанныеЗаполнения);
КонецФункции
Функция ЯчейкаЗаголовкаТаблицыHTML(ТекстЗаголовка, ШиринаКолонкиПикселей)
ТекстЗаполнения = НормализованныйТекстДляHTML(ТекстЗаголовка);
Шаблон = "<th style=""width: [ШиринаКолонкиПикселей]px; font-family: [ТелоШрифт]; border: [ЯчейкаГраница]; padding: [КонтентВнутреннийОтступ]; font-size: [КонтентРазмерШрифта]; line-height: [КонтентМежстрочныйИнтервал]; text-align: left;"">
| [ТекстЗаполнения]
|</th>";
ПараметрыЗаполнения = Новый Структура;
ПараметрыЗаполнения.Вставить("ШиринаКолонкиПикселей", Формат(ШиринаКолонкиПикселей, "ЧДЦ=0; ЧГ="));
ПараметрыЗаполнения.Вставить("ТекстЗаполнения", ТекстЗаполнения);
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, ПараметрыЗаполнения);
КонецФункции
Функция СтрокаТаблицыHTML(ДанныеЯчеекСтрокиТаблицы)
Шаблон = "<tr style=""font-family: [ТелоШрифт]; border: [ЯчейкаГраница]; padding: [КонтентВнутреннийОтступ]; font-size: [КонтентРазмерШрифта]; line-height: [КонтентМежстрочныйИнтервал]; color: [КонтентЦветТекста];"">
| [ДанныеЯчеекСтрокиТаблицы]
|</tr>";
ТекстЗаполнения = СтрСоединить(ДанныеЯчеекСтрокиТаблицы, Символы.ПС);
Результат = СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, Новый Структура("ДанныеЯчеекСтрокиТаблицы", ТекстЗаполнения));
Возврат Результат;
КонецФункции
Функция ЯчейкаСтрокиОсновныхДанныхHTML(ТекстЯчейки, ШиринаКолонкиПикселей)
ТекстЗаполнения = НормализованныйТекстДляHTML(ТекстЯчейки);
Шаблон = "<td style=""width: [ШиринаКолонкиПикселей]px; font-family: [ТелоШрифт]; border: [ЯчейкаГраница]; padding: [КонтентВнутреннийОтступ]; font-size: [КонтентРазмерШрифта]; line-height: [КонтентМежстрочныйИнтервал]; color: [КонтентЦветТекста];"">
| [ЗначениеЯчейкиСтрокиТаблицы]
|</td>";
ПараметрыЗаполнения = Новый Структура;
ПараметрыЗаполнения.Вставить("ШиринаКолонкиПикселей", Формат(ШиринаКолонкиПикселей, "ЧДЦ=0; ЧГ="));
ПараметрыЗаполнения.Вставить("ЗначениеЯчейкиСтрокиТаблицы", ТекстЗаполнения);
Возврат СтроковыеФункцииКлиентСервер.ВставитьПараметрыВСтроку(Шаблон, ПараметрыЗаполнения);
КонецФункции
Функция АбсолютнаяШиринаКолонок(ТаблицаЗначений, ОбщаяШирина)
Колонки = Новый Массив;
Для Каждого Колонка Из ТаблицаЗначений.Колонки Цикл
Колонки.Добавить(Новый Структура("Колонка, Ширина", Колонка.Имя, Колонка.Ширина));
КонецЦикла;
СуммаЗаданных = 0;
КоличествоНезаполненных = 0;
Для Каждого Колонка Из Колонки Цикл
Если Колонка.Ширина > 0 Тогда
СуммаЗаданных = СуммаЗаданных + Колонка.Ширина;
Иначе
КоличествоНезаполненных = КоличествоНезаполненных + 1;
КонецЕсли;
КонецЦикла;
// Шаг 1: нормализация
Если СуммаЗаданных = 0 Тогда
Для Каждого Колонка Из Колонки Цикл
Колонка.Вставить("ШиринаПроцентов", Окр(100 / Колонки.Количество(), 0));
КонецЦикла;
ИначеЕсли СуммаЗаданных <= 100 Тогда
Свободно = 100 - СуммаЗаданных;
Средняя = ?(КоличествоНезаполненных > 0, Свободно / КоличествоНезаполненных, 0);
Для Каждого Колонка Из Колонки Цикл
Если Колонка.Ширина = 0 Тогда
Колонка.Вставить("ШиринаПроцентов", Окр(Средняя, 0));
Иначе
Колонка.Вставить("ШиринаПроцентов", Окр(Колонка.Ширина, 0));
КонецЕсли;
КонецЦикла;
Иначе
// Масштабирование
Для Каждого Колонка Из Колонки Цикл
Если Колонка.Ширина > 0 Тогда
Пропорция = Колонка.Ширина / СуммаЗаданных * 100;
Колонка.Вставить("ШиринаПроцентов", Окр(Пропорция, 0));
Иначе
Колонка.Вставить("ШиринаПроцентов", 0);
КонецЕсли;
КонецЦикла;
// Заполнение оставшихся нулей
НовыйСумма = 0;
КоличествоНезаполненных = 0;
Для Каждого Колонка Из Колонки Цикл
Если Колонка.ШиринаПроцентов > 0 Тогда
НовыйСумма = НовыйСумма + Колонка.ШиринаПроцентов;
Иначе
КоличествоНезаполненных = КоличествоНезаполненных + 1;
КонецЕсли;
КонецЦикла;
Остаток = 100 - НовыйСумма;
Средняя = ?(КоличествоНезаполненных > 0, Остаток / КоличествоНезаполненных, 0);
Для Каждого Колонка Из Колонки Цикл
Если Колонка.ШиринаПроцентов = 0 Тогда
Колонка.ШиринаПроцентов = Окр(Средняя, 0);
КонецЕсли;
КонецЦикла;
КонецЕсли;
// Шаг 2: корректировка процентов
ОбщаяСумма = 0;
Для Каждого Колонка Из Колонки Цикл
ОбщаяСумма = ОбщаяСумма + Колонка.ШиринаПроцентов;
КонецЦикла;
Ошибка = 100 - ОбщаяСумма;
Пока Ошибка <> 0 Цикл
Для Каждого Колонка Из Колонки Цикл
Если Ошибка = 0 Тогда
Прервать;
КонецЕсли;
Изменение = ?(Ошибка > 0, 1, -1);
Колонка.ШиринаПроцентов = Колонка.ШиринаПроцентов + Изменение;
Ошибка = Ошибка - Изменение;
КонецЦикла;
КонецЦикла;
// Шаг 3: абсолютная ширина
ОбщаяПикселей = 0;
Для Каждого Колонка Из Колонки Цикл
Пикселей = Окр(ОбщаяШирина * Колонка.ШиринаПроцентов / 100, 0);
Колонка.Вставить("ШиринаПикселей", Пикселей);
ОбщаяПикселей = ОбщаяПикселей + Пикселей;
КонецЦикла;
// Шаг 4: корректировка до точной ширины
Остаток = ОбщаяШирина - ОбщаяПикселей;
Пока Остаток <> 0 Цикл
Для Каждого Колонка Из Колонки Цикл
Если Остаток = 0 Тогда
Прервать;
КонецЕсли;
Изменение = ?(Остаток > 0, 1, -1);
Колонка.ШиринаПикселей = Колонка.ШиринаПикселей + Изменение;
Остаток = Остаток - Изменение;
КонецЦикла;
КонецЦикла;
Возврат Колонки;
КонецФункции
#КонецОбласти
#Область СлужебныеПроцедурыИФункции
#КонецОбласти