2025年Java mpjx读取MPP+XER文件 平替DHTMLX网站接口

Java mpjx读取MPP+XER文件 平替DHTMLX网站接口首先介绍下 MPP 文件和 XER 文件 国内都是 MPP 后缀文件 国外基本上都是用的 XER 后缀文件 DBTMLX 网站是一个 MPP 在线网站提供免费的 API 接口但是速度较慢 所以为了安全性 请求速度决定按照他们家的 API 数据格式重新写一个服务 MPP 文件内容 Maven 我引入最新的包

大家好,我是讯享网,很高兴认识大家。

首先介绍下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/ 
小讯
上一篇 2025-04-01 21:18
下一篇 2025-01-14 15:47

相关推荐

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容,请联系我们,一经查实,本站将立刻删除。
如需转载请保留出处:https://51itzy.com/kjqy/67908.html