java解析mpp文件(包含层级关系)

文章介绍了如何使用MPPReader库解析MPP文件,通过递归循环处理文件中的任务对象,将数据映射到自定义的ArrowDiagramImport实体类中,包括任务名称、工期、层级等信息,同时处理前置任务关系。解析后的数据存储为列表并打印展示。
摘要由CSDN通过智能技术生成

导入数据
我用的是递归循环的,不限制有多少子级关系都可以拿到

首先引入解析mpp所需依赖

        <dependency>
            <groupId>net.sf.mpxj</groupId>
            <artifactId>mpxj</artifactId>
            <version>7.1.0</version>
        </dependency>

解析所用实体类,每个字段都有对应意思

public class ArrowDiagramImport extends Model<ArrowDiagramImport> {

    @TableId(value = "ID")
    private String id;

    /**
     * 序号
     */
    @TableField(value = "SERIAL_NUMBER",exist = true  )
    private String serialNumber;

    /**
     * 节点名称
     */
    @TableField(value = "TASK_NAME",exist = true  )
    private String taskName;

    /**
     * 前置节点ID
     */
    @TableField(value = "PARENT_ID",exist = true  )
    private String parentId;

    /**
     * 工期
     */
    @TableField(value = "DURATION",exist = true  )
    private Double duration;

    /**
     * 计划开始时间
     */
    @TableField(value = "PLAN_START_DATE",exist = true  )
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
    private Date planStartDate;

    /**
     * 计划结束时间
     */
    @TableField(value = "PLAN_END_DATE",exist = true  )
    @JsonFormat(locale="zh", timezone="GMT+8", pattern="yyyy-MM-dd")
    private Date planEndDate;

    /**
     * 层级
     */
    @TableField(value = "plan_level",exist = true  )
    private String planLevel;

    /**
     * 是否拆分 0是 1否(代表该条数据是不是父节点)
     */
    @TableField(value = "is_not_split",exist = true  )
    private String isNotSplit;

    /**
     * 拆分后子任务的父节点序号
     */
    @TableField(value = "split_parent_id",exist = true  )
    private String splitParentId;

}

核心代码

    public void mppFileAnalysis(MultipartFile multipartFile) {
        try {
            //读取文件的组件
            MPPReader mppReader = new MPPReader();
            //注意,如果在这一步出现了读取异常,肯定是版本不兼容,换个版本试试
            ProjectFile pf = mppReader.read(multipartFile.getInputStream());
            //从文件中获取的任务对象
            List<Task> tasks = pf.getChildTasks();
            //解析后数据存入对象
            List<ArrowDiagramImport> importList = new ArrayList<>();
            //递归解析方法
            childrenTask(tasks.get(0).getChildTasks(), new ArrowDiagramImport(), importList);
            for (ArrowDiagramImport diagramImport : importList) {
                System.out.println(diagramImport.getTaskName());
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

递归方法

taskList 循环解析对象,rtSingleArrowDiagramImport 代表当前循环的数据是它的子级,importList 循环解析后数据存入的集合

    //taskList 循环解析对象,rtSingleArrowDiagramImport   代表当前循环的数据是它的子级,importList   循环解析后数据存入的集合
    public void childrenTask(List<Task> taskList, ArrowDiagramImport rtSingleArrowDiagramImport, List<ArrowDiagramImport> importList) {
        //设置层级,如果等于空,则代表是第一层级,不为空则在父级节点的层级基础上+1
        int levelNum;
        if (StringUtils.isEmpty(rtSingleArrowDiagramImport.getPlanLevel())) {
            levelNum = 1;
        } else {
            levelNum = Integer.parseInt(rtSingleArrowDiagramImport.getPlanLevel()) + 1;
        }
        //循环所有节点
        for (Task task : taskList) {
            ArrowDiagramImport diagramImport = new ArrowDiagramImport();
            diagramImport.setId(StringUtils.getUUID());
            diagramImport.setSerialNumber(task.getID().toString());
            diagramImport.setSplitParentId(rtSingleArrowDiagramImport.getSerialNumber());//将上一级目录的Id赋值给下一级的ParentId
            diagramImport.setPlanLevel(String.valueOf(levelNum));//层级
            diagramImport.setTaskName(task.getName());//这个是获取文件中的“任务名称”列的数据
            diagramImport.setDuration(task.getDuration().getDuration());//获取的是文件中的“工期”
            diagramImport.setPlanStartDate(task.getStart());//获取文件中的 “开始时间”
            diagramImport.setPlanEndDate(task.getFinish());//获取文件中的 “完成时间”
            diagramImport.setParentId(getParentIds(task));
            if (task.getChildTasks().size() > 0) {
                diagramImport.setIsNotSplit(DelFlagType.Normal.getType());
                childrenTask(task.getChildTasks(), diagramImport, importList);//继续进行递归,当前保存的只是父任务的信息
            } else {
                diagramImport.setIsNotSplit(DelFlagType.Delete.getType());
            }
            importList.add(diagramImport);
        }
    }

该方法是为了获取前置节点的关系,包含特殊前置关系

 public String getParentIds(Task task) {
        String parentId = "";
        if (task.getPredecessors().size() > 0) {
            for (Relation relation : task.getPredecessors()) {
                //前置节点ID
                String id = relation.getTargetTask().getID().toString();
                //关联前置节点的关系 FS/FF/SS/SF
                String type = relation.getType().toString();
                //与前置节点关系的天数
                Integer duration = (int) relation.getLag().getDuration();
                //如果类型=FS,并且天数为0,则代表没有特殊关系
                if (type.equals(DiagramPlanType.FS.getCode()) && duration == 0.0) {
                    parentId += id + ",";

                } else {
                    String durationStr = "";
                    if (duration > 0.0) {
                        durationStr = "+" + duration + "工日";
                    } else if (duration < 0.0) {
                        durationStr = duration.toString() + "工日";
                    }
                    parentId += id + type + durationStr + ",";
                }
            }
            parentId = parentId.substring(0, parentId.length() - 1);
        }
        return parentId;
    }
Microsoft Project 是一款常用的项目管理软件,它使用的文件格式为 .mpp。如果需要解析 .mpp 文件,可以使用 Microsoft Project 软件自带的 API,也可以使用第三方库或者工具实现。 Microsoft Project 提供了 VBA 编程接口,可以通过编写 VBA 宏实现对 .mpp 文件解析。具体步骤如下: 1. 打开 Microsoft Project 软件,按下 Alt + F11 打开 VBA 编辑器。 2. 在 VBA 编辑器中,插入一个新的模块。 3. 在模块中编写 VBA 代码,使用 Project 对象和 Task 对象来访问 .mpp 文件中的数据。例如,以下代码可以输出 .mpp 文件中所有任务的名称: ``` Sub ParseMppFile() Dim proj As Project Set proj = Application.ActiveProject Dim task As Task For Each task In proj.Tasks Debug.Print task.Name Next task End Sub ``` 此外,还可以使用第三方库或者工具实现 .mpp 文件解析。例如,有一些 Python 库可以读取和操作 .mpp 文件,如 pympp 和 pywin32。使用这些库,可以在 Python 环境中编写代码来读取 .mpp 文件中的数据。例如,以下 Python 代码可以读取 .mpp 文件中所有任务的名称: ``` import win32com.client app = win32com.client.Dispatch("MSProject.Application") app.Visible = True proj = app.FileOpenEx("path/to/mpp/file.mpp") for task in proj.Tasks: print(task.Name) proj.Close() app.Quit() ``` 需要注意的是,使用第三方库或者工具解析 .mpp 文件可能会受到 Microsoft Project 版本和 .mpp 文件格式的限制。
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值