作者: | 来源:互联网 | 2023-07-07 16:51
目标:导出MPP文件,以MSPROJECT应用程序打MPP文件,关闭MSPROJECT后,读取MPP文件的数据
要求:安装MSPROJECT,添加引用Microsoft Office 12.0 Object Library(COM组件,命名空间:Microsoft.Office.Interop.MSProject)
1、导出MPP文件
1、创建COM(MSPROJECT)
Microsoft.Office.Interop.MSProject App = new Microsoft.Office.Interop.MSProject.ApplicationClass();
2、创建PROJECT
App.FileNew(Type.Missing, Type.Missing, Type.Missing, false);
3、循环写入任务
/*递归写入Task*/
Action, short> action = null;
action = (roots, level) =>
{foreach (var item in roots){var task = file.CreateTask(item.TaskName);/*初始化参数:名称、开始时间、结束时间、限时*/task.Name = item.TaskName;task.Start = item.PlanStart;task.Finish = item.PlanEnd;task.OutlineLevel = level;/*GUID目前无法写入,所以将ID写入到备注中*/task.SetField(PjField.pjTaskNotes, item.ID.ToString());/*如果有前后置依赖关系*/if (item.BeforeID.HasValue){var beforeTask = file.TaskList.FirstOrDefault(u => u.Notes == item.BeforeID.ToString());var dependency = task.TaskDependencies.Add(beforeTask, PjTaskLinkType.pjFinishToStart, 1);}/*如果有子级,开始递归,子父级关系目前只能由递归设置level设定*/if (list.Any(u => u.ParentID == item.ID)){action(list.Where(u => u.ParentID == item.ID), (short)(level + 1));}}
};
/*在MPP文件中,level是从1开始*/
action(list.where(u=>u.isRoot),1)
4、保存MPP文件
/*保存至指定路径*/
this.App.FileSaveAs(FileName, PjFileFormat.pjMPP, missing, false,missing, missing, missing, missing, missing, missing,missing, missing, missing, missing, missing, missing,missing, missing, missing);
/*退出COM组件*/
this.App.Quit(PjSaveType.pjSave);
2、打开MPP文件,并等待应用程序关闭
直接调用Start具体的文件,如果文件有对应的默认打开程序,将会直接打开文件(同理OFFICE、视频、图片等文件也可以)
/*打开指定路径的MPP文件:FileName="C:/*.mpp"*/
System.Diagnostics.Process.Start(FileName).WaitForExit();
3、读取MPP文件
1、调用COM组件打开MPP文件
Microsoft.Office.Interop.MSProject App = new Microsoft.Office.Interop.MSProject.ApplicationClass();
/*打开指定路径的文件*/
App.FileOpen(fileName,false, missing, missing, missing, missing, missing, missing, missing,missing, missing, PjPoolOpen.pjPoolReadWrite, missing, missing, missing, missing);
2、循环读取任务
/*在App.ActiveProject.Tasks中已经包含了所有的任务*/
foreach (Microsoft.Office.Interop.MSProject.Task task in App.ActiveProject.Tasks)
{var _t = new Task(){ID = getTaskGuid(task),TaskName = task.Name,PlanStart = ((DateTime)task.Start).Date,PlanEnd = ((DateTime)task.Finish).Date,};/*子父关联,层级深度大于1(从1开始)*/if (task.OutlineLevel > 1 && task.OutlineParent != null){_t.ParentID = getTaskGuid(task.OutlineParent);}/*前后置关系:如果任务1->2有关系,那么,在1-2中都会有TaskDependencies。其中1的from=自己,to=2;2的from=1,to=自己*/foreach (TaskDependency item in task.TaskDependencies){_t.BeforeID = getTaskGuid(item.From);/*如果本身是起点,直接跳过*/if (_t.BeforeID == _t.ID)_t.BeforeID = null;}/*如果已经存在重复性的任务*/if (list.Any(u => u.ID == _t.ID)){/*元素替换*/list[list.IndexOf(list.First(u => u.ID == _t.ID))] = _t;}else{list.Add(_t);}
}
4、补充
最初的任务目标只需要读取MPP文件内容,这个时候使用的是第三方控件mpxj,官方地址为:http://www.mpxj.org/。
但是这个控件不支持MPP格式文件的写入,最终还是决定使用微软官方的COM组件。