IF Function in VBA

I managed to create a macro to show the following:

If (I3<>0,I3*G3,H3*G3) and this repeats itself for cell N3,R3, V3,Z3 ETC.

Option Explicit
Sub Eg()
Range("J3, N3,R3, V3,Z3,AD3,AH3,AL3,AP3,AT3,Ax3,BB3,XF3,BJ3").Formula = "=IF(RC[-1]<>0,RC[-1]*RC[-3],RC[-2]*RC[-3])"
End Sub

Let me explain a bit more how this should work:

This report needs to be downloaded from an application.
The macro needs to be attached to this report so that when I download the report the macro automatically runs this formula in the appropriate columns.

Also I 'll have to populate the spreadhseet for all the rows with this formula.

The columns where the formula should sit are not blank but this needs to be catered for in the report automatically once the macro is run.

What am I missing here?

Hope you'll be able to help.

Thanks.

AttachmentSize
Example_Actual_Spend_on_Time_Sheet_16_11_v1.xls40.5 KB

The total spend works!! Fantastic but the autoexec bit is not

Hi Argy

The total spend column works but I have inserted the autoexec code but I still have to click the run macro to make it work once I have downloaded the file. please see the code below:

Private Sub Workbook_Open()
If MsgBox("Run the bill rate and total spend macro ?", vbQuestion + vbYesNo, "Auto compute") = vbYes Then
Eg_New
End If
End Sub

Option Explicit

Sub Eg_New()
'---------------------------------------------------------------------------
' Procedure : Eg_New

'Constants :

'Color for bill rate column
Const BILL_RATE_CELL_COLOR As Long = 15849925
'Color for total spend column
Const TOTAL_SPEND_CELL_COLOR As Long = 12379352
'Value of the first row (could be over 1)
Const FIRST_ROW As Integer = 1
'Row start of data (FIRST_ROW must be ajusted)
Const TARGET_ROW As Integer = 3
'Number of columns between bill rate columns
Const COLUMN_OFFSET_BETWEEN_SUBTOTALS As Integer = 3
'Bill rate formula
Const BILL_RATE_FORMULA As String = "=IF(RC[-1]<>0,RC[-1]*RC[-3],RC[-2]*RC[-3])"

Dim oRng As Range
Dim C As Integer
Dim R As Long
Dim strRangeAddress As String
Dim intColumnIndex As Integer
Dim blnApplyConversion As Boolean
Dim lngLastRow As Long
Dim intLastColumn As Integer
Dim intUsedLastColumn As Integer

Dim intColPosition As Integer
Dim strTotalSpendFormula As String

On Error GoTo L_ErrEg
Application.ScreenUpdating = False
'Get the working area
Cells(1, 1).Select
'last row
lngLastRow = ActiveCell.End(xlDown).Row
Cells(2, 1).Select
'True last column
intLastColumn = ActiveCell.End(xlToRight).Column
Cells(3, 1).Select
'Supposed last column
intUsedLastColumn = ActiveCell.SpecialCells(xlCellTypeLastCell).Column
'Delete unused columns
If intUsedLastColumn > intLastColumn Then
For C = intLastColumn + 1 To intUsedLastColumn
Columns(intLastColumn + 1).Delete
Next
End If
'For each row
For R = TARGET_ROW To lngLastRow
'For the 14 target cells (4 by 4)
For C = 10 To intLastColumn Step 4
'Build the address A1
strRangeAddress = Cells(R, C).Address(False, False)
'Set the range object
Set oRng = Range(strRangeAddress)
'Define the range formula and its features
With oRng
.FormulaR1C1 = BILL_RATE_FORMULA
.Interior.Color = BILL_RATE_CELL_COLOR
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
'Build Total Spend formula
intColPosition = intLastColumn - (C - COLUMN_OFFSET_BETWEEN_SUBTOTALS)
strTotalSpendFormula = strTotalSpendFormula & "RC[-" & intColPosition & "],"
Next C
'Put the Total Spend formula
If Right$(strTotalSpendFormula, 1) = "," Then strTotalSpendFormula = Left$(strTotalSpendFormula, Len(strTotalSpendFormula) - 1)
strTotalSpendFormula = "=SUM(" & strTotalSpendFormula & ")"
'Set the range object
strRangeAddress = Cells(R, C - 1).Address(False, False)
Set oRng = Range(strRangeAddress)
With oRng
.FormulaR1C1 = strTotalSpendFormula
.Interior.Color = TOTAL_SPEND_CELL_COLOR
.HorizontalAlignment = xlRight
.Font.Bold = True
End With
'Emptying formula variable
strTotalSpendFormula = vbNullString
Next R
'Put title
Cells(2, C - 1).Value = "Total Spend"
On Error GoTo 0
L_ExEg:
'Hide formulas...
ActiveWindow.DisplayFormulas = False
'Freeing objects
Set oRng = Nothing
Application.ScreenUpdating = True
Exit Sub

L_ErrEg:
MsgBox Err.Description, 48, Err.Source
Resume L_ExEg
End Sub

Well, in this way, you

Well, in this way, you haven't other choice than to put a command button into the toolbar or into the ribbon (according to your Office version) where the command button will call the function I wrote for you from the perso.xls ou the personal.xlsb (according to your Office version too).
To create a perso(nal).xls(b), run the process to record a macro for nothing : just after you have chosen personal macro within the dialog box of macro recorder.
Then, clic on Stop record once you clicked on Ok. This operation will create a hidden workbook that will systematically be loaded with your Excel instance. Then copy the subroutine Eg_New into the module1 and save the workbook.
From the Excel options, customize the ribbon or the toolbar (according to your Office version) to set the Eg_New() macro to the comand button.
Now you will have the button always available, and above all this, it will be usable once you data file is downloaded.

Did you understood all ?

P.S. Sorry for my english sentences, I'm french...

I speak french! I'll try what you have just written ....

so if I have understood correctly I need to do the following:

1)Open new workbook
2)Then I click on record macro
3select personal macro
4)click ok
5)Stop recording
6) Insert command button
7)copy and paste your code in module 1
8) save workbook.

8)the command button issitting on the spreadsheet.

please let me know if this is ok?

No, it is not recommanded to

No, it is not recommanded to put a command button on the spreadsheet if the spreadsheet is directly downloaded from a other application. In fact, if you insert a command button into the ribbon (into a own group) or into the toolbar, it will allows you to have the availability of the button each time you need. In this way, it is better to add a confirmation message inside and before the code, such as :

If MsgBox("Do you want to apply formulas ?", vbQuestion + vbYesNo, "Confirm") = vbNo Then Exit Sub

Otherwize, if the spreadsheet downloads data from Excel directly and always into the same workbook, alright, you can put the command button on the spreadsheet. For my part, I rather keep the first suggestion.

i'm confused now....

Argy

I am so sorry but I 'm getting confused. Do you mean to insert a command button in the developer screen?Is this how you mean to add the message before the code?

If MsgBox("Do you want to apply formulas ?", vbQuestion + vbYesNo, "Confirm") = vbNo Then Exit Sub
Option Explicit

Sub Eg_New()
'---------------------------------------------------------------------------
' Procedure : Eg_New

'
'Constants :

'Color for bill rate column
Const BILL_RATE_CELL_COLOR As Long = 15849925
'Color for total spend column
Const TOTAL_SPEND_CELL_COLOR As Long = 12379352
'Value of the first row (could be over 1)
Const FIRST_ROW As Integer = 1
'Row start of data (FIRST_ROW must be ajusted)
Const TARGET_ROW As Integer = 3
'Number of columns between bill rate columns
Const COLUMN_OFFSET_BETWEEN_SUBTOTALS As Integer = 3
'Bill rate formula
Const BILL_RATE_FORMULA As String = "=IF(RC[-1]<>0,RC[-1]*RC[-3],RC[-2]*RC[-3])"

Dim oRng As Range
Dim C As Integer
Dim R As Long
Dim strRangeAddress As String
Dim intColumnIndex As Integer
Dim blnApplyConversion As Boolean
Dim lngLastRow As Long
Dim intLastColumn As Integer
Dim intUsedLastColumn As Integer

Dim intColPosition As Integer
Dim strTotalSpendFormula As String

On Error GoTo L_ErrEg
Application.ScreenUpdating = False
'Get the working area
Cells(1, 1).Select
'last row
lngLastRow = ActiveCell.End(xlDown).Row
Cells(2, 1).Select
'True last column
intLastColumn = ActiveCell.End(xlToRight).Column
Cells(3, 1).Select
'Supposed last column
intUsedLastColumn = ActiveCell.SpecialCells(xlCellTypeLastCell).Column
'Delete unused columns
If intUsedLastColumn > intLastColumn Then
For C = intLastColumn + 1 To intUsedLastColumn
Columns(intLastColumn + 1).Delete
Next
End If
'For each row
For R = TARGET_ROW To lngLastRow
'For the 14 target cells (4 by 4)
For C = 10 To intLastColumn Step 4
'Build the address A1
strRangeAddress = Cells(R, C).Address(False, False)
'Set the range object
Set oRng = Range(strRangeAddress)
'Define the range formula and its features
With oRng
.FormulaR1C1 = BILL_RATE_FORMULA
.Interior.Color = BILL_RATE_CELL_COLOR
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
'Build Total Spend formula
intColPosition = intLastColumn - (C - COLUMN_OFFSET_BETWEEN_SUBTOTALS)
strTotalSpendFormula = strTotalSpendFormula & "RC[-" & intColPosition & "],"
Next C
'Put the Total Spend formula
If Right$(strTotalSpendFormula, 1) = "," Then strTotalSpendFormula = Left$(strTotalSpendFormula, Len(strTotalSpendFormula) - 1)
strTotalSpendFormula = "=SUM(" & strTotalSpendFormula & ")"
'Set the range object
strRangeAddress = Cells(R, C - 1).Address(False, False)
Set oRng = Range(strRangeAddress)
With oRng
.FormulaR1C1 = strTotalSpendFormula
.Interior.Color = TOTAL_SPEND_CELL_COLOR
.HorizontalAlignment = xlRight
.Font.Bold = True
End With
'Emptying formula variable
strTotalSpendFormula = vbNullString
Next R
'Put title
Cells(2, C - 1).Value = "Total Spend"
On Error GoTo 0
L_ExEg:
'Hide formulas...
ActiveWindow.DisplayFormulas = False
'Freeing objects
Set oRng = Nothing
Application.ScreenUpdating = True
Exit Sub

L_ErrEg:
MsgBox Err.Description, 48, Err.Source
Resume L_ExEg
End Sub

Final version

Hum, no, no.

The Option Explicit must always be the first instruction
Just under this instruction, you can have local private declarations...
And under these declarations, you put the set of subroutines and/or functions

This is the final version of the code that you must attach to the command button :

Option Explicit

Sub Eg_New()
'---------------------------------------------------------------------------
' Procedure : Eg_New

' Notice : Press F5 to run the macro
'---------------------------------------------------------------------------
'Constants :

'Color for bill rate column
Const BILL_RATE_CELL_COLOR As Long = 15849925
'Color for total spend column
Const TOTAL_SPEND_CELL_COLOR As Long = 12379352
'Value of the first row (could be over 1)
Const FIRST_ROW As Integer = 1
'Row start of data (FIRST_ROW must be ajusted)
Const TARGET_ROW As Integer = 3
'Number of columns between bill rate columns
Const COLUMN_OFFSET_BETWEEN_SUBTOTALS As Integer = 3
'Bill rate formula
Const BILL_RATE_FORMULA As String = "=IF(RC[-1]<>0,RC[-1]*RC[-3],RC[-2]*RC[-3])"

Dim oRng As Range
Dim C As Integer
Dim R As Long
Dim strRangeAddress As String
Dim intColumnIndex As Integer
Dim blnApplyConversion As Boolean
Dim lngLastRow As Long
Dim intLastColumn As Integer
Dim intUsedLastColumn As Integer

Dim intColPosition As Integer
Dim strTotalSpendFormula As String

On Error GoTo L_ErrEg
'Confirm execution...
If MsgBox("Do you want to apply formulas ?", vbQuestion + vbYesNo, "Confirm") = vbNo Then Exit Sub
'Freeze screen
Application.ScreenUpdating = False
'Get the working area
Cells(1, 1).Select
'last row
lngLastRow = ActiveCell.End(xlDown).Row
Cells(2, 1).Select
'True last column
intLastColumn = ActiveCell.End(xlToRight).Column
Cells(3, 1).Select
'Supposed last column
intUsedLastColumn = ActiveCell.SpecialCells(xlCellTypeLastCell).Column
'Delete unused columns
If intUsedLastColumn > intLastColumn Then
For C = intLastColumn + 1 To intUsedLastColumn
Columns(intLastColumn + 1).Delete
Next
End If
'For each row
For R = TARGET_ROW To lngLastRow
'For the 14 target cells (4 by 4)
For C = 10 To intLastColumn Step 4
'Build the address A1
strRangeAddress = Cells(R, C).Address(False, False)
'Set the range object
Set oRng = Range(strRangeAddress)
'Define the range formula and its features
With oRng
.FormulaR1C1 = BILL_RATE_FORMULA
.Interior.Color = BILL_RATE_CELL_COLOR
.HorizontalAlignment = xlCenter
.Font.Bold = True
End With
'Build Total Spend formula
intColPosition = intLastColumn - (C - COLUMN_OFFSET_BETWEEN_SUBTOTALS)
strTotalSpendFormula = strTotalSpendFormula & "RC[-" & intColPosition & "],"
Next C
'Put the Total Spend formula
If Right$(strTotalSpendFormula, 1) = "," Then strTotalSpendFormula = Left$(strTotalSpendFormula, Len(strTotalSpendFormula) - 1)
strTotalSpendFormula = "=SUM(" & strTotalSpendFormula & ")"
'Set the range object
strRangeAddress = Cells(R, C - 1).Address(False, False)
Set oRng = Range(strRangeAddress)
With oRng
.FormulaR1C1 = strTotalSpendFormula
.Interior.Color = TOTAL_SPEND_CELL_COLOR
.HorizontalAlignment = xlRight
.Font.Bold = True
End With
'Emptying formula variable
strTotalSpendFormula = vbNullString
Next R
'Put title
Cells(2, C - 1).Value = "Total Spend"
On Error GoTo 0
L_ExEg:
'Hide formulas...
ActiveWindow.DisplayFormulas = False
'Freeing objects
Set oRng = Nothing
Application.ScreenUpdating = True
Exit Sub

L_ErrEg:
MsgBox Err.Description, 48, Err.Source
Resume L_ExEg
End Sub

It works but I need to fine tune...

Hello ARgy

You are fantastic. It works!

However when I click on the command button the dialogue box of the macro opens up and I need to click the run button. This is something I want to avoid.

I have sent you in an email what I mean.

Thanks

To create a ribbon button

To create a ribbon button click on
File
Options
Customize Ribbon

1/ In the right frame, select the group Home and add a new group such as you already made it. Then, name it with an appropriate name.
Then expand the group and let it highlighted

2/ In the command list "Choose commands from"
Select Macros
In the list, select PERSONAL!Eg_New
Click on the buttton Add >>
The macro is copied into the list.
Make a right click to customize the name and the icon.

Apparently, it's what you did but I'm not sure...

If the dialogbox appears, it's because you have dropped the wrong macro from your ribbon customization.
Perhaps you forgot to copy the entire subroutine into the module of the PERSONAL VBAProject. Then, it is not private (you can see "All open workbooks" in the picture you sent me).
The best way is to copy the module from the dataworkbook into the PERSONAL VBAproject by drag and drop with the mouse.
Then the module is duplicated. After you verify that it has been copied correctly, you can remove the original module from your data workbook after confirmation (you can save it by safe preference).

Can you tell how you have proceeded ?

I got it!!

Argy you are a genius!

It works and I can't thank you enough:)

Merci beaucoup pour votre patience et votre savoir faire.

Comme vous pouvez le constater je ne suis qu'une debutante et j'aimerai en savoir d'avantage.

Est-ce que c'est possible de me guider sur le choix de lectures, livres etc?

Merci merci beaucoup.

The other users are unable to see the macro...

Dear Argy
I am having a problem with user visibility of the macro.

I have atatched the macro template on the reporting tool of the application. However the other users are uanable to click on the Icon to refresh the data. It seems that I am the only one to do so.

I am going to send you some print screens.

Thanks for advising.