Как задать раскрывающийся список в VBA, который зависит от значений соседней ячейки?

#vba #drop-down-menu

Вопрос:

На первом листе у меня есть таблица под названием «Инвентарь», которая состоит из двух столбцов. В первом столбце содержатся все штрих-коды, а во Втором-Описание элемента.

Пример:

Штрих-код Описание
1111 Пункт 1
2222 Пункт 2
3333 Пункт 3
4444 Пункт 4
2222 Пункт 222

На втором листе у меня есть таблица под названием «Выход», где вы вводите штрих-код в ячейку в первом столбце, а в соседней ячейке во втором столбце отображается описание товара на основе штрих-кода, введенного с помощью формулы ВПР.

На данный момент я не столкнулся ни с какими проблемами, и все работает отлично.

Но некоторые штрих-коды имеют несколько разных описаний (как показано в примере со штрих-кодом «2222»), и я хочу иметь возможность изменить описание элемента с помощью выпадающего списка, в котором отображаются только разные элементы, имеющие один и тот же штрих-код.

Например, если я введу штрих-код «2222», в соседней ячейке появится «Пункт 2». Я хочу установить раскрывающийся список в ячейке описания, в котором будут отображаться пункт 2 и пункт 222, и выбрать тот, который я хочу.

Можете ли вы помочь мне решить эту проблему?

     Sub Data_Val()

    dim Inventory_Sheet, Out_Sheet as Worksheet

    set Inventory_sheet = Thisworkbook.worksheets("Inventory")
    set Out_Sheet = thisworkbook.worksheets("Out")

    Out_Sheet.activate

    Range("B2").Select
    With Selection.Validation
        .Delete
        .Add Type:=xlValidateList, _
         AlertStyle:=xlValidAlertStop, _
         Operator:=xlBetween, _
         Formula1:="='Inventory'!$B$2:$B$6"
        .IgnoreBlank = True
        .InCellDropdown = True
        .InputTitle = ""
        .ErrorTitle = ""
        .InputMessage = ""
        .ErrorMessage = ""
        .ShowInput = True
        .ShowError = True
    End With
    End Sub 
 

Комментарии:

1. Теперь, когда вы говорите «Стол», вы имеете в виду реальный Table ( ListObject )? То же самое для второго листа.

2. Да, я имею в виду таблицы как ListObject, И единственное, что я пробовал, — это Выбор. Утверждение. Удалить. Добавьте тип:=xlValidateList, Стиль оповещения:=xlValidAlertStop, Оператор:= _ xlBetween, Формула 1:=»=’Inventory_Table’!$B$2:$F$6″ .IgnoreBlank = True . InCellDropdown = Истина . InputTitle = «» .ErrorTitle = «» .InputMessage = «». ErrorMessage = «» .ShowInput = True . showError = True Заканчивается, И этот код показывает все описания, независимо от введенного штрих-кода.

3. Пожалуйста, отредактируйте свой вопрос и поместите код туда! Такой код не может быть понят в комментарии. Я подготовлю фрагмент кода с использованием события, чтобы автоматически создать необходимую проверку, когда что — то изменится в инвентарном листе. Пожалуйста, назовите лист, на котором хранится таблица «Инвентаризация», таким же («Инвентаризация»)…

Ответ №1:

Пожалуйста, используйте следующий подход а:

  1. В следующем коде требуется ссылка на «Среду выполнения сценариев Microsoft». С этим можно справиться и без него, используя позднюю привязку, но вы не воспользуетесь предложениями intellisense. Используйте следующий код, чтобы автоматически создать его:
 Sub addScrRunTimeRef()
  'Add a reference to 'Microsoft Scripting Runtime':
  'In case of error ('Programmatic access to Visual Basic Project not trusted'):
  'Options->Trust Center->Trust Center Settings->Macro Settings->Developer Macro Settings->
  '         check "Trust access to the VBA project object model"
  Application.VBE.ActiveVBProject.References.AddFromFile "C:WindowsSysWOW64scrrun.dll"
End Sub
 

Запустите код и сохраните книгу!

  1. Создайте Public переменную в стандартном модуле:
 Public dictDescript As Scripting.Dictionary
 
  1. Скопируйте следующий код в модуль кода листа «Инвентаризация» :
 Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
    Dim rng As Range, arrT, i As Long
   Set rng = Me.ListObjects("Inventory").DataBodyRange
   If Not Intersect(Target, rng) Is Nothing Then
        Set dictDescript = New Scripting.Dictionary
        arrT = rng.value                      'to make code faster
        For i = 1 To UBound(arrT)
            'update the dictionary
            If Not dictDescript.Exists(arrT(i, 1)) Then
                dictDescript.Add arrT(i, 1), arrT(i, 2)
            Else
                dictDescript(arrT(i, 1)) = dictDescript(arrT(i, 1)) amp; "|" amp; arrT(i, 2)
            End If
        Next i
   End If
End Sub
 

Он обновит необходимый словарь, когда что-то будет изменено в таблице.

  1. Скопируйте следующий код в модуль кода таблицы с сохранением «Вне».:
 Option Explicit

Private Sub Worksheet_Change(ByVal Target As Range)
   Dim rngO As Range
   Set rngO = Me.ListObjects("Out").DataBodyRange.Columns(1)
   
   If Not Intersect(Target, rngO) Is Nothing Then
       If dictDescript Is Nothing Then 'if nothing has been placed in the dictionary:
            Dim rng As Range, arrT, i As Long, strCondition As String
            Set rng = Worksheets("Inventory").ListObjects("Inventory").DataBodyRange
            Set dictDescript = New Scripting.Dictionary
             arrT = rng.value                      'to make code faster
             For i = 1 To UBound(arrT)
                 'update the dictionary
                 If Not dictDescript.Exists(arrT(i, 1)) Then
                     dictDescript.Add arrT(i, 1), arrT(i, 2)
                 Else
                     dictDescript(arrT(i, 1)) = dictDescript(arrT(i, 1)) amp; "," amp; arrT(i, 2)
                 End If
             Next i
        End If
       'return the validation list from the dictionary:
        strCondition = dictDescript(Target.value)
        If strCondition = "" Then  'if a wrong string has been inputed (not one of the barcodes in Inventory sheet)
            MsgBox Target.value amp; " barcode, does not exist in ""Inventory"" sheet...", vbInformation, _
                                                                                         "No appropriate barcode input"
            Target.Offset(0, 1).Validation.Delete: Target.Offset(0, 1).value = ""
            Exit Sub
        End If
        'create the validation:
        Target.Offset(0, 1).value = ""
        With Target.Offset(0, 1).Validation
            .Delete
            .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:=xlBetween, Formula1:=strCondition
            .IgnoreBlank = True
            .InCellDropdown = True
            .ShowInput = True
            .ShowError = True
        End With
    End If
End Sub
 

Поиграйте со своими штрих-кодами и отправьте несколько отзывов.

Комментарии:

1. @Энтони, разве вы не нашли время, чтобы протестировать предложенное выше решение? Если его протестировать, разве он не вел себя так, как вам нужно?