1.用Microsoft Office Word打開word原件;
2.把需要動态修改的内容替換成${XX}的形式,如果有圖檔,盡量選擇較小的圖檔幾十K左右的小圖檔,并調整好位置,占位(小圖檔轉換的base64資料少,便于修改);如下圖

3.另存為,選擇儲存類型Word 2003 XML 文檔(*.xml)【這裡說一下為什麼用Microsoft Office Word打開且要儲存為Word 2003XML,本人親測,用WPS找不到Word 2003XML選項,如果儲存為Word XML,會有相容問題,避免出現導出的word文檔不能用Word 2003打開的問題】,儲存的檔案名不要是中文
4.用notepad++打開檔案;
5. 将文檔内容中需要動态修改内容的地方,換成freemarker的辨別。其實就是Map<String, Object>中key,如${landName};
6.在加入了圖檔占位的地方,會看到一片base64編碼後的代碼,把base64替換成${image},也就是Map<String, Object>中key,值必須要處理成base64;
代碼如:<w:binData w:name="wordml://自定義.png" xml:space="preserve">${xx}</w:binData>
注意:“>${xx}<”這尖括号中間不能加任何其他的諸如空格,tab,換行等符号。
如果需要循環,則使用:<#list maps as map></#list> maps是Map<String, Object>中key,值為數組,map為自定義;
7. 辨別替換完之後,模闆就弄完了,另存為.ftl字尾檔案即可。注意:一定不要用word打開ftl模闆檔案,否則xml内容會發生變化,導緻前面的工作白做了。把最開始得到的doc模闆檔案和ftl檔案放在同一級目錄下
8.代碼部分
pom:
<!-- word導出 -->
<dependency>
<groupId>org.apache.poi</groupId>
<artifactId>poi-scratchpad</artifactId>
<version>3.8</version>
</dependency>
<!-- 生成圖檔-->
<dependency>
<groupId>org.jfree</groupId>
<artifactId>jfreechart</artifactId>
<version>1.0.19</version>
</dependency>
<dependency>
<groupId>org.freemarker</groupId>
<artifactId>freemarker</artifactId>
<version>2.3.23</version>
</dependency>
工具類:
import freemarker.template.Configuration;
import freemarker.template.Template;
import freemarker.template.TemplateException;
import sun.misc.BASE64Decoder;
import sun.misc.BASE64Encoder;
import javax.servlet.http.HttpServletRequest;
import java.io.*;
import java.util.HashMap;
import java.util.Map;
public class DoOffice_word_freemarker {
private Configuration configuration = null;
public DoOffice_word_freemarker() {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
}
public void createDoc(HttpServletRequest request, Map<String, Object> dataMap, String fileName)
throws IOException {
// dataMap 要填入模本的資料檔案
//模闆位址
String tmpFile = request.getSession().getServletContext().getRealPath("/WEB-INF");
configuration.setDirectoryForTemplateLoading(new File(tmpFile));
Template t = configuration.getTemplate("template.ftl");
// 輸出文檔路徑及名稱
File outFile = new File(fileName);
Writer out = null;
FileOutputStream fos = null;
try {
fos = new FileOutputStream(outFile);
OutputStreamWriter oWriter = new OutputStreamWriter(fos, "UTF-8");
// 這個地方對流的編碼不可或缺,使用main()單獨調用時,應該可以,但是如果是web請求導出時導出後word文檔就會打不開,并且包XML檔案錯誤。主要是編碼格式不正确,無法解析。
// out = new BufferedWriter(new OutputStreamWriter(new
// FileOutputStream(outFile)));
out = new BufferedWriter(oWriter);
} catch (FileNotFoundException e1) {
e1.printStackTrace();
}
try {
t.process(dataMap, out);
out.close();
fos.close();
} catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
// System.out.println("---------------------------");
}
// 圖檔處理
public static String getImageStr() {
String imgFile = "f:/123.png";
InputStream is = null;
byte[] data = null;
try {
is = new FileInputStream(imgFile);
data = new byte[is.available()];
is.read(data);
is.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();
return encoder.encode(data);
}
public static boolean Base64ToImage(String imgStr,String imgFilePath) {
// 對位元組數組字元串進行Base64解碼并生成圖檔
BASE64Decoder decoder = new BASE64Decoder();
try {
// Base64解碼
byte[] b = decoder.decodeBuffer(imgStr);
for (int i = 0; i < b.length; ++i) {
if (b[i] < 0) {// 調整異常資料
b[i] += 256;
}
}
OutputStream out = new FileOutputStream("f:/123.png");
out.write(b);
out.flush();
out.close();
return true;
} catch (Exception e) {
return false;
}
}
public static void main(String[] args) throws IOException {
Base64ToImage("","");
Map<String, Object> datas = new HashMap<String, Object>();
datas.put("bianhao", "1232");
datas.put("dushuyi", "1235");
datas.put("weizhi", "1423");
datas.put("tuzhi", "25123");
datas.put("kongshen", "1我23");
datas.put("ksshuiwei", "123");
datas.put("endshuiwei","請問123");
datas.put("kstime", "123");
datas.put("endtime", "1啊23");
datas.put("counttime", "123");
datas.put("result", "1夫人23");
datas.put("img", getImageStr().substring(22,getImageStr().length()));
Map<String, Object> dataMap = new HashMap<String, Object>();
dataMap.put("photo", getImageStr().substring(22,getImageStr().length()));
dataMap.put("name", "Blue");
dataMap.put("gender", "男");
dataMap.put("birth", "1992-2-2");
dataMap.put("grade", "1203班");
dataMap.put("major", "軟體");
dataMap.put("Id", "201219010110");
dataMap.put("phone", "123456");
dataMap.put("roomId", "S-222");
dataMap.put("zhengzhi", "團員");
dataMap.put("IdCard", "411322199202022212");
dataMap.put("address", "河南省鄭州市地球村");
dataMap.put("parent_phone1", "11111111");
dataMap.put("parent_phone2", "22222222");
dataMap.put("gold", "這裡是目标,新學期新氣象,好好學習,天天向上");
DoOffice_word_freemarker mdoc = new DoOffice_word_freemarker();
//mdoc.createDoc(datas, "d:/00.docx");
//System.out.println(getImageStr().substring(22,getImageStr().length()));
}
}
通過圖檔位址擷取圖檔然後轉換成base64格式:
public static String GetImageStrFromUrl(String imgURL) {
byte[] data = null;
try {
// 建立URL
URL url = new URL(imgURL);
// 建立連結
HttpURLConnection conn = (HttpURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setConnectTimeout(5 * 1000);
InputStream inStream = conn.getInputStream();
int count = conn.getContentLength();
data = new byte[count];
int readCount = 0;
while (readCount<count){
readCount += inStream.read(data,readCount,count-readCount);
}
//data = new byte[inStream.available()];
inStream.read(data);
inStream.close();
} catch (IOException e) {
e.printStackTrace();
}
// 對位元組數組Base64編碼
BASE64Encoder encoder = new BASE64Encoder();
// 傳回Base64編碼過的位元組數組字元串
return encoder.encode(data);
}
主業務代碼:
/**
* WORD導出
*/
@RequestMapping(value = "/word", method= RequestMethod.GET)
@ResponseBody
public String word(HttpServletRequest request) throws Exception {
//模闆位址(把最開始得到的doc模闆檔案和ftl檔案放在同一級目錄下)
String tmpFile = request.getSession().getServletContext().getRealPath("/WEB-INF/template.doc");
//導出檔案儲存位址/usr/apache-tomcat-7.0.69/webapps/template.doc
String expFile = "D:/"+ DateUtils.getToday() +".doc";
String daba_points = "JH-05";
String daba_content = "查xx。";
String daba_result = getResult("J1H-05");
String daba_images = FileUtil.GetImageStrFromUrl("圖檔位址");
Map<String, Object> datas = new HashMap<String, Object>();
datas.put("daba_points", daba_points);
datas.put("daba_content", daba_content);
datas.put("daba_result",daba_result);
datas.put("daba_images", daba_images);
DoOffice_word_freemarker mdoc = new DoOffice_word_freemarker();
mdoc.createDoc(request,datas, expFile);
return daba_images;
}
成果: