Java利用mpxj解析mpp格式檔案
阿新 • • 發佈:2019-01-07
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、資料儲存
將解析的結果,經過子任務排序,即獲取每條子任務的父任務,大家可以理解為書本目錄的大綱。
下面看看資料儲存到資料庫後的效果: