mpp文件是什么?
MPP是Microsoft Project项目管理软件的文件扩展名,此软件旨在帮助个人跟踪,组织或维护项目。
在线打开mpp文件方式:https://projectviewercentral.com/freeviewer/
结构
一个Project由Task,Resources,Calendar构成,Task与Calendar,Resources与Calendar都有关系。
MPXJ是一个开源的包,网址:http://www.mpxj.org/howto-write-mpx.html
它的api文档:http://www.mpxj.org/apidocs/index.html
它需要POI的支持。
它可以读取MPP文件(不能写MPP文件!!!要经过XML过渡。。。)
可以读写MPX文件,MPX就是一个纯文本文件,里面有TASK,Resource之类的信息,按一定格式书写的。
Project 98及之前版本可以另存为MPX文件,从Project 2000开始就不支持另存为MPX格式了,
但是,它们仍然可以读取MPX文件。
MPXJ的读写的类主要有这么几个:
读:
net.sf.mpxj.mpp.MPPReader: reads Microsoft Project MPP files
net.sf.mpxj.mpx.MPXReader: reads Microsoft MPX files
net.sf.mpxj.mspdi.MSPDIReader: reads Microsoft MSPDI (XML) files
net.sf.mpxj.mpd.MPDIReader: reads Microsoft MPD files
net.sf.mpxj.planner.PlannerReader: reads Planner (XML) files
写:
net.sf.mpxj.mpx.MPXWriter: writes Microsoft MPX files
net.sf.mpxj.mspdi.MSPDIWriter: writes Microsoft MSPDI (XML) files
net.sf.mpxj.planner.PlannerWriter: writes Planner (XML) files
所以,目前可以做的就是:
1.读取MPP文件信息,写入DB之类的……
2.new 一个ProjectFile,写入Task,Resources,Calendar之类的信息,
然后使用MPXWriter写入MPX文件,然后用Project打开,好像会有个导入数据的对话框。
引入maven依赖
<dependency>
<groupId>net.sf.mpxj</groupId>
<artifactId>mpxj</artifactId>
<version>8.0.8</version>
</dependency>
以xml格式写出
核心方法
public String export(String projectId) {
// 生成唯一标识
String uuid = UUID.randomUUID().toString();
// 作者使用是linux系统,这里方便演示直接路径写在方法里面,作者建议写在配置文件,方便维护
String path = "/home/cqf/team/";
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("project_id", projectId);
// 获取项目
Project project = this.projectMapper.selectById(projectId);
// 没有找到该项目的信息
if (ObjectUtils.isEmpty(project)) {
return null;
}
// 导出文件名称
String fileName = path + uuid + project.getName() + ".xml";
// 作者使用是linux系统,这里方便演示直接路径写在方法里面,作者建议写在配置文件,方便维护
File templatesFile = new File("/home/cqf/team/开办新公司 - 导出模板.mpp");
try {
MPPReader mppRead = new MPPReader();
ProjectFile file = mppRead.read(templatesFile);
Task task = file.addTask();
findChildrenTask(projectId, task, null, true);
/*MPXWriter writer = new MPXWriter();
// 设置简体中文,防止乱码
writer.setLocale(Locale.CHINESE);
// writer.setLocale(Locale.SIMPLIFIED_CHINESE);
try {
writer.write(file, fileName);
} catch (IOException e) {
e.printStackTrace();
}*/
//生成文件
ProjectWriter writer = new MSPDIWriter();
try {
writer.write(file, fileName);
} catch (IOException e) {
e.printStackTrace();
}
} catch (MPXJException e) {
e.printStackTrace();
}
// 返回文件名称
return fileName;
}
递归查询子任务
/**
* 查询任务及子任务用于项目添加任务
*
* @param projectId
* @param parentTask
* @param parentId
* @param firstFlag 是否是第一层
*/
public void findChildrenTask(String projectId, Task parentTask, Integer parentId, boolean firstFlag) {
List<MppTask> mppTasks;
// 父id为空且为第一次则查询,否则退出递归
if (null == parentId && firstFlag) {
// 获取父级任务
mppTasks = taskMapper.findParent(projectId);
} else {
// 当父id为空时,查询为空即结束递归
mppTasks = taskMapper.findByParentId(projectId, parentId);
}
for (int i = 0; i < mppTasks.size(); i++) {
MppTask mppTask = mppTasks.get(i);
// 获取当前任务的全部子任务
List<MppTask> childrenTask = taskMapper.findByParentId(projectId, mppTask.taskId);
Task task = parentTask.addTask();
task.setName(mppTask.name);
task.setStart(mppTask.startDate);
task.setFinish(mppTask.endDate);
task.setActualStart(mppTask.actualStart);
task.setActualFinish(mppTask.actualFinish);
task.setDuration(Duration.getInstance(5, TimeUnit.DAYS));
task.setID(mppTask.taskId);
// task.setOutlineLevel(parentTask.getOutlineLevel() + 1);
// task.setUniqueID(parentTask.getUniqueID() + 1);
if (childrenTask.size() > 0) {
// 递归查询子任务
findChildrenTask(projectId, task, mppTask.taskId, false);
}
}
}
最后吐槽一下,这玩意是真的恶心,比opencv还恶心,案例太少了,不懂用它的api,它的api不仅全是英文,而且还没有demo演示,身为英语渣的我表示看不懂,关键是软件项目管理的课没有听(因为疫情影响,上的网课)
果然,有些东西错过了,迟早要补回来。