一、實作功能
1、支援表格、圖像、插入頁腳,其中圖像包含base64 位和 隻傳入圖像路徑
2、要求使用對應的模闆 故隻能作為參考
3、裡面的以下判斷時根據 模闆檔案裡面的key進行的特殊處理
二、代碼(版本 3.15)
package com.hyzs.szcg.doc.utils;
import java.awt.image.BufferedImage;
import java.io.*;
import java.math.BigInteger;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLEncoder;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import com.hyzs.gz.common.core.exception.CommonException;
import com.hyzs.szcg.doc.vo.DocWordUtilVO;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang.StringUtils;
import org.apache.poi.openxml4j.exceptions.InvalidFormatException;
import org.apache.poi.util.Units;
import org.apache.poi.xwpf.model.XWPFHeaderFooterPolicy;
import org.apache.poi.xwpf.usermodel.*;
import org.apache.xmlbeans.impl.xb.xmlschema.SpaceAttribute;
import org.openxmlformats.schemas.wordprocessingml.x2006.main.*;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import sun.misc.BASE64Decoder;
import javax.imageio.ImageIO;
/**
*
* @Title: WordExport.java
* @Description: 導出word文檔
* @author zzh
* @version 1.0
*/
@Slf4j
@Component
public class PoiExportWord {
@Value("${apiKey}")
private String apiKey;
private String templatePath;
private XWPFDocument doc = null;
private FileInputStream is = null;
private OutputStream os = null;
private DocWordUtilVO docWordUtilVO=new DocWordUtilVO();
public DocWordUtilVO init(Map<String,Object> params,String templatePath,String targetPath) throws IOException {
docWordUtilVO.setWordFlag(false);
this.templatePath = templatePath;
File file=new File(this.templatePath);
File fileTarget=new File(targetPath);
if (!fileTarget.getParentFile().exists()){
//目錄不存在則建立目錄
fileTarget.getParentFile().mkdirs();
}
//插入目前時間 年月日
insertDate(params);
if(file.exists()){
is = new FileInputStream(file);
doc = new XWPFDocument(is);
try {
if(export(params)){
docWordUtilVO.setWordFlag(generate(targetPath));
docWordUtilVO.setWordPath(targetPath);
}
} catch (Exception e) {
throw CommonException.exception("文書生成失敗!",e);
}
}else{
// log.error("io error -> 檔案模闆不存在》"+this.templatePath);
throw CommonException.exception("io error 模闆檔案不存在");
}
return docWordUtilVO;
}
/**
* 替換掉占位符
* @param params
* @return
* @throws Exception
*/
public boolean export(Map<String,Object> params) throws Exception{
this.replaceInPara(doc, params);
export(params, 0);//表格資料
return true;
}
/**
* 替換掉表格中的占位符
* @param params
* @param tableIndex
* @return
* @throws Exception
*/
public boolean export(Map<String,Object> params,int tableIndex) throws Exception{
//動态插入表格清單資料
this.insertTable(params);
this.replaceInTable(doc, params,tableIndex);
return true;
}
/**
* 循環生成表格
* @param params
* @return
* @throws Exception
*/
public boolean insertTable(Map<String,Object> params) throws Exception{
this.insertValueToTable(doc, params);
return true;
}
private void insertValueToTable(XWPFDocument doc,Map<String, Object> params) throws Exception {
List<XWPFTable> tableList = doc.getTables();
for (int t=0;t<tableList.size();t++){
//循環表格
XWPFTable table = tableList.get(t);
List<XWPFTableRow> rows = table.getRows();
int temRowNum=0;
String key="";//表格 清單資料的 key
for (int j = 0; j <rows.size() ; j++) {
String rowText = rows.get(j).getCell(0).getText();// 擷取到表格行的第一個單元格
//确定辨別行的位置 辨別行的下一行就是模闆行 模闆行 以 foreachRows_開頭 列 ${foreachRows_giveDocList} giveDocList為表單的key
boolean begin = rowText.indexOf("$")>-1;
boolean end = rowText.indexOf("}")>-1;
if(begin&&end){
Matcher matcher = this.matcher(rowText);
if(matcher.find()){
String keyText = matcher.group().substring(2,matcher.group().length()-1);
if(keyText!=null&&!"".equals(keyText)&&keyText.startsWith("foreachRows_")){
temRowNum=j;
key=StringUtils.removeStart(keyText,"foreachRows_");
break;
}
}
}
}
if(rows.size()<2){
break;
}
if(temRowNum==0&&"".equals(key)){
//該表格不需要動态生成
break;
}
//模闆行
XWPFTableRow tmpRow = rows.get(temRowNum+1);
//擷取清單資料
Object value=params.get(key);
List<Map<String,Object>> listData=new ArrayList<>();
if(value instanceof List){
listData=(List<Map<String,Object>>)value;
}
Map m=new HashMap();
m.putAll(params);
m.remove(key);
for (int i = 0; i < listData.size(); i++) {
Map<String,Object> map = listData.get(i);
map.putAll(m);
map.put("no",i+1);//添加表格序号
//------------------------------------
/* 循環生成模闆行 */
//在表格指定位置新增一行
XWPFTableRow targetRow = table.insertNewTableRow(temRowNum+2+i);
copyRow(targetRow,tmpRow);
List<XWPFTableCell> cells;
List<XWPFParagraph> paras;
cells = targetRow.getTableCells();
for (XWPFTableCell cell : cells) {
paras = cell.getParagraphs();
for (XWPFParagraph para : paras) {
this.replaceInPara(para, map);
}
}
}
table.removeRow(temRowNum);// 删除辨別行
table.removeRow(temRowNum);// 删除模版行
}
}
/**
* 生成word文檔
* @param outDocPath
* @return
* @throws IOException
*/
public boolean generate(String outDocPath){
try {
createFooter();
os = new FileOutputStream(outDocPath);
doc.write(os);
} catch (FileNotFoundException e) {
throw CommonException.exception("文書生成失敗!",e);
}catch (IOException e) {
throw CommonException.exception("文書生成失敗!",e);
}finally {
try {
doc.close();
this.close(os);
this.close(is);
} catch (IOException e) {
throw CommonException.exception("文書IO流關閉失敗!",e);
}
}
return true;
}
/**
* 替換表格裡面的變量
*
* @param doc
* 要替換的文檔
* @param params
* 參數
* @throws Exception
*/
private void replaceInTable(XWPFDocument doc, Map<String, Object> params,int tableIndex) throws Exception {
List<XWPFTable> tableList = doc.getTables();
if(tableList.size()>tableIndex){
for (int i=0;i<tableList.size();i++){
XWPFTable table = tableList.get(i);
List<XWPFTableRow> rows;
List<XWPFTableCell> cells;
List<XWPFParagraph> paras;
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);
}
}
}
}
}
}
/**
* 替換段落裡面的變量
*
* @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
* @throws IOException
* @throws
*/
private boolean replaceInPara(XWPFParagraph para, Map<String, Object> params) throws Exception {
boolean data = false;
List<XWPFRun> runs;
//有符合條件的占位符
if (this.matcher(para.getParagraphText()).find()) {
runs = para.getRuns();
data = true;
Map<Integer,String> tempMap = new TreeMap<>();
for (int i = 0; i < runs.size(); i++) {
XWPFRun run = runs.get(i);
String runText = run.toString();
//以"$"開頭
boolean begin = runText.indexOf("$")>-1;
boolean end = runText.indexOf("}")>-1;
if(begin && end){
tempMap.put(i, runText);
fillBlock(para, params, tempMap, i);
continue;
}else if(begin && !end){
tempMap.put(i, runText);
continue;
}else if(!begin && end){
tempMap.put(i, runText);
fillBlock(para, params, tempMap, i);
continue;
}else{
if(tempMap.size()>0){
tempMap.put(i, runText);
continue;
}
continue;
}
}
} else if (this.matcherRow(para.getParagraphText())) {
runs = para.getRuns();
data = true;
}
return data;
}
/**
* 填充run内容
* @param para
* @param params
* @param tempMap
* @param
* @param
* @throws
* @throws IOException
* @throws Exception
*/
@SuppressWarnings("rawtypes")
private void fillBlock(XWPFParagraph para, Map<String, Object> params,
Map<Integer, String> tempMap, int index)
throws InvalidFormatException, IOException, Exception {
Matcher matcher;
if(tempMap!=null&&tempMap.size()>0){
String wholeText = "";
List<Integer> tempIndexList = new ArrayList<Integer>();
for(Map.Entry<Integer, String> entry :tempMap.entrySet()){
tempIndexList.add(entry.getKey());
wholeText+=entry.getValue();
}
if(wholeText.equals("")){
return;
}
matcher = this.matcher(wholeText);
if (matcher.find()) {
boolean isPic = false;//圖檔辨別
boolean isBasePic = false;//base64圖檔辨別
boolean isTencentPic = false;//騰訊地圖圖檔
boolean isUnderLine=false;//下劃線辨別
boolean checkbox=false;//複選框辨別
boolean isPicList=false;//傳入多張圖檔辨別
List<Map<String,Object>> images=new ArrayList<>();
ByteArrayInputStream inputStream=null;
int width = 0;
int height = 0;
int picType = 0;
String path = null;
String keyText = matcher.group().substring(2,matcher.group().length()-1);
String newRunText = "";
Object value = params.get(keyText);
if(value instanceof String){
newRunText = matcher.replaceFirst(String.valueOf(value));
}else if(value instanceof Map){
Map pic = (Map)value;
if(pic.containsKey("fileSuffix")&&pic.containsKey("filePath")){
//插入圖檔
isPic = true;
path = pic.get("filePath").toString();
//擷取圖檔大小
BufferedImage sourceImg = ImageIO.read(getPicStream(path));
width=sourceImg.getWidth();
height=sourceImg.getHeight();
if(width>200){
width=200;
}
if(height>200){
height=200;
}
if(keyText.endsWith("Sign")||keyText.endsWith("_sign")){//簽名限制大小
width=50;
height=30;
}
picType=sourceImg.getType();
}else if(pic.containsKey("personalSignature")){
// base64字元串的 圖檔形式
isBasePic=true;
//将字元串轉換為byte數組
String file= (String) pic.get("personalSignature");
file=file.replaceFirst("data:image/png;base64,","");
byte[] bytes = new BASE64Decoder().decodeBuffer(file.trim());
//轉化為輸入流
inputStream = new ByteArrayInputStream(bytes);
//擷取圖檔大小
BufferedImage sourceImg = ImageIO.read(new ByteArrayInputStream(bytes));
width = sourceImg.getWidth();
height = sourceImg.getHeight();
if(width>200){
width=200;
}
if(height>200){
height=200;
}
if(keyText.endsWith("Sign")||keyText.endsWith("_sign")){//簽名限制大小
width=50;
height=30;
}
picType=sourceImg.getType();
}else if(pic.containsKey("name")&&pic.containsKey("address")&&pic.containsKey("latitude")){
//是一個 位址
newRunText = matcher.replaceFirst(String.valueOf(pic.get("name")));
}
}else if(value instanceof List){
//在表單中為下拉選擇 在模闆中為文本框
List list=(List)value;
if(list.size()>0){
if(list.get(0) instanceof String){
String listStr=String.join(",",list);
newRunText = matcher.replaceFirst(String.valueOf(listStr));
}else if(list.get(0) instanceof Map){
Map m=(Map) list.get(0);
if(m.containsKey("filePath")&&m.containsKey("fileSuffix")&&m.containsKey("fileName")) {
//是圖檔
//插入圖檔
isPicList=true;
//images
for (int i = 0; i < list.size(); i++) {
Map image=(Map) list.get(i);
//擷取圖檔大小
BufferedImage sourceImg = ImageIO.read(getPicStream(image.get("filePath").toString()));
Map<String,Object> map=new HashMap<>();
map.put("path",image.get("filePath").toString());
map.put("width",400);
map.put("height",250);
map.put("picType",sourceImg.getType());
images.add(map);
}
}else if(m.containsKey("personalSignature")){
// base64字元串的 圖檔形式
isBasePic=true;
//将字元串轉換為byte數組
String file= (String) m.get("personalSignature");
byte[] bytes = new BASE64Decoder().decodeBuffer(file.trim());
//轉化為輸入流
inputStream = new ByteArrayInputStream(bytes);
//擷取圖檔大小
BufferedImage sourceImg = ImageIO.read(new ByteArrayInputStream(bytes));
width = sourceImg.getWidth();
height = sourceImg.getHeight();
if(width>200){
width=200;
}
if(height>200){
height=200;
}
if(keyText.endsWith("Sign")||keyText.endsWith("_sign")){//簽名限制大小
width=50;
height=30;
}
picType=sourceImg.getType();
}else if(m.containsKey("q")&&m.containsKey("a")){
int size=68;
//問答形式
StringBuffer str=new StringBuffer();
for (int i=0;i<list.size();i++){
Map map=(Map) list.get(i);
if(i!=0){
str.append("\n");
}
int lengthQ=getLength(map.get("q").toString());
str.append("問:").append(map.get("q"));
int t;
if(lengthQ>size){
t=3;
if(lengthQ%2==0){
t++;
}
}else{
t=3;
if(lengthQ%2==1){
//t--;
}
}
for (int j = t; (j <size-lengthQ%size)&&(lengthQ%size!=0); j++) {
if(j ==((size-1)-lengthQ%size)){
str.append("_");
}else{
str.append(" ");
}
}
int lengthA=getLength(map.get("a").toString());
if(lengthA>size){
t=3;
if(lengthA%2==0){
t++;
}
}else{
t=3;
if(lengthA%2==1){
// t--;
}
}
str.append("\n答:").append(map.get("a"));
for (int j = t; (j <size-lengthA%size)&&(lengthA%size!=0); j++) {
if(j ==((size-1)-lengthA%size)){
str.append("_");
}else{
str.append(" ");
}
}
}
if(str.length()>0){
isUnderLine=true;
newRunText = matcher.replaceFirst(str.toString());
}
}else{
StringBuffer listStr=new StringBuffer();
for (int i = 0; i <list.size() ; i++) {
Map map=(Map) list.get(i);
if(map.containsKey(keyText+"Label")){
listStr.append(map.get(keyText+"Label")).append(",");
}
}
if(listStr.length()>0){
newRunText = matcher.replaceFirst(listStr.toString().substring(0,listStr.length()-1));
}
}
}
}
}else if(value == null){
//如果value為null 則說明在from表單中沒有傳該值
//判斷 keyText 是否是複選框 key 以 flag 作為字首
if(keyText!=null&&!"".equals(keyText)&&keyText.startsWith("flag_")){
//判斷 params 是否包含 keyText這個Key 若 包含
//截取字元串 列如 flag_sourceType_1 ---> sourceType
//在表單中為下拉選擇 在模闆中為複選框
String str[]=keyText.split("_");
boolean flag=false;
checkbox=true;
if(str.length>2){
//String key=str[2];//StringUtils.substringBetween(keyText,"_","_");
String s[]=new String[str.length-2];
int t=0;
for (int i = 0; i <str.length ; i++) {
if(i!=0&&i!=str.length-1){
s[t]=str[i];
t++;
}
}
String key=StringUtils.join(s, "_");
Object v=params.get(key);
if(v instanceof List){
List list=(List)v;
for (int i = 0; i <list.size() ; i++) {
if(list.get(i) instanceof Map){
Map map=(Map) list.get(i);
if(map.containsKey(key)){
if(map.get(key).toString().equals(str[str.length-1])){
//說明此值被選中
flag=true;
break;
}
}
}else{
if (list.get(i).toString().equals(str[str.length-1])){
//說明此值被選中
flag=true;
break;
}
}
}
}else if(v instanceof String){
if(v.toString().equals(str[str.length-1])){
flag=true;
}
}
}
if (flag){
newRunText = matcher.replaceFirst("■");//■
}else{
newRunText = matcher.replaceFirst("□");//
}
}else if(keyText!=null&&!"".equals(keyText)&&keyText.startsWith("signDate_")){
//以signDate_作為字首的是日期 表單裡面的日期時間
String key=StringUtils.substring(keyText,9);//取出日期對應的圖檔的key
if(params.get(key)!=null){
Object o=params.get(key);
if(o instanceof List){
String date = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
newRunText = matcher.replaceFirst(date);
params.put(keyText,date);
}
if(o instanceof Map){
String date = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
newRunText = matcher.replaceFirst(date);
params.put(keyText,date);
}
if(o instanceof String){//非圖檔簽名
String date = new SimpleDateFormat("yyyy年MM月dd日").format(new Date());
newRunText = matcher.replaceFirst(date);
params.put(keyText,date);
}
}
}else if(keyText!=null&&!"".equals(keyText)&&keyText.startsWith("isNull_")){
//以isNull_作為字首的是當事人證件類型号碼
String key=StringUtils.substring(keyText,7);//取出号碼的key
String[] keys=key.split("_");
if(keys.length>1){
boolean flag=false;
for (int i = 0; i <keys.length ; i++) {
String k=keys[i];
if(params.get(k)!=null){
Object o=params.get(k);
if(o instanceof String){
flag=true;
break;
}
}
}
if(flag){
newRunText = matcher.replaceFirst("■");
}else{
newRunText = matcher.replaceFirst("□");
}
}else{
if(params.get(key)!=null){
Object o=params.get(key);
if(o instanceof String){
newRunText = matcher.replaceFirst("■");
}
}else{
newRunText = matcher.replaceFirst("□");
}
}
}else if(keyText!=null&&!"".equals(keyText)&&keyText.startsWith("isTime_")){
//轉化時間格式
String key=StringUtils.substring(keyText,7);//取出時間的key
//格式轉化
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日HH時mm分");
SimpleDateFormat formatter1 = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
SimpleDateFormat formatter2 = new SimpleDateFormat("yyyy-MM-dd HH:mm");
SimpleDateFormat formatter3 = new SimpleDateFormat("HH:mm");
SimpleDateFormat formatter4 = new SimpleDateFormat("HH時mm分");
SimpleDateFormat formatter5 = new SimpleDateFormat("yyyy年MM月dd日");
SimpleDateFormat formatter6 = new SimpleDateFormat("yyyy-MM-dd");
if(params.get(key)!=null&&!"".equals(params.get(key))&&isValidDate(params.get(key).toString(),"yyyy-MM-dd HH:mm:ss")){
//判斷時間格式是否正确
Date date = null;
try {
date = formatter1.parse(params.get(key).toString());
newRunText = matcher.replaceFirst(formatter.format(date));
} catch (ParseException e) {
newRunText = matcher.replaceFirst(params.get(key)==null?"":params.get(key).toString());
}
}else if(params.get(key)!=null&&!"".equals(params.get(key))&&isValidDate(params.get(key).toString(),"yyyy-MM-dd HH:mm")){
//判斷時間格式是否正确
Date date = null;
try {
date = formatter2.parse(params.get(key).toString());
newRunText = matcher.replaceFirst(formatter.format(date));
} catch (ParseException e) {
newRunText = matcher.replaceFirst(params.get(key)==null?"":params.get(key).toString());
}
}else if(params.get(key)!=null&&!"".equals(params.get(key))&&isValidDate(params.get(key).toString(),"yyyy-MM-dd")){
//判斷時間格式是否正确
Date date = null;
try {
date = formatter6.parse(params.get(key).toString());
newRunText = matcher.replaceFirst(formatter5.format(date));
} catch (ParseException e) {
newRunText = matcher.replaceFirst(params.get(key)==null?"":params.get(key).toString());
}
}else if(params.get(key)!=null&&!"".equals(params.get(key))&&isValidDate(params.get(key).toString(),"HH:mm")){
//判斷時間格式是否正确
Date date = null;
try {
date = formatter3.parse(params.get(key).toString());
newRunText = matcher.replaceFirst(formatter4.format(date));
} catch (ParseException e) {
newRunText = matcher.replaceFirst(params.get(key)==null?"":params.get(key).toString());
}
}
else if(key!=null&&!"".equals(key)&&(key.endsWith("_yyyy")||key.endsWith("_MM")||key.endsWith("_dd"))){
//把前端傳入的日期(yyyy-MM-dd)拆為 yyyy MM dd等
String dateStr="yyyy";
if(key.endsWith("_yyyy")){
key=StringUtils.removeEnd(key,"_yyyy");
dateStr="yyyy";
}else if(key.endsWith("_MM")){
key=StringUtils.removeEnd(key,"_MM");
dateStr="MM";
}else if(key.endsWith("_dd")){
key=StringUtils.removeEnd(key,"_dd");
dateStr="dd";
}
SimpleDateFormat formatter7 = new SimpleDateFormat(dateStr);
if(params.get(key)!=null&&!"".equals(params.get(key))) {
Date date=null;
try{
date=formatter6.parse(params.get(key).toString());
newRunText = matcher.replaceFirst(formatter7.format(date));
}catch (ParseException e){
newRunText = matcher.replaceFirst("");
}
}
}
else{
newRunText = matcher.replaceFirst(params.get(key)==null?"":params.get(key).toString());
}
}else if(keyText!=null&&!"".equals(keyText)&&keyText.startsWith("isTencentApi_")){
//以isTencentApi_作為字首的是 小程式給坐标點 背景調用騰訊api擷取圖檔寫入文書
String key=StringUtils.removeStart(keyText,"isTencentApi_");
if(params.get(key)!=null&&!"".equals(params.get(key))){
Object v=params.get(key);
if (v instanceof Map){
Map m=(Map)v;
if(m.containsKey("name")&&m.containsKey("address")&&m.containsKey("latitude")&&m.containsKey("longitude")){
StringBuilder stringBuffer = new StringBuilder();
String latitude=m.get("latitude").toString();
String longitude=m.get("longitude").toString();
try {
stringBuffer.append("zoom=18");
stringBuffer.append("&markers=color:blue"+ URLEncoder.encode("|", "utf-8")+"label:A"+URLEncoder.encode("|", "utf-8")+latitude+","+longitude);
stringBuffer.append("&key="+apiKey);
stringBuffer.append("&size=400*300");
stringBuffer.append("&format=png");
stringBuffer.append("&maptype=roadmap");
} catch (UnsupportedEncodingException e) {
log.error("文書調用騰訊api失敗");
throw CommonException.exception("文書調用騰訊api失敗!",e);
}
byte[] bytes=TencentApiUtil.doGetHttps(stringBuffer.toString());
if(bytes!=null&&bytes.length>0){
//轉化為輸入流
inputStream = new ByteArrayInputStream(bytes);
isTencentPic=true;
width=400;
height=300;
picType=XWPFDocument.PICTURE_TYPE_PNG;
}
}
}
}
}else if (keyText!=null&&!"".equals(keyText)&&keyText.startsWith("isUnderLine_")){
//isUnderLine_ 開頭的需要一整行下劃線 列 : isUnderLine_4_isAvoid
String keyS="isUnderLine_";
String key=StringUtils.removeStart(keyText,keyS);// 列 4_isAvoid
//取出變量前面有幾個位元組
String str1=key.substring(0, key.indexOf("_"));
int count=0;
if(StringUtils.isNumeric(str1)){
count=Integer.parseInt(str1);//列如 4
}
key=StringUtils.removeStart(key,count+"_");
if(params.get(key)!=null&&!"".equals(params.get(key))){
Object v=params.get(key);
String contextStr="";
if (v instanceof String || v instanceof Map){
int size=68;
StringBuffer str=new StringBuffer();
if (v instanceof String){
contextStr=v.toString();
str.append(v.toString());
}else if(v instanceof Map){
//前端傳入的位址
Map m=(Map)v;
if(m.containsKey("name")&&m.containsKey("address")&&m.containsKey("latitude")&&m.containsKey("longitude")){
str.append(m.get("address").toString());
contextStr=m.get("address").toString();
}
}
int length=getLength(contextStr)+count;
int t=0;
for (int j = t; (j <size-length%size)&&(length%size!=0); j++) {
if(j ==((size-1)-length%size)){
str.append("_");
}else{
str.append(" ");
}
}
if(str.length()>0){
isUnderLine=true;
newRunText = matcher.replaceFirst(str.toString());
}
}
}
}else if (keyText!=null&&!"".equals(keyText)&&keyText.startsWith("currentTime")){
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日HH時mm分");
String dateStr=formatter.format(new Date());
newRunText = matcher.replaceFirst(dateStr);
}else if (keyText!=null&&!"".equals(keyText)&&keyText.startsWith("currentDate")){
SimpleDateFormat formatter = new SimpleDateFormat("yyyy年MM月dd日");
String dateStr=formatter.format(new Date());
newRunText = matcher.replaceFirst(dateStr);
}else if (keyText!=null&&!"".equals(keyText)&&keyText.startsWith("signature")){
docWordUtilVO.setSignFlag(true);
docWordUtilVO.setKeyWord(".sign~");
newRunText = matcher.replaceFirst(".sign~");
}else if (keyText!=null&&!"".equals(keyText)&&keyText.equals("other")){
newRunText = matcher.replaceFirst(" _");
}
}
//模闆樣式
XWPFRun tempRun = null;
// 直接調用XWPFRun的setText()方法設定文本時,在底層會重新建立一個XWPFRun,把文本附加在目前文本後面,
// 是以我們不能直接設值,需要先删除目前run,然後再自己手動插入一個新的run。
for(Integer pos : tempIndexList){
tempRun = para.getRuns().get(pos);
tempRun.setText("", 0);
}
if(isPic){
//addPicture方法的最後兩個參數必須用Units.toEMU轉化一下
//para.insertNewRun(index).addPicture(getPicStream(path), picType, "測試",Units.toEMU(width), Units.toEMU(height));
tempRun.addPicture(getPicStream(path), picType, "圖檔",Units.toEMU(width), Units.toEMU(height));
}else if(isPicList){
for (int i = 0; i <images.size() ; i++) {
tempRun.addPicture(getPicStream(images.get(i).get("path").toString()), Integer.parseInt(images.get(i).get("picType").toString()), "圖檔",Units.toEMU(Integer.parseInt(images.get(i).get("width").toString())), Units.toEMU(Integer.parseInt(images.get(i).get("height").toString())));
tempRun.addBreak();
}
}else if(isBasePic){
//base64圖檔加載
tempRun.addPicture(inputStream, picType, "圖檔",Units.toEMU(width), Units.toEMU(height));
}else if(isTencentPic){
//地圖選點通過騰訊api擷取的圖檔
tempRun.addPicture(inputStream, picType, "圖檔",Units.toEMU(width), Units.toEMU(height));
}else{
//樣式繼承
if(newRunText.indexOf("\n")>-1){
String[] textArr = newRunText.split("\n");
if(textArr.length>0){
//設定字型資訊
String fontFamily = tempRun.getFontFamily();
int fontSize = tempRun.getFontSize();
//logger.info("------------------"+fontSize);
for(int i=0;i<textArr.length;i++){
if(i==0){
tempRun.setText(textArr[0],0);
}else{
if(StringUtils.isNotEmpty(textArr[i])){
XWPFRun newRun=para.createRun();
//設定新的run的字型資訊
newRun.setFontFamily(fontFamily);
if(isUnderLine){//設定下滑線
newRun.setUnderline(UnderlinePatterns.SINGLE);
}
if(fontSize==-1){
newRun.setFontSize(10);
}else{
newRun.setFontSize(fontSize);
}
if(checkbox){
newRun.setFontSize(20);
}
newRun.addBreak();
newRun.setText(textArr[i], 0);
}
}
}
}
}else{
tempRun.setText(newRunText,0);
}
}
}
tempMap.clear();
}
}
/**
* 正則比對字元串
*
* @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 boolean matcherRow(String str) {
Pattern pattern = Pattern.compile("\\$\\[(.+?)\\]",
Pattern.CASE_INSENSITIVE);
Matcher matcher = pattern.matcher(str);
return matcher.find();
}
private InputStream getPicStream(String picPath) throws Exception{
//FileInputStream fis = new FileInputStream(new File(picPath));
URL url = new URL(picPath);
//打開連結
HttpURLConnection conn = (HttpURLConnection)url.openConnection();
//設定請求方式為"GET"
conn.setRequestMethod("GET");
//逾時響應時間為20秒
conn.setConnectTimeout(20 * 1000);
//通過輸入流擷取圖檔資料
InputStream fis = conn.getInputStream();
return fis;
}
/**
* 關閉輸入流
*
* @param is
*/
private void close(InputStream is) {
if (is != null) {
try {
is.close();
} catch (IOException e) {
log.error("文書關閉輸入流失敗");
throw CommonException.exception("文書關閉輸入流失敗!",e); }
}
}
/**
* 關閉輸出流
*
* @param os
*/
private void close(OutputStream os) {
if (os != null) {
try {
os.close();
} catch (IOException e) {
log.error("文書關閉輸出流失敗");
throw CommonException.exception("文書關閉輸入流失敗!",e); }
}
}
/**
* 判斷時間格式是否正确
* @param
* @return
*/
public static boolean isValidDate(String strDate,String strFormat) {
SimpleDateFormat formatter = new SimpleDateFormat(strFormat);
try{
Date date = formatter.parse(strDate);
String s=formatter.format(date);
return strDate.equals(formatter.format(date));
}catch(Exception e){
return false;
}
}
public void copyRow(XWPFTableRow targetRow,XWPFTableRow sourceRow){
//複制行屬性
targetRow.getCtRow().setTrPr(sourceRow.getCtRow().getTrPr());
List<XWPFTableCell> cellList = sourceRow.getTableCells();
if (null == cellList) {
return;
}
//複制列及其屬性和内容
XWPFTableCell targetCell = null;
for (XWPFTableCell sourceCell : cellList) {
targetCell = targetRow.addNewTableCell();
//列屬性
targetCell.getCTTc().setTcPr(sourceCell.getCTTc().getTcPr());
//段落屬性
if(sourceCell.getParagraphs()!=null&&sourceCell.getParagraphs().size()>0){
targetCell.getParagraphs().get(0).getCTP().setPPr(sourceCell.getParagraphs().get(0).getCTP().getPPr());
if(sourceCell.getParagraphs().get(0).getRuns()!=null&&sourceCell.getParagraphs().get(0).getRuns().size()>0){
XWPFRun cellR = targetCell.getParagraphs().get(0).createRun();
cellR.setText(sourceCell.getText());
cellR.setBold(sourceCell.getParagraphs().get(0).getRuns().get(0).isBold());
}else{
targetCell.setText(sourceCell.getText());
}
}else{
targetCell.setText(sourceCell.getText());
}
}
}
public static int getLength(String s) {
int length = 0;
for (int i = 0; i < s.length(); i++) {
int ascii = Character.codePointAt(s, i);
if (ascii >= 0 && ascii <= 255) {
length++;
} else {
length += 2;
}
}
return length;
}
//插入年月日
private void insertDate(Map<String, Object> params) {
Calendar calendar = Calendar.getInstance();
params.put("nowYear",calendar.get(Calendar.YEAR)+"");
params.put("nowMonth",(calendar.get(Calendar.MONTH+1)<10)?"0"+calendar.get(Calendar.MONTH+1):calendar.get(Calendar.MONTH+1)+"");
params.put("nowDay",(calendar.get(Calendar.DAY_OF_MONTH)<10)?"0"+calendar.get(Calendar.DAY_OF_MONTH):calendar.get(Calendar.DAY_OF_MONTH)+"");
params.put("nowHour",(calendar.get(Calendar.HOUR_OF_DAY)<10)?"0"+calendar.get(Calendar.HOUR_OF_DAY):calendar.get(Calendar.HOUR_OF_DAY)+"");
params.put("nowMinute",(calendar.get(Calendar.MINUTE)<10)?"0"+calendar.get(Calendar.MINUTE):calendar.get(Calendar.MINUTE)+"");
params.put("nowSecond",(calendar.get(Calendar.SECOND)<10)?"0"+calendar.get(Calendar.SECOND):calendar.get(Calendar.SECOND)+"");
}
//生成頁腳
public void createFooter(){
/*
* 生成頁腳段落
* 給段落設定寬度為占滿一行
* */
CTSectPr sectPr=doc.getDocument().getBody().addNewSectPr();
XWPFHeaderFooterPolicy headerFooterPolicy=new XWPFHeaderFooterPolicy(doc,sectPr);
try {
XWPFFooter footer=headerFooterPolicy.createFooter(STHdrFtr.DEFAULT);
XWPFParagraph paragraph = footer.getParagraphArray(0);
paragraph.setAlignment(ParagraphAlignment.LEFT);
paragraph.setVerticalAlignment(TextAlignment.CENTER);
paragraph.setBorderTop(Borders.THICK);
CTTabStop tabStop = paragraph.getCTP().getPPr().addNewTabs().addNewTab();
tabStop.setVal(STTabJc.RIGHT);
int twipsPerInch = 1440;
tabStop.setPos(BigInteger.valueOf(6 * twipsPerInch));
/*
* 給段落建立元素
* */
XWPFRun run = paragraph.createRun();
setXWPFRunStyle(run,"宋體",8);
run.addTab();
String s=run.getFontFamily();
/*
* 生成頁碼
* 頁碼右對齊
* */
run = paragraph.createRun();
run.setText("第");
setXWPFRunStyle(run,"宋體",8);
run = paragraph.createRun();
CTFldChar fldChar = run.getCTR().addNewFldChar();
fldChar.setFldCharType(STFldCharType.Enum.forString("begin"));
setXWPFRunStyle(run,"宋體",8);
run = paragraph.createRun();
CTText ctText = run.getCTR().addNewInstrText();
ctText.setStringValue("PAGE \\* MERGEFORMAT");
ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve"));
setXWPFRunStyle(run,"宋體",8);
fldChar = run.getCTR().addNewFldChar();
fldChar.setFldCharType(STFldCharType.Enum.forString("end"));
run = paragraph.createRun();
run.setText("頁/共");
setXWPFRunStyle(run,"宋體",8);
run = paragraph.createRun();
fldChar = run.getCTR().addNewFldChar();
fldChar.setFldCharType(STFldCharType.Enum.forString("begin"));
run = paragraph.createRun();
ctText = run.getCTR().addNewInstrText();
ctText.setStringValue("NUMPAGES \\* MERGEFORMAT ");
ctText.setSpace(SpaceAttribute.Space.Enum.forString("preserve"));
setXWPFRunStyle(run,"宋體",8);
fldChar = run.getCTR().addNewFldChar();
fldChar.setFldCharType(STFldCharType.Enum.forString("end"));
run = paragraph.createRun();
run.setText("頁");
setXWPFRunStyle(run,"宋體",8);
} catch (IOException e) {
throw CommonException.exception("頁腳設定失敗!",e);
}
}
/**
* 設定頁腳的字型樣式
*
* @param r1 段落元素
*/
private void setXWPFRunStyle(XWPFRun r1,String font,int fontSize) {
r1.setFontSize(fontSize);
CTRPr rpr = r1.getCTR().isSetRPr() ? r1.getCTR().getRPr() : r1.getCTR().addNewRPr();
CTFonts fonts = rpr.isSetRFonts() ? rpr.getRFonts() : rpr.addNewRFonts();
fonts.setAscii(font);
fonts.setEastAsia(font);
fonts.setHAnsi(font);
}
}