以文本方式查看主题

-  Foxtable(狐表)  (http://foxtable.com/bbs/index.asp)
--  专家坐堂  (http://foxtable.com/bbs/list.asp?boardid=2)
----  流水账设计的详细介绍  (http://foxtable.com/bbs/dispbbs.asp?boardid=2&id=2744)

--  作者:狐狸爸爸
--  发布时间:2009/5/11 16:03:00
--  流水账设计的详细介绍
 

关于流水账

本示例可以参考CaseStudy目录下的文件:流水账.Table

假定有下面一个简单的流水帐式的表格,输入收入和支出,能够自动计算出余额。



此主题相关图片如下:1030.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是自动生成,对于日期相同的行,只能根据输入顺序计算,不过这对于实际的应用并没有多大的影响。
如果你很在意这个,你可以自己假如一个编号列,自己输入编号,这样就可以自行调整计算顺序,代码请自行编写,就当是一个小练习吧。

 下载信息  [文件大小:   下载次数: ]
点击浏览该文件:管理项目7.table


--  作者:smileboy
--  发布时间:2009/5/11 16:04:00
--  
还凑合,继续努力图片点击可在新窗口打开查看
--  作者:程兴刚
--  发布时间:2009/5/11 16:06:00
--  

抢先看,顶!

晕,还是没人加快啊!

[此贴子已经被作者于2009-5-11 16:32:32编辑过]

--  作者:卟离卟弃
--  发布时间:2009/5/11 16:11:00
--  

学习
如果加一个名称列用来区分.
如:09-05-11 钢笔     收入 10 支出 5  结存 5
    09-05-11 记事本  收入 10 支出 5  结存 5
    09-05-12 钢笔     收入 10 支出 4  结存 11
    09-05-12 记事本  收入 10 支出 4  结存 11

像这样多个东西在一个表格中记录流水账
代码有什么变化?


--  作者:狐狸爸爸
--  发布时间:2009/5/11 16:25:00
--  
一样的设计啊,只需在条件表达式中,加入名称的比较,也就是相同名称的就行了。
--  作者:狐狸爸爸
--  发布时间:2009/5/11 16:48:00
--  
这个文件的例子二,就分产品计算流水账了:

 下载信息  [文件大小:   下载次数: ]
图片点击可在新窗口打开查看点击浏览该文件:管理项目7.table

[此贴子已经被作者于2009-5-11 16:48:40编辑过]

--  作者:yangming
--  发布时间:2009/5/11 17:10:00
--  
顶!呵呵
--  作者:卟离卟弃
--  发布时间:2009/5/11 17:15:00
--  
 下载信息  [文件大小:   下载次数: ]
图片点击可在新窗口打开查看点击浏览该文件:流水账记录.table


为什么输日期09-5-12   编号B002时,引用的结存不是5-11日的?输其它任何日期引用的结存数都没有问题.就5-12日有问题.不明白.

--  作者:狐狸爸爸
--  发布时间:2009/5/11 17:23:00
--  
你得条件设置不正确,所以得不到正确的结果,看这个:

 下载信息  [文件大小:   下载次数: ]
图片点击可在新窗口打开查看点击浏览该文件:管理项目32.table


--  作者:mr725
--  发布时间:2009/5/11 19:57:00
--  
这种流水账能正确反映到某日的余额,不过如果就把该余额表原封不动的让一个人看的话,再让她告诉你余额是多少? 她一定会将最后一行的余额数字报给你的~~(如果她又报给了你的上司的话。。。呵呵)

通常还是按最后一行为表中真正的余额比较好,需要看某日的余额时,再按一楼第三断代码筛选后列出比较合适!!