O365(Access 2016)中VBA拼写检查多修正时崩溃问题求助
我之前碰到过一模一样的问题,O365版本的Access对VBA事件上下文和命令执行的稳定性要求比旧版严格太多,你的代码里有几个关键问题导致了崩溃,咱们一步步来修复:
首先先处理一个小语法问题——原代码里Exit Sub后面多写了一个End If,虽然Access 2010可能会忽略这个冗余语句,但O365的VBA引擎对语法错误的容忍度更低,这个小问题可能会在后台引发潜在的执行异常,先把它删掉。
接下来是核心矛盾:在Lost Focus事件中强制给控件设置焦点。Lost Focus事件本身就是控件即将失去焦点的触发时机,此时Access正在处理焦点转移的内部状态,你强行调用.SetFocus会打乱这个流程,当拼写检查执行批量操作(比如“全部更改”)时,这种状态冲突就会直接导致崩溃。
另外,DoCmd.SetWarnings False/True在这里完全没必要,拼写检查命令本身不会弹出需要抑制的系统警告,关闭警告反而会隐藏崩溃前的错误提示,不利于排查问题,直接删掉这两行就行。
推荐修复方案:改用AfterUpdate事件触发拼写检查
把触发事件从Lost Focus换成AfterUpdate,只有当字段内容实际修改时才触发检查,既避免了焦点冲突,也减少了不必要的触发次数。修正后的代码如下:
Private Sub txtMyField_AfterUpdate() Dim strSpell As String ' 用Nz函数处理空值,简化判断逻辑 strSpell = Nz(Me.txtMyField.Value, "") ' 空内容直接退出 If Len(strSpell) = 0 Then Exit Sub ' 确保控件处于编辑状态并选中全部内容 Me.txtMyField.SetFocus Me.txtMyField.SelStart = 0 Me.txtMyField.SelLength = Len(strSpell) ' 执行拼写检查 DoCmd.RunCommand acCmdSpelling End Sub
如果必须保留Lost Focus事件
如果你因为业务需求一定要用Lost Focus,可以在设置焦点前加入DoEvents让Access完成当前的焦点转移流程,再执行后续操作:
Private Sub txtMyField_LostFocus() Dim strSpell As String strSpell = Nz(Me.txtMyField.Value, "") If Len(strSpell) = 0 Then Exit Sub ' 让Access完成当前的焦点处理,避免状态冲突 DoEvents Me.txtMyField.SetFocus Me.txtMyField.SelStart = 0 Me.txtMyField.SelLength = Len(strSpell) DoCmd.RunCommand acCmdSpelling End Sub
额外说明
原代码里的IsNull(Len(strSpell))其实是冗余的——如果strSpell是Null,Len(strSpell)会返回Null,用Nz转换后直接判断长度是否为0就足够了,这样代码更简洁也更可靠。
内容的提问来源于stack exchange,提问作者FortCol

