如何使用 MFC 检索 Office 文档中的宏名称的列表

心已赠人 2022-08-24 05:26 49阅读 0赞

如何使用 MFC 检索 Office 文档中的宏名称的列表

本文介绍如何创建 MFC 自动化客户端检索 for Applications (VBA) 的 Visual Basic 列表的示例从 Microsoft Office 文档的宏 ( SubFunction 过程)。

要获取 Microsoft Excel 中的 VBA 过程的列表工作簿、 Microsoft PowerPoint 演示文稿或 Microsoft Word 文档,可以使用类和函数公开由 Microsoft Visual Basic for Applications 扩展性库与应用程序对象模型。 当打开文档时使用自动化时,可以访问循环访问集合 VBComponents 文档的 VBProject 对象 ; VBComponents 集合包含标准模块,以及在项目中包含的类模块。 后对 VBComponent 引用可以检索其属性 (包括代码),并需要操作该组件。

请注意 特殊的考虑,Microsoft Access: Microsoft Access 是一个例外,在 Visual Basic for Applications 扩展性库不需要访问数据库项目中的代码。 Microsoft Access 对象模型公开方法或直接访问代码模块允许您的属性。 有关检索或操作与在 Access 数据库模块代码警告之一是必须先打开该模块。

以下步骤演示如何创建一个 MFC 自动化客户端从 Office 文档中检索的 SubFunction 过程列表。 示例代码阐释如何使用 Office 应用程序类型库和 Visual Basic for Applications 扩展性库的类包装 ; 该示例还提供了特殊的案例考虑,对于 Microsoft Access 数据库。

示例项目

  1. 在 Visual C++,创建命名 ListMacros 一个新的 MFC AppWizard EXE 项目。 选择 对话框基于 作为类型,然后接受所有其他默认值。
  2. 视图 菜单中上, 单击 ClassWizard 。 在 ClassWizard 对话框单击 自动化 选项卡,然后执行下列操作:

    • 单击 添加类 并选择 从类型库
    • 浏览到找到 Microsoft Visual Basic for Applications Extensibility 类型库 (VBE6EXT.olb),,然后单击 打开

      请注意 VBE6EXT.olb 在默认文件夹是 C:/Program Files /Common Files /Microsoft Shared/VBA/VBA6。

    • 在类型库中选择所有类,然后单击 确定 以创建类包装。
  3. 重复上述步骤创建 Microsoft Excel、 Microsoft PowerPoint、 Microsoft Access 和 Microsoft Word 类型库的类包装。 选择正确的类型库在自动化的 Office 的版本。 请参见本文以获取有关查找正确的类型库的信息后面,”参考一节。
  4. 若要避免类名称冲突,请请为每个类包装通过执行以下添加命名空间:

    • 将以下代码添加到 Excel9.h 的开头:

      namespace Excel{

      ,然后添加结转大括号 (}) 文件的末尾。

    • 将以下代码添加到显示”# endif”(不带引号) 的行下方的 Excel9.cpp,开头之前在第一个类的定义:

      using namespace Excel;

  5. 重复这些步骤以创建剩余的命名空间: MSWordPPTMSAccessVBAExt
  6. 单击 ResourceView 并打开 IDD_LISTMACROS_DIALOG 对话框。 删除所有控件,对话框上绘制其替换为以下控件:

    1. Control Type Properties
    2. ------------ -------------------------
    3. Button ID: ID_Run
    4. Caption: Run
    5. Edit Box ID: IDC_FILENAME
    6. List Box ID: IDC_MACROLIST
    7. Use Tabstops: Checked
  7. 视图 菜单上单击 ClassWizard ,选择 成员变量 选项卡,在 类名称 下拉列表框中中, 选择 CListMacrosDlg ,然后执行下列操作:

    • 在控件列表上双击 IDC_FILENAME 。 在 添加成员变量 对话框提供在变量名 m_sFilename ,然后单击 确定
    • 在控件列表上双击 IDC_MACROLIST 。 在 添加成员变量 对话框提供变量名 m_MacroList控制 ,更改该 类别 ,然后单击 确定
  8. 单击 确定 以关闭 ClassWizard 对话框。
  9. 双击 运行 按钮在对话框。 单击要添加成员函数 OnRun 确定 。 将以下代码添加到 CListMacrosDlg::OnRun()

    `void CListMacrosDlg::OnRun()
    {
    USES_CONVERSION;

    UpdateData(TRUE);

  1. COleVariant vOpt(DISP_E_PARAMNOTFOUND, VT_ERROR); //for Optional args
  2. //Determine the PROGID for the filename supplied
  3. CLSID clsid;
  4. HRESULT hr = GetClassFile(T2OLE(m_sFilename), &clsid);
  5. if (FAILED(hr))
  6. {
  7. CString sMsg;
  8. sMsg.Format("Unable to determine progid for file: %s", m_sFilename);
  9. AfxMessageBox(sMsg);
  10. return;
  11. }
  12. LPOLESTR lpOleStr;
  13. ProgIDFromCLSID(clsid, &lpOleStr);
  14. CString sProgID = CString(lpOleStr);
  15. sProgID.MakeUpper();
  16. //If the version independent progid is EXCEL.SHEET, WORD.DOCUMENT, or
  17. //POWERPOINT.SHOW, then open the file in its associated application.
  18. //Once the file is open, call GetMacros to place the list of macro
  19. //names in the list box.
  20. if(sProgID.Find("EXCEL.SHEET",0)>=0) //Microsoft Excel Workbook
  21. {
  22. Excel::_Application oApp;
  23. oApp.CreateDispatch("Excel.Application");
  24. Excel::Workbooks oBooks = oApp.GetWorkbooks();
  25. Excel::_Workbook oBook = oBooks.Open(m_sFilename, vOpt, vOpt, vOpt,
  26. vOpt, vOpt, vOpt, vOpt, vOpt,
  27. vOpt, vOpt, vOpt, vOpt);
  28. LPDISPATCH lpDisp = oBook.GetVBProject();
  29. GetMacros(lpDisp);
  30. oBook.Close(COleVariant((short)FALSE), vOpt, vOpt);
  31. oApp.Quit();
  32. }
  33. else if(sProgID.Find("WORD.DOCUMENT",0)>=0) //Microsoft Word Document
  34. {
  35. MSWord::_Application oApp;
  36. oApp.CreateDispatch("Word.Application");
  37. MSWord::Documents oDocs = oApp.GetDocuments();
  38. MSWord::_Document oDoc = oDocs.Open(COleVariant(m_sFilename), vOpt,
  39. vOpt, vOpt, vOpt, vOpt, vOpt,
  40. vOpt, vOpt, vOpt, vOpt, vOpt);
  41. // For Office Word 2003 and Office Word 2007, 16 parameters are required.
  42. /* MSWord::_Document oDoc = oDocs.Open(COleVariant(m_sFilename), vOpt,
  43. vOpt, vOpt, vOpt, vOpt, vOpt,
  44. vOpt, vOpt, vOpt, vOpt, vOpt,
  45. vOpt,vOpt,vOpt,vOpt);
  46. */
  47. LPDISPATCH lpDisp = oDoc.GetVBProject();
  48. GetMacros(lpDisp);
  49. oDoc.Close(COleVariant((short)FALSE), vOpt, vOpt);
  50. oApp.Quit(vOpt, vOpt, vOpt);
  51. }
  52. else if(sProgID.Find("POWERPOINT.SHOW",0)>=0) //Microsoft PowerPoint
  53. //Presentation
  54. {
  55. PPT::_Application oApp;
  56. oApp.CreateDispatch("Powerpoint.Application");
  57. PPT::Presentations oAllPres = oApp.GetPresentations();
  58. PPT::_Presentation oPres = oAllPres.Open(m_sFilename, 0, 0, 0);
  59. LPDISPATCH lpDisp = oPres.GetVBProject();
  60. GetMacros(lpDisp);
  61. oPres.Close();
  62. oApp.Quit();
  63. }
  64. else if(sProgID.Find("ACCESS.APPLICATION", 0)>=0) //Microsoft Access DB
  65. { //** Special Consideration for Access Code Project
  66. MSAccess::_Application oApp;
  67. oApp.CreateDispatch("Access.Application");
  68. MSAccess::DoCmd oDoCmd = oApp.GetDoCmd();
  69. oApp.OpenCurrentDatabase(m_sFilename, FALSE);
  70. // For Office Access 2003 and Office Access 2007, 3 parameters are required.
  71. /*oApp.OpenCurrentDatabase(m_sFilename, FALSE,NULL);*/
  72. MSAccess::_CurrentProject oProj = oApp.GetCurrentProject();
  73. MSAccess::AllObjects oObjs = oProj.GetAllModules();
  74. CString sModName, sProcName, sItem;
  75. long lProcKind = 0;
  76. for(long i=0;i<=oObjs.GetCount()-1;i++)
  77. {
  78. MSAccess::AccessObject oObj = oObjs.GetItem(COleVariant(i));
  79. sModName = oObj.GetName();
  80. //Module must be open:
  81. oDoCmd.OpenModule(COleVariant(sModName), vOpt);
  82. MSAccess::Modules oMods = oApp.GetModules();
  83. MSAccess::Module oMod = oMods.GetItem(COleVariant(sModName));
  84. long lLineCount = oMod.GetCountOfLines();
  85. long j=1;
  86. while(j<lLineCount)
  87. {
  88. sProcName = oMod.GetProcOfLine(j, &lProcKind);
  89. if(!sProcName.IsEmpty()){
  90. sItem.Format("%s/t/t%s", sModName, sProcName);
  91. m_MacroList.AddString(sItem);
  92. j = j + oMod.GetProcCountLines(sProcName, lProcKind); }
  93. else {
  94. j++; }
  95. }
  96. }
  97. oApp.Quit(0);
  98. }
  99. else //Other...
  100. {
  101. CString sMsg;
  102. sMsg.Format("Unable to extract macro names for files with progid %s",
  103. sProgID);
  104. AfxMessageBox(sMsg);
  105. }

}`

  1. 添加以下包括 ListMacrosDlg.cpp:

    `#include

    include “Excel9.h” // for Office Excel 2003 and later, use #include “Excel.h”

    include “MSWord9.h” // for Office Word 2003 and later, use #include “MSWord.h”

    include “MSPPT9.h” // for Office Powerpoint 2003 and later, use #include “msppt.h”

    include “MSAcc9.h” // for Office Access 2003 and later, use #include “msacc.h”

    include “VBE6Ext.h”`

  2. 单击 ClassView 选项 Right-click CListMacrosDlg 并选择 添加成员函数 。 提供 void函数类型GetMacros(LPDISPATCH lpDisp)函数声明 中,选择 专用 ,然后单击 确定 。 将以下代码添加 CListMacrosDlg::GetMacros

    `void CListMacrosDlg::GetMacros(LPDISPATCH lpDisp)
    {
    long i, j; //counters

    //Clear the list box and set the tab stops
    j=m_MacroList.GetCount();
    for (i=j-1;i>=0;i—){
    m_MacroList.DeleteString(i);}
    m_MacroList.SetTabStops(50);

    //Iterate the collection of components in the VBA project
    //referenced by lpDisp.
    VBAExt::_VBProject oVBProj;
    oVBProj.AttachDispatch(lpDisp, TRUE);
    VBAExt::_VBComponents oVBComps = oVBProj.GetVBComponents();
    long lCompCount = oVBComps.GetCount();
    long lLineCount;
    long lProcKind = 0;
    VBAExt::_VBComponent oVBComp;
    VBAExt::_CodeModule oCode;

    for(i=1; i<=lCompCount; i++)
    {
    oVBComp = oVBComps.Item(COleVariant(i));
    oCode = oVBComp.GetCodeModule();

    //If the component contains any lines of code, then
    //retrieve the name of each procedure (Functions and Subs)
    //add it to the list box along with the module name.
    CString sProcName, sItem;
    lLineCount = oCode.GetCountOfLines();
    j=1;
    while(j<lLineCount)
    {

    1. sProcName = oCode.GetProcOfLine(j, &lProcKind);
    2. if(!sProcName.IsEmpty()){
    3. sItem.Format("%s/t/t%s", oVBComp.GetName(), sProcName);
    4. m_MacroList.AddString(sItem);
    5. j = j + oCode.GetProcCountLines(sProcName, lProcKind); }
    6. else {
    7. j++; }

    }
    }
    }`

  3. 将下面的代码行添加到在 ListMacros.cpp CListMacrosApp::InitInstance() 的开头:

    AfxOleInit();

  4. 生成项目并运行它。 选择一个文件 (.xls、.doc、.mdb 或.ppt) 包含宏,然后单击 运行 。 宏的列表将显示在列表框。

其他注意事项

  • 此示例所示的代码检索仅的 SubFunction 过程。 如果想要检索 Property GetProperty Let ,或 Property Set 过程,您必须修改代码。 ProcOfLine 的第二个参数可以是下列之一 (该代码示例使用它等效于 vbext_pk_Proc 的 0):

    1. Constant Value Description
    2. ------------- ----- ------------------------------------------------
    3. vbext_pk_Get 3 Procedure that returns the value of a property
    4. vbext_pk_Let 1 Procedure that assigns a value to a property
    5. vbext_pk_Set 2 Procedure that sets a reference to an object
    6. vbext_pk_Proc 0 All procedures other than property procedures
  • 如果 VBA 模块受密码保护,将显示要求输入密码,对话框。 如果您不知道密码,程序不能列出这些过程。
  • 打开 (和 OpenCurrentDatabase ) 方法,上述示例中的用于 Office 2000 类型库。 Office XP 类型库有要传递给这些方法的其他参数。 请参见在”参考”部分的其他信息。

(c) Microsoft Corporation 2000 保留所有权利。 由 Lori B Turner,Microsoft Corporation 供稿。

自动化 Microsoft Office XP 的说明

某些方法和属性已更改为 Microsoft Office XP。 有关使用与 Microsof Word 类型库本文所述的示例代码的其他信息,单击下面的文章编号,以查看 Microsoft 知识库中的文章:

224925 (http://support.microsoft.com/kb/224925/ ) INFO: 用于 Office 类型库可能会更改与新版本

Office XP 应用程序具有允许以编程方式访问 VBA 对象模型一个安全选项。 如果此设置是”关”(默认),您可能会收到错误运行上述示例代码。 有关此设置以及可以在如何纠正该错误的其他信息,单击下面的文章编号,以查看 Microsoft 知识库中的文章:

282830 (http://support.microsoft.com/kb/282830/ ) PRB: 编程访问到 Office XP VBA 项目被拒绝

有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应:

266387 (http://support.microsoft.com/kb/266387/ ) 如何查找和列表访问 VBA 过程使用 MFC

194906 (http://support.microsoft.com/kb/194906/ ) 如何添加和运行 VBA 宏使用从 MFC 的自动化

这篇文章中的信息适用于:
  • Microsoft Office Word 2007
  • Microsoft Office Word 2003
  • Microsoft Word 2002 标准版
  • Microsoft Word 2000 标准版
  • Microsoft Office PowerPoint 2007
  • Microsoft Office PowerPoint 2003
  • Microsoft PowerPoint 2002 标准版
  • Microsoft PowerPoint 2000 标准版
  • Microsoft Office Excel 2007
  • Microsoft Excel 2002 标准版
  • Microsoft Excel 2000 标准版
  • Microsoft Office Access 2007
  • Microsoft Office Access 2003
  • Microsoft Access 2002 标准版
  • Microsoft Access 2000 标准版
  • Microsoft Visual C++ 6.0 专业版
  • Microsoft Foundation Class Library 4.2

发表评论

表情:
评论列表 (有 0 条评论,49人围观)

还没有评论,来说两句吧...

相关阅读

    相关 如何使用C++ 在Word文档创建列表

    列表分类是指在Word文档中使用不同格式排序的列表,来帮助我们一目了然地表达出一段文字的主要内容。比如,当我们描述了某个主题的若干点,就可以用列表把它们一一表达出来,而不是写成

    相关 MFC定时器使用

    近期在编一个扫雷游戏时,用到了定时器。其实在C++中定时器的应用非常广泛,例如录音的时候采样频率的控制,俄罗斯方块游戏发射子弹的频率以及前面介绍的扫雷游戏中都有用到定时器函数。

    相关 C语言如何使用

    C语言中如何使用宏 C(和C++)中的宏(Macro)属于编译器预处理的范畴,属于编译期概念(而非运行期概念)。下面对常遇到的宏的使用问题做了简单总结。 宏使用中的常见