NonSoft

DataGridViewに便利なメソッドを追加する
サンプル(VB.NET)


 サンプル(ソース/コード)
<このサンプルの概要>
DataGridViewの派生クラスを作って便利なメソッドを追加して行くと高機能のDataGridViewが出来あがります。
.NETで使用するフレックスグリッド(FlexGrid)の代表的な存在?であるDataGridViewなので、自分だけの便利な
メソッドを追加してライバルに差を付けましょう。(と言うかDataGridViewの標準で実装して欲しいのですが)
このサンプルはDataGridViewの使用方法のサンプルとしてもご使用頂けると思います。

このサンプルは以下の機能を実装しています。
(1)DataGridViewのカラム幅をファイルへ保存/読込するための実装
(2)DataGridViewの各カラムへの入力可能文字を制限するための実装
(3)DataGridViewでCtrl-Vキー押下時にクリップボードから貼り付けるための実装
(4)DataGridViewでDelやBackspaceキー押下時にセルの内容を消去するための実装

今後以下の機能の実装を予定しています。
(1)DataGridViewのコンボボックス(ComboBox)をプルダウン(F4)するための実装
(2)DataGridViewのセルの内容をCSV形式で保存するための実装
(3)DataGridViewのセルの内容をHTML形式で保存するための実装
(4)DataGridViewのセルの内容をEXCEL形式で保存するための実装
(5)DataGridViewのセルの内容をDB(ACCESS等)に保存するための実装(DBサンプルとの組み合わせ)
(6)DataGridViewのセルの内容をDB(ACCESS等)から読込むための実装(DBサンプルとの組み合わせ)

ちなみに、このDataGridViewPlusをもっと便利にしているサイトを紹介します。
DataGridViewでコピー&ペーストを可能にする(バインド対応)
DataGridView CSV出力(C#/VB.NET)
DataGridView CSV読込(C#/VB.NET)
DataGridView EXCEL出力(C#/VB.NET)
DataGridView EXCEL読込(C#/VB.NET)
DataGridView HTML出力(C#/VB.NET)

C#.NET版はこちら「DataGridViewに便利なメソッドを追加するサンプル(C#.NET)」です。
また、DataGridViewを使用する上でよく使う技(メモ)は DataGridViewの小技 です。

このサンプルを使用する方法(VB2005の場合)は以下の通りです。
(1)Form1にSystem.Windows.Forms.DataGridViewを追加する
(2)Form1.Designer.vbのSystem.Windows.Forms.DataGridViewの部分をDataGridViewPlusに変更する。
(注)VB2010でForm1.Designer.vbの中のソースを表示するには何らかの設定が必要なようです。。。

★DataGridViewからの派生クラス(DataGridViewPlus.vb)
Imports System.IO
Imports System.Text
Imports System.Xml.Serialization
Imports System.Windows.Forms

Public Class DataGridViewPlus
    Inherits System.Windows.Forms.DataGridView

    ' ----------------------------------------------------------------------------------
    ' DataGridViewのカラム幅をファイルへ保存/読込するための実装↓↓↓↓↓↓↓↓↓↓↓↓
    ' ----------------------------------------------------------------------------------
    ''' <summary>
    ''' DataGridViewのカラム幅をXML形式でシリアライズするためのクラス
    ''' </summary>
    ''' <remarks></remarks>
    Public Class ColWidths
        ''' <summary>
        ''' カラム幅s
        ''' </summary>
        Public Widths As Integer()
    End Class

    ''' <summary>
    ''' DataGridViewのカラム幅をファイルへ保存
    ''' </summary>
    ''' <remarks>DataGridViewのカラム幅をXML形式でシリアライズ</remarks>
    Public Sub SaveColWidths()
        Try
            ' EXEファイルのPATH
            Dim ExePath As String = System.AppDomain.CurrentDomain.BaseDirectory
            ' XMLファイルのPATH
            Dim XmlPath As String = ExePath & "\" & Me.Parent.Name & "_" & Me.Name & ".xml"
            ' XMLファイルオープン
            Dim sw As StreamWriter = New StreamWriter(XmlPath, False, Encoding.Default)
            Try
                ' シリアライザー
                Dim serializer As New XmlSerializer(GetType(ColWidths))
                ' DataGridViewのカラム幅取得
                Dim colw As New ColWidths
                ReDim colw.Widths(Me.Columns.Count - 1)
                For i As Integer = 0 To Me.Columns.Count - 1
                    colw.Widths(i) = Me.Columns(i).Width
                Next
                ' XMLファイル保存
                serializer.Serialize(sw, colw)
            Catch ex As Exception
            Finally
                ' XMLファイルクローズ
                If sw Is Nothing = False Then sw.Close()
            End Try
        Catch ex As Exception
        End Try
    End Sub

    ''' <summary>
    ''' DataGridViewのカラム幅を前回保存したファイルから読込
    ''' </summary>
    ''' <remarks>DataGridViewのカラム幅をXML形式でデシリアライズ</remarks>
    Public Sub ReadColWidths()
        Try
            ' EXEファイルのPATH
            Dim ExePath As String = System.AppDomain.CurrentDomain.BaseDirectory
            ' XMLファイルのPATH
            Dim XmlPath As String = ExePath & "\" & Me.Parent.Name & "_" & Me.Name & ".xml"
            ' XMLファイルオープン
            Dim sr As StreamReader = New StreamReader(XmlPath, Encoding.Default)
            Try
                ' シリアライザー
                Dim serializer As New XmlSerializer(GetType(ColWidths))
                ' XMLファイル読込
                Dim colw As New ColWidths
                colw = CType(serializer.Deserialize(sr), ColWidths)
                ' DataGridViewにカラム幅設定
                For i As Integer = 0 To Me.Columns.Count - 1
                    Me.Columns(i).Width = colw.Widths(i)
                Next
            Catch ex As Exception
            Finally
                ' XMLファイルクローズ
                If sr Is Nothing = False Then sr.Close()
            End Try
        Catch ex As Exception
        End Try
    End Sub
    ' ----------------------------------------------------------------------------------
    ' DataGridViewのカラム幅をファイルへ保存/読込するための実装↑↑↑↑↑↑↑↑↑↑↑↑
    ' ----------------------------------------------------------------------------------

    ' ----------------------------------------------------------------------------------
    ' DataGridViewの各カラムへの入力可能文字を制限するための実装↓↓↓↓↓↓↓↓↓↓↓↓
    ' ----------------------------------------------------------------------------------
    ''' <summary>
    ''' カラムへの入力可能文字を指定するための配列
    ''' </summary>
    ''' <remarks>ColumnChars(0)="1234567890"</remarks>
    Public ColumnChars() As String
    ''' <summary>
    ''' 編集中のカラム番号
    ''' </summary>
    ''' <remarks></remarks>
    Private _editingColumn As Integer
    ''' <summary>
    ''' 編集中のTextBoxEditingControl
    ''' </summary>
    ''' <remarks></remarks>
    Private _editingCtrl As DataGridViewTextBoxEditingControl

    ''' <summary>
    ''' セルが編集中になった時の処理
    ''' </summary>
    ''' <param name="sender">イベントの発生元</param>
    ''' <param name="e">イベントの情報</param>
    ''' <remarks>編集中のTextBoxEditingControlにKeyPressイベント設定</remarks>
    Private Sub DataGridViewPlus_EditingControlShowing( _
        ByVal sender As Object, ByVal e As DataGridViewEditingControlShowingEventArgs) _
        Handles Me.EditingControlShowing
        ' 編集中のカラム番号を保存
        _editingColumn = CType(sender, DataGridView).CurrentCellAddress.X
        Try
            ' 編集中のTextBoxEditingControlにKeyPressイベント設定
            _editingCtrl = CType(e.Control, DataGridViewTextBoxEditingControl)
            AddHandler _editingCtrl.KeyPress, AddressOf DataGridViewPlus_CellKeyPress
        Catch
        End Try
    End Sub

    ''' <summary>
    ''' セルの編集が終わった時の処理
    ''' </summary>
    ''' <param name="sender">イベントの発生元</param>
    ''' <param name="e">イベントの情報</param>
    ''' <remarks>編集中のTextBoxEditingControlからKeyPressイベント削除</remarks>
    Private Sub DataGridViewPlus_CellEndEdit(ByVal sender As Object, _
        ByVal e As DataGridViewCellEventArgs) Handles Me.CellEndEdit
        If _editingCtrl Is Nothing = False Then
            ' 編集中のTextBoxEditingControlからKeyPressイベント削除
            RemoveHandler _editingCtrl.KeyPress, AddressOf DataGridViewPlus_CellKeyPress
            _editingCtrl = Nothing
        End If
    End Sub

    ''' <summary>
    ''' 編集中のTextBoxEditingControlのKeyPressの処理
    ''' </summary>
    ''' <param name="sender">イベントの発生元</param>
    ''' <param name="e">イベントの情報</param>
    ''' <remarks>力可能文字の判定</remarks>
    Private Sub DataGridViewPlus_CellKeyPress( _
        ByVal sender As Object, ByVal e As KeyPressEventArgs)
        ' カラムへの入力可能文字を指定するための配列が指定されているかチェック
        If IsArray(ColumnChars) Then
            ' カラムへの入力可能文字を指定するための配列数チェック
            If ColumnChars.GetLength(0) - 1 >= _editingColumn Then
                ' カラムへの入力可能文字が指定されているかチェック
                If ColumnChars(_editingColumn) <> "" Then
                    ' カラムへの入力可能文字かチェック
                    If InStr(ColumnChars(_editingColumn), e.KeyChar) <= 0 AndAlso _
                       e.KeyChar <> Chr(Keys.Back) Then
                        ' カラムへの入力可能文字では無いので無効
                        e.Handled = True
                    End If
                End If
            End If
        End If
    End Sub
    ' ----------------------------------------------------------------------------------
    ' DataGridViewの各カラムへの入力可能文字を制限するための実装↑↑↑↑↑↑↑↑↑↑↑↑
    ' ----------------------------------------------------------------------------------

    ' ----------------------------------------------------------------------------------
    ' DataGridViewでCtrl-Vキー押下時にクリップボードから貼り付けるための実装↓↓↓↓↓↓
    ' DataGridViewでDelやBackspaceキー押下時にセルの内容を消去するための実装↓↓↓↓↓↓
    ' ----------------------------------------------------------------------------------
    Private Sub DataGridViewPlus_KeyDown( _
        ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs) _
        Handles Me.KeyDown
        Dim dgv As DataGridView = CType(sender, DataGridView)
        Dim x As Integer = dgv.CurrentCellAddress.X
        Dim y As Integer = dgv.CurrentCellAddress.Y
        If e.KeyCode = Keys.Delete Or e.KeyCode = Keys.Back Then
            ' セルの内容を消去
            dgv(x, y).Value = ""
        ElseIf (e.Modifiers And Keys.Control) = Keys.Control And e.KeyCode = Keys.V Then
            ' クリップボードの内容を取得
            Dim clipText As String = Clipboard.GetText()
            ' 改行を変換
            clipText = clipText.Replace(vbCrLf, vbLf)
            clipText = clipText.Replace(vbCr, vbLf)
            ' 改行で分割
            Dim lines() As String = clipText.Split(vbLf)

            Dim r As Integer
            Dim nflag As Boolean = True
            For r = 0 To lines.GetLength(0) - 1
                ' 最後のNULL行をコピーするかどうか
                If r >= lines.GetLength(0) - 1 And _
                   "".Equals(lines(r)) And nflag = False Then Exit For
                If "".Equals(lines(r)) = False Then nflag = False

                ' タブで分割
                Dim vals() As String = lines(r).Split(vbTab)

                ' 各セルの値を設定
                Dim c As Integer = 0
                Dim c2 As Integer = 0
                For c = 0 To vals.GetLength(0) - 1
                    ' セルが存在しなければ貼り付けない
                    If Not (x + c2 >= 0 And x + c2 < dgv.ColumnCount And _
                            y + r >= 0 And y + r < dgv.RowCount) Then
                        Continue For
                    End If
                    ' 非表示セルには貼り付けない
                    If dgv(x + c2, y + r).Visible = False Then
                        c = c - 1
                        Continue For
                    End If
                    '' 貼り付け処理(入力可能文字チェック無しの時)------------
                    '' 行追加モード&(最終行の時は行追加)
                    'If y + r = dgv.RowCount - 1 And _
                    '   dgv.AllowUserToAddRows = True Then
                    '    dgv.RowCount = dgv.RowCount + 1
                    'End If
                    '' 貼り付け
                    'dgv(x + c2, y + r).Value = vals(c)
                    ' ------------------------------------------------------
                    ' 貼り付け処理(入力可能文字チェック有りの時)------------
                    Dim pststr As String = ""
                    For i As Long = 0 To vals(c).Length - 1
                        _editingColumn = x + c2
                        Dim tmpe As KeyPressEventArgs = _
                            New KeyPressEventArgs(vals(c).Substring(i, 1))
                        tmpe.Handled = False
                        DataGridViewPlus_CellKeyPress(sender, tmpe)
                        If tmpe.Handled = False Then
                            pststr = pststr & vals(c).Substring(i, 1)
                        End If
                    Next
                    ' 行追加モード&最終行の時は行追加
                    If y + r = dgv.RowCount - 1 And _
                       dgv.AllowUserToAddRows = True Then
                        dgv.RowCount = dgv.RowCount + 1
                    End If
                    ' 貼り付け
                    dgv(x + c2, y + r).Value = pststr
                    ' ------------------------------------------------------
                    ' 次のセルへ
                    c2 = c2 + 1
                Next
            Next
        End If
    End Sub
    ' ----------------------------------------------------------------------------------
    ' DataGridViewでCtrl-Vキー押下時にクリップボードから貼り付けるための実装↑↑↑↑↑↑
    ' DataGridViewでDelやBackspaceキー押下時にセルの内容を消去するための実装↑↑↑↑↑↑
    ' ----------------------------------------------------------------------------------

End Class

★テスト用フォーム(Form1.vb)
' 予めFrom1にSystem.Windows.Forms.DataGridViewを追加してください。
' そしてForm1.Designer.vbのSystem.Windows.Forms.DataGridViewの部分を
' DataGridViewPlusに変更してください。
Public Class Form1

    Private Sub Form1_Load( _
        ByVal sender As System.Object, ByVal e As System.EventArgs) _
        Handles MyBase.Load

        ' セル選択モード
        DataGridView1.SelectionMode = DataGridViewSelectionMode.CellSelect
        ' 行ヘッダー無し
        DataGridView1.RowHeadersVisible = False
        ' カラムヘッダーは中央表示
        DataGridView1.ColumnHeadersDefaultCellStyle.Alignment = _
            DataGridViewContentAlignment.MiddleCenter

        ' カラムの追加
        ' TextBoxカラムの追加
        DataGridView1.Columns.Add("aaa", "AAA")
        DataGridView1.Columns.Add("bbb", "BBB")
        'DataGridView1.Columns.Add("ccc", "CCC")
        ' ComboBoxカラムの追加
        Dim cbo As DataGridViewComboBoxColumn = New DataGridViewComboBoxColumn()
        cbo.HeaderText = "CCC"
        cbo.Name = "ccc"
        Dim i As Integer
        For i = 1 To 30
            cbo.Items.Add("" & i)
        Next
        DataGridView1.Columns.Add(cbo)

        ' 各カラムを編集可能に設定
        For i = 0 To DataGridView1.Columns.Count - 1
            DataGridView1.Columns(i).[ReadOnly] = False
        Next

        ' 行の追加
        DataGridView1.Rows.Clear()
        DataGridView1.Rows.Add()
        DataGridView1.Rows(0).Cells(0).Value = "11"
        DataGridView1.Rows(0).Cells(1).Value = "12"
        DataGridView1.Rows(0).Cells(2).Value = "13"
        DataGridView1.Rows.Add()
        DataGridView1.Rows(1).Cells(0).Value = "21"
        DataGridView1.Rows(1).Cells(1).Value = "22"
        DataGridView1.Rows(1).Cells(2).Value = "23"

        ' DataGridViewのカラム幅読込
        DataGridView1.ReadColWidths()

        ' DataGridViewの入力可能文字指定
        Dim ColumnChars() As String
        ReDim ColumnChars(DataGridView1.Columns.Count - 1)
        ColumnChars(0) = "abc"
        ColumnChars(1) = "123"
        ColumnChars(2) = ""
        DataGridView1.ColumnChars = ColumnChars
    End Sub

    Private Sub Form1_FormClosed( _
        ByVal sender As Object, ByVal e As System.Windows.Forms.FormClosedEventArgs) _
        Handles Me.FormClosed
        ' DataGridViewのカラム幅保存
        DataGridView1.SaveColWidths()
    End Sub
End Class

★ちなみに・・・DataGridViewを使用する上でよく使う技
・DataGridViewの行追加方法
  DataGridView1.Rows.Add()

・DataGridViewの行削除方法
  DataGridView1.Rows.RemoveAt(0)

・DataGridViewのカラム削除方法(カラムヘッダも削除されます)
  DataGridView1.Columns.RemoveAt(0)

・DataGridViewの全行削除方法(注意:カラム幅の自動モードで例外が発生する可能性有り)
  DataGridView.Rows.Clear()

・DataGridViewの指定カラムでソートする方法
  DataGridView1.Sort(DataGridView1.Columns(0), ListSortDirection.Ascending)

・DataGridViewの行やカラムを入力禁止(ReadOnly)にする方法
  DataGridView1.Rows(0).ReadOnly = True
  DataGridView1.Columns(0).ReadOnly = True

・DataGridViewの指定セルの背景色を変更する方法
  DataGridView1.Rows(i).Cells("clmName").Style.BackColor = Color.LightSkyBlue

・DataGridViewに表示する先頭行(スクロール時の先頭行)を変更する方法
  DataGridView1.FirstDisplayedScrollingRowIndex = 10

・DataGridViewのスクロール範囲でセルが表示されているか確認する方法
  If DataGridView1.Rows(4).Cells("clmName").Displayed Then

・DataGridViewのカレントセルを取得/変更する方法
  Dim v as String = DataGridView1.CurrentCell.Value
  DataGridView1.CurrentCell = DataGridView1.Rows(4).Cells("clmName")

・DataGridViewのカレントセルのフォーカスを消す方法
  Private Sub DataGridView1_SelectionChanged( _
    ByVal sender As System.Object, ByVal e As System.EventArgs) _
  Handles DataGridView1.SelectionChanged
      Dim dgv As DataGridView = sender
      dgv.CurrentCell = Nothing
  End Sub