一种常见(粒度,统计值)报表的实现方案
语言:C#
开发环境:Vs2008
1。实现目标
很多时候,我经常要做如下这样的一张报表:
纵向为统计粒度,横向为指标值,本例中合计是没有意义的,只是为了演示
2。具体实现
从数据库中取出三张表(DataTable):
表1,命名为:VTable,作用:保存纵向统计力度的名称列表
表2,命名为:HTable,作用:保存横向指标的名称列表
表3,命名为:CellTable,作用:保存指标值
然后将三张表合在一个DataSet里,通过DataSet的GetXml()方法取得一个XML字符串,
这样,有了这个Xml字符串,配上通用的Xslt,就可以使用Asp:Xml控件进行展现
以下开始演示:
我建了三张表:StudentInfo, SubjectInfo, ScoreInfo
结合上图,很容易知道三张表各自的用途
看下面取DataSet数据源的代码:
有几个约定:表名(VTable,HTable,CellTable),列名(VName,HName,CellValue)
再看下面的XSLT:
通过Asp:Xml控件(x1)展现:
搞定!
这样,当需要做这样的报表的时候,只需要写3条非常简单的sql语句就完成了。
^_^
开发环境: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;
}
}
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]) > 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中计算了合计值<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]) > 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>
通过Asp:Xml控件(x1)展现:
private void ShowData() {
DataSet ds = this.GetDataSet();
string xml = ds.GetXml();
x1.DocumentContent = xml;
x1.TransformSource = "HVReport.xslt";
}
DataSet ds = this.GetDataSet();
string xml = ds.GetXml();
x1.DocumentContent = xml;
x1.TransformSource = "HVReport.xslt";
}
搞定!
这样,当需要做这样的报表的时候,只需要写3条非常简单的sql语句就完成了。
^_^