MS Office 自动化编程(一)---从Word文档中获取文档属性

学习Office自动化之前先阅读一些COM书籍,对于理解Office自动化有很大帮助。以下示例代码使用VS2010进行编译。目前市面上已有的关于Office自动化的书籍,多是快餐式的,看过之后只能知道最基本的使用。要想更多的了解,非得MSDN不可。下面就是msdn上跟office开发相关的详细资料。

总目录:http://msdn.microsoft.com/en-us/library/bb726434(v=office.12)

 

针对Office2007:http://msdn.microsoft.com/en-us/library/bb726436(v=office.12)

 

Word组件对象详细资料:http://msdn.microsoft.com/msword.tlhen-us/library/bb244515(v=office.12).aspx

可以参看组件对象的详细信息,包括属性,方法等等介绍。

 

使用VC进行自动化编程的基本步骤:

1.初始化COM组件---应用程序调用com库中的函数(除CoGetMalloc和内存分配函数)之前必须初始化com库

2.建立Application对象并使之运行---建立自动化对象以便使用其提供的功能

3.使用Application对象提供的方法、事件实现自动化处理过程

4.关闭自动化对象

 

示例:从Word文档中获取文档属性(文档页数、文档作者等)

 

1.新建基于对话框的项目GetWordPro,并添加一些用于打开,显示Word文档属性的简单控件。

 

2.在项目中引入类型库

Class Wizard->Add Class->MFC class From Type Lib(关于类型库,COM相关书籍有详细介绍)->在Available Tpe libraries中选择 Microsoft Word 12.0Object Library<8.4>

我用的是Office 2007组件,版本不同名称会稍有不同。作为初学,对各个接口不是太了解的情况下,我们选择全部的接口到Generated Classes后finish。等熟悉之后就可以挑选自己需要的接口了。

 

3.在对话框类中声明我们需要的对象

//Represents the Microsoft Office Word application. 
	//For example, the ActiveDocument property returns a Document object.
	CApplication	m_oApp;

	//A collection of all the Document objects that are currently open in Word.
	CDocuments		m_oDocs; 

	CDocument0		m_oDoc;

 

4.OnInitDialog()中添加以下代码

// TODO: Add extra initialization here
	if (CoInitialize(NULL) != 0)
	{
		AfxMessageBox(_T("COM库初始化失败!"));
		exit(1);
	}

	if (!m_oApp.CreateDispatch(_T("Word.Application"), NULL))
	{
		AfxMessageBox(_T("启动Word程序失败!"));
		return FALSE;
	}
	
	//COM VARIANT类型的封装类
	COleVariant vopt(DISP_E_PARAMNOTFOUND, VT_ERROR);
	//This structure is used by IDispatch::Invoke to contain the arguments passed to a method or property.
	DISPPARAMS dpNoArgs = {NULL, NULL, 0, 0};
	HRESULT hr;
	VARIANT vResult;
	//添加一个新文档
	m_oDocs = m_oApp.get_Documents();
	m_oDoc = m_oDocs.Add(vopt, vopt, vopt, vopt);

	//用于保存Word内置属性接口
	//IDispatch is the COM interface for automation
	LPDISPATCH lpdispProps;
	lpdispProps = m_oDoc.get_BuiltInDocumentProperties();

	hr = lpdispProps->Invoke(0x4, IID_NULL, LOCALE_NAME_USER_DEFAULT,
		DISPATCH_PROPERTYGET, &dpNoArgs, &vResult, NULL, NULL);
	long lPropCount = vResult.lVal;
	CComboBox * pComboList = (CComboBox*)GetDlgItem(IDC_PROPERTY_COM);

	char szPropName[255];
	DISPPARAMS dpItem;
	VARIANT vArgs[1];
	vArgs[0].vt = VT_I4;
	vArgs[0].lVal = 0;
	dpItem.cArgs = 1;
	dpItem.cNamedArgs = 0;
	dpItem.rgvarg = vArgs;

	//向列别添加可选项
	for (long i = 1; i <= lPropCount; i++)
	{
		//获得一个文档属性
		dpItem.rgvarg[0].lVal = i;
		hr = lpdispProps->Invoke(0x0, IID_NULL, LOCALE_NAME_USER_DEFAULT, 
			DISPATCH_PROPERTYGET, &dpItem, &vResult, NULL, NULL);
		LPDISPATCH lpdispProp = vResult.pdispVal;
		hr = lpdispProp->Invoke(0x3, IID_NULL, LOCALE_NAME_USER_DEFAULT,
			DISPATCH_PROPERTYGET, &dpNoArgs, &vResult, NULL, NULL);
		pComboList->InsertString(-1, vResult.bstrVal);
		lpdispProp->Release();
	}

	lpdispProps->Release();
	
	//关闭文档
	m_oDoc.Close(COleVariant((short)false), vopt, vopt);
	m_oDoc.ReleaseDispatch();
	m_oDoc.m_lpDispatch = NULL;

	pComboList->EnableWindow(0);

这一段的注意点:get_BuiltInDocumentProperties();函数调用返回的是DocumentProperties Collection 对象http://msdn.microsoft.com/en-us/library/aa190807(v=office.10).aspx  。属性值有多个,可以在http://msdn.microsoft.com/en-us/library/microsoft.office.interop.word.wdbuiltinproperty(v=office.14).aspx或者msword.tlh(由导入类型库之后在Debug生成的头文件)中的enum WdBuiltInProperty查看。例子中直接使用了0x3这样的id值,如果只知道方法或者属性的名字的前提下,可以使用http://support.microsoft.com/kb/179494中的方法。

 

5.其他控件的响应函数

void CGetWordPropDlg::OnBnClickedChooseword()
{
	// TODO: Add your control notification handler code here
	OPENFILENAME ofn;
	TCHAR lpStrFileName[MAX_PATH] = _T("");
	ZeroMemory(&ofn, sizeof(ofn));

	ofn.lStructSize = sizeof(OPENFILENAME);
	ofn.hwndOwner = this->m_hWnd;
	ofn.lpstrFilter = _T("Word(.docx)\0*.docx\0");
	ofn.nMaxFile = MAX_PATH;
	ofn.lpstrFile = lpStrFileName;
	ofn.hInstance = AfxGetInstanceHandle();
	ofn.Flags = OPEN_EXISTING;

	if (GetOpenFileName(&ofn) == IDOK)
	{
		CString strFile = ofn.lpstrFile;
		SetDlgItemText(IDC_FILENAME, strFile);
		CComboBox* pComboList = (CComboBox*)GetDlgItem(IDC_PROPERTY_COM);
		pComboList->EnableWindow(TRUE);

		COleVariant vopt(DISP_E_PARAMNOTFOUND, VT_ERROR);
		if (m_oDoc.m_lpDispatch != NULL)
		{
			m_oDoc.Close(COleVariant((short)false), vopt, vopt);
			m_oDoc.ReleaseDispatch();
			m_oDoc.m_lpDispatch = NULL;
		}
		m_oDoc = m_oDocs.Open(COleVariant(strFile), vopt, COleVariant((short)true), vopt, vopt,
			vopt,vopt,vopt,vopt, vopt, vopt, vopt, vopt, vopt, vopt,vopt);
	}
}


void CGetWordPropDlg::OnSelchangePropertyCom()
{
	// TODO: Add your control notification handler code here
	CString sProperty;
	CComboBox* pComboPropList = (CComboBox*)GetDlgItem(IDC_PROPERTY_COM);
	pComboPropList->GetLBText(pComboPropList->GetCurSel(), sProperty);

	LPDISPATCH lpdispProps;
	lpdispProps = m_oDoc.get_BuiltInDocumentProperties();

	VARIANT vResult;
	DISPPARAMS dpItem;
	VARIANT vArgs[1];
	vArgs[0].vt = VT_BSTR;
	vArgs[0].bstrVal = sProperty.AllocSysString();
	dpItem.cArgs = 1;
	dpItem.cNamedArgs = 0;
	dpItem.rgvarg = vArgs;
	HRESULT hr = lpdispProps->Invoke(0x0, IID_NULL, LOCALE_NAME_USER_DEFAULT,
		DISPATCH_PROPERTYGET, &dpItem, &vResult, NULL, NULL);

	SysFreeString(vArgs[0].bstrVal);

	DISPPARAMS dpNoArgs = {NULL, NULL, 0, 0};
	LPDISPATCH lpdispProp;
	lpdispProp = vResult.pdispVal;

	hr = lpdispProp->Invoke(0x0, IID_NULL, LOCALE_NAME_USER_DEFAULT,
		DISPATCH_PROPERTYGET, &dpNoArgs, &vResult, NULL, NULL);

	CString sPropValue = _T("");
	switch (vResult.vt)
	{
	case VT_BSTR:
		sPropValue = vResult.bstrVal;
		break;
	case VT_I4:
		sPropValue.Format(_T("%d"), vResult.lVal);
		break;
	case VT_DATE:
		{
			COleDateTime dt(vResult);
			sPropValue = dt.Format(0, LANG_USER_DEFAULT);
			break;
		}
	default:
		sPropValue = _T("该属性不可用");
		break;
	}
	SetDlgItemText(IDC_PROPERTY_VALUE, sPropValue);
	lpdispProp->Release();
	lpdispProps->Release();
}


void CGetWordPropDlg::OnDestroy()
{
	CDialogEx::OnDestroy();

	// TODO: Add your message handler code here
	COleVariant vopt(DISP_E_PARAMNOTFOUND, VT_ERROR);
	m_oApp.Quit(COleVariant((short)false), vopt, vopt);
	CDialogEx::OnCancel();
}


在编译的过程中会出现编译的错误,全部指向msword.tlh文件,需要在CApplication.h、CDocuments.h等实用到的头文件中添加红色部分,是因为命名冲突导致的编译失败

#import "C:\\Program Files\\Microsoft Office\\Office12\\MSWORD.OLB" no_namespace raw_interfaces_only rename("FindText","_FindText")rename("Rectangle","_Rectangle") rename("ExitWindows","_ExitWindows")


 

6.运行结果

 


 

{ "manifest_version": 3, "name": "My V3 Extension", "version": "versionString", "action": {}, "default_locale": "en", "description": "A plain-text description", "icons": {}, "action": , "author": , "automation": , "background": { "service_worker": }, "chrome_settings_overrides": {}, "chrome_url_overrides": {}, "commands": {}, "content_capabilities": , "content_scripts": [{}], "content_security_policy": "policyString", "converted_from_user_script": , "current_locale": , "declarative_net_request": , "devtools_page": "devtools.html", "differential_fingerprint": , "event_rules": [{}], "externally_connectable": { "matches": ["*://*.contoso.com/*"] }, "file_browser_handlers": [], "file_system_provider_capabilities": { "configurable": true, "multiple_mounts": true, "source": "network" }, "homepage_url": "http://path/to/homepage", "host_permissions": [], "import": [{"id": "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"}], "incognito": "spanning, split, or not_allowed", "input_components": , "key": "publicKey", "minimum_chrome_version": "versionString", "nacl_modules": [], "natively_connectable": , "oauth2": , "offline_enabled": true, "omnibox": { "keyword": "aString" }, "optional_permissions": ["tabs"], "options_page": "options.html", "options_ui": { "chrome_style": true, "page": "options.html" }, "permissions": [""], "platforms": , "replacement_web_app": , "requirements": {}, "sandbox": [], "short_name": "Short Name", "side_panel": {}, "storage": { "managed_schema": "schema.json" }, "system_indicator": , "tts_engine": {}, "update_url": "http://path/to/updateInfo.xml", "version_name": "aString", "web_accessible_resources": [] } 请以表格的显示列出在扩展开发每个属性的作用
07-24
| 属性名称 | 作用 | |-------------------------------|-----------------------------------------------------------------------------------------------------------------------------------| | manifest_version | 指定扩展程序的清单版本号 | | name | 指定扩展程序的名称 | | version | 指定扩展程序的版本号 | | action | 指定扩展程序的行为 | | default_locale | 指定默认的本地化语言 | | description | 指定扩展程序的简要描述 | | icons | 指定扩展程序的图标 | | author | 指定扩展程序的作者 | | automation | 指定是否启用自动化测试 | | background | 指定扩展程序的后台页面,可以是一个服务工作者(service worker) | | chrome_settings_overrides | 指定覆盖 Chrome 设置的选项 | | chrome_url_overrides | 指定覆盖 Chrome URL 的选项 | | commands | 指定扩展程序的命令 | | content_capabilities | 指定内容脚本的能力 | | content_scripts | 指定内容脚本的文件和在哪些页面上运行 | | content_security_policy | 指定内容安全策略 | | converted_from_user_script | 指定是否将用户脚本转换为扩展程序 | | current_locale | 指定当前的本地化语言 | | declarative_net_request | 指定是否使用声明式网络请求 | | devtools_page | 指定扩展程序的开发工具页面 | | differential_fingerprint | 指定扩展程序的差异指纹 | | event_rules | 指定事件规则,用于监听和处理事件 | | externally_connectable | 指定扩展程序可以与哪些网站进行外部连接 | | file_browser_handlers | 指定处理文件浏览的处理程序 | | file_system_provider_capabilities | 指定文件系统提供者的能力 | | homepage_url | 指定扩展程序的主页URL | | host_permissions | 指定扩展程序需要访问的主机权限列表 | | import | 指定导入其他扩展程序的ID | | incognito | 指定是否允许在隐身模式下使用扩展程序 | | input_components | 指定输入组件的配置 | | key | 指定扩展程序的公钥 | | minimum_chrome_version | 指定最低支持的 Chrome 版本 | | nacl_modules | 指定使用哪些 Native Client (NaCl)模块 | | natively_connectable | 指定扩展程序可以原生连接到哪些应用程序 | | oauth2 | 指定 OAuth2 配置 | | offline_enabled | 指定扩展程序是否支持离线模式 | | omnibox | 指定扩展程序的 Omnibox 配置 | | optional_permissions | 指定扩展程序可选的权限列表 | | options_page | 指定扩展程序的选项页面 | | options_ui | 指定扩展程序的选项界面配置 | | permissions | 指定扩展程序需要的权限列表 | | platforms | 指定扩展程序支持的平台列表 | | replacement_web_app | 指定扩展程序替代的 Web 应用 | | requirements | 指定扩展程序的需求 | | sandbox | 指定扩展程序的沙盒策略 | | short_name | 指定扩展程序的简称 | | side_panel | 指定扩展程序的侧边栏配置 | | storage | 指定扩展程序的存储配置 | | system_indicator | 指定扩展程序的系统指示器配置 | | tts_engine | 指定 TTS(文本到语音)引擎配置 | | update_url | 指定更新信息的 URL | | version_name | 指定版本名称 | | web_accessible_resources | 指定哪些资源可以从网页访问 |
评论 16
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值