代码改变世界

微软BI 之SSRS 系列 - 实现 Excel 中图表结合的报表设计

2014-08-22 22:13  BIWORK  阅读(5372)  评论(0编辑  收藏  举报
来自群里面讨论的一个问题,EXCEL 中有类似于这样的图形,上面是 Chart, Chart X轴上的值正好就是下方 Table 的列头,这个在 SSRS 中应该如何实现?
 
SSRS 2008、2008RS,2012 中实际上没有这种对应的控件,我们通常想到的方式可能是上方一个单独的 Chart 图,下方一个 Table 然后合并在一起。但是这样会存在一些问题,因为 Chart 轴的值不是固定的,会随着聚合值的增加而扩展。并且对于表中的列头来说也没有办法完全能够和 Chart X 轴上的坐标对应在一条竖线上,一定会有偏差。
 
在 SSRS 中,我们可以通过一些技巧来实现类似于这样的效果。下面是我用 Column Chart 来展现的这种类似于 Excel 中的效果,虽然实现比较接近了,但我并不推荐这么做! 因为我们完全可以通过合理的变通,并使用其它的方式将这些数据展现的更加合理!  
 
原始测试数据 (AdventureWorksDW2012)就是一个简单的查询 - 
SELECT DPC.EnglishProductCategoryName,
    FIS.OrderDate,
    FIS.OrderDateKey,
    DD.CalendarYear,
    FIS.SalesOrderNumber,
    FIS.SalesOrderLineNumber,
    FIS.SalesAmount AS Internet_Sales
FROM FactInternetSales AS FIS
INNER JOIN DimProduct AS DP
ON FIS.ProductKey = DP.ProductKey
INNER JOIN DimProductSubcategory AS DPS
ON DP.ProductSubcategoryKey = DPS.ProductSubcategoryKey
INNER JOIN DimProductCategory AS DPC
ON DPS.ProductCategoryKey = DPC.ProductCategoryKey
INNER JOIN DimDate AS DD
ON FIS.OrderDate = DD.FullDateAlternateKey

新建报表和数据集 Dataset,选择 Matrix 行分组为 Product Category ,列分组为 Calendar year。

 
添加两个新行 - 选择 Outside Group - Above。
并删除第一行。
删除的时候只删除行,但是不要连组给删除了。
删除之后的样子就是这样的。
第二行是表头要显示的年份,第一行用作行内 Column Chart 图。
在第一行的这个位置插入 Data Bar,选择 Stacked Column。
 
填充 Stacked Column 中的聚合值,分组以及系列。
填充完毕后就可以看到大致的效果了,每一列都是从 Matrix 列分组展开的,而每一列当中的 Column Chart 的分组又依赖于当前的列分组中的年份。
自行做一些美化工作,包括格式化等等。
存在一个问题,不同的系列是出来了,但是无法区分各个系列与产品分类的关系。
思路是 - Chart 图中的颜色模板使用自定义的,然后使用自定义函数获取指定的颜色,这几种颜色需要和自定义模板中的颜色是一样的。
Private colorPalette As String() = {"SeaGreen", "Orange", "RoyalBlue"}
    Private count As Integer = 0
    Private mapping As New System.Collections.Hashtable()

    Public Function GetColor(ByVal groupingValue As String) As String
        If mapping.ContainsKey(groupingValue) Then
            Return mapping(groupingValue)
        End If

        Dim c As String = colorPalette(count Mod colorPalette.Length)
        count = count + 1
        mapping.Add(groupingValue, c)
        Return c
    End Function

报表的自定义函数。

 
设置 Stacked Column 图的自定义模板颜色。
 
选中 English Product Category 文本框,设置它的背景颜色,调用函数。
=Code.GetColor(Fields!EnglishProductCategoryName.Value)
最后,要做出这种效果还需要进一步的格式化,调整边框等操作使得这个 Stacked Column 像一个整体,而非单一的个体,这些美化的细节就不一一描述了。可以参考 天善学院微软SSRS2012报表课程 基础案例中的 - 案例6,案例13,案例18,案例24 以及 SSRS 报表设计提高篇中的报表美化与设计等案例。所以本文只讲解实现的流程,过于细节的设计技巧,包括一些聚合分组的概念,自定义函数等不是本文的重点。
对于文章开头看到的这种 Line Chart 形式可不可以做,也可以做,可以通过调整 Chart 区域折线的平面宽度使得几个独立的折线区域也连接成一个整体。但是像最左侧的 Y 轴线如何实现,几个产品不使用底线区分而要求使用 Chart 中自带的系列又该显示且不重复?这些都不是拖拖拽拽就可以实现的,这需要熟练掌握 SSRS 报表中的各种知识点和技能点,不同控件的组合使用技巧等。当然,如果就这个案例来说,假设实际开发中如果是我,我会拒绝设计这种样子的报表,因为上图很明显在阅读性和数据呈现上完全体现不出来像 Excel 展现出来的那种效果。
 
所以,在实际报表开发过程中,不能为了模仿而模仿,因为很有可能模仿成一个四不像。
 
吐吐口水吧! 在实际项目中,在引导客户改变已有使用习惯,适应新的适应习惯的过程中往往确实是伴着口水,Fighting 的,包括遭受到客户对自身能力的怀疑,这些在项目开发中都是很正常的。像有很多客户往往会提出他们认为很好实现但实则很难实现的一些效果要求必须实现,这些极端情况也是客观存在的。对于我来说,我也会遇到一些变态的和不合理的需求,但通常情况下我也会直接拒绝,坦诚告诉客户无法实现,因为它已经违背了 SSRS 自身特性。但同时我也会尝试拿出另多的替代的解决方案让客户来选择,这样客户通常会比较容易接受和妥协。就像出门从北京到上海出差,告诉他们飞机确实因为技术原因就是不能飞,在客户非要证明但又无法证明飞机就是能起飞的同时给他们选择高铁,汽车和自行车三选一,一般情况下客户还是会从中选择他最能够接受的一种最优方案,因为谁也耗不起时间。

更多 BI 文章请参看 BI 系列随笔列表 (SSIS, SSRS, SSAS, MDX, SQL Server)

如果觉得这篇文章看了对您有帮助,请帮助推荐,以方便他人在 BIWORK 博客推荐栏中快速看到这些文章。