魔改——MFC SDI 支持 内嵌 EXCEL OLE

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

本文版权归作者所有

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

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

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

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

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

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

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

本文链接: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

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

时间: 2024-11-03 03:34:31

魔改——MFC SDI 支持 内嵌 EXCEL OLE的相关文章

魔改——MFC SDI转MDI

==================================声明================================== 本文原创,转载在正文中显要的注明作者和出处,并保证文章的完整性. 未经作者同意请勿修改(包括本声明),保留法律追究的权利. 未经作者同意请勿用于出版.印刷或学术引用. 本文不定期修正完善,为保证内容正确,建议移步原文处阅读. 本文链接:http://www.cnblogs.com/wlsandwho/p/4286906.html =============

Java编辑PPT的折线图,与内嵌Excel联动

/** * 折线图的数据写入方法 * @param slide ppt图表 * @param index 折线图的下标 * @param data 需要填充的数据 * @param titles 内嵌Excel的X轴title * @param columnTitles 内嵌Excel的Y轴title * @return * @throws IOException */ @SuppressWarnings("unused") public static XSLFSlide setLin

Java设置PPT的扇形图,与内嵌Excel联动

/** * 设置饼图的主方法 * @param slide 图表 * @param index 图标位置 * @param data 需要设置的数据 * @param titles 关联Excel的标题 * @return */ public static XSLFSlide setPieChart(XSLFSlide slide, int index, List<String> data, List<String> titles) { // 获取指定位置的图形 XSLFChart

C# Dsoframer.ocx 如何在winform中嵌入Excel,内嵌Excel,word

如果你还不太清楚Dspframer.ocx怎么放到窗体上就看上一篇文章,里面详细介绍了是如何放到窗体上的. 链接:http://www.cnblogs.com/pingming/p/4182045.html 第一步 创建新窗体 创建一个新窗体,放置一个panel容器控件,我们就是要将dsoframer.ocx放到panel里面. 第二步 下面是所有调用的方法,有步骤的. public partial class ExcelForm : DevExpress.XtraEditors.XtraFor

C# 如何在winform中嵌入Excel,内嵌Excel,word

近使用.net做一个小软件遇到一个问题,就是想实现把excel表格在winform中打开,同时可以操作,不单单是打开.或者就提取数据.在网上找了好多资料,发现这方面的资料比较少,即使有,都是旧版本的使用方法.在这里分享一下自己用vs C# 在winform中嵌入excel的一些经验. 首先,本人使用的VS 版本是2010,据我所知,2010的vs是没有这个控件(就是想button控件能直接拉进去的).因此我们需要一个第三方控件来实现这个功能. 然后,那么我们需要的第三方控件叫什么呢?这个控件就是

使内嵌式jetty服务器支持jsp

1.jetty是什么 jetty是一个轻量级的web服务器,类似tomcat,但用起来比tomcat灵活,尤其是支持内嵌式使用.所谓内嵌式即以java语句的形式启动jetty,这样我们可以无需部署和启动web容器就能达到同样的效果.这对于简单的基于http协议的应用以及调试程序就方便的多了. 2.一个简单的jetty服务器 简单到仅需类似以下几条语句: public class JettySample { public static void main(String[] args)throws 

SAP ALV内嵌(In-place)Excel的问与答

1.问题:点击ALV工具栏的"Excel"图标后,出现空白的内嵌Excel界面,无法正常显示报表数据.可按以下思路解决:(1)检查Excel中的宏安全设置选项.访问方法:启动Excel,点击"Tools"菜单,选择 "Option"菜单项,在弹出的"Option"窗体点击"Security"标签页,再点击窗体右下角的"Macro Security..."按钮,在弹出的"Secu

内嵌函数和闭包

函数的嵌套 python的函数支持内嵌,即在函数中定义函数 >>> def fun1(): print('fun1()正在被调用') def fun2(): print('fun2()正在被调用') fun2() >>> fun1() fun1()正在被调用 fun2()正在被调用 内嵌函数的作用域在外部函数之内,即fun2只能在fun1之内调用. >>> fun2() Traceback (most recent call last): File &

swt java 内嵌ActiveX控件

这里用的是SWT/JFace开发application中SWT自带的org.eclipse.swt.ole.win32 包可以支持内嵌OLE和ActiveX. 具体用法如下: //创建一个OleFrame做为OLE(或ActiveX)的框架 OleFrame oleFrame = new OleFrame(this, SWT.NONE); //创建ActiveX的容器,其中的classID是ActiveX的classid,在注册表中可以找到 OleControlSite oleControl =