查看了在项目管理中需要使用到project软件最终生成的.mpp文件,大概必然有这些实体类
---Task实体类
private Integer id;
private Timestamp start_date;
private Timestamp end_date;
private Integer percent_done;
private String name;
private Integer priority;
private Timestamp baseline_start_date;
private Timestamp baseline_end_date;
private Integer parent_id;
private Double duration;
private String duration_unit;
private String other_field;
private Integer pid;
//默认index都为0 ,不进行排序
private Integer index = 0;
//资源以及任务进度
private String resources; //资源
那么剩下就是project解析了。
对于project解析需要加入三个包
mpxj.jar poi-3.15.jar rtfparserkit-1.8.0.jar
值得注意的是,如果你的MPPReader.read()报错或者不执行时,那么其中一种原因就是你的poi包需要升级版本了
步骤:1.先要解析得到所有的集合.
refreshTaskInfo
// 解析线上mpp文件,同时获取TaskInfo
public static List<TaskInfo> readInputStream(FileInputStream in,String fileName){
List<TaskInfo> taskList = new ArrayList<TaskInfo>();
try{
MPPReader mppRead = new MPPReader();
ProjectFile pf = mppRead.read(in);
System.out.println("fileName:" + fileName);
List<Task> tasks = pf.getAllTasks();
System.out.println("taskSize:" + tasks.size());
for (int i = 0; i < tasks.size(); i++) {
Task task = tasks.get(i);
TaskInfo taskInfo = new TaskInfo();
taskInfo.setTask_id(task.getID());
taskInfo.setTask_unique_id(task.getUniqueID());
taskInfo.setTask_outline_level(task.getOutlineLevel());
taskInfo.setTask_name(task.getName());
taskInfo.setTask_duration(task.getDuration().getDuration());
taskInfo.setTask_start_date(GetDate.DateConvertStr(task.getStart()));
taskInfo.setTask_finish_date(GetDate.DateConvertStr(task.getFinish()));
taskInfo.setTask_resource(getResources(task));
List<Relation> task_predecessors = task.getPredecessors();
taskInfo.setTask_predecessors(getPredecessorsStr(task_predecessors));
taskList.add(taskInfo);
}
}catch (MPXJException e) {
System.out.println("MPXJException:" + e.getMessage());
return null;
} catch (Exception e) {
System.out.println("Exception:" + e.getMessage());
return null;
}
return taskList;
}
//得到资源
@SuppressWarnings("unused")
private static String getResources(Task task){
if(task == null){
return "";
}else{
StringBuffer sb = new StringBuffer();
List<ResourceAssignment> assignments = task.getResourceAssignments();
for(ResourceAssignment ra : assignments){
Resource resource = ra.getResource();
if(resource != null){
sb = sb.append(resource.getName());
}
}
return sb.toString();
}
}
//得到任务进度
public static String getPredecessorsStr(List<Relation> task_predecessors){
if(task_predecessors ==null){
return "";
}else{
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);
}
}
}
}
return sb.toString();
}
}
那么现在是得到了list集合,可是我们通过project文件知道,各个任务之间存在了一个层级关系,所以此时需要用到递归算法。此时感觉发杂了。那么怎么办了?
下面一套源码满足了这个方式
package com.mss.shtoone.bim.util;
import java.util.HashMap;
import java.util.List;
import java.util.Hashtable;
import java.util.Map;
import com.mss.shtoone.bim.entity.BIM_ConstructionPlan;
import com.mss.shtoone.bim.entity.BIM_ConstructionPlanDependency;
import com.mss.shtoone.bim.service.BIMConstructionPlanService;
import java.sql.Timestamp;
import java.text.SimpleDateFormat;
import net.sf.json.JSONException;
import net.sf.json.JSONObject;
import net.sf.mpxj.MPXJException;
import net.sf.mpxj.ProjectFile;
import net.sf.mpxj.Relation;
import net.sf.mpxj.Resource;
import net.sf.mpxj.ResourceAssignment;
import net.sf.mpxj.Task;
import net.sf.mpxj.mpp.MPPReader;
public class ProjectUtil {
public static Map<Integer,String> intMap=new HashMap<Integer, String>(); //key里面存放task中的唯一id和数据中uuid
private static Hashtable dependencyTypes = new Hashtable();
private static Hashtable columnTypes = new Hashtable();
private static Hashtable columnIndexNames = new Hashtable();
private static JSONObject getTaskData(Task task, JSONObject object){
SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
try{
object.put("Id", task.getUniqueID());
object.put("Name", task.getName());
object.put("StartDate", dateFormat.format(task.getStart()));
object.put("EndDate", dateFormat.format(task.getFinish()));
object.put("Duration", task.getDuration().toString().replaceAll("(?!\\.)[\\D]", ""));
object.put("DurationUnit", task.getDuration().getUnits());
object.put("PercentDone", task.getPercentageComplete());
object.put("Milestone", task.getMilestone());
if (task.getBaselineStart() != null){
object.put("BaselineStartDate", task.getBaselineStart());
} else {
object.put("BaselineStartDate", object.get("StartDate"));
}
if (task.getBaselineFinish() != null){
object.put("BaselineEndDate", task.getBaselineFinish());
} else {
object.put("BaselineEndDate", object.get("EndDate"));
}
if (task.getBaselineDuration() != null){
object.put("BaselineDuration", task.getBaselineDuration());
} else {
object.put("BaselineDuration", object.get("Duration"));
}
object.put("leaf", true);
}catch(JSONException e){
System.out.println(e.getMessage());
System.exit(0);
}
return object;
}
private static BIM_ConstructionPlan fetchTaskData(Task task, String parentId,String fileId){
BIM_ConstructionPlan plan =new BIM_ConstructionPlan();
try{
plan.setPlanParentId(parentId);
plan.setPlanPriority(1); //默认设置其优先级都为1
plan.setPlanName(task.getName());
plan.setPlanStartTime(new Timestamp(task.getStart().getTime()));
plan.setPlanEndTime(new Timestamp(task.getFinish().getTime()));
plan.setPlanTimeLimit((int)Double.parseDouble(task.getDuration().toString().replaceAll("(?!\\.)[\\D]", ""))); //工期
plan.setPlanTimeLimitUnit(task.getDuration().getUnits().toString());
plan.setPlanPercentDone(task.getPercentageComplete().doubleValue()); //完成百分比
plan.setPlanResource(getResources(task));
plan.setPlanFileId(fileId);
plan.setPlanState("0");
//备注
}catch(Exception e){
e.printStackTrace();
System.exit(0);
}
return plan;
}
//得到资源
@SuppressWarnings("unused")
private static String getResources(Task task){
if(task == null){
return "";
}else{
StringBuffer sb = new StringBuffer();
List<ResourceAssignment> assignments = task.getResourceAssignments();
for(ResourceAssignment ra : assignments){
Resource resource = ra.getResource();
if(resource != null){
sb = sb.append(resource.getName());
}
}
return sb.toString();
}
}
//得到任务进度
public static String getPredecessorsStr(List<Relation> task_predecessors){
if(task_predecessors ==null){
return "";
}else{
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);
}
}
}
}
return sb.toString();
}
}
/**
* 递归重建任务节点, 该函数被重载了2次
*
* */
public static boolean listHierarchy(ProjectFile projectFile,BIMConstructionPlanService constructionPlanService,String fileId){
boolean flag = false;
//初始化project中的常量和常量的映射
intMap.clear();
//这里有两层嵌套
for(Task tempTask :projectFile.getChildTasks()){
int idx = 0;
for (Task task : tempTask.getChildTasks()) {
//添加最上层任务节点, 第三个参数parentId=0
BIM_ConstructionPlan plan =fetchTaskData(task,null,fileId);
//设置节点在姊妹节点下的顺序
plan.setPlanIndex(idx++);
System.out.print(plan.getPlanName());
//添加到数据库中
constructionPlanService.saveOrUpdate(plan);
//获取保存mpp中id和数据库中id的映射
intMap.put(task.getUniqueID(), plan.getId());
//递归调用
listHierarchy(task, constructionPlanService, plan.getId(),fileId);
}
}
//节点之间的关系
for (Task task : projectFile.getAllTasks()) {
List<Relation> predecessors = task.getPredecessors();
if (predecessors != null && predecessors.isEmpty() == false){
for (Relation relation : predecessors){
BIM_ConstructionPlanDependency dependency = new BIM_ConstructionPlanDependency();
dependency.setSource(intMap.get(relation.getSourceTask().getUniqueID()));
dependency.setTarget(intMap.get(relation.getTargetTask().getUniqueID()));
dependency.setType(getDependencyType(relation.getType().toString()));
dependency.setPlanFileId(fileId);
constructionPlanService.save(dependency);
}
flag=true;
}
}
return flag;
}
private static void listHierarchy(Task task, BIMConstructionPlanService constructionPlanService,String pid,String fileId){
//节点的先后顺序
int idx = 0;
for (Task child : task.getChildTasks()) {
BIM_ConstructionPlan plan =fetchTaskData(child,pid,fileId);
//设置任务的先后顺序
plan.setPlanIndex(idx++);
constructionPlanService.saveOrUpdate(plan);
intMap.put(child.getUniqueID(), plan.getId());
listHierarchy(child, constructionPlanService,plan.getId(),fileId);
}
}
private static void keyValue(Hashtable tab, String key, String value){
tab.put(key, value);
}
private static void addKeys(){
keyValue(dependencyTypes, "FF", "3");
keyValue(dependencyTypes, "FS", "2");
keyValue(dependencyTypes, "SF", "1");
keyValue(dependencyTypes, "SS", "0");
keyValue(columnTypes, "Duration", "durationcolumn");
keyValue(columnTypes, "Start", "startdatecolumn");
keyValue(columnTypes, "Finish", "enddatecolumn");
keyValue(columnTypes, "% Complete", "percentdonecolumn"); //完成情况
keyValue(columnIndexNames, "Task Name", "Name");
keyValue(columnIndexNames, "Baseline Start", "BaselineStartDate");
keyValue(columnIndexNames, "Baseline Finish", "BaselineEndDate");
}
private static int getDependencyType(String content){
Object ret = dependencyTypes.get(content);
return Integer.parseInt(ret.toString());
}
private static String getColumnType(String content){
String ret = columnTypes.get(content).toString();
return ret;
}
private static String getColumnIndexName(String content){
String ret = columnIndexNames.get(content).toString();
return ret;
}
/**
* 导入mpp文件的函数入口
*
*
* */
public static boolean readProject(String path, BIMConstructionPlanService constructionPlanService,String fileId){
boolean flag=false;
MPPReader reader = new MPPReader();
ProjectFile projectFile;
//初始化Map
addKeys();
try {
projectFile = reader.read(path);
flag=listHierarchy(projectFile,constructionPlanService,fileId);
} catch (MPXJException e) {
e.printStackTrace();
}
return flag;
}
}