Как программно экспортировать данные из 1С в формат HTML без ошибок и кракозябр?

Программист 1С v8.3 (Обычные формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

В процессе интеграции 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);

Давайте подробно рассмотрим этот и другие способы экспорта данных.

Способ 1. Программное сохранение табличного документа через встроенные типы файлов

Использование объекта ТабличныйДокумент — это самый простой и быстрый способ получить готовый HTML-код, если у вас уже есть разработанный печатный макет в конфигураторе. Платформа берет на себя всю работу по отрисовке ячеек, объединению строк, настройке шрифтов и цветов.

Рассмотрим детально процедуру выгрузки остатков товаров на основе макета с явным указанием формата:


Процедура ВыгрузитьОстаткиВHTML_ТабДок() Экспорт

    // Инициализация табличного документа и получение макета
    ДокТаб = Новый ТабличныйДокумент;
    ДокТаб.ИмяПараметровПечати = "ПАРАМЕТРЫ_ПЕЧАТИ_ВЫГРУЗКИ";
    
    // Получаем макет обработки
    Макет = ПолучитьМакет("Анализ");
    ОбластьЗаписей = Макет.ПолучитьОбласть("ДетальныеЗаписи");
    
    // Формируем запрос к остаткам товаров на складах
    Запрос = Новый Запрос;
    Запрос.Текст = 
    "ВЫБРАТЬ
    |	Остатки.Номенклатура КАК Номенклатура,
    |	Остатки.Номенклатура.Артикул КАК Артикул,
    |	ЕСТЬNULL(Остатки.КоличествоОстаток, 0) КАК СвободныйОстаток
    |ИЗ
    |	РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаАнализа, Склад = &Склад) КАК Остатки
    |ГДЕ
    |	ЕСТЬNULL(Остатки.КоличествоОстаток, 0) > 0";
    
    Запрос.УстановитьПараметр("ДатаАнализа", КонецДня(ТекущаяДата()));
    Запрос.УстановитьПараметр("Склад", Справочники.Склады.НайтиПоКоду("00013"));
    
    Выборка = Запрос.Выполнить().Выбрать();
    
    // Заполняем табличный документ в цикле
    Пока Выборка.Следующий() Цикл
        ОбластьЗаписей.Параметры.Код = Выборка.Артикул;
        ОбластьЗаписей.Параметры.Товар = Выборка.Номенклатура.Наименование;
        ОбластьЗаписей.Параметры.Остаток = Выборка.СвободныйОстаток;
        ДокТаб.Вывести(ОбластьЗаписей);
    КонецЦикла;
    
    // Настраиваем параметры отображения перед выгрузкой
    ДокTab.ОтображатьСетку = Ложь;
    ДокТаб.ОтображатьЗаголовки = Ложь;
    ДокТаб.ТолькоПросмотр = Истина;
    
    // Записываем файл на диск с явным указанием формата HTML
    ПутьКФайлу = "D:\Temp\ostatki.html";
    ДокТаб.Записать(ПутьКФайлу, ТипФайлаТабличногоДокумента.HTML);
    
    Сообщить("Выгрузка успешно завершена в файл: " + ПутьКФайлу);

КонецПроцедуры

Обратите внимание на важную деталь при экспорте в HTML. В перечислении ТипФайлаТабличногоДокумента доступно несколько различных веб-стандартов:

  1. HTML — базовый формат. Платформа генерирует HTML-код, совместимый с большинством старых и современных браузеров. Если в табличном документе присутствуют картинки, логотипы компании или диаграммы, 1С создаст рядом с основным файлом папку с ресурсами (например, ostatki_files) и поместит графику туда. Это накладывает дополнительные сложности при последующей отправке по FTP, так как вам придется загружать не один файл, а весь каталог.
  2. HTML3 — устаревший стандарт, генерирующий максимально упрощенную разметку. Стоит использовать только в редких случаях интеграции с очень старыми информационными системами.
  3. HTML4 — стандарт, использующий каскадные таблицы стилей (CSS) для описания внешнего вида ячеек.
  4. HTML5 — наиболее прогрессивный и рекомендуемый вариант для современных систем. При выборе ТипФайлаТабличногоДокумента.HTML5 платформа упаковывает графические элементы и картинки непосредственно внутрь самого HTML-кода с использованием кодирования Base64 (тег img с источником данных data:image/png;base64...). На выходе вы получаете один полностью автономный файл, который содержит в себе и стили, и разметку, и картинки. Его крайне удобно отправлять по FTP или пересылать по электронной почте.

Способ 2. Ручная генерация HTML с использованием шаблонов (чистый код)

Несмотря на простоту использования табличного документа, у этого метода есть существенный недостаток — избыточность кода. Конвертер 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, чтобы не сломать верстку
        ОчищенноеНаименование = Выборка.Наименование;
        ОчищенноеНаименование = СтрЗаменить(ОчищенноеНаименование, "&", "&amp;");
        ОчищенноеНаименование = СтрЗаменить(ОчищенноеНаименование, "<", "&lt;");
        ОчищенноеНаименование = СтрЗаменить(ОчищенноеНаименование, ">", "&gt;");
        
        Строка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-файл успешно сгенерирован: " + ПутьКФайлу);

КонецПроцедуры

Преимущества этого подхода очевидны: файл получается максимально компактным (его размер в несколько раз меньше файла, созданного через ТабличныйДокумент), стили вынесены в заголовок документа, а верстка полностью контролируется разработчиком и может быть адаптирована под дизайн любого веб-ресурса.

Способ 3. Программная сборка HTML через объектную модель DOM

Для создания сложных веб-страниц со строгим соблюдением стандартов консорциума 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 (или наоборот). Чтобы гарантировать стабильное отображение текста на любых устройствах, всегда следуйте двум правилам:

Автоматическая отправка сгенерированного HTML на удаленный FTP-сервер

Поскольку исходная задача автора темы включала автоматическую выгрузку полученного файла на 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), либо ручную шаблонизацию через ЗаписьТекста для формирования компактных прайс-листов и каталогов для интеграции с веб-сайтами.

← На главную