使用 LotusScript 和自动化集成 IBM Lotus Notes 和 Microsoft Office

本文介绍的技术让 Microsoft® Office 应用程序(比如 Microsoft Excel)可以以不同的格式向 IBM® Lotus Notes® 数据库发布信息。

Mike Maroney, 资深软件工程师, IBM

Mike Maroney 是 IBM Lotus Technical Support 组织的一位资深软件工程师。他从 Lotus Notes 3 开始就成为一位经过认证的开发人员,并且采用本文介绍的技术开发了产品应用程序。这些应用程序被一家 “财富 500 强” 跨国公司采用。



2009 年 5 月 05 日

简介

发布需求

多数 Lotus Notes 开发人员都清楚 Lotus Notes 发布的局限性。可能经常需要创建包含 Lotus Notes 应用程序数据的邮件、特定格式的报表,或者支持数据透视表等特性。Lotus Notes 本身无法实现这些东西。

一种常常被忽视的办法是使用 Microsoft Office 发布存储在 Lotus Notes 数据库中的信息。虽然本文介绍的技术同样适用于其他应用程序(比如 Lotus SmartSuite®),但本文关注的焦点是 Microsoft Word 发布。

要求和限制

为了使用本文中的代码,必须安装相关的应用程序(以 Microsoft Word 为例)。这些例子被编写为运行在本地系统上的由用户触发的代理。

本文所述的创建其他应用程序引用的两种方法不支持 OS/2、UNIX®、Linux® 和 Macintosh。

最后,不建议在服务器端环境中使用 OLE 自动化,而且 Microsoft 也不支持。不过可以考虑使用开放源代码的 XML 文件格式。请参阅 Microsoft Support Article 257757 了解更多信息。

前提条件

本文假设您熟悉 LotusScript® 和对象模型的概念。

如果需要查看 Microsoft Office 应用程序的对象模型,可以:

  1. 打开应用程序并按下 ALT + F11,打开 Visual Basic Editor。
  2. 选择 View - Object Browser。这样就可以看到完整的对象列表及相关的属性和方法。本文包含一些可以下载的示例代码和一个示例数据库。

开始

创建 Microsoft Office 应用程序引用

在 Lotus Notes 和其他应用程序之间共享数据的第一步是获得目标应用程序的引用。LotusScript 提供了两个函数来实现这个步骤:

CreateObject( className )
GetObject( pathName, [ className ] )

请参阅 Lotus Domino® Designer Help 数据库了解这两个函数的详细说明,包括例子。

http://www.ibm.com/developerworks/lotus/documentation/

CreateObject 建立对 className 参数所指定的 OLE 自动化对象的引用。下面列出了一些 Microsoft Office 类名:

  • Word.Application
  • Excel.Application
  • Access.Application
  • PowerPoint.Application
  • MSProject.Application

这些应用程序都有一些共同的特点,即可用于以不同方式发布信息。比方说,Microsoft Excel 可用于发布销售数据和创建图表。Microsoft Project 可用于显示任务。

如前所述,本文主要讨论使用 Microsoft Word 发布数据。现在启动 Microsoft Word 应用程序并创建编程句柄。可以使用下列代码:

Dim wordApp as Variant
Set wordApp = CreateObject(“Word.Application”)
wordApp.Visible = True

GetObject 提供了对运行中的应用程序的引用。参数 pathName 可以是空字符串,或者引用一个文件。如果引用一个文件,就不需要指定 className,因为它由文件的类型决定。

这两个函数都可获得对指定应用程序的引用。现在就可以通过 LotusScript 控制该应用程序,执行创建和打开文档、传递文本、设置文本格式等操作了。

上面代码中的最后一行使应用程序是可见的。这一步通常在代码完成需要的处理之后再执行,但是出于调试目的,在开发过程中这样做很方便。如果应用程序的可见的,在代码执行中就可以单步调试每一行代码。

创建新的 Microsoft Word 文档

继续上面的代码片段,使用 LotusScript 向 Microsoft Word 传递文本。首先需要获得对 Word 新文档的引用。代码如下:

Dim wordDoc as Variant
Set wordDoc = wordApp.Documents.Add()

第二行中,我们从应用程序对象沿着 Microsoft Word 对象模型进入到应用程序的文档集合。然后使用 add 方法创建一个新文档并返回其引用。

目标应用程序是了解可用对象及其相关方法和属性的好地方。例如,启动 Microsoft Word 然后选择 Tools - Macro - Visual Basic Editor(或者按下 Alt + F11)。打开编辑器之后,从菜单中选择 View - Object browser(或者按 F2)。选择最顶层的应用程序对象,右侧就是相关的成员,如图 1 所示。

图 1. 对象浏览器
对象浏览器

使用 select 方法

文档对象包含很多需要注意的方法。把文本输入文档之前,首先需要知道光标在什么位置。虽然通过程序对文档执行操作,但对 Microsoft Word 而言就像有人手动与它交互一样。

比方说,在 Microsoft Word 中创建一个新文档时,光标显示在页的上方。编程创建文档的时候情况是一样的。因此我们先看看 Select 方法:

Dim cursor as Variant
Set cursor = wordApp.Selection

这两行代码提供了对 Selection 对象的引用。然后就可以使用 Selection 对象向文档输入文本了。

输入文本

Selection 对象有一个 TypeText 方法,用于在当前光标位置输入一个文字串。

cursor.TypeText(“Hello, world!”)

上述代码向活动文档的当前光标位置输入了经典的文本 “Hello, world!”。

格式化

如果需要设置 Microsoft Word 的文本格式,可以选中文本然后修改格式。例如,我们希望用粗体显示刚刚输入的 “Hello, world!”。

wordDoc.Paragraphs(1).Range.Select
cursor.Font.Bold = True

首先选中文档的第一个段落。第二行对选择的内容应用粗体格式。

使用书签

Microsoft Word 提供了书签功能,让用户为文档中的特定位置创建标签。这样通过菜单 Edit - Go to 就能很快返回到那个位置。对于开发人员来说,同样可以利用该功能改进文档的导航和引用。

清单 1 所示的代码中包含三个部分,每个部分都有一个书签,然后通过书签确定希望在何处插入文本。

清单 1. 创建和使用书签
For counter = 1 To 3
	selection.typetext "This is Section Header " & Cstr(counter)
	selection.typeparagraph
	selection.typeparagraph
	selection.moveup
	selection.moveup
	selection.expand wdParagraph
	Set bookmarks(counter) = worddoc.bookmarks.add("SectionHeader" & 
	Cstr(counter), selection.range)
	selection.moveend wdStory
	selection.collapse wdCollapseEnd
Next

selection.goto wdGoToBookmark, , , "SectionHeader1"
selection.movedown
selection.typetext "This text is associated with the first section...."
selection.goto wdGoToBookmark, , , "SectionHeader2"
selection.movedown
selection.typetext "This text is associated with the second section...."
selection.goto wdGoToBookmark, , , "SectionHeader3"
selection.movedown
selection.typetext "This text is associated with the third section...."

总而言之,首先从对象模型的最高层开始,然后根据需要逐渐向下引用。使用 Variant 变量保存经常使用的不同对象的引用。仔细阅读清单 2 所示的完整代码。可以将这段代码粘贴到一个代理中,然后使用 LotusScript 调试器单步调试它,看看实际效果。

清单 2. HelloWorld 示例代码
‘Dimension the variables
Dim wordApp as Variant
Dim wordDoc as Variant
Dim cursor as Variant

‘Get references to OLE objects
On Error Resume Next
Set wordApp = GetObject(“Word.Application”)
If wordApp Is Nothing Then
	Set wordApp = CreateObject(“Word.Application”)
End If
wordApp.Visible = True
Set wordDoc = wordApp.Documents.Add()
Set cursor = wordApp.Selection

‘Pass text to the new document and format it
cursor.TypeText(“Hello, world!”)
wordDoc.Paragraphs(1).Range.Select
cursor.Font.Bold = True

复杂的例子

下面三小节讨论使用 Microsoft Word 的高级特性,包括表格、对话框和邮件的合并。表格用于组织信息,在邮件合并中也很有用。对话框用于接收用户的输入。比如询问用户是否需要保存文件。

创建和使用表格

Microsoft Word 中的表格使您能够有序地组织数据。邮件合并时定义的数据源文档通常就是包含表格的文档。表格的每一行代表一条记录,表格的每一列代表一个字段。

清单 3 中创建的表格包含 1 个行和 7 个列。每列都包含一个字段名。

清单 3. 插入表格
	Set tbl = worddoc.tables.add(selection.range, 1, 7)
	'Set up the header row of the table
	With tbl
		.cell(1, 1).select
		selection.typetext "Title"
		.cell(1, 2).select
		selection.typetext "FirstName"
		.cell(1, 3).select
		selection.typetext "LastName"
		.cell(1, 4).select
		selection.typetext "OfficeStreetAddress"
		.cell(1, 5).select
		selection.typetext "OfficeCity"
		.cell(1, 6).select
		selection.typetext "OfficeState"
		.cell(1, 7).select
		selection.typetext "OfficeZip"
		.rows.last.select
	End With

为了美观,也可以设置表格的格式。Microsoft Word 使用点作为计量单位。编写一个函数把英寸转化成点数很简单,只要英寸数乘上 72 即可(每英寸 72 点)。清单 4 中的代码就使用这个函数调整列宽。这个例子还使用了一个常量 wdAdjustNone,它的值是 0。尽管这是 Microsoft Word 的一个内部常量,但您还需要声明自己的常量。

清单 4. 调整列宽
	'Format column widths
	With tbl
		.columns(1).setwidth InchesToPoints(.6), wdAdjustNone
		.columns(2).setwidth InchesToPoints(1), wdAdjustNone
		.columns(3).setwidth InchesToPoints(1), wdAdjustNone
		.columns(4).setwidth InchesToPoints(1.6), wdAdjustNone
		.columns(5).setwidth InchesToPoints(1), wdAdjustNone
		.columns(6).setwidth InchesToPoints(1), wdAdjustNone
		.columns(7).setwidth InchesToPoints(1), wdAdjustNone
	End With

使用通用对话框

Microsoft Word 很容易访问通用对话框,比如 Save As。您可以通过调用 Word.Application.Dialogs.Show 方法并确定所需的对话框来使用它们。例如,下面的代码片段显示 Save As 对话框,让用户决定用什么文件名将文档保存在什么地方。

rc = wordobj.dialogs(wdDialogFileSaveAs).Show

上例中的 rc 被设置为 dialogs().Show 调用的返回值。表 1 列出了可能的返回值。

表 1. File Save As 对话框可能的返回值
返回值说明
-2Close 按钮
-1OK 按钮
0 (zero)Cancel 按钮
> 0 (zero)命令按钮:1 表示第一个,2 表示第二个,依次类推

创建邮件合并

Microsoft Word 提供了完善的邮件合并功能。邮件合并是指创建一个套用信函并关联一个数据源文档。源文档包含多条记录(通常在一个表格中)和插入到套用信函中的字段。定义好源文档之后,就可以把数据合并到新的文档或者直接发送到打印机。

清单 5 中的例子选择 Lotus Notes Personal 地址簿中的 Person 文档,并将其导入套用信函所使用的 Microsoft Word 数据源文档。注意:为了节省空间,省略了一些变量的声明。可从本文的下载小节下载相关的示例文件,其中包含完整的源代码。

清单 5. 创建邮件合并
Option Public
Option Explicit
%INCLUDE "LSCONST.LSS"

Dim w As notesuiworkspace
Dim uiview As notesuiview
Dim col As notesdocumentcollection, doc As notesdocument
Dim tbl As Variant
Dim maindoc As Variant
Dim path As String
Dim rc As Integer

Dim wordobj As Variant
Dim worddoc As Variant
Dim selection As Variant, range As Variant


Sub Initialize
	Set w = New notesuiworkspace
	Set uiview = w.currentview
	Set col = uiview.documents
	If col.count = 0 Then 
		Msgbox "No documents selected!", MB_OK + MB_ICONINFORMATION, "Error"
		End
	End If
	
	Set wordobj = createobject("Word.Application")
	wordobj.visible = True
	Set worddoc = wordobj.documents.add()
	Call worddoc.content.select()
	Set selection = wordobj.selection()
	Call selection.collapse()
	path = wordobj.Options.DefaultFilePath(wdDocumentsPath)
	
	Call CheckForExistingFiles
	
	Call FormatMailMergeSource
	
	Set doc = col.getfirstdocument
	Do Until doc Is Nothing
		Call PopulateData
		Set doc = col.getnextdocument(doc)
	Loop
	
	Msgbox "Your data source has been created.  You now need to identify 
	where you wish to save this file.", _
	MB_OK + MB_ICONINFORMATION, "Save the Data Source"
	rc = wordobj.dialogs(wdDialogFileSaveAs).Show
	If (rc = 0) Or (rc = -2) Then
		Msgbox "You have cancelled your mail merge.", 
		MB_OK + MB_ICONINFORMATION, "Operation Cancelled"
		End
	End If
	
	Call CreateMailMergeMain
	
End Sub

Sub FormatMailMergeSource()
	'Page layout
	With worddoc.pagesetup
		.topmargin = inchestopoints(.4)
		.bottommargin = inchestopoints(.4)
		.leftmargin = inchestopoints(.4)
		.rightmargin = inchestopoints(.4)
	End With
	Set tbl = worddoc.tables.add(selection.range, 1, 7)
	'Set up the header row of the table
	With tbl
		.cell(1, 1).select
		selection.typetext "Title"
		.cell(1, 2).select
		selection.typetext "FirstName"
		.cell(1, 3).select
		selection.typetext "LastName"
		.cell(1, 4).select
		selection.typetext "OfficeStreetAddress"
		.cell(1, 5).select
		selection.typetext "OfficeCity"
		.cell(1, 6).select
		selection.typetext "OfficeState"
		.cell(1, 7).select
		selection.typetext "OfficeZip"
		.rows.last.select
	End With
	'Format column widths
	With tbl
		.columns(1).setwidth InchesToPoints(.6), wdAdjustNone
		.columns(2).setwidth InchesToPoints(1), wdAdjustNone
		.columns(3).setwidth InchesToPoints(1), wdAdjustNone
		.columns(4).setwidth InchesToPoints(1.6), wdAdjustNone
		.columns(5).setwidth InchesToPoints(1), wdAdjustNone
		.columns(6).setwidth InchesToPoints(1), wdAdjustNone
		.columns(7).setwidth InchesToPoints(1), wdAdjustNone
	End With
	selection.collapse wdCollapseStart
End Sub

Sub PopulateData()
	tbl.rows.last.select
	selection.insertrowsbelow 1
	With tbl.rows.last
		.cells(1).range.insertafter doc.Title(0)
		.cells(2).range.insertafter doc.FirstName(0)
		.cells(3).range.insertafter doc.LastName(0)
		.cells(4).range.insertafter doc.OfficeStreetAddress(0)
		.cells(5).range.insertafter doc.OfficeCity(0)
		.cells(6).range.insertafter doc.OfficeState(0)
		.cells(7).range.insertafter doc.OfficeZip(0)
	End With
End Sub

Sub CreateMailMergeMain()
	Set maindoc = wordobj.documents.add()
	Call LinkMainAndSource
	Msgbox "Your main document has been created.  You now need to 
	identify where you wish to save this file.", _
	MB_OK + MB_ICONINFORMATION, "Save the Main Document"
	rc = wordobj.dialogs(wdDialogFileSaveAs).Show
	If (rc = 0) Or (rc = -2) Then
		Msgbox "You have cancelled your mail merge.", 
		MB_OK + MB_ICONINFORMATION, "Operation Cancelled"
		End
	End If
End Sub

Sub CheckForExistingFiles()
	If isFile(path & "\Source.doc") Then Kill path & "\Source.doc"
	If isFile(path & "\Main.doc") Then Kill path & "\Main.doc"
End Sub

Function isFile(Byval sFileName As String) As Integer
	Dim lFileLength As Long
	On Error Resume Next
	
	isFile = False
	If Dir$(sFileName, ATTR_NORMAL) <> "" Then
		lFileLength = Filelen(sFileName)
		If (lFileLength > 0) Then isFile = True
	End If
End Function

Sub LinkMainAndSource
	maindoc.MailMerge.OpenDataSource worddoc.path & "\" & 
	worddoc.name, False, False, True
End Sub

Function InchesToPoints(inches As Double) As Long
	InchesToPoints = inches*72
End Function

以上代码基于前面的例子创建了邮件合并。您可以用类似的代码向客户发送新产品、帐户余额等信息,或者邀请他们参与某项活动。


结束语

这些技术也适用于其他 Microsoft Office 应用程序,比如 Microsoft Excel。只要安装了相关的软件,就能够使用类似的技术以不同的格式发布 Lotus Notes 数据库中的信息。请记住,每个应用程序的 Object Explorer 都提供了很有价值的文档和关于对象模型的例子。


致谢

本文作者衷心感谢 Lotus Technical Support 组织的 Josh Sherman 审阅了本文!


附录:关于示例应用程序的说明

下载部分中的示例 Lotus Notes 应用程序包括以下代理:

  • 简单的例子。这个代理就是经典的 “Hello, World!”,它将该文本发送给新建的 Microsoft Word 文档。
  • 时间选择技巧,A 部分。这个代理和下一个代理一起说明了有可能出现的时间选择陷阱。A 部分输入并格式化一些文本,然后插入一个硬回车。它说明了格式如何延续到下一个段落。
  • 时间选择技巧,B 部分。这个代理和上一个代理一起说明可能出现的时间选择陷阱。B 部分输入一些文本、插入硬回车并输入更多的文本,然后格式化原来的文本。
  • 书签的例子。这个代理创建了三个部分,并为它们添加书签,然后利用书签插入文本。
  • 邮件合并。这个代理允许用户在数据库 People 视图中选择一个或多个 Lotus Notes 文档,创建 Microsoft Word 数据源文档,建立链接到数据源文档的主文档,然后用 Microsoft Word 生成邮件合并。它建立了数据源和主文档,用户需要按照 Micorosoft Word 的常规邮件合并过程输入套用信函和插入字段。

下载

描述名字大小
MSOffice.nsf1MB

参考资料

条评论

developerWorks: 登录

标有星(*)号的字段是必填字段。


需要一个 IBM ID?
忘记 IBM ID?


忘记密码?
更改您的密码

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件

 


在您首次登录 developerWorks 时,会为您创建一份个人概要。您的个人概要中的信息(您的姓名、国家/地区,以及公司名称)是公开显示的,而且会随着您发布的任何内容一起显示,除非您选择隐藏您的公司名称。您可以随时更新您的 IBM 帐户。

所有提交的信息确保安全。

选择您的昵称



当您初次登录到 developerWorks 时,将会为您创建一份概要信息,您需要指定一个昵称。您的昵称将和您在 developerWorks 发布的内容显示在一起。

昵称长度在 3 至 31 个字符之间。 您的昵称在 developerWorks 社区中必须是唯一的,并且出于隐私保护的原因,不能是您的电子邮件地址。

标有星(*)号的字段是必填字段。

(昵称长度在 3 至 31 个字符之间)

单击提交则表示您同意developerWorks 的条款和条件。 查看条款和条件.

 


所有提交的信息确保安全。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=10
Zone=Lotus
ArticleID=387518
ArticleTitle=使用 LotusScript 和自动化集成 IBM Lotus Notes 和 Microsoft Office
publish-date=05052009