有没有更有效的方法来编写以下内容:
Private Sub ConvertDatesToValue_Click()
Dim Rng1 As Range, Rng2 As Range, Rng3 As Range, Rng4 As Range
Set Rng1 = Range("Q8:Q12")
Set Rng2 = Range("Q16:Q20")
Set Rng3 = Range("T8:T12")
Set Rng4 = Range("T16:T20")
Rng1.Value = Rng1.Value
Rng2.Value = Rng2.Value
Rng3.Value = Rng3.Value
Rng4.Value = Rng4.Value
End Sub
它看起来和感觉都有点笨拙。
最佳答案
Private Sub ConvertDatesToValue_Click()
因此,我们正在查看控件的 Click
处理程序,可能是工作表上的 ActiveX 按钮,在这种情况下,我们位于该工作表的代码隐藏模块中。
该按钮意味着调用一个命令,该命令将转换公式及其在包含日期的特定单元格范围内的值。
我将从一个负责在给定 Range
的情况下将 Range.Value
分配给自身的过程开始:
Public Sub FreezeFormulaResult(ByVal target As Range)
target.Value = target.Value
End Sub
接下来我们需要确定要传递到该过程的范围。
Dim Rng1 As Range, Rng2 As Range, Rng3 As Range, Rng4 As Range Set Rng1 = Range("Q8:Q12") Set Rng2 = Range("Q16:Q20") Set Rng3 = Range("T8:T12") Set Rng4 = Range("T16:T20")
感谢您避免了隐式 Variant
陷阱,并为每个变量声明了显式类型。
it looks and feels a bit janky
那是因为变量具有该数字后缀。 Rng1...RngN
确实是一种代码味道:对于需要一堆东西的问题来说,这是一个肮脏的解决方案。
通常,更优雅的解决方案是使用数组:
Dim ranges As Variant
ranges = Array(Range("Q8:Q12"), Range("Q16:Q20"), Range("T8:T12"), Range("T16:T20"))
给猫剥皮的方法有很多种,但联合脱节的Range
1不会产生预期的结果。因为您需要 4 个不同的区域,所以您需要 4 个不同的操作。
如何点击处理程序需要获取范围,取决于该处理程序所在的位置。
<小时/>如果我们正在查看 Worksheet
上的 MSForms.CommandButton
(ActiveX) 按钮,那么点击处理程序就位于我们想要获取的同一个工作表中细胞来自。
在这种情况下,我们可以处理当前对象 Me
- 事实上,通过 not 限定我们正在执行的 Range
调用< em>正是...隐含地。
换句话说:
Set Rng1 = Range("Q8:Q12")
意思是:
Set Rng1 = Me.Range("Q8:Q12")
标准模块中不能有按钮 Click
处理程序,但如果您要将其编写为一个:
Set Rng1 = Range("Q8:Q12")
那么这就是隐含的:
Set Rng1 = ActiveSheet.Range("Q8:Q12")
请注意差异:这就是为什么隐式代码是邪恶的,以及为什么上下文就是一切 - 通过编写显式代码,您可以通过使上下文成为本地而不是环境来减少认知负担em>.
我们需要一些东西来为我们提供一个要使用的 Range
对象数组。让我们尝试抽象 - 它可能是工作表代码隐藏中的公共(public)属性:
Public Property Get ImportantDateRanges() As Variant
ImportantDateRanges = Array( _
Me.Range("Q8:Q12"), _
Me.Range("Q16:Q20"), _
Me.Range("T8:T12"), _
Me.Range("T16:T20"))
End Property
现在按钮的 Click
处理程序不再需要关心单元格是什么,并且抽象级别非常完美:
Private Sub ConvertDatesToValues_Click()
FreezeDateFormulas
End sub
Private Sub FreezeDateFormulas()
Dim dateRanges As Variant
dateRanges = Me.ImportantDateRanges
Dim i As Long
For i = LBound(dateRanges) To UBound(dateRanges)
FreezeFormulaResult dateRanges(i)
Next
End Sub
<小时/>
如果我们在UserForm
上查看MSForms.CommandButton
,它是完全相同的ActiveX 按钮,... but it's an entirely different story ,因为虽然您不拥有 Worksheet
实例(Excel 拥有),但您确实拥有一个 UserForm
实例 - 这也带来了影响这里有很多需要解释的地方(该链接指向我写的一篇关于表单如何不需要运行该节目的文章)。
关于vba - 如何优化 Range Set 和 .Value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51567317/