如何使用VBA从Access中的同一字段填充Word中的多个书签/表单字段

时间:2019-02-13 19:52:53

标签: vba ms-access ms-word

我以前一直使用某些VBA将Access中的字段传递到Word文档中,直到达到255个字符的限制。 site的帮助使我现在使用书签代替了表单字段。

我本来是在Word上填充许多不同的字段的,在某些情况下,我是在Word文档的两个位置上使用Access中的相同数据。我通过致电:

.FormFields("txtReasonforReward").Result = Me![Reason for Reward]
.FormFields("txtReasonforReward2").Result = Me![Reason for Reward]

由于我现在有另一种填充“ Reason for Reward”框的方法,以避开字符数限制(下面的代码),所以我不确定如何填充“ txtReasonforReward2”。我确实有几个实例,在其中我添加了第二个字段并在末尾添加了2个...我不相信这是最好的方法,因此,如果有人可以建议如何使用FormFields和Bookmarks来实现这一点,我真的会很感激。

Dim objWord As Object
Set objWord = CreateObject("Word.Application")
objWord.Visible = True
Set doc = objWord.Documents.Open(***path to file***, , True)

Dim rng As Word.Range
Dim x As String

With doc
.FormFields("txtFirstName").Result = Me![First Name]
.FormFields("txtLastName").Result = Me![Last Name]
`examples cut for clarity...
.FormFields("txtHRID").Result = Me![ID]
.FormFields("txtPeriod").Result = Me![Period]

If doc.ProtectionType <> wdNoProtection Then
   doc.Unprotect
End If

Set rng = doc.Bookmarks("txtReasonforReward").Range
rng.MoveStart wdCharacter, -1
x = rng.Characters.First
rng.FormFields(1).Delete
rng.Text = x & Me![Reason for Reward]
doc.Protect wdAllowOnlyFormFields, True

.Visible = True
.Activate

End With

objWord.View.ReadingLayout = True

2 个答案:

答案 0 :(得分:0)

以问题和背景问题中的代码为基础...

Word可以使用REF域代码来复制书签的内容。由于表单字段还使用书签标识符,因此这将与现有表单字段以及加书签的内容一起使用。如果有人熟悉,可以直接插入REF字段,也可以通过插入书签的交叉引用来直接插入。

请参阅替代方法以插入255个以上的字符,在这种情况下,还必须在要插入的范围周围放置一个书签,并更新REF字段,以便它们反映书签内容整个文档中。代码的修改部分如下。

'Declarations to be added at the beginning of the procedure
Dim fld As Word.Field
Dim bkmName As String

'Name of form field, bookmark to be added and text in REF field code
bkmName = "txtReasonforReward"     

'Existing code
If doc.ProtectionType <> wdNoProtection Then
   doc.Unprotect
End If
Set rng = doc.Bookmarks(bkmName).Range
rng.MoveStart wdCharacter, -1
x = rng.Characters.First
rng.FormFields(1).Delete
rng.Text = x & Me![Reason for Reward]

' New code
'Leave that single character out of the range for the bookmark
rng.MoveStart wdCharacter, 1
'Bookmark the inserted content
doc.Bookmarks.Add bkmName, rng
'Update fields so that REF's pick up the bookmark content
For Each fld In doc.Fields
    If fld.Type = wdFieldRef Then
        fld.Update
    End If
Next

doc.Protect wdAllowOnlyFormFields, True

如果需要将其应用于许多领域,则此方法会有些笨拙。可能需要执行一些操作,例如将书签名称写到“访问”表单中控件的Tag属性中,然后循环控件以从控件中选择书签名称和数据,而不是显式地将它们写出来。这只是对未来的思考。

总而言之,实现这一目标的“现代”方法是使用内容控件而不是表单域/书签。内容控件没有255个字符的限制,文档可以作为一种形式被保护,多个内容控件可以具有相同的标题(名称)和/或标签。此外,可以将内容控件“映射”到存储在文档中的自定义XML部件,以便更改一个控件的内容将更改另一个控件的内容。试图在此处描述超出“答案”范围的所有内容,但所有这些内容都可以通过搜索Internet公开获得。

就个人而言,如果这是我的项目,并且知道我对它的了解:如果文档中不需要表单字段(不需要用户通过字段输入),我将仅使用书签和REF字段。

答案 1 :(得分:0)

有很多方法可以做这种事情。看一下下面的方法,看看是否可以使它起作用。

Option Compare Database
' This concept uses Docvariables in MS Word
Sub PushToWord()

Dim wapp As Word.Application
Dim wdoc As Word.Document
Dim db As DAO.Database
Dim fld As DAO.Field
Dim rs As DAO.Recordset
Dim filenm As String
Dim NumFields As Integer
Dim i As Integer

Set db = CurrentDb
Set rs = db.OpenRecordset("tbl_CustomerData")

Set wapp = New Word.Application
wapp.Visible = True


Set rs = DBEngine(0)(0).OpenRecordset("SELECT * FROM tbl_CustomerData")

If rs.RecordCount > 0 Then
  rs.MoveFirst

  Do While Not rs.EOF
     For i = 0 To rs.Fields.Count - 1
        Set fld = rs.Fields(i)
        Debug.Print fld.Name, fld.Value
            If fld.Value = 20 Then
                filenm = "C:\Users\Ryan\Desktop\Coding\Integrating Access and Word\From Access to Word\Letter1.doc"
                    Set wdoc = wapp.Documents.Open(filenm)
                wapp.ActiveDocument.Variables("Name").Value = rs.Fields("Name").Value
            End If
     Next
     rs.MoveNext
  Loop
  Set fld = Nothing
  rs.Close
End If
Set rs = Nothing

End Sub

该代码从Access运行,您可以通过多种方式将其触发(按钮单击事件,表单加载事件,某些其他对象事件等)

相关问题