【问题标题】:From main form, run VBA to validate total in subform从主窗体,运行 VBA 以验证子窗体中的总计
【发布时间】:2014-12-04 12:36:04
【问题描述】:

我在 MS Access 2002 中有一个表单,在命令按钮后面有以下 sn-p 代码。

'Requery subform to make sure total is calculated
Me.fsubUpdateShipments.Requery
DoEvents

'Confirm quantities have been entered
If Form_fsubUpdateShipments.txtTotalShipmentQty.Value <= 0 Then
    MsgBox "Cannot create shipment, no quantities have been entered", vbCritical
    Exit Sub
End If

这几个月来一直运行良好,但今天一位同事来找我并解释说,即使他们输入了数量,错误消息也会显示。

经过一番挖掘后,我确定.Value &lt;= 0 表达式在相关文本框完成计算其值之前被评估:=Sum([QtyToShip])。这似乎只发生在子表单有大量记录(大约 10 条或更多)并且显然是一个严重问题时。

在包含If 语句的行上添加断点可以使代码正确运行,但我显然不能永久使用此方法。

有什么方法可以强制代码暂停,直到子窗体控件完成重新计算它们的值?

【问题讨论】:

  • 我想说WAITING 是这里唯一的解决方案
  • 或者,如果您决定更改当前解决方案以在记录集上使用ADO.Recordset then calling a .Requery,则会触发RecordsetChangeComplete 事件,这将允许您在RecorodsetChangeCompleted 触发后立即继续执行IF 语句。
  • @vba4all 如果我错了,请纠正我,但 Application.Wait 仅在 Excel 中有效?
  • 看看here有一个访问权限,或者你可以添加对Excel对象模型的引用,如果你真的想使用application.wait
  • @Smandoli 如果我删除.Requery,我仍然会遇到同样的问题。我不知道为什么过去我把它放在那里,我可能没有它也可以生活,但是如果用户在焦点位于时单击主窗体上的命令按钮,我仍然会遇到 If 语句被评估得太早子窗体。似乎无齿翼龙的答案是我能得到的最好的答案。

标签: ms-access vba ms-access-2002


【解决方案1】:

我会完全跳过使用用户界面并查看表格。如果这是在主窗体命令按钮上运行的,则子窗体失去焦点并保存其值。重新查询是不必要的。只需在 DSum 的标准(第三个参数)中重新创建父子关系:

If DSum("QtyToShip", "ShipmentDetails", "ShipmentID = " & Me!ShipmentID) <= 0 Then
    MsgBox "Cannot create shipment, no quantities have been entered", vbCritical
    Exit Sub
End If

【讨论】:

  • +1 用于指出子表单数据应该被解析。 (尽管为什么看起来不是这样是一个重要的问题。)这个解决方案应该可以正常工作。至于“表现不佳”,这似乎不是可以注意到差异的情况。
  • 我建议您将DSum() 的结果放入一个整数变量中,然后对其进行评估:If intTotalQty &lt; 1... 使用变量可能会发现缺陷,甚至可能解决时间问题。无论如何,这是一个对你有好处的习惯。
【解决方案2】:

有两个选项,其他人已经确定了,但由于他们的建议要么不完整,要么不整洁(缓慢),所以我发布了这篇文章。

A.您可以强制等待以延迟 IF 测试:

把它放在一个模块中:

Private Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
...
Public Sub GoSleep(millisecondDelay as long)
    Sleep (millisecondDelay)
End Sub

并以您的形式:

'Requery subform to make sure total is calculated
Me.fsubUpdateShipments.Requery
DoEvents

GoSleep 1000 '1 second delay. Or 2000, whatever is required really

'Confirm quantities have been entered
If Form_fsubUpdateShipments.txtTotalShipmentQty.Value <= 0 Then
   MsgBox "Cannot create shipment, no quantities have been entered", vbCritical
   Exit Sub
End If

B.正如另一个答案所说,您可以自己重新计算,并在此结果的基础上进行测试。

但是,我建议不要像 pteranodon 建议的那样使用 DSum,而是建议使用比 DSum 更快的方法,因为 DSum(DCount 等)非常慢。

我通常将 ADO 用于数据操作,尽管我的代码可以很容易地适应 DAO。要使用此代码,如果您还没有 Microsoft activeX 2.8,则需要参考:

在一个模块中:

Public Function GetDBValue(qry as string) as variant
    dim rst as new adodb.recordset
    rst.open qry, currentproject.connection, adOpenKeyset, adLockReadOnly
    if rst.eof then
        GetValue = null
    else
        GetValue = rst.fields(0)
    end if
end function

public Function IsNullSQL(basevalue as variant, replacementvalue as variant) as variant
    isNullSQL = iif(isnull(basevalue), replacementvalue, basevalue)
end function

在你的表格中:

''Requery subform to make sure total is calculated
'Me.fsubUpdateShipments.Requery
'DoEvents

'Confirm quantities have been entered
If IsNullSQL(GetValue("SELECT Sum(QtyToShip) FROM tbl WHERE ..."), -1) < 0 Then
    MsgBox "Cannot create shipment, no quantities have been entered.", vbCritical, "No Quantities to Ship"
    Exit Sub
End If

'If Form_fsubUpdateShipments.txtTotalShipmentQty.Value <= 0 Then
'    MsgBox "Cannot create shipment, no quantities have been entered", vbCritical
'    Exit Sub
'End If

【讨论】:

  • 使用睡眠功能只能是最后的手段。更好地解决问题(我怀疑这是可以解决的)。第二个答案最好作为单独的答案提供。我为彻底的编码鼓掌,但是(a)DSum() 更简单,实际上没有危险,并且(b)我不能支持仅仅为了这个而将某人逼向ADO
  • 我接受你对 ADO 的看法——但这正是我所使用的。但我不能同意。我永远记不起它的语法,而且在涉及大量数据的地方,它确实会影响性能。
  • 我在这里必须同意@Smandoli,如果我的问题不清楚,我深表歉意,但数据集通常非常小,大约 3-4 条记录.强制任意等待时间似乎会导致不必要的延迟,并且每个用户都有不同的 PC 规格可能一开始就很难计算。 DSum 可能会对性能产生更多影响,但它绝对更安全、更简洁。
猜你喜欢
  • 1970-01-01
  • 2019-08-01
  • 2011-07-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多