Объект ФорматированныйДокумент в платформе 1С:Предприятие предназначен для работы с форматированным текстом, содержащим различные шрифты, цвета, картинки и гиперссылки. Однако при попытке программно обойти его элементы, скопировать их в другой документ или собрать структуру вручную разработчики часто сталкиваются с непредсказуемым поведением. В частности, один и тот же текст может дробиться на разное количество элементов на разных компьютерах, а при добавлении некоторых из них возникает ошибка, и метод возвращает Неопределено.
В этой статье мы подробно разберем, почему возникают эти проблемы, как на это влияют версии платформы и движки рендеринга, а также рассмотрим надежные альтернативные способы работы с форматированным текстом без прямого обращения к коллекции элементов.
Разработчики часто замечают, что при копировании текста из внешних источников (например, MS Word или веб-страницы) и последующем сохранении в базу данных, структура документа ведет себя непредсказуемо. На одной платформе строка записывается как единый текстовый элемент, а на другой — дробится на множество мелких фрагментов (например, отделяя кавычки от текста).
Проанализируем ситуацию подробнее. Такое поведение напрямую связано с двумя факторами:
ТекстФорматированногоДокумента, оборачивая каждый символ или кавычку в отдельные невидимые контейнеры. Более новые движки оптимизируют разметку и объединяют такой текст в один элемент.Посмотрим, почему происходит сбой при программном переносе или заполнении элементов из хранилища значений. Типичный сценарий ошибки выглядит следующим образом:
НовыйЭлемент = ПриемникДокумент.Элементы.Добавить(ДобавляемыйЭлемент.Текст, Тип("ТекстФорматированногоДокумента"));
Если в процессе обхода коллекции исходного документа попадается элемент, текст которого пуст (равен ""), метод Добавить() возвращает значение Неопределено или вызывает критическую ошибку. Откуда же берутся эти пустые элементы?
При визуальном редактировании пользователем (вводе текста, удалении символов, переносах строк клавишей Enter) визуальный редактор HTML неявно создает пустые теги или невидимые контейнеры для удержания фокуса ввода или сохранения параметров шрифта в данной строке. В режиме предприятия пользователь видит пустую строку или пробел, но в XML/HTML-структуре документа физически существует элемент разметки. При попытке программно создать элемент с пустым текстом через коллекцию Элементы срабатывает внутренний контроль платформы, который запрещает инициализацию пустого текстового узла, что и приводит к ошибке.
Важный вывод: Программный обход коллекции Элементы и попытка ручной сборки документа поэлементно — это крайне нестабильный путь. Структура коллекции может спорадически меняться даже в рамках одного сеанса работы пользователя.
Поскольку прямое манипулирование коллекцией элементов не гарантирует стабильности, рассмотрим правильные архитектурные подходы, рекомендуемые экспертами 1С.
Вместо того чтобы разбирать документ по косточкам, гораздо эффективнее и безопаснее работать с ним как с единым текстом в формате HTML. Платформа берет на себя всю работу по корректному парсингу и генерации внутренней структуры элементов.
Если вам нужно модифицировать текст (например, вставить параметры или автотекст в шаблон письма), сделайте это на уровне обычной строки, а затем загрузите результат обратно в документ. Посмотрим на пример:
// Шаг 1. Получим HTML-представление и структуру вложений из исходного документа
ТекстHTML = "";
СтруктураВложений = Новый Структура;
ИсходныйДокумент.ПолучитьHTML(ТекстHTML, СтруктураВложений);
// Шаг 2. Произведем текстовую замену параметров в HTML-строке
ТекстHTML = СтрЗаменить(ТекстHTML, "[ИмяКлиента]", "Иван Иванович");
ТекстHTML = СтрЗаменить(ТекстHTML, "[НомерДоговора]", "ДГ-2023/15");
// Шаг 3. Загрузим модифицированный HTML обратно в документ-приемник
ДокументПриемник = Новый ФорматированныйДокумент;
ДокументПриемник.УстановитьHTML(ТекстHTML, СтруктураВложений);
Этот способ полностью решает проблему «битых» элементов, пустых строк и платформенных различий. Платформа 1С самостоятельно и без ошибок построит внутреннее дерево объектов из переданной HTML-строки.
Если ваша задача состоит в том, чтобы собрать новый документ программно из различных частей (например, добавить заголовок определенного цвета, затем вставить обычный текст и подпись), вместо элементов форматированного документа используйте объект ФорматированнаяСтрока.
Сформируем итоговый текст через массив элементов форматированной строки, а затем загрузим его в документ одной командой:
// Создадим массив для частей форматированной строки
МассивЧастей = Новый Массив;
// Добавим обычный текст
МассивЧастей.Добавить("Уважаемый ");
// Добавим выделенный текст (красный и жирный)
ШрифтВыделенный = Новый Шрифт(,, Истина); // Жирный шрифт
ВыделенныйТекст = Новый ФорматированнаяСтрока("Клиент", ШрифтВыделенный, WebЦвета.Красный);
МассивЧастей.Добавить(ВыделенныйТекст);
МассивЧастей.Добавить(", благодарим Вас за сотрудничество!");
// Объединяем все части в одну форматированную строку
ИтоговаяСтрока = Новый ФорматированнаяСтрока(МассивЧастей);
// Инициализируем документ и устанавливаем строку
НовыйДокумент = Новый ФорматированныйДокумент;
НовыйДокумент.УстановитьФорматированнуюСтроку(ИтоговаяСтрока);
При таком подходе исключены любые ошибки несовместимости типов, а код будет работать абсолютно одинаково на любых релизах платформы, в тонком, толстом или веб-клиенте.
В случаях, когда вам требуется очень сложная работа с текстом (например, создание таблиц, которые стандартный ФорматированныйДокумент не поддерживает в полной мере, или внедрение продвинутых CSS-стилей), разработчики рекомендуют отказаться от стандартного объекта в пользу элемента формы Поле HTML документа.
Связав это поле с современным JavaScript-редактором (например, TinyMCE или CKEditor), вы получите:
Таким образом, для простых задач форматирования лучшим выбором будет использование методов УстановитьHTML() и УстановитьФорматированнуюСтроку(), что полностью избавит вас от ошибок разбора элементов коллекции.