0

OFFSET我的代码使用取决于该单元格地址的公式给出的范围在单元格上设置列表验证。

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

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

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

该测试应将下拉验证分配给具有单元格和B1内容的单元格,然后检查的内容是否与这些单元格中的任何一个匹配。但它失败并出现此错误:A1A2B1Set ResultRange

Method 'Range' of object '_Global' failed.

我认为问题在于,当我调用 时Range(rangeName),Excel 不知道将ROW()and应用COLUMN()到哪个单元格,因此我需要以某种方式计算formula该单元格解析为的地址——在这种情况下$A$1:$A$2,,以便我可以分配那个值为RangeName

那么,给定OFFSET()我将动态参数传递给的这个公式,我如何获得这个公式为指定范围返回的范围rng

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

4

1 回答 1

0

这不漂亮,但会做你喜欢你必须已经定义的事情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

根据要求进行编辑,我继续将 OffsetFormula 设为可选,因为它将假定传递的范围具有需要解析的公式:

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
于 2012-11-10T03:00:45.060 回答