9

3 Tips for Writing Formulas with VBA Macros in Excel

Bottom line: Learn 3 tips for writing and creating formulas in your VBA macros with this article and video.

Skill level: Intermediate

Watch on YouTube and give it a thumbs up.YouTube Thumbs Up LikeYouTube Subscribe Logo Excel Campus

Download the File

Download the Excel file to follow along with the video.

3 Tips For Writing Excel Formulas In VBA.xlsm (82.3 KB)

Automate Formula Writing

Writing formulas can be one of the most time consuming parts of your weekly or monthly Excel task.  If you’re working on automating that process with a macro, then you can have VBA write the formula and input it into the cells for you.

Writing formulas in VBA can be a bit tricky at first, so here are 3 tips to help save time and make the process easier.

Tip #1: The Formula Property

The Formula property is a member of the Range object in VBA.  We can use it to set/create a formula for a single cell or range of cells.

There are a few requirements for the value of the formula that we set with the Formula property:

  1. The formula is a string of text that is wrapped in quotation marks.  The value of the formula must start and end in quotation marks.
  2. The formula string must start with an equal sign = after the first quotation mark.

Here is a simple example of a formula in a macro.

Sub Formula_Property()

  'Formula is a string of text wrapped in quotation marks
  'Starts with an = sign
  Range("B10").Formula = "=SUM(B4:B9)"

End Sub

The Formula property can also be used to read an existing formula in a cell.

Tip #2: Use the Macro Recorder

When your formulas are more complex or contain special characters, they can be more challenging to write in VBA.  Fortunately we can use the macro recorder to create the code for us.

Create Formula VBA code with the Macro Recorder

Here are the steps to creating the formula property code with the macro recorder.

  1. Turn on the macro recorder (Developer tab > Record Macro)
  2. Type your formula or edit an existing formula.
  3. Press Enter to enter the formula.
  4. The code is created in the macro.

If your formula contains quotation marks or ampersand symbols, the macro recorder will account for this.  It creates all the sub-strings and wraps everything in quotes properly. Here is an example.

Sub Macro10()
'Use the macro recorder to create code for complex formulas with
'special characters and relative references

  ActiveCell.FormulaR1C1 = "=""Total Sales: "" & TEXT(R[-5]C,""$#,###"")"
    
End Sub

Tip #3: R1C1 Style Formula Notation

If you use the macro recorder for formulas, you will notices that it creates code with the FormulaR1C1 property.

R1C1 style notation allows us to create both relative (A1), absolute ($A$1), and mixed ($A1, A$1) references in our macro code.

R1C1 stands for Rows and Columns.

Relative References

For relative references we specify the number of rows and columns we want to offset from the cell that the formula is in.  The number of rows and columns are referenced in square brackets.

The following would create a reference to a cell that is 3 rows above and 2 rows to the right of the cell that contains the formula.

R[-3]C[2]

Negative numbers go up rows and columns to the left.

Positive numbers go down rows and columns to the right.

Absolute References

We can also use R1C1 notation for absolute references.  This would typically look like $A$2.

For absolute references we do NOT use the square brackets.  The following would create a direct reference to cell $A$2, row 2 column 1

R2C1

Mixed References

with mixed references we add the square brackets for either the row or column reference, and no brackets for the other reference.  The following formula in cell B2 would create this reference to A$2, where the row is absolute and the column is relative.

R2C[-1]

When creating mixed references, the relative row or column number will depend on what cell the formula is in.

It’s easiest to just use the macro recorder to figure these out.

FormulaR1C1 Property versus Formula Property

The FormulaR1C1 property reads the R1C1 notation and creates the proper references in the cells.  If you use the regular Formula property with R1C1 notation, then VBA will attempt to put those letters in the formula, and it will likely result in a formula error.

Therefore, use the Formula property when your code contains cell references ($A$1), the FormulaR1C1 property when you need relative references that are applied to multiple cells or dependent on where the formula is entered.

If your spreadsheet changes based on conditions outside your control, like new columns or rows of data are imported from the data source, then relative references and R1C1 style notation will probably be best.

I hope those tips help.  Please leave a comment below with questions or suggestions.

Free Webinar on Macros & VBA

Please share
Jon Acampora
 

Welcome to Excel Campus! I am excited you are here. My name is Jon and my goal is to help you learn Excel to save time with your job and advance in your career. I've been an avid Excel user and VBA developer for 10+ years. I am also a Microsoft MVP. I try to learn something new everyday, and want to share this knowledge with you to help you improve your skills. When I'm not looking at spreadsheets, I get outdoors and surf. :) more about me

Click Here to Leave a Comment Below 9 comments
Barbara - June 13, 2018

Hi Jon,

Let’s make this more complicated…

My formula is an array formula that needs to have named ranges changed when I create a new sheet. For example, the I need is an array formula that contains a range that is named data6. When I create the new month, I need to rename data6 to data7. I have been doing this manually each month, but there are 7 cells, each with different formulas that need to be changed.

Example of my working formula in Excel:
{=IFERROR(INDEX(data2,MATCH(1,(pNum2=B4)*(action2=”Retain”),0),12),”n/a”)}

Failed VBA attempts: Earlier code has already set monNum to the number of the current month. rng1 is dim as String. I’m sure it has to do with how I’m referring to the named ranges, but stumped as to how to do it.

1. Range(“L3”).Select
Selection.FormulaArray = _
“=IFERROR(INDEX(data” & monNum,MATCH(1,(pNum5=RC2)*(action5=””Retain””),0),12),””no test””)”
Returns expected end of statement

2. Range(“L3”).Select
Selection.FormulaArray = _
“=IFERROR(INDEX(rng1,MATCH(1,(pNum5=RC2)*(action5=””Retain””),0),12),””no test””)”
returns {=IFERROR(INDEX(RNG1,MATCH(1,(pNum5=RC2)*(action5=”Retain”),0),12),”no test”)}

Reply
    Jon Acampora - June 13, 2018

    Hi Barbara,

    You are on the right track here. The variables will NOT be wrapped in quotes since they are evaluated in the VB Editor. However, the rest of the formula does need to be wrapped in quotes.

    The variables and strings are joined together with ampersands. Here is an example where rng1 is a variable that is declared and set in the macro.

    "=SUM(" & rng1 & ")"

    Notice that after the variable we have another ampersand and then text wrapped in quotes.

    This same technique will apply to your formula. Join the text after the variable with an ampersand and quotes.

    I hope that helps. Thanks! 🙂

    Reply
G - April 20, 2018

Hello Jon,
How can we run macro for a range of cells instead of one cell?

-We want to copy all formula for not only B3, but B3:B12. How can we do that?

Regards,
G

Reply
    Jon Acampora - June 13, 2018

    Hi G,

    When using R1C1 style notation you can apply the same formula to all the cells in a range. Here is an example.

    Range("B3:B12").FormulaR1C1 = "=RC[1]+RC[2]"

    That line of code would put the same formula in each cell. The formula in cell B3 would evaluate to C3+D3. The formula in cell B4 would be C4+D4.

    If you already have a formula in cell B3, then you can just copy it down to the rest of the cells. There are many ways to do this, but here is one simple line of code using the Copy method.

    Range("B3").Copy Range("B4:B12")
    
    Checkout my article on 3 Ways to Copy and Paste Cells with VBA Macros + Video for more details on these techniques.

    Reply
G - April 20, 2018

The FormulaR1C1 property reads the R1C1 notation and creates the proper references in the cells. If you use the regular Formula property with R1C1 notation, then VBA will attempt to put those letters in the formula, and it will likely result in a formula error.

Hi Jon,
Can you please explain on what you say on the top?
You are saying same thing but one creates error and one not!

Regards,
G

Reply
    Jon Acampora - June 13, 2018

    Hi G,

    If you are using R1C1 style notation in your formula text, then it is best to use the FormulaR1C1 property.

    Notice how this line uses FormulaR1C1

    Range("B3:B12").FormulaR1C1 = "=RC[1]+RC[2]"

    The following line uses R1C1, but uses the Formula property.

    Range("B3:B12").Formula = "=RC[1]+RC[2]"

    That line could result in an error if you have mixed references. Most of the time VBA will figure it out and still convert the R1C1 to cell references. As the formula gets more complex then it might not be able to convert it. Therefore, it’s best to use FormulaR1C1 when you have R1C1 references in your formula text.

    I hope that helps.

    Reply
claudiu - April 13, 2018

Hi Jon,

first of all, Thank You for your answer. In my example, “lCell” is the place where I need the Sum function. And the Sum function should add the values from column I2 to I
Can you help me to understand and resolve that?

Thank you again

Reply
claudiu - April 12, 2018

Hi Jon!

Is it possible to make that construction dynamic? I mean the SUM function

Sub LastCell_Total ()

Dim lCell as Range
Set lCell = Range(“I2”).End(xlDown).Offset(1, 0)
lCell.Formula = WorksheetFunction.Sum(Range(Range(“I2”), Range(“I2”).End(xlDown)))

End Sub

Reply
    Jon Acampora - April 12, 2018

    Hi Claudiu,
    Great question! Yes, absolutely.

    You could declare a variable to hold the last row number. Or use the Row property of lCell.

    Then use the variable in the formula string. Concatenate it with the ampersands. Here is an example.

    Range("A4").Formula = "=SUM(B4:B" & lCell.Row & ")"

    When that evaluates is will create the range reference with the last row number after B. Something like B4:B203

    I hope that helps.

    Reply

Leave a Reply: