Results 1 to 5 of 5

Thread: Copying and Pasting in a DGV

Threaded View

  1. #5
    Hyperactive Member
    Join Date
    Apr 2010
    Posts
    420

    Re: Copying and Pasting in a DGV

    This is one That is virtually but not quite finished yet (and some bits have been copied form various sources and altered), Copy paste works ok, the only issue is in deleting rows, can only delete one row at a time, even if more are selected, I am currently working to fix this. However the rest of it works well and the cut / copy paste has the same rules as excel. You can also cut / copy paste from an external source to the DGV.

    There is a known bug, that if you actually select the cell and are editing the actual contents and then right click, two pop up windows appear, the one I defined and another one which looks to be a pre defined one from somewhere.

    If it is defined as read only then you can only copy

    Any suggested improvements or bug fixes welcome

    Code:
    Public Class DataGridViewCutPaste
        Inherits DataGridView
    
        Private WithEvents contextMenuDataGrid As New ContextMenuStrip
    
        Public Sub New()
    
        End Sub
    
        Public Property BindingSource() As BindingSource     ' this now acts as get & set to the same name prefixed with underscore _
        Public Property CutPasteReadWrite() As Boolean = False    ' allows alteration to the datagridview
    
        Private Function CheckBindingsource(ByRef aBindingsource As BindingSource)
            If aBindingsource Is Nothing Then
                MsgBox("bindingsource not defined")
                CheckBindingsource = False
                Exit Function
            End If
            CheckBindingsource = True
    
        End Function
    
    
        Private Sub ValidateData_Click(ByVal sender As System.Object, ByVal e As System.Windows.Forms.KeyEventArgs) Handles Me.KeyDown
            If _CutPasteReadWrite = True Then
                Select Case e.KeyCode         'read write options
    
                    Case 86   'ctrl V
                        PasteClipboardValue()
                    Case 88   'ctrl X
                        cut()
                End Select
            End If
            Select Case e.KeyCode         ' read  options
                Case 67 '  ctrl c
                    CopyToClipboard()
            End Select
    
    
            'MsgBox(e.KeyCode)
        End Sub
        Private Sub me_CellMouseDown(sender As Object, e As System.Windows.Forms.DataGridViewCellMouseEventArgs) Handles Me.CellMouseDown
            If e.Button = MouseButtons.Right And e.RowIndex > -1 Then
                Me.CurrentCell = Me(e.ColumnIndex, e.RowIndex)
                If contextMenuDataGrid.Items.Count = 0 Then
                    If _CutPasteReadWrite = True Then
    
                        contextMenuDataGrid.Items.Add("Add Row")
                        contextMenuDataGrid.Items.Add("Add 10 Rows")
                        contextMenuDataGrid.Items.Add("Insert Row at Cursor")
                        contextMenuDataGrid.Items.Add("Delete Row")
                        contextMenuDataGrid.Items.Add("Paste")
                        contextMenuDataGrid.Items.Add("Cut")
                    End If
                    contextMenuDataGrid.Items.Add("Copy")
    
    
                End If
                contextMenuDataGrid.Show(Me, e.Location)
            End If
        End Sub
    
        Private Sub contextMenuDataGrid_Click(sender As Object, ByVal e As System.Windows.Forms.ToolStripItemClickedEventArgs) Handles contextMenuDataGrid.ItemClicked
            contextMenuDataGrid.Hide()
            If CheckBindingsource(_BindingSource) = False Then Exit Sub
    
            Select Case e.ClickedItem.Text
                Case "Copy"
                    CopyToClipboard()
                Case "Cut"
                    cut()
                Case "Paste"
                    PasteClipboardValue()
                Case "Insert Row at Cursor"
                    insertRowAtCursor()
                Case "Add Row"
                    _BindingSource.AddNew()
                Case "Add 10 Rows"
                    Add10Rows()
    
                Case "Delete Row"
                    DeleteRow()
            End Select
        End Sub
    
        Public Sub CopyToClipboard()            ' public so it can be called off the toolstrip on the master form
            Dim dataObj As DataObject = Me.GetClipboardContent
            If Not IsNothing(dataObj) Then
                Clipboard.SetDataObject(dataObj)
            End If
        End Sub
        Public Sub cut()                           ' public so it can be called off the toolstrip on the master form
            CopyToClipboard()
            For counter As Integer = 0 To Me.SelectedCells.Count - 1
                Me.SelectedCells(counter).Value = String.Empty
            Next
        End Sub
        Sub DeleteRow()
            Dim SelectedRowCount As Integer = Me.SelectedCells.OfType(Of DataGridViewCell)().Select(Function(x) x.RowIndex).Distinct().Count()
            If CheckBindingsource(_BindingSource) = False Then Exit Sub
            _BindingSource.RemoveCurrent()
        End Sub
    
        Sub Add10Rows()
            Dim startingCell As Integer = Me.CurrentCell.ColumnIndex
            If CheckBindingsource(_BindingSource) = False Then Exit Sub
            For i = 1 To 10
                _BindingSource.AddNew()
            Next
            Me.CurrentCell = Me.Rows(0).Cells(startingCell)
        End Sub
        Sub insertRowAtCursor()
            If CheckBindingsource(_BindingSource) = False Then Exit Sub
            Dim DataGridViewCursorCurrentRow As Integer = Me.CurrentRow.Index
            Dim startingCell As Integer = Me.CurrentCell.ColumnIndex
            _BindingSource.AddNew()
            Dim dataGridROwCount As Integer = Me.RowCount
            Dim j As Integer
            For j = 0 To Me.Columns.Count - 1
                For i = dataGridROwCount - 1 To DataGridViewCursorCurrentRow + 1 Step -1
                    Me.Rows(i).Cells(j).Value = Me.Rows(i - 1).Cells(j).Value
                    Me.Rows(i - 1).Cells(j).Value = ""
                Next
            Next
            Me.CurrentCell = Me.Rows(0).Cells(startingCell)
    
        End Sub
    
        Private Sub PasteClipboardValue()
            If Me.SelectedCells.Count = 0 Then
                MessageBox.Show("No Cell selected", "Paste")
                Exit Sub
            End If
    
            Dim StartingCell As DataGridViewCell = GetStartingCell(Me)
            Dim SelectedrowCount = Me.SelectedCells.OfType(Of DataGridViewCell)().Select(Function(x) x.RowIndex).Distinct().Count()
            Dim SelectedColumnCount = Me.SelectedCells.OfType(Of DataGridViewCell)().Select(Function(x) x.ColumnIndex).Distinct().Count()
    
            Dim startingCellRow = StartingCell.RowIndex
            Dim StartingCellColumn = StartingCell.ColumnIndex
    
            Dim clipBoardValue As Dictionary(Of Integer, Dictionary(Of Integer, String)) = ClipboardValues(Clipboard.GetText.TrimEnd(vbCr, vbLf))  'trim end needed due to excel 
            Dim clipboardRowCount As Integer = clipBoardValue.Keys.Count
    
            Dim clipboardArray(1000, 30) As String
            Dim i As Integer = 0
            Dim j As Integer = 0
            Dim maxArrayCol As Integer = 0
            Dim maxarrayrow As Integer = 0
    
            For Each rowkey As Integer In clipBoardValue.Keys
                Dim startingCellColumnIndex As Integer = StartingCell.ColumnIndex
                For Each cellkey As Integer In clipBoardValue(rowkey).Keys
                    Dim cell As DataGridViewCell = Me(startingCellColumnIndex, startingCellRow)
                    cell.Value = clipBoardValue(rowkey)(cellkey)
                    'If cell.Value Is Nothing Then
                    clipboardArray(i, j) = vbNull
                    '  Else
                    clipboardArray(i, j) = cell.Value.trim(vbCr, vbLf)
                    ' End If
    
                    j += 1     'j = j + 1
                Next
                If j > maxArrayCol Then maxArrayCol = j
                j = 0
                i += 1       'i = i + 1
            Next
            maxarrayrow = i
            Dim maxClipboardCol As Integer = maxArrayCol
            'clipboadarray Contains the clipboard with maxcolrow & col giving the number of rows & colums  subtract 1 to get array
            Dim cj As Integer = 0
            Dim cc As Integer = 0
    
            If SelectedrowCount = 1 And SelectedColumnCount = 1 Then   ' this is if only a starting postion has been specified
                Dim rowsLefttotheBottom = Me.RowCount - startingCellRow
                Dim columnsLefttotheRight = Me.ColumnCount - StartingCellColumn
                If rowsLefttotheBottom >= maxarrayrow Then SelectedrowCount = maxarrayrow Else SelectedrowCount = SelectedrowCount + rowsLefttotheBottom - 1
                If columnsLefttotheRight >= maxArrayCol Then SelectedColumnCount = maxArrayCol Else SelectedColumnCount = SelectedColumnCount + columnsLefttotheRight - 1
            End If
            Dim rowsFilled As Integer
            Dim rowsFilledMultiple = False
            Dim columnsFilledMultiple = False
            If SelectedrowCount Mod maxarrayrow = 0 Then rowsFilledMultiple = True Else rowsFilledMultiple = False
            If SelectedColumnCount Mod maxArrayCol = 0 Then columnsFilledMultiple = True Else columnsFilledMultiple = False
            For i = startingCellRow To startingCellRow + SelectedrowCount - 1
                For j = StartingCellColumn To StartingCellColumn + SelectedColumnCount - 1
                    Dim cell As DataGridViewCell = Me(j, i)
                    cell.Value = clipboardArray(cj, cc)
                    Application.DoEvents()
                    cc += 1     'cc = cc + 1
                    Dim numberOfColsLeft = StartingCellColumn + SelectedColumnCount - 1
                    If cc >= maxClipboardCol Then
                        If cc >= maxClipboardCol Then
                            cc = 0
                            If columnsFilledMultiple = False Then Exit For
                        End If
                    End If
                Next
                rowsFilled += 1
                cc = 0
                cj += 1      'cj = cj + 1
                If cj >= clipboardRowCount Then
                    cj = 0
                    If rowsFilledMultiple = False Then Exit For
                End If
            Next
    
        End Sub
    
        Private Function GetStartingCell(dgView As DataGridView) As DataGridViewCell
            If dgView.SelectedCells.Count = 0 Then Return Nothing
            Dim rowIndex As Integer = dgView.Rows.Count - 1
            Dim ColIndex As Integer = dgView.Columns.Count - 1
            For Each dgvcell As DataGridViewCell In dgView.SelectedCells
    
                If dgvcell.RowIndex < rowIndex Then rowIndex = dgvcell.RowIndex
                If dgvcell.ColumnIndex < ColIndex Then ColIndex = dgvcell.ColumnIndex
            Next
            Return dgView(ColIndex, rowIndex)
        End Function
        Private Function ClipboardValues(clipboardvalue As String) As Dictionary(Of Integer, Dictionary(Of Integer, String))
            Dim lines() As String = clipboardvalue.Split(CChar(Environment.NewLine))
            Dim copyValues As Dictionary(Of Integer, Dictionary(Of Integer, String)) = New Dictionary(Of Integer, Dictionary(Of Integer, String))
            For i As Integer = 0 To lines.Length - 1
                copyValues.Item(i) = New Dictionary(Of Integer, String)
                Dim linecontent() As String = lines(i).Split(ChrW(Keys.Tab))
                If linecontent.Length = 0 Then
                    copyValues(i)(0) = String.Empty
                Else
                    For j As Integer = 0 To linecontent.Length - 1
                        copyValues(i)(j) = linecontent(j)
                    Next
                End If
            Next
            Return copyValues
        End Function
    
    End Class
    Last edited by Signalman; Oct 11th, 2021 at 06:35 PM.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  



Click Here to Expand Forum to Full Width