我的代码使用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
和A1
的内容为单元格A2
分配下拉验证,然后检查B1
的内容是否匹配那些细胞但它在Set ResultRange
行失败并出现此错误:
Method 'Range' of object '_Global' failed.
我认为问题在于,当我调用Range(rangeName)
时,Excel不知道将ROW()
和COLUMN()
应用到哪个单元格,所以我需要以某种方式计算地址formula
解析为此单元格 - 在本例中为$A$1:$A$2
,以便我可以将该值分配给RangeName
。
因此,根据我传递动态参数的OFFSET()
公式,如何获得此公式为rng
指定的范围返回的范围?
编辑:由于公式可能会根据不同的情况而变化,我正在寻找一个解决方案,给定从某个范围开始的OFFSET()
公式,返回该公式给出的范围。硬编码的解决方案是不可接受的,因为工作表中有几个不同的OFFSET()
公式,每当其中一个公式发生变化时,更改验证测试的代码是不切实际的。
答案 0 :(得分: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