JAVA根据模板生成WORD并导出
实现功能
根据模板生成WORD文件,模板文件参数可配.
一 : WORD导出效果
先看一下导出的demo文件,具体参数可手动修改
下图为word_demo.docx导出的WORD文件
下图为word_list.docx导出的WORD文件
二 : 编写WORD模板
WORD文件模板,新建WORD文件,将所需参数用特殊符号 ${} 配置,如下图.
demo模板(数据替换模板中的配置参数) : word_demo.docx
demo模板(导出数据列表,数据表格在文件下方自动拼接) : word_list.docx
三 : 引入所需maven依赖
项目采用springboot框架
<!--WORD导出POM-->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.8</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.8</version>
</dependency>
四 : JAVA代码工具类
WORD导出接口类 WordController.java
package com.chang.word;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.util.ArrayList;
import java.util.List;
/**
* WORD导出
* @author message丶小和尚
* @create 2020/01/10
*/
@Controller
public class WordController {
@Resource
private WordExportService wordExportService;//Word导出工具
@RequestMapping("exportWordDemo")
@ResponseBody
public void exportWordDemo(HttpServletResponse response, @RequestParam("param")String param) throws Exception{
WordResult wordResult = new WordResult();
wordResult.setData(param);
wordExportService.toWordDemo(response, wordResult);
}
@RequestMapping("exportWordList")
@ResponseBody
public void exportWordList(HttpServletResponse response, @RequestParam("param")String param) throws Exception{
List<WordResult> wordResultList = new ArrayList<>();
WordResult wordResult = new WordResult();
wordResult.setData(param);
wordResultList.add(wordResult);
wordExportService.toWordList(response, wordResult, wordResultList);
}
}
WORD导出工具类 WordExportService.java
package com.chang.word;
import org.springframework.stereotype.Service;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.ByteArrayInputStream;
import java.io.InputStream;
import java.io.OutputStream;
import java.util.List;
/**
* 模板文档下载
* @author message丶小和尚
* @create 2020/01/10
*/
@Service
public class WordExportService {
//文件名
private final static String DEMO_WORD_FILE="模板demo文件";
private final static String DEMO_WORD_LIST="模板list文件";
public void toWordDemo(HttpServletResponse response, WordResult wordResult)throws Exception{
byte[] bytes = WordBaseService.toWordDemo(wordResult);
if(bytes != null){
uploadWord(response,bytes,DEMO_WORD_FILE);
}
}
public void toWordList(HttpServletResponse response, WordResult wordResult, List<WordResult> publicResultList)throws Exception{
byte[] bytes = WordBaseService.toWordList(wordResult,publicResultList);
if(bytes != null){
uploadWord(response,bytes,DEMO_WORD_LIST);
}
}
/**
* 下载模板
* @param response 响应
* @param bytes 字节
* @param fileName 文件名
* @throws Exception
*/
private void uploadWord(HttpServletResponse response, byte[] bytes, String fileName) throws Exception{
try {
if(bytes != null){
// OutputStream outputStream = new FileOutputStream("E:ceshi.docx");
OutputStream outputStream = response.getOutputStream();
response.setCharacterEncoding("utf-8");
response.setContentType("application/x-download");
HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
String userAgent = request.getHeader("User-Agent");
byte[] byteName = userAgent.contains("MSIE") ? fileName.getBytes() : fileName.getBytes("UTF-8");//name.getBytes("UTF-8")处理safari的乱码问题
fileName = new String(byteName, "ISO-8859-1"); // 各浏览器基本都支持ISO编码
response.setHeader("Content-disposition", String.format("attachment; filename=\"%s\"", fileName+".docx"));//文件名外的双引号处理firefox的空格截断问题
InputStream is = new ByteArrayInputStream(bytes);
byte[] buff = new byte[1024];
int len = 0;
while ((len = is.read(buff)) != -1) {
outputStream.write(buff, 0, len);
}
is.close();
outputStream.close();
}
} catch (Exception e) {
throw(e);
}
}
}
WORD导出工具类 WordBaseService.java
package com.chang.word;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.xwpf.usermodel.ParagraphAlignment;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STJc;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.STVerticalJc;
import org.springframework.stereotype.Component;
import org.springframework.util.StringUtils;
import java.io.ByteArrayOutputStream;
import java.io.File;
import java.math.BigInteger;
import java.util.List;
import java.util.Map;
/**
* @author message丶小和尚
* @create 2020/01/10
* 模板下载
*/
@Slf4j
@Component
public class WordBaseService {
private static String templateBasePath = "/app/static/template/";
private final static String WORD_DEMO = "word_demo.docx";
private final static String WORD_LIST = "word_list.docx";
//Word导出,参数配置
public static byte[] toWordDemo(WordResult wordResult) throws Exception {
return toWordObjectMap(wordResult,WORD_DEMO);
}
private static byte[] toWordObjectMap(Object obj,String filePath) throws Exception{
byte[] bytes = null;
if(obj != null ){
bytes = toWordAllModelAnalysis(WordUtil.setMapObject(obj),templateBasePath + filePath);
}
return bytes;
}
private static byte[] toWordAllModelAnalysis(Map<String, Object> mapObject, String modelPath) throws Exception {
byte[] bytes = null;
if(mapObject != null && !StringUtils.isEmpty(modelPath)){
File file = new File(modelPath);
if(!file.exists()&&!file.isFile()){
log.error("模板文件不存在");
return null;
}
try {
XWPFDocument doc = WordUtil.generateWord(mapObject, modelPath);
ByteArrayOutputStream baos=new ByteArrayOutputStream();
doc.write(baos);
bytes = baos.toByteArray();
baos.close();
} catch (Exception e) {
log.error("文件处理异常",e);
}
}
return bytes;
}
//Word导出,列表设置
public static byte[] toWordList(WordResult wordResult, List<WordResult> publicResultList) throws Exception {
return toWordObjectMapPublic(wordResult,publicResultList,WORD_LIST);
}
private static byte[] toWordObjectMapPublic(Object obj, List<WordResult> list, String filePath) throws Exception{
byte[] bytes = null;
if(obj != null ){
bytes = toWordAllModelAnalysisPublic(WordUtil.setMapObject(obj),list,templateBasePath+filePath);
}
return bytes;
}
private static byte[] toWordAllModelAnalysisPublic(Map<String, Object> mapObject,List<WordResult> list, String modelPath) throws Exception {
byte[] bytes = null;
if(mapObject != null && !StringUtils.isEmpty(modelPath)){
File file = new File(modelPath);
if(!file.exists()&&!file.isFile()){
log.error("模板文件不存在");
return null;
}
try {
XWPFDocument doc = WordUtil.generateWord(mapObject, modelPath);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
//插入表格
XWPFTable table = doc.createTable();
table.getCTTbl().addNewTblPr().addNewJc().setVal(STJc.CENTER);//设置表格居中
//设置表头
XWPFTableRow tableRowOne = table.getRow(0);
XWPFParagraph paragraph0 = getStyle(doc.createParagraph(),"序号");
tableRowOne.getCell(0).setParagraph(paragraph0);
paragraph0.removeRun(0);
tableRowOne.getCell(0).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1000));//设置宽度
tableRowOne.getCell(0).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中
// tableRowOne.getCell(0).getCTTc().getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
XWPFParagraph paragraph1 = getStyle(doc.createParagraph(),"数据");
tableRowOne.addNewTableCell().setParagraph(paragraph1);
paragraph1.removeRun(0);
tableRowOne.getCell(1).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1500));//设置宽度
tableRowOne.getCell(1).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中
// tableRowOne.getCell(1).getCTTc().getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
//循环设置Word表格内容
for (int i = 0; i < list.size(); i++) {
XWPFTableRow tableRow = table.createRow();
XWPFParagraph paragraph00 = getStyleNotBold(doc.createParagraph(),String.valueOf(i+1));
tableRow.getCell(0).setParagraph(paragraph00);
paragraph00.removeRun(0);
XWPFParagraph paragraph01 = getStyleNotBold(doc.createParagraph(),list.get(i).getData());
tableRow.getCell(1).setParagraph(paragraph01);
paragraph01.removeRun(0);
tableRow.getCell(0).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1000));
tableRow.getCell(0).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中
// tableRow.getCell(0).getCTTc().getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
tableRow.getCell(1).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(1500));
tableRow.getCell(1).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中
// tableRow.getCell(1).getCTTc().getPList().get(0).addNewPPr().addNewJc().setVal(STJc.CENTER);
}
doc.write(byteArrayOutputStream);
bytes = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
} catch (Exception e) {
log.error("文件处理异常",e);
}
}
return bytes;
}
//设置段落格式
private static XWPFParagraph getStyle(XWPFParagraph paragraphX, String name){
paragraphX.setAlignment(ParagraphAlignment.CENTER);//对齐方式
XWPFRun runXOne = paragraphX.createRun();//创建文本对象
runXOne.setText(name);
runXOne.setFontSize(15);//字体大小
runXOne.setFontFamily("黑体");//字体
runXOne.setBold(true);//加粗
runXOne.setTextPosition(10);//设置行间距
return paragraphX;
}
//设置段落格式
private static XWPFParagraph getStyleNotBold(XWPFParagraph paragraphX, String name){
paragraphX.setAlignment(ParagraphAlignment.CENTER);//对齐方式
XWPFRun runXOne = paragraphX.createRun();//创建文本对象
runXOne.setText(name);
runXOne.setFontSize(14);//字体大小
runXOne.setBold(false);//加粗
runXOne.setTextPosition(10);//设置行间距
return paragraphX;
}
}
WORD导出工具类 WordUtil.java
package com.chang.word;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.poi.POIXMLDocument;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.openxml4j.opc.OPCPackage;
import org.apache.poi.xwpf.usermodel.XWPFDocument;
import org.apache.poi.xwpf.usermodel.XWPFParagraph;
import org.apache.poi.xwpf.usermodel.XWPFRun;
import org.apache.poi.xwpf.usermodel.XWPFTable;
import org.apache.poi.xwpf.usermodel.XWPFTableCell;
import org.apache.poi.xwpf.usermodel.XWPFTableRow;
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.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.lang.reflect.Field;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
/**
* @author message丶小和尚
* @create 2020/01/10
* 模板的装载过程
*/
public class WordUtil {
private static Log log = LogFactory.getLog(WordUtil.class);
/**
* 装载模板所对应的对象
* @param object
* @return map
*/
public static Map<String,Object> setMapObject(Object object){
Map<String,Object> mapObject = new HashMap<String,Object>();
if(object != null){
Field[] fields = object.getClass().getDeclaredFields();
log.info("fields" + fields.length);
for(Field field : fields){
try {
field.setAccessible(true);
String str = "${" + field.getName() + "}";
Object objValue = field.get(object);
if(objValue != null){
log.info(str + "----" + objValue.toString());
mapObject.put(str, objValue);
}else{
mapObject.put(str, "");
}
} catch(Exception e) {
log.error("模板对象出现错误", e);
}
}
} else {
log.error("模板对象不是对应的一个类对象");
}
return mapObject;
}
/**
* 根据指定的参数值、模板,生成 word 文档
* @param param 需要替换的变量
* @param template 模板
* @return XWPFDocument
* @throws IOException
* @throws InvalidFormatException
*/
public static XWPFDocument generateWord(Map<String, Object> param, String template) throws IOException, InvalidFormatException {
if(param == null || template == null){
return null ;
}
XWPFDocument xwpfDocument = null;
log.info("解析的模版为:" + template);
try {
OPCPackage pack = POIXMLDocument.openPackage(template);
xwpfDocument = new XWPFDocument(pack);
if (param.size() > 0) {
//处理段落
List<XWPFParagraph> paragraphList = xwpfDocument.getParagraphs();
processParagraphs(paragraphList, param, xwpfDocument);
//处理表格
Iterator<XWPFTable> it = xwpfDocument.getTablesIterator();
while (it.hasNext()) {
XWPFTable table = it.next();
List<XWPFTableRow> rows = table.getRows();
for (XWPFTableRow row : rows) {
List<XWPFTableCell> cells = row.getTableCells();
for (XWPFTableCell cell : cells) {
List<XWPFParagraph> paragraphListTable = cell.getParagraphs();
processParagraphs(paragraphListTable, param, xwpfDocument);
}
}
}
}
} catch (IOException e) {
log.error("文件处理异常", e);
throw(e);
}catch (InvalidFormatException e) {
log.error("文档中内容处理异常", e);
throw(e);
}
return xwpfDocument;
}
/**
* 处理段落
* @param paragraphList
* @param param
* @param doc
* @throws InvalidFormatException
* @throws FileNotFoundException
*/
public static void processParagraphs(List<XWPFParagraph> paragraphList, Map<String, Object> param, XWPFDocument doc) throws InvalidFormatException, FileNotFoundException{
if(paragraphList != null && paragraphList.size() > 0){
for(XWPFParagraph paragraph : paragraphList){
List<XWPFRun> runs = paragraph.getRuns();
for (XWPFRun run : runs) {
String text = run.getText(0);
if(text != null){
boolean isSetText = false;
for (Map.Entry<String, Object> entry : param.entrySet()) {
String key = entry.getKey();
if(text.indexOf(key) != -1){
isSetText = true;
Object value = entry.getValue();
if (value instanceof String) {//文本替换
log.info(key + "模板中模要转化属性对应的值:" + value);
text = text.replace(key, value.toString());
} else if (value instanceof Map) {//图片替换
text = text.replace(key, "");
Map pic = (Map)value;
int width = Integer.parseInt(pic.get("width").toString());
int height = Integer.parseInt(pic.get("height").toString());
int picType = getPictureType(pic.get("type").toString());
String byteArray = (String) pic.get("imgPath");
log.info("模板中模要转化的图片" + byteArray);
CTInline inline = run.getCTR().addNewDrawing().addNewInline();
insertPicture(doc,byteArray,inline, width, height);
}
}
}
if(isSetText){
run.setText(text,0);
}
}
}
}
}
}
/**
* 根据图片类型,取得对应的图片类型代码
* @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;
}
/**
* 将输入流中的数据写入字节数组
* @param inputStream
* @param isClose
* @return
*/
public static byte[] inputStream2ByteArray(InputStream inputStream,boolean isClose){
byte[] byteArray = null;
try {
int total = inputStream.available();
byteArray = new byte[total];
inputStream.read(byteArray);
} catch (IOException e) {
log.error("IO异常",e);
} finally {
if(isClose){
try {
inputStream.close();
} catch (Exception e2) {
log.debug("关闭流失败");
}
}
}
return byteArray;
}
/**
*
* @param document
* @param filePath
* @param inline
* @param width
* @param height
* @throws InvalidFormatException
* @throws FileNotFoundException
*/
private static void insertPicture(XWPFDocument document, String filePath, CTInline inline, int width, int height) throws InvalidFormatException, FileNotFoundException {
document.addPictureData(new FileInputStream(filePath), XWPFDocument.PICTURE_TYPE_PNG);
int id = document.getAllPictures().size() - 1;
final int EMU = 9525;
width *= EMU;
height *= EMU;
// String blipId = document.getAllPictures().get(id).getPackageRelationship().getId();
Integer blipIdString = document.getAllPictures().get(id).getPictureType();
String blipId = blipIdString.toString();
String picXml = getPicXml(blipId, width, height);
XmlToken xmlToken = null;
try {
xmlToken = XmlToken.Factory.parse(picXml);
} catch (XmlException xe) {
log.error("XmlException",xe);
}
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("IMG_" + id);
docPr.setDescr("IMG_" + id);
}
/**
* get the xml of the picture
* @param blipId
* @param width
* @param height
* @return
*/
private static String getPicXml(String blipId, int width, int height) {
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=\"" + 0 +
"\" 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>";
return picXml;
}
}
WORD导出实体类(模板所需参数) WordResult.java
package com.chang.word;
import java.io.Serializable;
/**
* WORD导出参数类
* @author message丶小和尚
* @create 2020/01/10
*/
public class WordResult implements Serializable {
private static final long serialVersionUID = 1L;
public String data;
public String getData() {
return data;
}
public void setData(String data) {
this.data = data;
}
}
五 : 配置信息说明
在WordExportService中,可设置导出的Word文件名.
在WordBaseService中,可设置Word模板配置的地址,以及配置模板名称
六 : 在固定位置插入表格
6.1 : 情况说明
在真实的业务场景中,可能会涉及Word中表格的导出。表格并不是拼接在文档末尾,而是设置在文档中,即某个段落与段落之间,类似下图这种情况。
对于这种在固定位置插入表格的情况,我们可采用同样的占位符的方式来实现。
如图所示,定义一个占位符 ${make_newTable},当然里面的内容可以自己定义,需注意不能与文档中其他占位符同名即可。
6.2 : 编码实现
前提是前面的架子已经搭好。
这里的实现结果为标准表格导出,如果需要特殊表格,即合并单元格等,可改造该方法,对cell做特殊处理即可。
在WordTempleCommonService.java文件中增加方法如下:
//通用导出WORD 包含list
public static byte[] toWordCommonIndexList(Object obj,List<String> head,List<List<String>> list,String filePath) throws Exception{
byte[] bytes = null;
if(obj != null ){
bytes = toWordAllModelAnalysisCommonIndexList(WordUtil.setMapObject(obj),head,list,WordConstant.TEMPLATE_BASE_PATH + filePath);
}
return bytes;
}
private static byte[] toWordAllModelAnalysisCommonIndexList(Map<String, Object> mapObject,List<String> head,List<List<String>> stringList, String modelPath) throws Exception {
byte[] bytes = null;
if(mapObject != null && !StringUtils.isEmpty(modelPath)){
File file = new File(modelPath);
if(!file.exists() && !file.isFile()){
return null;
}
try {
XWPFDocument doc = WordUtil.generateWord(mapObject, modelPath);
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
List<XWPFParagraph> xwpfParagraphList = doc.getParagraphs();
for(int s = 0; s < xwpfParagraphList.size(); s++){
XWPFParagraph xwpfParagraphIndex = xwpfParagraphList.get(s);
if("${make_newTable}".equals(xwpfParagraphIndex.getText())){
XmlCursor cursor = xwpfParagraphIndex.getCTP().newCursor();
XWPFTable table = doc.insertNewTbl(cursor);
//插入表格
table.getCTTbl().addNewTblPr().addNewJc().setVal(STJc.CENTER);//设置表格居中
//定义map
Map<Integer,Integer> map = new HashMap<Integer,Integer>();
//设置表头
XWPFTableRow tableRowOne = table.getRow(0);
for(String string:head){
Integer index = head.indexOf(string);//当前所处序号
Integer width = string.length() * 350 + 200;
if(0 == index && "序号".equals(string)){
width = 800;
}
map.put(index,width);
XWPFParagraph paragraph = getCommonIndexStyle(doc.createParagraph(), string, true);
if(0 == index){
tableRowOne.getCell(0).setParagraph(paragraph);
paragraph.removeRun(0);
tableRowOne.getCell(index).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(width));//设置宽度
tableRowOne.getCell(0).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中
tableRowOne.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(600));
} else {
tableRowOne.addNewTableCell().setParagraph(paragraph);
paragraph.removeRun(0);
tableRowOne.getCell(index).getCTTc().addNewTcPr().addNewTcW().setW(BigInteger.valueOf(width));//设置宽度
tableRowOne.getCell(index).getCTTc().addNewTcPr().addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中
tableRowOne.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(600));
}
doc.removeBodyElement(doc.getPosOfParagraph(paragraph));
}
//循环设置Word表格内容
for(List<String> list : stringList){
XWPFTableRow tableRow = table.createRow();
for(int i = 0; i < list.size(); i++){
CTTcPr tcpr = tableRow.getCell(i).getCTTc().addNewTcPr();
XWPFParagraph paragraph = getCommonIndexStyle(doc.createParagraph(), list.get(i), false);
tableRow.getCell(i).setParagraph(paragraph);
paragraph.removeRun(0);
tcpr.addNewTcW().setW(BigInteger.valueOf(map.get(i)));//设置宽度,表头设置了宽度,此处设置表头的宽度
tcpr.addNewVAlign().setVal(STVerticalJc.CENTER);//设置水平居中
tableRow.getCtRow().addNewTrPr().addNewTrHeight().setVal(BigInteger.valueOf(500));
doc.removeBodyElement(doc.getPosOfParagraph(paragraph));
}
}
doc.removeBodyElement(doc.getPosOfParagraph(xwpfParagraphIndex));
}
}
doc.write(byteArrayOutputStream);
bytes = byteArrayOutputStream.toByteArray();
byteArrayOutputStream.close();
} catch (Exception e) {
log.error("文件处理异常,Exception:", e);
}
}
return bytes;
}
//设置通用段落格式
private static XWPFParagraph getCommonIndexStyle(XWPFParagraph paragraphX, String name, boolean flag){
paragraphX.setAlignment(ParagraphAlignment.CENTER);//对齐方式
paragraphX.setVerticalAlignment(TextAlignment.CENTER);//对齐方式
XWPFRun runXOne = paragraphX.createRun();//创建文本对象
runXOne.setText(name);
if(null == name){
runXOne.setText("");
}
runXOne.setFontSize(12);//字体大小
runXOne.setFontFamily("Calibri (正文)");//字体
if(flag){
runXOne.setBold(true);//加粗
}
runXOne.setTextPosition(10);//设置行间距
return paragraphX;
}
上述代码中需要注意的是:doc.removeBodyElement(doc.getPosOfParagraph(xwpfParagraphIndex));
这是由于我们在生成表格的时候,会去调用 doc.createParagraph(),创建段落,如果不去remove的话,会导致文档产生非常多的空白页。
方法getCommonIndexStyle,其主要作用即设置样式,如果想设置不同样式,可以自行设置即可。
然后在WordTempleService.java文件中增加方法如下:
//指定位置插入表格 ${make_newTable}
public void toWordCommonIndexList(HttpServletResponse response, Object object,List<String> head,List<List<String>> list,String wordTemplate,String fileName)throws Exception{
byte[] bytes = WordTempleCommonService.toWordCommonIndexList(object,head,list,wordTemplate);
if(bytes != null){
uploadWord(response,bytes,fileName);
}
}
上述代码的 uploadWord方法,可在文中找到。
至此方法已经搭建完成,下面是模拟调用。
wordTempleService.toWordCommonIndexList(response, templateDate, tableHead, tableData, wordTemplate, fileName);
参数说明:
response:响应头。
templateDate:Word模板导出的其他匹配数据。
tableHead:表格的表头。可使用Arrays.asList(“序号”, “姓名”)
tableData:表格的内容。
wordTemplate:模板的名称,需要注意路径问题。
fileName:导出的文件对应的文件名。
6.3 : 导出效果
七 : 可能出现的问题
在模板中配置参数 ${data} 时,可能会出现配置了参数,但是导出的时候赋值不了的情况,生成的Word中仍是 ${data} .
这种情况需要在代码中debug,找到对应的map,从代码中把对应的key复制到Word模板上.
如图所示复制一下,问题就可以解决了
附上材料下载地址
链接:https://pan.baidu.com/s/1jL1UpQatLVIjx0iBXIOMeg 提取码: ga1a
CSDN资源,0积分下载:https://download.csdn.net/download/qq_38254635/12099599
八 : 相关链接
JAVA生成Zip文件并导出:
https://blog.csdn.net/qq_38254635/article/details/127364398
JAVA导出Excel文件:
https://blog.csdn.net/qq_38254635/article/details/126691175
JAVA根据PDF文件生成图片:
https://blog.csdn.net/qq_38254635/article/details/112029941
JAVA根据模板生成PDF文件并导出:
https://blog.csdn.net/qq_38254635/article/details/103919024