【问题标题】:How do I loop across specific ranges with the row number as the variable?如何以行号作为变量遍历特定范围?
【发布时间】:2021-07-23 08:11:10
【问题描述】:

我有一堆公式适用于我的数据中的特定(非连续)范围。有没有办法用数组和/或循环在更少的行中做到这一点?

.Range("R" & RowA).FormulaR1C1 = "=RC[-1]"
.Range("W" & RowA).FormulaR1C1 = "=(RC[-5]*RC[-7])+RC[-2]"
.Range("Y" & RowA).FormulaR1C1 = "=RC[-12]*RC[-2]"

.Range("R" & RowB).FormulaR1C1 = "=RC[-1]"
.Range("W" & RowB).FormulaR1C1 = "=(RC[-5]*RC[-7])+RC[-2]"
.Range("Y" & RowB).FormulaR1C1 = "=RC[-12]*RC[-2]"

.Range("R" & RowC).FormulaR1C1 = "=RC[-1]"
.Range("W" & RowC).FormulaR1C1 = "=(RC[-5]*RC[-7])+RC[-2]"
.Range("Y" & RowC).FormulaR1C1 = "=RC[-12]*RC[-2]"

【问题讨论】:

  • 如果行数有限,.Range("R" & RowA & ",R" & RowB & ",R" & RowC).FormulaR1C1 = "=RC[-1]" 应该可以工作。

标签: excel vba loops


【解决方案1】:

是的,尽管我怀疑与您的想法不太一样。使用数组而不是单独的变量 RowARowBRowC,这样你就可以替换

Dim RowA as Long, RowB as Long, RowC as Long
RowA = 1
RowB = 3
RowC = 7 'example figures

与-

Dim Row(1 to 3) as Long
Row(1) = 1
Row(2) = 3
Row(3) = 7

那么你上面的代码可以缩短为如下循环:

For a = Lbound(Row) to Ubound(Row)
    .Range("R" & Row(a)).FormulaR1C1 = "=RC[-1]"
    .Range("W" & Row(a)).FormulaR1C1 = "=(RC[-5]*RC[-7])+RC[-2]"
    .Range("Y" & Row(a)).FormulaR1C1 = "=RC[-12]*RC[-2]"
Next

【讨论】:

  • 有没有一种方法可以在数组中使用较少的通用变量名称?例如,CustomerARow、CustomerBRow 等。这是因为我以后还需要引用这些变量。
  • @OliverTheseira 您可以随意命名数组(对于上面的示例,我建议将其命名为 CustomerRow(1 to 3) )-但是在括号内它必须是整数。但是,您可以使用任何您想要的整数,例如使用数字 15 到 17 而不是 1 到 3 的数组,如果有帮助的话。
  • 抱歉回复晚了,我正在休假。谢谢@Spencer,这非常有效。但是,声明变量数组的缺点是变量标识符将仅限于整数,而不是在这种情况下的客户名称。
【解决方案2】:

我会将行存储在一个数组中,然后使用Union 将所有行收集到一个变量中,并使用Intersect 收集每一列。

这样您可以一次访问特定列的所有已定义行。

Option Explicit

Public Sub example()
    Dim RowArr() As Variant
    RowArr = Array(1, 3, 17) 'define your rows here
    
    Dim AllRows As Range
        
    With ActiveSheet
        Dim Row As Variant
        For Each Row In RowArr
            If AllRows Is Nothing Then
                Set AllRows = .Rows(Row)
            Else
                Set AllRows = Union(AllRows, .Rows(Row))
            End If
        Next Row
        
        'write in all rows of a specific column
        Intersect(.Columns("R"), AllRows).FormulaR1C1 = "=RC[-1]"
        Intersect(.Columns("W"), AllRows).FormulaR1C1 = "=(RC[-5]*RC[-7])+RC[-2]"
        Intersect(.Columns("Y"), AllRows).FormulaR1C1 = "=RC[-12]*RC[-2]"
    End With
End Sub

除了循环,你也可以写:

Set AllRows = .Range("1:1,3:3,17:17")

喜欢

Option Explicit

Public Sub example()
    With ActiveSheet
        Dim AllRows As Range
        Set AllRows = .Range("1:1,3:3,17:17")
        
        'write in all rows of a specific column
        Intersect(.Columns("R"), AllRows).FormulaR1C1 = "=RC[-1]"
        Intersect(.Columns("W"), AllRows).FormulaR1C1 = "=(RC[-5]*RC[-7])+RC[-2]"
        Intersect(.Columns("Y"), AllRows).FormulaR1C1 = "=RC[-12]*RC[-2]"
    End With
End Sub

但这仅适用于少量的行。如果你有更多你需要使用Union

【讨论】:

  • 这个方法不错,以前没见过。也谢谢你的回答。
  • @Capt.Krusty 这里的优势是您只有 3 个写入进程(而不是 9 个),因为您一次将所有行写入一列!写入进程的数量是时间关键因素,你拥有的越少,你的代码就越快。
  • 嗨@Pᴇʜ,如果我像你在这里所做的那样使用数组函数,我可以写RowArr = Array(CustA, CustB, CustC)吗?如果是这样,这对我来说实际上是一个更好的解决方案,因为我可以直观地为每个客户存储一个带有标识符的变量,而不是纯粹的整数。
  • @OliverTheseira 我不会为CustA 等硬编码变量。如果您添加了一个客户,然后您必须再次触摸您的代码怎么办?不,而是让您的代码更具动态性,这样如果添加了一位客户,您就无需触摸它。每当您感觉需要对变量名进行编号(或 ABC)时,这清楚地表明您做错了。 • 我无法在评论中给你更详细的答案,所以我建议你为此打开一个新问题,并用一个很好的例子来解释你实际上想要做什么。
【解决方案3】:

可能是这样的:

Sub Test()
Dim letters, rows, i, letter, row

letters = Array("R", "W", "Y")
rows = Array(1, 5, 17)          'RowA, RowB, and so on...
i = 0
j = 0
For Each row In rows
    For Each letter In letters
        Debug.Print letters(i) & rows(j)
    '    .Range(letters(i) & rows(i)).FormulaR1C1 = "=RC[-1]"
    '    .Range(letters(i) & rows(i)).FormulaR1C1 = "=(RC[-5]*RC[-7])+RC[-2]"
    '    .Range(letters(i) & rows(i)).FormulaR1C1 = "=RC[-12]*RC[-2]"
         
        i = i + 1
    Next letter
    j = j + 1
    i = 0
Next row

End Sub

【讨论】:

  • 将“字母”存储为数组是个好主意,但不确定是否真的会提高效率,因为对每个字母应用不同的操作?
  • 为了知识,我可以知道每个变量的类型是什么吗?我不清楚数组变量类型。将字母和字母声明为字符串,将行和行声明为长变量类型是否正确?
  • 感谢@Spencer Barnes。当他要求“特定(非连续)范围”时,它应该只显示 For-Each-Loops 的可能性。 i 和 j 字符的更改只是工作。感谢您的反馈。
  • @Oliver Thereisa:您可以将数组定义为“Variant”,将 i、j 定义为“Integer”。
  • @Capt.Krusty 我可以知道为什么你需要在底部写 i=0 吗?
【解决方案4】:

使用“助手”程序

Option Explicit

Sub UsingRefRows()
    
    Const RowA As Long = 1
    Const RowB As Long = 3
    Const RowC As Long = 5
    
    Dim ws As Worksheet: Set ws = Sheet1
    
    Dim rrg As Range: Set rrg = RefRows(ws, RowA, RowB, RowC)
    
    Intersect(rrg, ws.Columns("R")).FormulaR1C1 = "=RC[-1]"
    Intersect(rrg, ws.Columns("W")).FormulaR1C1 = "=RC[-5]*RC[-7]+RC[-2]"
    Intersect(rrg, ws.Columns("Y")).FormulaR1C1 = "=RC[-12]*RC[-2]"

End Sub

Sub UsingRefRowsAndWriteRowsR1C1()
    
    Const RowA As Long = 1
    Const RowB As Long = 3
    Const RowC As Long = 5
    
    Const ColumnsList As String = "R,W,Y"
    Const FormulasList As String _
        = "=RC[-1]" & "," _
        & "=RC[-5]*RC[-7]+RC[-2]" & "," _
        & "=RC[-12]*RC[-2]"
    
    Dim ws As Worksheet: Set ws = Sheet1
    
    Dim rrg As Range: Set rrg = RefRows(ws, RowA, RowB, RowC)
    
    WriteRowsR1C1 rrg, ColumnsList, FormulasList
    
End Sub


Function RefRows( _
    ByVal ws As Worksheet, _
    ParamArray DataRows() As Variant) _
As Range
    Dim rg As Range
    Dim n As Long
    For n = 0 To UBound(DataRows)
        If rg Is Nothing Then
            Set rg = ws.Rows(DataRows(n))
        Else
            Set rg = Union(rg, ws.Rows(DataRows(n)))
        End If
    Next n
    If Not rg Is Nothing Then
        Set RefRows = rg
    End If
End Function

Sub WriteRowsR1C1( _
        ByVal RowsRange As Range, _
        ByVal ColumnsList As String, _
        ByVal FormulasList As String)
    
    Dim Cols() As String: Cols = Split(ColumnsList, ",")
    Dim Formulas() As String: Formulas = Split(FormulasList, ",")
    Dim ws As Worksheet: Set ws = RowsRange.Worksheet
    
    Dim n As Long
    For n = 0 To UBound(Cols)
        Intersect(RowsRange, ws.Columns(Cols(n))).FormulaR1C1 = Formulas(n)
    Next n
    
End Sub

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-01-10
    • 2021-12-19
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-04-06
    • 2021-04-08
    相关资源
    最近更新 更多