XDocReport导出Word
-
- 简介
- 示例
- 实现方式
-
- Maven依赖
- Word模板制作
-
- Word模板文字(四步)
- Word模板图片(五步)
- 具体实现
- 注意事项
- 结论
简介
这次的内容是关于Java实现导出Word的文章,主要应用技术为XDocReport。
以下内容主要为使用方法,详情可以去官网了解更多---->XDocRepor。
XDocReport表示XML文档报告。这是一个Java API,可以将MS Office (docx, pptx)或OpenOffice (odt), LibreOffice (odt)创建的XML文档与Java模型合并,生成报告,并在需要时将其转换为另一种格式(PDF, XHTML…)。使用xdoreport:
你用MS Word (docx, pptx)或OpenOffice (odt, ods)创建文档
您使用Velocity或Freemarker语法来设置要替换的变量。例如,您可以在文档中输入(这里使用Velocity语法):Hello $name !
通过合并文档与来自Java模型的’world’值来替换变量,以生成包含内容的报告:
Hello world!
示例
Word模板
导出样例
实现方式
实现方式的过程需要制作Word模板,本次模拟前台调用效果,后端提供Api供调用,文件从浏览器下载。
Maven依赖
<dependency> <groupId>org.apache.poi</groupId> <artifactId>poi</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>org.apache.poi</groupId> <artifactId>poi-ooxml</artifactId> <version>4.1.1</version> </dependency> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls</artifactId> <version>2.6.0</version> <exclusions> <exclusion> <groupId>ch.qos.logback</groupId> <artifactId>logback-core</artifactId> </exclusion> </exclusions> </dependency> <dependency> <groupId>org.jxls</groupId> <artifactId>jxls-poi</artifactId> <version>1.2.0</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.core</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.document</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.template</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.document.docx</artifactId> <version>2.0.2</version> </dependency> <dependency> <groupId>fr.opensagres.xdocreport</groupId> <artifactId>fr.opensagres.xdocreport.template.freemarker</artifactId> <version>2.0.2</version> </dependency>
Word模板制作
Word模板文字(四步)
- 本次示例使用WPS
- 在需要加入导出文字的部分,Windows摁下Ctrl+F9,Mac摁下command+F9,生成域。
3. 在生成的域上右键点击【编辑域】
4. 选择【邮件合并】,在域代码处的【MERGEFIELD】后边输入【 “${test}”】(实际变量由代码IContext对象的值决定,下边代码会有体现。)
Word模板图片(五步)
1.本次示例使用WPS。
2.在需要图片的地方先插入一张图片
3.导入图片后,可以自行调整大小,这样可以让导出的图片按照模板的大小生成。
4.选中图片,选择插入,点击书签。
5.输入书签名,点击添加。书签名作用与模板文字的域相同。
具体实现
-
现将模板放到项目工程的以下位置,resources下创建static
-
导入以下代码,以下代码为全部实现过程,包含url转为File流,读取模板文件。文字生成,图片生成,注(如果需要文件保存到本次,请根据代码注释部分,启用部分代码)
package xxx.utils; import fr.opensagres.xdocreport.core.XDocReportException; import fr.opensagres.xdocreport.document.IXDocReport; import fr.opensagres.xdocreport.document.images.FileImageProvider; import fr.opensagres.xdocreport.document.images.IImageProvider; 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; import lombok.extern.slf4j.Slf4j; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.net.HttpURLConnection; import java.net.URL; import java.util.Date; @Slf4j public class WordUtils { //文字生成实现类实现类 public static void textGeneration(HttpServletResponse response) throws Exception { //1.通过freemarker模板引擎加载文档,并缓存到registry中 InputStream in = null; OutputStream out = null; try { String path = Thread.currentThread().getContextClassLoader().getResource("static/elTest.docx").getPath(); in = new FileInputStream(path); IXDocReport report = XDocReportRegistry.getRegistry().loadReport(in, TemplateEngineKind.Freemarker); //2.设置填充字段、填充类以及是否为list。 FieldsMetadata fieldsMetadata = report.createFieldsMetadata(); IContext context = report.createContext(); context.put("name", "张三"); context.put("gender", "男"); context.put("type", "专家人才"); context.put("address", "东"); context.put("age", "40"); context.put("troops", "XX部"); fieldsMetadata.addFieldAsImage("pic"); //获得图片文件 File file = UrltoFile("https://img1.baidu.com/it/u=1960110688,1786190632&fm=253&fmt=auto&app=138&f=JPEG?w=500&h=281"); IImageProvider iImageProvider = new FileImageProvider(file, false); context.put("pic", iImageProvider); String outFileName = new Date().toString() ; //如果需要文件保存在本地,则放开以下注释。注释response的代码。 // out = Files.newOutputStream(new File("输出路径").toPath()); report.setFieldsMetadata(fieldsMetadata); response.setCharacterEncoding("UTF-8"); response.setHeader("Content-disposition", "attachment;filename*=utf-8''" + outFileName + ".docx"); out = response.getOutputStream(); report.process(context, out); } catch (IOException e) { log.error("读取Word模板异常", e); } catch (XDocReportException e) { log.error("word模板生成失败", e); } finally { if (in != null) { try { in.close(); } catch (IOException e) { e.printStackTrace(); } } if (out != null) { try { out.close(); } catch (IOException e) { e.printStackTrace(); } } } } //将Url转换为File public static File UrltoFile(String url) throws Exception { HttpURLConnection httpUrl = (HttpURLConnection) new URL(url).openConnection(); httpUrl.connect(); InputStream ins = httpUrl.getInputStream(); File file = new File(System.getProperty("java.io.tmpdir") + File.separator + "xie");//System.getProperty("java.io.tmpdir")缓存 if (file.exists()) { file.delete();//如果缓存中存在该文件就删除 } OutputStream os = new FileOutputStream(file); int bytesRead; int len = 8192; byte[] buffer = new byte[len]; while ((bytesRead = ins.read(buffer, 0, len)) != -1) { os.write(buffer, 0, bytesRead); } os.close(); ins.close(); return file; } //将File对象转换为byte[]的形式 public static byte[] FileTobyte(File file) { FileInputStream fileInputStream = null; byte[] imgData = null; try { imgData = new byte[(int) file.length()]; //read file into bytes[] fileInputStream = new FileInputStream(file); fileInputStream.read(imgData); } catch (IOException e) { e.printStackTrace(); } finally { if (fileInputStream != null) { try { fileInputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } return imgData; } }
3.Api入口示例。
package xxx.utils; import io.swagger.v3.oas.annotations.Operation; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; import javax.servlet.http.HttpServletResponse; @RestController @RequestMapping("test") public class TestController { @Operation(summary = "Word导出生成文字图片") @GetMapping() public void test(HttpServletResponse response) throws Exception { WordUtils.textGeneration(response); } }
4.请求API,生成文档。
注意事项
1.结合自身实际需要,自行编辑Word模板,及代码中的IContext对象的值。
2.以下代码False表示图片大小由模板图片大小决定,如需自己定义大小,可以修改为true。
IImageProvider iImageProvider = new FileImageProvider(file, false);
3.如果需要从0搭建demo,可参考另一篇创建SpringBoot工程使用Maven及Spring Initializer快速创建Spring Boot项目
结论
以上操作步骤为实际操作得出的demo,试验可应对复杂场景,如合同导出、发票生成,根据数据库数据导出对应数据。