Шаблоны, поля и форматирование
- Модель шаблона
- Получить сохраненный шаблон и его поля
- Устройство полей шаблона
- Добавить плейсхолдеры в DOCX
- Форматировать значения
- Обработать пустые и обязательные поля
- Повторить блок для списка объектов
- Вставить изображение или печать
- Учесть региональные настройки
- Выбрать вариант таблицы товаров
- Проверить шаблон перед генерацией
- Связанные материалы
Шаблон задает структуру будущего документа и места для подстановки данных. Модуль находит в теле шаблона плейсхолдеры, сопоставляет их с полями провайдера и при генерации заменяет подготовленными значениями.
Используйте класс Bitrix\DocumentGenerator\Template, чтобы загрузить шаблон и получить его тело, поля и связанные провайдеры. Для создания документа передайте подготовленный объект шаблона в метод Document::createByTemplate(), как показано в статье Документы.
Модель шаблона
Объект Template хранит название, код, регион, идентификаторы модуля и исходного файла, класс тела и настройки полей. Основные свойства шаблона перечислены в таблице. Исходный файл хранится отдельно от остальных данных шаблона.
Обязательные свойства обозначены *.
|
Свойство |
Тип |
Назначение |
|
|
|
Идентификатор шаблона |
|
|
|
Название шаблона длиной от 1 до 100 символов |
|
|
|
Символьный код шаблона |
|
|
|
Идентификатор модуля, который зарегистрировал шаблон |
|
|
|
Идентификатор исходного файла в хранилище модуля |
|
|
|
Класс тела документа. Если загруженное значение отсутствует или не наследует |
|
|
|
Регион, по которому модуль выбирает язык и региональные настройки форматирования |
|
|
|
Управляет обработкой полей
Значение по умолчанию — |
|
|
|
Вариант табличной части: все позиции, только товары или только услуги. Значение по умолчанию — пустая строка |
Класс Body разбирает содержимое конкретного формата. Класс Body\Docx выполняет несколько действий:
-
обрабатывает основной документ, колонтитулы и другие части DOCX,
-
извлекает плейсхолдеры,
-
заменяет значения и изображения.
Получить сохраненный шаблон и его поля
Чтобы получить объект шаблона и его поля, сначала сохраните DOCX-шаблон в модуле генератора документов. Например, для CRM-шаблона откройте раздел CRM > Настройки > Настройки CRM > Другое > Шаблоны документов или перейдите по адресу /crm/documents/templates/. Нажмите Добавить шаблон, загрузите DOCX и выберите разделы CRM, в которых он будет доступен. После сохранения идентификатор шаблона появится в столбце ID списка шаблонов.
Шаблон также можно добавить через REST API методом documentgenerator.template.add. Такой шаблон относится к REST-приложению и использует REST-провайдер.
Чтобы получить сохраненный шаблон по идентификатору в коде, подключите модуль documentgenerator и вызовите метод Template::loadById(). Метод возвращает объект Template или null, если запись не найдена или идентификатор некорректен. Повторно загружать DOCX-файл не нужно.
Если поля зависят от основного провайдера, передайте его класс в setSourceType() до первого вызова getFields(). Объект шаблона кеширует рассчитанный список полей в памяти.
<?php
use Bitrix\DocumentGenerator\DataProvider;
use Bitrix\DocumentGenerator\Template;
use Bitrix\Main\Loader;
if (!Loader::includeModule('documentgenerator'))
{
throw new \RuntimeException('Модуль documentgenerator не установлен');
}
$templateId = 17;
/** @var class-string<DataProvider> $providerClass */
// Замените классом провайдера из вашего модуля
$providerClass = Acme\Documents\OrderDataProvider::class;
$template = Template::loadById($templateId);
if ($template === null)
{
throw new \RuntimeException('Шаблон не найден');
}
$template->setSourceType($providerClass);
if ($template->getSourceType() === null)
{
throw new \RuntimeException('Класс провайдера недоступен для шаблона');
}
$body = $template->getBody();
if ($body === null)
{
throw new \RuntimeException('Не удалось получить тело шаблона');
}
$placeholders = $body->getPlaceholders();
$fields = $template->getFields();
После выполнения кода переменные содержат:
-
$template— сохраненный шаблон по его идентификатору. -
$body— объект, который представляет содержимое DOCX. -
$placeholders— коды плейсхолдеров, найденные в теле DOCX. -
$fields— описания доступных полей основного и служебного провайдеров.
В $fields входят не только поля, которые использованы в DOCX, но и все поля, доступные для выбранного провайдера. Массив также содержит служебные поля DOCUMENT и SOURCE.
Выбрать основной провайдер
У шаблона может быть несколько доступных провайдеров. Метод getDataProviders() возвращает их классы:
$providerClasses = $template->getDataProviders(true);
При первом вызове передайте true, чтобы метод преобразовал сохраненные фильтры в имена классов. Метод сохраняет результат в объекте Template. Поэтому вызовите getDataProviders(true) раньше getDataProviders() без аргумента.
Выберите из полученного списка класс, который соответствует исходному объекту документа. Затем выполните два действия:
-
Передайте класс в метод
setSourceType()до вызоваgetFields(). -
Проверьте результат через
getSourceType(). Если класс не зарегистрирован вDataProviderManager, метод вернетnull.
Выбранный класс становится основным провайдером текущего документа. Через поле SOURCE документ получает данные исходного объекта. Служебный провайдер DOCUMENT использует тот же источник.
Связанные провайдеры хранятся в настройках шаблона. Не добавляйте эту связь напрямую через Model\TemplateProviderTable. Настраивайте область применения шаблона через штатный интерфейс модуля, а структуру собственного провайдера формируйте по правилам статьи Провайдеры данных.
Устройство полей шаблона
Ключ массива, который возвращает Template::getFields(), совпадает с кодом плейсхолдера. Описание поля определяет источник, тип представления и поведение при пустом значении.
|
Ключ |
Тип |
Назначение |
|
|
|
Понятное пользователю название поля |
|
|
|
Путь к значению в дереве провайдеров, скалярное значение или обработчик, который возвращает значение |
|
|
|
Один из типов |
|
|
|
Класс вложенного провайдера |
|
|
|
Имя класса провайдера, которое модуль проверяет перед использованием |
|
|
|
Признак обязательного значения: |
|
|
|
Признак удаления строки таблицы или абзаца: |
|
|
|
Дополнительные настройки поля и провайдера. Состав зависит от типа поля |
Шаблон выбирает описание каждого плейсхолдера по приоритету:
-
Настройка для конкретного шаблона.
-
Настройка для основного провайдера шаблона.
-
Общая настройка без шаблона и провайдера.
-
Описание поля, которое
DataProviderManagerполучил из основного или служебного провайдера.
Метод getFields() всегда добавляет два служебных корневых поля: SOURCE и DOCUMENT.
-
SOURCEоткрывает данные исходного объекта. -
DOCUMENTоткрывает дату создания, название и номер документа, а также исходный объект через вложенное полеSOURCE.
Не сохраняйте настройки полей напрямую через Model\FieldTable. Этот ORM-класс обслуживает внутреннее хранение. Формируйте структуру полей в провайдере или используйте интерфейс настройки шаблона.
Добавить плейсхолдеры в DOCX
Добавьте текстовые плейсхолдеры в DOCX самостоятельно и заключите каждый код в фигурные скобки. Код может содержать латинские буквы, цифры, точки, символы _ и -.
{DOCUMENT.DOCUMENT_NUMBER}
{DOCUMENT.DOCUMENT_CREATE_TIME}
{SOURCE.CLIENT.NAME}
Точка разделяет уровни провайдеров. Например, путь SOURCE.CLIENT.NAME последовательно обращается к полю CLIENT основного провайдера и полю NAME вложенного провайдера.
Word может сохранить один плейсхолдер несколькими фрагментами внутри DOCX. При загрузке шаблона модуль объединяет такие фрагменты. Если поле не определяется, заново введите весь плейсхолдер одним стилем и повторно загрузите файл.
Во время обработки модуль заменяет неизвестный плейсхолдер пустой строкой. До генерации проверьте, что для каждого кода из $body->getPlaceholders() есть ключ с таким же именем в $template->getFields(). Отсутствующий ключ указывает на опечатку в плейсхолдере или на недоступное поле провайдера.
Форматировать значения
Тип поля определяет класс, который превращает исходное значение в строку или специальный объект для тела документа. Модификатор после символа ~ изменяет формат только в текущем месте шаблона.
{DOCUMENT.DOCUMENT_CREATE_TIME~format=DD.MM.YYYY}
{SOURCE.CLIENT.NAME~letterCase=upper}
Правила записи параметров:
-
Разделяйте несколько параметров запятыми.
-
Используйте
YиNдля логических значений. -
Учитывайте, что доступный набор параметров зависит от класса
Value. -
Сохраняйте регистр в именах параметров. Например, используйте
CurId, а неcurid.
Регистр итоговой строки
После основного форматирования модуль преобразует результат через Value\PlaneString. Поэтому модификатор letterCase можно применить к итоговой строке любого поля, например к названию месяца в отформатированной дате. Для исходной строки или числа Value\PlaneString выполняет и основное преобразование.
Модификатор letterCase поддерживает три значения:
|
Значение |
Результат |
|
|
Нижний регистр |
|
|
Верхний регистр |
|
|
Верхний регистр для первых букв слов |
Массив или объект без класса Value и без строкового представления нельзя вставить как обычный текст. Опишите для такого поля подходящий тип или вложенный провайдер.
Дата и время
Тип DATE использует Value\DateTime. По умолчанию класс берет формат даты из региональных настроек текущего контекста генерации. Параметр format переопределяет его для одного плейсхолдера.
{DOCUMENT.DOCUMENT_CREATE_TIME~format=DD.MM.YYYY}
Класс принимает объект Bitrix\Main\Type\Date, дату и время или строку, которую может разобрать Framework. Если строку преобразовать не удалось, результат будет пустым.
Имя
Тип NAME использует Value\Name. Исходное значение должно быть массивом с частями имени: TITLE, NAME, SECOND_NAME, LAST_NAME и при необходимости GENDER.
Параметр format задает порядок частей имени. Без него модуль использует формат имен из региональных настроек. В строке формата доступны подстановки:
-
#TITLE#— обращение, -
#NAME#— имя, -
#LAST_NAME#— фамилия, -
#SECOND_NAME#— отчество, -
#NAME_SHORT#— первая буква имени и точка, -
#LAST_NAME_SHORT#— первая буква фамилии и точка, -
#SECOND_NAME_SHORT#— первая буква отчества и точка.
Параметр case изменяет падеж русскоязычного имени:
|
Значение |
Падеж |
|
|
Именительный |
|
|
Родительный |
|
|
Дательный |
|
|
Винительный |
|
|
Творительный |
|
|
Предложный |
Класс изменяет падеж, если непустые части имени содержат только русские буквы, пробелы и дефисы. Пол задает элемент GENDER со значением F или M. Если элемент не задан, класс пытается определить пол по отчеству. Когда пол определить нельзя, части имени остаются в исходном падеже.
{SOURCE.CONTACT.NAME~format=#LAST_NAME# #NAME_SHORT# #SECOND_NAME_SHORT#,case=1}
Имена параметров Format и Case с заглавной буквы работают как псевдонимы для format и case.
Телефон
Тип PHONE использует Value\PhoneNumber. Класс разбирает исходную строку через Bitrix\Main\PhoneNumber\Parser и по умолчанию возвращает номер в международном формате.
Параметр format принимает одно из значений класса Bitrix\Main\PhoneNumber\Format:
-
E.164— формат E.164, например+74951234567. -
International— международный формат с разделителями. -
National— национальный формат.
Значение по умолчанию — International.
Множественные значения
Для списка простых значений DataProviderManager создает Value\Multiple. По умолчанию класс объединяет непустые элементы через запятую и пробел.
|
Модификатор |
Значение |
Результат |
|
|
|
Разделяет элементы запятой и пробелом |
|
|
|
Разделяет элементы переводом строки |
|
|
|
Выводит только первый непустой элемент |
{SOURCE.CONTACT.PHONES~mseparator=2}
{SOURCE.CONTACT.EMAILS~mfirst=Y}
Остальные модификаторы применяются к каждому элементу списка. Массивы и объекты без подходящего типа класс пропускает.
Элемент списка провайдеров
Если часть пути возвращает ArrayDataProvider, модуль по умолчанию берет поле первого элемента. Параметр index выбирает элемент по индексу. Нумерация начинается с нуля.
{SOURCE.PRODUCTS.NAME~index=0}
{SOURCE.PRODUCTS.NAME~index=1}
Первый плейсхолдер выведет название первого товара, второй — второго. Если элемента с заданным индексом нет, модуль подставит пустую строку.
Адрес CRM
Поля класса Bitrix\Crm\Integration\DocumentGenerator\Value\Address поддерживают модификаторы формата, разделителя и типа адреса. Модификаторы влияют на значение в виде массива. Строковый адрес класс возвращает без изменений.
|
Модификатор |
Значение |
Результат |
|
|
|
Европейский формат |
|
|
|
Формат Великобритании |
|
|
|
Формат США |
|
|
|
Российский формат |
|
|
|
Российский формат |
|
|
|
Формат Узбекистана |
|
|
|
Запятая и пробел |
|
|
|
Перевод строки |
|
|
|
HTML-разделитель |
|
|
|
Добавляет тип адреса в скобках, если он заполнен |
Без модификатора Format класс выбирает формат по региональным настройкам контекста генерации. Разделитель по умолчанию — запятая и пробел.
{SOURCE.CLIENT.ADDRESS~Format=4,Separator=2,ShowType=Y}
Деньги CRM
Поля класса Bitrix\Crm\Integration\DocumentGenerator\Value\Money по умолчанию используют базовую валюту CRM.
|
Модификатор |
Значение |
Результат |
|
|
Код валюты |
Форматирует сумму в выбранной валюте |
|
|
|
Сохраняет незначащие нули дробной части |
|
|
|
Не добавляет обозначение валюты |
|
|
|
Преобразует сумму в слова, если доступна функция |
Если преобразование в слова недоступно или вернуло пустой результат, класс форматирует сумму числом.
{SOURCE.OPPORTUNITY~WZ=Y,NS=Y}
{SOURCE.OPPORTUNITY~CurId=RUB,W=Y}
Обработать пустые и обязательные поля
Результат для пустого значения зависит от настройки и типа поля.
|
Условие |
Результат |
|
Плейсхолдер отсутствует в рассчитанных значениях |
|
|
Значение текстового плейсхолдера равно |
В документ попадает пустая строка |
|
Поле имеет |
|
|
Множественное поле не содержит подходящих элементов |
|
|
Поле типа |
|
|
Изображение, печать или множественное поле содержит |
|
Проверьте обязательные значения без сохранения файла. Передайте в Document::createByTemplate() идентификатор или объект того типа, который ожидает основной провайдер.
use Bitrix\DocumentGenerator\Document;
$sourceId = 25;
// Замените идентификатором или объектом того типа, который ожидает провайдер
$document = Document::createByTemplate($template, $sourceId);
if ($document === null)
{
throw new \RuntimeException('Не удалось создать объект документа');
}
$emptyRequiredFields = $document->checkFields();
foreach ($emptyRequiredFields as $placeholder => $field)
{
$title = $field['TITLE'] ?? $placeholder;
echo $placeholder . ': ' . $title . PHP_EOL;
}
Пустой массив $emptyRequiredFields означает, что метод не нашел пропущенных обязательных значений. После проверки выполните пробную генерацию. Порядок сохранения файла и обработки объекта Result описан в разделе «Создать и сохранить документ» статьи Документы.
Повторить блок для списка объектов
Для множественного провайдера можно повторить несколько абзацев или строк таблицы. Поместите начало и конец блока в отдельные плейсхолдеры с общим кодом списка.
{SOURCE.PRODUCTS.BLOCK_START}
{SOURCE.PRODUCTS.NAME} — {SOURCE.PRODUCTS.PRICE}
{SOURCE.PRODUCTS.BLOCK_END}
При обработке модуль копирует содержимое между маркерами для каждого элемента ArrayDataProvider, заменяет вложенные поля и удаляет исходные маркеры. Маркеры должны относиться к тому же множественному полю, что и плейсхолдеры внутри блока.
Размещайте начало и конец блока не дальше 20 соседних абзацев или других XML-узлов друг от друга. Если конец не найден в этом диапазоне, модуль не создает повторяемый блок.
Для таблицы разместите поля одного элемента в одной строке между маркерами. Если список пуст, модуль удалит исходный повторяемый фрагмент.
Не вкладывайте блок одного множественного провайдера в другой без отдельной проверки результата. Порядок обхода и структура XML могут дать лишние или потерянные строки.
Вставить изображение или печать
Для типов IMAGE и STAMP одного текстового плейсхолдера недостаточно. Добавьте в DOCX изображение-заглушку и запишите плейсхолдер в альтернативный текст или имя этого изображения. Класс Body\Docx найдет такую фигуру и заменит связанный файл, сохранив размещение изображения в документе.
Если значение изображения пустое, модуль удаляет фигуру из результата. Настройка поля HIDE_ROW=Y дополнительно удаляет строку таблицы, а если строки нет — ближайший абзац.
Поле STAMP обрабатывается как изображение, но зависит от настройки шаблона WITH_STAMPS. При значении N документ передает для всех полей STAMP внутренний маркер — строку из одного пробела. Класс Body\Docx удаляет изображение с таким значением, но HIDE_ROW не удаляет содержащую его строку или абзац. При значении Y модуль использует данные провайдера.
Учесть региональные настройки
Свойство шаблона REGION участвует в создании контекста генерации. Класс DataProviderManager выбирает по нему язык региональных фраз и настройки форматов дат и имен.
Если настройки для региона недоступны, модуль берет их из текущего контекста приложения. Поэтому одинаковые исходные данные одного шаблона могут иметь разный формат в разных окружениях.
Перед генерацией задайте регион в настройках шаблона. Добавляйте модификатор поля только тогда, когда его формат должен отличаться от регионального.
Выбрать вариант таблицы товаров
Настройка PRODUCTS_TABLE_VARIANT передается из шаблона в создаваемый документ. Она принимает одно из трех значений:
|
Значение |
Результат |
|
Пустая строка |
Все позиции |
|
|
Только товары |
|
|
Только услуги |
Настройка влияет на данные, которые предоставляет интеграционный провайдер товаров. Сам Body\Docx не определяет, является ли позиция товаром или услугой. Если собственный провайдер не учитывает вариант, фильтрацию нужно реализовать в нем.
Проверить шаблон перед генерацией
Проверьте шаблон перед созданием документа с помощью Document::createByTemplate().
-
Проверьте права пользователя на настройку шаблона и чтение исходного объекта: метод
Template::loadById()эти права не проверяет. Подробнее читайте в статье Права доступа. -
Убедитесь, что
Template::loadById()вернул объект. -
Проверьте, что
getSourceType()возвращает ожидаемый класс основного провайдера. -
Убедитесь, что
getBody()вернул объект, а тело поддерживает обработку файла. -
Проверьте, что каждый код из
getPlaceholders()имеет описание вgetFields(). -
Убедитесь, что обязательные поля имеют источник данных.
-
Проверьте, что плейсхолдеры изображений находятся в имени или альтернативном тексте фигур.
-
Убедитесь, что маркеры повторяемого блока имеют одинаковый префикс и расположены рядом.
-
Проверьте, что регион и вариант таблицы товаров соответствуют сценарию документа.
-
Создайте пробный документ и обработайте ошибки объекта
Result, которые могут возникнуть при проверке обязательных значений и обработке DOCX. Подробнее об этом читайте в статье Документы.
Связанные материалы
-
Схема работы генератора документов и основные объекты — место шаблона и полей в процессе генерации.
-
Провайдеры данных — источники значений и дерево составных полей.
-
Документы — создание документа по подготовленному шаблону.
-
Права доступа — проверка доступности шаблона для пользователя.