Foxtable(狐表)用户栏目专家坐堂 → [求助]能否在交叉表的垂直分组列中增加列(已解决)


  共有23408人关注过本帖树形打印复制链接

主题:[求助]能否在交叉表的垂直分组列中增加列(已解决)

帅哥哟,离线,有人找我吗?
ybil
  21楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:超级版主 帖子:521 积分:4910 威望:0 精华:7 注册:2008/9/2 22:22:00
  发帖心情 Post By:2011/7/12 16:48:00 [只看该作者]

If e.Form.Controls("ComboBox2").Value Is Nothing Then
    MessageBox.Show("请在右侧选择生成报表的年份","提示")
    Return
End If
'根据年份生成临时表

Dim nf,sql1,sql2,sql3,s1,s2,jgf,rjs,rjjgf,wb,Bs As String
nf = e.Form.Controls("ComboBox2").Value
sql1 = " From(Select 报表年月,日期,单位,Sum(加工费) As 加工费,Sum(投工) As 投工 FROM {日报源表} WHERE Year(日期) = "
sql1+= nf & " Group By 报表年月,日期,单位 ORDER BY 单位,日期,报表年月) Group By 单位"
sql2="Select DISTINCT 报表年月 FROM {日报源表} WHERE Year(日期) = " & nf

Dim cmd As New SQLCommand
Dim dt As DataTable
cmd.CommandText = sql2
dt = cmd.ExecuteReader()

Dim Ls As List(Of String)
Ls =dt.GetUniqueValues("","报表年月")

For n As Integer = 0 To ls.Count-1
    s1 = "sum(iif(报表年月 = " & Ls(n) & ",加工费,Null))"
    jgf = s1 & " as " &  Ls(n) & "_加工费"
    s2 = "avg(iif(报表年月 = " & Ls(n) & ",投工,Null))"
    rjs = s2 & " as " &  Ls(n) & "_月均人数"
    rjjgf= s1 & "/" & s2 & " as " &  Ls(n) & "_人均加工费"
    If n >0 Then
        wb = s1 & "/" & s2 & "/(sum(iif(报表年月 = " & Ls(n-1) & ",加工费,Null))/ avg(iif(报表年月 = " & Ls(n-1) & ",投工,Null))" & ") as " &  Ls(n) & "_环比"
        If n =  ls.Count-1 Then
            wb = wb & ",Sum(加工费) As 合计_加工费,sum(投工) as 合计_年均人数,sum(加工费) as 年人均加工费,Sum(加工费) As 名次"
        End If
    End If
    sql3+ = "," & jgf &  "," & rjs & "," & rjjgf & ","  & wb
Next
sql3="select 单位" & sql3.Replace(",,",",") & sql1

Dim b As New SQLGroupTableBuilder("年度汇总","日报源表")
b.Groups.AddDef("单位") '根据产品分组
b.Totals.AddDef("加工费") '对数量进行统计
b.Build '生成统计表
DataTables("年度汇总").Fill(sql3,True)

For Each dc As DataCol In  DataTables("年度汇总").DataCols
    If dc.name <> "单位" Then
        DataTables("年度汇总").DataCols(dc.Name).SetFormat("0.00")
        bs+="," & dc.name
    End  If
Next
DataTables("年度汇总").DataCols("名次").SetFormat("0")

Dim sum As Double
For Each r As Row In Tables("年度汇总").Rows
    sum =0
    For Each dc As DataCol In DataTables("年度汇总").DataCols
        If dc.name.IndexOf("_月均人数")> -1 Then
            sum+= r(dc.name)
        End If
        If dc.name = "合计_年均人数" Then
            r("合计_年均人数") = sum/ls.Count
            r("年人均加工费") = ls.Count*r("合计_加工费")/sum
            Exit For
        End If
    Next
Next
Dim drs As List(Of DataRow) = DataTables("年度汇总").Select("[单位] <> '合计'","年人均加工费 DESC")
For n As Integer = 0 To drs.Count - 1 '遍历所有行
    If n > 0 AndAlso drs(n)("年人均加工费") = drs(n-1)("年人均加工费") Then '如果年人均加工费和上一行相同
        drs(n)("名次") = drs(n-1)("名次") '则排名等于上一行
    Else
        drs(n)("名次") = n + 1 '设置名次
    End If
Next
Dim t As Table = Tables("年度汇总")
Dim g As SubtotalGroup
t.SubtotalGroups.Clear()
t.GroupAboveData = False
t.TreeVisible = False
t.SpillNode = True

g = New Subtotalgroup
g.Aggregate = AggregateEnum.Sum
g.GroupOn = "*"
g.TotalOn = bs.Trim(",").Replace(",名次","")
g.Caption = "合计"
t.SubtotalGroups.Add(g)
t.Subtotal()

Dim r1 As Row
With Tables("年度汇总")
    For i As Integer = 0 To .Rows.Count(True) - 1 'Count加上参数True
        r1 = .Rows(i,True) 'Rows也需要加上参数True
        If r1.IsGroup Then '如果是分组行
            For n As Integer = 0 To .Cols.Count -1
                If .cols(n).name.Indexof("人均加工费")> -1 Then
                    r1(.cols(n).name) = r1(.cols(n-2).name)/r1(.cols(n-1).name)
                End If
                
            Next
        End If
    Next
End With

Tables("年度汇总").Cols("单位").TextAlign = TextAlignEnum.Center
Tables("年度汇总").Cols("名次").TextAlign = TextAlignEnum.Center
Tables("年度汇总").AutoSizeCols()
MainTable = Tables("年度汇总") '

 回到顶部
帅哥哟,离线,有人找我吗?
ybil
  22楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:超级版主 帖子:521 积分:4910 威望:0 精华:7 注册:2008/9/2 22:22:00
  发帖心情 Post By:2011/7/12 16:49:00 [只看该作者]

注:报表年月改为整数型

 回到顶部
帅哥哟,离线,有人找我吗?
狐狸爸爸
  23楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:管理员 帖子:47448 积分:251048 威望:0 精华:91 注册:2008/6/17 17:14:00
  发帖心情 Post By:2011/7/12 16:52:00 [只看该作者]

Y版出马,楼主有福了。

 

图片点击可在新窗口打开查看


 回到顶部
帅哥哟,离线,有人找我吗?
ybil
  24楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:超级版主 帖子:521 积分:4910 威望:0 精华:7 注册:2008/9/2 22:22:00
  发帖心情 Post By:2011/7/12 18:55:00 [只看该作者]

原来的思路:

'读取ComboBox2中的年份
If e.Form.Controls("ComboBox2").Value Is Nothing Then
    MessageBox.Show("请在右侧选择生成报表的年份","提示")
    Return
End If
'根据年份生成临时表
Dim nf As String = e.Form.Controls("ComboBox2").Value
Dim sql As String = "Select 报表年月,日期,单位,Sum(加工费) As 加工费,Sum(投工) As 投工,Sum(加工费) as 人均加工费,Sum(加工费) As 环比  FROM {日报源表} WHERE Year(日期) = '" & nf &  "' Group By 报表年月,日期,单位 ORDER BY 单位,日期,报表年月"
'根据临时表生成年度汇总表
Dim b As New CrossTableBuilder("年度汇总",sql)
b.HGroups.AddDef("单位")
b.VGroups.AddDef("报表年月")
b.Totals.AddDef("加工费")
b.Totals.AddDef("投工",AggregateEnum.Average,"月均人数")
b.Totals.AddDef("人均加工费",AggregateEnum.Average,"人均加工费")
b.Totals.AddDef("环比",AggregateEnum.Average,"环比")
b.HorizontalTotal = True
b.VerticalTotal = True
b.Build()

Dim t As Table = Tables("年度汇总")
Dim i As Integer =(Tables("年度汇总").Cols.Count-5)/4

t.DataTable.DataCols.Add("合计_年均人数", Gettype(Double),"[合计_投工]/" & i)
t.DataTable.DataCols.Add("年人均加工费", Gettype(Double),"合计_加工费/合计_年均人数")
t.DataTable.DataCols.Add("名次", Gettype(Integer))
t.Cols.Remove("合计_投工","合计_人均加工费","合计_环比")
For Each r As Row In T.Rows
    For Each dc As DataCol In t.DataTable.DataCols
        If dc.name.IndexOf("人均加工费_")> -1 Then
            r(dc.name) =r(dc.name.Replace("人均",""))/r(dc.name.Replace("人均加工费","投工"))            
            If dc.name = "人均加工费_1" Then
                r("环比_1")=Nothing
            Else
                Dim n1 As Integer = Val(dc.name.split("_")(1))
                r("环比_" & n1)=r(dc.name)/r("人均加工费_" & n1-1)
            End If
        End If
        r("年人均加工费") = r("合计_加工费") /r("合计_年均人数")
    Next
Next

Dim drs As List(Of DataRow) = t.DataTable.Select("[单位] <> '合计'","年人均加工费 DESC")
For n As Integer = 0 To drs.Count - 1 '遍历所有行
    If n > 0 AndAlso drs(n)("年人均加工费") = drs(n-1)("年人均加工费") Then '如果年人均加工费和上一行相同
        drs(n)("名次") = drs(n-1)("名次") '则排名等于上一行
    Else
        drs(n)("名次") = n + 1 '设置名次
    End If
Next
For Each dc As DataCol In  t.DataTable.DataCols
    If dc.name <> "单位" Then
        t.DataTable.DataCols(dc.Name).SetFormat("0.00")
    End  If
Next
t.DataTable.DataCols("名次").SetFormat("0")
t.Cols("单位").TextAlign = TextAlignEnum.Center
t.Cols("名次").TextAlign = TextAlignEnum.Center
t.AutoSizeCols()
MainTable =t
[此贴子已经被作者于2011-7-12 19:04:10编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
yyzlxc
  25楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:七尾狐 帖子:1525 积分:10580 威望:0 精华:0 注册:2008/9/24 11:16:00
  发帖心情 Post By:2011/7/12 19:16:00 [只看该作者]

非常感谢ybil老师的帮助,其代码让我大开眼界,效果也是我所期望的,看来要到这一步,自己还有很长的路要走,真是自己有幸碰到了大师,好感动!!

 

 


图片点击可在新窗口打开查看此主题相关图片如下:a.png
图片点击可在新窗口打开查看

 


 


图片点击可在新窗口打开查看此主题相关图片如下:b.png
图片点击可在新窗口打开查看

对照两张表,感觉动态生成的环比列还存在一点瑕疵,应该作一些调整,效果可能会更好,因为自己是生手,不知从何下手,也只能冒胆请ybil老师帮助改一下代码,再次衷心感谢!!


 回到顶部
帅哥哟,离线,有人找我吗?
yyzlxc
  26楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:七尾狐 帖子:1525 积分:10580 威望:0 精华:0 注册:2008/9/24 11:16:00
  发帖心情 Post By:2011/7/12 19:25:00 [只看该作者]

另外,动态载入数据的代码是在(报表年月)字符型的基础上完成的,我将数据类型改成整数型后,运行出错,无从下手,也一并提请老师,望请指教!!

 

'载入当月数据
If e.Form.Controls("ComboBox1").Value Is Nothing Then
    MessageBox.Show("请在右侧选择报表年月","提示")
    Return
End If
Dim ym As String = e.Form.Controls("ComboBox1").Value
Dim Filter As String = "报表年月 = '" & ym &  "'"
If user.Group = "填报" Then
   filter = filter & " And 单位 = '"  & user.name & "'"
End If
DataTables("日报源表").LoadFilter = filter
DataTables("日报源表").Load
'打开表返回最末行
With Tables("日报源表")
    .Position = .Rows.Count - 1
End With
'排序
Tables("日报源表").Sort = "单位,日期,报表年月"
Tables("日报源表").AutoSizeCols()


 回到顶部
帅哥哟,离线,有人找我吗?
ybil
  27楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:超级版主 帖子:521 积分:4910 威望:0 精华:7 注册:2008/9/2 22:22:00
  发帖心情 Post By:2011/7/12 22:45:00 [只看该作者]

'载入当月数据
.......
Dim Filter As String = "报表年月 = " & ym 
.......

年报:

'读取ComboBox2中的年份
Dim nf,s,sql As String 
nf = e.Form.Controls("ComboBox2").Value
If nf Is Nothing Then
    MessageBox.Show("请在右侧选择生成报表的年份","提示")
    Return
End If

'根据年份生成临时表
sql = "Select 报表年月,日期,单位,Sum(加工费) As 加工费,Sum(投工) As 投工,1 as 人均加工费,1 As 环比  FROM {日报源表} WHERE Year(日期) = " & nf & " Group By 报表年月,日期,单位"
'根据临时表生成年度汇总表
Dim b As New CrossTableBuilder("年度汇总",sql)
b.HGroups.AddDef("单位")
b.VGroups.AddDef("报表年月")
b.Totals.AddDef("加工费")
b.Totals.AddDef("投工",AggregateEnum.Average,"月均人数")
b.Totals.AddDef("人均加工费",AggregateEnum.Average,"人均加工费")
b.Totals.AddDef("环比",AggregateEnum.Average,"环比")
b.HorizontalTotal = True
b.VerticalTotal = True
b.Build()

Dim t As Table = Tables("年度汇总")
Dim i As Integer =(Tables("年度汇总").Cols.Count-5)/4

t.StopRedraw
t.DataTable.DataCols.Add("合计_年均人数", Gettype(Double),"[合计_投工]/" & i)
t.DataTable.DataCols.Add("年人均加工费", Gettype(Double),"合计_加工费/合计_年均人数")
t.DataTable.DataCols.Add("名次", Gettype(Integer))
t.Cols.Remove("环比_1","合计_投工","合计_人均加工费","合计_环比")
For Each r As Row In T.Rows
    For Each dc As DataCol In t.DataTable.DataCols
        If dc.name.IndexOf("人均加工费_")> -1 Then
            r(dc.name) =r(dc.name.Replace("人均",""))/r(dc.name.Replace("人均加工费","投工"))            
            If dc.name <> "人均加工费_1" Then                       
                Dim n1 As Integer = Val(dc.name.split("_")(1))
                r("环比_" & n1)=(r(dc.name)-r("人均加工费_" & n1-1))/r("人均加工费_" & n1-1)
            End If
        End If
        r("年人均加工费") = r("合计_加工费") /r("合计_年均人数")
    Next
Next

Dim drs As List(Of DataRow) = t.DataTable.Select("[单位] <> '合计'","年人均加工费 DESC")
For n As Integer = 0 To drs.Count - 1 '遍历所有行
    If n > 0 AndAlso drs(n)("年人均加工费") = drs(n-1)("年人均加工费") Then '如果年人均加工费和上一行相同
        drs(n)("名次") = drs(n-1)("名次") '则排名等于上一行
    Else
        drs(n)("名次") = n + 1 '设置名次
    End If
Next
For Each dc As DataCol In  t.DataTable.DataCols
    If dc.name <> "单位" AndAlso dc.name <> "名次" Then
        s="0.00" & iif(dc.name.Indexof("环比")>-1,"%","")
        t.DataTable.DataCols(dc.Name).SetFormat(s)
    End  If
Next

t.Cols("单位").TextAlign = TextAlignEnum.Center
t.Cols("名次").TextAlign = TextAlignEnum.Center
t.AutoSizeCols()
t.ResumeRedraw
MainTable =t
[此贴子已经被作者于2011-7-13 12:33:08编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
yyzlxc
  28楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:七尾狐 帖子:1525 积分:10580 威望:0 精华:0 注册:2008/9/24 11:16:00
  发帖心情 Post By:2011/7/13 8:50:00 [只看该作者]

谢谢ybil老师的热情帮助,所有问题都得到了圆满解决。对这段代码,我还需要好好消化,对ybil老师的无私帮助,再次表示衷心地感谢!!祝愿狐表论坛的明天更加灿烂辉煌。

 回到顶部
帅哥哟,离线,有人找我吗?
yyzlxc
  29楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:七尾狐 帖子:1525 积分:10580 威望:0 精华:0 注册:2008/9/24 11:16:00
  发帖心情 Post By:2011/7/20 0:43:00 [只看该作者]

根据ybil老师的代码,解决了在交叉表的垂直分组列中增加列的难题,并用外部数据源access文件顺利通过,全部达到预想效果。但是将外部数据源调整到SQL Server2005时,在运行此段代码时,出现错误提示(如下图),不知问题出在那里,希望各位老师帮助看看问题所在,不胜感谢!!

 附加说明:在运行三个月的数据时代码运行正常,并有结果,只是环比数据为0或1,但是运行十二个月的数据时出错。

 


图片点击可在新窗口打开查看此主题相关图片如下:b.jpg
图片点击可在新窗口打开查看

 

具体代码如下:

 

'年度汇总表
'读取ComboBox2中的年份
Dim nf,s,sql As String
nf = e.Form.Controls("ComboBox2").Value
If nf Is Nothing Then
    MessageBox.Show("请在右侧选择生成报表的年份","提示")
    Return
End If
'根据年份生成临时表
sql = "Select 报表年月,日期,单位,Sum(加工费) As 加工费,Sum(投工) As 投工,1 as 人均加工费,1 As 环比  FROM {日报源表} WHERE Year(日期) = " & nf & " Group By 报表年月,日期,单位"
'根据临时表生成年度汇总表
Dim b As New CrossTableBuilder("年度汇总",sql,"SCGL")
b.HGroups.AddDef("单位")
b.VGroups.AddDef("报表年月")
b.Totals.AddDef("加工费")
b.Totals.AddDef("投工",AggregateEnum.Average,"月均人数")
b.Totals.AddDef("人均加工费",AggregateEnum.Average,"人均加工费")
b.Totals.AddDef("环比",AggregateEnum.Average,"环比")
b.HorizontalTotal = True
b.VerticalTotal = True
b.Build()

Dim t As Table = Tables("年度汇总")
Dim i As Integer =(Tables("年度汇总").Cols.Count-5)/4
t.StopRedraw   '停止绘制表格
t.DataTable.DataCols.Add("合计_年均人数", Gettype(Double),"[合计_投工]/" & i)
t.DataTable.DataCols.Add("年人均加工费", Gettype(Double),"合计_加工费/合计_年均人数")
t.DataTable.DataCols.Add("名次", Gettype(Integer))
t.Cols.Remove("环比_1","合计_投工","合计_人均加工费","合计_环比")
For Each r As Row In T.Rows
    For Each dc As DataCol In t.DataTable.DataCols
        If dc.name.IndexOf("人均加工费_")> -1 Then
            r(dc.name) =r(dc.name.Replace("人均",""))/r(dc.name.Replace("人均加工费","投工"))
            If dc.name <> "人均加工费_1" Then
                Dim n1 As Integer = Val(dc.name.split("_")(1))
                r("环比_" & n1)=(r(dc.name)-r("人均加工费_" & n1-1))/r("人均加工费_" & n1-1)
            End If
        End If
        r("年人均加工费") = r("合计_加工费") /r("合计_年均人数")
    Next
Next

Dim drs As List(Of DataRow) = t.DataTable.Select("[单位] <> '合计'","年人均加工费 DESC")
For n As Integer = 0 To drs.Count - 1 '遍历所有行
    If n > 0 AndAlso drs(n)("年人均加工费") = drs(n-1)("年人均加工费") Then '如果年人均加工费和上一行相同
        drs(n)("名次") = drs(n-1)("名次") '则排名等于上一行
    Else
        drs(n)("名次") = n + 1 '设置名次
    End If
Next
For Each dc As DataCol In  t.DataTable.DataCols
    If dc.name <> "单位" AndAlso dc.name <> "名次" Then
        s="0.00" & iif(dc.name.Indexof("环比")>-1,"%","")
        t.DataTable.DataCols(dc.Name).SetFormat(s)
    End  If
Next
t.Cols("单位").TextAlign = TextAlignEnum.Center
t.Cols("名次").TextAlign = TextAlignEnum.Center
t.AutoSizeCols()
t.ResumeRedraw   '恢复绘制表格
MainTable =t
Tables("年度汇总").Cols.Frozen = 1 '冻结一列

[此贴子已经被作者于2011-7-20 11:18:05编辑过]

 回到顶部
帅哥哟,离线,有人找我吗?
狐狸爸爸
  30楼 | 信息 | 搜索 | 邮箱 | 主页 | UC


加好友 发短信
等级:管理员 帖子:47448 积分:251048 威望:0 精华:91 注册:2008/6/17 17:14:00
  发帖心情 Post By:2011/7/20 7:56:00 [只看该作者]

可能某个值太大,超出了integer的范围,请先找出出错代码是哪一行,然后再考虑解决方法。

 


 回到顶部
总数 51 上一页 1 2 3 4 5 6 下一页