一覧形式のデータを扱う際、最も便利なDataTableクラスについての解説と、基本的な使い方について解説したいと思います。
DataTableは表形式のデータを扱うクラス
行と列で構成された一覧形式のデータ形式を管理するためのクラスがDataTableです。
特長として
- データベースからのデータ読み込み、データベースへのデータ書き込みが簡単に行える
- DataTable内に保持されているデータは、XML形式のテキストファイルとして保存、及び読み込みができる。
- DataGridViewと関連づける事で、DataTable内に保持されているデータを表示したり、DataGridViewの操作による変更内容を、自動でDataTableに反映してくれる。
- 表示内容のフィルタリング機能を持っており、指定した条件に合うデータだけを絞り込むことが出来る。
- DataTableにデータ(行)を登録した時点で、自動的にオリジナルの値が別領域に保持されるので、変更・追加・削除した内容を元に戻すことが可能。
- 各セルごとにオリジナルと現在の値、その他管理用情報等を保持しているため、メモリ消費量が元のデータの2倍以上必要になる。
といった事が挙げられます。
メモリの消費量は大きいが、便利な機能が豊富であるため、一覧形式のデータを扱うクラスとして重宝されています。
さて、このDataTableは、DataRowとDataColumnという2つのクラスの集合体になっていますので、DataTableを理解するには、この2つのクラスを理解しておく必要があります。
DataRowとDataColumnクラス
一覧表の行を保持するクラスとして、DataRowが用意されています。
また、セルを保持するクラスとして、DataColumnが用意されています。
DataRowとDataColumnの関係は下図の様になっており、1つのDataRowクラスの中に複数のDataColumnが格納されています。
Rowsプロパティ
DataTableクラスは、複数のDataRowを一まとめに管理するクラスです。
DataTableのプロパティにRowsというのがあり、ここに複数のDataRowを保持する構造になっています。
このRowsプロパティには、DataRowCollectionというクラスが入っていて、実際にはDataRowCollectionクラスが複数のDataRowを管理しています。
これを図で表すと以下のようになります。
1つ1つのDataRowクラスには、複数のDataColumnクラスが配列の様に格納されていて、これをDataTableが束ねてしているというイメージです。
Columnsプロパティ
DataRowCollectionが複数のDataRowを管理していると言いましたが、DataTableはColumns プロパティで列の情報、すなわちDataColumnを管理しています。
そしてRowsプロパティと同様に、ColumnsプロパティにはDataColumnCollectionが格納されており、このDataColumnCollectionが複数のDataColumnの情報を管理する構造になっています。
Column.ADDとRows.ADD
DataTableは、あらかじめ列を追加してから、行を追加していくという手順が必要になります。
まず、最初に new DatatTable() で空のクラスを作成してから、DataTableのColumnsプロパティに対して、Addメソッドで列を追加します。
下記は4つの列を追加するサンプルソースです。
1 2 3 4 5 |
DataTable dt = new DataTable(); dt.Columns.Add("カテゴリ"); dt.Columns.Add("アプリ"); dt.Columns.Add("ID"); dt.Columns.Add("パスワード"); |
Addメソッドには第2引数があって、変数の型を指定できます。
特に何も指定しなければ、何でも入るobject型が自動的に採用されます。
では、次に行を追加しましょう。
Rowsプロパティに対して、Addメソッドを呼び出すことにより、空の行が追加できます。
1 |
dt.Rows.Add(); |
AddRowメソッドを呼び出すと、DataColumnCollectionに登録されているDataColumnの名前と型でセルと行を作り、DataRowCollectionに登録してくれます。
もう1つの方法として、 NewRow メソッドを使うことも出来ます。
こちらは 空の列を持つDataRowを作るところまではやってくれますが、DataRowCollectionへの登録はしてくれません。
自分で dt.Rows.Add メソッドを使って登録する必要があります。
1 2 3 |
DataRow dr = dt.NewRow(); dt.Rows.Add(dr); |
こちらの方法は2ステップになるので、一見不便そうに見えますが、実はこちらの方法はよく使います。
というのは、NewRowメソッドで取得した空のDataRowに対して、データを入れやすいからです。
参考までに、Rows.ADDを使う例1~3と、NewRowを使う例の4パターンを作ってみました。
最初にRows.ADDを使ってしまうと、わざわざDataRowを取り出す作業が増えてしまいますが、NewRowを使うパターンだと、その作業が不要になるため、全体的にシンプルになります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 |
//Addメソッドを使う例1 dt.Rows.Add(); dt.Rows[dt.Rows.Count - 1]["カテゴリ"] = "画像"; dt.Rows[dt.Rows.Count - 1]["アプリ"] = "写真AC"; dt.Rows[dt.Rows.Count - 1]["ID"] = "hogehoge"; dt.Rows[dt.Rows.Count - 1]["パスワード"] = "#pass0123!"; //Addメソッドを使う例2 dt.Rows.Add(); int pos = dt.Rows.Count - 1; dt.Rows[pos]["カテゴリ"] = "画像"; dt.Rows[pos]["アプリ"] = "写真AC"; dt.Rows[pos]["ID"] = "hogehoge"; dt.Rows[pos]["パスワード"] = "#pass0123!"; //Addメソッドを使う例3 dt.Rows.Add(); DataRow dr = dt.Rows[dt.Rows.Count - 1]; dr["カテゴリ"] = "画像"; dr["アプリ"] = "写真AC"; dr["ID"] = "hogehoge"; dr["パスワード"] = "#pass0123!"; //NewRowメソッドを使う例 DataRow dr = dt.NewRow(); dr["カテゴリ"] = "画像"; dr["アプリ"] = "写真AC"; dr["ID"] = "hogehoge"; dr["パスワード"] = "#pass0123!"; dt.Rows.Add(dr); |
各セルへのアクセスの方法
DataTableの各セルへは、インデックス又は名前でアクセスが可能です。
どちらが良いという訳ではなく、それぞれメリット、デメリットがあります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 |
//インデックスを使う方法 DataRow dr = dt.NewRow(); dr[0] = "画像"; dr[1] = "写真AC"; dr[2] = "hogehoge"; dr[3] = "#pass0123!"; dt.Rows.Add(dr); //名前を使う方法 DataRow dr = dt.NewRow(); dr["カテゴリ"] = "画像"; dr["アプリ"] = "写真AC"; dr["ID"] = "hogehoge"; dr["パスワード"] = "#pass0123!"; dt.Rows.Add(dr); |
インデックスを使う方法は、ループ処理の中で値を設定する場合に便利ですが、列の並びが変わると予期せぬ列(セル)に予期せぬ値が格納される心配があります。
逆に、名前をしていする場合は、列の並びが変わっても影響は受けませんが、列名が変わると影響を受けますし、いちいち名前を書くのも面倒です。
従って、ケースバイケースで使い分けて頂く必要があります。
DataGridVIewとの連携
DataGridView に連携する場合、DataGridViewのDataSourceプロパティにDataTableを代入するだけで完了です。
このサンプルでは、uxIdPasswordGrid という名前のDataGridViewコントロールに、DataTableを代入しています。
1 |
uxIdPasswordGrid.DataSource = dt; |
この操作を行う事で、DataGridViewからデータを変更、追加、削除した内容が、自動的にDataTableにも反映されるようになります。
データのフィルタリングとソート
DataTableの内容を絞り込みしたい場合、DataTableのDefaultView プロパティを使います。
DefaultViewプロパティにはDataViewというクラスが登録されていて、このクラスが持つRowFIlterプロパティに絞り込み条件を設定します。
DataViewクラスには、Sortプロパティがあり、ここにソート項目を設定できます。
下記の例は、”カテゴリ”という名前を持つ列(DataColumn)に対して、”画像” が登録されているDataRowだけ抽出し、カテゴリ、サイト名の順でソートをするサンプルです。
1 2 |
dt.DefaultView.RowFilter = "カテゴリ='画像'"; dt.DefaultView.Sort = "カテゴリ,サイト名"; |
RowFilterに記述する条件はデータベースからデータを抽出する際に使われるSQLによく似た書き方をします。
値が文字列の場合はシングルクォート で囲みますが、数値の場合はその必要はありません。
like 演算子を使う事で、前方一致、後方一致、曖昧検索を行うことが出来ます。
演算子 | 説明 |
---|---|
= | 指定した値と等しい |
<> | 指定した値と等しくない |
< | 指定した値より小さい |
> | 指定した値より大きい |
<= | 指定した値以上 |
=> | 指定した値以下 |
Is Null | 値がNull |
Like | ド値が指定したパターンと一致する 任意の複数文字はパーセント(%) 任意の一文字はアンダースコア(_) 前方一致の例: Like '画像%' 後方一致の例: Like '%画像' 曖昧検索の例: Like '%画像%' |
NOT | 条件を否定。 NOT Like 、Is NOT Like など |
AND | 指定したすべての条件を満たすレコードを抽出 |
OR | 指定した条件のどれかひとつを満たすレコードを抽出 |
また、組み込み関数として文字列の長さを取得する len(列名) が使えます。
1 |
len(商品名) > 5 |
データの保存と読み込み
DataTableが保持している内容は、WriteXmlメソッドでファイル書き込み、ReadXmlメソッドでファイル読み込みが出来ます。
1 2 |
dt.WriteXml("idpass.xml"); dt.ReadXml("idpass.xml"); |
ファイルはXML形式で保存されますが、テキスト形式なのでテキストエディタでの編集が可能です。
下記は、保存したファイルのサンプルです。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 |
<?xml version="1.0" standalone="yes"?> <DocumentElement> <IdPass> <カテゴリ>画像サイト</カテゴリ> <アプリ_x002F_サイト名>写真AC</アプリ_x002F_サイト名> <ID>hogehoge</ID> <パスワード>123@5533</パスワード> </IdPass> <IdPass> <カテゴリ>画像サイト</カテゴリ> <アプリ_x002F_サイト名>パクソタ</アプリ_x002F_サイト名> <ID>areare</ID> <パスワード>1335=!aj3Gs</パスワード> </IdPass> <IdPass> <カテゴリ>画像サイト</カテゴリ> <アプリ_x002F_サイト名>モデルフォト</アプリ_x002F_サイト名> <ID>modemode</ID> <パスワード>as11322fasdfs</パスワード> </IdPass> <IdPass> <カテゴリ>通販サイト</カテゴリ> <アプリ_x002F_サイト名>楽天</アプリ_x002F_サイト名> <ID>rakuraku</ID> <パスワード>1#%#9s125taj-^#</パスワード> </IdPass> <IdPass> <カテゴリ>通販サイト</カテゴリ> <アプリ_x002F_サイト名>アマゾン</アプリ_x002F_サイト名> <ID>amaama</ID> <パスワード>2234#%%12323#</パスワード> </IdPass> </DocumentElement> |