交叉表的简单实现2:使用前端程序实现

上篇介绍了 交叉表的简单实现1:使用存储过程,这里采取在前端程序实现。
实现要点:
1。读取所有目标成绩(flatScroreTable)
2。从目标成绩中提取考试时间(不重复),作为交叉表的列表头
3。从目标成绩中提取考试科目(不重复),作为交叉表的行表头
4。根据2动态构建一个DataTable(crossScroreTable),此DataTable具有一个科目列,若干考试时间列,以及其他信息。
5。将3中的考试科目写入DataTable
6。从flatScroreTable中读取成绩值填入crossScroreTable对应单元格
说明:便于理解,这里将交叉表crossScroreTable想象成一张Excel表,列名就当作列表头,科目名就当作行表头。

主要代码:
void LoadScoreData()
{
读取指定学生的所有成绩#region读取指定学生的所有成绩
stringstuName=drpStu.SelectedValue;
stringconnStr="SERVER=.;DATABASE=DemoLib;UID=sa";
stringsql="SELECTSubjectName,StudentName,ScoreValue,ExamDateFROMt_ScoreWHEREStudentName=@StuName";
DataSetds
=newDataSet();
SqlDataAdapterda
=newSqlDataAdapter(sql,connStr);
da.SelectCommand.CommandType
=CommandType.Text;
da.SelectCommand.Parameters.Add(
"@StuName",stuName);
da.Fill(ds,
"FlatScore");
#endregion
读取指定学生的所有成绩

DataTableflatScoreTable
=ds.Tables[0];
DataViewflatScoreView
=newDataView(flatScoreTable);
//读取科目列表,排除重复
DataTablesubjectList;
//.NET2usingtheToTablemethodsupportedbyDataView
//subjectList=flatScoreView.ToTable("SubjectList",true,"SubjectName");
subjectList=SelectDistinct(flatScoreTable,"SubjectList",true,"SubjectName");
//读取考试时间列表,排除重复
//.NET2
DataTableexamDateList;
//.NET2usingtheToTablemethodsupportedbyDataView
//examDateList=flatScoreView.ToTable("ExamDateList",true,"ExamDate");
examDateList=SelectDistinct(flatScoreTable,"ExamDateList",true,"ExamDate");

创建交叉表#region创建交叉表
DataTablecrossScoreTable
=newDataTable();

构造表模式#region构造表模式
//科目列
crossScoreTable.Columns.Add("科目",typeof(string));
//考试时间列,以时间为列名
foreach(DataRowrinexamDateList.Rows){
crossScoreTable.Columns.Add(((DateTime)r[
0]).ToString("yyyy年M月dd日"),typeof(string));
}

#endregion
构造表模式

从成绩表读取并写入数据#region从成绩表读取并写入数据
DataColumnCollectioncols
=crossScoreTable.Columns;
//按先科目(行)后时间(列)遍历
foreach(DataRowrinsubjectList.Rows){
DataRownewRow
=crossScoreTable.NewRow();
//科目
newRow[0]=r[0];
//成绩,遍历时间
for(inti=1;i<cols.Count;i++){
//返回具有指定科目和指定考试的成绩
//eg."SubjectName='孙光'ANDExamDate='2007-5-19'"
flatScoreView.RowFilter=String.Format("SubjectName='{0}'ANDExamDate='{1}'",r[0],examDateList.Rows[i-1][0]);
if(flatScoreView.Count>0){
newRow[cols[i]]
=flatScoreView[0]["ScoreValue"];
}

}

//加入新表
crossScoreTable.Rows.Add(newRow);
}

#endregion
从成绩表读取并插入数据

#endregion
创建交叉表

//绑定,输出数据
grdCrossScore.DataSource=crossScoreTable;
grdCrossScore.DataBind();
grdFlatScore.DataSource
=flatScoreTable;
grdFlatScore.DataBind();
grdSubjectList.DataSource
=subjectList;
grdSubjectList.DataBind();
grdExamDate.DataSource
=examDateList;
grdExamDate.DataBind();
}

看下这个方法:
DataTableSelectDistinct(DataTablesourceTable, string newTableName, bool distinct, params string []columnNames)
扩展 ADO.NET 1.x 中DataTable 以及 DataView 均无法支持的:SELECT DISTINCT Column1,Column2.... 语法,(选择不重复的行)
如果 ADO.NET 2.0 中我们就可以直接使用 DataView 的 ToTable 方法的重载版本:
public DataTableToTable( bool distinct, params string []columnNames);

public DataTableToTable( string tableName, bool distinct, params string []columnNames);

SelectDistinct 网上有很多版本,原理基本一样,只是效率问题,这里是修改于 Erik Porter 的 Select DISTINCT on DataTable

SelectDistinct完整代码:

<!--<br><br>Code highlighting produced by Actipro CodeHighlighter (freeware)<br>http://www.CodeHighlighter.com/<br><br>-->implementssuchas'SELECTDISTINCTColumn0,Column1'sqlclauseforDataTable.#regionimplementssuchas'SELECTDISTINCTColumn0,Column1'sqlclauseforDataTable.
/**//*
*Theimplementdetailrefersto
http://weblogs.asp.net/eporter/archive/2005/02/10/370548.aspx.ManythankstoErikPorter.
*NOTE:The.NET2.0'sDataViewprovideraToTablemethodthatwillbuildaDataTablebasedoffofthecurrentDataViewand
*alsoallowyoutospecifywhichcolumnsyouwantintheDataTableasallasbeingabletosayDistinctrowsonly.
*So,recommendstoconsumetheoverridemethoddirectlyasfollowing:
*<example>
*DataTablesrcTable;
*//
*DataViewsrcView=srcTable.DefaultView;
*DataTabledstTable=srcView.ToTable("NewTableName",true,"ColumnName1","ColumnName2","ColumnNameN");
*</example>
*/


privatestaticDataTableSelectDistinct(DataTablesourceTable,stringnewTableName,booldistinct,paramsstring[]columnNames)
{
object[]lastValues;
DataTablenewTable;
DataRow[]orderedRows;

if(columnNames==null||columnNames.Length==0)
thrownewArgumentNullException("columnNames");

lastValues
=newobject[columnNames.Length];
newTable
=newDataTable();

for(inti=0;i<columnNames.Length;i++){
DataColumncolumn
=sourceTable.Columns[columnNames[i]];
if(column==null){
thrownewArgumentException(
String.Format(
"Thespecifiedcolumn(columnNames[{0}]withvalueof'{1}')isnotinthesourceTable.",i.ToString(),columnNames[i]),
"columnNames");
}

newTable.Columns.Add(columnNames[i],column.DataType);
}


orderedRows
=sourceTable.Select("",string.Join(",",columnNames));

if(distinct){
foreach(DataRowrowinorderedRows){
if(!ColumnValuesAreEqual(lastValues,row,columnNames)){
newTable.Rows.Add(CreateRowClone(row,newTable.NewRow(),columnNames));

SetLastValues(lastValues,row,columnNames);
}

}

}

else{
foreach(DataRowrowinorderedRows){
newTable.Rows.Add(CreateRowClone(row,newTable.NewRow(),columnNames));
}

}

returnnewTable;
}


privatestaticboolColumnValuesAreEqual(object[]lastValues,DataRowcurrentRow,string[]columnNames)
{
boolareEqual=true;

for(inti=0;i<columnNames.Length;i++){
if(lastValues[i]==null||!lastValues[i].Equals(currentRow[columnNames[i]])){
areEqual
=false;
break;
}

}


returnareEqual;
}


privatestaticDataRowCreateRowClone(DataRowsourceRow,DataRownewRow,string[]columnNames)
{
foreach(stringfieldincolumnNames){
newRow[field]
=sourceRow[field];
}


returnnewRow;
}


privatestaticvoidSetLastValues(object[]lastValues,DataRowsourceRow,string[]columnNames)
{
for(inti=0;i<columnNames.Length;i++){
lastValues[i]
=sourceRow[columnNames[i]];
}

}


#endregion

说明:由于朋友要求是在 1.1 环境下,所以只有自己写SelectDistinct,只有用DataGrid演示了^_^
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值