Trong bài viết này, tôi sẽ hướng dẫn các bạn xuất dữ liệu ra file word và pdf sử dụng thư viện xDocReport.
Nội dung
xDocReport là gì?
XDocReport hay XML Document reporting là một thư viện mã nguồn mở, nó cung cấp các API để hợp nhất tài liệu XML được tạo bằng MS Office (docx, pptx) hoặc OpenOffice (odt), LibreOffice (odt) với bean của Java để tạo báo cáo và chuyển đổi nó nếu bạn cần một định dạng khác (PDF, XHTML …) .
Với XDocReport chúng ta sẽ:
- Tạo một tài liệu với MS Word (docx, pptx) hoặc OpenOffice (odt, ods).
- Sử dụng cú pháp Velocity hoặc Freemarker để đặt biến và các biến này sẽ được thay thế bởi code Java. Ví dụ bạn có thể nhập tài liệu của bạn (cú pháp Velocity được sử dụng ở đây): Hello $name !
- Thay thế biến với giá trị “world” đến từ bean của Java để tạo báo cáo với nội dung: Hello world !
Các module của xDocReport
xDocReport gồm có 3 module:
- document : module này định nghĩa loại tài liệu bạn muốn sử dụng làm template (docx, odt, …). Chẳng hạn:
- template : module này xác định cú pháp (Velocity, Freemarker) mà bạn sử dụng trong template tài liệu (odt, docx …) để thiết lập tên fields, cú pháp để quản lý các vòng lặp, điều kiện …
- converter : module này định nghĩa khả năng chuyển đổi báo cáo được tạo ra (docx, odt …) sang một định dạng khác (PDF, XHTML …).
Để sử dụng xDocReport cần phải khai báo các thư viện sau:
- fr.opensagres.xdocreport.core: XDocReport Core.
- fr.opensagres.xdocreport.document : Document type API (docx, odt).
- fr.opensagres.xdocreport.template: Template engine API (Velocity, Freemarker).
- fr.opensagres.xdocreport.converter: Converter API (docx -> PDF, XHTML).
Download thư viện xDocReport:
Có thể sử dụng một trong 2 cách sau:
- Download gói Jar:
Truy cập link: https://code.google.com/archive/p/xdocreport/downloads
Chọn download: fr.opensagres.xdocreport.document.tools-1.0.4-distribution.zip
- Download thông qua Maven:
Khai báo các thư viện docx, odt, template Velocity, Freemarker, chuyển docx, odt sang XHTML, PDF.
<!-- Docuement: docx --> <!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.document.docx --> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.document.docx</artifactId> <version>2.0.1</version> </dependency> <!-- Docuement: odt --> <!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.document.odt --> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.document.odt</artifactId> <version>2.0.1</version> </dependency> <!-- Template: velocity --> <!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.template.velocity --> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.template.velocity</artifactId> <version>2.0.1</version> </dependency> <!-- Template: freemarker --> <!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.template.freemarker --> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId> <version>2.0.1</version> </dependency> <!-- Converter: docx 2 PDF/XHTML --> <!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.converter.docx.xwpf --> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.converter.docx.xwpf</artifactId> <version>2.0.1</version> </dependency> <!-- Converter: odt 2 PDF/XHTML --> <!-- https://mvnrepository.com/artifact/fr.opensagres.xdocreport/fr.opensagres.xdocreport.converter.odt.odfdom --> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.converter.odt.odfdom</artifactId> <version>2.0.1</version> </dependency>
Ví dụ xuất dữ liệu ra file word (.docx)
Các bước thực thiện trong ví dụ này:
- Download thư viện xDocReport
- Tạo project và khai báo khai viện xDocReport
- Tạo các Java model
- Sử dụng XDocReport Tools để thiết kế template
- Xuất dữ liệu ra file word
- Xuất dữ liệu ra file pdf
Download thư viện xDocReport
Truy cập link: https://code.google.com/archive/p/xdocreport/downloads
Chọn download: fr.opensagres.xdocreport.document.tools-1.0.4-distribution.zip
Giải nén file .zip, ta có 3 folder sau:
- bin : chứa các filecdrtools.bat được sử dụng cho các tính năng xem trước của macro. File bat này gọi XDocReport JARs từ thư mục lib.
- lib : chứa toàn bộ JAR cần thiết để tạo báo cáo docx với cú pháp Freemarker hoặc Velocity.
- macro : chứa file macro MS Word XDocReport.dotm.
Tạo project và khai báo thư viện xDocReport
File -> New -> Java Project -> Nhập tên project XdocreportTutorial.
Chép các gói jar cần thiết thư mục lib vào project và khai báo như sau:
Tạo các Java model
Project.java
package com.gpcoder.model; public class Project { private final String name; public Project(String name) { this.name = name; } public String getName() { return name; } }
Developer.java
package com.gpcoder.model; public class Developer { private final String name; private final String lastName; private final String mail; public Developer(String name, String lastName, String mail) { this.name = name; this.lastName = lastName; this.mail = mail; } public String getName() { return name; } public String getLastName() { return lastName; } public String getMail() { return mail; } }
Macro của MS Word cần các trường XML để đánh dấu các biến trong template. Bạn có thể tạo ra nó từ model Java. File xml này sẽ được sử dụng ở phần tiếp theo của bài viết.
GenerateXMLFields.java
package com.gpcoder; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import com.gpcoder.model.Developer; import com.gpcoder.model.Project; import fr.opensagres.xdocreport.core.XDocReportException; import fr.opensagres.xdocreport.template.TemplateEngineKind; import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; public class GenerateXMLFields { public static void main(String[] args) throws XDocReportException,IOException { // 1) Create FieldsMetadata by setting Velocity as template engine FieldsMetadata fieldsMetadata = new FieldsMetadata(TemplateEngineKind.Velocity.name()); // 2) Load fields metadata from Java Class fieldsMetadata.load("project", Project.class); // Here load is called with true because model is a list of Developer. fieldsMetadata.load("developers", Developer.class, true); // 3) Generate XML fields in the file "project.fields.xml". // Extension *.fields.xml is very important to use it with MS Macro XDocReport.dotm // FieldsMetadata#saveXML is called with true to indent the XML. File xmlFieldsFile = new File("project.fields.xml"); fieldsMetadata.saveXML(new FileOutputStream(xmlFieldsFile), true); } }
Thực thi chương trình trên, một file project.fields.xml được tạo ra như sau:
Sử dụng XDocReport Tools để thiết kế template
Ở bước này chúng ta có thể thiết kế template docx với MS Word XDocReport.dotm bằng cách sử dụng các trường XML được tạo ra project.fields.xml ở trên. Trước khi sử dụng Macro này, chúng ta cần phải cài đặt và cấu hình nó.
Cài đặt và cấu hình file Marco XDocReport.dotm
Chép file XDocReport.dotm trong thư mục macro vào thư mục khởi động của Mircrosoft Word .
- Thư mục khởi động Word trên Windows 7, 10: C:\Users\$USER_NAME\AppData\Roaming\Microsoft\Word\STARTUP. Trong đó, $USER_NAME là tên tài khoản của Window User.
- Thư mục khởi động Word trên Windows XP: C:\Documents and Settings\$USER_NAME\Application Data\Microsoft\Word\STARTUP. Trong đó, $USER_NAME là tên tài khoản của Window User.
Lưu ý: Mặc định, thư mục AppData trên Windows 7, 10 và Application Data trên Windows XP ở trạng thái ẩn (hidden), nếu không nhìn thấy thì vào Menu File/ Tool -> Folder Option -> Show hidden files…
Đóng MS Word của bạn nếu nó được mở và mở lại nó. Khi mở MS Word, nó tải các macro từ thư mục STARTUP. Khi MS Word mở, bạn sẽ thấy trình đơn XDocReport sau đây:
Cấu hình sử dụng file fields.xml
Cấu hình của MS Word XDocReport.dotm gồm 2 phần:
- Sử dụng hộp thoại các trường dữ liệu XML để đánh dấu các biến dữ liệu.
- Xem trước kết quả của việc xuất thông tin giữa docx được thiết kế và các giá trị (đến từ tệp dữ liệu JSON).
Cấu hình Fields
Trên menu của Word -> XDocReport -> Settings -> chọn đường dẫn đến thư mục chứa file project.fields.xml -> Save
Nếu cấu hình thư mục chính xác, bạn sẽ thấy thông báo này màu xanh như trên.
Thiết kế template docx
Trên menu của Word -> XDocReport -> Fields
Hộp thoại danh sách các fields và treeview được hiển thị lấy từ project.fields.xml
Thiết kế template như sau:
- Đặt biến cho tên Project: trong nhóm project -> Chọn Name -> Insert Field
- Đặt biến cho bảng Developers: trong nhóm developer lần lượt Chọn Name -> Insert Field, LastName -> Insert Field, Email -> Insert Field
- Đặt vòng lặp hiển thị danh sách tên developer: trong nhóm developer -> chọn Name -> Insert list ->
Ta có kết quả như sau:
Preview
Khi đang thiết kế template docx, chúng ta có thể xem trước kết quả của docx đã tạo. Để làm điều đó, hãy nhấp vào nút Settings -> Chọn đường dẫn đến thư mục bin của package đã download -> Nhấn nút Save.
Nhấn Preview để mở xem trước được tạo ra docx:
Bạn có thể nhận thấy, mergefields được thay thế bằng một số giá trị. Các giá trị này đến từ tệp JSON. Nếu bạn truy cập vào thư mục có chứa project.fields.xml, bạn sẽ thấy rằng có project.fields.xml-data xuất hiện:
Vào thư mục project.fields.xml-data bạn sẽ thấy file default.json được tạo ra bởi lớp fr.opensagres.xdocreport.document.tools.Main bằng cách sử dụng các tệp tin XML fields project.fields.xml. Bạn có thể sửa đổi default.json với các giá trị của bạn như sau:
{ "project": { "Name": "XDocReport" }, "developers": [{ "Name": "Giang", "Mail": "gpcoder@gmail.com", "LastName": "Phan" }, { "Name": "ZERR", "Mail": "angelo.zerr@gmail.com", "LastName": "Angelo" } ] }
Nhấn Preview lại lần nữa, bạn sẽ thấy nội dung như sau:
Xuất dữ liệu ra file word
Sau khi đã thiết kế xong file template, lưu lại với tên Project.docx và chép vào thư mục template của project:
Code xuất dữ liệu ra file docx:
package com.gpcoder; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import com.gpcoder.model.Developer; import com.gpcoder.model.Project; import fr.opensagres.xdocreport.core.XDocReportException; import fr.opensagres.xdocreport.document.IXDocReport; import fr.opensagres.xdocreport.document.registry.XDocReportRegistry; import fr.opensagres.xdocreport.template.IContext; import fr.opensagres.xdocreport.template.TemplateEngineKind; import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; public class GenerateDocxReport { public static void main(String[] args) throws IOException, XDocReportException { // 1) Load Docx file by filling Velocity template engine and cache it to the registry InputStream in = new FileInputStream("template/Project.docx"); IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Velocity); // 2) Create fields metadata to manage lazy loop (#forech velocity) for table row. // Create FieldsMetadata by setting Velocity as template engine FieldsMetadata fieldsMetadata = report.createFieldsMetadata(); // Load fields metadata from Java Class fieldsMetadata.load("project", Project.class); // Load is called with true because model is a list of Developer. fieldsMetadata.load("developers", Developer.class, true); // 3) Create context Java model IContext context = report.createContext(); Project project = new Project("XDocReport"); context.put("project", project); // Register developers list context.put("developers", getDevelopers()); // 4) Generate report by merging Java model with the Docx OutputStream out = new FileOutputStream(new File("Project_out.docx")); report.process(context, out); } private static List<Developer> getDevelopers(){ List<Developer> developers = new ArrayList<>(); developers.add(new Developer("Giang", "Phan", "gpcoder@gmail.com")); developers.add(new Developer("ZERR", "Angelo", "angelo.zerr@gmail.com")); return developers; } }
Thực thi chương trình trên, một file Project_out.docx được tạo ra trong thư mục của project như sau:
Nội dung file được tạo ra:
Xuất dữ liệu ra file pdf
XDocReport cung cấp phương thức để chuyển đổi docx sang một định dạng khác như XHTML và PDF.
XDocReport hướng modular, có nghĩa là bạn có thể chọn bất kỳ thư viện chuyển đổi nào và viết một phương thức chuyển đổi của riêng bạn nếu cần thiết.
XDocReport cung cấp một số công cụ chuyển đổi: chuyển đổi PDF thông FOP với XSL, thông qua IText với POI-HWPF …. Mặc định, XDocReport sử dụng phương thức chuyển đổi PDF thông qua IText with POI-HWPF.
- Lưu ý: thư viện IText không phải miễn phí hoàn toàn.
Download các gói thư viện sau và import vào project:
dom4j-1.6.1.jar
fr.opensagres.xdocreport.converter.docx.xwpf-1.0.4.jar
fr.opensagres.xdocreport.itext.extension-1.0.4.jar
itext-2.1.7.jar
ooxml-schemas-1.1.jar
org.apache.poi.xwpf.converter.core-1.0.4.jar
org.apache.poi.xwpf.converter.pdf-1.0.4.jar
org.apache.poi.xwpf.converter.xhtml-1.0.4.jar
poi-3.9.jar
poi-ooxml-3.9.jar
stax-api-1.0.1.jar
xml-apis-1.0.b2.jar
xmlbeans-2.3.0.jar
commons-codec-1.5.jar
Code xuất ra file pdf:
package com.gpcoder; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.util.ArrayList; import java.util.List; import com.gpcoder.model.Developer; import com.gpcoder.model.Project; import fr.opensagres.xdocreport.converter.ConverterTypeTo; import fr.opensagres.xdocreport.converter.ConverterTypeVia; import fr.opensagres.xdocreport.converter.Options; import fr.opensagres.xdocreport.converter.XDocConverterException; import fr.opensagres.xdocreport.core.XDocReportException; import fr.opensagres.xdocreport.document.IXDocReport; import fr.opensagres.xdocreport.document.registry.XDocReportRegistry; import fr.opensagres.xdocreport.template.IContext; import fr.opensagres.xdocreport.template.TemplateEngineKind; import fr.opensagres.xdocreport.template.formatter.FieldsMetadata; public class GeneratePDF { public static void main(String[] args) throws XDocConverterException, XDocReportException, IOException { // 1) Load Docx file by filling Velocity template engine and cache it to the registry InputStream in = new FileInputStream("template/Project.docx"); IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Velocity); // 2) Create fields metadata to manage lazy loop (#forech velocity) for table row. // Create FieldsMetadata by setting Velocity as template engine FieldsMetadata fieldsMetadata = report.createFieldsMetadata(); // Load fields metadata from Java Class fieldsMetadata.load("project", Project.class); // Load is called with true because model is a list of Developer. fieldsMetadata.load("developers", Developer.class, true); // 3) Create context Java model IContext context = report.createContext(); Project project = new Project("XDocReport"); context.put("project", project); // Register developers list context.put("developers", getDevelopers()); // 4) Generate report by merging Java model with the Docx OutputStream out = new FileOutputStream(new File("Project_Out.pdf")); // report.process(context, out); Options options = Options.getTo(ConverterTypeTo.PDF).via(ConverterTypeVia.XWPF); report.convert(context, options, out); } private static List<Developer> getDevelopers(){ List<Developer> developers = new ArrayList<>(); developers.add(new Developer("Giang", "Phan", "gpcoder@gmail.com")); developers.add(new Developer("ZERR", "Angelo", "angelo.zerr@gmail.com")); return developers; } }
Thực thi chương trình trên, một file Project_Out.pdf được tạo ra như sau:
Nội dung file pdf:
Trên đây là những thao tác cơ bản để xuất dữ liệu ra file docx và convert sang pdf. Ngoài ra, thư viện này còn hỗ trợ xuất ra file pptx, odt, hoặc convert sang xhtml.
Các bạn có thể sử dụng maven để quản lý download thư viện java thay vì sử dụng cách download và import thủ công như bài viết.
Hy vọng bài viết này giúp ích cho các bạn. Cám ơn các bạn đã quan tâm và theo dõi. Hẹn gặp lại ở các bài viết tiếp theo.
Tài liệu tham khảo:
- https://github.com/opensagres/xdocreport
- https://github.com/opensagres/xdocreport/wiki
- Marco XDocReport