В процессе интеграции 1С с корпоративными сайтами, интернет-магазинами или внешними порталами разработчики часто сталкиваются с задачей выгрузки информационных панелей, отчетов или прайс-листов в веб-форматы. Самый очевидный способ передачи простых структурированных данных — это выгрузка в CSV или TXT. Однако, когда перед нами встает задача представить данные в красивом визуальном виде непосредственно для отображения в браузере, оптимальным выбором становится формат HTML.
При реализации этой задачи в 1С начинающие программисты нередко сталкиваются с неприятной проблемой: сохраненный файл вместо красивой таблицы отображает непонятный набор служебных символов (так называемые «кракозябры» или внутренний код сериализации 1С). В рамках этой статьи мы детально разберем причины этой ошибки, рассмотрим стандартные механизмы платформы 1С для работы с HTML и изучим альтернативные, более производительные и гибкие способы генерации веб-страниц.
Обратимся к ситуации, описанной разработчиком на форуме. Код формирования табличного документа выглядел вполне стандартно: создавался документ, заполнялся макет по результатам запроса, настраивались параметры отображения. Проблема крылась в финальной строчке записи файла:
ДокТаб.Записать("D:\ostatki.html");
При попытке открыть полученный файл ostatki.html в браузере пользователь видел неструктурированные текстовые блоки с большим количеством фигурных скобок, кавычек и цифр, например:
},3,0,3,0,
{16,1,
{1,1,
{"#","72457"}
}
},1,
Выясним причину такого поведения платформы. Метод Записать() объекта ТабличныйДокумент имеет несколько параметров. Первый параметр — это путь к файлу. Второй параметр — это тип файла, который определяет, в каком именно формате данные будут сохранены на диск. По умолчанию, если этот параметр не указан, 1С сохраняет табличный документ в своем собственном внутреннем формате (MXL). Расширение файла .html в пути сохранения никак не влияет на логику работы платформы — она просто записывает внутренний формат MXL в файл с расширением HTML. Браузер, естественно, не может распознать внутренний формат 1С и пытается отобразить его как обычный текст.
Для решения этой проблемы необходимо явно передавать тип файла вторым параметром:
ДокТаб.Записать("D:\ostatki.html", ТипФайлаТабличногоДокумента.HTML);
Давайте подробно рассмотрим этот и другие способы экспорта данных.
Использование объекта ТабличныйДокумент — это самый простой и быстрый способ получить готовый HTML-код, если у вас уже есть разработанный печатный макет в конфигураторе. Платформа берет на себя всю работу по отрисовке ячеек, объединению строк, настройке шрифтов и цветов.
Рассмотрим детально процедуру выгрузки остатков товаров на основе макета с явным указанием формата:
Процедура ВыгрузитьОстаткиВHTML_ТабДок() Экспорт
// Инициализация табличного документа и получение макета
ДокТаб = Новый ТабличныйДокумент;
ДокТаб.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ВЫГРУЗКИ";
// Получаем макет обработки
Макет = ПолучитьМакет("Анализ");
ОбластьЗаписей = Макет.ПолучитьОбласть("ДетальныеЗаписи");
// Формируем запрос к остаткам товаров на складах
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура КАК Номенклатура,
| Остатки.Номенклатура.Артикул КАК Артикул,
| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК СвободныйОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаАнализа, Склад = &Склад) КАК Остатки
|ГДЕ
| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) > 0";
Запрос.УстановитьПараметр("ДатаАнализа", КонецДня(ТекущаяДата()));
Запрос.УстановитьПараметр("Склад", Справочники.Склады.НайтиПоКоду("00013"));
Выборка = Запрос.Выполнить().Выбрать();
// Заполняем табличный документ в цикле
Пока Выборка.Следующий() Цикл
ОбластьЗаписей.Параметры.Код = Выборка.Артикул;
ОбластьЗаписей.Параметры.Товар = Выборка.Номенклатура.Наименование;
ОбластьЗаписей.Параметры.Остаток = Выборка.СвободныйОстаток;
ДокТаб.Вывести(ОбластьЗаписей);
КонецЦикла;
// Настраиваем параметры отображения перед выгрузкой
ДокTab.ОтображатьСетку = Ложь;
ДокТаб.ОтображатьЗаголовки = Ложь;
ДокТаб.ТолькоПросмотр = Истина;
// Записываем файл на диск с явным указанием формата HTML
ПутьКФайлу = "D:\Temp\ostatki.html";
ДокТаб.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.HTML);
Сообщить("Выгрузка успешно завершена в файл: " + ПутьКФайлу);
КонецПроцедуры
Обратите внимание на важную деталь при экспорте в HTML. В перечислении ТипФайлаТабличногоДокумента доступно несколько различных веб-стандартов:
ostatki_files) и поместит графику туда. Это накладывает дополнительные сложности при последующей отправке по FTP, так как вам придется загружать не один файл, а весь каталог.ТипФайлаТабличногоДокумента.HTML5 платформа упаковывает графические элементы и картинки непосредственно внутрь самого HTML-кода с использованием кодирования Base64 (тег img с источником данных data:image/png;base64...). На выходе вы получаете один полностью автономный файл, который содержит в себе и стили, и разметку, и картинки. Его крайне удобно отправлять по FTP или пересылать по электронной почте.Несмотря на простоту использования табличного документа, у этого метода есть существенный недостаток — избыточность кода. Конвертер 1С пытается в точности воспроизвести сетку ячеек, создавая огромное количество пустых тегов <col>, тяжелые инлайновые стили CSS для каждой ячейки и громоздкую разметку таблиц. Если такой файл предназначен не для чтения глазами пользователя, а для автоматического парсинга скриптом веб-сайта, работать с ним будет крайне трудно.
Для создания чистого, легковесного и отзывчивого HTML-кода лучше применить метод ручной генерации на основе заранее подготовленного HTML-шаблона. Создадим файл-шаблон (например, template.html) и сохраним его в макет обработки с типом "Двоичные данные" или "Текст".
Пример структуры HTML-шаблона:
<!DOCTYPE html>
<html lang="ru">
<head>
<meta charset="UTF-8">
<title>Прайс-лист остатков</title>
<style>
body { font-family: Arial, sans-serif; background-color: #f4f6f9; color: #333; margin: 20px; }
h1 { color: #1c355e; border-bottom: 2px solid #1c355e; padding-bottom: 10px; }
table { width: 100%; border-collapse: collapse; margin-top: 20px; box-shadow: 0 2px 5px rgba(0,0,0,0.1); background: #fff; }
th { background-color: #1c355e; color: white; padding: 12px; text-align: left; }
td { padding: 10px; border-bottom: 1px solid #ddd; }
tr:hover { background-color: #f1f5f9; }
.articul { font-weight: bold; color: #555; }
.qty { text-align: right; font-weight: bold; }
</style>
</head>
<body>
<h1>Актуальные остатки товаров</h1>
<p>Дата формирования: [ДатаФормирования]</p>
<table>
<thead>
<tr>
<th>Артикул</th>
<th>Наименование товара</th>
<th style="text-align: right;">Свободный остаток</th>
</tr>
</thead>
<tbody>
[СтрокиТаблицы]
</tbody>
</table>
</body>
</html>
Теперь напишем программный код в 1С, который будет считывать этот шаблон, наполнять его данными из информационной базы и записывать итоговый файл в кодировке UTF-8:
Процедура ВыгрузитьОстаткиВHTML_Шаблон() Экспорт
// Получаем текст шаблона из макета (предположим, что макет текстовый)
ТекстШаблона = ПолучитьМакет("ШаблонHTML").ПолучитьТекст();
// Заменяем простые параметры в шапке документа
ТекстШаблона = СтрЗаменить(ТекстШаблона, "[ДатаФормирования]", Формат(ТекущаяДата(), "ДЛФ=DDT"));
// Выполняем запрос для получения данных
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| Остатки.Номенклатура.Артикул КАК Артикул,
| Остатки.Номенклатура.Наименование КАК Наименование,
| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК СвободныйОстаток
|ИЗ
| РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаАнализа, Склад = &Склад) КАК Остатки
|ГДЕ
| ЕСТЬNULL(Остатки.КоличествоОстаток, 0) > 0";
Запрос.УстановитьПараметр("ДатаАнализа", КонецДня(ТекущаяДата()));
Запрос.УстановитьПараметр("Склад", Справочники.Склады.НайтиПоКоду("00013"));
Выборка = Запрос.Выполнить().Выбрать();
СтрокиТаблицыHTML = "";
// Генерируем строки таблицы динамически
Пока Выборка.Следующий() Цикл
// Очищаем текстовые данные от возможных спецсимволов HTML, чтобы не сломать верстку
ОчищенноеНаименование = Выборка.Наименование;
ОчищенноеНаименование = СтрЗаменить(ОчищенноеНаименование, "&", "&");
ОчищенноеНаименование = СтрЗаменить(ОчищенноеНаименование, "<", "<");
ОчищенноеНаименование = СтрЗаменить(ОчищенноеНаименование, ">", ">");
СтрокаHTML = "<tr>" +
"<td class=""articul"">" + Выборка.Артикул + "</td>" +
"<td>" + ОчищенноеНаименование + "</td>" +
"<td class=""qty"">" + Формат(Выборка.СвободныйОстаток, "ЧГ=0") + "</td>" +
"</tr>" + Символы.ПС;
СтрокиТаблицыHTML = СтрокиТаблицыHTML + СтрокаHTML;
КонецЦикла;
// Вставляем сгенерированные строки в тело шаблона
ИтоговыйHTML = СтрЗаменить(ТекстШаблона, "[СтрокиТаблицы]", СтрокиТаблицыHTML);
// Записываем итоговый файл в кодировке UTF-8
ПутьКФайлу = "D:\Temp\price.html";
ЗаписьТекста = Новый ЗаписьТекста;
ЗаписьТекста.Открыть(ПутьКФайлу, КодировкаТекста.UTF8, , Истина);
ЗаписьТекста.Записать(ИтоговыйHTML);
ЗаписьТекста.Закрыть();
Сообщить("Легковесный HTML-файл успешно сгенерирован: " + ПутьКФайлу);
КонецПроцедуры
Преимущества этого подхода очевидны: файл получается максимально компактным (его размер в несколько раз меньше файла, созданного через ТабличныйДокумент), стили вынесены в заголовок документа, а верстка полностью контролируется разработчиком и может быть адаптирована под дизайн любого веб-ресурса.
Для создания сложных веб-страниц со строгим соблюдением стандартов консорциума W3C ручная склейка строк может оказаться ненадежной (легко забыть закрыть тег или перепутать вложенность элементов). В платформе 1С реализован полноценный механизм работы с объектной моделью документа — DOM (Document Object Model). Мы можем программно конструировать элементы разметки, задавать им атрибуты и выстраивать дерево документа.
Рассмотрим, как сгенерировать HTML-документ с помощью объектов ДокументHTML, ЗаписьDOM и ЗаписьHTML:
Процедура ВыгрузитьВHTML_ЧерезDOM() Экспорт
// Создаем новый пустой HTML-документ
ДокументHTML = Новый ДокументHTML;
// Создаем корневой элемент html
ЭлементHTML = ДокументHTML.СоздатьЭлемент("html");
ДокументHTML.ДобавитьПодчиненный(ЭлементHTML);
// Создаем секцию head и настраиваем кодировку
ЭлементHead = ДокументHTML.СоздатьЭлемент("head");
ЭлементHTML.ДобавитьПодчиненный(ЭлементHead);
ЭлементMeta = ДокументHTML.СоздатьЭлемент("meta");
ЭлементMeta.УстановитьАтрибут("charset", "utf-8");
ЭлементHead.ДобавитьПодчиненный(ЭлементMeta);
ЭлементTitle = ДокументHTML.СоздатьЭлемент("title");
ЭлементTitle.ТекстовоеСодержимое = "Экспорт через DOM";
ЭлементHead.ДобавитьПодчиненный(ЭлементTitle);
// Создаем тело документа body
ЭлементBody = ДокументHTML.СоздатьЭлемент("body");
ЭлементHTML.ДобавитьПодчиненный(ЭлементBody);
// Создаем таблицу
ЭлементTable = ДокументHTML.СоздатьЭлемент("table");
ЭлементTable.УстановитьАтрибут("border", "1");
ЭлементTable.УстановитьАтрибут("style", "border-collapse: collapse; width: 50%;");
ЭлементBody.ДобавитьПодчиненный(ЭлементTable);
// Пример добавления строки заголовков
ЭлементTR_Head = ДокументHTML.СоздатьЭлемент("tr");
ЭлементTable.ДобавитьПодчиненный(ЭлементTR_Head);
ЭлементTH1 = ДокументHTML.СоздатьЭлемент("th");
ЭлементTH1.ТекстовоеСодержимое = "Товар";
ЭлементTR_Head.ДобавитьПодчиненный(ЭлементTH1);
ЭлементTH2 = ДокументHTML.СоздатьЭлемент("th");
ЭлементTH2.ТекстовоеСодержимое = "Остаток";
ЭлементTR_Head.ДобавитьПодчиненный(ЭлементTH2);
// Заполняем данными (для демонстрации добавим статичные строки)
Для Счетчик = 1 По 5 Цикл
ЭлементTR_Data = ДокументHTML.СоздатьЭлемент("tr");
ЭлементTable.ДобавитьПодчиненный(ЭлементTR_Data);
ЭлементTD_Name = ДокументHTML.СоздатьЭлемент("td");
ЭлементTD_Name.ТекстовоеСодержимое = "Товар тестовый №" + Счетчик;
ЭлементTR_Data.ДобавитьПодчиненный(ЭлементTD_Name);
ЭлементTD_Qty = ДокументHTML.СоздатьЭлемент("td");
ЭлементTD_Qty.ТекстовоеСодержимое = Строка(Счетчик * 10);
ЭлементTD_Qty.УстановитьАтрибут("style", "text-align: right;");
ЭлементTR_Data.ДобавитьПодчиненный(ЭлементTD_Qty);
КонецЦикла;
// Записываем сконструированный DOM-документ в файл
ПутьКФайлу = "D:\Temp\dom_export.html";
ЗаписьHTML = Новый ЗаписьHTML;
ЗаписьHTML.ОткрытьФайл(ПутьКФайлу, "UTF-8");
ЗаписьDOM = Новый ЗаписьDOM;
ЗаписьDOM.Записать(ДокументHTML, ЗаписьHTML);
ЗаписьHTML.Закрыть();
Сообщить("Документ HTML успешно создан через DOM в файле: " + ПутьКФайлу);
КонецПроцедуры
Этот метод исключает возникновение синтаксических ошибок в коде разметки, так как платформа сама следит за валидностью дерева DOM, автоматически закрывая все открытые теги и преобразуя спецсимволы в сущности HTML.
Частой проблемой при генерации веб-страниц является некорректное отображение русских символов. Браузер может пытаться открыть сохраненный файл в системной кодировке (например, Windows-1251 в русскоязычной ОС), в то время как сам файл сохранен в формате UTF-8 (или наоборот). Чтобы гарантировать стабильное отображение текста на любых устройствах, всегда следуйте двум правилам:
КодировкаТекста.UTF8 в методе Открыть() объекта ЗаписьТекста или в параметрах инициализации ЗаписьHTML.<head> вашего HTML-кода обязательно размещайте тег метаданных: <meta charset="UTF-8">. Это дает однозначное указание браузеру использовать Юникод при рендеринге страницы.Поскольку исходная задача автора темы включала автоматическую выгрузку полученного файла на FTP-сервер, рассмотрим, как связать процесс генерации и отправки в единый регламентный процесс. Для этого воспользуемся встроенным объектом платформы 1С — FTPСоединение.
Посмотрим на готовый сценарий автоматизации выгрузки прайс-листа:
Процедура ВыгрузитьФайлНаFTP(ЛокальныйПутьКФайлу, ИмяФайлаНаСервере)
// Параметры подключения к FTP-серверу
СерверFTP = "ftp.mysite.ru";
ПортFTP = 21;
ЛогинFTP = "ftp_user";
ПарольFTP = "StrongPassword123";
ПутьНаСервере = "/public_html/prices/";
Попытка
// Создаем соединение с сервером
СоединениеFTP = Новый FTPСоединение(СерверFTP, ПортFTP, ЛогинFTP, ПарольFTP, , Ложь);
// Переходим в нужный каталог на сервере
СоединениеFTP.УстановитьТекущийКаталог(ПутьНаСервере);
// Отправляем файл на сервер
СоединениеFTP.Записать(ЛокальныйПутьКФайлу, ИмяФайлаНаСервере);
ЗаписьЖурналаРегистрации("Выгрузка на FTP", УровеньЖурналаРегистрации.Информация, , ,
"Файл успешно загружен на FTP: " + ПутьНаСервере + ИмяФайлаНаСервере);
Исключение
// Обработка ошибок подключения и отправки
ИнформацияОбОшибке = ОписаниеОшибки();
ЗаписьЖурналаРегистрации("Выгрузка на FTP", УровеньЖурналаРегистрации.Ошибка, , ,
"Ошибка при работе с FTP: " + ИнформацияОбОшибке);
ВызватьИсключение "Не удалось отправить файл на FTP-сервер: " + ИнформацияОбОшибке;
КонецПопытки;
КонецПроцедуры
Объединяя методы генерации HTML и выгрузки по FTP, мы получаем законченное автоматизированное решение. Например, настроив регламентное задание в 1С, база данных сможет самостоятельно каждый час генерировать свежие остатки товаров в красивом и легковесном виде, а затем мгновенно отправлять полученный HTML-файл прямо на сайт компании без какого-либо участия человека.
Выбор конкретного метода генерации HTML зависит от ваших текущих задач: используйте ТабличныйДокумент для быстрой выгрузки внутренних отчетов с сохранением сложного форматирования (желательно в формате HTML5), либо ручную шаблонизацию через ЗаписьТекста для формирования компактных прайс-листов и каталогов для интеграции с веб-сайтами.