網友ping留言問了JS DOCX套版元件問題,由其所提供下載位置(https://github.com/djpate/docxgen)的Readme文件,判斷是PHP所開發,直覺地認為所謂JS套版是JavaScript呼叫PHP完成。但ping後續補充: 真的是純JavaScript,並提供可執行的程式包,我這才驚覺:
啥咪!! 真有神人用純JavaScript寫出DOCX套版元件?
DOCX的本質是ZIP壓縮打包的一堆XML檔案,理論上只要能解壓ZIP、解析及操作XML,就能完成文件修改。我但沒過這一切可以全用JavaScript解決? node.js揮軍Server端,Espruino殺進嵌入系統,今天的JavaScript,沒有極限!
做了簡單解析,發現它依賴base64.js(Base64編碼)、jszip.js(ZIP壓縮解壓),其餘只靠一個docxgen.js搞定全部工作。要執行套版時,只要先準備一個Word文件,在其中穿插{ tag1}、{tag2}註明要置換成其他文字的位置,執行如下JavaScript,就可得到套版後的Word檔。
new DocxGen().loadFromFile("tagExample.docx", { async: true })
.success(function(doc){
doc.setTags({ tag1:"tag1Value", tag2:"tag2Value" });
doc.applyTags() //apply them replace all occurences of {tag*}
doc.output() //Output the document using Data-URI
});
原程式的tagExample.docx需透過XHR存取,Chrome預設開啟本機HTML執行時不允許XHR存取本地磁碟機檔案,嫌外加Chrome啟動參數麻煩,又不想為此丟到IIS測試,於是用了Object URL技巧,改選取本機檔案作為XHR下載對象。如此,就能直接在本機用Chrome測試。操作示範如下:
tagExample.docx內含{last_name} {first_name}等標籤,在<textarea>編輯JSON字串定義好first_name, last_name等要置換的文字,選取檔案後按下【套版】,馬上能下載套版好的Word檔,其中{last_name}等標籤都已被換成指定的文字。但示範也突顯ping所說的中文變亂碼問題。例如: "黑暗執行緒"變成"黑暗執行緒"。
既是純JavaScript,就一定能Trace Code、找出問題並修正。想到這裡,手就癢了,馬上開啟Chrome偵錯工具,找到docxgen.js。但發現它被Minify壓縮:
不怕,點一下左下的Pretty print鈕,Chrome立刻將JavaScript程式碼縮排整理妥當,恭請長官審閱:
設下中斷點一路追蹤,查出一處可疑:
DocUtils.encode_utf8 = function (e) { return unescape(encodeURIComponent(e)); }
函式目的應是將文字轉為utf8編碼,但感覺套在中文會出包。以console測試unescape(encodeURIComponent("黑暗執行緒")),果然傳回"黑暗執行緒",跟Word成品中的亂碼一致,驗證是encode_utf8把中文轉壞了!
如果這樣不行,該怎麼克服? 想起"&#unicode;"的Unicode字元表示法,將encode_utf8改成:
DocUtils.encode_utf8 = function (e) {
var r = [];
for (var i = 0; i < e.length; i++) {
var asc = e.charCodeAt(i);
r.push("&#" + asc + ";");
}
return r.join("");
}
雖然轉為"&#nnnn;"後長度會增加,至少確保編碼正確無誤。薑!薑!薑!薑~ Bug被修掉囉!
最後,花一點時間聊聊這個JavaScript版套版元件—docxgen.js。
網路上關於它的討論很少,較完整的說明只有法國javascript-ninja網站的Demo網頁,由網站直接瀏覽目錄找到Readme.md(文件寫入時間是2014-2-18),說明裡提到它支援Chrome 26+、Firefox 3+,Safari沒測過,IE不行(連IE10都不行,理由是XHR無法處理純Binary檔案)。由於檔案日期很新,或許是個尚未公開的Open Source Project吧! 我個人認為,直接置換XML {tag}的做法在遇到Word儲存的複雜樣式時,可能還有些地雷要掃。若限定必須在非Windows主機直接進行DOCX套表,這絕對是很出色的解決方案。