跨表统计的自动更新

首先我们重复一下上一节的内容。

假定有一个如下图所示的订单表:

我们希望新增这么一个表,在该表中输入一个产品名称,能够自动统计出该产品总的销售数量。
首先增加一个表,表的名称为“统计”,该表包括两列,分别是字符型的产品,和整数型的数量:

然后在该表的DataColChanged事件 中设置如下代码:

If e.DataCol.Name = "产品" Then
    e.DataRow("数量") = DataTables("订单").Compute("Sum(数量)","[产品] = '" & e.NewValue & "'")
End
If

请在统计表设置好上述代码后,重置一次该表的产品列。

现在要求在订单表输入或修改某订单的数量后,能够即时更新统计表对应产品的数量统计值。

为此可将订单表的DataColChanged事件代码设置为:

If e.DataCol.Name = "数量" Then
    Dim pr As DataRow
    pr =
DataTables("统计").Find("产品 = '" & e.DataRow("产品") & "'")
    If
pr IsNot Nothing
Then
        pr(
"数量")= pr("数量") + e.NewValue - e.OldValue
    End
If
End
If

代码的原理很简单,修改某订单的数量后,上面的代码会在统计表找出对应的产品,然后将该产品的数量累计值加上此订单的新数量值,并减去此订单的原数量值,得到该产品最新的销售数量。

另一种自动更新方式

假定统计表不单单要产品总销售数量,还要统计总的销售金额:

首先将统计表的DataColChanged事件代码设置为:

If e.DataCol.Name = "产品" Then
    Dim
Filter As String = "[产品] = '" & e.NewValue & "'"
    e.
DataRow("数量") = DataTables("订单").Compute("Sum(数量)", Filter)
    e.
DataRow("金额") = DataTables("订单").Compute("Sum(金额)", Filter)
End
If

同样在统计表设置好上述代码后,请重置一次该表的产品列。

订单表的金额列是一个表达式列,其表达式为:[数量] * [单价] * (1 - [折扣])
我们知道表达式列有一个特性,就是其值发生变化后,并不会触发DataColChanged事件,此特性导致我们无法简单地用前面介绍的方法来自动更新统计表中的销售金额。
所以有必要考虑用另一重算方法,将订单表的DataColChanged事件代码设置为:

Select Case e.DataCol.Name
    Case
"数量","单价","折扣"
       
Dim pr As DataRow
        pr =
DataTables("统计").Find("产品 = '" & e.DataRow("产品") & "'")
        If
pr IsNot Nothing Then
            DataTables
("统计").DataCols("产品").RaiseDataColChanged(pr)
        End
If
End
Select

代码的原理是,当订单表中数量、单价、折扣三列中任何一列的内容发生变化,就从统计表中找出对应产品所在的行,然后“欺骗性”地通知系统该行的产品列内容发生了变化,于是触发统计表的DataColChanged事件,重算 此行的数量和金额。

这种更新方式是很常用的,即使处理的不是表达式列,我们多数时候也会采用这种更新方式。
因为使用RaiseDataColChanged更新,代码不会涉及具体的计算,所以代码是通用的,基本上不会因为计算要求的变动,而去修改更新代码。

提醒:

一般来说,统计表是没有必要即时更新的,完全可以像上一节那样简单地在项目事件MainTableChanged中加入下面的代码:

If MainTable.Name = "统计" Then
    DataTables(
"统计表").DataCols("产品").RaiseDataColChanged()

End
If

这样切换到统计表之后,会自动执行上述代码更新统计结果,虽然效率也不如前面的高,但这种差别用户是很难感受得到的,所以这种简单的处理方式足以满足绝大多数场合的需要。


本页地址:http://www.foxtable.com/webhelp/topics/1472.htm