vba - 如何优化 Range Set 和 .Value

标签 vba excel

有没有更有效的方法来编写以下内容:

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"))

给猫剥皮的方法有很多种,但联合脱节的Range1不会产生预期的结果。因为您需要 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 实例 - 这也带来了影响这里有很多需要解释的地方(该链接指向我写的一篇关于表单如何不需要运行该节目的文章)。

<小时/>

1 How can I optimise Range Set and .Value

关于vba - 如何优化 Range Set 和 .Value,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51567317/

相关文章:

vba - 使用 IIf 时出现语法错误

vba - 如何传递光标并将焦点设置在 VBA 中的用户窗体文本框上?

excel - 如何在多行上重复功能

excel - 确保您的 VBA 代码兼容 64 位

excel - 将二维分隔字符串解析为范围

excel - 计算特定文本在数组中的次数

excel - 如何根据一个公共(public)行连接来自 2 个不同 Excel 工作表的数据?

excel - 在access vba中调用excel函数

excel - 通过双击单元格从工作表中调用宏

excel - VBA excel Target.Address =单元格范围