Microsoft Access 表单,“运行时错误‘3164’:无法更新字段。”错误,让我发疯

问题描述 投票:0回答:1

找到了解决方案,但我仍然希望得到帮助,请参阅我的问题的最后!!

我在 Access 中创建了一个连接到外部数据库的表单,在该表单中我可以为我工作的公司创建一个案例,其中包含所有必需的详细信息。它还具有一些功能来自动化流程的某些部分,例如具有从某个文件夹打开 Word 文档模板并使用案例详细信息进行修改的功能的按钮。到目前为止一切顺利(我将向您展示代码,以便您更好地理解表单的作用)

一旦我创建了第二个表格,它在数据库中查找案例编号以将其带回并让我更新/修改案例,这里我遇到了问题。一旦我打开一个已创建的案例,并尝试单击“创建上诉听证会结果”按钮,从磁盘上的路径位置打开一个 Word 文档,并使用案例中的最新详细信息自动更新该文件,我收到此错误“运行时错误‘3164’:无法更新字段。”。

这里有一些代码,以便您更好地了解,下面的代码来自我创建案例时,使用按钮创建上诉听证会文件的结果,这里一切正常:

Public Function matchExactCaseNumber(caseNumber As String) As Boolean
If DCount("*", "health_appeals", "exact_case_number='" & caseNumber & "'") > 0 Then
    matchExactCaseNumber = True
Else
    matchExactCaseNumber = False
End If
End Function

Function GetUserFullName() As String
    Dim WSHnet, userName, UserDomain, objUser
    Set WSHnet = CreateObject("WScript.Network")
    userName = WSHnet.userName
    UserDomain = WSHnet.UserDomain
    Set objUser = GetObject("WinNT://" & UserDomain & "/" & userName & ",user")
    GetUserName = objUser.FullName
    Splitusername = Split(GetUserName, ", ")
    SureName = Splitusername(0)
    FirstName = Splitusername(1)
    GetUserFullName = FirstName & " " & SureName
    
End Function

Private Sub Form_Load()
   DoCmd.GoToRecord , , acNewRec
   Me.pxtoc_expert = GetUserFullName()
   Me.pxtoc_expert_mail = Environ("USERNAME") & "@amazon.com"
End Sub

Private Sub Form_BeforeUpdate(Cancel As Integer)
    Dim response
    response = MsgBox("Do you want to save this as new record? Are you sure?" & vbCrLf & _
    "Yes=Save new record" & vbCrLf & "No=Close and don't save", vbQuestion + vbYesNo, "Save Changes?")

    If response = vbYes Then
        If matchExactCaseNumber(Me.exact_case_number) = True Then
            MsgBox "This Exact Case number: " & vbCrLf & vbCrLf & _
            Me.exact_case_number & vbCrLf & vbCrLf & _
            "already exists in health_appeals table, please open the update form and update the old case! ", vbInformation
            Me.Undo
            DoCmd.OpenForm "frmHealthAppeals", acNormal
        Else
            MsgBox "New record saved!", vbInformation
            DoCmd.OpenForm "frmHealthAppeals", acNormal
        End If
    ElseIf response = vbNo Then
        'Cancel = False
        Me.Undo
        DoCmd.OpenForm "frmHealthAppeals", acNormal
    Else
        Cancel = True
    End If
End Sub

Public Function workdocsPath() As String
Dim Path As String: Path = "UK Health & Attendance\Appeals\"
workdocsPath = "W:\Team Spaces\CTK Absence Management\" & Path
End Function

Public Function healthFolder() As String

Dim desktopPath As String
Dim folder As String

desktopPath = Environ("USERPROFILE") & "\Desktop\"
folder = desktopPath & "Health&Attendance"

If Dir(folder, vbDirectory) = "" Then
    MkDir folder
    healthFolder = folder
Else
    healthFolder = folder
End If
End Function

Private Sub cmdOutcomeLetter_Click()
    Path = workdocsPath()

    savePath = healthFolder()
    
    Dim wordApp As Object
    Dim wordDoc As Object
    
    Set wordApp = CreateObject("Word.Application")
    
    wordApp.Visible = True
    
    Set wordDoc = wordApp.Documents.Open(Path & "health_appeal_outcome.docx")
    
    With wordDoc
    
    
        .FormFields("today").Result = Format(Date, "dd mmmm yyyy")
        .FormFields("respondent_name").Result = Me.respondent_name
        
    '    ' Home Address 1
    '    If IsNull(Me.home_address_one) Then
    '        .FormFields("home_address_one").Delete
    '    Else
    '        .FormFields("home_address_one").Result = Me.home_address_one
    '    End If
    '    ' Home Address 2
    '    If IsNull(Me.home_address_two) Then
    '        .FormFields("home_address_two").Delete
    '    Else
    '        .FormFields("home_address_two").Result = Me.home_address_two
    '    End If
    '    ' Postcode
    '    If IsNull(Me.postcode) Then
    '        .FormFields("postcode").Delete
    '    Else
    '        .FormFields("postcode").Result = Me.postcode
    '    End If
    '    ' City
    '    If IsNull(Me.city) Then
    '        .FormFields("city").Delete
    '    Else
    '        .FormFields("city").Result = Me.city
    '    End If
    '    ' County
    '    If IsNull(Me.county) Then
    '        .FormFields("county").Delete
    '    Else
    '        .FormFields("county").Result = Me.county
    '    End If
        
        .FormFields("mails").Result = Me.personal_mail_address & ";" & Me.work_mail_address
        .FormFields("respondent_name_two").Result = Me.respondent_name
        .FormFields("meeting_date").Result = Format(Me.meeting_date, "dd mmmm yyyy")
        .FormFields("pxtoc_expert_two").Result = Me.pxtoc_expert
        .FormFields("notetaker_name").Result = Me.notetaker_name
        .FormFields("pxtoc_expert").Result = Me.pxtoc_expert
        .FormFields("respondent_name_thre").Result = Me.respondent_name
    
    End With
    
    
    wordDoc.SaveAs savePath & "\" & Me.respondent_name & " - Disciplinary Appeal Outcome Letter.docx"
    
    
    wordDoc.Activate
    wordDoc.Windows.Application.WindowState = wdWindowStateMinimize
    wordDoc.Windows.Application.WindowState = wdWindowStateMaximize
    
    Set wordApp = Nothing
    Set wordDoc = Nothing
End Sub

现在,所有代码都是用于一个表单,我在其中创建一个案例并可以选择将其保存在数据库中。一旦我决定返回一个案例并修改它,我就会使用第二个表单从数据库中检索它,更新案例的表单的代码是这样的:

Option Compare Database

Private Sub cmdCloseWindow_Click()
DoCmd.Close acForm, Me.Name
DoCmd.OpenForm "frmFormalHealth", acNormal
End Sub
'_____________________________________________
'_____________________________________________
'__________ Utilities Functions_______________
'_____________________________________________
'_____________________________________________
Public Function workdocsPath() As String
Dim Path As String: Path = "UK Health & Attendance\Appeals\"
workdocsPath = "W:\Team Spaces\CTK Absence Management\" & Path
End Function

Public Function healthFolder() As String

Dim desktopPath As String
Dim folder As String

desktopPath = Environ("USERPROFILE") & "\Desktop\"
folder = desktopPath & "Health&Attendance"

If Dir(folder, vbDirectory) = "" Then
    MkDir folder
    healthFolder = folder
Else
    healthFolder = folder
End If


End Function
Public Function Emailer(ValueCell As String) As String
Dim cellValue As String
Dim valuesArray() As String
Dim i As Long

valuesArray = Split(ValueCell, ",")

For i = LBound(valuesArray) To UBound(valuesArray)
    valuesArray(i) = valuesArray(i) & "@amazon.com"
Next i

Emailer = Join(valuesArray, ";")

End Function

Private Sub cmdOutcomeLetter_Click()
    Path = workdocsPath()

    savePath = healthFolder()
    
   ' Dim wordApp As Object
    'Dim wordDoc As Object
    
    'Set wordApp = CreateObject("Word.Application")
    
    'wordApp.Visible = True
    
    'Set wordDoc = wordApp.Documents.Open(Path & "health_appeal_outcome.docx")
    
    'With wordDoc
    
    
     '   .FormFields("today").Result = Format(Date, "dd mmmm yyyy")
      '  .FormFields("respondent_name").Result = Me.respondent_name
        
    '    ' Home Address 1
    '    If IsNull(Me.home_address_one) Then
    '        .FormFields("home_address_one").Delete
    '    Else
    '        .FormFields("home_address_one").Result = Me.home_address_one
    '    End If
    '    ' Home Address 2
    '    If IsNull(Me.home_address_two) Then
    '        .FormFields("home_address_two").Delete
    '    Else
    '        .FormFields("home_address_two").Result = Me.home_address_two
    '    End If
    '    ' Postcode
    '    If IsNull(Me.postcode) Then
    '        .FormFields("postcode").Delete
    '    Else
    '        .FormFields("postcode").Result = Me.postcode
    '    End If
    '    ' City
    '    If IsNull(Me.city) Then
    '        .FormFields("city").Delete
    '    Else
    '        .FormFields("city").Result = Me.city
    '    End If
    '    ' County
    '    If IsNull(Me.county) Then
    '        .FormFields("county").Delete
    '    Else
    '        .FormFields("county").Result = Me.county
    '    End If
        
       ' .FormFields("mails").Result = Me.personal_mail_address & ";" & Me.work_mail_address
       ' .FormFields("respondent_name_two").Result = Me.respondent_name
       ' .FormFields("meeting_date").Result = Format(Me.meeting_date, "dd mmmm yyyy")
       ' .FormFields("pxtoc_expert_two").Result = Me.pxtoc_expert
       ' .FormFields("notetaker_name").Result = Me.notetaker_name
       ' .FormFields("pxtoc_expert").Result = Me.pxtoc_expert
       ' .FormFields("respondent_name_thre").Result = Me.respondent_name
    
    'End With
    
    
    'wordDoc.SaveAs savePath & "\" & Me.respondent_name & " - Disciplinary Appeal Outcome Letter.docx"
    
    
    'wordDoc.Activate
    'wordDoc.Windows.Application.WindowState = wdWindowStateMinimize
    'wordDoc.Windows.Application.WindowState = wdWindowStateMaximize
    
    'Set wordApp = Nothing
    'Set wordDoc = Nothing
End Sub

如您所见,这些功能是相同的,只是减去了我正在更新字段的表单中不需要的一些功能。现在,当我尝试单击 OutcomeLetter 并且函数 cmdOutcomeLetter_Click() 运行时,我在“Path = workdocsPath()”行收到此错误。我已经测试过了,文件路径似乎是正确的。我只是不明白为什么会发生这个错误。

我尝试仔细检查文件路径,它似乎是正确的,我还尝试注释掉出现此错误的“Path = workdocsPath()”行,然后直接将文件路径输入到 wordApp.Documents .像这样打开线路:

Set wordDoc = wordApp.Documents.Open("W:\Team Spaces\CTK Absence Management\UK Health & Attendance\Appeals\health_appeal_outcome.docx")

令人惊讶的是,这是有效的,但是一旦我使用 workdocsPath() 函数来检索路径(当它将 workdocsPath() 的值分配给“Path = workdocsPath()”行中的 Path 时,这似乎是正确的,那就是我收到错误的时候。

我发现为什么这不起作用,基本上在调试器模式下,如果我将鼠标悬停在 Path = workdocsPath() 行的 Path 变量上,它没有 workdocsPath 检索到的路径的值,我怀疑这就是为什么我收到错误,路径应该为空,但是,事实并非如此,所以我所做的是创建另一个新变量来存储文件路径,它WORKS

但现在我很好奇为什么我不能重用 Path 变量?为什么我要被迫创建一个新的?这是我所做的解决问题的方法,但我仍然无法为此重用路径...:

Dim filePath As String: filePath = workdocsPath()

所以我使用了新的 filePath 变量。但我应该能够重用 Path,因为当我使用第一个表单创建案例时,我重用变量 Path 没有任何问题,不知道为什么使用第二个表单我无法重用它?

vba ms-access ms-access-2016
1个回答
0
投票

确保您始终在所有代码模块中包含 Option 显式。

当您使用变量 workdocsPath 时,该变量将是一个例程的本地变量,然后当您退出该子/函数时它就会超出范围。 但是,其他代码将会编译 - 因为您没有强制声明所有变量。如果你这样做了,那么你的代码将无法编译。

因此,对于所有代码模块,始终如此,我重复一遍始终如此:

Option Compare Database
Option Explicit

您可以使用此选项让 VBA 编辑器始终自动添加“Option Explicit”:

从 VBA 编辑器 -> 工具 -> 选项,然后选择此选项:

enter image description here

请注意,选择上述选项不会更改现有模块,但对于所有新的报告/表单和代码模块,将自动添加 Option Explicit。

选择上述意味着不会发生像您的示例这样的错误和问题。

 Sub MyTest

    sFun = "Hello"

 End Sub


 Sub Mytest2
    
     debug.print sFun

 End Sub

因此,在上面,当您退出第一个子时,变量 sFun 就会超出范围(不存在)。但是,由于您没有 Option Explicit,因此上面的代码可以正常编译。如果你打开 optionexplicit,那么上面的代码将不会编译,从而避免此类错误。

© www.soinside.com 2019 - 2024. All rights reserved.