如何优化范围集和.Value

时间:2018-07-28 01:36:07

标签: excel vba excel-vba

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

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 

它的外观和感觉有点过时。

3 个答案:

答案 0 :(得分:4)

尝试直接还原值。

Private Sub ConvertDatesToValue_Click()

    With Worksheets("sheet9")
        .Range("Q8:Q12") = .Range("Q8:Q12").Value
        .Range("Q16:Q20") = .Range("Q16:Q20").Value
        .Range("T8:T12") = .Range("T8:T12").Value
        .Range("T16:T20") = .Range("T16:T20").Value
    End With

End Sub

您真的应该知道您正在使用的工作表。

答案 1 :(得分:4)

Private Sub ConvertDatesToValue_Click()

因此,我们正在查看控件的Click处理程序,大概是工作表上的ActiveX按钮,在这种情况下,我们位于该工作表的代码隐藏模块中。

该按钮意味着调用一个命令,该命令将在包含日期的特定单元格区域中转换公式及其值。

在给定Range.Value的情况下,我将从负责将Range分配到自身的过程开始:

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陷阱而为这些变量中的每一个声明显式类型的荣誉。

  

它的外观和感觉有点僵硬

这是因为变量具有该数字后缀。 Rng1...RngN确实是一种代码气味:它是解决需要一堆东西 的问题的肮脏解决方案。

通常,更优雅的解决方案是使用数组:

Dim ranges As Variant
ranges = Array(Range("Q8:Q12"), Range("Q16:Q20"), Range("T8:T12"), Range("T16:T20"))

有很多方法可以给猫皮毛,但是联合的脱节Range 1 不会产生预期的结果。因为需要4个不同的区域,所以需要4个不同的操作。

操作方式点击处理程序需要提取范围,取决于该处理程序在哪里。


如果我们正在查看MSForms.CommandButton上的Worksheet(ActiveX)按钮,则单击处理程序位于我们要从中获取单元格的同一张纸中。

在那种情况下,我们可以处理当前对象Me-实际上,通过限定Range的调用,我们可以精确地完成 隐式。

换句话说:

Set Rng1 = Range("Q8:Q12")

表示:

Set Rng1 = Me.Range("Q8:Q12")

在标准模块中没有按钮Click处理程序,但是如果要在一个模块中编写它:

Set Rng1 = Range("Q8:Q12")

然后这将是隐式的:

Set Rng1 = ActiveSheet.Range("Q8:Q12")

请注意区别:这就是为什么隐式代码是邪恶的,而上下文是一切的原因-通过编写显式代码,您可以通过使上下文 local 而不是 ambient 来减轻认知负担。 em>。

我们需要能够为我们提供Range对象数组的某物。让我们尝试抽象-它可能是工作表代码背后的公共财产:

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

如果我们在MSForms.CommandButton上查看UserForm,则它是完全相同的ActiveX按钮... but it's an entirely different story,因为虽然您没有{{1 }}实例(Excel确实),您确实拥有一个Worksheet实例-这就带来了太多的含义,在这里无法解释(该链接指向我写的一篇有关表单如何不起作用的文章不需要进行表演)。


1 How can I optimise Range Set and .Value

答案 2 :(得分:4)

您可以遍历4个区域:

Dim r As Range
For Each r In Range("Q8:Q12,Q16:Q20,T8:T12,T16:T20").Areas
    r = r.Value
Next