SHOEISHA iD

※旧SEメンバーシップ会員の方は、同じ登録情報(メールアドレス&パスワード)でログインいただけます

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

ComponentZine(ComponentOne)

データベースのデータからバブルチャートを作成する.NETアプリケーションを作る

「PowerTools ComponentOne Studio 2012J」のC1Chart2D/C1FlexGridコントロールを使った.NETアプリケーションの作成 その2

  • このエントリーをはてなブックマークに追加

 前回は、「PowerTools ComponentOne Studio 2012J」の「C1Chart(2D)」コントロールと「C1FlexGrid」コントロールを使用して、データを直接グリッドに入力しリアルタイムにデータをバブルチャートで表示するアプリケーションを作成しました。今回はこのアプリケーションを、C1FlexGridコントロールがデータベースと連結してデータを直接読み込み表示できる機能を利用し、データベースファイルからデータを読み込んでバブルチャートを作れるように改良してみました。

  • このエントリーをはてなブックマークに追加
グラフ化するデータベースとクエリ文を入力すると、
グラフ化するデータベースとクエリ文を入力すると、
グリッドにデータベースデータを表示しバブルチャート化する
グリッドにデータベースデータを表示しバブルチャート化する

はじめに

 前回は、「PowerTools ComponentOne Studio 2012J」の「C1Chart(2D)」コントロールと「C1FlexGrid」コントロールを使用して、データを直接グリッドに入力しリアルタイムにデータをバブルチャートで表示するアプリケーションを作成しました。

 そこで、C1FlexGridコントロールがデータベースと連結してデータを直接読み込んで表示できる機能を利用し、このアプリケーションをいろいろなデータベースからデータを読み込んでバブルチャートを作れるように改良してみました(今回はAccessデータベースファイルを使用しています)。

対象読者

 Visual Basic 2005/2008/2010、またはVisual C# 2005/2008/2010を使ってプログラムを作ったことがある人。

必要な環境

 Visual Basic 2005/2008/2010、Visual C# 2005/2008/2010、Visual Studio 2005/2008/2010のいずれかでプログラムが作れる環境。

 なお、本プログラムはWindows 7上で動作するVisual Studio 2010を使用して作成し、動作確認を行っています。

プログラム実行時の注意事項

 「PowerTools ComponentOne Studio 2012J」を使って作成したアプリケーションを配布する場合、「PowerTools ComponentOne Studio 2012J」のアセンブリファイルを添付する必要があります。これは、Common Language RuntimeのDLLをアプリケーションと一緒に配布するのと同じです。

 本記事のサンプルアプリケーションを正常に動作させるためには、次のファイルをインストールする必要があります。

サンプルファイルの実行に必要なファイル(※.NET Framework 4でのみ利用可)
ファイル名 説明
C1.C1FlexGrid.2.dll 本体アセンブリ
C1.C1FlexGrid.4.dll 本体アセンブリ(※)
C1.Win.C1Chart.2.dll C1Chart本体アセンブリ
C1.Win.C1Chart.4.dll C1Chart本体アセンブリ(※)

 このファイルを、プログラムを実行するフォルダに格納します。

 .NET Framework 2.0から追加されたクラスやメンバを使用しているので、.NET Framework 2.0以上のバージョンの.NET Frameworkがインストールされていることが必須条件です。

コンポーネントのインストール

 「PowerTools ComponentOne Studio 2012J」を使用するには、開発環境(Visual Studio/Visual Basic/Visual C#)に、「PowerTools ComponentOne Studio 2012J」をインストールする必要があります。

 インストーラは、グレープシティのWebページからダウンロードできます。

 ダウンロードしたい製品にチェックを付け[申込フォーム]ボタンを押すと、「トライアル版申込フォーム」ページに移動しますので、「個人情報の収集および使用に同意する」にチェックを入れ「同意する」ボタンをクリックします。

 トライアル申込フォームが表示されますので、必要情報を登録すると添付トライアルライセンスキーファイルとダウンロードサイトを記載したE-Mailが送られてきます。ここからダウンロードします。ダウンロードファイルは圧縮ファイルになっていますので、解凍してインストーラを起動します。

 制限事項などの詳細については、インストーラに同梱されているリリースノートを参照ください。

コントロールの追加

 「PowerTools ComponentOne Studio 2012J」をインストールしたら、プロジェクトにコントロールを追加します。

 ツールボックスに専用のタブを作成し、使用するコンポーネントを追加します。追加するコンポーネントはアセンブリ名が「C1.Win.C1FlexGrid.4」の「C1FlexGrid」コントロールと、アセンブリ名が「C1.Win.C1Chart.4」の「C1Chart」コントロールです。

追加するコントロール
コントロール アセンブリ
C1FlexGrid C1.Win.C1FlexGrid.4
C1Chart C1.Win.C1Chart.4
アセンブリ名が「C1.Win.C1FlexGrid.4」の「C1FlexGrid」コントロール
アセンブリ名が「C1.Win.C1FlexGrid.4」の「C1FlexGrid」コントロール
アセンブリ名が「C1.Win.C1Chart.4」の「C1Chart」コントロール
アセンブリ名が「C1.Win.C1Chart.4」の「C1Chart」コントロール

データベースの連結方法

 C1FlexGridコントロールは、ADO.NETデータソースオブジェクト(DataTable、DataView、DataSet、DataViewManagerなど)へのデータ連結をサポートします。

 グリッドをデータソースに連結するには、データソースオブジェクトを作成し、グリッドのDataSourceプロパティに設定します。データソースオブジェクトが複数のテーブルを持っている場合は、使用テーブルを指定する文字列をDataMemberプロパティに設定します。また、SetDataBindingメソッドを使うと、両方のプロパティを同時に設定することもできます。

 新しいデータソースをグリッドに割り当てると、グリッドは自動的にその列を更新してデータソース内で使用可能な列に連結します。

データソースを連結する方法

 データソースをグリッドに連結する方法は2通りあります。

 1つは、Visual Studioのデータソース構成ウィザードを使用してC1FlexGridコントロールにデータソースを連結する方法です。この方法を使うと、ウィザードの質問に答えていくだけで、簡単にデータベースをグリッドに連結できます。ただし、この方法はアプリケーションに1つのデータベースファイルを固定してしまいますので、複数のデータベースを切り替えてグリッドにデータを表示するのには向いていません。

C1FlexGridコントロールのスマートタグからデータソースの追加を選ぶ
C1FlexGridコントロールのスマートタグからデータソースの追加を選ぶ
データソース構成ウィザードが表示される
データソース構成ウィザードが表示される

 もう一つの方法は、コードからデータベースオブジェクトを作成し、グリッドに連結する方法です。この方法だと、例えばダイアログボックスでデータベースファイルを選んでグリッドに表示する機能を組み込むことができます。しかし、データを取り出すクエリを入力する機能も持たせないと、データベースからデータを抽出することができません。

 それぞれ、データベースを使用する目的に応じて使い分けることになります。

 今回は、ダイアログボックスでAccessのデータベースファイルを選んでグリッドに表示するようにしますので、コードからデータベース連結を行います。

データベース連結の手順

 コードからデータベースファイルをグリッドに連結するには、以下の手順をとります。

  • (1)接続文字列を作成する
  • (2)開くデータベースファイルを指定する
  • (3)クエリ文字列を作成する
  • (4)接続文字列とクエリ文字列を使用してOleDbDataAdapterオブジェクトを作成する
  • (5)OleDbDataAdapterクラスのFillメソッドでDataSetオブジェクトにクエリの結果セットを格納する
  • (6)C1FlexGridコントロールのDataSourceプロパティに、DataSetオブジェクトのテーブルを設定する

 (1)から(5)までの処理は、ADO.NETのデータベース接続処理です。これは、ウィザードを使用したデータベース連結も同じで、ウィザードがコードを書く代りをやってくれているだけです。

 (6)のコードが、クエリの結果セットをグリッドに表示するための連結処理です。C1FlexGridコントロールは、DataSourceプロパティの値が変わると、自動的にグリッドの行列を作成してセルにデータを格納し、データベースの列見出しをグリッドの列ヘッダに設定してくれるので、データベースの連結処理はたったこの1行で済みます。

 プログラマがやることは、開くデータベースファイルを指定し、データを取り出すクエリ文(SQL文)を作成するだけです。

 あとは、お好みでグリッドの各種装飾やフィルタリング、小計処理などのオプション機能を操作するコードを書いていきます。

グリッドの行列数と列ヘッダがデータベースに従って自動的に設定される
グリッドの行列数と列ヘッダがデータベースに従って自動的に設定される

GUIのデザイン

 今回は、前回作成したフォームに手を加え、データベースファイルの選択とクエリ文の入力機能を追加します。追加するコントロールは、ButtonコントロールとOpenFileDialogコントロールの2つです。クエリ文の入力は、コードからInputBoxを表示して入力してもらうようにします。

フォームのデザイン

 Buttonコントロールを1つ追加し、Clickイベントハンドラを作成します。

 OpenFileDialogコントロールは、Filterプロパティを設定しAccessデータベースファイルを選べるようにします。

OpenFileDialogコントロールの設定
プロパティ 設定値
FileName (空白)
Filter Accessファイル(*.mdb)|*.mdb
フォームのレイアウト
フォームのレイアウト

データベース連結処理の実装

 まずは、グリッドをデータベースに連結する処理を作成します。この処理は、ボタン「データベースの読み込み」のClickイベントハンドラで行います。

 なお、System.Data.OleDb名前空間への参照を追加しておいてください。

 また、クエリ文の入力にインプットボックスを使用します。これは、Visual BasicのInputBoxメソッドを使用しますので、C#で使う場合はプロジェクトの参照設定に「Microsoft.VisualBasic」を追加しておいてください。

C#は「Microsoft.VisualBasic」への参照を追加しておく
C#は「Microsoft.VisualBasic」への参照を追加しておく

 (1)最初に、DBファイル名の取得と接続文字を作成します。データベースファイル名は、OpenFileDialogコントロールを使用して取得します。また、接続文字列は変数connに作成します。Accessデータベースは、Microsoft.Jet.OLEDB.4.0データベースプロバイダを使用します。

 (2)次に、クエリ文(SQL文)の入力を受け付けます。ここでは処理を簡単にするために、インプットボックスに直接クエリ文を入力してもらうことにしました。入力するクエリ文は、データベース側で事前に抽出用クエリを作成し、そのSQL文を入力するだけ済みます。

 インプットボックスは、InteractionクラスのInputBoxメソッドを使用し、ユーザーに1行入力ができるダイアログを表示します。引数にプロンプトとタイトル、表示位置などを指定し、ユーザーが入力してOKボタンを押すと入力文字列を返してきます。キャンセルボタンが押されると空白の文字列を返してきますのでこれを判断し、文字列が入力された場合のみ文字列を変数に格納します。キャンセルボタンが押されれば処理を中止します。

 なお、InputBoxメソッドは、Visual Basicでは簡単に使用でき引数を省略しても大丈夫なのですが、C#の場合は引数を省略してしまうとエラーになりますので引数の個数が一致するように記述します。

 (3)クエリを実行しDataSetにデータを取り込みます。接続文字列とクエリ文が作成できたら、OleDbDataAdapterクラスのインスタンスを作成します。コンストラクタの引数には、作成した接続文字列とクエリ文を指定します。

 そして、Fillメソッドを実行します。引数にはDataSetオブジェクトを作成し指定します。Fillメソッドは、指定したデータテーブルからクエリを実行してデータを抽出し、DataSetオブジェクト内にクエリの結果セットをテーブルとして作成します。

 (4)作成した結果セットのテーブルを、C1FlexGridコントロールのDataSourceプロパティにセットします。これで、グリッドにクエリの結果が格納されます。

 Accessデータベースのテーブルデータは、先頭列にインデックス番号が主キーとして付加されている場合が多いので(今回のサンプルデータも先頭列が主キーのインデックスになっています)、これをグリッドから削除しておきます。

 以上で、C1FlexGridコントロールのデータ連結処理はでき上がりです。

データベースのテーブルデータがグリッドに格納される
データベースのテーブルデータがグリッドに格納される
VB.NET
'★ 名前空間を追加
Imports System.Data.OleDb

'★ 新規追加処理-グリッドのデータ接続
Private Sub Button5_Click(sender As System.Object, e As System.EventArgs) Handles Button5.Click
    '(1)DBファイル名の取得と接続文字の作成
    Dim dbname As String = ""
    If OpenFileDialog1.ShowDialog() = Windows.Forms.DialogResult.OK Then
        dbname = OpenFileDialog1.FileName
    else
        Exit Sub
    End If

    Dim conn As String = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" & dbname

    'サンプルデータベース用クエリ文字列
    'SELECT chart_data.* FROM chart_data
    'SELECT 台風発生個数の推移.* FROM 台風発生個数の推移

    '(2)SQL文の入力
    Dim sqlstr As String = InputBox("クエリのSQL文字列を入力してください", "テーブルの取り込み")
    If sqlstr = "" Then
        Exit Sub
    End If

    '(3)クエリを実行しDataSetにデータを取り込む
    Dim data_adap As OleDbDataAdapter = New OleDbDataAdapter(sqlstr, conn)
    Dim data_sset As DataSet = New DataSet()

    data_adap.Fill(data_sset)

    '(4)グリッドにデータを接続
    C1FlexGrid1.DataSource = data_sset.Tables(0)
    C1FlexGrid1.Cols.Remove(1)   'キー列を削除
End Sub
C#
// ★ 名前空間を追加
using System.Data.OleDb;

// ★ 新規追加処理-グリッドのデータ接続
private void button5_Click(object sender, EventArgs e)
{
    // (1)DBファイル名の取得と接続文字の作成
    string dbname = "";
    if (openFileDialog1.ShowDialog() == System.Windows.Forms.DialogResult.OK)
    {
        dbname = openFileDialog1.FileName;
    }
    else
    {
        return;
    }
    string conn = "Provider=Microsoft.Jet.OLEDB.4.0; Data Source=" + dbname;

    // サンプルデータベース用クエリ文字列
    // SELECT chart_data.* FROM chart_data
    // SELECT 台風発生個数の推移.* FROM 台風発生個数の推移

    //(2)SQL文の入力
    string sqlstr = Microsoft.VisualBasic.Interaction.InputBox("クエリのSQL文字列を入力してください", "テーブルの取り込み", "", 200, 100);
    if(sqlstr == "")
    {
        return;
    }

    //(3)クエリを実行しDataSetにデータを取り込む
    OleDbDataAdapter data_adap = new OleDbDataAdapter(sqlstr, conn);
    DataSet data_sset = new DataSet();

    data_adap.Fill(data_sset);

    //(4)グリッドにデータを接続
    c1FlexGrid1.DataSource = data_sset.Tables[0];
    c1FlexGrid1.Cols.Remove(1);   //キー列を削除
}
Interaction.InputBoxメソッドの書式
public static string InputBox(
    string Prompt,
    string Title,
    string DefaultResponse,
    int XPos,
    int YPos
)
Prompt

 必須。ダイアログボックスにメッセージとして表示するString式です。Promptの最大長は、約1024文字です。使用される文字の幅によって変わります。Promptが複数の行で構成される場合、復帰文字(Chr(13))、ラインフィード文字(Chr(10))、または復帰とラインフィードの組み合わせ(Chr(13)およびChr(10))を各行の間で使用して、行を分割できます。

Title

 省略可能。ダイアログボックスのタイトルバーに表示されるString型の式。Titleを省略した場合、タイトルバーにはアプリケーションの名前が表示されます。

DefaultResponse

 省略可能。他に入力がない場合に、テキストボックスに既定値として表示されるString型の式。DefaultResponseを省略すると、表示されるテキストボックスは空になります。

XPos

 省略可能。ダイアログボックスの左端から画面の左端までの距離をtwip単位で指定する数式です。XPosを省略すると、ダイアログボックスの水平位置が中央になります。

YPos

 省略可能。ダイアログボックスの上端から画面の上端までの距離をtwip単位で指定する数式です。YPosを省略すると、ダイアログボックスは垂直方向に対して画面の上端から約1/3の位置に配置されます。

バブルチャート作成処理

 グリッドのデータが更新されたので、これに基づくバブルチャート作成処理も修正を加えます。修正点は、グリッドの行列数と列見出しの数がデータベースごとに変わりますので、これをグリッドの変化に対応できるようにする部分です。

データ用配列の要素数をデータ数に合わせるように修正

 まずは、チャート作成用データがグリッドのデータ数によって変化しますので、これに合わせてデータを格納する配列の要素数も変えられるようにします。前回のアプリケーションでは、要素数を7個に固定していましたので、これを変数に変えます。

 チャート化するデータ数は、グリッドの行数で把握できます。これは、C1FlexGridコントロールのRowsコレクションオブジェクトのCountプロパティで取得できます。要素数のインデックスは0から始まりますから、Countプロパティの値から1を差し引きます。

 要素数の確保は、Visual BasicではReDimステートメントで、C#では配列の宣言時に行います。配列が確保できたら、C1FlexGridコントロールのGetDataDisplayメソッドでデータを取得していきます。

VB.NET
'----------------------- グラフ作成 ----------------------------------------------------
Private Sub Button2_Click(sender As System.Object, e As System.EventArgs) Handles Button2.Click
    'Dim xp(6) As Integer
    'Dim yp(6) As Integer
    'Dim vol(6) As Integer
    'Dim i As Integer

    'グリッドからデータを取得 
    'For i = 0 To 6
    '    xp(i) = Convert.ToInt16(C1FlexGrid1.GetDataDisplay(i + 1, 2))
    '    yp(i) = Convert.ToInt16(C1FlexGrid1.GetDataDisplay(i + 1, 3))
    '    vol(i) = Convert.ToInt16(C1FlexGrid1.GetDataDisplay(i + 1, 4))
    'Next i

    '★ 配列数の確保をデータ数に合わせるように修正 
    Dim rownum As Integer = C1FlexGrid1.Rows.Count - 2
    Dim xp() As Integer
    Dim yp() As Integer
    Dim vol() As Integer
    Dim i As Integer

    ReDim xp(rownum)
    ReDim yp(rownum)
    ReDim vol(rownum)

    For i = 0 To C1FlexGrid1.Rows.Count - 2
        xp(i) = Convert.ToInt16(C1FlexGrid1.GetDataDisplay(i + 1, 2))
        yp(i) = Convert.ToInt16(C1FlexGrid1.GetDataDisplay(i + 1, 3))
        vol(i) = Convert.ToInt16(C1FlexGrid1.GetDataDisplay(i + 1, 4))
    Next i
C#
//----------------------- グラフ作成 ----------------------------------------------------
private void button2_Click(object sender, EventArgs e)
{
    //int[] xp = new int[7];
    //int[] yp  = new int[7];
    //int[] vol = new int[7];
    //int i;

    ////FlexGridからデータを取得 
    //for(i=0; i<=6; i++)
    //{
    //    xp[i] = Convert.ToInt16(c1FlexGrid1.GetDataDisplay(i + 1, 2));
    //    yp[i] = Convert.ToInt16(c1FlexGrid1.GetDataDisplay(i + 1, 3));
    //    vol[i] = Convert.ToInt16(c1FlexGrid1.GetDataDisplay(i + 1, 4));
    //}

    // ★ 配列数の確保をデータ数に合わせるように修正 
    int rownum = c1FlexGrid1.Rows.Count - 1;
    int[] xp = new int[rownum];
    int[] yp = new int[rownum];
    int[] vol = new int[rownum];
    int i;

    //FlexGridからデータを取得 
    for (i = 0; i <= c1FlexGrid1.Rows.Count-2; i++)
    {
        xp[i] = Convert.ToInt16(c1FlexGrid1.GetDataDisplay(i + 1, 2));
        yp[i] = Convert.ToInt16(c1FlexGrid1.GetDataDisplay(i + 1, 3));
        vol[i] = Convert.ToInt16(c1FlexGrid1.GetDataDisplay(i + 1, 4));
    }

データラベルの修正と表示範囲の自動設定を追加

 チャートデータが設定できたら、データラベルを更新する処理を作成します。

 また、チャートデータが入れ替わりますので、データの表示範囲も一度リセットするために、最大値と最小値を自動的に設定できるようにします。

 (1)新しいチャートデータに合わせてラベルを新しく作り直します。ラベルデータの作成は前回と同じですが、Forループの繰り返し回数をチャートデータ数に合わせます。

 (2)そして、ChartAreaクラスのAxisX、AxisYオブジェクトの「AutoMax」「AutoMin」プロパティをTrue設定し、チャートの表示範囲をデータに合わせる自動設定に切り替えておきます。この処理をしておかないと、チャートデータが切り替わってもXY軸の軸目盛は変わらない、という状態になってしまいます。

 以上ででき上がりです。

VB.NET
'ラベルの作成
    Dim lab As C1.Win.C1Chart.Label

    ' 一度ラベルを削除
    If C1Chart1.ChartLabels.LabelsCollection.Count > 0 Then
        C1Chart1.ChartLabels.LabelsCollection.RemoveAll()
    End If


    '(1)★ ラベルの個数を修正しデータ数に自動設定
    'For i = 0 To 6 
    For i = 0 To C1FlexGrid1.Rows.Count - 2
        lab = C1Chart1.ChartLabels.LabelsCollection.AddNewLabel()
        lab.Text = C1FlexGrid1.GetDataDisplay(i + 1, 1)
        lab.Compass = LabelCompassEnum.East
        lab.AttachMethod = AttachMethodEnum.DataIndex
        lab.AttachMethodData.GroupIndex = 0
        lab.AttachMethodData.SeriesIndex = 0
        lab.AttachMethodData.PointIndex = i
        lab.Style.BackColor = Color.Transparent
        lab.Visible = True
    Next

    '(2)★ 一度表示範囲を自動にリセット
    C1Chart1.ChartArea.AxisX.AutoMax = True
    C1Chart1.ChartArea.AxisX.AutoMin = True

    C1Chart1.ChartArea.AxisY.AutoMax = True
    C1Chart1.ChartArea.AxisY.AutoMin = True
End Sub
C#
    //ラベルの作成
    C1.Win.C1Chart.Label lab ;

    // 一度ラベルを削除
    if(c1Chart1.ChartLabels.LabelsCollection.Count>0)
    {
        c1Chart1.ChartLabels.LabelsCollection.RemoveAll();
    }

    //(1)★ ラベルの個数を修正しデータ数に自動設定
    // for (i = 0; i <= 6; i++)           
    for (i = 0; i <= c1FlexGrid1.Rows.Count-2; i++)
    {
        lab = c1Chart1.ChartLabels.LabelsCollection.AddNewLabel();
        lab.Text = c1FlexGrid1.GetDataDisplay(i + 1, 1);
        lab.Compass = LabelCompassEnum.East;
        lab.AttachMethod = AttachMethodEnum.DataIndex;
        lab.AttachMethodData.GroupIndex = 0;
        lab.AttachMethodData.SeriesIndex = 0;
        lab.AttachMethodData.PointIndex = i;
        lab.Style.BackColor = Color.Transparent;
        lab.Visible = true;
    }

    //(2)★ 一度表示範囲を自動にリセット
    c1Chart1.ChartArea.AxisX.AutoMax = true;
    c1Chart1.ChartArea.AxisX.AutoMin = true;

    c1Chart1.ChartArea.AxisY.AutoMax = true;
    c1Chart1.ChartArea.AxisY.AutoMin = true;
}

まとめ

 チャートデータにデータベースが使えるようになると、アプリケーションの利用範囲も広がります。

 サンプルアプリケーションなので、チャートデータの抽出に直接クエリ文を入力するようにしましたが、ユーザーフレンドリーなアプリケーションに仕上げるのであれば、このクエリの入力処理も簡単にできるように作成しておくと良いですね。

 また、バブルチャートもChartAreaクラスのメンバを使用すればより細かな装飾ができますし、元データの列数から棒グラフや折れ線グラフも表示できるような機能を実装すれば、より使い勝手のあるチャート作成アプリケーションに仕上げることができます。

今回は、Accessのデータベースファイルを使用しましたが、ADO.NETで使用できるデータベースであればどのようなデータベースでもデータを抽出してグラフ化できます。

 

参考資料(サンプルデータ)

この記事は参考になりましたか?

  • このエントリーをはてなブックマークに追加

この記事は参考になりましたか?

この記事をシェア

  • このエントリーをはてなブックマークに追加
CodeZine(コードジン)
https://codezine.jp/article/detail/6831 2012/10/29 14:00

イベント

CodeZine編集部では、現場で活躍するデベロッパーをスターにするためのカンファレンス「Developers Summit」や、エンジニアの生きざまをブーストするためのイベント「Developers Boost」など、さまざまなカンファレンスを企画・運営しています。

新規会員登録無料のご案内

  • ・全ての過去記事が閲覧できます
  • ・会員限定メルマガを受信できます

メールバックナンバー

アクセスランキング

アクセスランキング