前言: 模版填充
前一篇文章讲述了如何将中组部任免审批表lrmx格式的文件读取到我们自定义的Person类中,本篇文章主要讲述如何生成word文档. 生成的文件docx的格式,这里就不考虑doc格式的情况了.使用的模版也是docx. 一般采用word模版都会在需要插入的位置添加标记符,然后使用字符串替换的方式来实现,考虑到干部任免审批表的内容主要是表格。将整个文件作为一个大的表格来处理这种思路
一、需要使用到的主要包:
主要使用的org.apache.poi 下的如下几个包,版本也许略有不同,但没有太大影响.
java
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-ooxml</artifactId>
<version>3.15</version>
</dependency>
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.15</version>
</dependency>
二、核心处理思路:
处理的前提是我们默认已经将中组部任免审批表lrmx格式的文件中的内容读到到我们定义的Person类中,并且建立了空白模版文件存在项目目录下。模版的内容如下,就是用干部任免审批表软件导出一个word即可,里面不要有填写任何数据。
1. 加载模版文件:
将模版文件以文件流的形式读取,并初始化一个XWPFDocument 对象用于后续的处理。
java
FileInputStream in = new FileInputStream(this.TmplateFilePath);// 加载文档
XWPFDocument xwpf = new XWPFDocument(in);
2. 处理填表人的内容填写:
从上图我们可以看到任免审批表的内容填写绝大部分都是在一个大的表格里面,只有填表人在页尾部分。
表格里面呈报单位,审批机关意见,行政机关任免意见在实际工作中,这些地方都是任免过程中打印出来后手工填写的,所以前期我们处理包括数据库建设都没有这一块的内容。对于填表人位置的填写,处理方法是遍历所有的 XWPFParagraph (段落对象), 然后在遍历该段落对象下面的XWPFRun (文本对象) ,如果该文本对象中含有"填表人:" 四个字符, 那么就把填表人的信息填充进去。代码如下:
java
List<XWPFParagraph> plist = xwpf.getParagraphs();
for (XWPFParagraph ph : plist){
for (XWPFRun r : ph.getRuns()){
if(r.getText(0).equals("填表人:")){
r.setText(p.getTianBiaoRen());
}
}
}
3. 照片的处理:
从模版可以看出,审批表的主体部分是7列若干行,照片是放在第一行的第7列, 需要调用XWPFTable对象来获取审批表中所有的表格。需要注意整体的第一个表格不是我们所需要的主体部分。干部任免审批表几个字所在位置也是个表格。
前面我们已经将照片转换为base64的字符串进行存储,那么需要先把字符串穿换位byte数组。
java
byte[] b = Base64.getDecoder().decode(p.getZhaoPian());
然后通过XWPFRun 类的 addPicture方法将图片插入到文档中
java
run.addPicture(new ByteArrayInputStream(b), Document.PICTURE_TYPE_JPEG, "", 363 * 3600, 490 * 3600);
4. 内容的填充:
遍历文档所有的表格,然后再遍历行,再遍历列,如果这个单元格有内容,那么提取他单元格内容来决定他旁边单元格的内需要填充的内容.
java
List<XWPFTable> tables = xwpf.getTables();
for (int num = 0; num < tables.size(); num++) { //遍历所有表格
//遍历所有的表
XWPFTable tb = tables.get(num);
for (int i = 0; i < tb.getNumberOfRows(); i++) { //遍历所有行
for (int j = 0; j < tb.getRow(i).getTableCells().size(); j++) {
//遍历所有列
}
}
5. 完整的实现代码如下:
java
public void PersonToDocx() { //将Person对象写入输出docx文件
Person p = this.DoConvert();
if (p != null) {
String targetFilePath = LrmxFilePath.substring(0, LrmxFilePath.length() - 5) + "-任免审批表.docx"; //保存到lrxm文件所在目录
File f2 = new File(targetFilePath);
if (f2.exists()) {
f2.delete();
}
try {
FileInputStream in = new FileInputStream(this.TmplateFilePath);// 加载文档
XWPFDocument xwpf = new XWPFDocument(in);
List<XWPFParagraph> plist = xwpf.getParagraphs();
for (XWPFParagraph ph : plist){
for (XWPFRun r : ph.getRuns()){
if(r.getText(0).equals("填表人:")){
r.setText(p.getTianBiaoRen());
}
}
}
List<XWPFTable> tables = xwpf.getTables();
if (!p.getZhaoPian().trim().replaceAll("\r", "").replaceAll("\n", "").equals("")) { //如果照片不是空
//照片在模板文件表 1 row 0 cell 6
XWPFTableCell imageCell = tables.get(1).getRow(0).getTableCells().get(6);
XWPFParagraph pg = imageCell.getParagraphs().get(0);
XWPFRun run = pg.createRun();
byte[] b = Base64.getDecoder().decode(p.getZhaoPian());
InputStream sbs = new ByteArrayInputStream(b);
run.addPicture(new ByteArrayInputStream(b), Document.PICTURE_TYPE_JPEG, "", 363 * 3600, 490 * 3600);
}
Boolean ifFirst = true;
for (int num = 0; num < tables.size(); num++) {
//遍历所有的表
XWPFTable tb = tables.get(num);
for (int i = 0; i < tb.getNumberOfRows(); i++) {
//遍历所有的行
for (int j = 0; j < tb.getRow(i).getTableCells().size(); j++) {
//遍历所有单元格
// System.out.println(num + "," + i + "," + j + " " + tb.getRow(i).getCell(j).getText().trim().replaceAll(" ", ""));
switch (tb.getRow(i).getCell(j).getText().trim().replaceAll(" ", "")) {
case "姓名":
if (num == 1) {
tb.getRow(i).getCell(j + 1).setText(p.getXingMing());
}
break;
case "性别":
tb.getRow(i).getCell(j + 1).setText(p.getXingBie());
break;
case "出生年月(岁)":
tb.getRow(i).getCell(j + 1).setText(p.getChuShengNianYue().substring(0, 4) + "." + p.getChuShengNianYue().substring(4, 6) + "(" + p.getNianLing() + "岁)");
break;
case "民族":
tb.getRow(i).getCell(j + 1).setText(p.getMinZu());
break;
case "籍贯":
tb.getRow(i).getCell(j + 1).setText(p.getJiGuan());
break;
case "出生地":
tb.getRow(i).getCell(j + 1).setText(p.getChuShengDi());
break;
case "入党时间":
tb.getRow(i).getCell(j + 1).setText(p.getRuDangShiJian());
break;
case "参加工作时间":
tb.getRow(i).getCell(j + 1).setText(p.getCanJiaGongZuoShiJian());
break;
case "健康状况":
tb.getRow(i).getCell(j + 1).setText(p.getJianKangZhuangKuang());
break;
case "专业技术职务":
tb.getRow(i).getCell(j + 1).setText(p.getZhuanYeJiShuZhiWu());
break;
case "熟悉专业有何专长":
tb.getRow(i).getCell(j + 1).setText(p.getShuXiZhuanYeYouHeZhuanChang());
break;
case "全日制教育":
XWPFParagraph pg = tb.getRow(i).getCell(j + 1).getParagraphs().get(0);
XWPFRun run = pg.createRun();
run.setText(p.getQuanRiZhiJiaoYu_XueLi());
run.addBreak();
run.setText(p.getQuanRiZhiJiaoYu_XueWei());
break;
case "毕业院校系及专业":
if (ifFirst) {
XWPFParagraph pg2 = tb.getRow(i).getCell(j + 1).getParagraphs().get(0);
XWPFRun run2 = pg2.createRun();
run2.setText(p.getQuanRiZhiJiaoYu_XueLi_BiYeYuanXiaoXi());
run2.addBreak();
run2.setText(p.getQuanRiZhiJiaoYu_XueWei_BiYeYuanXiaoXi());
ifFirst = false;
} else {
XWPFParagraph pg3 = tb.getRow(i).getCell(j + 1).getParagraphs().get(0);
XWPFRun run3 = pg3.createRun();
run3.setText(p.getZaiZhiJiaoYu_XueLi_BiYeYuanXiaoXi());
run3.addBreak();
run3.setText(p.getZaiZhiJiaoYu_XueWei_BiYeYuanXiaoXi());
ifFirst = true;
}
break;
case "在职教育":
XWPFParagraph pg4 = tb.getRow(i).getCell(j + 1).getParagraphs().get(0);
XWPFRun run4 = pg4.createRun();
run4.setText(p.getZaiZhiJiaoYu_XueLi());
run4.addBreak();
run4.setText(p.getZaiZhiJiaoYu_XueWei());
break;
case "现任职务":
tb.getRow(i).getCell(j + 1).setText(p.getXianRenZhiWu());
break;
case "拟任职务":
tb.getRow(i).getCell(j + 1).setText(p.getNiRenZhiWu());
break;
case "拟免职务":
tb.getRow(i).getCell(j + 1).setText(p.getNiMianZhiWu());
break;
case "简历":
int lastLine = 1;
XWPFParagraph pg5 = tb.getRow(i).getCell(j + 1).getParagraphs().get(0);
XWPFRun run5 = pg5.createRun();
for (JianLi jl : p.getJianLi()) {
if (lastLine != p.getJianLi().size()) {
if (ifFirst) {
run5.setText(jl.getKaiShiNianYue() + "--" + jl.getJieSuNianYue() + " " + jl.getJingLi());
ifFirst = false;
} else {
tb.getRow(i).getCell(j + 1).addParagraph().createRun().setText(jl.getKaiShiNianYue() + "--" + jl.getJieSuNianYue() + " " + jl.getJingLi());
}
lastLine++;
} else {
tb.getRow(i).getCell(j + 1).addParagraph().createRun().setText(jl.getKaiShiNianYue() + "--" + " " + jl.getJieSuNianYue() + " " + jl.getJingLi());
}
}
break;
case "奖惩情况":
tb.getRow(i).getCell(j + 1).setText(p.getJiangChengQingKuang());
break;
case "年核度结考果":
tb.getRow(i).getCell(j + 1).setText(p.getNianDuKaoHeJieGuo());
break;
case "任免理由":
tb.getRow(i).getCell(j + 1).setText(p.getRenMianLiYou());
break;
case "家庭主要成员及重要社会关系":
List<JiaTingChengYuan> jtcyList = p.getJiaTingChengYuan();
for (int m = 0; m < jtcyList.size(); m++) {
XWPFTableRow tr = tb.getRow(i + m + 1);
tr.getCell(1).setText(jtcyList.get(m).getChengWei());
tr.getCell(2).setText(jtcyList.get(m).getXingMing());
tr.getCell(3).setText(String.valueOf(jtcyList.get(m).getNianLing()));
tr.getCell(4).setText(jtcyList.get(m).getZhengZhiMianMao());
tr.getCell(5).setText(jtcyList.get(m).getGongZuoDanWeiJiZhiWu());
}
break;
case "呈报单位":
tb.getRow(i).getCell(j + 1).setText(p.getChengBaoDanWei());
break;
}
}
}
}
FileOutputStream fos = new FileOutputStream(targetFilePath);
xwpf.write(fos);
fos.close();
in.close();
} catch (Exception ex) {
myloger.error(p.getXingMing() + "," + ex.getMessage());
}
}
}
总结:
整个生成word的过程没有太多的难度,主要还是实际编写代码过程中,一些细节上东西的修正了.