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

本文介绍了如何使用MPXJ库解析MPP和XER格式的项目管理文件,处理编码差异,构建任务信息实体类和关联关系,并通过API实现高效安全的数据处理,同时提到了官方文档支持的文件格式和可能遇到的问题资源。
摘要由CSDN通过智能技术生成

首先介绍下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/
  • 6
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
Java可以通过使用特定的库或工具来读取.mpp格式的数据。以下是两种常见的方法: 1. 使用OpenProj: OpenProj是一个开源的项目管理软件,它可以导入和读取.mpp格式的数据。您可以在Java代码中使用相关的OpenProj库,通过加载.mpp文件并解析其中的数据。使用OpenProj库,您可以获得项目的名称、任务列表、任务时间表、任务关系等信息。以下是一个简单的示例代码: ```java import net.sf.mpxj.*; import net.sf.mpxj.reader.ProjectReader; import net.sf.mpxj.reader.UniversalProjectReader; public class MppReader { public static void main(String[] args) { try { // 加载.mpp文件 ProjectReader reader = new UniversalProjectReader(); ProjectFile project = reader.read("path/to/your/project.mpp"); // 获取项目信息 System.out.println("项目名称: " + project.getProjectProperties().getName()); // 获取任务列表并输出任务名称和开始时间 for (Task task : project.getAllTasks()) { System.out.println("任务名称: " + task.getName()); System.out.println("开始时间: " + task.getStart()); } } catch (MPXJException e) { e.printStackTrace(); } } } ``` 2. 使用MPXJ库: MPXJ是一个Java库,专门用于读取和处理多种项目文件格式,包括.mpp格式。通过使用MPXJ库,您可以加载.mpp文件,并通过API获取项目的各项信息。以下是一个简单的示例代码: ```java import net.sf.mpxj.*; import net.sf.mpxj.reader.ProjectReader; import net.sf.mpxj.reader.ProjectReaderUtility; public class MppReader { public static void main(String[] args) { try { // 加载.mpp文件 ProjectReader reader = ProjectReaderUtility.getProjectReader("path/to/your/project.mpp"); ProjectFile project = reader.read(); // 获取项目信息 System.out.println("项目名称: " + project.getProjectProperties().getName()); // 获取任务列表并输出任务名称和开始时间 for (Task task : project.getAllTasks()) { System.out.println("任务名称: " + task.getName()); System.out.println("开始时间: " + task.getStart()); } } catch (MPXJException e) { e.printStackTrace(); } } } ``` 以上是两种常见的通过Java读取.mpp格式数据的方法。您可以根据自己的需求选择适合的方法,并根据需要进一步处理和分析数据。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

BIMCC筑云

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值