1. 创建一个空的 springboot 工程,引入 jar 包
org.apache.poi
poi-ooxml
3.17
org.apache.poi
poi
3.17
2. 工具类一
package com.example.demo.util;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
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 java.io.IOException;
import java.io.InputStream;
public class CustomXWPFDocument extends XWPFDocument {
public CustomXWPFDocument(InputStream in) throws IOException {
super(in);
}
public CustomXWPFDocument(OPCPackage pkg) throws IOException {
super(pkg);
}
public void createPicture(String blipId,int id, int width, int height, XWPFParagraph paragraph)
{
final int EMU = 9525;
width *= EMU;
height *= EMU;
// 给段落插入图片
CTInline inline = paragraph.createRun().getCTR().addNewDrawing().addNewInline();
String picXml = “” +
“” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
” ” +
“”;
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(“Picture ” + id);
docPr.setDescr(“Generated”);
}
}
3. 工具类二
package com.example.demo.util;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.xwpf.usermodel.*;
import java.io.*;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
public class WordUtil {
/**
* 替换段落里面的变量
*
* @param doc 要替换的文档
* @param params 参数
* @throws FileNotFoundException
* @throws InvalidFormatException
*/
public void replaceInPara(CustomXWPFDocument doc, Map params) throws InvalidFormatException, FileNotFoundException {
Iterator iterator = doc.getParagraphsIterator();
XWPFParagraph para;
while (iterator.hasNext()) {
para = iterator.next();
this.replaceInPara(para, params,doc);
}
}
/**
* 替换段落里面的变量
*
* @param para 要替换的段落
* @param params 参数
* @throws FileNotFoundException
* @throws InvalidFormatException
*/
public void replaceInPara(XWPFParagraph para, Map params, CustomXWPFDocument doc) throws InvalidFormatException, FileNotFoundException {
List runs;
Matcher matcher;
if (this.matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
int start = -1;
int end = -1;
String str = “”;
String text= “”;
for (int i = 0; i < runs.size(); i++) {
text += runs.get(i).toString();
}
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
System.out.println(“——>>>>>>>>>” + text);
if (text.contains(“$”)) {
start = text.indexOf(“$”);
}
if ((start != -1)) {
str += text.substring(text.indexOf(“$”), text.length()).trim();
String paraList=runs.toString();
System.out.println(“ 未删除前 ”+paraList);
Object[] runArr = runs.toArray();
int size=runs.size();
int $Index=0;
for (int j = 0; j < runArr.length; j++) {
if (runArr[j].toString().contains(“$”)) {
$Index=j;
break;
}
}
int startIn=$Index;
while (startIn
para.removeRun(startIn);
System.out.println(“ 删除中 ”+para.getRuns());
}
System.out.println(“ 删除后 ”+para.getRuns());
}
if (‘}’ == text.charAt(text.length() – 1)) {
if (start != -1) {
end = text.length() – 1;
break;
}
}
}
System.out.println(“start—>”+start);
System.out.println(“end—>”+end);
System.out.println(“str—->>>” + str);
for (String key : params.keySet()) {
if (str.equals(key)) {
if(str.indexOf(“@”)==-1){
String value= params.get(key).toString();
para.createRun().setText(value);
break;
}else{
String value= params.get(key).toString();
int length = para.getRuns().size();
if (length > 0) {
for (int i = (length – 1); i >= 0; i–) {
para.removeRun(i);
}
}
String blipId = doc.addPictureData(new FileInputStream(new File(value)), CustomXWPFDocument.PICTURE_TYPE_PNG);
doc.createPicture(blipId,doc.getNextPicNameNumber(CustomXWPFDocument.PICTURE_TYPE_PNG), 550, 250,para);
break;
}
}
}
}
}
/**
* 替换表格里面的变量
*
* @param doc 要替换的文档
* @param params 参数
* @throws FileNotFoundException
* @throws InvalidFormatException
*/
public void replaceInTable(CustomXWPFDocument doc, Map params) throws InvalidFormatException, FileNotFoundException {
Iterator iterator = doc.getTablesIterator();
XWPFTable table;
List rows;
List cells;
List paras;
while (iterator.hasNext()) {
table = iterator.next();
rows = table.getRows();
for (XWPFTableRow row : rows) {
cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
paras = cell.getParagraphs();
for (XWPFParagraph para : paras) {
this.replaceInPara(para, params,doc);
}
}
}
}
}
/**
* 正则匹配字符串
*
* @param str
* @return
*/
private Matcher matcher(String str) {
Pattern pattern = Pattern.compile(“\\$\\{(.+?)\\}”, Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher;
}
/**
* 关闭输入流
*
* @param is
*/
public void close(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
/**
* 关闭输出流
*
* @param os
*/
public void close(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
4. 测试代码
package com.example.demo.controller;
import ch.qos.logback.core.util.FileUtil;
import com.example.demo.util.CustomXWPFDocument;
import com.example.demo.util.WordUtil;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RestController;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.HashMap;
import java.util.Map;
@RestController
public class ExportWordController {
@RequestMapping(value = “/export”)
public void export(HttpServletRequest request,HttpServletResponse response) throws Exception {
Map params = new HashMap<>();
params.put(“${Name}”, “Fisher3652”);
params.put(“${Sex}”, “ 男 ”);
params.put(“${Desc}”, “18 岁 \tJAVA 开发 \r 熟悉 JVM 基本原理 ”);
params.put(“${@Pic}”, “C:\\Users\\111\\Pictures\\123.jpg”);
//spring 项目使用此方法获取文件路径
// String fileNameInResource = request.getSession().getServletContext().getRealPath(“Demo.docx”);
InputStream is;
CustomXWPFDocument doc;
//spring 项目使用此方法获取创建文件
// is = new FileInputStream(new File(fileNameInResource));
//springboot 项目使用次方法
is = FileUtil.class.getClassLoader().getResourceAsStream(“static/Demo.docx”);
doc = new CustomXWPFDocument(is);
WordUtil xwpfTUtil = new WordUtil();
xwpfTUtil.replaceInPara(doc, params);
xwpfTUtil.replaceInTable(doc, params);
// 此处不指定下载目录,默认到用户本地的下载文件下
亨达返佣 http://www.fx61.com/brokerlis…
OutputStream os = response.getOutputStream();
response.setContentType(“application/vnd.ms-excel”);
SimpleDateFormat sdf = new SimpleDateFormat(“yyyyMMddHHmmss”);
String fileName = sdf.format(new Date());
response.setHeader(“Content-type”, “text/html;charset=UTF-8”);
response.setHeader(“Content-disposition”, “attachment;filename=” + fileName + “.doc”);
doc.write(os);
xwpfTUtil.close(os);
xwpfTUtil.close(is);
os.flush();
os.close();
System.out.println(“word 成功生成 ”);
}
}