Validation 从验证公式中获取动态范围的地址

Validation 从验证公式中获取动态范围的地址,validation,vba,excel,Validation,Vba,Excel,“我的代码”使用由依赖于单元格地址的偏移量公式给出的范围,在单元格上设置列表验证 由于此验证是在已经有内容的单元格上以编程方式设置的,因此我需要一个函数来确定单元格的现有内容是否违反验证 使用以下代码进行测试时遇到问题: Sub test() Dim sht As Worksheet Dim rng As Range Dim formula As String Dim rangeName As String Set sht = ThisWorkbook.S

“我的代码”使用由依赖于单元格地址的
偏移量
公式给出的范围,在单元格上设置列表验证

由于此验证是在已经有内容的单元格上以编程方式设置的,因此我需要一个函数来确定单元格的现有内容是否违反验证

使用以下代码进行测试时遇到问题:

Sub test()
    Dim sht As Worksheet
    Dim rng As Range
    Dim formula As String
    Dim rangeName As String
    Set sht = ThisWorkbook.Sheets("Sheet1")
    With sht
        .Range("a1").Value = "a"
        .Range("a2").Value = "aa"
        Set rng = .Range("b1")
        formula = "=OFFSET(INDIRECT(ADDRESS(ROW(),COLUMN())),0,-1,2,1)"
        rng.Validation.Add Type:=xlValidateList, Formula1:=formula
        rangeName = Replace(formula, "=", "")
        Set ResultRange = .Range(rangeName).Find(rng.Value, lookat:=xlWhole)
        If ResultRange Is Nothing Then
            Debug.Print "violates validation"
        Else
            Debug.Print "validated"
        End If
    End With
End Sub
此测试应使用单元格
A1
A2
的内容对单元格
B1
进行下拉验证,然后检查
B1
的内容是否与这些单元格中的任何一个相匹配。但它在
Set ResultRange
行失败,出现以下错误:

对象“\u Global”的方法“Range”失败。

我认为问题在于,当我调用
范围(rangeName)
时,Excel不知道将
行()
列()
应用到哪个单元格,因此我需要以某种方式计算
公式
解析为该单元格的地址——在本例中,
$A$1:$A$2
,这样我就可以将该值赋给
RangeName

因此,给定我要传递动态参数的
OFFSET()
公式,如何获得该公式返回的范围,该范围由
rng
指定


编辑:由于公式可能会根据不同的情况而变化,我正在寻找一种解决方案,即给定从某个范围开始的
OFFSET()
公式,返回该公式给定的范围。硬编码的解决方案是不可接受的,因为工作表中有几种不同的
OFFSET()
公式,每次公式更改时都更改验证测试的代码是不切实际的。

这并不漂亮,但可以做您想做的事情,您必须已经定义了
rng
,和
rng
不得位于A列:

rangeName = .Range(.Cells(rng.Row, rng.Column - 1), .Cells(rng.Row + 1, rng.Column - 1)).Address
另一个注意事项是,您的验证默认情况下将忽略空白,因此您可能希望更新if以检查空白:

If ResultRange Is Nothing And rng.Value <> "" then
    Debug.Print "violates validation"
Else
    Debug.Print "validated"
End If

谢谢,但这需要我在更改
OFFSET()
公式时更改这行代码。我需要一些不是硬编码的东西;我会相应地修改我的问题,所以。。。在您假设的工作环境中,偏移公式是通过代码计算还是硬编码为字符串?@DanielCook,偏移公式是硬编码为命名范围。我只是想弄清楚。。。因此,您的意思是,在实际用例中,您的公式不是像
“=OFFSET(INDIRECT(ADDRESS(ROW(),COLUMN()))、0、-1,2,1)”
,而是像
“=NamedRange”
?我特别想澄清的是,如果您期望的是
=OFFSET(A1,2,3,B1,B2)
,或者数字将被硬编码。@DanielCook:列和行偏移将被硬编码,就像您刚才给出的OFFSET(间接(…)示例一样。不过,应用程序中还有几个不同的OFFSET()公式,因此最实用的解决方案是使用函数ReturnRange(initialRange作为Range,offsetFormula作为String),返回为该单元格和公式计算的范围。这就是我的想法。我同意你的观点,我只是想在给你写之前澄清一下。但是自从你澄清之后,我将你的函数头片段扩展成了一个函数。
Function ReturnRange(initialRange As Range, Optional OffsetFormula As String) As Range
    Dim parameters
    Dim upBound As Long
    Dim topLeftCell As Range
    Dim bottomRightCell As Range
    On Error Resume Next
    'If an error occurs result will be Nothing
    If OffsetFormula = "" Then OffsetFormula = initialRange.Formula
    If UCase(Left(OffsetFormula, 7)) = "=OFFSET" Then
        parameters = Split(Left(OffsetFormula, Len(OffsetFormula) - 1), ",")
        'Using upbound variable to avoid constant calls to Ubound(parameters)
        upBound = UBound(parameters)
        Set topLeftCell = initialRange.Offset(parameters(upBound - 3), parameters(upBound - 2))
        Set bottomRightCell = topLeftCell.Offset(parameters(upBound - 1) - 1, parameters(upBound) - 1)
        Set ReturnRange = Range(topLeftCell, bottomRightCell)
    End If
End Function