1. 程式人生 > >java語言Office轉html

java語言Office轉html

轉換工具我選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。


歡迎大家一起探討、進步!