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