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、 運行結果。