代码改变世界

Reports Starter Kit详细介绍(二)

2006-05-28 14:57  Clingingboy  阅读(1954)  评论(1编辑  收藏  举报
         这次接着继续分析交叉分析报表和详情资料报表

1.交叉分析报表

交叉分析报表是根据不同的年份,然后根据不同的季度统计月份销售总额和各地区销售总额

先看下图



这个效果跟表格式报表有点相似,还是DataList镶套DataGrid

<asp:datalist id="QuartersList" runat="server" cellspacing="0" cellpadding="0">
                
<ItemTemplate>
                    
<TABLE cellSpacing="0" cellPadding="3" border="0">
                        
<TR>
                            
<TD class="textbold" colSpan="2">Quarter
                                
<%# Container.DataItem %>
                            
</TD>
                        
</TR>
                        
<TR>
                            
<TD colSpan="2"><IMG height="5" src="images/spacer.gif"></TD>
                        
</TR>
                        
<TR>
                            
<TD><IMG src="images/spacer.gif" width="30"></TD>
                            
<TD>
                                
<TABLE cellSpacing="0" cellPadding="0" border="0">
                                    
<asp:datagrid id=DataGrid1 runat="server" CssClass="Content" CellPadding="3" OnItemDataBound="SumItems" DataSource="<%# GetQuarterDetails((int)Container.DataItem) %>" ShowFooter="True" GridLines="None" AutoGenerateColumns="False" width="600">
                                        
<columns>
                                            
<asp:templatecolumn headertext="Month" itemstyle-cssclass="ItemStyle" headerstyle-cssclass="HeaderStyle"
                                                footerstyle-cssclass
="FooterStyle">
                                                
<itemtemplate>
                                                    
<%String.Format("{0:MMMM}",DataBinder.Eval(Container.DataItem, "OrderDate")) %>
                                                
</itemtemplate>
                                            
</asp:templatecolumn>
                                            
<asp:boundcolumn datafield="Eastern" headertext="Eastern" itemstyle-cssclass="ItemStyleRight" headerstyle-cssclass="HeaderStyleRight"
                                                footerstyle-cssclass
="FooterStyleRight"></asp:boundcolumn>.            </asp:datagrid></TABLE>
                            
</TD>
                        
</TR>
                        
<TR>                            <TD colSpan="2"><IMG height="10" src="images/spacer.gif"></TD>
                    
</TR>
                
</TABLE>
                
</ItemTemplate>
                
<HeaderStyle CssClass="ReportTitle"></HeaderStyle>
            
</asp:datalist>

DataList没有绑定数据库中的数据,而是绑定了一个数组,表示季节

1private void BindList()
2        {
3            QuartersList.DataSource = new int[41234 };
4            QuartersList.DataBind();
5        }

在前台显示的时候也没有绑定任何字段(下面的绑定我也有点模糊,为什么就不需要字段呢,但我测试过,是可以用的)
Quarter<%# Container.DataItem %>

然后DataGrid控件根据年份和季度来获取,因为绑定季度是固定不变的,所需要改变的只是年份而已

protected CrossTabReportCollection GetQuarterDetails(int quarter)
        
{
            
return CrossTabReport.GetRegionSales(quarter, Convert.ToInt32(YearDropDownList.SelectedItem.Value));
        }

DataSource="<%# GetQuarterDetails((int)Container.DataItem) %>

提取数据最关键的地方还是在存储过程这里.我第一眼看的时候发现有两个from子句,有点模糊,后来发现第一个From下面有一个"("

里面还存在一个select语句,是提取统计大多数字段,

大概意思是根据年份,季度获取各个区域的销售额,然后在季度中分组,其显示的效果就是DataGrid的效果

而外部的seleclt语句是为了定义一个TotalMoth,目的是获取月份地区销售额


ALTER PROCEDURE Reports_GetSalesByRegion
(
    
@Year int,
        
@Quarter int
)
AS
    
--销售总额为各个地区销售额的总和
    Select 
       
*, TotalMonth = Eastern + Western + Northern + Southern
From   
    (
    
--销售月份
    Select DatePart(month, OrderDate) MonthOfSales, 
    
--东部地区
    Sum(Case RegionID When 1 Then (UnitPrice * Quantity ) Else 0 EndAs Eastern,
    
--西部地区
    Sum(Case RegionID When 2 Then (UnitPrice * Quantity ) Else 0 EndAs Western,
    
--北部地区
    Sum(Case RegionID When 3 Then (UnitPrice * Quantity ) Else 0 EndAs Northern,
    
--南部地区
    Sum(Case RegionID When 4 Then (UnitPrice * Quantity ) Else 0 EndAs Southern
From Reports_Orders O
    
--地区
    Inner Join Reports_Territories T On O.TerritoryID = T.TerritoryID 
    
--订单详细
    Inner Join [Reports_Order Details] OD On O.OrderID = OD.OrderID
    
--年份,季节条件
    Where Year(OrderDate) = @Year And DatePart(q, OrderDate) = @Quarter
    
--按月份分组
    Group By DatePart(month, OrderDate)

As T
Order By MonthOfSales

我根据上面的语句改了一下,下面的语句看起来比较容易理解



ALTER PROCEDURE Reports_GetSalesByRegion
(
    
@Year int,
        
@Quarter int
)
AS
    
--销售总额为各个地区销售额的总和
    
    
--销售月份
    Select DatePart(month, OrderDate) MonthOfSales, 
    
    
--东部地区
    Sum(Case RegionID When 1 Then (UnitPrice * Quantity ) Else 0 EndAs Eastern,
    
--西部地区
    Sum(Case RegionID When 2 Then (UnitPrice * Quantity ) Else 0 EndAs Western,
    
--北部地区
    Sum(Case RegionID When 3 Then (UnitPrice * Quantity ) Else 0 EndAs Northern,
    
--南部地区
    Sum(Case RegionID When 4 Then (UnitPrice * Quantity ) Else 0 EndAs Southern,
    
Sum(UnitPrice * Quantity) As TotalMonth
    
From Reports_Orders O
    
--地区
    Inner Join Reports_Territories T On O.TerritoryID = T.TerritoryID 
    
--订单详细
    Inner Join [Reports_Order Details] OD On O.OrderID = OD.OrderID
    
--年份,季节条件
    Where Year(OrderDate) = @Year And DatePart(q, OrderDate) = @Quarter
    
--按月份分组
    Group By DatePart(month, OrderDate)




其他的实现,还有页脚统计区域销售额,格式化,同上次讲的例子实现方法相同
实现代码需写在Item_Created事件里面,由于镶套在DataList里,需要手动写代码.
以为我是认为是实现报表效果的关键

2,详细资料报表

详细资料报表中有两张表,一张表按年度,月份统计订单数和销售额,另一张表则显示全年或指定季度订单的信息




(1)当我们重新选择年份的时候,两张表均发生变化,此事件需要重新绑定两个表
当选择季度的时候,第一张表不变,只需绑定一个表

(2)为了保存查询数据,当重新绑定的时候,其中设置了两个Session.然后在Page_Load中判断

private void YearDropDownList_SelectedIndexChanged(object sender, System.EventArgs e)
        
{
            Session[_masterDetailYear] 
= YearDropDownList.SelectedItem.Value;
            BindSummary();
            BindDetails();
        }


        
private void QuarterDropDownList_SelectedIndexChanged(object sender, System.EventArgs e) 
        
{
            Session[_masterDetailQuarter] 
= QuarterDropDownList.SelectedItem.Value;
            BindDetails();
        }
 

其他效果,如页眉显示销售总额,实现方法差不多.下面还看存储过程怎么写.

上面我们讲的交叉分析报表是根据季度按月份分组,下面的则是根据年份按季度分组.道理是一样的.第一张表实现的关键就在于下面的存储过程.



ALTER PROCEDURE Reports_GetOrderSummary
(
    
@Year int
)
AS

--从订购日期中取季节
SELECT 
    
DATEPART(q, OrderDate) Quarter, 
    
--统计订单数
    COUNT(DISTINCT Reports_Orders.OrderID) OrdersShipped, 
    
--统计销售额
    SUM(UnitPrice * Quantity * (1-Discount)) Sales 
FROM Reports_Orders 
--订单表和订单明细表关联
    INNER JOIN [Reports_Order Details] Details 
        
ON Reports_Orders.OrderID = Details.OrderID 
--年份等于给定参数        
WHERE YEAR(OrderDate) =  @Year 
--按季节分组
GROUP BY DATEPART(q, OrderDate)



显示第二张表数据的存储过程


ALTER PROCEDURE Reports_GetOrdersAndDetails
(
    
@Year int,
    
@Quarter int
)    
AS

SELECT 
    Reports_Orders.OrderID,
    OrderDate,
    
--计算单张订单销售额
    SUM(UnitPrice * Quantity * (1-Discount)) Sales

FROM Reports_Orders 
    
INNER JOIN [Reports_Order Details] Details 
        
ON Reports_Orders.OrderID = Details.OrderID 

WHERE
--年度等于指定年度
    YEAR(OrderDate) = @Year AND
    (
@Quarter = 0 OR
    
--否则,只选取指定的季节
    DATEPART(q, OrderDate) = @Quarter)

GROUP BY
--按年份,订单ID,订购日期分组
    DATEPART(y, OrderDate),
    Reports_Orders.OrderID,
    OrderDate

wehre中有一个选择,表示如果下拉框中选择是All的话,则显示全部信息,否则根据季度显示

上面的几个存储过程多处用到了时间函数,如果不熟悉的话请,参考一下帮助文件.

以上就是我对两个报表的分析.本人表达能力不强.希望对看到此文的人有帮助.也望大家指出错误