-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathMyDataGridView.vb
235 lines (183 loc) · 8.94 KB
/
MyDataGridView.vb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
Imports System.Text.RegularExpressions
Imports System.IO
Public Class MyDataGridView
Inherits DataGridView
'//////////////////////////////////////////////////////////////////////////////
' Speed up the datagridview scrolling
' For remote desktop check this thread:
' http://stackoverflow.com/questions/118528/horrible-redraw-performance-of-the-datagridview-on-one-of-my-two-screens
Sub New()
MyBase.New()
Me.DoubleBuffered = True
End Sub
' Switch off double buffering for row/column resize
Protected Overrides Sub OnMouseDown(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseDown(e)
If HitTest(e.X, e.Y).RowIndex = -1 OrElse HitTest(e.X, e.Y).ColumnIndex = -1 Then SetStyle(ControlStyles.OptimizedDoubleBuffer, False)
End Sub
Protected Overrides Sub OnMouseUp(ByVal e As System.Windows.Forms.MouseEventArgs)
MyBase.OnMouseUp(e)
If HitTest(e.X, e.Y).RowIndex = -1 OrElse HitTest(e.X, e.Y).ColumnIndex = -1 Then SetStyle(ControlStyles.OptimizedDoubleBuffer, True)
End Sub
'//////////////////////////////////////////////////////////////////////////////
' Check if the cell is empty
' Uses MS (column, row) notation !!!
Public ReadOnly Property IsEmpty(i As Integer, j As Integer) As Boolean
Get
Return Me(i, j).Value Is Nothing OrElse Me(i, j).Value Is DBNull.Value OrElse String.IsNullOrWhiteSpace(Me(i, j).Value.ToString())
End Get
End Property
Public ReadOnly Property IsNotEmpty(i As Integer, j As Integer) As Boolean
Get
Return Not (Me(i, j).Value Is Nothing OrElse Me(i, j).Value Is DBNull.Value OrElse String.IsNullOrWhiteSpace(Me(i, j).Value.ToString()))
End Get
End Property
' Process "Ctrl-?" pressed in DataGridView!!!!
'//////////////////////////////////////////////////////////////////////////////
Protected Overrides Sub OnKeyDown(e As KeyEventArgs)
If e.KeyCode = Keys.V And e.Control Then
PasteData(Me)
End If
If e.KeyCode = Keys.C And e.Control Then
Me.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText
End If
If e.KeyCode = Keys.X And e.Control Then
Me.ClipboardCopyMode = DataGridViewClipboardCopyMode.EnableWithoutHeaderText
If Me.GetCellCount(DataGridViewElementStates.Selected) > 0 Then
Try
' Add the selection to the clipboard.
Clipboard.SetDataObject(Me.GetClipboardContent())
' Clear selected cells
Dim cell As DataGridViewCell
For Each cell In Me.SelectedCells
cell.Value = ""
Next
Catch ex As System.Runtime.InteropServices.ExternalException
End Try
End If
End If
If e.KeyCode = Keys.Delete Then
Dim cell As DataGridViewCell
For Each cell In Me.SelectedCells
cell.Value = ""
Next
End If
MyBase.OnKeyDown(e)
End Sub
' Process "Ctrl-V" pressed in Cell Editing mode!!!!
'//////////////////////////////////////////////////////////////////////////////
Protected Overrides Sub OnEditingControlShowing(e As DataGridViewEditingControlShowingEventArgs)
Dim EditingTxtBox As TextBox = CType(e.Control, TextBox)
RemoveHandler EditingTxtBox.KeyDown, AddressOf MyDataGridView_EditingModeKeyDown
AddHandler EditingTxtBox.KeyDown, AddressOf MyDataGridView_EditingModeKeyDown
MyBase.OnEditingControlShowing(e)
End Sub
'//////////////////////////////////////////////////////////////////////////////
' Column select
Protected Overrides Sub OnColumnHeaderMouseClick(e As DataGridViewCellMouseEventArgs)
For i As Integer = 0 To Me.ColumnCount - 1
Me.Columns(i).SortMode = DataGridViewColumnSortMode.NotSortable
Next
If e.Button = Windows.Forms.MouseButtons.Left Then
If Me.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect Then
Me.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect
Me.Columns(e.ColumnIndex).Selected = True
End If
End If
MyBase.OnColumnHeaderMouseClick(e)
End Sub
' Row select
Protected Overrides Sub OnRowHeaderMouseClick(e As DataGridViewCellMouseEventArgs)
If e.Button = Windows.Forms.MouseButtons.Left Then
If Me.SelectionMode = DataGridViewSelectionMode.ColumnHeaderSelect Then
Me.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect
Me.Rows(e.RowIndex).Selected = True
End If
End If
MyBase.OnRowHeaderMouseClick(e)
End Sub
'//////////////////////////////////////////////////////////////////////////////
'//////////////////////////////////////////////////////////////////////////////////////////////////////////
'
' Private methods
'
'//////////////////////////////////////////////////////////////////////////////////////////////////////////
Private Sub PasteData(ByRef dgv As DataGridView)
Dim tmp() As String
Dim row_split() As String
Dim i, ii As Integer
Dim c, cc, r As Integer
Try
Dim str As String = Clipboard.GetText()
tmp = Regex.Split(str, vbCrLf)
If Clipboard.ContainsData("Biff5") OrElse Clipboard.ContainsData("Biff8") OrElse Clipboard.ContainsData("Biff12") Then
' The data is Excel table
' Get the size of the selected area from clipboard 'Format129' field
Dim iData As IDataObject = Windows.Forms.Clipboard.GetDataObject()
' Does not work without next line...???
Dim allFormats As [String]() = iData.GetFormats()
If iData.GetDataPresent("Format129") Then
Dim Stream As MemoryStream = iData.GetData("Format129")
Dim sr As StreamReader = New StreamReader(Stream)
Dim tstr As String = sr.ReadToEnd()
' Match strings like: "Cut 2R x 2C" or "Copy 2R x 2C"
Dim m As Match = Regex.Match(tstr, "^(Copy|Cut) (\d+)R x (\d+)C")
If m.Success Then
Dim groups As GroupCollection = m.Groups
Dim nr As Integer = CInt(groups.Item("2").Value)
' Correct the number of selected rows
If nr < tmp.Length Then
ReDim Preserve tmp(nr - 1)
End If
End If
End If
ElseIf Clipboard.ContainsData("ObjectLink") Then
Dim Stream As MemoryStream = Windows.Forms.Clipboard.GetData("ObjectLink")
Dim sr As StreamReader = New StreamReader(Stream)
If Regex.IsMatch(sr.ReadToEnd(), "Word\.Document") Then
' The data may come from Word table
' Trim last 'vbCrLf'
str = Regex.Replace(str, "\r?\n$", "")
tmp = Regex.Split(str, vbCrLf)
End If
End If
r = dgv.CurrentCellAddress.Y()
c = dgv.CurrentCellAddress.X()
If tmp.Length >= dgv.Rows.Count - r Then
dgv.Rows.Add(tmp.Length - (dgv.Rows.Count - r) + 1)
End If
For i = 0 To tmp.Length - 1
row_split = tmp(i).Split(vbTab)
cc = c
For ii = 0 To row_split.Length - 1
If cc > dgv.ColumnCount - 1 Then
' Save and restore 'SelectionMode'
Dim tmp_selectionmode As DataGridViewSelectionMode = Me.SelectionMode
Me.SelectionMode = DataGridViewSelectionMode.RowHeaderSelect
dgv.ColumnCount += 1
dgv.Columns(cc).SortMode = DataGridViewColumnSortMode.NotSortable
Me.SelectionMode = tmp_selectionmode
End If
dgv(cc, r).Value = row_split(ii).TrimStart
cc = cc + 1
Next
r = r + 1
Next
Catch ex As Exception
MsgBox(ex.Message.ToString, MsgBoxStyle.Critical)
End Try
End Sub
' Process "Ctrl-V" pressed in Cell Editing mode!!!!
'//////////////////////////////////////////////////////////////////////////////
Public Sub MyDataGridView_EditingModeKeyDown(ByVal sender As Object, ByVal e As System.Windows.Forms.KeyEventArgs)
Dim dgv As DataGridView = sender.EditingControlDataGridView
If (e.KeyCode = Keys.V AndAlso e.Control) Then
If Regex.IsMatch(Clipboard.GetText(), "[\t\n]") Then
' Paste in table mode
dgv.EndEdit()
PasteData(dgv)
End If
End If
End Sub
End Class