本文介绍了Word域与数据库结合的方法,给用户提供一个插入Word域的界面,并把数据库的数据填充到Word文件中。

域是Word中最具有实用价值的功能之一,它表示文档中可能发生变化的数据或邮件合并文档中套用信函、标签中的占位符。Microsoft Word 可以在您使用一些特定命令时插入域,如"插入"菜单上的"日期和时间"命令。您也可使用"插入"菜单上的"域"命令手动插入域。事实上,我们在日常工作中常会脱离Microsoft Word的操作环境。一般,用户是先建立好一些Word文件模板,然后利用所提供的应用程序功能向Word文件模板中插入域,用该域对应的值取代域值,这样就达到了向Microsoft Word文件中插入数据的作用。我们常把数据放入数据库中,数据库的内容不断地变化,我们的域值也跟着不断地变化,取到灵活自动更新的作用,要达到这方面的功能,就应该把数据库与Word域结合起来。

解决方法

首先要解决这一问题,我们必须先了解Word域有关的知识:Word域代码位于花括号或大括号 ( { } )中,域类似于 Microsoft Excel 中的公式:域代码类似于公式,域结果(域结果:当 Microsoft Word 执行域指令时,在文档中插入的文字或图形。在打印文档或隐藏域代码时,将以域结果替换域代码。)类似于公式产生的值。可在文档中切换显示域代码及其结果。正好,数据库的字段名对应域代码,字段值对应域值。我们利用VBA编程可以达到目的。VBA for Word 中有关域的类型很多,其中Type:=wdFieldAddin是一种关于字段与字段值对应的特殊域,正是借助它的功能解决问题。我们可以这么设想,用户先打开Word文件,然后向打开的Word文件中插入域,然后用数据库的数据填充。插入域时有二种可能,一种是单值域,即一个域代码对应一个域值(一对一关系),这种情况的域可以插入任何地方;另一种情况是多值域,即一个域代码对应多个域值(一对多关系)。这种情况的域只能插入表格中,并且当表格的行数比域值少时,要能自动提供增加表格行的功能。

实例说明

利用Visual Basic。Net编写通用的类,给用户提供可视化的编辑界面,用于用户在Word文件中插入域标志。针对Word文件或Excel表格文件,扫描整个文件,将其中的域标志取出来,然后通过从数据库中取出字段所对应的值,将值填写到文件中域对应的位置。若对应位置已有值,则判断该值与要填写的值是否相同,若不同则替换之。插入值分为:

A、单纯的值,直接使用一个值替换域。

B、表格中的单元格。若该表格填写不下,是否增加表格单元?以及与该单元关联的域等。

例如,有二个Access数据库的表(:表1对应单值域,表2对应多值域)如下:

表1:工程

表2:校核

利用VBA编写的一个通用的处理Word域的程序。开发步骤如下:

1、建立项目,向项目中增加处理Word域的类

启动Visual Studio。NET。在新建项目中选择Visual Basic项目,在模板中选择Windows应用程序,把工程名更改为WordDoc。

● 向工程中增加名称为CWordDoc的类。

● 定义的CWordDoc类的属性。代码如下:

以下为引用的内容:

'定义Word应用对象及文档对象

Private wdApp As New Word..Application()

Private wdDoc As New Word.Document()

'所处理的Word模板文件

Private FileName As String

'域的个数及对应的数组

Dim FieldCount As Int16

Dim MyField()

'Word是否已运行

Private IsWordRunning As Boolean

'是否已经插入了表格行

Private IsInsertRow As Boolean

'Word工具栏对象及菜单栏对象数组

Dim CommandBarIndex() As Integer

Dim SaveCommandBarMenuIndex() As Integer

● 定义的CWordDoc类的方法。

定义打开Word文件的方法。建立Word应用对象和文档对象,并打开Word文件。设定Word已经运行。VBA编程主要是先建立某一个应用程序的对象,然后按需要处理应用对象。Word应用对象是“Word.Application”,通过CreateObject方法建立之。代码如下:

以下为引用的内容:

Public Sub OpenWordDocument(ByVal FileName As String)

wdApp = CreateObject("Word。Application")

wdApp.Documents。Open(FileName)

wdDoc = wdApp.ActiveDocument

wdDoc.ActiveWindow.DocumentMap = False

wdApp.Visible = True

IsWordRunning = True

End Sub

保存Word文件。代码如下:

以下为引用的内容:

Public Sub SaveWordDocument()

wdDoc.SaveAs(FileName)

End Sub

定义Word环境的大小。

Word启动后一般是全屏幕(最大化),要把用户操作界面显示出来,不被Word遮蔽,处理的方法是把用户界面设为顶层窗体,也可使用户界面与Word各自处在自己位置,平行布置。这里是让用户界面位于屏幕的最顶上,Word位于用户界面的下面。因此要重新调整Word的位置,这需要设置Word窗体状态为普通类型(wdWindowStateNormal)。代码如下:

以下为引用的内容:

Public Sub SetWordSize(ByVal Left As Integer, ByVal top As Integer,

ByVal width As Integer, ByVal height As Integer)

wdApp。WindowState = Word.WdWindowState.wdWindowStateNormal

wdApp。Left = Left

wdApp。Top = top

wdApp。Width = width

wdApp。Height = height

End Sub

这里我们利用Word文档对象中域对象的Add方法向Word文件中插入域。域的Data属性代表该域的名称。插入域时应该选取插入点(Selection),即用户光标处位置。如果该位置是单元格且已插入域,应该提示是否覆盖。插入域时要分析是插入单值域还是多值域。根据关键字的后缀识别,关键字的最后一个字符是'F'时则为多值域。多值域只能插入在表格中。是否是表格以插入点的单元格识别。实现该功能的代码如下:

以下为引用的内容:

'在文档中插入域

'KeyWord:域的关键字

Public Function InsertField(ByVal KeyWord As String) As Integer

Dim mySelection As Selection

Dim Code As String

Dim MyField As Field

Dim myRange As Range

wdApp。Selection。Collapse(Direction:=wdCollapseEnd)

mySelection = wdApp。Selection      '插入点

If KeyWord。Chars(KeyWord。Length - 1) = "F" Then

If IsCell(mySelection) <> True Then

MsgBox("该位置不是单元格,请选择单元格", vbOKOnly + vbExclamation)

Exit Function

End If

End If

If IsCell(mySelection) = True Then

If CellFieldCount(mySelection) > 0 Then

If MsgBox("该单元格已有域,是否覆盖?", vbYesNo) = 6 Then

mySelection.Cells.Item(1).Select()

mySelection.Delete()

Else

Exit Function

End If

End If

End If

MyField = wdDoc.Fields.Add(Range:=mySelection.Range, Type:=wdFieldAddin)

MyField.Data = KeyWord

End Function

我们可以通过选择点的表格数判断插入点的性质。表格数为0,则选择点不位于单元格中,反则不位于单元格中。

以下为引用的内容:

'选择点(光标)是否是单元格。

Private Function IsCell(ByVal mySelection As Selection) As Boolean

If mySelection.Tables.Count > 0 Then

Return True

Else

Return False

End If

End Function

'计算选择点(光标)的单元格的域数

Private Function CellFieldCount(ByVal mySelection As Selection) As Integer

CellFieldCount = mySelection.Cells.Item(1).Range.Fields.Count

End Function

'记录插入域代码及关键字。这里主要是调用上面的InsertField方法。

Public Function InsertFieldByKeyWord(ByVal KeyWord As String) As Integer

Dim ID As Integer

FieldCount = FieldCount + 1

ReDim MyField(FieldCount)

ID = InsertField(KeyWord)

MyField(FieldCount).ID = ID

MyField(FieldCount).KeyWord = KeyWord

End Function

当Word文件已经插入了域,就要填充域值。填充域值应该分为二种情况考虑。一种是单值域,一种是多值域。单值域是一一对应关系,仅取出值域插入到对应的位置。实现的方法是扫描整个文档,找出是用户插入的域(Fields.Type = 81),用域值取代之,这里用到了一个由关键字得到值的方法GetFieldValues,这个方法在后面将会讲到,对应的是数据库的"工程"表。怎样保证永远仅插入一个值呢?方法是先清除掉原域值和域代码,再在当前插入点插入域代码和域值。实现的方法如下:

以下为引用的内容:

'用关键字对应的值插入值,在文档中在有域的地方插入对应的值

Public Function InsertValue() As Boolean

Dim i, Count As Integer

Dim KeyWord As String

Dim Value, Data

Dim mySelection As Selection

Count = wdDoc.Fields.Count

For i = 1 To Count

If wdDoc.Fields.Item(i).Type = 81 Then

KeyWord = wdDoc.Fields.Item(i).Data

If Right(KeyWord, 1) <> "F" Then

Value = clsDB.GetFieldValues("工程", KeyWord)

wdDoc.Fields.Item(i).Select()

mySelection = wdApp.Selection      '插入点

If mySelection.Tables.Count <> 0 Then

'clear  text

mySelection.Cells.Item(1).Select()

mySelection.Delete()

'还原原域

InsertField(KeyWord)

End If

wdDoc.Fields.Item(i).Result.Text = Value(0).itemarray(0)

End If

End If

Next

End Function

插入多值域时要考虑表格行数够不够,不够时要增加表格行数,且每插入一个值,光标要下移一行。这里对应的是数据库的"校核"表。实现的方法如下:

以下为引用的内容:

'插入多值域

Public Function InsertCollection() As Boolean

Dim i, j, Count As Integer

Dim KeyWord As String

Dim mySelection As Selection

Dim rec() As Object

Dim recCount As Integer

Count = wdDoc.Fields.Count

For i = 1 To Count

If wdDoc.Fields.Item(i).Type = 81 Then

KeyWord = Trim(wdDoc.Fields.Item(i).Data)

If Right(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)

With rec

recCount =.GetLength(0) - 1

For j = 1 To recCount - 1

If IsInsertRow = False Then

Call InsertRow(mySelection, recCount)

End If

mySelection.Cells.Item(1).Select()

mySelection.Delete()

mySelection.TypeText(Text:=rec(j).itemarray(0))

mySelection.MoveDown(Unit:=wdLine, Count:=1)

Next

End With

End If

End If

Next

End Function

Private Function InsertRow(ByVal mySelection As Selection,

ByVal recCount As Integer) As Boolean

Dim InsertRowCount As Integer           '插入的行数

Dim CurrCell As Cell

CurrCell = mySelection.Cells.Item(1)

InsertRowCount = recCount - mySelection.Tables.Item(1).Rows.Count + 1

If InsertRowCount > 0 Then

mySelection.InsertRows(InsertRowCount)

CurrCell.Select()

mySelection.MoveUp(Unit:=wdLine, Count:=InsertRowCount)

IsInsertRow = True

End If

End Function

如果表格行数少于表数据的行数则应该增加表格行数。增加多少表格行数由表数据的行数减去现有表格行数加入计算出来。当插入了行,光标一定下移了几行,这里要还原光标至原来位置,方法是先保留插入点,插入行后,重新选择插入点,使光标上移几行。表格已经插入行以后就不要再插入了,所以至IsInsertRow为真。

以下为引用的内容:

'向表格中增加行数。

Private Function IsInsert(ByVal mySelection As Selection,

ByVal recCount As Integer) As Boolean

Dim InsertRowCount As Integer           '插入的行数

Dim CurrCell As Cell

CurrCell = mySelection.Cells.Item(1)

InsertRowCount = recCount - mySelection.Tables.Item(1).Rows.Count + 1

If InsertRowCount > 0 Then

mySelection.InsertRows(InsertRowCount)

CurrCell.Select()

mySelection.MoveUp(Unit:=wdLine, Count:=InsertRowCount)

IsInsertRow = True

End If

End Function

Word的菜单和工具箱很多,用户操作时先关掉这些不必要的东西,最后恢复Word环境的原状。

以下为引用的内容:

'恢复Word环境的所有命令及菜单。

Public Sub OpenCommandBar()

Dim i As Integer

For i = 0 To UBound(CommandBarIndex) - 1

wdDoc.CommandBars(i + 1).Visible = True

Next

For i = 0 To UBound(SaveCommandBarMenuIndex) - 1

wdDoc.CommandBars.Item("Menu Bar").Controls(i + 1)。Visible = True

Next

End Sub

'关闭Word环境的所有命令及菜单。

Public Sub CloseCommandBar()

Dim i As Integer

Dim cBar

ReDim CommandBarIndex(1)

ReDim SaveCommandBarMenuIndex(1)

i = 0

For Each cBar In wdDoc.CommandBars

If cBar.Type = 0 And cBar.Enabled = True Then

If cBar.Visible = True Then

ReDim CommandBarIndex(i + 1)

CommandBarIndex(i) = cBar.Index

i = i + 1

cBar.Visible = False

End If

End If

Next

i = 0

For Each cBar In wdDoc.CommandBars("Menu Bar").Controls

If cBar.Visible = True Then

ReDim SaveCommandBarMenuIndex(i + 1)

SaveCommandBarMenuIndex(i) = cBar.Index

i = i + 1

cBar.Visible = False

End If

Next

End Sub

2、增加一个处理数据库的类COleDataAccess。

COleDataAccess类很简单,包含连接数据库的方法ConnAccess,打开静态表的方法GetDataTable,由字段名得到字段值的方法GetFieldValues。

以下为引用的内容:

Public Class COleDataAccess

Private mOleCnnDB As New OleDbConnection()

'连接Access数据库:DBName数据库名。

Public Sub ConnAccess(ByVal DBName As String)

mOleCnnDB.ConnectionString =

"Provider=Microsoft.Jet.OLEDB.4.0;Password="""

";User ID=Admin;" & _

"Data Source='" & DBName & "'"

mOleCnnDB.Open()

End Sub

'获取数据表.strSql查询条件。

Public Overloads Function GetDataTable(ByVal strSql As String) As DataTable

Dim myDataSet As New DataSet()

Dim myOleDataAdapter As New OleDbDataAdapter()

myOleDataAdapter.SelectCommand = New OleDbCommand(strSql, mOleCnnDB)

Try

myOleDataAdapter.Fill(myDataSet)

Catch er As Exception

MsgBox(er.ToString)

End Try

Return myDataSet.Tables(0)

End Function

'由字段名得到字段值的方法:. TableName表名 ; FieldName 字段名

Public Overloads Function GetFieldValues(ByVal TableName As String,

ByVal FieldName As String) As Object()

Dim dr As DataTable

Dim sql As String

sql = "select " + FieldName + " from " + TableName

dr = GetDataTable(sql)

Dim al(dr.Rows.Count) As Object

dr.Rows.CopyTo(al, 0)

Return al

End Function

End Class

3、增加模块Module1

模块Module1定义COleDataAccess类的变量clsDB,并连接数据库,显示用户窗体。

以下为引用的内容:

Module Module1

Public clsDB As New COleDataAccess()

Sub main()

clsDB.ConnAccess("工程数据。mdb")

Dim frm As New frmUserWord()

frm.ShowDialog()

End Sub

End Module

4、增加用户操作窗体

向工程中增加一窗体frmUserWord,窗体标题为"处理Word文档",在frmUserWord上加入3个CommandButton,用于打开文件(cmdOpenFile)、填充数据(cmdFill)、保存文件(cmdSave)用的命令按钮;2个ComboBox,用于所插入的字段名;2个 Label;2个CommonDialog,用于执行打开文件和保存文件;打开文件的对话框OpenFileDialog1、保存文件的对话框SaveFileDialog1。界面如下:

窗体frmUserWord类事实很简单,frmUserWord 类的代码如下:以下为引用的内容:

Public Class frmUserWord

Inherits System.Windows.Forms.Form

Dim clsDoc As New CWordDoc()

'打开Word文件。并使处理界面位于Word最顶端,适当调整Word位置,关闭Word其它功能。

Private Sub cmdOpenFile_Click(ByVal sender As System。Object,

ByVal e As System。EventArgs) Handles cmdOpenFile。Click

Dim FileName As String

OpenFileDialog1.ShowDialog()

FileName = OpenFileDialog1.FileName

If FileName = "" Then

Exit Sub

End If

clsDoc.OpenWordDocument(FileName)

clsDoc.SetWordSize(0, 50, 2000, 2000)

clsDoc.CloseCommandBar()

Me.Top = 0

Me.Left = 0

Me.Width = 10000

Me.Height = 80

ComboBox1.Enabled = True

ComboBox2.Enabled = True

cmdSave.Enabled = True

cmdFill.Enabled = True

End Sub

在Form的Load事件中定义打开和保存文件的格式,并填充ComboBox数据。ComboBox数据对应数据库表的字段名。以下为引用的内容:

Private Sub Form1_Load(ByVal sender As System.Object, ByVal e As

System.EventArgs) Handles MyBase.Load

Dim i As Integer

OpenFileDialog1.Title = "打开文件"

OpenFileDialog1.Filter = "Word文档(*.doc)|*.doc|Word文档模板(*.dot)|*.dot"

SaveFileDialog1.Title = "保存文件"

SaveFileDialog1.Filter = "Word文档(*.doc)|*.doc|Word文档模板(*.dot)|*.dot"

Dim dt As New DataTable()

dt = clsDB.GetDataTable("select * from 工程")

For i = 0 To dt.Columns.Count - 1

ComboBox1.Items.Add(dt.Columns.Item(i).ColumnName)

Next

dt = clsDB.GetDataTable("select * from 校核")

For i = 0 To dt.Columns.Count - 1

ComboBox2.Items.Add(dt.Columns.Item(i).ColumnName)

Next

End Sub

'填充数据

Private Sub cmdFill_Click(ByVal sender As System.Object, ByVal e As

System。EventArgs) Handles cmdFill.Click

clsDoc.InsertValue()

clsDoc.InsertCollection()

End Sub

'用户选择所插入域的域名,并在光标处插入单值域。

Private Sub ComboBox1_SelectedIndexChanged(ByVal sender As Object,

ByVal e As System.EventArgs) Handles ComboBox1.SelectedIndexChanged

clsDoc.InsertField(sender.Text)

End Sub

'用户选择所插入域的域名,并在光标处插入多值域。

域所对应多值时,域只能插入表格中。且要与单值域区分,标记为多值插入。

Private Sub ComboBox2_SelectedValueChanged(ByVal sender As Object,

ByVal e As System.EventArgs) Handles ComboBox2.SelectedValueChanged

Dim KeyWord As String

KeyWord = sender.Text + "F" '标记是多值

clsDoc.InsertField(KeyWord)

End Sub

'保存Word文件。

Private Sub cmdSave_Click(ByVal sender As System.Object,

ByVal e As System.EventArgs) Handles cmdSave.Click

clsDoc.SaveWordDocument()

End Sub

'打开Word的命令菜单及工具箱。

Private Sub frmUserWord_Closed(ByVal sender As Object,

ByVal e As System.EventArgs) Handles MyBase.Closed

clsDoc.OpenCommandBar()

End Sub

End Class

5、应用与测试

一般,此种应用是作为一个软件的一部分,我们可以把它生成组件来用,方法把项目的输出类型改为类库后,把它生成DLL文件就可。这里为了方便测试就直接把它生成应用程序。

下面对它运行时的结果如下:

打开一Word文件运行后的界面如下:

结论

上面方法介绍了Word域的利用,利用VBA编写Word域的方法。Word域所对应的数据库的字段的单值和多值的关系,极有普遍性,很有实用价值。

mysql字段和域_Word域与数据库的结合编程相关推荐

  1. php数据库字段类型,mysql 字段类型说明

    mysql 字段类型说明 更新时间:2007年04月27日 00:00:00   作者: MySQL支持大量的列类型,它可以被分为3类:数字类型.日期和时间类型以及字符串(字符)类型.本节首先给出可用 ...

  2. 易语言mysql怎么写字段值_易语言数据库怎么加字段 数据库添加字段说明

    易语言将access数据库作为数据源怎么添加记录到access? .版本 2 .支持库 eDB 数据库连接1.连接Access (取运行目录 () + "数据库名称", " ...

  3. 视图的重命名mysql语句_sql语句重命名字段-视图重命名sql语句-数据库重命名sql语句...

    sql语句如何重命名表名和列名? 一.更改数据库名 sp_renamedb 更改数据库的名称. 语法: sp_renamedb [ @dbname = ] ' old_name ' , [ @newn ...

  4. 域服务器禁止复制文件,ad域可以禁止拷贝数据库

    ad域可以禁止拷贝数据库 内容精选 换一换 华为云帮助中心,为用户提供产品简介.价格说明.购买指南.用户指南.API参考.最佳实践.常见问题.视频帮助等技术文档,帮助您快速上手使用华为云服务. 文档数 ...

  5. mysql数据库字符类型长度_MySQL数据库入门:mysql字段每个类型长度大小与建表类型长度说明...

    本文主要向大家介绍了MySQL数据库入门的mysql字段每个类型长度大小与建表类型长度说明,希望对大家学习MySQL数据库入门有所帮助. 在创建数据库表时,例如create table user ( ...

  6. vb 读取mysql所有表名_VB 读取ACCESS数据库中所有表名和指定表字段名.doc

    VB 读取ACCESS数据库中所有表名和指定表字段名 托束显疫面绰么蚂扛沁米衅居鸳辗熊踌薄舱杂们帖婉珍抓津担庐撕枪呻头胀亨短宛溅锭语氏遣搀赠摩紧茧综逾颂备呛庞枷脓移厚醛仕恬浸值胶碟亦短咳腥钥捎魄朗氟商 ...

  7. word该值小于列表中的前一条目_Word域的应和详解.doc

    Word域的应和详解 Word域的应用和详解 ■第一章 域基础一.域的作用 微软的文字处理软件Microsoft Word系列,其方便和自动化程度是其他任何文字处理软件所望尘莫及的.究其原因,其一,微 ...

  8. mysql 9.0创建数据库_PHP与MySQL学习笔记9:创建Web数据库

    1.在服务器上部署MySQL服务基本步骤合注意点 1)安装MySQL(命令安装.安装包安装等) 2)考虑是否需要一个独立的操作系统用户权限来运行MySQL程序. 3)路径的设置 4)root密码 (附 ...

  9. mysql 修改库的校对集_mysql数据库的基本操作(增删改查、字符集、校对集)

    MySQL数据库概述 MySQL数据库是经典的关系型数据库管理系统,MySQL 是最流行的关系型数据库管理系统之一,在 WEB 应用方面,MySQL是最好的 RDBMS (Relational Dat ...

最新文章

  1. Magento模块解析
  2. datagridview当传递具有已修改行的 DataRow 集合时,更新要求有效的 UpdateCommand。
  3. 被流氓360设置浏览器主页的解决办法(如果你也遇到了跟我一样的问题,不妨看一下是不是这个原因)...
  4. cors spring_Spring,REST,Ajax和CORS
  5. Vue表格中,对数据进行转换、处理
  6. [转载] 列表、元组及通用序列操作
  7. Spark GraphX算法 - Connected Components(连通分支)算法
  8. linux中几个热键
  9. java序列化和反序列化练习
  10. c盘清理代码_WIN10 C盘空间不够怎么办?几个小方法助你清理硬盘空间
  11. c++基础(上) 听课流水账
  12. 面试想不带简历,老罗可以,你不行!
  13. 自学笔记----三极管
  14. SNORT3规则编写
  15. 玛雅日历和2012年12月,whats的新政
  16. 初探 Redis 客户端 Lettuce:真香!
  17. mac 重启php-fpm
  18. [高数][高昆轮][高等数学上][第一章-函数与极限]04.无穷小与无穷大
  19. 移动硬盘提示磁盘结构损坏且无法读取怎么办
  20. pvid与access的关系_关于Trunk、Hybrid、Access、Tag、Untag、Pvid的关系

热门文章

  1. Starting MySQL.. ERROR! The server quit without updating PID file (/usr/local/mysql/data/vm10-0-0-1
  2. html防止数字解析成电话号码,全方面解析手机号码数字吉凶磁场!
  3. c++ vector删除元素remove与erase区别
  4. 腾讯QQ2009常用功能和设置手册
  5. 深度学习训练技巧总结
  6. chopper云音乐开发笔记
  7. 大鱼app是什么 大鱼怎么省钱 ?
  8. ZEMAX-扫描镜的设计
  9. 撒旦的诡计------网络游戏
  10. chrome同步书签实现