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

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

主要代码:
void LoadScoreData()
    
{
        
读取指定学生的所有成绩 读取指定学生的所有成绩

        DataTable flatScoreTable 
= ds.Tables[0];
        DataView flatScoreView 
= new DataView(flatScoreTable);
        
// 读取科目列表,排除重复
        DataTable subjectList;
        
// .NET 2 using the ToTable method supported by DataView
        
//subjectList = flatScoreView.ToTable("SubjectList", true, "SubjectName");        
        subjectList = SelectDistinct(flatScoreTable, "SubjectList"true"SubjectName");        
        
// 读取考试时间列表,排除重复
        
// .NET 2
        DataTable examDateList;
        
// .NET 2 using the ToTable method supported by DataView
        
//examDateList = flatScoreView.ToTable("ExamDateList", true, "ExamDate");        
        examDateList = SelectDistinct(flatScoreTable, "ExamDateList"true"ExamDate");        
       
        
#region 创建 交叉表
        DataTable crossScoreTable 
= new DataTable();
        
        
#region 构造表模式
        
// 科目 列
        crossScoreTable.Columns.Add("科目"typeof(string));
        
// 考试时间 列,以时间为列名
        foreach (DataRow r in examDateList.Rows) {
            crossScoreTable.Columns.Add(((DateTime)r[
0]).ToString("yyyy年M月dd日"), typeof(string));
        }

        
#endregion
 构造表模式
        
        
#region 从成绩表读取并写入数据        
        DataColumnCollection cols 
= crossScoreTable.Columns;
        
// 按先科目(行)后时间(列)遍历        
        foreach (DataRow r in subjectList.Rows){
            DataRow newRow 
= crossScoreTable.NewRow();
            
// 科目
            newRow[0= r[0];
            
// 成绩,遍历时间
           for(int i=1; i< cols.Count; i++{
               
// 返回具有指定科目和指定考试的成绩
               
// eg. "SubjectName='孙光' AND ExamDate='2007-5-19'"
               flatScoreView.RowFilter = String.Format("SubjectName='{0}' AND ExamDate='{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();
    }

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

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

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

SelectDistinct完整代码:

#region implements such as 'SELECT DISTINCT Column0, Column1' sql clause for DataTable. 
    
/*
     * The implement detail refers to 
http://weblogs.asp.net/eporter/archive/2005/02/10/370548.aspx. Many thanks to Erik Porter.
     * NOTE:The .NET 2.0's DataView provider a ToTable method that will build a DataTable based off of the current DataView and 
     *      also allow you to specify which columns you want in the DataTable as all as being able to say Distinct rows only.
     *      So, recommends to consume the override method directly as following:
     *      <example>
     *      DataTable srcTable;
     *      // 
     *      DataView srcView = srcTable.DefaultView;
     *      DataTable dstTable = srcView.ToTable("NewTableName", true, "ColumnName1", "ColumnName2", "ColumnNameN");
     *      </example>
    
*/


    
private static DataTable SelectDistinct(DataTable sourceTable, string newTableName, bool distinct, params string[] columnNames)
    
{
        
object[] lastValues;
        DataTable newTable;
        DataRow[] orderedRows;

        
if (columnNames == null || columnNames.Length == 0)
            
throw new ArgumentNullException("columnNames");

        lastValues 
= new object[columnNames.Length];
        newTable 
= new DataTable();

        
for (int i = 0; i < columnNames.Length; i++{            
            DataColumn column 
= sourceTable.Columns[columnNames[i]];
            
if (column == null{
                
throw new ArgumentException(
                    String.Format(
"The specified column (columnNames[{0}] with value of '{1}') is not in the sourceTable.", i.ToString(), columnNames[i]),
                    
"columnNames");
            }

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


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

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

                    SetLastValues(lastValues, row, columnNames);
                }

            }

        }

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

        }

        
return newTable;
    }


    
private static bool ColumnValuesAreEqual(object[] lastValues, DataRow currentRow, string[] columnNames)
    
{
        
bool areEqual = true;

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

        }


        
return areEqual;
    }


    
private static DataRow CreateRowClone(DataRow sourceRow, DataRow newRow, string[] columnNames)
    
{
        
foreach (string field in columnNames) {
            newRow[field] 
= sourceRow[field];
        }


        
return newRow;
    }


    
private static void SetLastValues(object[] lastValues, DataRow sourceRow, string[] columnNames)
    
{
        
for (int i = 0; i < columnNames.Length; i++{
            lastValues[i] 
= sourceRow[columnNames[i]];
        }

    }


    
#endregion

说明:由于朋友要求是在 1.1 环境下,所以只有自己写SelectDistinct,只有用DataGrid演示了^_^
 
版权声明:本文为博主原创文章,未经博主允许不得转载。

相关文章推荐

qt 写的tcp客户端程序实现简单的连接接受和发送消息

自己写的一个客户端程序,源码的连接http://download.csdn.net/detail/qq_28637193/9615451 界面是这样的。注意在pro文件中需要加入 QT += netw...

java程序实现md5加密功能(2)

源代码如下所示:public class MD5 { /* 下面这些S11-S44实际上是一个4*4的矩阵,在原始的C实现中是用#define 实现的, 7. 这里把它们实现成为static ...

用递归算法写一段程序实现 1+2+...+1000000 、java.lang.StackOverflowError 异常,原因,bug调查,处理

Exception in thread "main" java.lang.StackOverflowError 题目原来是:用递归算法写一段程序实现 1+2+...+1000000 然后,简单吗,就...

VC++信息安全编程(2)分析程序实现自我删除

很多时候,我们制作自动安装程序,安装完成以后自动删除,软件仅仅安装一次就自动删除,以保护软件知识产权。软件自动删除的代码是如何实现的呢,我们来看下#ifdef _DEBUG #define new D...

java 二进制 文件I/O 2进制和10进制的转换 程序实现 以及移位

1详细二进制 (主要是用于基本i/o流) #二进制: 1、计算机内部都是2进制 2、数组和ArrayList的区别:ArrayLlsit里面有算法(通用算法,只有当通用算法不行的时候,可以自己...

SDK学习笔记2-一个Win32窗口程序实现过程

Win32程序实现的步骤: WinMain函数的定义 创建一个窗口 1. 设计一个窗口类 2. 注册窗口类 3. 创建窗口 4. 显示及刷新窗口进行消息循环 完成回调函数 //WinMain...

Android应用程序实现自动更新功能2_客户端实现

上一篇配置好

简单的学生信息处理程序实现(C++程序设计第2周)

简单的学生信息处理程序实现 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩。) 注意: 总时间限制: 1000ms 内存限制: 65536...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)