一种常见(粒度,统计值)报表的实现方案

语言:C#
开发环境:Vs2008

1。实现目标
很多时候,我经常要做如下这样的一张报表:
纵向为统计粒度,横向为指标值,本例中合计是没有意义的,只是为了演示

2。具体实现
从数据库中取出三张表(DataTable):
表1,命名为:VTable,作用:保存纵向统计力度的名称列表
表2,命名为:HTable,作用:保存横向指标的名称列表
表3,命名为:CellTable,作用:保存指标值

然后将三张表合在一个DataSet里,通过DataSet的GetXml()方法取得一个XML字符串,
这样,有了这个Xml字符串,配上通用的Xslt,就可以使用Asp:Xml控件进行展现

以下开始演示:
我建了三张表:StudentInfo, SubjectInfo, ScoreInfo
结合上图,很容易知道三张表各自的用途



看下面取DataSet数据源的代码:
private DataSet GetDataSet() {
            
string sql1 = "select StudentName VName from StudentInfo";
            
string sql2 = "select SubjectName HName from SubjectInfo";
            
string sql3 = @"select StudentName VName,SubjectName HName,Score CellValue
                            from ScoreInfo s, StudentInfo std,SubjectInfo subj
                            where s.StudentId=std.StudentId and s.SubjectId=subj.SubjectId
";
            DataSet ds 
= new DataSet();
            
using (SqlConnection conn = new SqlConnection(ConfigurationManager.ConnectionStrings["DbConnString"].ConnectionString)) {
                conn.Open();
                SqlDataAdapter da 
= new SqlDataAdapter(sql1, conn);
                da.Fill(ds, 
"VTable");
                da 
= new SqlDataAdapter(sql2, conn);
                da.Fill(ds, 
"HTable");
                da 
= new SqlDataAdapter(sql3, conn);
                da.Fill(ds, 
"CellTable");
                
return ds;
            }

        }

有几个约定:表名(VTable,HTable,CellTable),列名(VName,HName,CellValue)

再看下面的XSLT:
<?xml version="1.0" encoding="UTF-8" ?>
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
  
<!--
    written by Guozhijian
    
2008/01/04
  
-->
  
<xsl:output method="html"/>
    
<xsl:template match="/">
        
<style type="text/css">
      .lborder3 
{border:1px solid #000000;font-family:Tahoma;font-size:12px;}
      .mbodymain 
{text-align:center;background-color:#ffffff;}
    
</style>
        
<table class="lborder3" cellpadding="3" cellspacing="1" align="center">
            
<xsl:call-template name="tplH"/>
            
<xsl:call-template name="tplV"/>
            
<xsl:call-template name="tplLastLine"/>
        
</table>
    
</xsl:template>
  
<!--横向表头模版-->
    
<xsl:template name="tplH">
        
<tr>
            
<td class="mbodyMain"></td>
            
<xsl:for-each select="NewDataSet/HTable">
                
<td class="mbodyMain">
                    
<xsl:value-of select="HName"/>
                
</td>
            
</xsl:for-each>
            
<td class="mbodyMain">合计</td>
        
</tr>
    
</xsl:template>
  
<!--纵向表头模版-->
    
<xsl:template name="tplV">
        
<xsl:for-each select="NewDataSet/VTable">
            
<tr>
                
<td class="mbodyMain"><xsl:value-of select="VName"/></td>
                
<xsl:variable name="vname" select="VName"/>
                
<xsl:for-each select="/NewDataSet/HTable">
                    
<td class="mbodyMain">
                        
<xsl:call-template name="tplCellValue">
                            
<xsl:with-param name="vName" select="$vname"/>
                            
<xsl:with-param name="hName" select="HName"/>
                        
</xsl:call-template>
                    
</td>
                
</xsl:for-each>
                
<td class="mbodyMain">
                    
<xsl:call-template name="tplHSum">
                        
<xsl:with-param name="vName" select="$vname"/>
                    
</xsl:call-template>
                
</td>
            
</tr>
        
</xsl:for-each>
    
</xsl:template>
  
<!--数据单元格模版-->
    
<xsl:template name="tplCellValue">
        
<xsl:param name="vName"/>
        
<xsl:param name="hName"/>
        
<xsl:choose>
            
<xsl:when test="count(/NewDataSet/CellTable[VName=$vName and HName=$hName]) &gt; 0">
                
<xsl:value-of select="/NewDataSet/CellTable[VName=$vName and HName=$hName]/CellValue"/>
            
</xsl:when>
            
<xsl:otherwise>0</xsl:otherwise>
        
</xsl:choose>
    
</xsl:template>
  
<!--横向统计值模版-->
    
<xsl:template name="tplHSum">
        
<xsl:param name="vName"/>
        
<xsl:value-of select="sum(/NewDataSet/CellTable[VName=$vName]/CellValue)"/>
    
</xsl:template>
  
<!--纵向统计值模版-->
    
<xsl:template name="tplVSum">
        
<xsl:param name="hName"/>
        
<xsl:value-of select="sum(/NewDataSet/CellTable[HName=$hName]/CellValue)"/>
    
</xsl:template>
  
<!--尾行统计值模版-->
    
<xsl:template name="tplLastLine">
        
<tr>
            
<td class="mbodyMain">合计</td>
            
<xsl:for-each select="NewDataSet/HTable">
                
<td class="mbodyMain">
                    
<xsl:call-template name="tplVSum">
                        
<xsl:with-param name="hName" select="HName"/>
                    
</xsl:call-template>
                
</td>
            
</xsl:for-each>
            
<td class="mbodyMain">
                
<xsl:value-of select="sum(NewDataSet/CellTable/CellValue)"/>
            
</td>
        
</tr>
    
</xsl:template>
</xsl:stylesheet>

  
在XSLT中计算了合计值

通过Asp:Xml控件(x1)展现:
private void ShowData() {
            DataSet ds 
= this.GetDataSet();
            
string xml = ds.GetXml();
            x1.DocumentContent 
= xml;
            x1.TransformSource 
= "HVReport.xslt";
        }

搞定!
这样,当需要做这样的报表的时候,只需要写3条非常简单的sql语句就完成了。
^_^
posted on 2008-01-04 17:10  Tristan(GuoZhijian)  阅读(2274)  评论(5编辑  收藏  举报