如何使用 MFC 检索 Office 文档中的宏名称的列表
本文介绍如何创建 MFC 自动化客户端检索 for Applications (VBA) 的 Visual Basic 列表的示例从 Microsoft Office 文档的宏 ( Sub 和 Function 过程)。
要获取 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 文档中检索的 Sub 和 Function 过程列表。 示例代码阐释如何使用 Office 应用程序类型库和 Visual Basic for Applications 扩展性库的类包装 ; 该示例还提供了特殊的案例考虑,对于 Microsoft Access 数据库。
namespace Excel{
using namespace Excel;
Control Type Properties ------------ ------------------------- Button ID: ID_Run Caption: Run Edit Box ID: IDC_FILENAME List Box ID: IDC_MACROLIST Use Tabstops: Checked
void CListMacrosDlg::OnRun()
{
USES_CONVERSION;
UpdateData(TRUE);
COleVariant vOpt(DISP_E_PARAMNOTFOUND, VT_ERROR); //for Optional args
//Determine the PROGID for the filename supplied
CLSID clsid;
HRESULT hr = GetClassFile(T2OLE(m_sFilename), &clsid);
if (FAILED(hr))
{
CString sMsg;
sMsg.Format("Unable to determine progid for file: %s", m_sFilename);
AfxMessageBox(sMsg);
return;
}
LPOLESTR lpOleStr;
ProgIDFromCLSID(clsid, &lpOleStr);
CString sProgID = CString(lpOleStr);
sProgID.MakeUpper();
//If the version independent progid is EXCEL.SHEET, WORD.DOCUMENT, or
//POWERPOINT.SHOW, then open the file in its associated application.
//Once the file is open, call GetMacros to place the list of macro
//names in the list box.
if(sProgID.Find("EXCEL.SHEET",0)>=0) //Microsoft Excel Workbook
{
Excel::_Application oApp;
oApp.CreateDispatch("Excel.Application");
Excel::Workbooks oBooks = oApp.GetWorkbooks();
Excel::_Workbook oBook = oBooks.Open(m_sFilename, vOpt, vOpt, vOpt,
vOpt, vOpt, vOpt, vOpt, vOpt,
vOpt, vOpt, vOpt, vOpt);
LPDISPATCH lpDisp = oBook.GetVBProject();
GetMacros(lpDisp);
oBook.Close(COleVariant((short)FALSE), vOpt, vOpt);
oApp.Quit();
}
else if(sProgID.Find("WORD.DOCUMENT",0)>=0) //Microsoft Word Document
{
MSWord::_Application oApp;
oApp.CreateDispatch("Word.Application");
MSWord::Documents oDocs = oApp.GetDocuments();
MSWord::_Document oDoc = oDocs.Open(COleVariant(m_sFilename), vOpt,
vOpt, vOpt, vOpt, vOpt, vOpt,
vOpt, vOpt, vOpt, vOpt, vOpt);
// For Office Word 2003 and Office Word 2007, 16 parameters are required.
/* MSWord::_Document oDoc = oDocs.Open(COleVariant(m_sFilename), vOpt,
vOpt, vOpt, vOpt, vOpt, vOpt,
vOpt, vOpt, vOpt, vOpt, vOpt,
vOpt,vOpt,vOpt,vOpt);
*/
LPDISPATCH lpDisp = oDoc.GetVBProject();
GetMacros(lpDisp);
oDoc.Close(COleVariant((short)FALSE), vOpt, vOpt);
oApp.Quit(vOpt, vOpt, vOpt);
}
else if(sProgID.Find("POWERPOINT.SHOW",0)>=0) //Microsoft PowerPoint
//Presentation
{
PPT::_Application oApp;
oApp.CreateDispatch("Powerpoint.Application");
PPT::Presentations oAllPres = oApp.GetPresentations();
PPT::_Presentation oPres = oAllPres.Open(m_sFilename, 0, 0, 0);
LPDISPATCH lpDisp = oPres.GetVBProject();
GetMacros(lpDisp);
oPres.Close();
oApp.Quit();
}
else if(sProgID.Find("ACCESS.APPLICATION", 0)>=0) //Microsoft Access DB
{ //** Special Consideration for Access Code Project
MSAccess::_Application oApp;
oApp.CreateDispatch("Access.Application");
MSAccess::DoCmd oDoCmd = oApp.GetDoCmd();
oApp.OpenCurrentDatabase(m_sFilename, FALSE);
// For Office Access 2003 and Office Access 2007, 3 parameters are required.
/*oApp.OpenCurrentDatabase(m_sFilename, FALSE,NULL);*/
MSAccess::_CurrentProject oProj = oApp.GetCurrentProject();
MSAccess::AllObjects oObjs = oProj.GetAllModules();
CString sModName, sProcName, sItem;
long lProcKind = 0;
for(long i=0;i<=oObjs.GetCount()-1;i++)
{
MSAccess::AccessObject oObj = oObjs.GetItem(COleVariant(i));
sModName = oObj.GetName();
//Module must be open:
oDoCmd.OpenModule(COleVariant(sModName), vOpt);
MSAccess::Modules oMods = oApp.GetModules();
MSAccess::Module oMod = oMods.GetItem(COleVariant(sModName));
long lLineCount = oMod.GetCountOfLines();
long j=1;
while(j<lLineCount)
{
sProcName = oMod.GetProcOfLine(j, &lProcKind);
if(!sProcName.IsEmpty()){
sItem.Format("%s/t/t%s", sModName, sProcName);
m_MacroList.AddString(sItem);
j = j + oMod.GetProcCountLines(sProcName, lProcKind); }
else {
j++; }
}
}
oApp.Quit(0);
}
else //Other...
{
CString sMsg;
sMsg.Format("Unable to extract macro names for files with progid %s",
sProgID);
AfxMessageBox(sMsg);
}
}
#include <afxpriv.h>
#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"
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)
{
sProcName = oCode.GetProcOfLine(j, &lProcKind);
if(!sProcName.IsEmpty()){
sItem.Format("%s/t/t%s", oVBComp.GetName(), sProcName);
m_MacroList.AddString(sItem);
j = j + oCode.GetProcCountLines(sProcName, lProcKind); }
else {
j++; }
}
}
}
AfxOleInit();
其他注意事项
Constant Value Description ------------- ----- ------------------------------------------------ vbext_pk_Get 3 Procedure that returns the value of a property vbext_pk_Let 1 Procedure that assigns a value to a property vbext_pk_Set 2 Procedure that sets a reference to an object vbext_pk_Proc 0 All procedures other than property procedures
(c) Microsoft Corporation 2000 保留所有权利。 由 Lori B Turner,Microsoft Corporation 供稿。
某些方法和属性已更改为 Microsoft Office XP。 有关使用与 Microsof Word 类型库本文所述的示例代码的其他信息,单击下面的文章编号,以查看 Microsoft 知识库中的文章:
Office XP 应用程序具有允许以编程方式访问 VBA 对象模型一个安全选项。 如果此设置是"关"(默认),您可能会收到错误运行上述示例代码。 有关此设置以及可以在如何纠正该错误的其他信息,单击下面的文章编号,以查看 Microsoft 知识库中的文章:
有关其他信息,请单击下面的文章编号,以查看 Microsoft 知识库中相应: