先看效果图:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvcXFfMjAzODkxNzU=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

public class GeneralTemplateWord2007Util {

public static void main(String[] args) {

// TODO Auto-generated method stub

String filePath = "C:/Users/Administrator/Desktop/doc/模板.docx";

String outFile = "C:/Users/Administrator/Desktop/生成模板.docx";

Map<String, Object> params = new HashMap<String, Object>();

params.put("font", "你好");

params.put("name", "小宝");

params.put("age", "xx");

params.put("sex", "男");

params.put("job", "肉盾");

params.put("hobby", "电商");

params.put("phone", "1717");

        



try {

GeneralTemplateWord2007Util gt = new GeneralTemplateWord2007Util();



Map<String, List<List<String>>> map=new HashMap<String, List<List<String>>>();

map.put("user", gt.generateTestData(5));

map.put("aa", gt.generateTestData(7));

map.put("mytable", gt.generateTestData(11));



gt.templateWrite(filePath, outFile, params, map);

System.out.println("生成模板成功");

} catch (Exception e) {

// TODO Auto-generated catch block

System.out.println("生成模板失败");

e.printStackTrace();

}

}





// 生成測试数据

public List<List<String>> generateTestData(int num) {

List<List<String>> resultList = new ArrayList<List<String>>();

for (int i = 1; i <= num; i++) {

List<String> list = new ArrayList<String>();

list.add("" + i);

list.add("測试_" + i);

list.add("測试2_" + i);

list.add("測试3_" + i);

list.add("測试4_" + i);

list.add("測试5_" + i);

resultList.add(list);

}

return resultList;

}





/**

* 用一个docx文档作为模板,然后替换当中的内容,再写入目标文档中。



* @throws Exception

*/

public void templateWrite(String filePath, String outFile,

Map<String, Object> params, Map<String, List<List<String>>> map)

throws Exception {





InputStream is = new FileInputStream(filePath);

XWPFDocument doc = new XWPFDocument(is);

// 替换段落里面的变量

this.replaceInPara(doc, params);

// 替换表格里面的变量并插入数据

this.insertValueToTable(doc, params, map);

OutputStream os = new FileOutputStream(outFile);

doc.write(os);

this.close(os);

this.close(is);

}





/**

* 替换段落里面的变量



* @param doc

*            要替换的文档

* @param params

*            參数

* @throws Exception 

*/

private void replaceInPara(XWPFDocument doc, Map<String, Object> params) throws Exception {

Iterator<XWPFParagraph> iterator = doc.getParagraphsIterator();

XWPFParagraph para;

while (iterator.hasNext()) {

para = iterator.next();

this.replaceInPara(para, params);

}

}





/**

* 替换段落里面的变量



* @param para

*            要替换的段落

* @param params

*            參数

* @throws Exception 

*/

private String replaceInPara(XWPFParagraph para, Map<String, Object> params) throws Exception {

String str=null;

List<XWPFRun> runs;

XWPFRun run = null;

Matcher matcher;

Matcher mr;

int fontSize=0;

boolean setBold=false;

boolean setItalic=false;

UnderlinePatterns setUnderline=null; 

String setColor="";

int setTextPosition=0;

String setFontFamily=null;





if (this.matcher(para.getParagraphText()).find()) {

runs = para.getRuns();

for (int i = 0; i < runs.size(); i++) {

run = runs.get(i);

String runText = run.toString();

matcher = this.matcher(runText);

if (matcher.find()) {

while ((matcher = this.matcher(runText)).find()) {

runText = matcher.replaceFirst(String.valueOf(params

.get(matcher.group(1))));

}

// 直接调用XWPFRun的setText()方法设置文本时,在底层会又一次创建一个XWPFRun。把文本附加在当前文本后面。

// 所以我们不能直接设值。须要先删除当前run,然后再自己手动插入一个新的run。

fontSize=run.getFontSize();

setBold=run.isBold();

setItalic=run.isItalic();

setUnderline=run.getUnderline();

setColor=run.getColor();

setTextPosition=run.getTextPosition();

setFontFamily=run.getFontFamily();



para.removeRun(i);

XWPFRun runP = para.insertNewRun(i);



runP.setText(runText);

runP.setBold(setBold);

runP.setItalic(setItalic);

runP.setUnderline(setUnderline);

runP.setColor(setColor);

runP.setTextPosition(setTextPosition);



if(fontSize!=-1) runP.setFontSize(fontSize);

if (setFontFamily != null) runP.setFontFamily(setFontFamily);

}

}

} else if ((mr=this.matcherRow(para.getParagraphText())).find()) {

str=mr.group(1)+"";

}

return str;

}





/**

* 按模版行样式填充数据,暂未实现特殊样式填充(如列合并),仅仅能用于普通样式(如段落间距 缩进 字体 对齐)



* @param doc

*            要替换的文档

* @param params

*            參数

* @param resultList

*            须要遍历的数据

* @throws Exception

*/

private void insertValueToTable(XWPFDocument doc,

Map<String, Object> params, Map<String, List<List<String>>> map)

throws Exception {

Iterator<XWPFTable> iterator = doc.getTablesIterator();

XWPFTable table = null;

List<XWPFTableRow> rows = null;

List<XWPFParagraph> paras;

List<XWPFTableCell> tmpCells = null;// 模版列

XWPFTableRow tmpRow = null;// 匹配用

XWPFTableCell tmpCell = null;// 匹配用

int thisRow = 0;

String str=null;

while (iterator.hasNext()) {

List<XWPFTableCell> cells = null;

List<List<String>> resultList=null;

table = iterator.next();

rows = table.getRows();

for (int i = 1; i <= rows.size(); i++) {

cells = rows.get(i - 1).getTableCells();

for (XWPFTableCell cell : cells) {

paras = cell.getParagraphs();

for (XWPFParagraph para : paras) {

str=this.replaceInPara(para, params);

if (str!=null) {

thisRow = i;// 找到模板行

resultList=map.get(str);



tmpRow = rows.get(i - 1);

cells = tmpRow.getTableCells();





}

}

}

}

if (thisRow > 0 && resultList.size()>0) {

this.insertRowToTable(table, tmpRow, tmpCell, thisRow,

resultList, tmpCells, tmpCells);

} else {

System.out.println("该表格中未找到动态标志符");

return;

}

thisRow = 0;

}

}





public void insertRowToTable(XWPFTable table, XWPFTableRow tmpRow,

XWPFTableCell tmpCell, int thisRow, List<List<String>> resultList,

List<XWPFTableCell> tmpCells, List<XWPFTableCell> cells)

throws Exception {

tmpCells = tmpRow.getTableCells();

for (int i = 0, len = resultList.size(); i < len; i++) {

XWPFTableRow row = table.insertNewTableRow(thisRow + i);

row.setHeight(tmpRow.getHeight());

List<String> list = resultList.get(i);

cells = row.getTableCells();

// 插入的行会填充与表格第一行同样的列数

for (int k = 0, klen = cells.size(); k < klen; k++) {

tmpCell = tmpCells.get(k);

XWPFTableCell cell = cells.get(k);

setCellText(tmpCell, cell, list.get(k));

}

// 继续写剩余的列

for (int j = cells.size(), jlen = list.size(); j < jlen; j++) {

tmpCell = tmpCells.get(j);

XWPFTableCell cell = row.addNewTableCell();

setCellText(tmpCell, cell, list.get(j));

}

}

// 删除模版行

table.removeRow(thisRow - 1);

}





public void setCellText(XWPFTableCell tmpCell, XWPFTableCell cell,

String text) throws Exception {

CTTc cttc2 = tmpCell.getCTTc();

CTTcPr ctPr2 = cttc2.getTcPr();





CTTc cttc = cell.getCTTc();

CTTcPr ctPr = cttc.addNewTcPr();

cell.setColor(tmpCell.getColor());

// cell.setVerticalAlignment(tmpCell.getVerticalAlignment());

if (ctPr2.getTcW() != null) {

ctPr.addNewTcW().setW(ctPr2.getTcW().getW());

}

if (ctPr2.getVAlign() != null) {

ctPr.addNewVAlign().setVal(ctPr2.getVAlign().getVal());

}

if (cttc2.getPList().size() > 0) {

CTP ctp = cttc2.getPList().get(0);

if (ctp.getPPr() != null) {

if (ctp.getPPr().getJc() != null) {

cttc.getPList().get(0).addNewPPr().addNewJc()

.setVal(ctp.getPPr().getJc().getVal());

}

}

}





if (ctPr2.getTcBorders() != null) {

ctPr.setTcBorders(ctPr2.getTcBorders());

}





XWPFParagraph tmpP = tmpCell.getParagraphs().get(0);

XWPFParagraph cellP = cell.getParagraphs().get(0);

XWPFRun tmpR = null;

if (tmpP.getRuns() != null && tmpP.getRuns().size() > 0) {

tmpR = tmpP.getRuns().get(0);

}

XWPFRun cellR = cellP.createRun();

cellR.setText(text);

// 复制字体信息

if (tmpR != null) {

cellR.setBold(tmpR.isBold());

cellR.setItalic(tmpR.isItalic());

cellR.setStrike(tmpR.isStrike());

cellR.setUnderline(tmpR.getUnderline());

cellR.setColor(tmpR.getColor());

cellR.setTextPosition(tmpR.getTextPosition());

if (tmpR.getFontSize() != -1) {

cellR.setFontSize(tmpR.getFontSize());

}

if (tmpR.getFontFamily() != null) {

cellR.setFontFamily(tmpR.getFontFamily());

}

if (tmpR.getCTR() != null) {

if (tmpR.getCTR().isSetRPr()) {

CTRPr tmpRPr = tmpR.getCTR().getRPr();

if (tmpRPr.isSetRFonts()) {

CTFonts tmpFonts = tmpRPr.getRFonts();

CTRPr cellRPr = cellR.getCTR().isSetRPr() ? cellR

.getCTR().getRPr() : cellR.getCTR().addNewRPr();

CTFonts cellFonts = cellRPr.isSetRFonts() ?

cellRPr

.getRFonts() : cellRPr.addNewRFonts();

cellFonts.setAscii(tmpFonts.getAscii());

cellFonts.setAsciiTheme(tmpFonts.getAsciiTheme());

cellFonts.setCs(tmpFonts.getCs());

cellFonts.setCstheme(tmpFonts.getCstheme());

cellFonts.setEastAsia(tmpFonts.getEastAsia());

cellFonts.setEastAsiaTheme(tmpFonts.getEastAsiaTheme());

cellFonts.setHAnsi(tmpFonts.getHAnsi());

cellFonts.setHAnsiTheme(tmpFonts.getHAnsiTheme());

}

}

}

}

// 复制段落信息

cellP.setAlignment(tmpP.getAlignment());

cellP.setVerticalAlignment(tmpP.getVerticalAlignment());

cellP.setBorderBetween(tmpP.getBorderBetween());

cellP.setBorderBottom(tmpP.getBorderBottom());

cellP.setBorderLeft(tmpP.getBorderLeft());

cellP.setBorderRight(tmpP.getBorderRight());

cellP.setBorderTop(tmpP.getBorderTop());

cellP.setPageBreak(tmpP.isPageBreak());

if (tmpP.getCTP() != null) {

if (tmpP.getCTP().getPPr() != null) {

CTPPr tmpPPr = tmpP.getCTP().getPPr();

CTPPr cellPPr = cellP.getCTP().getPPr() != null ?

cellP

.getCTP().getPPr() : cellP.getCTP().addNewPPr();

// 复制段落间距信息

CTSpacing tmpSpacing = tmpPPr.getSpacing();

if (tmpSpacing != null) {

CTSpacing cellSpacing = cellPPr.getSpacing() != null ? cellPPr

.getSpacing() : cellPPr.addNewSpacing();

if (tmpSpacing.getAfter() != null) {

cellSpacing.setAfter(tmpSpacing.getAfter());

}

if (tmpSpacing.getAfterAutospacing() != null) {

cellSpacing.setAfterAutospacing(tmpSpacing

.getAfterAutospacing());

}

if (tmpSpacing.getAfterLines() != null) {

cellSpacing.setAfterLines(tmpSpacing.getAfterLines());

}

if (tmpSpacing.getBefore() != null) {

cellSpacing.setBefore(tmpSpacing.getBefore());

}

if (tmpSpacing.getBeforeAutospacing() != null) {

cellSpacing.setBeforeAutospacing(tmpSpacing

.getBeforeAutospacing());

}

if (tmpSpacing.getBeforeLines() != null) {

cellSpacing.setBeforeLines(tmpSpacing.getBeforeLines());

}

if (tmpSpacing.getLine() != null) {

cellSpacing.setLine(tmpSpacing.getLine());

}

if (tmpSpacing.getLineRule() != null) {

cellSpacing.setLineRule(tmpSpacing.getLineRule());

}

}

// 复制段落缩进信息

CTInd tmpInd = tmpPPr.getInd();

if (tmpInd != null) {

CTInd cellInd = cellPPr.getInd() != null ?

cellPPr.getInd()

: cellPPr.addNewInd();

if (tmpInd.getFirstLine() != null) {

cellInd.setFirstLine(tmpInd.getFirstLine());

}

if (tmpInd.getFirstLineChars() != null) {

cellInd.setFirstLineChars(tmpInd.getFirstLineChars());

}

if (tmpInd.getHanging() != null) {

cellInd.setHanging(tmpInd.getHanging());

}

if (tmpInd.getHangingChars() != null) {

cellInd.setHangingChars(tmpInd.getHangingChars());

}

if (tmpInd.getLeft() != null) {

cellInd.setLeft(tmpInd.getLeft());

}

if (tmpInd.getLeftChars() != null) {

cellInd.setLeftChars(tmpInd.getLeftChars());

}

if (tmpInd.getRight() != null) {

cellInd.setRight(tmpInd.getRight());

}

if (tmpInd.getRightChars() != null) {

cellInd.setRightChars(tmpInd.getRightChars());

}

}

}

}

}





/**

* 正则匹配字符串



* @param str

* @return

*/

private Matcher matcher(String str) {

Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}",

Pattern.CASE_INSENSITIVE);

Matcher matcher = pattern.matcher(str);

return matcher;

}





/**

* 正则匹配字符串



* @param str

* @return

*/

private Matcher matcherRow(String str) {

Pattern pattern = Pattern.compile("\\$\\[(.+?

)\\]",

Pattern.CASE_INSENSITIVE);

Matcher matcher = pattern.matcher(str);

return matcher;

}





/**

* 关闭输入流



* @param is

*/

private void close(InputStream is) {

if (is != null) {

try {

is.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}





/**

* 关闭输出流



* @param os

*/

private void close(OutputStream os) {

if (os != null) {

try {

os.close();

} catch (IOException e) {

e.printStackTrace();

}

}

}

}

POI动态生成word2007加强版的更多相关文章

  1. java动态生成带下拉框的Excel导入模板

    在实际开发中,由于业务需要,常常需要进行Excel导入导出操作.以前做一些简单的导入时,先准备一个模板,再进行导入,单有十几. 二十几个导入模板时,往往要做十几.二十几个模板.而且,当在模板中需要有下 ...

  2. freemarker动态生成word并将生成的word转为PDF,openoffice转换word乱码

    之前项目有个需求,需要先动态生成word内容,然后再预览生成word的内容(不能修改).整理一下,方便以后使用. 网上参考了好多大神的博客.具体也忘了参考谁的了,如有侵权,请告知修改. 思路一: 将目 ...

  3. poi自动生成Ecxel表格和Chart图表

    最近因为业务需求,需要做poi自动导出Ecxel表格和Chart折线图的功能. 所以我在网上找到了一篇关于poi生成Chart图表的博客,代码很详细,但是缺少相关注释说明. 想要将它改造成自己需要的样 ...

  4. poi实现生成下拉选联动

    在我们实际的程序开发中,经常需要用到从excel导入数据中系统中,而为了防止用户在excel中乱输入文字,有些需要用到下拉选的地方,就需要从程序中动态生成模板.本例子简单的讲解一下,如何生成级联下拉选 ...

  5. Aop动态生成代理类时支持带参数构造函数

    一.背景 在某些情况下,我们需要植入AOP代码的类并没有默认构造函数.那么此时动态生成的代理类也需要相同签名的构造函数,并且内部调用原始类的构造函数.自己折腾了1晚上没搞定,现在搞定了发出来供大家一起 ...

  6. dynamic-css 动态 CSS 库,使得你可以借助 MVVM 模式动态生成和更新 css,从 js 事件和 css 选择器的苦海中脱离出来

    dynamic-css 使得你可以借助 MVVM 模式动态生成和更新 css,从而将本插件到来之前,打散.嵌套在 js 中的修改样式的代码剥离出来.比如你要做元素跟随鼠标移动,或者根据滚动条位置的变化 ...

  7. ABP(现代ASP.NET样板开发框架)系列之20、ABP展现层——动态生成WebApi

    点这里进入ABP系列文章总目录 ABP(现代ASP.NET样板开发框架)系列之20.ABP展现层——动态生成WebApi ABP是“ASP.NET Boilerplate Project (ASP.N ...

  8. 【.NET深呼吸】Zip文件操作(2):动态生成Zip文档

    通过前面一篇烂文的介绍,大伙儿知道,ZipArchive类表示一个zip文档实例,除了用上一篇文章中所列的方法来读写zip文件外,还可以直接通过ZipArchive类,动态生成zip文件. 文件流操作 ...

  9. jquery动态生成的元素添加事件的方法

    动态生成的元素如果要添加事件,要写成 $(document).on("click", "#txtName", function() { alert(this.v ...

随机推荐

  1. laravel使用redis做缓存的方法

    1.存redis 使用setex命令可以同时设置数据和保存时间 $data = [ 'name'=>zhangsan, , ]; Redis::setex($cacheKey, , serial ...

  2. 洛谷——P2371 EXCEEDED WARNING C(50)

    P2371 EXCEEDED WARNING C 题目背景 第三道溢出警告... 机(wei)智(suo)的TMXi又搬题来坑大家了... 注意时空限制[坏笑] 题目描述 [li]1949年,阿三的数 ...

  3. POJ1751 Highways(Prim)

    Highways Time Limit: 1000MS   Memory Limit: 10000K Total Submissions: 13182   Accepted: 3814   Speci ...

  4. [BZOJ 1293] 生日礼物

    Link: BZOJ 1293 传送门 Solution: 这题直接上尺取法就行了吧 先将每种颜色第一个放入优先队列,用$mx$维护当前的末尾位置 每次取出第一个颜色,更新答案.将其下一个放入队列中去 ...

  5. 【博弈论】【SG函数】Codeforces Round #188 (Div. 1) D. Game with Powers

    将整个游戏可以划分成若干个互不相交的子游戏. 每个子游戏的sg值只与其中的数的个数有关.而这个数不会超过30. 于是可以预处理出这个sg值表. 然后从1到n枚举,对<=sqrt(n)的部分,用个 ...

  6. [USACO2015DEC]Max Flow

    题目大意: 给你一棵n个点的树,有m次操作,每次将给定的路径上所有点的点权+1. 问最后最大的点权是多少. 思路: #include<cstdio> #include<cctype& ...

  7. TZOJ 删除前导多余的*号

    描述 规定输入的字符串中只包含字母和*号,编写程序使字符串中前导的*号不得多于n个:若多于n个,则删除多余的*号:若少于或等于n个,则什么也不做,字符串中间和尾部的*号不删除. 输入 输入数据包括一串 ...

  8. Spring Boot企业微信点餐系统-第一章-课程介绍

    一.项目简介——技术要点 前端和后端: 后端主要技术: 微信接口技术 微信支付 微信扫码登录 微信模板消息推送 开发环境 但实际上我用的环境和这上面还是有点不一样,我服务器用的是win,到时候我会详细 ...

  9. 64945e3dtw1dii6vfdr19j.jpg(PNG 图像,1497x929 像素)

    64945e3dtw1dii6vfdr19j.jpg(PNG 图像,1497x929 像素)

  10. 浅谈RBF函数

    所谓径向基函数 (Radial Basis Function 简称 RBF), 就是某种沿径向对称的标量函数. 通常定义为空间中任一点x到某一中心xc之间欧氏距离的单调函数 , 可记作 k(||x-x ...