2013年11月1日金曜日

VB 日付変数と DataTable と DataGridView

VB で、Form に配置するコントロールって、色々ありますよね。 Lable や TextBox やListBox や ComboBox 。
これらは単一の項目に対応して機能しますが、複数の項目に対しては、ListView や DataGridView がありますね。
DataGridView というとデータベース専用って感じの解説が多いんですが、表形式のコントロールです。
今回、データベースを使わず、DataTable と DataGridView とで、日付変数を扱ったら 躓いてしまったので、メモしておきます。


先ず、VB の日付変数から。

日付変数は日付型で定義します。
その値は、日付値と時刻値を保持します。
   日付値  0001 年 1 月 1 日から 9999 年 12 月 31 日までの範囲。
   時刻値  12:00:00 AM (深夜) から 11:59:59 PM * までの範囲。
  注 * 変数は IEEE 64 ビット (8 バイト) の整数として格納され、時刻精度は11:59:59.9999999 PM まで認識可能です。
時刻値が割り当てられない場合、既定値である日の先頭の深夜に設定されます。


次に、日付定数。 

日付の値は、両端を # で囲み、#10/30/2013 10:20:30# の様に、M/d/yyyy H:m:s の形式で設定します。
ここが注意点です!       #月/日/西暦 4 桁半角スペース時:分:秒#
PC 上で標準的に表示される   2013/10/30    とは順番が異なります。
  正確には OS で設定された表示方法とは です。 コントロール パネルから変更可能になっていますね。
  私のWin7 の短い形式では、選択肢はいずれも年が冒頭に来ます。
      あっ、VB って VB2008SP1EE です。 version 書いて置かないと ... 。
これは お決まりごと です。 守らないとコンパイラに怒られます。


他のデバイスやソフトでは。

日付の扱い方は まちまち です。
文字型で扱ったり、浮動小数点で扱ったり、つまり、有効範囲と精度は夫々です。
事前に、良く調べておきましょう。  特に、秒表示。
同じ VB の中でも、Timer 等は精度が異なります。


さて、本題。

上記の注意点を踏まえて、VB で、DataTable と DataGridView を用いて、一覧表形式のプログラムを作ろう、と。

DataTable の中に Date で定義された列を入れて、DataGridView で表示して見ると ... 。
秒単位が抜け落ちて表示されますね。  まいった!
Debug してみると、 ... 、
Date を収めた DataTable 列は秒を保持しているのに、DataGridView 列には分単位迄しか表示されません。
一体、どうしたというのでしょうか?

散々悩んだ挙句に気付いたのが、日付変数の特殊性!
画面表示等は 文字列 です。 !!!
                      日付変数に限らず、文字以外の変数は皆 変換が必要でしたね、忘れてました
                      自動的に変換してくれる初期設定が秒ナシの指定であったのですね。
DataTimePicker で良く使われる CustomFormat プロパティも戻り値は文字列 です。
DataTimePicker の値を示す Value プロパティでは戻り値は日付型です。
DataGridView でも同じ事をします。

つまり、
 DataColumn("ColumnTime", GetType(Date)) で DataTable の "ColumnTime" 列 に保持し、
 DataGridView.DataSource に DataTable 名 を指定し、
 DataGridView.Columns("ColumnTime").DefaultCellStyle.Format = "yyyy/MM/dd HH:mm:ss" で表示形式を設定します。


これで、一件落着!      秒が忽然と姿を現します。

  日付を文字型として扱う方法もありますが、個人的には、
  データ誤入力の回避や演算の利便性から、ちゃんと日付型で保持した方が良い と思っています。


以下に、参考コードを。 Column 名が上とは異なります。 dr への代入は色々なパターンを試しています。
Private Sub InitializeDTable()
        Dim dt As DataTable
        Dim dr As DataRow

        'Create DataTable
        dt = New DataTable()
        dt.Columns.Add(New DataColumn("FileName", GetType(String)))
        dt.Columns.Add(New DataColumn("CreationNow", GetType(Date)))
        dt.Columns.Add(New DataColumn("CreationNew", GetType(Date)))

        dr = dt.NewRow()
        dr(0) = "001.txt"
        dr(1) = DateTime.Now
        dr(2) = Format(dr(1), "yyyy/MM/dd HH:mm:ss")
        dt.Rows.Add(dr)

        dr = dt.NewRow()
        dr(0) = "002.exe"
        dr(1) = #10/30/2013 12:00:30 PM#
        dr(2) = dr(1)
        dt.Rows.Add(dr)

        dr = dt.NewRow()
        dr(0) = "003.tmp"
        dr(1) = New System.DateTime(2100, 1, 1, 12, 34, 56)
        dr(2) = dr(1)
        dt.Rows.Add(dr)

        'DGV DataSource and Setting
        Me.DataGridView1.DataSource = dt
        Me.DataGridView1.AllowUserToAddRows = False
        Me.DataGridView1.AllowUserToDeleteRows = False
        Me.DataGridView1.RowHeadersWidth = 40
           Me.DataGridView1.Width = 360
           Me.Width = 430

        Me.DataGridView1.Columns("FileName").Width = 80
        Me.DataGridView1.Columns("FileName").ReadOnly = True

        Me.DataGridView1.Columns("CreationNow").DefaultCellStyle.Format = "yyyy/MM/dd HH:mm:ss"   ' Show Second
        Me.DataGridView1.Columns("CreationNow").Width = 110
        Me.DataGridView1.Columns("CreationNow").ReadOnly = True

        ' ************************************************ "CreationNew" Column Is No CellStyle's Format ( Default )
        Me.DataGridView1.Columns("CreationNew").Width = 110
        Me.DataGridView1.Columns("CreationNew").ReadOnly = False
End Sub

Form に、ひとつ DataGridView を貼り付けただけでも実行可能なコードです。
Sub Form1_Load に InitializeDTable() 1 行を記述して、試せます。 勿論、本コードも。
"CreationNow" では秒までが、"CreationNew" では分までしかが、各々、表示されるのが分ると思います。
  万一、コードをコピーして使い廻す方は、ちゃんと、直して下さいね。"CreationNew" のFormat 指定。!!!

この例では、"CreationNew" のみ編集可能としています。 また、見出しでソートが可能です。
他と見較べながら編集作業が可能な DataGridView は、この様に、データベースと接続しないでも利用出来ますね。

  DataGridView は便利で重宝な反面、膨大な量のプロパティやメソッドがあります。
  使いこなせる様になるのは大変ですが、是非、覚えておきたいコントロールですね。

  また、データベースの表示手段として紹介されるDataGridView は、
  どうしても、データベース絡みの Connection , DataAdapter , DataSet と入り混ざり、
  一層 難解な印象を与えますね。
  今回の様に、一旦、データベースから離れて見て見るのも良いかも ... です。


尚、Format 書式の指定文字列の各記号については、 msdn の以下の Documents を参照下さい。
      カスタムの日付と時刻の書式指定文字列 .NET Framework 4.5



[2013/12/03] Format 書式の指定文字列について、追補

0 件のコメント:

コメントを投稿