==================================声明==================================

本文版权归作者所有

未经作者授权 请勿转载 保留法律追究的权利

本文原创,已获得转载授权的,必须在正文中显要地注明作者和出处,并保证文章(包括本声明)的完整性。

被授权人不可再次授权第三方。

未经作者授权请勿修改(包括本声明),保留法律追究的权利。

未经作者授权请勿用于学术性引用。

未经作者授权请勿用于商业出版、商业印刷、商业引用以及其他商业用途。                    <--------总有一天我要自己做一个模板干掉这只土豆

 

本文不定期修正完善,为保证内容正确,建议移步原文处阅读。

本文链接:http://www.cnblogs.com/wlsandwho/p/4512840.html

=======================================================================

并没有找到什么好的资料

微软的官方文档里有一个SDI嵌入Excel的例子,再加上MFC的代码都是可见的,所以应该是可以搞一搞的。

这是微软官方文档https://support.microsoft.com/zh-cn/kb/184663网上对这篇古老的文章大肆抄袭。

我就不贴出来了,我这里用Win7 64+VC2010+Office 2007实现一下。

=======================================================================

万一哪天我忘了怎么弄这个,还能找找自己的博客,顺便感叹下自己曾经也是的。

=======================================================================

1 创建工程

下面的很重要,一定要选择为容器

2 添加Excel

这里我是64位系统,文件路径带x86,32位的不带这个。

点击完成和确定,MFC会自动生成一大堆类。(叫包装类更合适吧?)

这里要修改一下生成的.h文件。

CApplication.h文件是一定会用到的。注销到原来的第一行,添加三个import和三个using,不要问为什么,这里不是重点讲Office二次开发。

1 //#import "C:\\Program Files (x86)\\Microsoft Office\\Office12\\EXCEL.EXE" no_namespace
2 // CApplication 包装类
3 #import "C:\\Program Files (x86)\\Common Files\\microsoft shared\\OFFICE12\\MSO.DLL" rename("RGB","MSORGB") rename("DocumentProperties","MSODocumentProperties")
4 using namespace Office;
5 #import "C:\\Program Files (x86)\\Common Files\\microsoft shared\\VBA\\VBA6\\VBE6EXT.OLB" 
6 using namespace VBIDE;
7 #import "C:\\Program Files (x86)\\Microsoft Office\\Office12\\EXCEL.EXE" rename("DialogBox","ExcelDialogBox") rename("RGB","ExcelRGB") rename("CopyFile","ExcelCopyFile") rename("ReplaceText","ExcelReplaceText") no_auto_exclude
8 using namespace Excel;

其他的.h文件,也是屏蔽原来的import,例如下面要用到

1 #include "CWorkbooks.h"
2 #include "CWorkbook.h"
3 #include "CWorksheets.h"
4 #include "CWorksheet.h"
5 #include "CRange.h"

我就把它们原来的第一个import都屏蔽了。

对于 “DialogBoxW”宏的实参不足

修改为

1 VARIANT _DialogBox()

3 修改CntrItem.h和CntrItem.cpp

由于之前添加了Excel,所以现在文件比较多,要慢慢找找。一定能找到的。

值得注意的是,这个文件名并没有遵循“文件名<=>类名”的国际惯例,例如我的这个Embed_ExcelWLS工程,文件名还是叫CntrItem.h,但是类名叫CEmbed_ExcelWLSCntrItem。

给CEmbed_ExcelWLSCntrItem类添加一个函数用于获得接口。(为了区别原有代码,我会在自己添加的代码前加一行“/”)

 1 // CntrItem.h : CEmbed_ExcelWLSCntrItem 类的接口
 2 //
 3 
 4 #pragma once
 5 
 6 class CEmbed_ExcelWLSDoc;
 7 class CEmbed_ExcelWLSView;
 8 
 9 class CEmbed_ExcelWLSCntrItem : public COleClientItem
10 {
11     DECLARE_SERIAL(CEmbed_ExcelWLSCntrItem)
12 
13 // 构造函数
14 public:
15     CEmbed_ExcelWLSCntrItem(CEmbed_ExcelWLSDoc* pContainer = NULL);
16         // 注意: 允许 pContainer 为 NULL 以启用 IMPLEMENT_SERIALIZE
17         //  IMPLEMENT_SERIALIZE 要求类具有带零
18         //  参数的构造函数。OLE 项通常是用
19         //  非 NULL 文档指针构造的
20 
21 // 特性
22 public:
23     CEmbed_ExcelWLSDoc* GetDocument()
24         { return reinterpret_cast<CEmbed_ExcelWLSDoc*>(COleClientItem::GetDocument()); }
25     CEmbed_ExcelWLSView* GetActiveView()
26         { return reinterpret_cast<CEmbed_ExcelWLSView*>(COleClientItem::GetActiveView()); }
27 
28 public:
29     virtual void OnChange(OLE_NOTIFICATION wNotification, DWORD dwParam);
30     virtual void OnActivate();
31 
32 protected:
33     virtual void OnGetItemPosition(CRect& rPosition);
34     virtual void OnDeactivateUI(BOOL bUndoable);
35     virtual BOOL OnChangeItemPosition(const CRect& rectPos);
36     virtual BOOL OnShowControlBars(CFrameWnd* pFrameWnd, BOOL bShow);
37 
38 // 实现
39 public:
40     ~CEmbed_ExcelWLSCntrItem();
41 #ifdef _DEBUG
42     virtual void AssertValid() const;
43     virtual void Dump(CDumpContext& dc) const;
44 #endif
45     virtual void Serialize(CArchive& ar);
46 
47 //////////////////////////////////////////////////////////////////////////
48 public:
49     LPDISPATCH GetIDispatch();
50 };
 1 //////////////////////////////////////////////////////////////////////////
 2 /*******************************************************************
 3 *   This method returns the IDispatch* for the application linked to
 4 *   this container.
 5 ********************************************************************/ 
 6 LPDISPATCH CEmbed_ExcelWLSCntrItem::GetIDispatch()
 7 {
 8     //The this and m_lpObject pointers must be valid for this function
 9     //to work correctly. The m_lpObject is the IUnknown pointer to
10     // this object.
11     ASSERT_VALID(this);
12 
13     ASSERT(m_lpObject != NULL);
14 
15     LPUNKNOWN lpUnk = m_lpObject;
16 
17     //The embedded application must be running in order for the rest
18     //of the function to work.
19     Run();
20 
21     //QI for the IOleLink interface of m_lpObject.
22     LPOLELINK lpOleLink = NULL;
23     if (m_lpObject->QueryInterface(IID_IOleLink,
24         (LPVOID FAR*)&lpOleLink) == NOERROR)
25     {
26         ASSERT(lpOleLink != NULL);
27         lpUnk = NULL;
28 
29         //Retrieve the IUnknown interface to the linked application.
30         if (lpOleLink->GetBoundSource(&lpUnk) != NOERROR)
31         {
32             TRACE0("Warning: Link is not connected!\n");
33             lpOleLink->Release();
34             return NULL;
35         }
36         ASSERT(lpUnk != NULL);
37     }
38 
39     //QI for the IDispatch interface of the linked application.
40     LPDISPATCH lpDispatch = NULL;
41     if (lpUnk->QueryInterface(IID_IDispatch, (LPVOID FAR*)&lpDispatch)
42         !=NOERROR)
43     {
44         TRACE0("Warning: does not support IDispatch!\n");
45         return NULL;
46     }
47 
48     //After assuring ourselves it is valid, return the IDispatch
49     //interface to the caller.
50     ASSERT(lpDispatch != NULL);
51     return lpDispatch;
52 }

4 修改View文件

 添加一个函数EmbedAutomateExcel

 1 // Embed_ExcelWLSView.h : CEmbed_ExcelWLSView 类的接口
 2 //
 3 
 4 #pragma once
 5 
 6 class CEmbed_ExcelWLSCntrItem;
 7 
 8 class CEmbed_ExcelWLSView : public CView
 9 {
10 protected: // 仅从序列化创建
11     CEmbed_ExcelWLSView();
12     DECLARE_DYNCREATE(CEmbed_ExcelWLSView)
13 
14 // 特性
15 public:
16     CEmbed_ExcelWLSDoc* GetDocument() const;
17     // m_pSelection 将所选内容保存在当前的 CEmbed_ExcelWLSCntrItem 中。
18     // 对于许多应用程序,这种成员变量不足以
19     //  表示某个选择,例如在不属于 CEmbed_ExcelWLSCntrItem 的对象中
20     //  选定的一个或多个对象。提供这种选择
21     //  机制的目的只是帮助您入门
22 
23     // TODO: 用适合应用程序的选择机制替换此选择机制
24     CEmbed_ExcelWLSCntrItem* m_pSelection;
25 
26 // 操作
27 public:
28 
29 // 重写
30 public:
31     virtual void OnDraw(CDC* pDC);  // 重写以绘制该视图
32     virtual BOOL PreCreateWindow(CREATESTRUCT& cs);
33 protected:
34     virtual void OnInitialUpdate(); // 构造后第一次调用
35     virtual BOOL OnPreparePrinting(CPrintInfo* pInfo);
36     virtual void OnBeginPrinting(CDC* pDC, CPrintInfo* pInfo);
37     virtual void OnEndPrinting(CDC* pDC, CPrintInfo* pInfo);
38     virtual BOOL IsSelected(const CObject* pDocItem) const;// 容器支持
39 
40 // 实现
41 public:
42     virtual ~CEmbed_ExcelWLSView();
43 #ifdef _DEBUG
44     virtual void AssertValid() const;
45     virtual void Dump(CDumpContext& dc) const;
46 #endif
47 
48 protected:
49 
50 // 生成的消息映射函数
51 protected:
52     afx_msg void OnDestroy();
53     afx_msg void OnSetFocus(CWnd* pOldWnd);
54     afx_msg void OnSize(UINT nType, int cx, int cy);
55     afx_msg void OnInsertObject();
56     afx_msg void OnCancelEditCntr();
57     afx_msg void OnFilePrint();
58     afx_msg void OnFilePrintPreview();
59     afx_msg void OnRButtonUp(UINT nFlags, CPoint point);
60     afx_msg void OnContextMenu(CWnd* pWnd, CPoint point);
61     DECLARE_MESSAGE_MAP()
62 
63 //////////////////////////////////////////////////////////////////////////
64 public:
65     void EmbedAutomateExcel();
66 };
67 
68 #ifndef _DEBUG  // Embed_ExcelWLSView.cpp 中的调试版本
69 inline CEmbed_ExcelWLSDoc* CEmbed_ExcelWLSView::GetDocument() const
70    { return reinterpret_cast<CEmbed_ExcelWLSDoc*>(m_pDocument); }
71 #endif

实现代码稍微改了下,毕竟office12不是excel9了。

  1 //////////////////////////////////////////////////////////////////////////
  2 /********************************************************************
  3 *   This method encapsulates the process of embedding an Excel
  4 *   Worksheet in a View object and automating that worksheet to add
  5 *   some text to cell A1.
  6 ********************************************************************/ 
  7 void CEmbed_ExcelWLSView::EmbedAutomateExcel()
  8 {
  9    //Change the cursor so the user knows something exciting is going
 10    //on.
 11    BeginWaitCursor();
 12 
 13    CEmbed_ExcelWLSCntrItem* pItem = NULL;
 14    TRY
 15    {
 16         //Get the document associated with this view, and be sure it's
 17         //valid.
 18         CEmbed_ExcelWLSDoc* pDoc = GetDocument();
 19         ASSERT_VALID(pDoc);
 20 
 21         //Create a new item associated with this document, and be sure
 22         //it's valid.
 23         pItem = new CEmbed_ExcelWLSCntrItem(pDoc);
 24         ASSERT_VALID(pItem);
 25         
 26         // Get Class ID for Excel sheet.
 27         // This is used in creation.
 28         CLSID clsid;
 29         if(FAILED(::CLSIDFromProgID(L"Excel.sheet",&clsid)))
 30             //Any exception will do. We just need to break out of the
 31             //TRY statement.
 32             AfxThrowMemoryException();
 33 
 34         // Create the Excel embedded item.
 35         if(!pItem->CreateNewItem(clsid))
 36             //Any exception will do. We just need to break out of the
 37             //TRY statement.
 38             AfxThrowMemoryException();
 39 
 40         //Make sure the new CContainerItem is valid.
 41         ASSERT_VALID(pItem);
 42 
 43         // Launch the server to edit the item.
 44         pItem->DoVerb(OLEIVERB_SHOW, this);
 45 
 46         // As an arbitrary user interface design, this sets the
 47         // selection to the last item inserted.
 48         m_pSelection = pItem;   // set selection to last inserted item
 49         pDoc->UpdateAllViews(NULL);
 50 
 51         //Query for the dispatch pointer for the embedded object. In
 52         //this case, this is the Excel worksheet.
 53         LPDISPATCH lpDisp;
 54         lpDisp = pItem->GetIDispatch();
 55 
 56         //Add text in cell A1 of the embedded Excel sheet
 57         CApplication ExcelApp;
 58         CWorkbooks ExcelBooks;
 59         CWorkbook ExcelBook;
 60         CWorksheets ExcelSheets;
 61         CWorksheet ExcelSheet;    
 62         CRange ExcelRange;
 63 
 64 
 65         ExcelBook.AttachDispatch(lpDisp);
 66         ExcelApp=ExcelBook.get_Application();
 67         ExcelSheets=ExcelBook.get_Sheets();
 68         ExcelSheet=ExcelSheets.get_Item(COleVariant((short)1));
 69         ExcelRange=ExcelSheet.get_Range(COleVariant(TEXT("A1")),COleVariant(TEXT("A1")));
 70         ExcelRange.put_Item(_variant_t((long)1),_variant_t((long)1),_variant_t(TEXT("Hello Embed-Excel by WLS")));
 71 
 72         ExcelRange.ReleaseDispatch();
 73         ExcelSheet.ReleaseDispatch();
 74         ExcelSheets.ReleaseDispatch();
 75         ExcelBook.ReleaseDispatch();
 76         ExcelApp.Quit();
 77         ExcelApp.ReleaseDispatch();
 78     
 79 
 80         //NOTE: If you are automating Excel 2002, the Range.SetValue method has an 
 81         //additional optional parameter specifying the data type.  Because the 
 82         //parameter is optional, existing code will still work correctly, but new 
 83         //code should use the new convention.  The call for Excel2002 should look 
 84         //like the following:
 85         
 86         //range.SetValue( ColeVariant( (long)DISP_E_PARAMNOTFOUND, VT_ERROR ), 
 87         //                COleVariant("Hello, World!"));
 88     }
 89 
 90     //Here, we need to do clean up if something went wrong.
 91     CATCH(CException, e)
 92     {
 93         if (pItem != NULL)
 94         {
 95             ASSERT_VALID(pItem);
 96             pItem->Delete();
 97         }
 98         AfxMessageBox(IDP_FAILED_TO_CREATE);
 99     }
100     END_CATCH
101 
102     //Set the cursor back to normal so the user knows exciting stuff
103     //is no longer happening.
104     EndWaitCursor();
105 }

记得添加.h文件

5 修改OnInsertObject函数

 1 void CEmbed_ExcelWLSView::OnInsertObject()
 2 {
 3     // 调用标准的“插入对象”对话框以获得有关
 4     //  新 CEmbed_ExcelWLSCntrItem 对象的信息
 5 //     COleInsertDialog dlg;
 6 //     if (dlg.DoModal() != IDOK)
 7 //         return;
 8 // 
 9 //     BeginWaitCursor();
10 // 
11 //     CEmbed_ExcelWLSCntrItem* pItem = NULL;
12 //     TRY
13 //     {
14 //         // 创建与此文档相连接的新项
15 //         CEmbed_ExcelWLSDoc* pDoc = GetDocument();
16 //         ASSERT_VALID(pDoc);
17 //         pItem = new CEmbed_ExcelWLSCntrItem(pDoc);
18 //         ASSERT_VALID(pItem);
19 // 
20 //         // 通过对话框数据初始化该项
21 //         if (!dlg.CreateItem(pItem))
22 //             AfxThrowMemoryException();  // 任何异常都将导致该结果
23 //         ASSERT_VALID(pItem);
24 //         
25 //         if (dlg.GetSelectionType() == COleInsertDialog::createNewItem)
26 //             pItem->DoVerb(OLEIVERB_SHOW, this);
27 // 
28 //         ASSERT_VALID(pItem);
29 //         // 作为任意用户界面设计,这会将所选内容
30 //         //  设置为插入的最后一项
31 // 
32 //         // TODO: 重新实现所选内容,使其适合于您的应用程序
33 //         m_pSelection = pItem;   // 将所选内容设置为插入的最后一项
34 //         pDoc->UpdateAllViews(NULL);
35 //     }
36 //     CATCH(CException, e)
37 //     {
38 //         if (pItem != NULL)
39 //         {
40 //             ASSERT_VALID(pItem);
41 //             pItem->Delete();
42 //         }
43 //         AfxMessageBox(IDP_FAILED_TO_CREATE);
44 //     }
45 //     END_CATCH
46 // 
47 //     EndWaitCursor();
48 
49     EmbedAutomateExcel();
50 }

 下面执行看下效果。

点击文件-退出

再点击取消

=======================================================================

要注意的是,部分安全软件,例如我的大Comodo会在HIPS和沙箱里拦截对COM口的访问,所以你懂的。

=======================================================================

 

 

 

 

 

 

 

=======================================================================

下一篇文章,将使用MFC的对话框程序实现内嵌Excel。

虽然实现了但还有些东西没弄好,为了部落的荣耀还是先写个SDI的放出来吧。

=======================================================================

文中示例代码在我的CSDN下载中http://download.csdn.net/detail/wlsgzl/8730199

不过,认真看文章跟着做的话基本不需要下载这个资源。

 

 

 

 

 

 

=======================================================================

耻辱墙 http://www.cnblogs.com/wlsandwho/p/4206472.html