http://www.developer.com/net/cplus/article.php/628601/Using-MS-Office-in-an-MFC-Application.htm
Once I was engaged in the project, whose main features were theh presence of a great amount of the typical forms of input and output generally associated with Office-type applications. The documents were to be filled from a data store, which the program would display via the use of views. It would be extremely desirable that the document template could understand these different data independently. Therefore, we made the decision to integrate Microsoft Office into our application in order to leverage the already built-in functionalty that we were seeking. To that extent, I present to you this article detailing exactly what steps are necessary in order to integrate Microsoft Office into your Visual C++/MFC applications. I should also note at this point that one constant problem that I have run into with regards to Office is the unstable nature of the product itself when using it in relation to an ActiveX Document. Therefore, as you look through this article (and the demo) you might see some less than efficient code. An example of a problem that I still have is that even after my application ends, Microsoft Office application remains in memory and can only be removed via the Task manager. If you do solve this problem, please let me know so that I can update this article as well as my own code. Enter CFormDemo into a field Name. Press the button New located near a Document field and then click the OK button, in the newly appeared form. And once again click the OK button. We shall place three Edit Boxes and two Buttons on the new form. In ClassWizard we shall bind Edit Boxes to variables (accordingly CString m_str, double m_double, long m_long). Now we are able to create MDI documents by pressing the buttons on the form. Make the following change into a class CXOfficeCntrItem:
I did not want to present the text of the appropriate methods, as it would have taken too much space. They can be looked up in the source texts of the program. It shall be necessary also to bring in the alterations to CXOfficeDoc and CXOfficeView classes listed below. Is easy to do with the help of ATL Wizard. The realization of methods can be looked up in the source texts.
Using MS Office in an MFC Application
July 10, 2000

Integrating MS Office
Let's begin.
<font color=green>// office.h</font>
#define Uses_MSO2000
<font color=green>// for MS Office 2000</font>
#ifdef Uses_MSO2000
#import "C:\Program Files\Microsoft Office\Office\MSO9.DLL"
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBA6\VBE6EXT.OLB"
#import "C:\Program Files\Microsoft Office\Office\MSWORD9.OLB" \
rename("ExitWindows","_ExitWindows")
#import "C:\Program Files\Microsoft Office\Office\EXCEL9.OLB" \
rename("DialogBox","_DialogBox") \
rename("RGB","_RGB") \
exclude("IFont","IPicture")
#import "C:\Program Files\Common Files\Microsoft Shared\DAO\DAO360.DLL" \
rename("EOF","EndOfFile") rename("BOF","BegOfFile")
#import "C:\Program Files\Microsoft Office\Office\MSACC9.OLB"
#else <font color=green>// for MS Office 97</font>
#import "C:\Program Files\Microsoft Office\Office\MSO97.DLL"
#import "C:\Program Files\Common Files\Microsoft Shared\VBA\VBEEXT1.OLB"
#import "C:\Program Files\Microsoft Office\Office\MSWORD8.OLB" \
rename("ExitWindows","_ExitWindows")
#import "C:\Program Files\Microsoft Office\Office\EXCEL8.OLB" \
rename("DialogBox","_DialogBox") \
rename("RGB","_RGB") \
exclude("IFont","IPicture")
#import "C:\Program Files\Common Files\Microsoft Shared\DAO\DAO350.DLL" \
rename("EOF","EndOfFile")
rename("BOF","BegOfFile")
#import "C:\Program Files\Microsoft Office\Office\MSACC8.OLB"
#endif
We shall add the following code to the beginning of XOfficeDoc.cpp file:
<font color=green>// FormDemo.cpp</font>
void NewXOfficeDoc(LPCTSTR,LPCTSTR,double,long);
void CFormDemo::OnButton1()
{
UpdateData();
NewXOfficeDoc("XOffice.doc",m_str,m_double,m_long);
}
void CFormDemo::OnButton2()
{
UpdateData();
NewXOfficeDoc("XOffice.xls",m_str,m_double,m_long);
}
<font color=green>// XOfficeDoc.cpp</font>
static CString g_template;
static CString g_str;
static double g_double;
static long g_long;
void NewXOfficeDoc(LPCTSTR aTemplate,
LPCTSTR aStr,
double aDouble,
long aLong)
{
CString str;
POSITION pos = AfxGetApp()->GetFirstDocTemplatePosition();
while (pos != NULL)
{
CDocTemplate *temp = AfxGetApp()->GetNextDocTemplate(pos);
if (temp->GetDocString(str,CDocTemplate::docName)
{
str == _T("XOffice"));
g_template = aTemplate;
g_str = aStr;
g_double = aDouble;
g_long = aLong;
temp->OpenDocumentFile(NULL);
return;
}
}
}
<font color=green>// CntrItem.h</font>
class CXOfficeCntrItem : public ColeDocObjectItem
{
<font color=green>//...</font>
public:
CXOfficeCntrItem(CXOfficeDoc* pContainer,LPCTSTR);
bool m_isCreate;
bool CreateItem(LPCTSTR);
<font color=green>//...</font>
};
<font color=green>// CntrItem.cpp</font>
CXOfficeCntrItem::CXOfficeCntrItem(CXOfficeDoc* pContainer,LPCTSTR templ)
: COleDocObjectItem(pContainer), m_isCreate(false)
{
CreateItem(templ);
}
bool CXOfficeCntrItem::CreateItem(LPCTSTR templ)
{
USES_CONVERSION;
<font color=green>// get storage for the object via virtual function call</font>
m_dwItemNumber = GetNewItemNumber();
GetItemStorage();
<font color=green>// add AfxOleInit(); in CXOfficeApp::InitInstance</font>
AfxOleGetMessageFilter()->EnableNotRespondingDialog(FALSE);
<font color=green>// attempt to create the object</font>
LPOLECLIENTSITE lpClientSite = GetClientSite();
SCODE sc = ::OleCreateFromFile(CLSID_NULL,
T2COLE(templ),
IID_IUnknown,
OLERENDER_DRAW,
NULL,
lpClientSite,
m_lpStorage,
(LPVOID*)&m_lpObject);
return m_isCreate = FinishCreate(sc) == TRUE;
}
So, now we are able to load ActiveX documents automatically. It is quite not bad already. J Pay attention to the fact that the procedures of preservation and loading of our documents work normally too, saving thus the contents of the initial template document. The truth is that we don't need it at all. The only thing that does not work is Print Preview. I was not able to understand it therefore, if someone manages to do it I shall be very obliged to find out about it first. <font color=green>// XOfficeDoc.h</font>
<font color=green>...</font>
class CXOfficeCntrItem;
class CXOfficeDoc : public COleDocument,
...
{
...
public:
CXOfficeCntrItem *m_ctrl;
CString m_template;
CString m_str;
double m_double;
long m_long;
bool LoadTemplate();
<font color=green>...</font>
};
<font color=green>// XOfficeDoc.cpp</font>
CXOfficeDoc::CXOfficeDoc()
: m_ctrl(0)
{
EnableCompoundFile();
}
BOOL CXOfficeDoc::OnNewDocument()
{
if (!COleDocument::OnNewDocument())
return FALSE;
m_template = g_template;
m_str = g_str;
m_double = g_double;
m_long = g_long;
return LoadTemplate();
}
bool CXOfficeDoc::LoadTemplate()
{
char path [_MAX_PATH];
char drive[_MAX_DRIVE];
char dir [_MAX_DIR];
char fname[_MAX_FNAME];
char ext [_MAX_EXT];
::GetModuleFileName(NULL,path,sizeof(path));
_splitpath(path, drive,dir,0, 0);
_splitpath(g_template,0, 0, fname,ext);
_makepath (path, drive,dir,fname,ext);
{
CWaitCursor cw;
m_ctrl = new CXOfficeCntrItem(this,path);
}
if (m_ctrl == 0 || m_ctrl->m_isCreate == false)
{
CString str = "Can not open the doc:\n";
str += path;
AfxMessageBox(str,MB_ICONSTOP);
return false;
}
return true;
}
<font color=green>// XOfficeView.cpp</font>
void CXOfficeView::OnInitialUpdate()
{
CView::OnInitialUpdate();
CWaitCursor wc;
m_pSelection = GetDocument()->m_ctrl;
<font color=green>...</font>
}
<font color=green>// XOfficeDoc.cpp</font>
void CXOfficeDoc::Serialize(CArchive& ar)
{
if (ar.IsStoring())
{
ar << m_template << m_str << m_double << m_long;
} else {
ar >> m_template >> m_str >> m_double >> m_long;
}
<font color=green> //COleDocument::Serialize(ar);</font>
}
BOOL CXOfficeDoc::OnOpenDocument(LPCTSTR lpszPathName)
{
if (!COleDocument::OnOpenDocument(lpszPathName))
return FALSE;
return LoadTemplate();
}
BOOL CXOfficeDoc::SaveModified()
{
return CDocument::SaveModified();
}
<font color=green>// CntrItem.cpp</font>
void CXOfficeCntrItem::OnChange(OLE_NOTIFICATION nCode, DWORD dwParam)
{
BOOL modified = m_pDocument->IsModified();
COleDocObjectItem::OnChange(nCode, dwParam);
m_pDocument->SetModifiedFlag(modified);
GetDocument()->UpdateAllViews(NULL);
}
<font color=green>// CntrItem.h</font>
<font color=green>...</font>
#include <comdef.h>
<font color=green>...</font>
class CXOfficeCntrItem : public COleDocObjectItem
{
public:
<font color=green>...</font>
int m_who; <font color=green>// 0 - ?, 1 - Word, 2 - Excel</font>
IDispatchPtr m_disp;
LPDISPATCH GetIDispatch();
void AttachDisp ();
void ActivateDisp();
void CloseDisp ();
<font color=green>...</font>
};
<font color=green>// CXOfficeView.cpp</font>
void CXOfficeView::OnInitialUpdate()
{
<font color=green>...</font>
m_pSelection = GetDocument()->m_ctrl;
m_pSelection->AttachDisp();
<font color=green>//Active documents should always be activated</font>
<font color=green>...</font>
m_pSelection->ActivateDisp();
}
<font color=green>// CXOfficeDoc.cpp</font>
void CXOfficeDoc::OnCloseDocument()
{
if (m_ctrl)
m_ctrl->CloseDisp();
COleDocument::OnCloseDocument();
}
Downloads
Download demo project - 36 Kb
Download source - 71 Kb