データを扱っていると、たまに処理上重複データを取り除いたりする必要があったります。
SQLでデータを取得する場合は、事前にdistinctするなどできますが、内部で作成したデータの
場合はそうもいきません。
そんな時、DataViewを使うと楽な場合があります。
以下のメソッドを利用すると重複行を取り除いた新たなデータテーブルを返してくれます。
DataView.ToTable(string, bool, string[])
第二引数にtrueを渡すと、重複行が取り除かれます。
てことで、以下、サンプルです。
// vim:set ts=4 sw=4 et ws is nowrap ft=cs: using System; using System.Data; using System.Data.Common; using System.Drawing; using System.Windows.Forms; namespace Gsf.Demo{ public class DemoForm : Form{ Button btnDoFilter; Button btnDoDistinct; DataGridView grdMain; DataTable _table; DataView _view; BindingSource _dataSource; public DemoForm(){ InitializeComponent(); InitializeControlData(); InitializeEventSettings(); InitializeDataBindings(); } protected void InitializeComponent(){ SuspendLayout(); Text = "DataView Sample"; Size = new Size(600, 400); StartPosition = FormStartPosition.CenterScreen; btnDoFilter = new Button(); btnDoFilter.Text = "Do Filter"; btnDoFilter.Location = new Point(0, 0); btnDoDistinct = new Button(); btnDoDistinct.Text = "Do Distinct"; btnDoDistinct.Location = new Point*1; Controls.AddRange(new Control{btnDoFilter, btnDoDistinct, grdMain}); ResumeLayout(); } protected void InitializeControlData(){ _table = new DataTable("SAMPLE_DATA"); _table.Columns.Add("ID", typeof(int)); _table.Columns.Add("NAME"); _table.Columns.Add("AGE", typeof(int)); DataRow newRow = null; for(int i = 0; i < 1000; i++){ newRow = _table.NewRow(); newRow.ItemArray = new object{ i, string.Format("gsf_zero{0}", i), (i + 1) }; _table.Rows.Add(newRow); } _view = new DataView(_table); _dataSource = new BindingSource(_view, ""); } protected void InitializeEventSettings(){ btnDoFilter.Click += (s, e) => { if(string.IsNullOrEmpty(_view.RowFilter)){ _view.RowFilter = "ID > 500 AND ID <= 510"; }else{ _view.RowFilter = string.Empty; } }; btnDoDistinct.Click += (s, e) => { // // 現在表示しているビュー上の重複する行を取り除いて表示する。 // // 本イベントハンドラは以下の動作を行います。 // // 1.現在表示されているデータテーブルが元のデータテーブルの場合 // ⇒現在表示しているビューデータから重複行を取り除いたデータを表示. // 2.現在表示されているデータテーブルが元のデータテーブルと違う場合 // ⇒元のデータテーブルに戻す. // DataTable currentTable = _view.Table; if(currentTable.TableName == _table.TableName){ // // 重複行判定対象となるカラム名の配列を作成. // (ここで指定するカラム名が重複判定対象列であると共にToTableメソッドにて // 返却される列になります。) // string[] colNames = new string[_table.Columns.Count]; for(int i = 0; i < _table.Columns.Count; i++){ colNames[i] = _table.Columns[i].ColumnName; } // // 重複行を取り除いた新たなデータテーブルを抽出. // bool isDistinct = true; DataTable filteredTable = _view.ToTable("FILTERED_TABLE", isDistinct, colNames); // // 抽出したデータテーブルを新たなデータテーブルとする。 // _view.Table = filteredTable; }else{ _view.Table = _table; } }; grdMain.DataError += (s, e) => { MessageBox.Show(e.Exception.Message); }; } protected void InitializeDataBindings(){ grdMain.DataSource = _dataSource; } [STAThread] static void Main(){ Application.EnableVisualStyles(); Application.Run(new DemoForm()); } } }
上記をコンパイルして実行すると、画面が起動します。
ボタンが2つありまして、Do Filterボタンを押下すると行フィルターが
適用されます。
また、Do Distinctボタンをすると現在の表示データから重複行を取り除いた
データとなります。
*1:btnDoFilter.Width + 10), 0); grdMain = new DataGridView(); grdMain.AutoGenerateColumns = true; grdMain.EditMode = DataGridViewEditMode.EditOnEnter; grdMain.Size = new Size(500, 300); grdMain.Location = new Point(0, (btnDoDistinct.Height + 10