Concatenate string to build formula in VBA - excel

I tried to build VBA code to enter a formula to sum up a range.
I want a formula in cell E30
=SUM(E10:E20)
Sub calTotalOneOffExpense()
Dim startRow As Integer
Dim endRow As Integer
startRow = 10
endRow = 20
Range("E30:E30").Select
Dim sFormula As String
sFormula = "=Sum(E" & startRow & ":E" & endRow & ")"
ActiveCell.FormulaR1C1 = _
sFormula
End Sub
The formula in E30 becomes
=SUM('E10':'E20')

I don't think you understand the difference between Formula and FormulaR1C1. You should study the documentation. Formula expects A1-style notation.
ActiveCell.Formula = "=Sum(E" & startRow & ":E" & endRow & ")"
FormulaR1C1 expects R1C1-style notation
ActiveCell.FormulaR1C1 = "=Sum(R" & startRow & "C5:R" & endRowRow & "C5)"
which is equivalent ​to
ActiveCell.Formula = "=Sum($E$10:$E$20)"

Do not use .FormulaR1C1
Use .Formula instead.
sFormula = "=SUM(E" & startRow & ":E" & endRow & ")"
ActiveCell.Formula = sFormula

Related

Why my cell output become like this =SUM('J2':'J13')-SUM('AB2':'AB13')

this is my vba code:
Sub Macro1()
Dim lastrow As Long
lastrow = 13
Range("AB" & CLng(lastrow) + 5).Select
ActiveCell.FormulaR1C1 = "=SUM(J2:J" & CLng(lastrow) & ")-SUM(AB2:AB" & CLng(lastrow) & ")"
End Sub
i wonder why the cell output have '' ?
should be.
Sub Macro1()
Dim lastrow As Long
lastrow = 13
Range("AB" & CLng(lastrow) + 5).Select
ActiveCell.Formula = "=SUM(J2:J" & CLng(lastrow) & ")-SUM(AB2:AB" & CLng(lastrow) & ")"
End Sub

VBA excel - range.formula issue

There is a particular part of my code which I cannot make work,
I'm trying to do the following command on VBA =RIGHT(LEFT(X1;Z1-2);LEN(LEFT(X1;Z1-2))-FIND(":";X1))
On cell X1, there is a text: RESULTS:NG & MODEL:IJ
My VBA code is:
LR = Cells(Rows.Count, "A").End(xlUp).Row
For i = 1 To LR
cel = "A" & i
cel2 = "Y" & i
cel3 = "Z" & i
cel4 = "X" & i
Range("M" & i).Formula = "=RIGHT(LEFT(" & cel4 & "," & cel3 & "-" & 2 & "),LEN(LEFT(" & cel4 & "," & cel3 & "-" & 2 & "))-FIND(:" & cel4 & "))"
Next i
I'm open for a better approach for this issue as well
Thanks in advance
Try writing all the formulas at once and reduce using quotes within the formula as much as possible.
Range(Cells(1, "M"), cells(lr, "M")).Formula = _
"=RIGHT(LEFT(X1, Z1-2), LEN(LEFT(X1, Z1-2))-FIND(char(58), X1))"
All range and cells reference within a sub procedure are better with a properly defined parent worksheet reference.
dim lr as long
with worksheets("sheet1")
LR = .Cells(.Rows.Count, "A").End(xlUp).Row
.Range(.Cells(1, "M"), .cells(lr, "M")).Formula = _
"=RIGHT(LEFT(X1, Z1-2), LEN(LEFT(X1, Z1-2))-FIND(char(58), X1))"
end with

My user defined VBA function is updating all cells using it with the same thing, I don't want it too

I am trying to make it easier for users to work with an excel sheet instead of having to modify an arduous expression anytime a change is needed. I am dynamically placing the function's result into a cell. I got everything functioning how it should except:
If I go to another sheet and use the formula, it will return the proper results; however, when returning to another sheet that was already using using it, that sheet will display the most resent results and no longer its own instance of passed variables. These sheets also tie into a dashboard sheet so I need to make sure that if I calculate one sheet, it doesn't tamper with the others. I wasn't sure how to word this issue, so if there is nomenclature in place that I am not using or if this has been answered in the past, let me know and I will close this out.
'-------------------
'getScore
' This function is called from a cell and is passed an intager.
' The integer represents the section that it is being called from.
' There is also the sheet title that is passed thrugh to the range.
'-------------------
Function getScore(section As Integer, sheetTitle As String)
Application.Volatile
Dim rngSt As Integer
Dim rngEnd As Integer
rngSt = getRange(section, sheetTitle, 1) 'Gets start range for formula
rngEnd = getRange(section, sheetTitle, 2) 'Gets end range for formula
Dim Formula As String 'Broken into seperate concatinated lines for readablility
'-(COUNTBLANK(H" & rngSt & ":H" & rngEnd & ")),"
' This section uses nested if statements to acrue the score through each level.
Formula = "=IF(SUM(D" & rngSt & ":D" & rngEnd & ")= nonBlank(D" & rngSt & ":D" & rngEnd & "),"
Formula = Formula & "IF(SUM(F" & rngSt & ":F" & rngEnd & ")= nonBlank(F" & rngSt & ":F" & rngEnd & "),"
Formula = Formula & "IF(SUM(H" & rngSt & ":H" & rngEnd & ")= nonBlank(H" & rngSt & ":H" & rngEnd & "),"
Formula = Formula & "IF(SUM(J" & rngSt & ":J" & rngEnd & ")= nonBlank(J" & rngSt & ":J" & rngEnd & "),"
Formula = Formula & "IF(SUM(L" & rngSt & ":L" & rngEnd & ")= nonBlank(L" & rngSt & ":L" & rngEnd & "),5,4),3),2),1), 0)"
getScore = Eval(Formula) 'Evaluates formula and returns a score of 0-5.
End Function
Here is the getRange fucntion
Function getRange(section As Integer, sheetName As String, rangePoint As Integer)
Application.Volatile
Dim FindRow As Range
Dim ws As Worksheet
Dim wb As Workbook
Set wb = ActiveWorkbook
If section = 1 Then
If rangePoint = 1 Then
With wb.Sheets(sheetName)
Set FindRow = .Range("C9:C9")
End With
getRange = FindRow.Row
End If
If rangePoint = 2 Then
With wb.Sheets(sheetName)
Set FindRow = .Range("C:C").Find(What:="rngEnd", LookIn:=xlValues)
End With
getRange = FindRow.Row - 1
End If
End IF
End Function
Here is my Eval fuction
Function Eval(Ref As String)
Application.Volatile
Eval = Evaluate(Ref)
End Function
nonBlank fucntion
Function nonBlank(r As Range) As Long 'Counts and returns the number of non blank cells found in given range.
Application.Volatile
nonBlank = r.Cells.Count - WorksheetFunction.CountBlank(r)
End Function
In your case, the function is returning exactly what you tell it to. Your UDF has no specification of worksheet anywhere. What you see on the first sheet, after the second sheet calculates, is the returned value of the function, since it calculated on the second sheet. It's a little confusing, so let me try to break it down another way.
You enter a formula with UDF on Sheet1
UDF calculates on Sheet1, with Sheet1 ranges
You navigate to Sheet2 and recalculate UDF entered there
UDF calculates on Sheet2, with Sheet2 ranges
Concurrently on Sheet1 the UDF also calculates, with Sheet2 ranges (this is why you get the same results)
Since calculation doesn't happen when you change sheets, you still see the results calculated correctly.
Bottom line (TL;DR): Your UDF is poorly written.
To help with an answer to your question, please post your getRange function as Scott asked, as well as an example of how you are calling the UDF.
Edit: I see you posted the getRange function, but it's not complete. I think you're missing an End If statement perhaps. Also, your getScore function doesn't compile because you have an extra ">" character in there. Not sure what it's doing in there.
Formula = "=IF(SUM('" & sheetTitle & "'D" & rngSt & ":D" & rngEnd & ")= nonBlank('" & sheetTitle & "'D" & rngSt & ":D" & rngEnd & "),"
Formula = Formula & "IF(SUM('" & sheetTitle & "'F" & rngSt & ":F" & rngEnd & ")= nonBlank('" & sheetTitle & "'F" & rngSt & ":F" & rngEnd & "),"
Formula = Formula & "IF(SUM('" & sheetTitle & "'H" & rngSt & ":H" & rngEnd & ")= nonBlank('" & sheetTitle & "'H" & rngSt & ":H" & rngEnd & "),"
Formula = Formula & "IF(SUM('" & sheetTitle & "'J" & rngSt & ":J" & rngEnd & ")= nonBlank('" & sheetTitle & "'J" & rngSt & ":J" & rngEnd & "),"
Formula = Formula & "IF(SUM('" & sheetTitle & "'L" & rngSt & ":L" & rngEnd & ")= nonBlank('" & sheetTitle & "'L" & rngSt & ":L" & rngEnd & "),5,4),3),2),1), 0)"
Please note this is the quick fix. I wouldn't write a UDF this way. But we would need much more detail if we delve into that.
EDIT: If I understood what you need, this is a much shorter version and should fix the issue you're seeing...
Function Score( _
ByVal Section As Long, _
ByVal Anchor As Range _
) As Long
Dim CheckRange As Range
Application.Volatile True
Set CheckRange = Anchor.Parent.Range("C9", Anchor.Parent.Cells(Anchor.Parent.Rows.Count, "C").End(xlUp))
Score = Abs(CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 1)) = CheckRange.Cells.Count) + _
CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 3)) = CheckRange.Cells.Count) + _
CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 5)) = CheckRange.Cells.Count) + _
CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 7)) = CheckRange.Cells.Count) + _
CLng(WorksheetFunction.CountA(CheckRange.Offset(0, 9)) = CheckRange.Cells.Count))
End Function
You would then call these from any cell like this...
=Score(1,A1)
=Score(1,Sheet2!A1)
=Score(1,'Some other sheet'!A1)
I'm not even sure what the 'Section' variable is for. There isn't much explanation here.
Thanks, Zack Barresse

Adding formula to a cell and referencing to variables

I am trying to get a formula into a cell with variables from VBA, but I'm getting another Application or Object defined error. The error is triggered on the first row op Range("R" & i).FormulaR1C1 = "=Q" & i & "/" & DollarRate. I have tried using just Formula instead of FormulaR1C1.
Columns Q and R are empty. Column Q will contain values in € and Column R will show the value in $.
Dim LastRow As Integer, i As Integer
Dim DollarRate As Double
DollarRate = InputBox("Enter dollar rate:", "Dollar rate")
Range("Q1").Value = "$ POS"
Range("R1").Value = "€ POS"
LastRow = Cells(Rows.Count, "A").End(xlUp).Row
For i = 2 To LastRow
Range("R" & i).FormulaR1C1 = "=Q" & i & "/" & DollarRate
Next i
Try replacing this:
For i = 2 To LastRow
Range("R" & i).FormulaR1C1 = "=Q" & i & "/" & DollarRate
Next i
with this:
Range("R2:R" & lastrow).FormulaLocal = "=Q2/" & DollarRate

Run Time Error 1004 SumIf function

I'm trying to use the Sumif function in VBA, however, I'm getting a run-time error. The error started when I tried to add the variable CritLastCol into the formula. If I replace that with an actual cell reference it works. I want to be able to autofill the rows below this and my criteria will change based on the row. In other words my sum range and criteria range are fixed and my criteria is the cell to the left of my activecell (but not one over, it could be 20, 30 columns over).
Sub SumBydimcode()
Dim lastCol As Integer
Dim CritLastCol As String
lastCol = Cells(3 & Columns.Count).End(xlToLeft).Column
lastRow = Range("A" & Rows.Count).End(xlUp).Row
NewLastRow = Range("I" & Rows.Count).End(xlUp).Row
CritLastCol = ActiveCell.End(xlToLeft).Value
ActiveCell.FormulaR1C1 = "=SUMIF(R3C8:R" & lastRow & "C8," & CritLastCol & ",R3C10:R" & lastRow & "C" & lastCol & ")"
ActiveCell.AutoFill Destination:=Range(ActiveCell.Address & ":J" & NewLastRow)
End Sub
You need to surround your CritLastCol variable in quotation marks. To do so in VBA, you use the double-quote twice "". As a result, your code would look like this:
ActiveCell.FormulaR1C1 = "=SUMIF(R3C8:R" & lastRow & "C8,""" & CritLastCol & """,R3C10:R" & lastRow & "C" & lastCol & ")"
Notice the extra double-quotes surrounding CritLastCol
Ok, I figured out a way to do it... Instead of autofill, I used a loop starting at the end of my data and working back up.
Sub SumBydimcode()
Dim lastCol As Integer
Dim CritLastCol As String
lastCol = Cells(3 & Columns.Count).End(xlToLeft).Column
lastRow = Range("A" & Rows.Count).End(xlUp).Row
NewLastRow = Range("I" & Rows.Count).End(xlUp).Row
NewFirstRow = lastRow + 7
S = ActiveCell.Row
If S > NewLastRow - NewFirstRow Then
For S = ActiveCell.Row To NewFirstRow Step -1
CritLastCol = ActiveCell.End(xlToLeft).Value
ActiveCell.FormulaR1C1 = "=SUMIF(R3C8:R" & lastRow & "C8,""" & CritLastCol & """,R3C10:R" & lastRow & "C" & lastCol & ")"
ActiveCell.Offset(-1, 0).Select
Next S
End If
End Sub

Resources