Пример для схемы Таблица внутри повторяющихся блоков
|
---|
Загрузите шаблон с помощью метода documentgenerator.template.add. После этого можете создать
документ
Пример содержимого шаблона (Скачать пример): // Описание значений values 'values' => [ 'Title' => 'Welcome to my template', 'Description' => '<b>Description is here</b>', 'Picture' => null, // you can put here link to an image 'Events' => [ [ 'Title' => 'Automation', 'Description' => 'Some description of the automation event', 'SpeakerName' => '{Event1SpeakersSpeakerName}', 'SpeakerCompany' => '{Event1SpeakersSpeakerCompany}', 'SpeakerPosition' => '{Event1SpeakersSpeakerPosition}', ], [ 'Title' => 'Documents', 'Description' => 'This event is about document procession', 'SpeakerName' => '{Event2SpeakersSpeakerName}', 'SpeakerCompany' => '{Event2SpeakersSpeakerCompany}', 'SpeakerPosition' => '{Event2SpeakersSpeakerPosition}', ], ], 'EventsEventTitle' => 'Events.Event.Title', 'EventsEventDescription' => 'Events.Event.Description', 'EventsEventSpeakerName' => 'Events.Event.SpeakerName', 'EventsEventSpeakerCompany' => 'Events.Event.SpeakerCompany', 'EventsEventSpeakerPosition' => 'Events.Event.SpeakerPosition', 'Event1SpeakersSpeakerName' => 'Event1Speakers.Speaker.Name', 'Event1SpeakersSpeakerCompany' => 'Event1Speakers.Speaker.Company', 'Event1SpeakersSpeakerPosition' => 'Event1Speakers.Speaker.Position', 'Event1Speakers' => [ [ 'Name' => 'Ivan Petrov', 'Company' => 'Cool Ltd.', 'Position' => 'Core developer', ], [ 'Name' => 'Igor Milov', 'Company' => 'Cool Ltd.', 'Position' => 'Product Manager', ], ], 'Event2Speakers' => [ [ 'Name' => 'Sergey Ivanov', 'Company' => 'Devils corp.', 'Position' => 'Chief', ], ], 'Event2SpeakersSpeakerName' => 'Event2Speakers.Speaker.Name', 'Event2SpeakersSpeakerCompany' => 'Event2Speakers.Speaker.Company', 'Event2SpeakersSpeakerPosition' => 'Event2Speakers.Speaker.Position', ] // Описание полей fields 'fields' => [ 'Events' => [ 'PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider', 'OPTIONS' => [ 'ITEM_NAME' => 'Event', 'ITEM_PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider', ], ], 'Event1Speakers' => [ 'PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider', 'OPTIONS' => [ 'ITEM_NAME' => 'Speaker', 'ITEM_PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider', ], ], 'Event2Speakers' => [ 'PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider', 'OPTIONS' => [ 'ITEM_NAME' => 'Speaker', 'ITEM_PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider', ], ], 'Event1SpeakersSpeakerName' => ['TITLE' => 'Event1SpeakersSpeakerName'], 'Event1SpeakersSpeakerCompany' => ['TITLE' => 'Event1SpeakersSpeakerCompany'], 'Event1SpeakersSpeakerPosition' => ['TITLE' => 'Event1SpeakersSpeakerPosition'], 'Event2SpeakersSpeakerName' => ['TITLE' => 'Event2SpeakersSpeakerName'], 'Event2SpeakersSpeakerCompany' => ['TITLE' => 'Event2SpeakersSpeakerCompany'], 'Event2SpeakersSpeakerPosition' => ['TITLE' => 'Event2SpeakersSpeakerPosition'], |
Примеры генерации документа
Здесь изложен полностью процесс генерации документа. Все примеры написаны на php через веб-хук.
Создание нумератора
Для начала создадим новый нумератор для реста с помощью documentgenerator.numerator.add
.
\Bitrix\Main\Loader::includeModule('rest'); $client = new \Bitrix\Main\Web\HttpClient(); $webHookUrl = 'http://mycrm.bitrix24.com/rest/1/webhookkey/'; $prefix = 'documentgenerator'; $data = [ 'fields' => [ 'name' => 'Rest Numerator', 'template' => '{NUMBER}', 'settings' => [ 'Bitrix_Main_Numerator_Generator_SequentNumberGenerator' => [ 'start' => '0', 'step' => '1', ], ], ], ]; $url = $webHookUrl.$prefix.'.numerator.add/'; $answer = $client->post($url, $data); try { $result = \Bitrix\Main\Web\Json::decode($answer); } catch(Exception $e) { var_dump($answer); } print_r($result);
Ответ
[result] => Array ( [numerator] => Array ( [name] => new rest numerator [template] => {NUMBER} [id] => 68 [settings] => Array ( [Bitrix_Main_Numerator_Generator_SequentNumberGenerator] => Array ( [start] => 0 [step] => 1 [periodicBy] => [timezone] => [isDirectNumeration] => ) ) ) )
Из ответа получаем id
нумератора и можем дальше его использовать.
Загрузка шаблона
Сначала необходимо загрузить шаблон. Весь код как в предыдущем примере, но другие входные данные и название метода:
documentgenerator.template.add
$data = [ 'fields' => [ 'name' => 'Rest Template', 'file' => base64_encode(file_get_contents($_SERVER['DOCUMENT_ROOT'].'/upload/rest_template.docx')), 'numeratorId' => 1, 'region' => 'ru', 'users' => ['UA'], 'providers' => ['Bitrix\\DocumentGenerator\\DataProvider\\Rest'], ], ]; $url = $webHookUrl.$prefix.'.template.add/';
Ответ
[result] => Array ( [template] => Array ( [id] => 203 [name] => Rest Template [region] => ru [code] => [download] => http://mycrm.bitrix24.com/bitrix/services/main/ajax.php?action=documentgenerator.template.download&id=203&ts=1539173306 [active] => Y [moduleId] => rest [numeratorId] => 1 [withStamps] => N [providers] => Array ( [bitrix\documentgenerator\dataprovider\rest] => bitrix\documentgenerator\dataprovider\rest ) [users] => Array ( [UA] => UA ) [isDeleted] => N [sort] => 500 [createTime] => 2018-10-10T14:08:26+02:00 [updateTime] => 2018-10-10T14:08:26+02:00 [downloadMachine] => http://mycrm.bitrix24.com/rest/1/webhookkey/documentgenerator.template.download/?token=documentgenerator%7CYWN0a // тут длинная ссылка ) )
Список полей
Проверим, что поля шаблона распознались правильно. Выполним метод documentgenerator.template.getfields
:
$data = [ 'id' => 203, 'providerClassName' => '\\Bitrix\\DocumentGenerator\\DataProvider\\Rest', 'value' => 1, ]; $url = $webHookUrl.$prefix.'.template.getfields/';
Ответ
[result] => Array ( [templateFields] => Array ( [DocumentNumber] => Array ( [title] => Номер [value] => 1 [group] => Array ( [0] => Документ ) [default] => 1 ) [SomeDate] => Array ( [value] => [default] => ) [SomeName] => Array ( [value] => [default] => ) [Stamp] => Array ( [value] => [default] => ) [Image] => Array ( [value] => [default] => ) [TableItemImage] => Array ( [value] => [default] => ) [TableItemName] => Array ( [value] => [default] => ) [TableItemPrice] => Array ( [value] => [default] => ) [TableIndex] => Array ( [value] => [default] => ) ) )
Как видим, все поля документа на месте.
Генерация простого документа
Если в документ необходимо вставить только простые текстовые данные, то надо в метод documentgenerator.document.add
передать только массив values
с текстовыми значениями:
$data = [ 'templateId' => 203, 'providerClassName' => 'Bitrix\\DocumentGenerator\\DataProvider\\Rest', 'value' => 1, 'values' => [ 'SomeDate' => '14.02.2018', 'SomeName' => 'Горелкин Владислав', ], ]; $url = $webHookUrl.$prefix.'.document.add/';
Но это самый простой случай. Теперь рассмотрим вариант, когда нам надо вставить картинки, печать, использовать модификатор для даты и имени, и заполнить таблицу несколькими значениями
Генерация документа с изображениями и печатями
Чтобы в документ передать сложные данные, не только в строковом формате, необходимо правильно сформировать параметр fields
. Для начала, заполним изображение и печать.
$data = [ 'templateId' => 203, 'providerClassName' => 'Bitrix\\DocumentGenerator\\DataProvider\\Rest', 'value' => 1, 'values' => [ 'SomeDate' => '14.02.2018', 'SomeName' => 'Горелкин Владислав', 'Stamp' => 'http://myrestapp.com/upload/stamp.png', // внешний путь к файлу печати 'Image' => 'http://myrestapp.com/upload/image.jpg', // внешний путь к файлу изображения ], 'fields' => [ 'Stamp' => ['TYPE' => 'STAMP'], // тип поля - печать 'Image' => ['TYPE' => 'IMAGE'], // тип поля - изображение ] ]; $url = $webHookUrl.$prefix.'.document.add/';
В массиве fields
можно указать тип поля, по ключу TYPE
.
- Для полей "Изображение" тип -
STAMP
- Для полей "Печать или подпись" тип -
IMAGE
В массиве values
в качестве значений необходимо указать абсолютный путь к файлу. Файл будет скачан по этому адресу и вставлен в документ.
Генерация документа с модификаторами даты и имени
Про сами модификаторы можно почитать здесь.
Использование модификаторов для дат и имён через REST не обязательно - входные данные могут быть заранее отформатированы самим приложением. Тем не менее, это может быть удобно. Поэтому в REST есть возможность использовать модификаторы. Для этого необходимо передать соответствующий тип поля в fields
. Также в fields
по ключу FORMAT
можно передать формат по умолчанию. Если в самом шаблоне у этого поля будет указан модификатор - будет применен модификатор шаблона.
Чтобы модификаторы работали для полей типа дата, необходимо передать их в следующем виде:
- в
values
дата должна быть передана в формате atom (как во всех rest-методах) - в
fields
TYPE
=DATE
- также в
fields
по ключуFORMAT['format']
можно передать модификатор по умолчанию (также, как в шаблоне)
Чтобы модификаторы работали для полей типа имя необходимо передать их в следующем виде:
- в
values
имя должно быть передано в виде массива
[ 'NAME' => 'Игорь', // имя 'LAST_NAME' => 'Иванов', // фамилия 'SECOND_NAME' => 'Петрович', // отчество 'GENDER' => 'M', // пол ]
По ключу GENDER
можно указать пол в явном виде (M
- мужской, F
- женский). Если пол не указан, то модуль попытается определить его по отчеству. Если отчество не указано - пол не будет определен и склонение не будет работать.
- в
fields
TYPE
=NAME
- в
fields
по ключуFORMAT['format']
можно передать формат по умолчанию - в
fields
по ключуFORMAT['case']
можно передать падеж по умолчанию
$data = [ 'templateId' => 203, 'providerClassName' => 'Bitrix\\DocumentGenerator\\DataProvider\\Rest', 'value' => 1, 'values' => [ 'SomeDate' => '2018-10-10T14:30:18+02:00', // значение передано в формате atom 'SomeName' => [ // имя передано в виде массива 'NAME' => 'Владислав', 'LAST_NAME' => 'Горелкин', 'GENDER' => 'M', ], ], 'fields' => [ 'SomeDate' => [ 'TYPE' => 'DATE', 'FORMAT' => [ 'format' => 'd f Y H:i', // формат вывода ], ], // тип поля - дата 'SomeName' => [ 'TYPE' => 'NAME', 'FORMAT' => [ // здесь можно передать формат поля по умолчанию 'case' => 0, // код падежа 'format' => '#NAME# #LAST_NAME#' // формат вывода ] ], // тип поля - имя ] ]; $url = $webHookUrl.$prefix.'.document.add/';
Генерация документа с данными в виде массива
В нашем тестовом шаблоне есть таблица, куда надо вставить картинку, название и цену товара. Модификаторы для цен нельзя использовать в ресте генератора документов, поэтому цену придётся передавать в виде сформированной строки.
Ниже рабочий пример кода, после него подробности.
$data = [ 'templateId' => 203, 'providerClassName' => '\\Bitrix\\DocumentGenerator\\DataProvider\\Rest', 'value' => 1, 'values' => [ 'Table' => [ [ 'Name' => 'Item name 1', 'Price' => '$111.23', 'Image' => 'http://myrestapp.com/upload/stamp.png' ], [ 'Name' => 'Item name 2', 'Price' => '$222.34', 'Image' => 'http://myrestapp.com/upload/stamp.png' ], ], 'TableItemName' => 'Table.Item.Name', 'TableItemImage' => 'Table.Item.Image', 'TableItemPrice' => 'Table.Item.Price', 'TableIndex' => 'Table.INDEX', ], 'fields' => [ 'Table' => [ 'PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider', 'OPTIONS' => [ 'ITEM_NAME' => 'Item', 'ITEM_PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider', ], ], 'TableItemImage' => ['TYPE' => 'IMAGE'], ], ]; $url = $webHookUrl.$prefix.'.document.add/';
Напоминаем, что в шаблон вставлена таблица, в таблице три поля {TableItemName}, {TableItemImage}, {TableItemPrice}. Для начала посмотрим, как заполняется массив полей fields
.
- Передаем настройки поля
Table
. Такого поля в явном виде нет в шаблоне, но оно нам нужно, чтобы передать по этому ключу массив значений для таблицы. - Для этого поля нужно обязательно указать провайдера
fields['Table']['PROVIDER'] = 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider'
. Таким образом мы указываем, что по этому ключу придёт массив значений. - Надо заполнить массив настроек провайдера.
fields['Table']['OPTIONS']['ITEM_NAME'] = 'Item'
. Здесь мы передали внутренний ключ, по которому провайдер будет обращаться к элементам массива. fields['Table']['OPTIONS']['ITEM_PROVIDER'] = 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider'
- здесь указывается, что каждый элемент массива поляTable
по ключуItem
- это простой хеш.- Указываем, что поле
TableItemImage
является изображением - здесь всё как обычно.
Теперь про массив values
.
- По ключу
Table
передаем простой массив (с индексными последовательными ключами). Каждый элемент массива - это ассоциативный массив, где ключ - это правая часть поля, за исключениемTable
(название поля-массива) иItem
(название внутреннего ключа). - В качестве значения для самих полей таблицы передаем цепочку получения значения из провайдера. Строится она как последовательные коды провайдеров, разделенные точкой. В нашем случае это будет
Table
- название поля-массива, откуда получаются значения. Потом точка. ДальшеItem
- название внутреннего ключа провайдераTable
, по которому провайдер отдает элементы массива. Потом точка. Дальше идёт ключ внутреннего ассоциативного массива из элементовTable
. - У провайдера
ArrayDataProvider
есть внутренняя переменнаяINDEX
, которая указывает на текущий номер элемента (начиная с 1). Чтобы в поле {TableIndex} внутри таблицы подставился порядковый номер, было указаноvalues['TableIndex'] = 'Table.INDEX'
.
Если указать в качестве значения поля обычную строку, то она вставится в таблицу как есть во все строки.
Копирование таблиц
Начиная с версии 18.7.200 модуля documentgenerator появилась возможность создавать документы с вложенными списками, т.е. когда одно из значений списка первого уровня - это ещё один список (Внимание: работает только через REST и PHP API, через интерфейс такое не сделать).
Это может быть полезно, когда необходимо вставить несколько таблиц одинаковой структуры, но с разным количеством строк.
Основная идея заключается в том, что список первого уровня должен в качестве значений отдавать названия полей для внутренних списков. Все описания и значения полей должны быть переданы сразу. В массиве полей внешний список должен идти первым (т.к. поля обрабатываются в том же порядке, в котором они переданы в описании)
Этот способ можно использовать в схеме Таблица внутри повторяющихся блоков или Повторяющиеся блоки внутри повторяющихся блоков, но нельзя вставить таблицу внутри таблицы.
Пример для схемы Повторяющиеся блоки внутри повторяющихся блоков
|
---|
Загрузите шаблон с помощью метода documentgenerator.template.add. После этого можете создать
документ
Пример содержимого шаблона (Скачать пример): <?php require_once($_SERVER['DOCUMENT_ROOT'].'/rest_test/rest.php'); $templateId = 58; $entityTypeId = 2; $entityid = 28; $action = new RestAction('document', 'add'); $action->setPrefix('crm.documentgenerator'); $data = [ 'templateId' => $templateId, 'entityTypeId' => $entityTypeId, 'entityId' => $entityid, 'values' => [ 'Title' => 'Welcome to my template', 'Description' => '<b>Description is here</b>', 'Picture' => null, // you can put here link to an image 'Events' => [ [ 'Title' => 'Automation', 'Description' => 'Some description of the automation event', 'SpeakerName' => '{Event1SpeakersSpeakerName}', 'BlockStart' => '{Event1Speakers.BLOCK_START}', 'BlockEnd' => '{Event1Speakers.BLOCK_END}', 'SpeakerCompany' => '{Event1SpeakersSpeakerCompany}', 'SpeakerPosition' => '{Event1SpeakersSpeakerPosition}', ], [ 'Title' => 'Documents', 'Description' => 'This event is about document procession', 'BlockStart' => '{Event2Speakers.BLOCK_START}', 'BlockEnd' => '{Event2Speakers.BLOCK_END}', 'SpeakerName' => '{Event2SpeakersSpeakerName}', 'SpeakerCompany' => '{Event2SpeakersSpeakerCompany}', 'SpeakerPosition' => '{Event2SpeakersSpeakerPosition}', ], ], // 'Events' => [ // [ // 'Title' => 'Automation', // 'Description' => 'Some description of the automation event', // 'SpeakerName' => '__Event1SpeakersSpeakerName__', // 'BlockStart' => '__Event1Speakers.BLOCK_START__', // 'BlockEnd' => '__Event1Speakers.BLOCK_END__', // 'SpeakerCompany' => '__Event1SpeakersSpeakerCompany__', // 'SpeakerPosition' => '__Event1SpeakersSpeakerPosition__', // ], // [ // 'Title' => 'Documents', // 'Description' => 'This event is about document procession', // 'BlockStart' => '__Event2Speakers.BLOCK_START__', // 'BlockEnd' => '__Event2Speakers.BLOCK_END__', // 'SpeakerName' => '__Event2SpeakersSpeakerName__', // 'SpeakerCompany' => '__Event2SpeakersSpeakerCompany__', // 'SpeakerPosition' => '__Event2SpeakersSpeakerPosition__', // ], //], 'EventsEventTitle' => 'Events.Event.Title', 'EventsEventDescription' => 'Events.Event.Description', 'EventsEventSpeakerName' => 'Events.Event.SpeakerName', 'EventsEventBlockStart' => 'Events.Event.BlockStart', 'EventsEventBlockEnd' => 'Events.Event.BlockEnd', 'EventsEventSpeakerCompany' => 'Events.Event.SpeakerCompany', 'EventsEventSpeakerPosition' => 'Events.Event.SpeakerPosition', 'Event1SpeakersSpeakerName' => 'Event1Speakers.Speaker.Name', 'Event1SpeakersSpeakerCompany' => 'Event1Speakers.Speaker.Company', 'Event1SpeakersSpeakerPosition' => 'Event1Speakers.Speaker.Position', 'Event1Speakers' => [ [ 'Name' => 'Ivan Petrov', 'Company' => 'Cool Ltd.', 'Position' => 'Core developer', ], [ 'Name' => 'Igor Milov', 'Company' => 'Cool Ltd.', 'Position' => 'Product Manager', ], ], 'Event2Speakers' => [ [ 'Name' => 'Sergey Ivanov', 'Company' => 'Devils corp.', 'Position' => 'Chief', ], ], 'Event2SpeakersSpeakerName' => 'Event2Speakers.Speaker.Name', 'Event2SpeakersSpeakerCompany' => 'Event2Speakers.Speaker.Company', 'Event2SpeakersSpeakerPosition' => 'Event2Speakers.Speaker.Position', ], 'fields' => [ 'Events' => [ 'PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider', 'OPTIONS' => [ 'ITEM_NAME' => 'Event', 'ITEM_PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider', ], ], 'Event1Speakers' => [ 'PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider', 'OPTIONS' => [ 'ITEM_NAME' => 'Speaker', 'ITEM_PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider', ], ], 'Event2Speakers' => [ 'PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\ArrayDataProvider', 'OPTIONS' => [ 'ITEM_NAME' => 'Speaker', 'ITEM_PROVIDER' => 'Bitrix\\DocumentGenerator\\DataProvider\\HashDataProvider', ], ], 'Event1SpeakersSpeakerName' => ['TITLE' => 'Event1SpeakersSpeakerName'], 'Event1SpeakersSpeakerCompany' => ['TITLE' => 'Event1SpeakersSpeakerCompany'], 'Event1SpeakersSpeakerPosition' => ['TITLE' => 'Event1SpeakersSpeakerPosition'], 'Event2SpeakersSpeakerName' => ['TITLE' => 'Event2SpeakersSpeakerName'], 'Event2SpeakersSpeakerCompany' => ['TITLE' => 'Event2SpeakersSpeakerCompany'], 'Event2SpeakersSpeakerPosition' => ['TITLE' => 'Event2SpeakersSpeakerPosition'] ] ]; $result = $action->run($data, 'document'); echo '<pre>'; print_r($result); echo '</pre>'; |