- PVSM.RU - https://www.pvsm.ru -
В одном из своих проектов мне понадобилось автоматизированно формировать документы договоров для клиентов. Договор представляет собой юридический документ длиной около 10 страниц и является шаблоном: в нужных местах подставляются данные конкретного клиента.
Первичные требования были такими:
В сложном стилизованном документе doc или docx вывести нужную информацию в помеченных местах.
В дальнейшем они были уточнены и расширены:
${}, <%%>, <%=%>
.Оказалось, что имеющиеся в области продукты (я говорю про платформу Java), не решают поставленную задачу. Ниже краткий обзор продуктов:
В качестве шаблона использует файл xml-разметки *.jrxml. Файл разметки документа + данные (как из БД, так и Map параметров) отдаются процессору, который формирует любой из следующих форматов: PDF, XML, HTML, CSV, XLS, RTF, TXT.
Не устроило:
Инструмент манипулирования составными частями docx-, pptx-, xlsx- документов с помощью Java-API.
Не устроило:
Инструмент манипулирования составными частями doc-, ppt-, xls- документов с помощью Java-API. Изначально создан для получения данных из документов этих форматов.
Не устроило:
Это было интересно :)
1. Контент документа хранится в виде xml, сжатом в zip-архиве. Распаковка-запаковка трудна тем, что традиционный зиппер JDK 6 не поддерживает явное указание кодировки (видимо, имен файлов). Получался битый docx при архивировании. Пришлось при запаковке контента использовать Groovy-класс-обертку AntBuilder, имеющий соответствующий параметр.
2. Любой введенный в MS Word текст может быть разбит программой на кусочки и помещен в разные группы xml-тэгов.Таким образом, мне пришлось вначале решить задачу очистки шаблона от сгенерированных прокладок xml. Для этой задачи я использовал regex-выражения, мне они показались быстрее SAX-парсера (хотя производительность не мерил).
3. Я решил использовать Groovy как скриптовый язык из-за простоты, Java-природы и входящего в ядро процессора шаблонов [3]. С ним также возникли интересные трудности. Оказалось, что даже в небольшом документе на 10 листов, можно легко нарваться на ограничение по длине строки между двумя скриптлетами. Пришлось заменять весь текст, идущий между скриптлетами на UUID-строки, прогонять процессор шаблонов Groovy, и только на выходе заменять UUID-строки на исходные кусочки XML.
Преодолев эти трудности, я опробовал проект в реальной жизни. Получилось хорошо!
Я создал англоязычный сайт проекта и опубликовал его.
Адрес проекта: snowindy.github.com/scriptlet4docx/ [4]
HashMap<String, Object> params = new HashMap<String, Object>();
params.put("name", "John");
params.put("sirname", "Smith");
DocxTemplater docxTemplater = new DocxTemplater(new File("path_to_docx_template/template.docx"));
docxTemplater.process(new File("path_to_result_docx/result.docx"), params);
На этом можно закончить, адресуя вас на сайт проекта…
Но для улучшения понимания, переведу наиболее интересную секцию “Scriptlet types explanation”.
Disclaimer: При работе с темплейтами, процессор шаблонов Groovy переводит все скриптлеты в Groovy-код, а текст между скриптлетами выводит таким образом: out.print('template_text')
Эквивалент выводу data в out: out.print(data)
Эквивалент выводу data в out: out.print(data)
Выполнение кода внутри скриптлета, ничего не выводит. Может быть использован для условного вывода:
<% if (cond) { %>
Этот текст будет вставлен, если "cond == true"
<% } else { %>
Этот текст будет вставлен, если "cond != true"
<% } %>
Это самый интересный вид скриптлетов! Он используется для вывода списков объектов в таблицу внутри docx-документа. Должен использоваться внутри ячейки таблицы.
К примеру, у нас есть список объектов Person. Объект имеет два поля: 'name' и 'address'. Мы хотим вывести список в таблице из двух колонок.
$[@person.name]
надо ввести в первую ячейку; $[@person.address]
— во вторую.Лежит здесь: ссылка [5].
Если я действительно изобрел новый подход к процессингу docx-шаблонов, хотелось бы популяризовать его.
Проекту есть куда стремиться:
Буду рад советам в распространении проекта в англоязычной аудитории!
Автор: Snowindy
Сайт-источник PVSM.RU: https://www.pvsm.ru
Путь до страницы источника: https://www.pvsm.ru/razrabotka/5750
Ссылки в тексте:
[1] документации: http://www.docx4java.org/svn/docx4j/trunk/docx4j/docs/Docx4j_GettingStarted.html
[2] ссылка: http://www.opendope.org/opendope_conventions_v2.3.html
[3] процессора шаблонов: http://groovy.codehaus.org/Groovy+Templates
[4] snowindy.github.com/scriptlet4docx/: http://snowindy.github.com/scriptlet4docx/
[5] ссылка: https://github.com/downloads/snowindy/scriptlet4docx/template-example.docx
Нажмите здесь для печати.