我最近研究 range.Validation.type=xlValidateList 并希望防止粘贴和剪切并禁止在包含下拉列表的单元格中输入错误的字符(并且可以输入与列表中的条目匹配的字符并显示那个条目)。
在处理最后一件不好的事情时(剪切下拉菜单并将其粘贴到另一个已经包含下拉菜单的单元格中),我发现了一种禁止粘贴和剪切数据验证列表的简单方法,该方法确实允许根据内容进行进一步处理已输入,
以下代码必须在工作表模块上。
它可以防止用户破坏单元格上的数据验证,因此使用 Application.Undo 恢复到不再需要粘贴或剪切之前的状态。
我不知道这是否有区别,但我保护了工作表并解锁了用户可能更改的单元格。
Private Function HasValidation(ByVal rng As Range) As Boolean
' See: https://superuser.com/questions/870926/restrict-paste-into-dropdown-cells-in-excel
' Returns True if every cell in Range r uses Data Validation
On Error Resume Next
Dim rngType: rngType = rng.Validation.Type
HasValidation = (Err.number = 0)
End Function
Private Sub Worksheet_SelectionChange(ByVal Target As Range)
' Switch DragAndDrop on/off on a range containing DataValidation
Dim modeCutCopy: modeCutCopy = Application.CutCopyMode
Dim usesValidation: usesValidation = HasValidation(Target)
If ((usesValidation = True) And (modeCutCopy <> 0)) Then Application.CutCopyMode = False ' MUST reset to avoid copying / cutting xlValidateList into another xlValidateList
' Turn DragAnddDrop on/off depending on if a cell uses Validation or not
If (usesValidation = Application.CellDragAndDrop) Then Application.CellDragAndDrop = (Not usesValidation)
GoTo SKIP
' Don't allow DragAndDrop if Target intersects with specified ranges
Dim myRange As Range
Set myRange = Worksheets("Evenementen").Range("Oordeel", "Waardering")
Dim rngIntersect As Range
Set rngIntersect = Application.Intersect(Target, myRange)
Application.CellDragAndDrop = (rngIntersect Is Nothing)
'' CheckInputValidationList(Target) ' Sophisticated testing and actions depending on the selection made
'' CheckInputValidationList(Target, myRange) ' Sophisticated testing and actions depending on the selection made for specific ranges
SKIP:
Debug.Print "SelectionChange " & Target.Address & " usesValidation=" & usesValidation & " cellDragAndDrop=" & Application.CellDragAndDrop
End Sub
在这种情况下,有两个包含(不同)数据验证列表的命名范围。
只要用户点击一个单元格,就会检查该单元格是否使用数据验证。
如果是这样,剪切和粘贴将被关闭,并且 CutCopyMode 将被清除,直到用户选择另一个单元格。
重要的是在执行任何更改某些内容的 VBA 代码之前检索当前的 CutCopyMode,因为当某些内容发生更改时,VBA 会自动将 CutCopyMode 从 xlCut 或 xlCopy 更改为 0。
需要该初始状态以避免将下拉列表粘贴到另一个上。
Worksheet_SelectionChange 子例程包含 SKIPPED 代码,如果用户访问两个范围之一中的单元格,该代码会执行类似的操作。
它还包含(变成注释)代码以在用户选择单元格时执行其他操作。该代码也可能放在 worksheet_Change 中