Reputation: 57
I have a bunch of formulae that is meant for specific (non-contiguous) ranges in my data. Is there any way to do this in less lines with an array and/or a loop?
.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]"
Upvotes: 2
Views: 437
Reputation: 54767
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
Upvotes: 2
Reputation: 57673
I would store the rows in an array, then use Union
to collect all the rows in a variable and Intersect
that with each column.
This way you can access all defined rows of a specific column at once.
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
Instead of the loop you can also write:
Set AllRows = .Range("1:1,3:3,17:17")
like
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
but this works only for a smaller amount of rows. If you have more you need to use Union
Upvotes: 3
Reputation: 627
Maybe something like this:
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
Upvotes: 2
Reputation: 2877
Yes, although I suspect not quite in the way you're thinking. Use an array instead of separate variables RowA
, RowB
and RowC
, so you'd replace
Dim RowA as Long, RowB as Long, RowC as Long
RowA = 1
RowB = 3
RowC = 7 'example figures
With -
Dim Row(1 to 3) as Long
Row(1) = 1
Row(2) = 3
Row(3) = 7
Then your above code can be shortened to the following loop:
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
Upvotes: 2