關於用Java編寫生成word文檔,動態添加數據到word文檔的一些心得,經過翻閱了無數的有用的和無用的資料以後,總算找到了一種靠譜的方法
1.概述
經過反反覆覆的查閱資料,總算找到了一個靠譜的生成word的方案,這裏分享給大家.
2.需求
首先我們的需求是通過一個指定的word模板來生成新的word並且填充內容,內容是我們在佈局頁面上面就寫好的,比如說EditText,TextView,或者是圖片ImageView,填充完內容之後,在頁面上進行點擊操作,生成新的word,可以指定路徑,內容自動填充到新生成word文檔中
3.方案
3.1 概述
這裏引用
http://www.open-open.com/doc/view/54c09cfaab9b43638fb1f6beb5d5f2eb 上面所講到的幾種方案。
3.1.1 jadoc
3.1.2 apache poi
3.1.3 java2word
3.1.4 iText
3.1.5 jsp
3.1.6 xml的方式
最終得出結論,這幾種方法 要麼就是操作太簡陋,沒有實現我們這樣複雜的需求,要麼就是不太好用。期間還去研究過一個名爲Jword的一個第三方,除去試用期只有30天,不是免費的之外,本身Jword自帶的jar包內含方法太多,導致出現 65536的問題,需要我們分 dex,分jar,去除沒用的方法,這裏這種大費周章的搞,不是我們的目的。
4.實現
4.1使用freemarker實現我們的需求
4.4.1 自己新建一個 word的模板 模板中指定需要填寫的內容的字段 如 name, type等
4.2.2.新建word文檔模板之後,保存爲xml格式的文件,保存之後打開編輯,在xml中修改我們的字段爲${name}等,修改之後可以通過代碼的方式來寫入內容到wrod中
4.2.3.利用freemarker 來實現 生成word、動態添加數據到word中
5.demo運行項目
5.1 這裏我們以 java項目爲例,Android項目類似,只需要添加文件讀寫權限即可。
5.2 這裏新建的模板爲 doc格式。
這裏我們指定每一項的字段,有圖片或者文件時不需要處理。
5.3 模板有了之後我們保存爲*xml 文件 ,打開編輯xml文件,用crtl+f 的方法 去找我們對應的NAME、SEX 並且將其改爲
${NAME}、${SEX}...
這裏我們需要找到類似這樣的標籤
<w:t>.......</w:t>
,然後將其修改爲
</w:t>${NAME}</w:t>
所有的字符串字段均作爲修改,這裏需要注意,當我們有圖片時,我們需要找的標籤是這樣的
w:binData w:name="wordml://02000001.jpg" xml:space="preserve">${image}</w:binData>
//這裏 ${image} 已經是修改之後的值,沒修改之前爲 一串很長的值,我們替換掉
這裏我已經修改過,原來的裏面是一堆很長很長的亂碼,我們直接用我給的這個給替換掉,代碼中用image去寫一張新的圖片進去。
5.4 至此,我們的xml修改成功,修改完成之後,我們需要修改生成的 xml後綴名 爲 ftl 格式,生成之後放到我們的項目之下,這個模板就當做我們word的模板,下面的事情就是寫代碼進去,將我們的內容填充進去,main函數中申明我們的模板
public static void main(String[] args){
Freemark freemark = new Freemark("template/");//這裏如果放在了具體的包名下,需要修改爲 "/com/test/template/"
freemark.setTemplateName("簡歷-朱老師.ftl");
freemark.setFileName("doc_"+new SimpleDateFormat("yyyy-MM-dd hh-mm-ss").format(new Date())+".doc");//生成的word名稱
freemark.setFilePath("D:/");//生成word存儲路徑
freemark.createWord();//生成方法
}
創建word的方法
private void createWord(){
Template t = null;
try {
t = configuration.getTemplate(templateName);
} catch (IOException e) {
e.printStackTrace();
}
File outFile = new File(filePath+fileName);
Writer out = null;
try {
out = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(outFile), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (FileNotFoundException e) {
e.printStackTrace();
}
Map map = new HashMap<String, Object>();
map.put("NAME", "韓滿義");
map.put("image", getImageStr());
map.put("SEX", "男");
map.put("BIRTH", "1987-08");
map.put("ZZMM", "黨員");
map.put("MZ", "漢");
map.put("JG", "河北省");
map.put("JKZK", "良好");
map.put("SG", "173cm");
map.put("HYZK", "已婚");
map.put("XL", "本科");
map.put("BYYX", "河北工業大學");
map.put("ZY", "軟件工程");
map.put("ZP", "照片//todo");
map.put("QZYX", "軟件方向工作薪資1w上下");
map.put("JYSH1", "06-09-01~10-06-20");
map.put("JYYZ1", "河北工業大學 軟件工程");
map.put("JYXW1", "學士學位");
map.put("JYKC1", "軟件工程、微積分、軟件過程管理、數據庫原理等等");
map.put("JYSH2", "10-07-01~至今");
map.put("JYYZ2", "ABCDE大學");
map.put("JYXW2", "XYZ學位");
map.put("JYKC2", "POI課程");
map.put("ZYJN", "軟件開發、軟件管理");
map.put("GZSH1", "10-07-01~11-12-09");
map.put("GZDZ1", "華信軟件");
map.put("GZGY1", "初級軟件工程師");
map.put("GZSH2", "11-12-15~14-4-05");
map.put("GZDZ2", "北京久其");
map.put("GZGY2", "高級軟件工程師");
map.put("JLQK", "二三等獎學金、富士通獎學金等");
map.put("ZWPJ", "興趣豐富、好奇心強、有研究精神。");
map.put("DH", "0312-3132098");
map.put("SJ", "15033768387");
map.put("YJ", "[email protected]");
map.put("DZ", "河北省保定市");
map.put("YB", "071000");
try {
t.process(map, out);
out.close();
} catch (TemplateException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
下面是類裏面的其餘方法:
/**
* freemark初始化
* @param templatePath 模板文件位置
*/
public Freemark(String templatePath) {
configuration = new Configuration();
configuration.setDefaultEncoding("utf-8");
configuration.setClassForTemplateLoading(this.getClass(),templatePath);
}
/**
* 得到圖片
* @return
*/
private String getImageStr() {
String imgFile = "D:/hanmanyi/pic/111.jpg";//需要在D盤下指定的目錄下放一張圖片
InputStream in = null;
byte[] data = null;
try {
in = new FileInputStream(imgFile);
data = new byte[in.available()];
in.read(data);
in.close();
} catch (IOException e) {
e.printStackTrace();
}
BASE64Encoder encoder = new BASE64Encoder();//這裏會報錯
return encoder.encode(data);
}
/**
* freemark模板配置
*/
private Configuration configuration;
/**
* freemark模板的名字
*/
private String templateName;
/**
* 生成文件名
*/
private String fileName;
/**
* 生成文件路徑
*/
private String filePath;
public String getFileName() {
return fileName;
}
public void setFileName(String fileName) {
this.fileName = fileName;
}
public String getFilePath() {
return filePath;
}
public void setFilePath(String filePath) {
this.filePath = filePath;
}
public String getTemplateName() {
return templateName;
}
public void setTemplateName(String templateName) {
this.templateName = templateName;
}
6.需要注意的問題
6.1 word模板如果有圖片或者是文件,需要有一張默認的圖片,即要賦值,不能爲空 ,如果不寫,則編譯不成功
6.2 BASE64ENCODE 出現的錯誤,這裏需要修改我們的編譯環境,以eclipse爲例,我們需要 windows->preference-> java->compiler->Error/warning->
這裏需要修改爲warning,不要弄成error
6.3 用我們自己的word模板時,需要用mircosoft ofice軟件,用WPS是無法通過編譯的,這裏已經測試過,具體office 2003破解版的下載地址在:http://www.xitongzhijia.net/soft/30642.html
6.4 如果我們想在安卓客戶端實現此處功能,建議後臺服務器寫一個接口,客戶端傳遞參數生成word文檔,之後返回客戶端,本項目爲web應用的項目,嘗試將項目改爲Android項目,運行報錯,Configration 在初始化過程中出錯,無法執行下去。
這裏整個word文檔的生成就已經完成,具體下載地址在 我的博客:http://download.csdn.net/detail/xzytl60937234/9623392