【问题标题】:How to fill multiple Bookmarks / FormFields in Word from the same field in Access using VBA如何使用 VBA 从 Access 中的同一字段填充 Word 中的多个书签/表单字段
【发布时间】:2019-07-07 18:27:29
【问题描述】:

我以前一直使用一些 VBA 将字段从 Access 传递到 Word 文档,直到遇到 255 个字符的限制。来自 site 的帮助使我现在使用书签而不是表单字段。

我最初在 Word 上填写了许多不同的字段,在某些情况下,我在 Word 文档的两个位置使用 Access 中的相同数据。我通过调用来实现这一点:

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

由于我现在有一种不同的方式来填写“奖励原因”框,以规避字符限制(下面的代码),我不知道如何填写“txtReasonforReward2”。我确实有几个实例,我添加了第二个字段并在最后添加了一个 2 ......我不相信这是最好的方法,所以如果有人可以建议如何使用 FormFields 和书签来实现这一点,我真的很感激。

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

【问题讨论】:

    标签: vba ms-access ms-word


    【解决方案1】:

    基于问题中的代码和背景问题...

    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
    

    如果需要将这种方法应用于许多领域,它会变得有点笨拙。将书签名称写入 Access 表单中控件的 Tag 属性然后循环控件以从控件中获取书签名称和数据可能是有意义的,而不是显式地写出每一个 - 但这是只是对未来的一个想法。

    话虽如此,实现这一目标的“现代”方式是使用内容控件而不是表单字段/书签。内容控件没有 255 个字符的限制,文档可以作为表单进行保护,多个内容控件可以具有相同的标题(名称)和/或标签。此外,内容控件可以“映射”到存储在文档中的自定义 XML 部件,以便更改一个控件的内容将更改另一个的内容。试图描述所有超出“答案”的内容,在这里,但通过搜索互联网可以公开获得。

    就个人而言,如果这是我的项目并且知道我所知道的:如果文档中不需要表单字段(不需要用户通过字段进行输入),我只会使用书签和 REF 字段。

    【讨论】:

      【解决方案2】:

      有很多方法可以做这种事情。看看下面的方法,看看你是否可以让它工作。

      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 运行,您可以通过多种方式触发它(按钮单击事件、表单加载事件、其他一些对象事件等)

      【讨论】:

        猜你喜欢
        • 2013-07-24
        • 2020-04-03
        • 1970-01-01
        • 2019-06-12
        • 2019-01-08
        • 2019-08-05
        • 2020-05-06
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多