1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > Java使用mpxj导入.mpp格式的Project文件(甘特图)

Java使用mpxj导入.mpp格式的Project文件(甘特图)

时间:2021-07-21 01:42:32

相关推荐

Java使用mpxj导入.mpp格式的Project文件(甘特图)

最近换工作了,主要的项目都是企业内部为支撑的管理平台,刚入入职没多久,遇到了一个需求,就是导入微软的Project文件,踩过不少坑,所以记录一下,后续还有从数据库导出Project引导文件,也就是xml文件

依赖

<!-- 读取project文件 --><dependency><groupId>net.sf.mpxj</groupId><artifactId>mpxj</artifactId><version>7.1.0</version></dependency>

代码

博主使用的读取方式是递归读取的,无论Project文件中的任务有多少层,都可以读到,好了,直接看代码,注意看注释:

核心方法

@Transactional@Overridepublic void readMmpFileToDB(File file) {//如果读取的是MultipartFile,那么直接使用获取InputStream即可try{//这个是读取文件的组件MPPReader mppRead = new MPPReader();//注意,如果在这一步出现了读取异常,肯定是版本不兼容,换个版本试试ProjectFile pf = mppRead.read(file);//从文件中获取的任务对象List<Task> tasks = pf.getChildTasks();//这个可以不用,这个list只是我用来装下所有的数据,如果不需要可以不使用List<Project> proList = new LinkedList<>();//这个是用来封装任务的对象,为了便于区别,初始化批次号,然后所有读取的数据都需要加上批次号Project pro = new Project();pro.setBatchNum(StringUtils.UUID());//生成批次号UUID//这个方法是一个递归方法getChildrenTask(tasks.get(0), pro ,proList, 0);}catch (MPXJException e) {logger.error(e.getMessage());throw new RuntimeException();} catch (Exception e) {logger.error(e.getMessage());throw new RuntimeException();}}

/*** 这个方法是一个递归* 方法的原理:进行读取父任务,如果下一层任务还是父任务,那么继续调用当前方法,如果到了最后一层,调用另外一个读取底层的方法* @param task* @param project* @param list* @param levelNum*/public void getChildrenTask(Task task, Project project, List<Project> list, int levelNum){if(task.getResourceAssignments().size() == 0){//这个判断是进行是否是最后一层任务的判断==0说明是父任务levelNum ++;//层级号需要增加,这个只是博主用来记录该层的层级数List<Task> tasks = task.getChildTasks();//继续获取子任务for (int i = 0; i < tasks.size(); i++) {//该循环是遍历所有的子任务if(tasks.get(i).getResourceAssignments().size() == 0){//说明还是在父任务层Project pro = new Project();if (project.getProjId() != null){//说明不是第一次读取了,因为如果是第一层,那么还没有进行数据库的添加,没有返回主键Idpro.setParentId(project.getProjId());//将上一级目录的Id赋值给下一级的ParentId}pro.setBatchNum(project.getBatchNum());//批量号pro.setImportTime(new Date());//导入时间pro.setLevel(levelNum);//层级pro.setTaskName(tasks.get(i).getName());//这个是获取文件中的“任务名称”列的数据pro.setDurationDate(tasks.get(i).getDuration().toString());//获取的是文件中的“工期”pro.setStartDate(tasks.get(i).getStart());//获取文件中的 “开始时间”pro.setEndDate(tasks.get(i).getFinish());//获取文件中的 “完成时间”pro.setResource(tasks.get(i).getResourceGroup());//获取文件中的 “资源名称”this.addProjectInfo(pro);//将该条数据添加到数据库,并且会返回主键Id,用做子任务的ParentId,这个需要在mybatis的Mapper中设置getChildrenTask(tasks.get(i), pro,list,levelNum);//继续进行递归,当前保存的只是父任务的信息}else{//继续进行递归getChildrenTask(tasks.get(i), project, list, levelNum);}}}else{//说明已经到了最底层的子任务了,那么就调用进行最底层数据读取的方法if (project.getProjId() != null){getResourceAssignment(task, project, list, levelNum);}}}

public void getResourceAssignment(Task task, Project project, List<Project> proList, int levelNum){List<ResourceAssignment> list = task.getResourceAssignments();//读取最底层的属性ResourceAssignment rs = list.get(0);Project pro = new Project();pro.setTaskName(task.getName());pro.setParentId(project.getProjId());pro.setLevel(levelNum);pro.setImportTime(new Date());pro.setBatchNum(project.getBatchNum());pro.setDurationDate(task.getDuration().toString());pro.setStartDate(rs.getStart());//注意,这个从ResourceAssignment中读取pro.setEndDate(rs.getFinish());//同上String resource = "";if(list.size() > 1){for (int i = 0; i < list.size(); i++) {if (list.get(i).getResource() != null){if(i < list.size() - 1){resource += list.get(i).getResource().getName() + ",";}else{resource += list.get(i).getResource().getName();}}}}else{if(list.size() > 0 && list.get(0).getResource() != null){resource = list.get(0).getResource().getName();}}if(!StringUtils.isEmpty(resource)){pro.setResource(resource);}this.addProjectInfo(pro);//将数据保存在数据库中,同样会返回主键proList.add(pro);}

封装对象

package com.winter.model;import java.util.Date;/*** Project文件封装类* Created By Donghua.Chen on /1/9*/public class Project {/* 自增主键Id */private Integer projId;/* 上级Id */private Integer parentId;/* 结构层级 */private Integer level;/* 任务名称 */private String taskName;/* 工期 */private String durationDate;/* 开始时间 */private Date startDate;/* 结束时间 */private Date endDate;/* 前置任务ID */private Integer preTask;/* 资源名称 */private String resource;/* 导入时间 */private Date importTime;/* 批次号 */private String batchNum;//省略get、set方法

Mybatis 接口方法

/*** 插入project数据* @param project* @return*/int addProjectSelective(Project project);

Mapper

<sql id="TABLE_PROJECT">PROJECT</sql><!-- 插入数据之后返回主键 需要这两个配置: useGeneratedKeys="true" keyProperty="projId" --><insert id="addProjectSelective" useGeneratedKeys="true" keyProperty="projId" parameterType="com.winter.model.Project">INSERT INTO<include refid="TABLE_PROJECT"/><trim prefix="(" suffix=")" suffixOverrides="," ><if test="parentId != null">parentId,</if><if test="level != null">level,</if><if test="taskName != null">taskName,</if><if test="durationDate != null">durationDate,</if><if test="startDate != null">startDate,</if><if test="endDate != null">endDate,</if><if test="preTask != null">preTask,</if><if test="resource != null">resource,</if><if test="importTime != null">importTime,</if><if test="importTime != null">batchNum,</if></trim><trim prefix="values (" suffix=")" suffixOverrides="," ><if test="parentId != null">#{parentId, jdbcType=INTEGER},</if><if test="level != null">#{level, jdbcType=INTEGER},</if><if test="taskName != null">#{taskName, jdbcType=VARCHAR},</if><if test="durationDate != null">#{durationDate, jdbcType=VARCHAR},</if><if test="startDate != null">#{startDate, jdbcType=DATE},</if><if test="endDate != null">#{endDate, jdbcType=DATE},</if><if test="preTask != null">#{preTask, jdbcType=INTEGER},</if><if test="resource != null">#{resource, jdbcType=VARCHAR},</if><if test="importTime != null">#{importTime, jdbcType=DATE},</if><if test="batchNum != null">#{batchNum, jdbcType=VARCHAR},</if></trim></insert>

效果

拓展

当然,还有很多自定义的字段读取,如果有需要可以联系我,或者看官方文档

email:1085143002@

相关资源

mpxj官方API文档:/apidocs/index.html项目源码:/WinterChenS/springboot-mybatis-demo导入模板在源码的file文件夹中,sql在sql文件夹中

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。