1. 程式人生 > >Java利用mpxj解析mpp格式檔案

Java利用mpxj解析mpp格式檔案

1、mpp檔案介紹

MPP是Microsoft Project專案管理軟體的副檔名,此軟體旨在幫助個人跟蹤,組織或維護專案。

2、mpp顯示效果

這裡寫圖片描述

3、mpp結構說明

通過上圖可以看出,檔案主體內容就是一條一條的記錄,記錄內容包括:任務ID、任務名、Duration、Start日期、Finish日期、Predecessors業務流、自定義欄位。

接下來,我們先來了解下mpp文件的解析工具類,目前主要是通過MPXJ工具類來解析該檔案。

例項中引入的maven依賴版本:

<dependency>
	<groupId>net.sf.mpxj</groupId>
<artifactId>mpxj</artifactId> <version>5.2.2</version> </dependency>

Package net.sf.mpxj.mpp
上面這個包是處理MPP檔案解析的主要集合,通過net.sf.mpxj.mpp.MPPReader類來構建讀檔案管道。

每條具體的任務都需要通過這個類net.sf.mpxj.Task來解析。

// 普通任務ID
Integer task_id =task.getID();
// 獨立任務ID
Integer task_unique_id =task.getUniqueID
(); // 大綱ID Integer task_outline_level =task.getOutlineLevel(); // 任務週期 double task_duration =task.getDuration().getDuration(); // 任務名 String task_name = task.getName(); // 任務開始日期 Date task_start_date = task.getStart(); // 任務結束日期 Date task_finish_date = task.getFinish(); // 任務流 List<Relation> task_predecessors =
task.getPredecessors();

4、mpp解析程式碼

解析線上mpp檔案,同時獲取TaskInfo

// NO.1 解析mpp檔案,同時獲取TaskInfo
	public static List<TaskInfo> readInputStream(InputStream in,String fileName){
		
		List<TaskInfo> taskList = new ArrayList<TaskInfo>();
		InputStream ins = in;
		
		try{		    
		    MPPReader mppRead = new MPPReader();
		    ProjectFile pf = mppRead.read(in);
		    logger.info("MPXJUtils.method [readInputStream]: fileName-" + fileName);

		    List<Task> tasks = pf.getAllTasks();
		    logger.info("MPXJUtils.method [readInputStream]: taskSize-" + tasks.size());
		    
		    for (int i = 0; i < tasks.size(); i++) {
		    	Task task = tasks.get(i);
		    	
		    	Integer task_id = task.getID();
		    	Integer task_unique_id = task.getUniqueID();
		    	Integer task_outline_level = task.getOutlineLevel();
		    	double task_duration = task.getDuration().getDuration();
		    	String task_name = task.getName();
		    	Date task_start_date = task.getStart();
		    	Date task_finish_date = task.getFinish();
		    	List<Relation> task_predecessors = task.getPredecessors();		    			    	
		    	logger.info("MPXJUtils.method [readInputStream] taskInfo:" + task_id + "|" + task_unique_id + "|" + task_outline_level + "|" + task_duration + "|" + task_start_date + "|" + task_finish_date + "|" + task_predecessors);
		    	
		    	// 封裝TaskInfo
		    	java.sql.Date sqlStartDate = Str2Date.getUKDate(task_start_date.toString());				// StartDate轉換
		    	java.sql.Date sqlFinishDate = Str2Date.getUKDate(task_finish_date.toString());				// FinishDate轉換
		    	StringBuffer sb = new StringBuffer();
		    	if(task_predecessors != null){
		    		if(task_predecessors.size() > 0){
		    			for(Relation relation : task_predecessors){
		    				Integer targetTaskId = relation.getTargetTask().getID();
		    				if(sb.length() == 0){
		    					sb.append(targetTaskId);
		    				}else{
		    					sb.append(","+targetTaskId);
		    				}
		    			}
		    		}
		    	}
		    	String task_predecessors_str = sb.toString();												// 任務流文字
		    	
		    	TaskInfo taskInfo = new TaskInfo();
		    	taskInfo.setTask_id(task_id);
		    	taskInfo.setTask_unique_id(task_unique_id);
		    	taskInfo.setTask_outline_level(task_outline_level);
		    	taskInfo.setTask_name(task_name);
		    	taskInfo.setTask_duration(task_duration);
		    	taskInfo.setTask_start_date(sqlStartDate);
		    	taskInfo.setTask_finish_date(sqlFinishDate);
		    	taskInfo.setTask_predecessors(task_predecessors_str);
		    	
		    	taskList.add(taskInfo);		    	
		    }		        
		}catch (MPXJException e) {
			logger.info("MPXJUtils.method [readInputStream]: MPXJException-" + e);
		    return null;  
		} catch (Exception e) { 
			logger.info("MPXJUtils.method [readInputStream]: MPXJException-" + e);
			return null;  
		} finally {			
			try {
				ins.close();
			} catch (IOException e) {
				// TODO Auto-generated catch block
				logger.info("MPXJUtils.method [readInputStream]: IOException-" + e);
				return null;  
			}
		}
		return taskList;
	}

封裝過的TaskInfo

public class TaskInfo {
	
	private int project_id;							// 所屬專案ID
	private int task_id;							// 任務ID
	private int task_unique_id;						// 任務唯一ID
	private int parent_id;							// 父任務ID
	private int task_outline_level;					// 任務級別
	private String task_name;						// 任務名稱
	private double task_duration;					// 任務工期
	private java.sql.Date task_start_date;			// 任務開始時間
	private java.sql.Date task_finish_date;			// 任務結束時間
	private String task_predecessors;				// 任務流
	private String task_operator;					// 負責人
	
	public int getProject_id() {
		return project_id;
	}
	public void setProject_id(int project_id) {
		this.project_id = project_id;
	}
	public int getTask_id() {
		return task_id;
	}
	public void setTask_id(int task_id) {
		this.task_id = task_id;
	}
	public int getTask_unique_id() {
		return task_unique_id;
	}
	public void setTask_unique_id(int task_unique_id) {
		this.task_unique_id = task_unique_id;
	}
	public int getParent_id() {
		return parent_id;
	}
	public void setParent_id(int parent_id) {
		this.parent_id = parent_id;
	}
	public int getTask_outline_level() {
		return task_outline_level;
	}
	public void setTask_outline_level(int task_outline_level) {
		this.task_outline_level = task_outline_level;
	}
	public double getTask_duration() {
		return task_duration;
	}
	public void setTask_duration(double task_duration) {
		this.task_duration = task_duration;
	}
	public Date getTask_start_date() {
		return task_start_date;
	}
	public void setTask_start_date(Date task_start_date) {
		this.task_start_date = task_start_date;
	}
	public Date getTask_finish_date() {
		return task_finish_date;
	}
	public void setTask_finish_date(Date task_finish_date) {
		this.task_finish_date = task_finish_date;
	}
	public String getTask_predecessors() {
		return task_predecessors;
	}
	public void setTask_predecessors(String task_predecessors) {
		this.task_predecessors = task_predecessors;
	}
	public String getTask_operator() {
		return task_operator;
	}
	public void setTask_operator(String task_operator) {
		this.task_operator = task_operator;
	}
	public String getTask_name() {
		return task_name;
	}
	public void setTask_name(String task_name) {
		this.task_name = task_name;
	}
}

解析本地mpp檔案方法,供測試使用

public static List<TaskInfo> readFile(){
		
		List<TaskInfo> taskList = new ArrayList<TaskInfo>();
		try{	
			File file = new File("/Users/ffff/Downloads/計劃(含月度版)V0.10-20160222.mpp");
		    MPPReader mppRead = new MPPReader();
		    ProjectFile pf = mppRead.read(file);
		    logger.info("MPXJUtils.method [readFile]: fileName-" + file.getName());

		    List<Task> tasks = pf.getAllTasks();
		    logger.info("MPXJUtils.method [readFile]: taskSize-" + tasks.size());
		    
		    for (int i = 0; i < tasks.size(); i++) {
		    	Task task = tasks.get(i);
		    	
		    	Integer task_id = task.getID();
		    	Integer task_unique_id = task.getUniqueID();
		    	Integer task_outline_level = task.getOutlineLevel();
		    	double task_duration = task.getDuration().getDuration();
		    	Date task_start_date = task.getStart();
		    	Date task_finish_date = task.getFinish();
		    	List<Relation> task_predecessors = task.getPredecessors();		    			    	
		    	logger.info("MPXJUtils.method [readFile] taskInfo:" + task_id + "|" + task_unique_id + "|" + task_outline_level + "|" + task_duration + "|" + task_start_date + "|" + task_finish_date + "|" + task_predecessors);
		    	
		    	// 封裝TaskInfo
		    	java.sql.Date sqlStartDate = Str2Date.getUKDate(task_start_date.toString());			// StartDate轉換
		    	java.sql.Date sqlFinishDate = Str2Date.getUKDate(task_finish_date.toString());			// FinishDate轉換
		    	StringBuffer sb = new StringBuffer();
		    	if(task_predecessors != null){
		    		if(task_predecessors.size() > 0){
		    			for(Relation relation : task_predecessors){
		    				Integer targetTaskId = relation.getTargetTask().getID();
		    				if(sb.length() == 0){
		    					sb.append(targetTaskId);
		    				}else{
		    					sb.append(","+targetTaskId);
		    				}
		    			}
		    		}
		    	}
		    	String task_predecessors_str = sb.toString();											// 任務流文字
		    	
		    	TaskInfo taskInfo = new TaskInfo();
		    	taskInfo.setTask_id(task_id);
		    	taskInfo.setTask_unique_id(task_unique_id);
		    	taskInfo.setTask_outline_level(task_outline_level);
		    	taskInfo.setTask_duration(task_duration);
		    	taskInfo.setTask_start_date(sqlStartDate);
		    	taskInfo.setTask_finish_date(sqlFinishDate);
		    	taskInfo.setTask_predecessors(task_predecessors_str);
		    	
		    	taskList.add(taskInfo);		    	
		    }		        
		}catch (MPXJException e) {
			logger.info("MPXJUtils.method [readFile]: MPXJException-" + e);
		    return null;  
		} catch (Exception e) { 
			logger.info("MPXJUtils.method [readFile]: MPXJException-" + e);
			return null;  
		} 		
		return taskList;
	}

本地測試,輸出mpp檔案結果:
這裡寫圖片描述

獲取子任務間的所屬父子關係

// NO.2 獲取TaskInfo之間的父子關聯關係
	public static List<TaskInfo> refreshTaskInfo(List<TaskInfo> taskList){
		
		List<Map<String,Integer>> tempTaskOutLine = new ArrayList<Map<String,Integer>>();
		for(TaskInfo taskInfo : taskList){
			
			int taskId = taskInfo.getTask_id();
			int taskOutLineLevel = taskInfo.getTask_outline_level();			
			int listSize = tempTaskOutLine.size();
			logger.info("MPXJUtils.method [refreshTaskInfo1]: taskId-" + taskId + ",taskOutLineLevel-" + taskOutLineLevel + ",listSize-" + listSize);
			
			// 初始化taskOutLineLevel
			if(listSize > 2){				
				if(taskOutLineLevel == 1){					
					for(int i=listSize;i>2;i--){
						tempTaskOutLine.remove(i-1);
					}
					listSize = 2;	
					logger.info("MPXJUtils.method [refreshTaskInfo2]: taskId-" + taskId + ",taskOutLineLevel-" + taskOutLineLevel + ",listSize-" + listSize);
				}				
			}
			
			
			Map<String,Integer> map = new HashMap<String,Integer>();
			map.put("taskId", taskId);
			map.put("taskOutLineLevel", taskOutLineLevel);
			
			if(listSize == 0){
				
				if(taskOutLineLevel == 0){
					tempTaskOutLine.add(map);
				}else{
					return null;
				}
				
			}else{
				
				Map<String,Integer> lastMap = tempTaskOutLine.get(listSize-1);
				int lastTaskId = lastMap.get("taskId");
				int lastTaskOutLineLevel = lastMap.get("taskOutLineLevel");
				
				if(taskOutLineLevel > lastTaskOutLineLevel){
								
					tempTaskOutLine.add(map);
					taskInfo.setParent_id(lastTaskId);
				}else if(taskOutLineLevel == lastTaskOutLineLevel){	
					
					tempTaskOutLine.set(taskOutLineLevel, map);
					
					Map<String,Integer> lastMap1 = tempTaskOutLine.get(taskOutLineLevel-1);
					int lastTaskId1 = lastMap1.get("taskId");
					taskInfo.setParent_id(lastTaskId1);
				}else if(taskOutLineLevel < lastTaskOutLineLevel){					
					
					tempTaskOutLine.set(taskOutLineLevel, map);
					
					Map<String,Integer> lastMap2 = tempTaskOutLine.get(taskOutLineLevel-1);
					int lastTaskId2 = lastMap2.get("taskId");
					taskInfo.setParent_id(lastTaskId2);
				}
			}						
		}
		
		return taskList;
	}	

5、資料儲存

將解析的結果,經過子任務排序,即獲取每條子任務的父任務,大家可以理解為書本目錄的大綱。
這裡寫圖片描述

下面看看資料儲存到資料庫後的效果:
這裡寫圖片描述