Как решить проблемы с разбором и программным заполнением ФорматированногоДокумента в 1С?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Объект ФорматированныйДокумент в платформе 1С:Предприятие предназначен для работы с форматированным текстом, содержащим различные шрифты, цвета, картинки и гиперссылки. Однако при попытке программно обойти его элементы, скопировать их в другой документ или собрать структуру вручную разработчики часто сталкиваются с непредсказуемым поведением. В частности, один и тот же текст может дробиться на разное количество элементов на разных компьютерах, а при добавлении некоторых из них возникает ошибка, и метод возвращает Неопределено.

В этой статье мы подробно разберем, почему возникают эти проблемы, как на это влияют версии платформы и движки рендеринга, а также рассмотрим надежные альтернативные способы работы с форматированным текстом без прямого обращения к коллекции элементов.

Выясним причину: почему один и тот же текст дробится по-разному?

Разработчики часто замечают, что при копировании текста из внешних источников (например, MS Word или веб-страницы) и последующем сохранении в базу данных, структура документа ведет себя непредсказуемо. На одной платформе строка записывается как единый текстовый элемент, а на другой — дробится на множество мелких фрагментов (например, отделяя кавычки от текста).

Проанализируем ситуацию подробнее. Такое поведение напрямую связано с двумя факторами:

  1. Разные движки отображения HTML в платформе 1С: Исторически в платформе 1С (особенно в тонком клиенте под Windows) для работы с HTML и форматированными документами использовался системный движок Microsoft Internet Explorer (MSHTML). Начиная с более современных релизов (в частности, с 8.3.14), платформа начала постепенный переход на современный движок Chromium/WebKit. Если ваши базы запущены на разных релизах платформы, или если одна база открыта в тонком клиенте, а другая — в веб-клиенте под управлением другой операционной системы, парсинг одного и того же текста будет выполняться принципиально разными алгоритмами.
  2. Сложная разметка («грязный» HTML) из MS Word: При копировании текста из офисных приложений в буфер обмена попадает не просто чистый текст, а огромный объем служебных HTML-тегов, стилевых свойств и параметров форматирования. Внутренний парсер старых движков пытается сохранить все эти микро-стили (даже если визуально они незаметны) и разбивает единое слово на цепочку элементов ТекстФорматированногоДокумента, оборачивая каждый символ или кавычку в отдельные невидимые контейнеры. Более новые движки оптимизируют разметку и объединяют такой текст в один элемент.

Проанализируем ошибку НовыйЭлемент = Неопределено

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


НовыйЭлемент = ПриемникДокумент.Элементы.Добавить(ДобавляемыйЭлемент.Текст, Тип("ТекстФорматированногоДокумента"));

Если в процессе обхода коллекции исходного документа попадается элемент, текст которого пуст (равен ""), метод Добавить() возвращает значение Неопределено или вызывает критическую ошибку. Откуда же берутся эти пустые элементы?

При визуальном редактировании пользователем (вводе текста, удалении символов, переносах строк клавишей Enter) визуальный редактор HTML неявно создает пустые теги или невидимые контейнеры для удержания фокуса ввода или сохранения параметров шрифта в данной строке. В режиме предприятия пользователь видит пустую строку или пробел, но в XML/HTML-структуре документа физически существует элемент разметки. При попытке программно создать элемент с пустым текстом через коллекцию Элементы срабатывает внутренний контроль платформы, который запрещает инициализацию пустого текстового узла, что и приводит к ошибке.

Важный вывод: Программный обход коллекции Элементы и попытка ручной сборки документа поэлементно — это крайне нестабильный путь. Структура коллекции может спорадически меняться даже в рамках одного сеанса работы пользователя.

Разберем по шагам надежные способы работы с ФорматированнымДокументом

Поскольку прямое манипулирование коллекцией элементов не гарантирует стабильности, рассмотрим правильные архитектурные подходы, рекомендуемые экспертами 1С.

Способ 1: Работа через HTML-строку (Лучшая практика)

Вместо того чтобы разбирать документ по косточкам, гораздо эффективнее и безопаснее работать с ним как с единым текстом в формате HTML. Платформа берет на себя всю работу по корректному парсингу и генерации внутренней структуры элементов.

Если вам нужно модифицировать текст (например, вставить параметры или автотекст в шаблон письма), сделайте это на уровне обычной строки, а затем загрузите результат обратно в документ. Посмотрим на пример:


// Шаг 1. Получим HTML-представление и структуру вложений из исходного документа
ТекстHTML = "";
СтруктураВложений = Новый Структура;
ИсходныйДокумент.ПолучитьHTML(ТекстHTML, СтруктураВложений);

// Шаг 2. Произведем текстовую замену параметров в HTML-строке
ТекстHTML = СтрЗаменить(ТекстHTML, "[ИмяКлиента]", "Иван Иванович");
ТекстHTML = СтрЗаменить(ТекстHTML, "[НомерДоговора]", "ДГ-2023/15");

// Шаг 3. Загрузим модифицированный HTML обратно в документ-приемник
ДокументПриемник = Новый ФорматированныйДокумент;
ДокументПриемник.УстановитьHTML(ТекстHTML, СтруктураВложений);

Этот способ полностью решает проблему «битых» элементов, пустых строк и платформенных различий. Платформа 1С самостоятельно и без ошибок построит внутреннее дерево объектов из переданной HTML-строки.

Способ 2: Программное формирование через ФорматированнуюСтроку

Если ваша задача состоит в том, чтобы собрать новый документ программно из различных частей (например, добавить заголовок определенного цвета, затем вставить обычный текст и подпись), вместо элементов форматированного документа используйте объект ФорматированнаяСтрока.

Сформируем итоговый текст через массив элементов форматированной строки, а затем загрузим его в документ одной командой:


// Создадим массив для частей форматированной строки
МассивЧастей = Новый Массив;

// Добавим обычный текст
МассивЧастей.Добавить("Уважаемый ");

// Добавим выделенный текст (красный и жирный)
ШрифтВыделенный = Новый Шрифт(,, Истина); // Жирный шрифт
ВыделенныйТекст = Новый ФорматированнаяСтрока("Клиент", ШрифтВыделенный, WebЦвета.Красный);
МассивЧастей.Добавить(ВыделенныйТекст);

МассивЧастей.Добавить(", благодарим Вас за сотрудничество!");

// Объединяем все части в одну форматированную строку
ИтоговаяСтрока = Новый ФорматированнаяСтрока(МассивЧастей);

// Инициализируем документ и устанавливаем строку
НовыйДокумент = Новый ФорматированныйДокумент;
НовыйДокумент.УстановитьФорматированнуюСтроку(ИтоговаяСтрока);

При таком подходе исключены любые ошибки несовместимости типов, а код будет работать абсолютно одинаково на любых релизах платформы, в тонком, толстом или веб-клиенте.

Способ 3: Использование элемента формы "Поле HTML документа"

В случаях, когда вам требуется очень сложная работа с текстом (например, создание таблиц, которые стандартный ФорматированныйДокумент не поддерживает в полной мере, или внедрение продвинутых CSS-стилей), разработчики рекомендуют отказаться от стандартного объекта в пользу элемента формы Поле HTML документа.

Связав это поле с современным JavaScript-редактором (например, TinyMCE или CKEditor), вы получите:

Таким образом, для простых задач форматирования лучшим выбором будет использование методов УстановитьHTML() и УстановитьФорматированнуюСтроку(), что полностью избавит вас от ошибок разбора элементов коллекции.

← На главную