Word域与数据库的结合编程.docx
《Word域与数据库的结合编程.docx》由会员分享,可在线阅读,更多相关《Word域与数据库的结合编程.docx(14页珍藏版)》请在冰点文库上搜索。
Word域与数据库的结合编程
本文介绍了Word域与数据库结合的方法,给用户提供一个插入Word域的界面,并把数据库的数据填充到Word文件中。
域是Word中最具有实用价值的功能之一,它表示文档中可能发生变化的数据或邮件合并文档中套用信函、标签中的占位符。
MicrosoftWord可以在您使用一些特定命令时插入域,如"插入"菜单上的"日期和时间"命令。
您也可使用"插入"菜单上的"域"命令手动插入域。
事实上,我们在日常工作中常会脱离MicrosoftWord的操作环境。
一般,用户是先建立好一些Word文件模板,然后利用所提供的应用程序功能向Word文件模板中插入域,用该域对应的值取代域值,这样就达到了向MicrosoftWord文件中插入数据的作用。
我们常把数据放入数据库中,数据库的内容不断地变化,我们的域值也跟着不断地变化,取到灵活自动更新的作用,要达到这方面的功能,就应该把数据库与Word域结合起来。
解决方法
首先要解决这一问题,我们必须先了解Word域有关的知识:
Word域代码位于花括号或大括号({})中,域类似于MicrosoftExcel中的公式:
域代码类似于公式,域结果(域结果:
当MicrosoftWord执行域指令时,在文档中插入的文字或图形。
在打印文档或隐藏域代码时,将以域结果替换域代码。
)类似于公式产生的值。
可在文档中切换显示域代码及其结果。
正好,数据库的字段名对应域代码,字段值对应域值。
我们利用VBA编程可以达到目的。
VBAforWord中有关域的类型很多,其中Type:
=wdFieldAddin是一种关于字段与字段值对应的特殊域,正是借助它的功能解决问题。
我们可以这么设想,用户先打开Word文件,然后向打开的Word文件中插入域,然后用数据库的数据填充。
插入域时有二种可能,一种是单值域,即一个域代码对应一个域值(一对一关系),这种情况的域可以插入任何地方;另一种情况是多值域,即一个域代码对应多个域值(一对多关系)。
这种情况的域只能插入表格中,并且当表格的行数比域值少时,要能自动提供增加表格行的功能。
实例说明
利用VisualBasic。
Net编写通用的类,给用户提供可视化的编辑界面,用于用户在Word文件中插入域标志。
针对Word文件或Excel表格文件,扫描整个文件,将其中的域标志取出来,然后通过从数据库中取出字段所对应的值,将值填写到文件中域对应的位置。
若对应位置已有值,则判断该值与要填写的值是否相同,若不同则替换之。
插入值分为:
A。
单纯的值,直接使用一个值替换域。
B。
表格中的单元格。
若该表格填写不下,是否增加表格单元?
以及与该单元关联的域等。
例如,有二个Access数据库的表(:
表1对应单值域,表2对应多值域)如下:
表1:
工程
工程名称
设计阶段
工程检索号
项目名称
新制
字数
图片数
建模工具
学习
(2)
fw-jm-2002
软件工程专家网
60
1000
3
表2:
校核
序号
校核主要问题
执行情况
1
排列不齐
No
2
文字错
Yes
3
文字错
Yes
4
内容提要不详细
No
5
文字错
Yes
6
数据有误
No
利用VBA编写的一个通用的处理Word域的程序。
开发步骤如下:
1.建立项目,向项目中增加处理Word域的类
启动VisualStudio。
NET。
在新建项目中选择VisualBasic项目,在模板中选择Windows应用程序,把工程名更改为WordDoc。
●向工程中增加名称为CWordDoc的类。
●定义的CWordDoc类的属性。
代码如下:
'定义Word应用对象及文档对象
PrivatewdAppAsNewWord..Application()
PrivatewdDocAsNewWord.Document()
'所处理的Word模板文件
PrivateFileNameAsString
'域的个数及对应的数组
DimFieldCountAsInt16
DimMyField()
'Word是否已运行
PrivateIsWordRunningAsBoolean
'是否已经插入了表格行
PrivateIsInsertRowAsBoolean
'Word工具栏对象及菜单栏对象数组
DimCommandBarIndex()AsInteger
DimSaveCommandBarMenuIndex()AsInteger
●定义的CWordDoc类的方法。
定义打开Word文件的方法。
建立Word应用对象和文档对象,并打开Word文件。
设定Word已经运行。
VBA编程主要是先建立某一个应用程序的对象,然后按需要处理应用对象。
Word应用对象是“Word.Application”,通过CreateObject方法建立之。
代码如下:
PublicSubOpenWordDocument(ByValFileNameAsString)
wdApp=CreateObject("Word。
Application")
wdApp.Documents。
Open(FileName)
wdDoc=wdApp.ActiveDocument
wdDoc.ActiveWindow.DocumentMap=False
wdApp.Visible=True
IsWordRunning=True
EndSub
保存Word文件。
代码如下:
PublicSubSaveWordDocument()
wdDoc.SaveAs(FileName)
EndSub
定义Word环境的大小。
Word启动后一般是全屏幕(最大化),要把用户操作界面显示出来,不被Word遮蔽,处理的方法是把用户界面设为顶层窗体,也可使用户界面与Word各自处在自己位置,平行布置。
这里是让用户界面位于屏幕的最顶上,Word位于用户界面的下面。
因此要重新调整Word的位置,这需要设置Word窗体状态为普通类型(wdWindowStateNormal)。
代码如下:
PublicSubSetWordSize(ByValLeftAsInteger,ByValtopAsInteger,
ByValwidthAsInteger,ByValheightAsInteger)
wdApp。
WindowState=Word.WdWindowState.wdWindowStateNormal
wdApp。
Left=Left
wdApp。
Top=top
wdApp。
Width=width
wdApp。
Height=height
EndSub
这里我们利用Word文档对象中域对象的Add方法向Word文件中插入域。
域的Data属性代表该域的名称。
插入域时应该选取插入点(Selection),即用户光标处位置。
如果该位置是单元格且已插入域,应该提示是否覆盖。
插入域时要分析是插入单值域还是多值域。
根据关键字的后缀识别,关键字的最后一个字符是'F'时则为多值域。
多值域只能插入在表格中。
是否是表格以插入点的单元格识别。
实现该功能的代码如下:
'在文档中插入域
'KeyWord:
域的关键字
PublicFunctionInsertField(ByValKeyWordAsString)AsInteger
DimmySelectionAsSelection
DimCodeAsString
DimMyFieldAsField
DimmyRangeAsRange
wdApp。
Selection。
Collapse(Direction:
=wdCollapseEnd)
mySelection=wdApp。
Selection '插入点
IfKeyWord。
Chars(KeyWord。
Length-1)="F"Then
IfIsCell(mySelection)<>TrueThen
MsgBox("该位置不是单元格,请选择单元格",vbOKOnly+vbExclamation)
ExitFunction
EndIf
EndIf
IfIsCell(mySelection)=TrueThen
IfCellFieldCount(mySelection)>0Then
IfMsgBox("该单元格已有域,是否覆盖?
",vbYesNo)=6Then
mySelection.Cells.Item
(1).Select()
mySelection.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
ReturnTrue
Else
ReturnFalse
EndIf
EndFunction
'计算选择点(光标)的单元格的域数
PrivateFunctionCellFieldCount(ByValmySelectionAsSelection)AsInteger
CellFieldCount=mySelection.Cells.Item
(1).Range.Fields.Count
EndFunction
'记录插入域代码及关键字。
这里主要是调用上面的InsertField方法。
PublicFunctionInsertFieldByKeyWord(ByValKeyWordAsString)AsInteger
DimIDAsInteger
FieldCount=FieldCount+1
ReDimMyField(FieldCount)
ID=InsertField(KeyWord)
MyField(FieldCount).ID=ID
MyField(FieldCount).KeyWord=KeyWord
EndFunction
当Word文件已经插入了域,就要填充域值。
填充域值应该分为二种情况考虑。
一种是单值域,一种是多值域。
单值域是一一对应关系,仅取出值域插入到对应的位置。
实现的方法是扫描整个文档,找出是用户插入的域(Fields.Type=81),用域值取代之,这里用到了一个由关键字得到值的方法GetFieldValues,这个方法在后面将会讲到,对应的是数据库的"工程"表。
怎样保证永远仅插入一个值呢?
方法是先清除掉原域值和域代码,再在当前插入点插入域代码和域值。
实现的方法如下:
'用关键字对应的值插入值,在文档中在有域的地方插入对应的值
PublicFunctionInsertValue()AsBoolean
Dimi,CountAsInteger
DimKeyWordAsString
DimValue,Data
DimmySelectionAsSelection
Count=wdDoc.Fields.Count
Fori=1ToCount
IfwdDoc.Fields.Item(i).Type=81Then
KeyWord=wdDoc.Fields.Item(i).Data
IfRight(KeyWord,1)<>"F"Then
Value=clsDB.GetFieldValues("工程",KeyWord)
wdDoc.Fields.Item(i).Select()
mySelection=wdApp.Selection '插入点
IfmySelection.Tables.Count<>0Then
'clear text
mySelection.Cells.Item
(1).Select()
mySelection.Delete()
'还原原域
InsertField(KeyWord)
EndIf
wdDoc.Fields.Item(i).Result.Text=Value(0).itemarray(0)
EndIf
EndIf
Next
EndFunction
插入多值域时要考虑表格行数够不够,不够时要增加表格行数,且每插入一个值,光标要下移一行。
这里对应的是数据库的"校核"表。
实现的方法如下:
'插入多值域
PublicFunctionInsertCollection()AsBoolean
Dimi,j,CountAsInteger
DimKeyWordAsString
DimmySelectionAsSelection
Dimrec()AsObject
DimrecCountAsInteger
Count=wdDoc.Fields.Count
Fori=1ToCount
IfwdDoc.Fields.Item(i).Type=81Then
KeyWord=Trim(wdDoc.Fields.Item(i).Data)
IfRight(KeyWord,1)="F"Then
KeyWord=Left(KeyWord,Len(KeyWord)-1)
rec=clsDB.GetFieldValues("校核",KeyWord)
'选择有域的单元格
wdDoc.Fields.Item(i).Select()
mySelection=wdApp.Selection '插入点
mySelection.Cells.Item
(1).Select()
'清除原值
mySelection.Delete()
'还原原域并更新值
InsertField(KeyWord+"F")
wdDoc.Fields.Item(i).Result.Text=rec(0).itemarray(0)
'光标下移
mySelection.Select()
mySelection.MoveDown(Unit:
=wdLine,Count:
=1)
Withrec
recCount=.GetLength(0)-1
Forj=1TorecCount-1
IfIsInsertRow=FalseThen
CallInsertRow(mySelection,recCount)
EndIf
mySelection.Cells.Item
(1).Select()
mySelection.Delete()
mySelection.TypeText(Text:
=rec(j).itemarray(0))
mySelection.MoveDown(Unit:
=wdLine,Count:
=1)
Next
EndWith
EndIf
EndIf
Next
EndFunction
PrivateFunctionInsertRow(ByValmySelectionAsSelection,
ByValrecCountAsInteger)AsBoolean
DimInsertRowCountAsInteger '插入的行数
DimCurrCellAsCell
CurrCell=mySelection.Cells.Item
(1)
InsertRowCount=recCount-mySelection.Tables.Item
(1).Rows.Count+1
IfInsertRowCount>0Then
mySelection.InsertRows(InsertRowCount)
CurrCell.Select()
mySelection.MoveUp(Unit:
=wdLine,Count:
=InsertRowCount)
IsInsertRow=True
EndIf
EndFunction
如果表格行数少于表数据的行数则应该增加表格行数。
增加多少表格行数由表数据的行数减去现有表格行数加入计算出来。
当插入了行,光标一定下移了几行,这里要还原光标至原来位置,方法是先保留插入点,插入行后,重新选择插入点,使光标上移几行。
表格已经插入行以后就不要再插入了,所以至IsInsertRow为真。
'向表格中增加行数。
PrivateFunctionIsInsert(ByValmySelectionAsSelection,
ByValrecCountAsInteger)AsBoolean
DimInsertRowCountAsInteger '插入的行数
DimCurrCellAsCell
CurrCell=mySelection.Cells.Item
(1)
InsertRowCount=recCount-mySelection.Tables.Item
(1).Rows.Count+1
IfInsertRowCount>0Then
mySelection.InsertRows(InsertRowCount)
CurrCell.Select()
mySelection.MoveUp(Unit:
=wdLine,Count:
=InsertRowCount)
IsInsertRow=True
EndIf
EndFunction
Word的菜单和工具箱很多,用户操作时先关掉这些不必要的东西,最后恢复Word环境的原状。
'恢复Word环境的所有命令及菜单。
PublicSubOpenCommandBar()
DimiAsIn