Excel VBA создает имя из двух разных диапазонов для использования в списке (проверка данных)

Можно ли создать одно имя из двух разных диапазонов для использования в списке (проверка данных)?

У меня есть два столбца: A с содержимым строк с 1 по 3 и C с содержимым с 1 по 4 строки.

Я пытался использовать ThisWorkbook.Names.Add Name:="TheList", RefersTo:=Range("A1:A3,C1:C4"), но при вставке =TheList в поле проверки данных он говорит: «Источник списка должен быть списком с разделителями или ссылкой на одну строку или столбец».

Есть ли способ объединить значения из обоих столбцов?


person coldpumpkin    schedule 18.08.2018    source источник
comment
Диапазон для списка проверки данных должен быть непрерывным. Вы можете решить эту проблему, настроив непрерывный список в другом столбце. Например, начиная с D1, вы можете ввести =A1, затем D2=A2, D3=A3, D4=C1 и т. д. Добавьте свой именованный диапазон для диапазона D1:D6, и он должен работать.   -  person PeterT    schedule 18.08.2018
comment
@PeterT Можно ли это сделать с помощью VBA? Я действительно не хочу создавать еще один столбец, потому что это форма.   -  person coldpumpkin    schedule 18.08.2018


Ответы (1)


Поскольку Excel требует, чтобы в качестве списка проверки данных использовался непрерывный диапазон значений, у вас действительно есть два варианта.

  1. Создайте отдельный (возможно, связанный) непрерывный столбец значений в неиспользуемой области рабочей книги. Добавление определенного имени для диапазона рекомендуется, но не обязательно.

Для этого метода я бы создал список в столбце «Z» (или, возможно, на другом скрытом рабочем листе). Вот пример:

Option Explicit

Sub MakeValidationRange()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Sheet1")

    Dim dataRange As Range
    Set dataRange = ws.Range("A1:A3,C1:C3")

    Dim valRange As Range
    Set valRange = ws.Range("Z1")

    Dim entry As Variant
    For Each entry In dataRange
        valRange.Formula = "=" & entry.Address
        Set valRange = valRange.Offset(1, 0)
    Next entry
    Set valRange = ws.Range("Z1").CurrentRegion

    '--- alternate method using a named range
    ThisWorkbook.Names.Add Name:="TheList", RefersTo:=valRange

    Dim dropDownCell As Range
    Set dropDownCell = ws.Range("B1")
    dropDownCell.Validation.Delete
    dropDownCell.Validation.Add Type:=xlValidateList, _
                                AlertStyle:=xlValidAlertStop, _
                                Formula1:="=TheList"

    '--- alternate method without creating a named range
    Set dropDownCell = ws.Range("B2")
    dropDownCell.Validation.Delete
    dropDownCell.Validation.Add Type:=xlValidateList, _
                                AlertStyle:=xlValidAlertStop, _
                                Formula1:="=(" & valRange.Address & ")"

End Sub
  1. Второй способ — вообще не использовать другой диапазон, а просто создать список с разделителями. Это делает список «жестко закодированным», но, поскольку он создан с помощью VBA, это может не быть помехой в вашем случае.

Ключевым моментом здесь является определение списка методом .Validation.Add без знака равенства. Например, список проверки будет Red,Orange,Yellow,Green,Blue,Indigo,Violet. Никаких двойных кавычек. Нет пробелов. Нет равных. Вот пример:

Option Explicit

Sub MakeValidationList()
    Dim ws As Worksheet
    Set ws = ThisWorkbook.Sheets("Sheet1")

    Dim dataRange As Range
    Set dataRange = ws.Range("A1:A3,C1:C3")

    Dim dataList As String
    Dim entry As Variant
    For Each entry In dataRange
        dataList = dataList & entry.Value & ","
    Next entry
    '--- remove the last trailing comma
    dataList = Left$(dataList, Len(dataList) - 1)

    Dim dropDownCell As Range
    Set dropDownCell = ws.Range("B3")
    dropDownCell.Validation.Delete
    dropDownCell.Validation.Add Type:=xlValidateList, _
                                AlertStyle:=xlValidAlertStop, _
                                Formula1:=dataList
End Sub
person PeterT    schedule 18.08.2018
comment
Отлично, именно то, что мне нужно! Я пошел по второму способу. Однако, если я изменю значение любой ячейки, оно будет постоянно добавляться снова, не удаляя предыдущий список. Похоже, dropDownCell.Validation.Delete не работает :\ - person coldpumpkin; 18.08.2018
comment
Я добавил dataList = "" перед For Each entry, чтобы очистить содержимое. Это правильный путь? По крайней мере, теперь он работает правильно :P - person coldpumpkin; 18.08.2018
comment
Если вы находитесь в цикле, да, это один из лучших способов очистить строку. Другой будет dataList = vbNullString. - person PeterT; 19.08.2018