Excel 2010: how to use autocomplete in validation list

后端 未结 6 866
鱼传尺愫
鱼传尺愫 2020-12-05 00:31

I\'m using a large validation list on which a couple of vlookup() functions depend. This list is getting larger and larger. Is there a way to type the first letters of the l

6条回答
  •  执笔经年
    2020-12-05 01:16

    Here's another option. It works by putting an ActiveX ComboBox on top of the cell with validation enabled, and then providing autocomplete in the ComboBox instead.

    Option Explicit
    
    ' Autocomplete - replacing validation lists with ActiveX ComboBox
    '
    ' Usage:
    '   1. Copy this code into a module named m_autocomplete
    '   2. Go to Tools / References and make sure "Microsoft Forms 2.0 Object Library" is checked
    '   3. Copy and paste the following code to the worksheet where you want autocomplete
    '      ------------------------------------------------------------------------------------------------------
    '      - autocomplete
    '      Private Sub Worksheet_SelectionChange(ByVal Target As Range)
    '          m_autocomplete.SelectionChangeHandler Target
    '      End Sub
    '      Private Sub AutoComplete_Combo_KeyDown(ByVal KeyCode As msforms.ReturnInteger, ByVal Shift As Integer)
    '          m_autocomplete.KeyDownHandler KeyCode, Shift
    '      End Sub
    '      Private Sub AutoComplete_Combo_Click()
    '          m_autocomplete.AutoComplete_Combo_Click
    '      End Sub
    '      ------------------------------------------------------------------------------------------------------
    
    ' When the combobox is clicked, it should dropdown (expand)
    Public Sub AutoComplete_Combo_Click()
        Dim ws As Worksheet: Set ws = ActiveSheet
        Dim cbo As OLEObject: Set cbo = GetComboBoxObject(ws)
        Dim cb As ComboBox: Set cb = cbo.Object
        If cbo.Visible Then cb.DropDown
    End Sub
    
    ' Make it easier to navigate between cells
    Public Sub KeyDownHandler(ByVal KeyCode As MSForms.ReturnInteger, ByVal Shift As Integer)
        Const UP As Integer = -1
        Const DOWN As Integer = 1
    
        Const K_TAB_______ As Integer = 9
        Const K_ENTER_____ As Integer = 13
        Const K_ARROW_UP__ As Integer = 38
        Const K_ARROW_DOWN As Integer = 40
    
        Dim direction As Integer: direction = 0
    
        If Shift = 0 And KeyCode = K_TAB_______ Then direction = DOWN
        If Shift = 0 And KeyCode = K_ENTER_____ Then direction = DOWN
        If Shift = 1 And KeyCode = K_TAB_______ Then direction = UP
        If Shift = 1 And KeyCode = K_ENTER_____ Then direction = UP
        If Shift = 1 And KeyCode = K_ARROW_UP__ Then direction = UP
        If Shift = 1 And KeyCode = K_ARROW_DOWN Then direction = DOWN
    
        If direction <> 0 Then ActiveCell.Offset(direction, 0).Activate
    
        AutoComplete_Combo_Click
    End Sub
    
    Public Sub SelectionChangeHandler(ByVal Target As Range)
        On Error GoTo errHandler
    
        Dim ws As Worksheet: Set ws = ActiveSheet
        Dim cbo As OLEObject: Set cbo = GetComboBoxObject(ws)
        Dim cb As ComboBox: Set cb = cbo.Object
    
        ' Try to hide the ComboBox. This might be buggy...
        If cbo.Visible Then
            cbo.Left = 10
            cbo.Top = 10
            cbo.ListFillRange = ""
            cbo.LinkedCell = ""
            cbo.Visible = False
            Application.ScreenUpdating = True
            ActiveSheet.Calculate
            ActiveWindow.SmallScroll
            Application.WindowState = Application.WindowState
            DoEvents
        End If
    
        If Not HasValidationList(Target) Then GoTo ex
    
        Application.EnableEvents = False
    
        ' TODO: the code below is a little fragile
        Dim lfr As String
        lfr = Mid(Target.Validation.Formula1, 2)
        lfr = Replace(lfr, "INDIREKTE", "") ' norwegian
        lfr = Replace(lfr, "INDIRECT", "") ' english
        lfr = Replace(lfr, """", "")
        lfr = Application.Range(lfr).Address(External:=True)
    
        cbo.ListFillRange = lfr
        cbo.Visible = True
        cbo.Left = Target.Left
        cbo.Top = Target.Top
        cbo.Height = Target.Height + 5
        cbo.Width = Target.Width + 15
        cbo.LinkedCell = Target.Address(External:=True)
        cbo.Activate
        cb.SelStart = 0
        cb.SelLength = cb.TextLength
        cb.DropDown
    
        GoTo ex
    
    errHandler:
        Debug.Print "Error"
        Debug.Print Err.Number
        Debug.Print Err.Description
    ex:
        Application.EnableEvents = True
    End Sub
    
    ' Does the cell have a validation list?
    Function HasValidationList(Cell As Range) As Boolean
        HasValidationList = False
        On Error GoTo ex
        If Cell.Validation.Type = xlValidateList Then HasValidationList = True
    ex:
    End Function
    
    ' Retrieve or create the ComboBox
    Function GetComboBoxObject(ws As Worksheet) As OLEObject
        Dim cbo As OLEObject
        On Error Resume Next
        Set cbo = ws.OLEObjects("AutoComplete_Combo")
        On Error GoTo 0
        If cbo Is Nothing Then
            'Dim EnableSelection As Integer: EnableSelection = ws.EnableSelection
            Dim ProtectContents As Boolean: ProtectContents = ws.ProtectContents
    
            Debug.Print "Lager AutoComplete_Combo"
            If ProtectContents Then ws.Unprotect
            Set cbo = ws.OLEObjects.Add(ClassType:="Forms.ComboBox.1", Link:=False, DisplayAsIcon:=False, _
                                Left:=50, Top:=18.75, Width:=129, Height:=18.75)
            cbo.name = "AutoComplete_Combo"
            cbo.Object.MatchRequired = True
            cbo.Object.ListRows = 12
            If ProtectContents Then ws.Protect
        End If
        Set GetComboBoxObject = cbo
    End Function
    

提交回复
热议问题