mpp文件是什么?
MPP是Microsoft Project項(xiàng)目管理軟件的文件擴(kuò)展名焦匈,此軟件旨在幫助個(gè)人跟蹤赘淮,組織或維護(hù)項(xiàng)目辕录。
在線打開mpp文件方式:https://projectviewercentral.com/freeviewer/
結(jié)構(gòu)
一個(gè)Project由Task,Resources梢卸,Calendar構(gòu)成走诞,Task與Calendar,Resources與Calendar都有關(guān)系蛤高。
MPXJ是一個(gè)開源的包蚣旱,網(wǎng)址:http://www.mpxj.org/howto-write-mpx.html
它的api文檔:http://www.mpxj.org/apidocs/index.html
它需要POI的支持。
它可以讀取MPP文件(不能寫MPP文件4鞫浮H獭!要經(jīng)過XML過渡恤批。异吻。。)
可以讀寫MPX文件开皿,MPX就是一個(gè)純文本文件涧黄,里面有TASK,Resource之類的信息赋荆,按一定格式書寫的笋妥。
Project 98及之前版本可以另存為MPX文件,從Project 2000開始就不支持另存為MPX格式了窄潭,
但是春宣,它們?nèi)匀豢梢宰x取MPX文件。
MPXJ的讀寫的類主要有這么幾個(gè):
讀:
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 一個(gè)ProjectFile,寫入Task幽污,Resources嚷辅,Calendar之類的信息,
然后使用MPXWriter寫入MPX文件距误,然后用Project打開簸搞,好像會(huì)有個(gè)導(dǎo)入數(shù)據(jù)的對(duì)話框。
引入maven依賴
<dependency>
<groupId>net.sf.mpxj</groupId>
<artifactId>mpxj</artifactId>
<version>8.0.8</version>
</dependency>
以xml格式寫出
核心方法
public String export(String projectId) {
// 生成唯一標(biāo)識(shí)
String uuid = UUID.randomUUID().toString();
// 作者使用是linux系統(tǒng),這里方便演示直接路徑寫在方法里面准潭,作者建議寫在配置文件趁俊,方便維護(hù)
String path = "/home/cqf/team/";
Map<String, Object> queryMap = new HashMap<>();
queryMap.put("project_id", projectId);
// 獲取項(xiàng)目
Project project = this.projectMapper.selectById(projectId);
// 沒有找到該項(xiàng)目的信息
if (ObjectUtils.isEmpty(project)) {
return null;
}
// 導(dǎo)出文件名稱
String fileName = path + uuid + project.getName() + ".xml";
// 作者使用是linux系統(tǒng),這里方便演示直接路徑寫在方法里面刑然,作者建議寫在配置文件寺擂,方便維護(hù)
File templatesFile = new File("/home/cqf/team/開辦新公司 - 導(dǎo)出模板.mpp");
try {
MPPReader mppRead = new MPPReader();
ProjectFile file = mppRead.read(templatesFile);
Task task = file.addTask();
findChildrenTask(projectId, task, null, true);
/*MPXWriter writer = new MPXWriter();
// 設(shè)置簡體中文,防止亂碼
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;
}
遞歸查詢子任務(wù)
/**
* 查詢?nèi)蝿?wù)及子任務(wù)用于項(xiàng)目添加任務(wù)
*
* @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) {
// 獲取父級(jí)任務(wù)
mppTasks = taskMapper.findParent(projectId);
} else {
// 當(dāng)父id為空時(shí),查詢?yōu)榭占唇Y(jié)束遞歸
mppTasks = taskMapper.findByParentId(projectId, parentId);
}
for (int i = 0; i < mppTasks.size(); i++) {
MppTask mppTask = mppTasks.get(i);
// 獲取當(dāng)前任務(wù)的全部子任務(wù)
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) {
// 遞歸查詢子任務(wù)
findChildrenTask(projectId, task, mppTask.taskId, false);
}
}
}
最后吐槽一下怔软,這玩意是真的惡心垦细,比opencv還惡心,案例太少了挡逼,不懂用它的api蝠检,它的api不僅全是英文,而且還沒有demo演示挚瘟,身為英語渣的我表示看不懂,關(guān)鍵是軟件項(xiàng)目管理的課沒有聽(因?yàn)橐咔橛绊懰撬螅系木W(wǎng)課)
果然乘盖,有些東西錯(cuò)過了,遲早要補(bǔ)回來憔涉。