DataGridViewでセルのコピー&ペースト。
Excelの動きに近づくように四苦八苦・・・
・コピー元から複数行へのコピー
・複数行から複数行へのコピー
が出来るようになっています
●フォームロード
Private Sub Form1_Load(ByVal sender As Object, ByVal e As System.EventArgs) Handles Me.Load
''テーブルを作成
Dim dataSet1 As DataSet = New DataSet("商品マスター")
Dim dataTable1 As DataTable = dataSet1.Tables.Add("商品テーブル")
Dim dataClumn1 As DataColumn = dataTable1.Columns.Add("ID")
Dim dataClumn2 As DataColumn = dataTable1.Columns.Add("商品")
Dim dataClumn3 As DataColumn = dataTable1.Columns.Add("値段")
Dim dataClumn4 As DataColumn = dataTable1.Columns.Add("個数")
''テーブルにデータを追加
dataTable1.Rows.Add(New Object() {1, "みかん", 100, "3個"})
dataTable1.Rows.Add(New Object() {2, "パイナップル", 300, "3個"})
dataTable1.Rows.Add(New Object() {3, "バナナ", 120, "1房"})
dataTable1.Rows.Add(New Object() {"", "", "", ""})
dataTable1.Rows.Add(New Object() {"", "", "", ""})
dataTable1.Rows.Add(New Object() {"", "", "", ""})
''データグリッドの行の追加と削除、データ編集を不許可にする
dataTable1.DefaultView.AllowNew = False
dataTable1.DefaultView.AllowDelete = False
dataTable1.DefaultView.AllowEdit = True
''データグリッドにテーブルを表示する
''(データソースにDataViewを使う)
'DataGridView1.SelectionMode = DataGridViewSelectionMode.FullRowSelect
DataGridView1.DataSource = dataTable1
End Sub
●各キー動作
''' <summary>
''' 選択行コピー・削除・切り取り
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub DataGridView1_KeyDown1(sender As Object, e As KeyEventArgs) Handles DataGridView1.KeyDown
If e.Control And e.KeyCode = Keys.C Then
''*** Ctrl+C 選択行コピー***
copyRow()
ElseIf e.KeyCode = Keys.Delete Then
''*** Delete 選択行削除***
deleteRow()
ElseIf e.Control And e.KeyCode = Keys.X Then
''*** Ctrl+X 選択行切り取り***
copyRow()
deleteRow()
ElseIf e.Control And e.KeyCode = Keys.V Then
''*** Ctrl+V 選択行ペースト***
CopyPaste(sender, e)
End If
End Sub
●コピー
''' <summary>
''' コピー
''' </summary>
Private Sub copyRow()
DataGridView1.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText
If DataGridView1.GetClipboardContent() IsNot Nothing Then
Clipboard.SetDataObject(DataGridView1.GetClipboardContent())
Else
''何もコピーしない
Return
End If
End Sub
●削除
''' <summary>
''' 削除
''' </summary>
Private Sub deleteRow()
For Each c As DataGridViewCell In DataGridView1.SelectedCells
Dim iR As Integer = c.RowIndex
Dim iC As Integer = c.ColumnIndex
If 4 <= c.ColumnIndex Then
''ヘッダ列以外
DataGridView1.Rows(iR).Cells(iC).Value = ""
End If
Next
End Sub
●ペースト
DataGridViewSelectionMode.FullRowSelectでないとDataGridView.SelectedRowsが取得できないようなので、苦肉の策でSelectedCellsから選択行のインデックスを取得しています(あんまりイケてないかも・・・)
''' <summary>
''' ペースト
''' </summary>
''' <param name="sender"></param>
''' <param name="e"></param>
Private Sub CopyPaste(sender As Object, e As KeyEventArgs)
Try
If DataGridView1.CurrentCell Is Nothing Then
Return
End If
Dim dt As DataTable = CType(DataGridView1.DataSource, DataTable)
Dim RowIndexList(dt.Rows.Count * dt.Columns.Count) As String
Dim ColIndexList(dt.Rows.Count * dt.Columns.Count) As String
Dim insertRowIndexMin As Integer = dt.Rows.Count ''選択行の最小インデックス
Dim insertRowIndexMax As Integer = 0 ''選択行の最大インデックス
Dim insertColIndexMin As Integer = dt.Columns.Count ''選択列の最小インデックス
Dim insertColIndexMax As Integer = 0 ''選択列の最大インデックス
For Each c As DataGridViewCell In DataGridView1.SelectedCells
''選択行列のインデックスに入れ替えていく
If insertRowIndexMin > c.RowIndex Then insertRowIndexMin = c.RowIndex
If insertRowIndexMax <= c.RowIndex Then insertRowIndexMax = c.RowIndex
If insertColIndexMin > c.ColumnIndex Then insertColIndexMin = c.ColumnIndex
If insertColIndexMax <= c.ColumnIndex Then insertColIndexMax = c.ColumnIndex
Next
Dim selectRowNum As Integer = (insertRowIndexMax - insertRowIndexMin) + 1 ''選択行数
Dim selectColNum As Integer = (insertColIndexMax - insertColIndexMin) + 1 ''選択列数
'クリップボードの内容を取得して、行で分ける
Dim pasteText As String = Clipboard.GetText()
If pasteText Is Nothing Then
Return
End If
Dim lines As String() = getLine(pasteText)
'タブで分割
Dim ValColNum As Integer = lines(0).Split(ControlChars.Tab).Length ''コピー列数
Dim ValRowNum As Integer = lines.Length ''コピー行数
Dim isHeader As Boolean = True
Dim num As Integer = 0
Dim num2 As Integer = 0
For i As Integer = insertRowIndexMin To insertRowIndexMax
If num = 0 Or (num Mod ValRowNum = 0 And selectRowNum Mod ValRowNum = 0) Then
If ValColNum < selectColNum And selectRowNum Mod ValRowNum = 0 Then
''コピー列数より選択列数が多いときのみ
For j As Integer = insertColIndexMin To insertColIndexMax
If num2 = 0 Or (num2 Mod ValColNum = 0 And selectColNum Mod ValColNum = 0) Then
setRow(lines, i, j, dt)
End If
num2 = num2 + 1
Next j
Else
setRow(lines, i, insertColIndexMin, dt)
End If
End If
num = num + 1
Next i
Catch ex As System.IO.FileNotFoundException
Debug.Print("コピーに失敗しました")
Return
End Try
End Sub
●1行ごとに各セルの値を設定
''' <summary>
''' 1行ごとに各セルの値を設定
''' </summary>
''' <param name="lines"></param>
''' <param name="insertRowIndex"></param>
''' <param name="insertColIndexMin"></param>
''' <param name="dt"></param>
Public Sub setRow(lines, insertRowIndex, insertColIndexMin, dt)
Dim rowIndex As Integer = insertRowIndex
For Each line As String In lines
'タブで分割
Dim vals As String() = line.Split(ControlChars.Tab)
'各セルの値を設定
setCol(rowIndex, insertColIndexMin, vals, dt)
'次の行へ
rowIndex += 1
''行が無ければ終了
If rowIndex >= dt.Rows.Count Then
Return
End If
'End If
Next line
End Sub
●クリップボードの内容を取得して、行で分ける
''' <summary>
''' クリップボードの内容を取得して、行で分ける
''' </summary>
''' <returns></returns>
Public Function getLine(pasteText)
Dim lines As String()
pasteText = pasteText.Replace(vbCrLf, vbLf)
pasteText = pasteText.Replace(vbCr, vbLf)
pasteText = pasteText.TrimEnd(New Char() {vbLf})
lines = pasteText.Split(vbLf)
Return lines
End Function
●各セルの値を設定
''' <summary>
''' 各セルの値を設定
''' </summary>
''' <param name="rowIndex"></param>
''' <param name="insertColIndexMin"></param>
''' <param name="vals"></param>
''' <param name="dt"></param>
Public Sub setCol(rowIndex, insertColIndexMin, vals, dt)
Dim row As DataGridViewRow = DataGridView1.Rows(rowIndex)
Dim i As Integer
Dim colIndex As Integer = insertColIndexMin
For i = 0 To vals.Length - 1
row.Cells(colIndex).Value = vals(i)
colIndex = colIndex + 1
''列が無ければ終了
If colIndex >= dt.Columns.Count Then
Exit For
End If
Next i
End Sub
参考記事:
DataGridViewで選択されたセルをクリップボードにコピーできるようにする
https://dobon.net/vb/dotnet/datagridview/clipboardcopy.html
C# DataGridViewでの値のコピー&ペーストの実装
https://effect.hatenablog.com/entry/2018/10/02/030816