poi根据模板导出word文档
POI结构与常用类
Apache POI是Apache软件基金会的开源项目,POI提供API给Java程序对Microsoft Office格式档案读和写的功能。 .NET的开发人员则可以利用NPOI (POI for .NET) 来存取 Microsoft Office文档的功能。
包名称说明
- HSSF提供读写Microsoft Excel XLS格式档案的功能。
- XSSF提供读写Microsoft Excel OOXML XLSX格式档案的功能。
- HWPF提供读写Microsoft Word DOC格式档案的功能。
- HSLF提供读写Microsoft PowerPoint格式档案的功能。
- HDGF提供读Microsoft Visio格式档案的功能。
- HPBF提供读Microsoft Publisher格式档案的功能。
- HSMF提供读Microsoft Outlook格式档案的功能。
测试例子
测试模板:
测试代码:
- @Test
- public void docxExportTest() throws IOException {
- InputStream is = null;
- FileOutputStream fos = null;
- try {
- //获取docx解析对象
- is = new FileInputStream("F:\\document\\咨询服务合同.docx");
- XWPFDocument document = new XWPFDocument(is);
- //组装参数
- File seal = new File("F:\\imgtest\\1.jpg");
- Map<String, Object> sealMap = new HashMap<String, Object>();
- sealMap.put("width", 50);
- sealMap.put("height", 50);
- sealMap.put("type", "jpg");
- sealMap.put("content", new FileInputStream(seal));
- Map<String, Object> contentMap = new HashMap<>();
- contentMap.put("part_a", "张三");
- contentMap.put("address_a", "青岛市市南区动漫产业园E座");
- contentMap.put("legal_person_a", "李四");
- contentMap.put("seal", sealMap);
- //解析替换段落文本对象
- XWPFUtil.changeParagraph(document, contentMap);
- //生成新的word文档
- SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
- String fileName = "咨询服务合同" + sdf.format(new Date()) + ".docx";
- File file = new File("F://" + fileName);
- fos = new FileOutputStream(file);
- document.write(fos);
- } catch (Exception e) {
- e.printStackTrace();
- } finally {
- if (is != null) {
- is.close();
- }
- if (fos != null) {
- fos.close();
- }
- }
- }
工具类:
- package com.m2plat.puhui.utils;
- import com.alibaba.fastjson.JSON;
- import org.apache.commons.io.IOUtils;
- import org.apache.poi.xwpf.usermodel.XWPFDocument;
- import org.apache.poi.xwpf.usermodel.XWPFParagraph;
- import org.apache.poi.xwpf.usermodel.XWPFRun;
- import org.apache.xmlbeans.XmlException;
- import org.apache.xmlbeans.XmlToken;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTNonVisualDrawingProps;
- import org.openxmlformats.schemas.drawingml.x2006.main.CTPositiveSize2D;
- import org.openxmlformats.schemas.drawingml.x2006.wordprocessingDrawing.CTInline;
- import org.slf4j.Logger;
- import org.slf4j.LoggerFactory;
- import org.springframework.core.io.ClassPathResource;
- import java.io.FileInputStream;
- import java.io.IOException;
- import java.io.InputStream;
- import java.io.OutputStream;
- import java.util.List;
- import java.util.Map;
- /**
- * Created by xiangzh on 2018/11/1.
- */
- public class XWPFUtils {
- private static Logger logger = LoggerFactory.getLogger(XWPFUtils.class);
- /**
- * 根据模板生成word文档
- * @param os
- * @param tempPath
- * @param contentMap
- */
- public static void writeTemp(OutputStream os, String tempPath, Map<String, Object> contentMap){
- logger.info("---根据模板生成word文档");
- logger.info("---模板地址:{}",tempPath);
- logger.info("---替换内容:{}", JSON.toJSONString(contentMap));
- ClassPathResource resource = new ClassPathResource(tempPath);
- if(resource == null || !resource.exists()){
- logger.error("---模板文件不存在,tempPath:{}",tempPath);
- return;
- }
- InputStream is = null;
- try{
- is = resource.getInputStream();
- XWPFDocument document = new XWPFDocument(is);
- XWPFUtils.changeParagraph(document, contentMap);
- //生成新的word文档
- document.write(os);
- }catch (IOException e){
- logger.error("---输出word文档失败,原因:{}",e.getMessage());
- }finally {
- IOUtils.closeQuietly(is);
- }
- }
- /**
- * 替换段落文本
- *
- * @param document docx解析对象
- * @param textMap 需要替换的信息集合
- */
- public static void changeParagraph(XWPFDocument document, Map<String, Object> textMap) {
- //获取段落集合
- List<XWPFParagraph> paragraphs = document.getParagraphs();
- for (XWPFParagraph paragraph : paragraphs) {
- List<XWPFRun> runs = paragraph.getRuns();
- for (XWPFRun run : runs) {
- String text = run.getText(0);
- //判断文本是否需要进行替换
- if (checkText(text)) {
- for (Map.Entry<String, Object> entry : textMap.entrySet()) {
- //匹配模板与替换值 格式${key}
- String key = "${" + entry.getKey() + "}";
- Object value = entry.getValue();
- if (text.contains(key)) {
- if (value instanceof String) { //文字替换
- text = text.replace(key, (String) value);
- } else if (value instanceof Map) { //图片替换
- text = text.replace(key, "");
- Map picMap = (Map) value;
- int width = Integer.parseInt(picMap.get("width").toString());
- int height = Integer.parseInt(picMap.get("height").toString());
- int picType = getPictureType(picMap.get("type").toString());
- FileInputStream fis = (FileInputStream) picMap.get("content");
- try {
- String blipId = document.addPictureData(fis, picType);
- int id = document.getNextPicNameNumber(picType);
- XWPFUtils.createPicture(id, blipId, width, height, run);
- } catch (Exception e) {
- e.printStackTrace();
- }
- }
- }
- }
- //替换模板原来位置
- run.setText(text, 0);
- }
- }
- }
- }
- /**
- * @param id
- * @param blipId
- * @param width 宽
- * @param height 高
- //* @param paragraph 段落
- */
- private static void createPicture(int id, String blipId, int width, int height,XWPFRun xwpfRun) {
- final int EMU = 9525;
- width *= EMU;
- height *= EMU;
- CTInline inline = xwpfRun.getCTR().addNewDrawing().addNewInline();
- //CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline(); //在遍历run列表的时候,创建新的run有可能会导致报错
- String picXml = ""
- + "<a:graphic xmlns:a=\"http://schemas.openxmlformats.org/drawingml/2006/main\">"
- + " <a:graphicData uri=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
- + " <pic:pic xmlns:pic=\"http://schemas.openxmlformats.org/drawingml/2006/picture\">"
- + " <pic:nvPicPr>" + " <pic:cNvPr id=\""
- + id
- + "\" name=\"Generated\"/>"
- + " <pic:cNvPicPr/>"
- + " </pic:nvPicPr>"
- + " <pic:blipFill>"
- + " <a:blip r:embed=\""
- + blipId
- + "\" xmlns:r=\"http://schemas.openxmlformats.org/officeDocument/2006/relationships\"/>"
- + " <a:stretch>"
- + " <a:fillRect/>"
- + " </a:stretch>"
- + " </pic:blipFill>"
- + " <pic:spPr>"
- + " <a:xfrm>"
- + " <a:off x=\"0\" y=\"0\"/>"
- + " <a:ext cx=\""
- + width
- + "\" cy=\""
- + height
- + "\"/>"
- + " </a:xfrm>"
- + " <a:prstGeom prst=\"rect\">"
- + " <a:avLst/>"
- + " </a:prstGeom>"
- + " </pic:spPr>"
- + " </pic:pic>"
- + " </a:graphicData>" + "</a:graphic>";
- inline.addNewGraphic().addNewGraphicData();
- XmlToken xmlToken = null;
- try {
- xmlToken = XmlToken.Factory.parse(picXml);
- } catch (XmlException xe) {
- xe.printStackTrace();
- }
- inline.set(xmlToken);
- inline.setDistT(0);
- inline.setDistB(0);
- inline.setDistL(0);
- inline.setDistR(0);
- CTPositiveSize2D extent = inline.addNewExtent();
- extent.setCx(width);
- extent.setCy(height);
- CTNonVisualDrawingProps docPr = inline.addNewDocPr();
- docPr.setId(id);
- docPr.setName("docx_img_ " + id);
- docPr.setDescr("docx Picture");
- }
- /**
- * 判断文本中是否包含$
- *
- * @param text 文本
- * @return 包含返回true, 不包含返回false
- */
- private static boolean checkText(String text) {
- if (text == null || "".equals(text)) {
- return false;
- }
- return text.contains("$");
- }
- /**
- * 根据图片类型,取得对应的图片类型代码
- *
- * @param picType
- * @return int
- */
- private static int getPictureType(String picType) {
- int res = XWPFDocument.PICTURE_TYPE_PICT;
- if (picType != null) {
- if (picType.equalsIgnoreCase("png")) {
- res = XWPFDocument.PICTURE_TYPE_PNG;
- } else if (picType.equalsIgnoreCase("dib")) {
- res = XWPFDocument.PICTURE_TYPE_DIB;
- } else if (picType.equalsIgnoreCase("emf")) {
- res = XWPFDocument.PICTURE_TYPE_EMF;
- } else if (picType.equalsIgnoreCase("jpg") || picType.equalsIgnoreCase("jpeg")) {
- res = XWPFDocument.PICTURE_TYPE_JPEG;
- } else if (picType.equalsIgnoreCase("wmf")) {
- res = XWPFDocument.PICTURE_TYPE_WMF;
- }
- }
- return res;
- }
- }
测试结果:
注意事项
1.实际开发过程中,模板通常存放在项目工程中,获取模板的代码如下:
- String tempPath = "static/exportTemplates/咨询服务合同.docx";
- ClassPathResource resource = new ClassPathResource(tempPath);
- InputStream is = resource.getInputStream();
- XWPFDocument document = new XWPFDocument(is);
2.导出文件时如果报错:Failed to read zip entry source,是因为打包编译将文件解压缩导致出问题,解决办法为在pom文件中配置nonFilteredFileExtension:
- <plugin>
- <artifactId>maven-resources-plugin</artifactId>
- <version>2.6</version>
- <configuration>
- <delimiters>
- <delimiter>@</delimiter>
- <delimiter>${*}</delimiter>
- </delimiters>
- <useDefaultDelimiters>false</useDefaultDelimiters>
- <encoding>UTF-8</encoding><!-- 指定编码格式,否则在DOS下运行mvn命令时当发生文件资源copy时将使用系统默认使用GBK编码 -->
- <nonFilteredFileExtensions>
- <nonFilteredFileExtension>bar</nonFilteredFileExtension>
- <nonFilteredFileExtension>zip</nonFilteredFileExtension>
- <nonFilteredFileExtension>txt</nonFilteredFileExtension>
- <nonFilteredFileExtension>pdf</nonFilteredFileExtension>
- <nonFilteredFileExtension>ttf</nonFilteredFileExtension>
- <nonFilteredFileExtension>xlsx</nonFilteredFileExtension>
- <nonFilteredFileExtension>xls</nonFilteredFileExtension>
- <nonFilteredFileExtension>docx</nonFilteredFileExtension>
- <nonFilteredFileExtension>doc</nonFilteredFileExtension>
- </nonFilteredFileExtensions>
- </configuration>
- </plugin>
3.所有导出参数必须转换成string类型后才能导出,否则替换不了。
参考:
war在服务器上读取文件报:java.io.IOException: Failed to read zip entry source
SpringBoot打成jar包后,读取resources目录下的文件
poi根据模板导出word文档的更多相关文章
- 使用Spire.Doc组件利用模板导出Word文档
以前一直是用Office的组件实现Word文档导出,但是让客户在服务器安装Office,涉及到版权:而且Office安装,包括权限配置也是比较麻烦. 现在流行使用第三方组件来实现对Office的操作, ...
- 前台导出Word文档思路步骤总结(freemarker)
1. 需求是导出word带表格,表格列数不变,行数由数据库的值决定: 2. 导出最开始想的是直接前端导出,使用了jquery-wordexport插件,导出后,表格边框全没了,无法使用: 3. 采用了 ...
- .NET通过调用Office组件导出Word文档
.NET通过调用Office组件导出Word文档 最近做项目需要实现一个客户端下载word表格的功能,该功能是用户点击"下载表格",服务端将该用户的数据查询出来并生成数据到Word ...
- C# 导出word文档及批量导出word文档(1)
这里用到了两个dll,一个是aspose.word.dll,另外一个是ICSharpCode.SharpZipLib.dll,ICSharpCode.SharpZipLib.dll是用于批量 ...
- C# 导出word文档及批量导出word文档(4)
接下来是批量导出word文档和批量打印word文件,批量导出word文档和批量打印word文件的思路差不多,只是批量打印不用打包压缩文件,而是把所有文件合成一个word,然后通过js来调用 ...
- C#导出Word文档开源组件DocX
1.帮助文档,这东西找了很久,而且它版本很旧,还是英文,W8.1系统上打不开 http://download.csdn.net/detail/zuofangyouyuan/7673573 2.开源网址 ...
- Java 用Freemarker完美导出word文档(带图片)
Java 用Freemarker完美导出word文档(带图片) 前言 最近在项目中,因客户要求,将页面内容(如合同协议)导出成word,在网上翻了好多,感觉太乱了,不过最后还是较好解决了这个问题. ...
- freemarker导出word文档
使用freemarker导出word文档的过程 **************************************************************************** ...
- 【Java】导出word文档之freemarker导出
Java导出word文档有很多种方式,本例介绍freemarker导出,根据现有的word模板进行导出 一.简单导出(不含循环导出) 1.新建一个word文件.如下图: 2.使用word将文件另存为x ...
随机推荐
- Linux使用expect实现自动登录的脚本
前提条件服务器已经安装过tcl和expect, 若未安装:可以先执行 yum install tcl expect 进行安装 第一步.编写以下自动登录脚本login.sh ########### ...
- 如何快捷地使用ChemBio 3D检查结构信息
ChemBio 3D是一款三维分子结构演示软件,能够轻松快捷地进行化学结构的制作和立体旋转.ChemBio 3D Ultra 14作为ChemBio 3D的最新版本可以更加快捷地制作化学结构.本教程将 ...
- python文件和目录操作方法大全(含实例)【python】
转自:http://www.jb51.net/article/48001.htm 一.python中对文件.文件夹操作时经常用到的os模块和shutil模块常用方法. 1.得到当前工作目录,即当前Py ...
- upper()
upper() 用于把字符串中的小写字母转换成大写字母 In [1]: str = "Hello World" In [2]: str.upper() Out[2]: 'HELLO ...
- 开源项目源码解析-PhotoView 源码解析
1. 功能介绍 特性(Features): 支持 Pinch 手势自由缩放. 支持双击放大/还原. 支持平滑滚动. 在滑动父控件下能够运行良好.(例如:ViewPager) 支持基于 Matrix 变 ...
- IIC协议
总线信号 : SDA :串行数据线 SCL :串行时钟 总线空闲状态 : SDA :高电平 SCL :高电平 起始位:SCL为高电平期间 SDA出现下降沿 终止位:SCL为高电平期间 SDA ...
- Android 基于帧布局实现一个进度条 FrameLayout+ProgressBar
在FrameLayout中添加一个ProgressBar居中 <ProgressBar android:layout_gravity="center" android:id= ...
- Apktool源码解析——第二篇
上一篇讲到ApkDecoder这个类,大部分调用到还是Androlib类,而且上次发现brutall的代码竟然不是最新的,遂去找iBotP.的代码了. 今天来看Androlib的代码: private ...
- c++11——lambda表达式
lambda表达式 函数式编程的一个语法,有如下优点: (1)声明式编程风格:就地匿名定义目标函数或函数对象,不需要额外写一个命名函数或者函数对象.以更直接的方式写程序,好的可读性和可维护性. (2) ...
- Java多线程详解(二)
评论区留下邮箱可获得<Java多线程设计模式详解> 转载请指明来源 1)后台线程 后台线程是为其他线程服务的一种线程,像JVM的垃圾回收线程就是一种后台线程.后台线程总是等到非后台线程死亡 ...