DataTableの基礎と使い方

当ページのリンクには広告が含まれています。

一覧形式のデータを扱う際、最も便利な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つの列を追加するサンプルソースです。

DataTable dt = new DataTable();
dt.Columns.Add("カテゴリ");
dt.Columns.Add("アプリ");
dt.Columns.Add("ID");
dt.Columns.Add("パスワード");

Addメソッドには第2引数があって、変数の型を指定できます。

特に何も指定しなければ、何でも入るobject型が自動的に採用されます。

では、次に行を追加しましょう。

Rowsプロパティに対して、Addメソッドを呼び出すことにより、空の行が追加できます。

dt.Rows.Add();

AddRowメソッドを呼び出すと、DataColumnCollectionに登録されているDataColumnの名前と型でセルと行を作り、DataRowCollectionに登録してくれます。

もう1つの方法として、 NewRow メソッドを使うことも出来ます。

こちらは 空の列を持つDataRowを作るところまではやってくれますが、DataRowCollectionへの登録はしてくれません。

自分で dt.Rows.Add メソッドを使って登録する必要があります。

DataRow dr = dt.NewRow();
dt.Rows.Add(dr);

こちらの方法は2ステップになるので、一見不便そうに見えますが、実はこちらの方法はよく使います。

というのは、NewRowメソッドで取得した空のDataRowに対して、データを入れやすいからです。

参考までに、Rows.ADDを使う例1~3と、NewRowを使う例の4パターンを作ってみました。

最初にRows.ADDを使ってしまうと、わざわざDataRowを取り出す作業が増えてしまいますが、NewRowを使うパターンだと、その作業が不要になるため、全体的にシンプルになります。

//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の各セルへは、インデックス又は名前でアクセスが可能です。

どちらが良いという訳ではなく、それぞれメリット、デメリットがあります。


//インデックスを使う方法
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を代入しています。

uxIdPasswordGrid.DataSource = dt;

この操作を行う事で、DataGridViewからデータを変更、追加、削除した内容が、自動的にDataTableにも反映されるようになります。

データのフィルタリングとソート

DataTableの内容を絞り込みしたい場合、DataTableのDefaultView プロパティを使います。

DefaultViewプロパティにはDataViewというクラスが登録されていて、このクラスが持つRowFIlterプロパティに絞り込み条件を設定します。

DataViewクラスには、Sortプロパティがあり、ここにソート項目を設定できます。

下記の例は、”カテゴリ”という名前を持つ列(DataColumn)に対して、”画像” が登録されているDataRowだけ抽出し、カテゴリ、サイト名の順でソートをするサンプルです。

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(列名) が使えます。

len(商品名) > 5

データの保存と読み込み

DataTableが保持している内容は、WriteXmlメソッドでファイル書き込み、ReadXmlメソッドでファイル読み込みが出来ます。

dt.WriteXml("idpass.xml");
dt.ReadXml("idpass.xml");

ファイルはXML形式で保存されますが、テキスト形式なのでテキストエディタでの編集が可能です。

下記は、保存したファイルのサンプルです。

<?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>

まとめ

今回は、表形式のデータを扱う際によく使われるDataTableの基本的な構造と、その使い方について解説しました。

DataTableは、行をつかさどるDataRowクラスと、列をつかさどるDataColumnクラスで構成されており、指定した条件でフィルタリングしたり、XML形式でのファイル保存や読み込み機能が搭載されています。

特にCSVファイルやリレーショナルデータベースとの相性が良いので、本格的にC#を学習される方は、是非この機会にDataTableの扱い方をマスターしてください。


よかったらシェアしてね!
  • URLをコピーしました!
  • URLをコピーしました!
目次