如何利用VBA编写控制Word域的功能.docx
- 文档编号:4537248
- 上传时间:2022-12-01
- 格式:DOCX
- 页数:31
- 大小:93.73KB
如何利用VBA编写控制Word域的功能.docx
《如何利用VBA编写控制Word域的功能.docx》由会员分享,可在线阅读,更多相关《如何利用VBA编写控制Word域的功能.docx(31页珍藏版)》请在冰豆网上搜索。
如何利用VBA编写控制Word域的功能
表1:
工程
工程名称
设计阶段
工程检索号
卷册号
项目名称
新制
字数
图片数
建模工具
学习
(2)
fw-jm-2002
软件工程专家网
60
1000
3
表2:
校核
序号
校核主要问题
执行情况
1
排列不齐
No
2
文字错
Yes
3
文字错
Yes
4
文字错
No
5
文字错
Yes
6
文字错
No
表2:
注册网址
Word域在软件开发中的应用
liyu
摘要域是Word最具有实用价值的功能之一,它表示文档中可能发生变化的数据或邮件合并文档中套用信函、标签中的占位符。
MicrosoftWord可以在您使用一些特定命令时插入域,如“插入”菜单上的“日期和时间”命令。
您也可使用“插入”菜单上的“域”命令手动插入域。
1.引言
事实上,我们在日常工作中常会脱离MicrosoftWord的操作环境。
一般,用户是先建立好一些Word文件模板,然后利用所提供的应用程序功能向Word文件模板中插入域,然后用该域对应的值取代域值,这样就达到了向MicrosoftWord文件中插入数据的作用。
我们常把数据放入数据库中,数据库的内容不断地变化,我们的域值也跟着不断地变化,取到灵活自动更新的作用,要达到这方面的功能,就应该把数据库与Word域结合起来。
首先要解决这一问题,我们必须先了解Word域有关的知识:
Word域代码位于花括号或大括号({})中,域类似于MicrosoftExcel中的公式:
域代码类似于公式,域结果(域结果:
当MicrosoftWord执行域指令时,在文档中插入的文字或图形。
在打印文档或隐藏域代码时,将以域结果替换域代码。
)类似于公式产生的值。
可在文档中切换显示域代码及其结果。
正好,数据库的字段名对应域代码,字段值对应域结果。
2.实现功能
下面是本人利用VBA编写的一通用的处理Word域的程序:
主要功能:
通用VB6编写通用的类,给用户提供可视化的编辑界面,用于用户在Word文件中插入域标志。
针对Word文件或Excel表格文件,扫描整个文件,将其中的域标志(如Set“aaa”)取出来,然后通过从数据库中取出”aaa”字段所对应的值,将值填写到文件中域对应的位置。
若对应位置已有值,则判断该值与要填写的值是否相同,若不同则替换。
插入值分为:
A.单纯的值,直接使用一个值替换域。
B.表格中的单元格。
若该表格填写不下,是否增加表格单元?
以及与该单元关联的域等。
3.操作步骤
3.1建立项目
开发方法:
启动VB6,新建一ActiveXDll工程,把工程名更改为VbaWord,把类名Class1更改为CSetDocField,向工程中增加一窗体Form1,窗体标题为处理Word文档,在Form1上加入2个CommandButton,用于打开文件和保存文件用的命令按钮;2个ComboBox,用于所插入的字段名;2个Label;2个CommonDialog,用于执行打开文件和保存文件。
界面如下:
3.2在项目中加入引用
按工程--引用--MicrosoftWord10.0ObjectLibrary引用Word(OFFICE2000为MicrosoftWord9.0ObjectLibrary)。
3.3增加操作窗体
在Form1的代码窗中定义以下变量:
OptionBase0
'申请Word应该对象及文档对象
PrivatewdAppAsNewWord.Application()
PrivatewdDocAsNewWord.Document()
'所处理的Word模板
PrivateFileNameAsString
'申请CSetDocField对象
PrivatemDocFldAsNewCSetDocField()
'Word工具栏对象及菜单栏对象
DimCommandBarIndex()AsInteger
DimSaveCommandBarMenuIndex()AsInteger
'在Form的Load的事件中定义的打开和保存文件的格式,并填充ComboBox数据。
ComboBox数据对应数据库表的字段名,这里由CSetDocField的属性提供。
PrivateSubForm_Load()
DimiAsInteger
CommonDialog1.DialogTitle="打开"
CommonDialog1.Filter="Word文档(*.doc)|*.doc|Word文档模板(*.dot)|*.dot"
CommonDialog2.DialogTitle="保存文件"
CommonDialog2.Filter=Word文档(*.doc)|*.doc|Word文档模板(*.dot)|*.dot"
FieldCount=0
Me.ScaleY(Me.height,fromscale:
=vbTwips,toscale:
=vbPoints)
Fori=1TogFieldColl.Count
Combo1.AddItem(gFieldColl.Item(i))
Next
Fori=1TogTableColl.Count
Combo2.AddItem(gTableColl.Item(i))
Next
EndSub
在Form1的代码窗中定义以下过程和函数:
'定义打开Word文件的过程。
建立Word应该对象及文档对象,并打开文件。
PrivateSubOpenWordDocument(ByValFileNameAsString)
wdApp=CreateObject("Word.Application")
wdApp.Documents.Open(FileName)
wdDoc=wdApp.ActiveDocument
wdDoc.ActiveWindow.DocumentMap=False
wdApp.Visible=True
IsWordRunning=True
EndSub
'在文档中插入域.KeyWord:
域的关键字.
这里我们利用Word文档对象的域对象的Add方法向Word文件中插入域。
域的Data属性代表该域的名称。
插入域时应该选取得插入点(Selection),既用户光标处位置。
如果该位置是单元格且已插入域应该提示是否覆盖
PrivateFunctionInsertField(ByValKeyWordAsString)AsInteger
DimmySelectionAsSelection
DimCodeAsString
DimMyFieldAsField
DimmyRangeAsRange
wdApp.Selection.Collapse(Direction:
=wdCollapseEnd)
mySelection=wdApp.Selection'插入点
IfIsCell(mySelection)=TrueThen
IfCellFieldCount(mySelection)>0Then
IfMsgBox("该单元格已有域,是否覆盖?
",vbYesNo)=6Then
mySelection.Cells
(1).Select()
mySelection.Delete()'.Text=Value
'mySelection.DeleteUnit:
=wdCharacter,Count:
=1
'mySelection.Cells
(1).Range.Fields
(1).Delete
Else
ExitFunction
EndIf
EndIf
EndIf
MyField=wdDoc.Fields.Add(Range:
=mySelection.Range,Type:
=wdFieldAddin)
MyField.Data=KeyWord
EndFunction
'选择点(光标)是否是单元格.
我们可以通过选择点的表格数判断插入点的性质。
表格数为0,则选择点不位于单元格中,反则不位于单元格中。
PrivateFunctionIsCell(ByValmySelectionAsSelection)AsBoolean
IfmySelection.Tables.Count>0Then
IsCell=True
Else
IsCell=False
EndIf
EndFunction
'取得选择点(光标)的单元格的域数
PrivateFunctionCellFieldCount(ByValmySelectionAsSelection)AsInteger
CellFieldCount=mySelection.Cells
(1).Range.Fields.Count
EndFunction
'打开Word文件.并使处理界面位于Word最顶端,适当调整Word位置,关闭Word其它功能。
PrivateSubcmdOpenFile_Click()
CommonDialog1.ShowOpen()
FileName=CommonDialog1.FileName
IfFileName=""Then
ExitSub
EndIf
OpenWordDocument(FileName)
IsShowField(True)
SetWordSize(0,42,2000,2000)
CloseCommandBar()
Me.top=0
Me.Left=0
Me.width=100000
Me.height=850
Picture1.top=Me.top
Picture1.Left=Me.Left+2000
cmdSave.Left=2000
cmdSave.top=cmdOpenFile.top
Combo1.Enabled=True
Combo2.Enabled=True
cmdSave.Visible=True
cmdOpenFile.Visible=False
EndSub
'保存Word文件.
PrivateSubcmdSave_Click()
IsShowField(False)
CommonDialog2.FileName=gSavePath+FileName
CommonDialog2.FileName=gSavePath+FileName
CommonDialog2.ShowSave()
wdDoc.SaveAs(CommonDialog2.FileName)
EndSub
'用户选择所插入域的域名,并在光标处插入域。
PrivateSubCombo1_Click()
DimKeyWordAsString
KeyWord=Combo1.Text
InsertField(KeyWord)
EndSub
'用户选择所插入域的域名,并在光标处插入域。
域所对应多值时,域只能插入表格中。
且要与单值域区分,标记为多值插入。
PrivateSubCombo2_Click()
DimKeyWordAsString
mySelection=wdApp.Selection'插入点
IfIsCell(mySelection)<>TrueThen
MsgBox("该位置不是单元格,请选择单元格",vbOKOnly+vbExclamation)
ExitSub
EndIf
KeyWord=Combo2.Text+"F"'标记是多值
InsertField(KeyWord)
EndSub
PrivateSubForm_Load()
DimiAsInteger
CommonDialog1.DialogTitle="打开"
CommonDialog1.Filter="Word文档(*.doc)|*.doc|Word文档模板(*.dot)|*.dot"
CommonDialog2.DialogTitle="保存文件"
CommonDialog2.Filter="Word文档(*.doc)|*.doc|Word文档模板(*.dot)|*.dot"
FieldCount=0
Me.ScaleY(Me.height,fromscale:
=vbTwips,toscale:
=vbPoints)
Fori=1TogFieldColl.Count
Combo1.AddItem(gFieldColl.Item(i))
Next
Fori=1TogTableColl.Count
Combo2.AddItem(gTableColl.Item(i))
Next
EndSub
'**********************************************************
PrivateFunctionInsertFieldByKeyWord(ByValKeyWordAsString)AsInteger
DimIDAsInteger
FieldCount=FieldCount+1
ReDimMyField(FieldCount)
ID=InsertField(KeyWord)
MyField(FieldCount).ID=ID
MyField(FieldCount).KeyWord=KeyWord
EndFunction
PrivateSubSetEnabled(ByValisEnabledAsBoolean)
DimobjAsControl
ForEachobjInMe.Controls
IfTypeName(obj)="TextBox"Then
obj.Enabled=isEnabled
EndIf
IfTypeName(obj)="ComboBox"Then
obj.Enabled=isEnabled
EndIf
IfTypeName(obj)="CheckBox"Then
obj.Enabled=isEnabled
EndIf
IfTypeName(obj)="CommandButton"Then
obj.Enabled=isEnabled
EndIf
Next
EndSub
'在关闭该界面时应该恢复Word环境。
PrivateSubForm_Unload(ByValCancelAsInteger)
IfFileName<>""Then
OpenCommandBar()
wdApp.ActiveWindow.Close()
wdApp.Quit()
EndIf
EndSub
'定义Word环境的大小。
PrivateSubSetWordSize(ByValLeftAsInteger,ByValtopAsInteger,ByValwidthAsInteger,ByValheightAsInteger)
wdApp.WindowState=wdWindowStateNormal
wdApp.Left=Left
wdApp.top=top
wdApp.width=width
wdApp.height=height
EndSub
'定义Word域代码是否可显示。
PrivateSubIsShowField(ByValIsShowAsBoolean)
wdApp.ActiveWindow.View.ShowFieldCodes=IsShow
EndSub
'关闭Word环境的所有命令及菜单。
PrivateSubCloseCommandBar()
DimiAsInteger
DimcBar
ReDimCommandBarIndex
(1)
ReDimSaveCommandBarMenuIndex
(1)
i=0
ForEachcBarInwdDoc.CommandBars
IfcBar.Type=0AndcBar.Enabled=TrueThen
IfcBar.Visible=TrueThen
ReDimCommandBarIndex(i+1)
CommandBarIndex(i)=cBar.Index
i=i+1
cBar.Visible=False
EndIf
EndIf
Next
i=0
ForEachcBarInwdDoc.CommandBars("MenuBar").Controls
IfcBar.Visible=TrueThen
ReDimSaveCommandBarMenuIndex(i+1)
SaveCommandBarMenuIndex(i)=cBar.Index
i=i+1
cBar.Visible=False
EndIf
Next
EndSub
'恢复Word环境的所有命令及菜单。
PrivateSubOpenCommandBar()
DimiAsInteger
Fori=0ToUBound(CommandBarIndex)-1
wdDoc.CommandBars(i+1).Visible=True
Next
Fori=0ToUBound(SaveCommandBarMenuIndex)-1
CommandBars("MenuBar").Controls(i+1).Visible=True
Next
EndSub
3.2增加窗体
下面我们继续编写CSetDocField类的内容。
CSetDocField类应该提供单值域和多值的域名,所以我们把它们定义为CSetDocField类的属性,并提供一运行上面窗口的方法。
这里我们要利用一些技巧,在定义类并向类属性赋性值后,事实赋性值是保存在所定义的实类中,该实类一旦消失,值也随着消失。
如何不通过该实类取得类的属性?
这是困扰许多开发人员的问题。
我的解决方法是申请与类属性对应的全局变量。
向类属性的同时,把值保存在对应的全局变量中,取值时取出对应的全局变量的值就可。
这里我们选增加一Module,其Code如下:
PublicgSavePathAsString
PublicgFieldCollAsCollection
PublicgTableCollAsCollection
SubMain()
Form1.Show
(1)
EndSub
下面我利用全局变量当作类属性使用的技巧:
CSetDocField类的Code:
PublicSubRun()
StaticFieldCollAsCollection
StaticTableCollAsCollection
Main()
EndSub
PropertyGetFieldColl()AsCollection
'SetFieldColl=mFieldColl
SetFieldColl=gFieldColl
EndProperty
PropertyLetFieldColl(FieldAsCollection)
SetgFieldColl=Field
EndProperty
PropertyGetTableColl()AsCollection
SetTableColl=gTableColl
EndProperty
PropertyLetTableColl(FieldAsCollection)
SetgTableColl=Field
EndProperty
PropertyLetSavePath(strAsString)
gSavePath=str
EndProperty
这里,我们把插入域的类编写好了,只要在VB6的文件菜单中执行生成该类的文件就可生成DLL文件。
下面编写将值填写到文件中域对应的位置的类。
在VbaWord工程中增加新类CWriteDataToDocument。
类CWriteDataToDocument由调用者提供所处理的文件模板,所以它应该有一文档属性DocumentName,打开DocumentName文件,向DocumentName文件中插入单值和多值。
插入多值时要判断是否增加单元格。
如果对应的值多于所提供的表格行数,则要增加行。
下面是它的完整Code:
PrivatewdAppAsNewWord.Application()
PrivatewdDocAsNewWord.Document()
PrivateIsInsertRowAsBoolean'是否已经插入了行
PublicDocumentNameAsString
PublicFunctionFillData()
OpenWordDocument()
InsertValue()
InsertCollection()
wdDoc.SaveAs(DocumentName)
EndFunction
PublicFunctionGetValueByField(ByValFieldNameAsString)AsString
GetValueByField="liyu"
EndFunction
PublicFunctionGetRecordSetByField(ByValFieldNameAsString)AsCollection
DimcollAsNewCollection()
coll.Add("li")
coll.Add("yu")
GetRecordSetByField=coll
EndFunction
PrivateSubOpenWordDocument()
wdApp=CreateObject("Word.Application")
wdApp.Documents.Open(DocumentName)
wdDoc=wdApp.ActiveDocument
wdApp.Visible=True
'wdDoc.ActiveWindow.Doc
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 如何 利用 VBA 编写 控制 Word 功能