package com.sisa.auweb.tools.bookmarkprocess; import org.apache.poi.openxml4j.opc.OPCPackage; import org.apache.poi.xwpf.usermodel.*; import org.apache.xmlbeans.impl.piccolo.io.FileFormatException; import java.io.*; import java.lang.reflect.Field; import java.util.*; import java.util.regex.Matcher; import java.util.regex.Pattern; import static feign.Util.toByteArray; /** * Created by clyan on 2019/7/2 15:15. */ public class Word2007 { private String wordPath = ""; private String writeFilePath = ""; private Object obj = null; Map<String, Object> map = new HashMap<String, Object>(); /* path:文件路徑 dataSource/objectMap:數據源. */ public Word2007(String path, String newFilePath, Object dataSource, Map<String, Object> objectMap) throws IOException { File file = new File(path); if (file.exists() == false || file.isFile() == false) { throw new FileNotFoundException("文件不存在"); } InputStream is = new FileInputStream(file); byte[] bytes = new byte[10]; if (is.read(bytes, 0, bytes.length) == -1) { is.close(); throw new FileFormatException("文件格式錯誤,本文件只能解析docx文件"); } String fileCode = bytesToHexString(bytes).toLowerCase(); if (fileCode.length() > 1) { if (fileCode.equals("504b0304140006000800") == false) { is.close(); throw new FileFormatException("文件格式錯誤,本文件只能解析docx文件"); } } is.close(); wordPath = path; writeFilePath = newFilePath; obj = dataSource; if (dataSource != null) { pickFields(); } else { this.map = objectMap; } } public void parseTemplate() { try { InputStream is = new FileInputStream(wordPath); XWPFDocument doc = new XWPFDocument(OPCPackage.open(is)); List<XWPFParagraph> list = doc.getParagraphs(); for (int i = 0; i < list.size(); i++) { XWPFParagraph graph = list.get(i); replaceInXWPFParagraph(graph, map); } replaceTables(map, doc); OutputStream os = new FileOutputStream(writeFilePath); doc.write(os); os.flush(); close(os); close(is); } catch (Exception ex) { System.out.print(ex.getStackTrace()); } } private void replaceInXWPFParagraph(XWPFParagraph para, Map<String, Object> params) { List<XWPFRun> runs = null; Matcher matcher; String runText = ""; if (matcher(para.getParagraphText()).find()) { runs = para.getRuns(); if (runs.size() > 0) { int j = runs.size(); for (int i = 0; i < j; i++) { XWPFRun run = runs.get(i); String i1 = run.toString(); runText += i1; } } int replaceCount = runText.trim().split("\\$").length - 1; matcher = matcher(runText); if (matcher.find()) { while ((matcher = matcher(runText)).find()) { runText = String.valueOf(params.get(matcher.group(1))); } //數據源不存在時跳過,以便檢查 if (runText.equals("null")) { runText = ""; } if (runs.size() > 0) { boolean handler = false; for (int i = 0; i < runs.size(); i++) { XWPFRun run = runs.get(i); String temp = run.toString(); if (handler == false && temp.indexOf("$") >= 0) { handler = true; } if (handler == true) { if (temp.equals("$") || temp.indexOf("$") == 0) { if (temp.indexOf("}") >= 0) { run.setText(runText, 0); handler = false; //一行有多個${狀況 replaceCount--; if (replaceCount > 0) { runText = ""; int j = runs.size(); for (int x = 0; x < j; x++) { XWPFRun run1 = runs.get(x); String i1 = run1.toString(); runText += i1; } matcher = matcher(runText); if (matcher.find()) { while ((matcher = matcher(runText)).find()) { runText = String.valueOf(params.get(matcher.group(1))); } } } } else { run.setText("", 0); } continue; } if (temp.indexOf("}") < 0) { run.setText("", 0); continue; } if (temp.indexOf("}") >= 0) { run.setText(runText, 0); handler = false; //一行有多個${狀況 replaceCount--; if (replaceCount > 0) { runText = ""; int j = runs.size(); for (int x = 0; x < j; x++) { XWPFRun run1 = runs.get(x); String i1 = run1.toString(); runText += i1; } matcher = matcher(runText); if (matcher.find()) { while ((matcher = matcher(runText)).find()) { runText = String.valueOf(params.get(matcher.group(1))); } } } } } } } } } } private void pickFields() { Class dataClass = (Class) obj.getClass(); Field[] fs = dataClass.getDeclaredFields(); for (int i = 0; i < fs.length; i++) { Field f = fs[i]; f.setAccessible(true); Object val = new Object(); try { val = f.get(obj); map.put(f.getName(), val); } catch (IllegalArgumentException e) { e.printStackTrace(); } catch (IllegalAccessException e) { e.printStackTrace(); } } } private byte[] generalFileContent() throws IOException { InputStream is = new FileInputStream(writeFilePath); byte[] data = toByteArray(is); is.close(); return data; } private void close(InputStream is) { if (is != null) { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } } private void close(OutputStream os) { if (os != null) { try { os.close(); } catch (IOException e) { e.printStackTrace(); } } } private String bytesToHexString(byte[] src) { StringBuilder stringBuilder = new StringBuilder(); if (null == src || src.length < 1) return null; for (byte b : src) { int v = b & 0xFF; String hv = Integer.toHexString(v); if (hv.length() < 2) stringBuilder.append(0); stringBuilder.append(hv); } return stringBuilder.toString(); } private static Matcher matcher(String str) { Pattern pattern = Pattern.compile("\\$\\{(.+?)\\}", Pattern.CASE_INSENSITIVE); Matcher matcher = pattern.matcher(str); return matcher; } private void replaceTable(Map<String, Object> params, XWPFTable table) { int count = table.getNumberOfRows(); for (int i = 0; i < count; i++) { XWPFTableRow row = table.getRow(i); List<XWPFTableCell> cells = row.getTableCells(); for (XWPFTableCell cell : cells) { List<XWPFParagraph> list = cell.getParagraphs(); for (int j = 0; j < list.size(); j++) { replaceInXWPFParagraph(list.get(j), params); } } } } private void replaceTables(Map<String, Object> params, XWPFDocument document) { Iterator<XWPFTable> itTable = document.getTablesIterator(); while (itTable.hasNext()) { XWPFTable table = itTable.next(); replaceTable(params, table); } } }