java語言Office轉html
阿新 • • 發佈:2018-11-22
轉換工具我選OpenOffice (版本4)+ jodconverter(版本3)。跨平臺,完全免費。
這兩樣工具網上很容易下載到,轉換程式碼也很簡單。主要的工作是對轉換形成的html程式碼進行加工。主要目的有二:
1.修正失真
2.清理掉冗餘程式碼
處理html文字主要工具是正則表示式。不過正則也有侷限,比如匹配標籤對。網上找到一個匹配標籤對的正則,複雜的讓人抓狂。因此我寫一個匹配標籤對的類,它的功能可示例如下:
原文字:"<a><a></a><b><a></a></b><c></c></a>"
對標籤a進行匹配後:"<a1><a2></a-2><b><a3></a-3></b><c></c></a-1>"
package office; import java.util.List; import tools.EasyRegex; /* * 配對原理:一對標籤之間巢狀的子標籤,其開始標誌數量和結束標誌數量相等 */ /** * 配對text文字中查詢到的第一對tag標籤,開始標誌加id,結束標誌加-id * 比如把<a></a> 標識為<a1></a-1> * @author IBM */ public class TagPair { int id = 0; String tag; public String result = ""; /** * @param text * @param tag 標籤名,使用小寫 * @return */ public TagPair(String text,String tag,int id) { this.id = id; this.tag = tag; String re = text; int e =0; int s = 0; int i = re.indexOf(tag); while(i>=0){ if(re.indexOf("<", i-1) == i-1){ s++; if(s == 1){//indexOf大小寫敏感特性這裡正好為我所有,將標誌過的標籤轉為大寫,這樣下次indexOf就不會再把它列入查詢結果 re = re.substring(0, i) + tag.toUpperCase()+ String.valueOf(id) + re.substring(i+tag.length()); } } else if(re.indexOf("</", i-2) == i-2){ e++; if(e == s){ result = re.substring(0, i) + tag.toUpperCase()+ String.valueOf(id*-1) + re.substring(i+tag.length()); break; } } i = re.indexOf(tag,i+tag.length()); } } /** * tag使用小寫 * @param text * @param tag * @return */ public static String pair(String text,String tag) { //String re = toLowercase(text);//如果能保證標籤都是小寫形式可省略此步驟 String re = text; int id = 1; TagPair tp = new TagPair(re,tag,id); while(tp.result.length() > 0){ re = tp.result; tp = new TagPair(tp.result,tag,++id); } return re; } /** * 大小寫不敏感 * @param html * @return */ public static String unPair(String html) { String re = html.replaceAll("(</?[a-gA-Gi-zI-Z]{1,8})(-?\\d{1,5})([^>]*?>)", "$1$3"); return re; } public static String toLowercase(String html) { String re = html; EasyRegex reg = new EasyRegex("<[^>]+?>"); List<String> ms = reg.matchs(re); for(String t : ms){ re = re.replace(t, t.toLowerCase()); } return re; } }
OpenOffice (版本4)+ jodconverter(版本3)轉換程式碼:
package office; import java.io.File; import java.util.List; import org.artofsolving.jodconverter.OfficeDocumentConverter; import org.artofsolving.jodconverter.office.DefaultOfficeManagerConfiguration; import org.artofsolving.jodconverter.office.OfficeManager; import tools.EasyFile; import tools.EasyRegex; public class Office2html { /** * 把office檔案轉換成html * @param file office檔案完整路徑 * @param folder html檔案及其包含資源存放路徑 * @return 返回html純文字內容 */ public static String convert(String file) { OfficeManager officeManager = null; try{ EasyFile f = new EasyFile(file);//這是我的一個工具類,對File進行了一下再包裝,可用File類代替 if(f.isExists()){ String output = f.getFolder() +"/"+f.nameWithoutExt() +".html"; DefaultOfficeManagerConfiguration config = new DefaultOfficeManagerConfiguration(); config.setOfficeHome("C:\\Program Files\\OpenOffice 4"); officeManager = config.buildOfficeManager(); officeManager.start(); OfficeDocumentConverter converter = new OfficeDocumentConverter(officeManager); File outputFile = new File(output); converter.convert(f.getFile(), outputFile);//轉換 String temp = EasyFile.readAllText(output, "GBK"); EasyFile.writeAllText(output, clearFormat(f.fileExt(),temp)); } return ""; } catch(Exception e){ e.printStackTrace(); return ""; } finally{ if (officeManager != null) { officeManager.stop(); } } } /** * ext表示轉換前檔案型別副檔名 * @param ext * @param html * @return */ static String clearFormat(String ext,String html) { String content = html; try{ if(ext.equals("doc") || ext.equals("docx")){ //去除多餘span標籤 content = content.replaceAll("</?SPAN[^>]*?>", ""); content = content.replaceAll("<META[^>]+?charset=[^>]+?>", //設定網頁編碼 "<HEAD>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"); //設定內容寬度並居中(接近A4紙寬度) content = content.replaceAll("<BODY[^>]*?>", "$0\n<div style=\"width:800px;margin:0 auto;\">"); content = content.replaceAll("</BODY>", "</div>\n</BODY>"); content = content.replaceFirst("<BODY", "<BODY style=\"text-align:center;\" "); //讓圖片者水平居中 content = content.replaceAll("<IMG([^>]+)ALIGN=[A-Z]{3,6}", "<IMG$1"); content = content.replaceAll("<IMG[^>]+?>", "<div align=\"center\">$0</div>"); //下面是找出所有帶align屬性的p標籤,改為div(對齊屬性在P標籤裡無效果)。不能把P全變成div,那樣失真嚴重。 content = TagPair.toLowercase(content); content = TagPair.pair(content, "p"); EasyRegex reg = new EasyRegex("(?<=<p)\\d{1,5}(?=.+align=)",true); List<String> ls = reg.matchs(content); for(String s : ls){ content = content.replaceFirst("<P"+s, "<div"); content = content.replaceFirst("</P-"+s, "</div"); } content = TagPair.unPair(content); content = content.replaceAll("line-height: 100%", ""); //這個屬性敗事有餘,取消掉 } else{ EasyRegex reg = new EasyRegex("<META[^>]+?charset=[^>]+?>"); content = content.replaceFirst(reg.match(content), "<HEAD>\n<meta http-equiv=\"Content-Type\" content=\"text/html; charset=utf-8\" />"); //excel中不設邊框依然有淺灰色線,但生成html就啥也沒有顯得太蒼白,所以刻意加上。 if(content.indexOf("border-top:") < 0 && content.indexOf("border-left:")<0){ reg = new EasyRegex("<TABLE[^>]+?>"); content = content.replaceFirst(reg.match(content),// "<TABLE border=\"1\" bordercolor=\"#a0c6e5\" style=\"border-collapse:collapse;\">"); } } } catch(Exception e) { e.printStackTrace(); } return content; } }
注:word中的圖片會被放到和html同位置資料夾下
經過這一番處理,生成的html檔案湊和著能看了。但畢竟word和瀏覽器是不同的軟體,對程式碼的解析有很多不一樣地方。比如有的文字在word中顯示居中,生成html就沒這個效果了。這不是java轉換的問題,是因為那段文字其實本就沒有居中屬性,word只是根據其上下文環境,把它給居中顯示了,但瀏覽器顯然沒這樣功能。
至於表格,由於其本身格式就比較固定,所以在html下表現出來和excel中差別不大。不過我也發現了一個bug,就是在轉換一個較大的excel檔案時,本來某單元格中只有一句話,結果轉換出來後,此格中這句話重複了數十遍,這應該是openoffice或jodconverter的bug。
歡迎大家一起探討、進步!