VC操作MPP文件
1.背景简介
因需要对Office系列进行程序操作,特需要使用COM编程。
Microsoft Project生成进度计划,office家族软件,文件后缀为.mpp。
具体信息见维基百科http://zh.wikipedia.org/wiki/Microsoft_Project。
读取MPP文件,网络上示例基本为C#,因为我所使用的是VC,C#代码只能做参考了。
因为COM组件是通用的,跨语言的(微软系),既然C#能做,那么VC也能做。
开发环境:
Project版本:Microsoft Project 2010。
VS版本:VS2005。
源码下载。
2.VC示例程序
1、 创建MFC工程,工程名为MyMPP。
创建一个对话框工程。
2、 增加COM接口包装类。
COM接口的调用,可以通过MFC添加进来。
右键Add->Class
选择MFC Class From TypeLib
选择MS Project COM组件,并生成包装类。
Microsoft Project 14.0 Object Library:本机安装的project 2010所提供的com组件。
Generated classes:为所需要用到的包装类,包装Interfaces中的接口。
最后,会生成五个头文件。
CIProjectDoc.h、CMSProject.h、CProjects.h、CTask.h、CTasks.h。
3、 COM头文件调整。
将(CIProjectDoc.h、CMSProject.h、CProjects.h、CTask.h、CTasks.h)
头文件中代码替换。
#import "C:\\Program Files\\MicrosoftOffice\\Office14\\MSPRJ.OLB" no_namespace替换为#pragma once
CIProjectDoc.h、CMSProject.h中使用了很多没有生成的类,会导致编译不通过。
解决方法:将出现T*的地方替换为LPDISPATCH。
例:
Application* GetApplication() { Application* result; GetProperty(0xfff4, VT_DISPATCH, (void*)&result); return result; } 调整为: LPDISPATCH GetApplication() { LPDISPATCH result; GetProperty(0xfff4, VT_DISPATCH, (void*)&result); return result; }
4、 MPP读取代码。
添加一个按钮,按钮响应代码如下。
#include "comdef.h" #include "CMSProject.h" #include "CProjects.h" #include "CIProjectDoc.h" #include "CTasks.h" #include "CTask.h" void CMyMPPDlg::OnBnClickedButton1() { // TODO: Add your control notification handler code here CString strFilter = _T(""); strFilter += _T("MS Project文件(*.mpp)|*.mpp||"); CFileDialog fileDlg(TRUE, _T("*.mpp"), NULL, OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, strFilter); if (fileDlg.DoModal() != IDOK ) { return; } CString strFilePath = fileDlg.GetPathName(); ::CoInitialize(NULL); ReadMppInfo(strFilePath); ::CoUninitialize(); } void CMyMPPDlg::ReadMppInfo(const CString& strFilePath) { CString strTipInfo = _T(""); try { CMSProject app; if (!app.CreateDispatch(_T("MSProject.Application"))) { MessageBox(_T("Office Project未安装")); return; } app.SetVisible(FALSE); BOOL openRes = app.FileOpen(_variant_t(strFilePath), _variant_t(true), vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, vtMissing, 1, vtMissing, vtMissing, vtMissing, vtMissing); if (!openRes) { MessageBox(_T("Office Project打开失败!")); return; } CProjects projs; projs = app.GetProjects(); int nProjCount = projs.get_Count(); for (int i = 1; i <= nProjCount; i++) { CIProjectDoc projDoc; projDoc = projs.get_Item(_variant_t(i)); CTasks tasks; tasks = projDoc.get_Tasks(); long nTaskCount = tasks.get_Count(); for (int j = 1; j <= nTaskCount; j++) { CTask task; task = tasks.get_Item(_variant_t(j)); CString strLevel = IntToCString(task.get_OutlineLevel()); CString strName = task.get_Name(); CString strStart = OleDateToStr(task.get_Start().date); CString strFinish = OleDateToStr(task.get_Finish().date); int nDays = GetTimeSpan(task.get_Start().date, task.get_Finish().date); CString strDays = IntToCString(nDays); strTipInfo += strLevel; strTipInfo += _T("|"); strTipInfo += strName; strTipInfo += _T("|"); strTipInfo += strDays; strTipInfo += _T("|"); strTipInfo += strStart; strTipInfo += _T("|"); strTipInfo += strFinish; strTipInfo += _T("\r\n"); } } app.FileClose(0, _variant_t(false)); } catch(_com_error &e) { MessageBox((LPWSTR)e.Description()); } if (!strTipInfo.IsEmpty()) { MessageBox(strTipInfo); } } int CMyMPPDlg::GetTimeSpan(const COleDateTime& dtStart, const COleDateTime& dtFinish) { COleDateTimeSpan timeSpan = dtFinish - dtStart; int nDays = timeSpan.GetDays(); if (nDays < 0) { nDays -= 1; } else { nDays += 1; } return nDays; } CString CMyMPPDlg::OleDateToStr(COleDateTime oleDate) { return oleDate.Format(_T("%Y-%m-%d")); } CString CMyMPPDlg::IntToCString(int nInput) { CString strInput = _T(""); strInput.Format(_T("%d"), nInput); return strInput; }
5、 运行结果。