关于流水账
本示例可以参考CaseStudy目录下的文件:流水账.Table
假定有下面一个简单的流水帐式的表格,输入收入和支出,能够自动计算出余额。
此主题相关图片如下:1030.gif
![dvubb 按此在新窗口浏览图片](UploadFile/2009-5/20095111612077626.gif)
实现的代码不复杂,只需将DataColChanged事件设为:
Select
Case e.DataCol.Name
Case "日期","收入","支出"
If e.DataRow.Isnull("日期") = False Then
For Each dr As DataRow In e.DataTable.Select("[日期] >= #" & e.DataRow("日期") & "#")
Dim Val1 As Double = e.DataTable.compute("Sum(收入)","[日期] <= #" & dr("日期") & "#")
Dim Val2 As Double = e.DataTable.compute("Sum(支出)","[日期] <= #" & dr("日期") & "#")
dr("余额") = Val1 - Val2
Next
End If
End Select
这样输入某一天的收入和支出,自该天开始的所有日期的余额,即可自动计算得出。
假如一天会有多次收入和支出,而且都作为单独的一行输入,那么用上述的代码计算得出的余额会有一些问题,因为上面的代码是比较日期的,这样同一日期的所有行,其余额都是相同的,显然这不符合我们的习惯,为此,我们可以将DataColChanged事件的代码改为:
Select
Case e.DataCol.Name
Case "日期","收入","支出"
If e.DataRow.Isnull("日期") = False Then
For Each dr As DataRow In e.DataTable.Select("[_Identify] >= " & e.DataRow("_Identify"))
Dim Val1 As Double = e.DataTable.Compute("Sum(收入)","[_Identify] <= " & dr("_Identify"))
Dim Val2 As Double = e.DataTable.Compute("Sum(支出)","[_Identify] <= " & dr("_Identify"))
dr("余额") = Val1 - Val2
Next
End If
End Select
我们知道_Identify列的值,每增加一行都会自动加1,所以其值代表着行的输入顺序,这样即使同一天输入多行数据,上面的代码也能正确计算出每一行的余额。
代码似乎已经很完美了,其实不然;因为上面的代码没有比较日期,只是比较输入顺序,所以你必须严格按照日期顺序输入数据,如果你输入完今天的收入和支出后,突然发现昨天漏输了一笔支出,那么麻烦来了,从这一笔开始,你再也没有办法得到正确的余额了,除非你删除今天的数据,输入这笔昨天的支出后,再重新输入今天的数据,显然,这是很“无理”的要求。
要解决上述问题,需要同时比较日期和输入顺序(_Identify),所以DataColChanged事件改为:
Select
Case e.DataCol.Name
Case "日期","收入","支出"
If e.DataRow.IsNull("日期") = False Then
Dim drs As List(of DataRow)
drs = e.DataTable.Select("[日期] >= #" & e.DataRow("日期") & "#","日期")
For Each dr As DataRow In drs
Dim Filter As String = "[日期] < #" & dr("日期") & "# Or ([日期] = #" & dr("日期") & "# And [_Identify] <= " & dr("_Identify") & ")"
Dim Val1 As Double = e.DataTable.Compute("Sum(收入)",Filter)
Dim Val2 As Double = e.DataTable.Compute("Sum(支出)",Filter)
dr("余额") = Val1 - Val2
Next
End If
End Select
现在的代码已经完美了,具备了实用的价值,唯一的缺点是_Identify是自动生成,对于日期相同的行,只能根据输入顺序计算,不过这对于实际的应用并没有多大的影响。
如果你很在意这个,你可以自己假如一个编号列,自己输入编号,这样就可以自行调整计算顺序,代码请自行编写,就当是一个小练习吧。