在VBA中使用动态列表验证

时间:2013-04-24 17:58:35

标签: validation vba

我是VBA编程的新手,我正在尝试使用Excel工作表中的列表验证数据。问题是每次从下拉列表中选择不同的条件时,列表的大小会有所不同。

例如:当我选择中国时,该列表会变成10个不同的卖家。范围A1到A10,但是当我选择日本时,我只有5个卖家,从A1到A5。

所以我每次都需要 Formula1 部分的新范围。

With Selection.Validation
    .Delete
    .Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
    xlBetween, Formula1:="=$Z$1:$Z$30"
    .IgnoreBlank = True
    .InCellDropdown = True
    .InputTitle = ""
    .ErrorTitle = ""
    .InputMessage = ""
    .ErrorMessage = ""
    .ShowInput = True
    .ShowError = True
End With

最好的方法是什么?

我知道如果我留下一个固定的范围它可以工作,但它看起来不行,因为它留下了很多空的空间,看起来并不整洁。

我希望这是可以理解的。

3 个答案:

答案 0 :(得分:1)

你可以用这样的东西得到列的非空单元格

Worksheets("Sheet1").Range("A1").End(xlDown)

然后,您只需将A1的Formula1属性构建为结果。

Dim strFormula1 as string
strFormula1 = "=$A$1:" & Worksheets("Sheet1").Range("A1").End(xlDown).Address()

希望它有所帮助,未测试可能有错误

答案 1 :(得分:1)

使用公式为

的命名范围

要创建名称,请转到公式/名称管理器/新建

在RefersTo中使用

选择一个名称,例如DataValidation
=OFFSET(Sheet1!$Z$1,0,0,COUNTA(Sheet1!$Z:$Z),1)

现在,您有一个动态间隔,可用于验证。

答案 2 :(得分:0)

另外两个答案更简单,但如果您有非连续的非空白单元格需要位于验证列表中,则无效。这种方法应该克服:)

您可以在VBA中使用自定义函数来返回已过滤的字符串地址。这将返回过滤后的地址,否则它将返回原始地址 IF 过滤后的地址不是有效范围。

注意如果返回的地址超过255个字符的限制,则可能会失败。

With Selection.Validation
.Delete
.Add Type:=xlValidateList, AlertStyle:=xlValidAlertStop, Operator:= _
xlBetween, Formula1:=GetAddress(Range("$Z$1:$Z$30"))
.IgnoreBlank = True
.InCellDropdown = True
.InputTitle = ""
.ErrorTitle = ""
.InputMessage = ""
.ErrorMessage = ""
.ShowInput = True
.ShowError = True
End With

将该功能放在普通代码模块中。

Function GetAddress(myRange As Range) As String

Dim cl As Range
Dim c As Long: c = 1
Dim tmpAddress As String

For Each cl In myRange
    If cl.Value <> vbNullString Then
        'Create a string value of cell address matching criteria'
        If tmpAddress = vbNullString Then
            tmpAddress = myRange.Cells(c).Address
        Else:
            tmpAddress = tmpAddress & "," & myRange.Cells(c).Address
        End If
    End If
    c = c + 1
Next

If Not Range(tmpAddress) Is Nothing Then
    GetAddress = "=" & tmpAddress
Else:
    MsgBox "There are no non-empty cells in this range.", vbInformation
    GetAddress = "=" & myRange.Address
End If

End Function