首先介绍下MPP文件和XER文件,国内都是MPP 后缀文件,国外基本上都是用的XER后缀文件。
DBTMLX网站是一个MPP在线网站提供免费的API接口但是速度较慢,所以为了安全性、请求速度决定按照他们家的API数据格式重新写一个服务。
MPP文件内容
Maven 我引入最新的包,经过尝试老版本的不支持project2007以上版本,解析会出现问题,所以大家可以按照我的版本来,不踩坑。
<dependency>
<groupId>net.sf.mpxj</groupId>
<artifactId>mpxj</artifactId>
<version>12.2.0</version>
</dependency>
然后创建我们的实体类
任务类
public class TaskInfo {
private int project_id;
// 所属项目ID
private int id; // 任务ID
private int task_unique_id; // 任务唯一ID
private String parent; // 父任务ID
private String task_type; // 任务类型(FS,SS,FF,SF)
private int task_outline_level; // 任务级别
private String text; // 任务名称
private double duration; // 任务工期
private Date start_date; // 任务开始时间
private Date task_finish_date; // 任务结束时间
private String task_predecessors; // 任务流
private String task_operator; // 负责人
private int progress; // 进度
private String type; //类型
}
关联关系类
public class Link {
/* 自增主键Id */
private String source;
/* 上级Id */
private String target;
/* 结构层级 */
private String type;
private int lag;
}
整合类
public class Gtt {
/* 自增主键Id */
private List<Link> links;
private List<TaskInfo> data;
public List<Link> getLinks() {
return links;
}
}
读取文件内容 MPP和XER文件读取类不一样 编码也有不同,注意看下面的注释
public ResultVo getGtt(MultipartFile file) throws MPXJException, IOException {
//MPP文件读取
InputStream inputStream = file.getInputStream();
MPPReader mppReader = new MPPReader();
ProjectFile pf = mppReader.read(inputStream);
//XER文件读取 注意编码问题 具体可以根据文档看看问题
PrimaveraXERFileReader reader = new PrimaveraXERFileReader();
reader.setEncoding("GB2312");
ProjectFile pf = reader.read(inputStream);
//从文件中获取的任务对象
List<Task> tasks = pf.getChildTasks();
//解析后数据存入对象
List<TaskInfo> importList = new ArrayList<>();
//递归解析方法
List<Task> getChildTasks = tasks.get(0).getChildTasks();
List<Link> linkList = new ArrayList<>();
childrenTaskNew(getChildTasks, new TaskInfo(), importList, linkList);
Gtt gtt = new Gtt();
gtt.setData(importList);
gtt.setLinks(linkList);
return new ResultVo(gtt);
}
重组数据的父子级关系
public void childrenTaskNew(List<Task> taskList, TaskInfo tsk, List<TaskInfo> importList, List<Link> linkList) {
//设置层级,如果等于空,则代表是第一层级,不为空则在父级节点的层级基础上+1
int levelNum;
if (StringUtils.isEmpty(String.valueOf(tsk.getTask_outline_level()))) {
levelNum = 1;
} else {
levelNum = Integer.parseInt(String.valueOf(tsk.getTask_outline_level()) + 1);
}
//循环所有节点
for (Task task : taskList) {
TaskInfo taskInfo = new TaskInfo();
taskInfo.setId(task.getID());
taskInfo.setTask_unique_id(task.getUniqueID());
taskInfo.setParent(tsk.getParent() == null ? "0" : String.valueOf(tsk.getId()));//将上一级目录的Id赋值给下一级的ParentId
taskInfo.setTask_outline_level(levelNum);//层级
taskInfo.setText(task.getName());//这个是获取文件中的“任务名称”列的数据
taskInfo.setDuration(task.getDuration().getDuration());//获取的是文件中的“工期”
taskInfo.setStart_date(TaskUtils.dateConvert(task.getStart()));//获取文件中的 “开始时间”
taskInfo.setTask_finish_date(TaskUtils.dateConvert(task.getFinish()));//获取文件中的 “完成时间”
if (task.getMilestone())
{
//里程碑
taskInfo.setType("milestone");
}else if (task.getSummary())
{
//项目
taskInfo.setType("project");
}else
{
//任务
taskInfo.setType("task");
}
if (task.getChildTasks().size() > 0) {
childrenTaskNew(task.getChildTasks(), taskInfo, importList, linkList);//继续进行递归,当前保存的只是父任务的信息
} else {
// diagramImport.setIsNotSplit(DelFlagType.Delete.getType());
}
List<Relation> task_predecessors = task.getPredecessors();
StringBuilder beforeTaskId = new StringBuilder();
StringBuilder beforeTaskType = new StringBuilder();
if (task_predecessors != null) {
if (task_predecessors.size() > 0) {
for (Relation relation : task_predecessors) {
Integer targetTaskId = relation.getTargetTask().getID();
if (beforeTaskId.length() == 0) {
beforeTaskId.append(targetTaskId);
beforeTaskType.append(relation.getType());
} else {
beforeTaskId.append("," + targetTaskId);
beforeTaskType.append("," + relation.getType());
}
String typeId = "0";
//创建新的link
if (task.getID().toString().equals("FS")) {
typeId = "0";
}
if (task.getID().toString().equals("SS")) {
typeId = "1";
}
if (task.getID().toString().equals("SF")) {
typeId = "2";
}
if (task.getID().toString().equals("FF")) {
typeId = "3";
}
Link lk = new Link();
lk.setSource(targetTaskId.toString());
lk.setType(typeId);
lk.setTarget(task.getID().toString());
lk.setLag( (int)relation.getLag().getDuration());
linkList.add(lk);
//fs 0 ss1 sf 2 ff 3
}
}
}
importList.add(taskInfo);
}
}
根据上面的方法,postman输出数据
官方文档支持的文件类型有很多,有问题请查看官网传送门
https://www.mpxj.org/supported-formats/