SUMIFS Formula in VBA with "<" - vba

Please could you tell me what is wrong with my second last SUMIFS formula where I use " < " &$F$1. All that is returned is FALSE in all the cells. The last SUMIFS without the < works fine.
Sub SumGroups()
Worksheets("Database").Activate
Dim lastCode, lastFiltCode As Integer
Dim Formula As String
'Determine Last Row in Column O (Unfiltered Codes)
lastCode = Range("O" & Rows.Count).End(xlUp).Row
'Filter Unique Codes into Column A Sheet2
Range("O1:O" & lastCode).AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=Sheet2.Range("A1"), Unique:=True
'Determine last Row in Column A (Filtered Codes)
Worksheets("Sheet2").Activate
lastFiltCode = Sheet2.Range("A" & Rows.Count).End(xlUp).Row
'Place SUMIF Formulas in Columns Sheet2
Worksheets("Sheet2").Range("B2:B" & lastFiltCode).Formula = _
"=SUMIFS(Database!$M$2:$M$" & lastCode & ",Database!$O$2:$O$" & lastCode & ",A2)"
Worksheets("Sheet2").Range("D2:D" & lastFiltCode).Formula = _
"=SUMIFS(Database!$M$2:$M$" & lastCode & ",Database!$O$2:$O$" & lastCode & ",A2,Database!$I$2:$I$" & lastCode & "," < " &$F$1)"
Worksheets("Sheet2").Range("F2:F" & lastFiltCode).Formula = _
"=SUMIFS(Database!$M$2:$M$" & lastCode & ",Database!$O$2:$O$" & lastCode & ",A2,Database!$I$2:$I$" & lastCode & ",$F$1)"
End Sub

Just to clarify why the other answers work:
SumIfs (as well as various other Excel functions requiring string operators (such as CountIf) expect that logical operators and their following statements be expressed as a string. I.e. should be enclosed in speech marks e.g. "myString".
Since a formula is also a string e.g. ActiveCell.Formula = "=If(A1=3, 1, 0)" the compiler gets confused about which set of quotation marks denotes the string. So for example this will not work: ActiveCell.Formula = "=If(A1=3, "Yes", "No")".
Technically the way to deal with this is to enclose the required quotation mark in quotation marks of it own; """ myValue """.
However, this quickly becomes confusing. Instead, use the Character function to return the char you require. In this case 34; chr(34) & myvalue & (chr34).

Worksheets("Sheet2").Range("D2:D" & lastFiltCode).Formula = _
"=SUMIFS(Database!$M$2:$M$" & lastCode & ",Database!$O$2:$O$" & lastCode & ",A2,Database!$I$2:$I$" & lastCode & ","" < "" &$F$1)"
This will do it.
put < in quotes.

First, in order to get <$F$1 inside the formula I use the Chr(34) to add the parenthesis "" inside the formula.
Besides that, you are mixing-up a few things:
Try to avoid using Worksheets("Database").Activate and Worksheets("Sheet2").Activate, and instead use fully qualified worksheets and ranges, like: With Worksheets("Database") and inside lastCode = .Range("O" & .Rows.Count).End(xlUp).Row.
You have Sheet2 and Worksheets("Sheet2"), these two not always mean the same worksheet. You could rename Sheet2 (by code name) to "Something", and that will be your 2nd sheet, and rename Sheet3 (by code name) to "Sheet2" and you have a problem. So decide on which method you want to use (I prefer to use Worksheets("Sheet2")).
Dim lastCode, lastFiltCode As Integer means lastCode is actually Variant and lastFiltCode is Integer. Anyway, it's better to use Long for both of these variables when you are trying to get the last row.
Code
Option Explicit
Sub SumGroups()
Dim lastCode As Long, lastFiltCode As Long
'Determine Last Row in Column O (Unfiltered Codes)
With Worksheets("Database")
lastCode = .Range("O" & .Rows.Count).End(xlUp).Row
'Filter Unique Codes into Column A Sheet2
.Range("O1:O" & lastCode).AdvancedFilter Action:=xlFilterCopy, _
CopyToRange:=Worksheets("Sheet2").Range("A1"), Unique:=True
End With
With Worksheets("Sheet2")
'Determine last Row in Column A (Filtered Codes)
lastFiltCode = .Range("A" & .Rows.Count).End(xlUp).Row
'Place SUMIF Formulas in Columns Sheet2
.Range("B2:B" & lastFiltCode).Formula = _
"=SUMIFS(Database!$M$2:$M$" & lastCode & ",Database!$O$2:$O$" & lastCode & ",A2)"
.Range("D2:D" & lastFiltCode).Formula = _
"=SUMIFS(Database!$M$2:$M$" & lastCode & ",Database!$O$2:$O$" & lastCode & ",A2,Database!$I$2:$I$" & lastCode & "," & Chr(34) & "<" & Chr(34) & "&$F$1)"
.Range("F2:F" & lastFiltCode).Formula = _
"=SUMIFS(Database!$M$2:$M$" & lastCode & ",Database!$O$2:$O$" & lastCode & ",A2,Database!$I$2:$I$" & lastCode & ",$F$1)"
End With
End Sub

Related

In VBA trying to create a dynamic Sumifs Formula with multiple criterias in multiple sheets

In VBA I am trying to create a sumifs formula with multiple criteria across different workbooks, but I am struggling on the syntax.
WorkbookRecut.Worksheets("Summary").Activate
Dim CountRows As Long
Dim CountRows2 As Long
CountRows = WorkbookRecut.Worksheets("Summary").Range("I" & WorkbookRecut.Worksheets("Summary").Rows.Count - 1).End(xlUp).Row
CountRows2 = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("I" & CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Rows.Count - 1).End(xlUp).Row
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Activate
Range("O6").Formula = _
"=Sumifs(" & [WorkbookRecut].Sheets("Summary").Range("I9").Address & ":" & [WorkbookRecut].Sheets("Summary").Range("I" & CountRows).Address _
& "," & [WorkbookRecut].Sheets("Summary").Range("A9").Address & ":" & [WorkbookRecut].Sheets("Summary").Range("A" & CountRows).Address _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("K6").Address(Rowabsolute:=False) _
& "," & [WorkbookRecut].Sheets("Summary").Range("D9").Address & ":" & [WorkbookRecut].Sheets("Summary").Range("D" & CountRows).Address _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("N6").Address(Rowabsolute:=False) & ")"
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("O6:O" & CountRows2).FillDown
Update
I have updated the most recent code. The only pending issue is the workbooks aren't changing, but all else works as I want :)
When creating a formula string to add to a cell you need to take into account where the different ranges are relative to the sheet where you're going to place the formula. Just calling Address() on one of the inputs may not give you what you want.
You can try something like the code below to abstract that part into a separate function:
Sub Tester()
Dim wsSumm As Worksheet, wsCBM As Worksheet
Dim lr As Long, f
Set wsSumm = WorkbookRecut.Worksheets("Summary")
Set wsCBM = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics")
lr = wsSumm.Cells(Rows.Count, "I").End(xlUp).Row
f = "=SUMIFS(" & RealAddress(wsCBM, wsSumm.Range("I9:I" & lr)) & "," & _
RealAddress(wsCBM, wsSumm.Range("A9:A" & lr)) & ",$K6," & _
RealAddress(wsCBM, wsSumm.Range("D9:D" & lr)) & ",$N6)"
With wsCBM.Range("O9")
.Formula = f
End With
End Sub
'get a range address for `rngRef`,
' suitable for use in a formula on worksheet `ws`
Function RealAddress(ws, rngRef As Range) As String
Dim s As String
If ws.Parent Is rngRef.Worksheet.Parent Then 'same workbooks?
If Not ws Is rngRef.Worksheet Then s = "'" & rngRef.Worksheet.Name & "'!" 'diff. worksheets?
s = s & rngRef.Address(True, True)
Else
s = rngRef.Address(True, True, external:=True) 'different workbooks
End If
RealAddress = s
End Function
For the formula: You're probably looking for the .Address property from each of your Ranges. Something like Range1.Address & ":" & Range2.Address To get an output like $I$9:$I$307.
But for your Ranges, you need to put the CountRows inside the Range input like WorkbookRecut.Sheets("Summary").Range("A" & CountRows) and then add the .Address to it.
I also agree with #TimWilliams that your formula code could benefit greatly in terms of readability by adding some nicknames for your worksheets.
Here is what your code would look like with those 3 things corrected:
Public CashBreaksMetricsWorkbookFinal As Workbook
Public WorkbookRecut As Workbook
Dim SumSh As Worksheet
Set SumSh = WorkbookRecut.Sheets("Summary")
Dim CountRows As Long
CountRows = SumSh.Range("I" & SumSh.Rows.Count - 1).End(xlUp).Row
Dim CSCIG As Worksheet
Set CSCIG = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics")
CSCIG.Activate
Range("O9").Formula = _
"=Sumifs(" & SumSh.Range("I9") & ":" & SumSh.Range("I" & CountRows).Address _
& "," & SumSh.Range("A9").Address & ":" & SumSh.Range("A" & CountRows).Address _
& "," & CSCIG.Range("K6").Address _
& "," & SumSh.Range("D9").Address & ":" & SumSh.Range("D" & CountRows).Address _
& "," & CSCIG.Range("N6").Address & ")"
CSCIG.Range("O9").FillDown
We were missing .Address(External:=True)
Thanks all for helping me get there (Finally!)
Final Code Below
Public CashBreaksMetricsWorkbookFinal As Workbook
Public WorkbookRecut As Workbook
Dim CountRows As Long
Dim CountRows2 As Long
CountRows = WorkbookRecut.Worksheets("Summary").Range("I" & WorkbookRecut.Worksheets("Summary").Rows.Count - 1).End(xlUp).Row
CountRows2 = CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("I" & CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Rows.Count - 1).End(xlUp).Row
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Activate
Range("O6").Formula = _
"=Sumifs(" & [WorkbookRecut].Sheets("Summary").Range("I9").Address(External:=True) & ":" & [WorkbookRecut].Sheets("Summary").Range("I" & CountRows).Address(External:=True) _
& "," & [WorkbookRecut].Sheets("Summary").Range("A9").Address(External:=True) & ":" & [WorkbookRecut].Sheets("Summary").Range("A" & CountRows).Address(External:=True) _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("K6").Address(Rowabsolute:=False) _
& "," & [WorkbookRecut].Sheets("Summary").Range("D9").Address(External:=True) & ":" & [WorkbookRecut].Sheets("Summary").Range("D" & CountRows).Address(External:=True) _
& "," & [CashBreaksMetricsWorkbookFinal].Worksheets("CSCIG_Cash Breaks Metrics").Range("N6").Address(Rowabsolute:=False) & ")"
CashBreaksMetricsWorkbookFinal.Worksheets("CSCIG_Cash Breaks Metrics").Range("O6:O" & CountRows2).FillDown
In the formula, you have to double-quote existing quotes:
Change
Sheets("Summary")
to:
Sheets(""Summary"")

Inserting formula using VBA in Excel does not work

First of all, I have tried to look at all the other examples of adding a formula using VBA, and I think I have tried to apply all the answers in this code
Sub AddFormulas(SheetName As String)
Dim i As Integer
'Switch worksheet
Set Wksht = ThisWorkbook.Worksheets(SheetName)
Wksht.Activate
Application.Calculation = xlCalculationManual
i = 2
While Not IsEmpty(Cells(i, 1))
Wksht.Cells(i, 18).Formula = "=IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")"
i = i + 1
Wend
Application.Calculation = xlCalculationAutomatic
End Sub
But still, it gives me this anoying error, that I can't interpret
If I change my line to
Wksht.Cells(i, 18) = "'IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")"
Then I get no error, and the correct formula is added, although as a text string
What is wrong, since it would not add what to me looks like a valid formula?
//V
The Formula property requires formulas to be written in English, i.e. English function names (not an issue here) and commas as separators rather than semi-colons.
So your statement should be:
Wksht.Cells(i, 18).Formula = "=IFERROR(VLOOKUP(A" & i & "," & Wksht.Cells(1, 18) & "!$A:$A,1,FALSE)," & Chr(34) & "MISSING" & Chr(34) & ")"
If you don't mind having "portability" issues, you could also use the FormulaLocal property, i.e.
Wksht.Cells(i, 18).FormulaLocal = "=IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")"
Write the formula as it should be in Excel, select it and run the following code:
Public Sub PrintMeUsefulFormula()
Dim strFormula As String
Dim strParenth As String
strParenth = """"
strFormula = Selection.Formula
strFormula = Replace(strFormula, """", """""")
strFormula = strParenth & strFormula & strParenth
Debug.Print strFormula
End Sub
It should print it as it should be.
I believe your code is giving error becouse of this Wksht.Cells(1, 18) part of line in this row Wksht.Cells(i, 18).Formula = "=IFERROR(VLOOKUP(A" & i & ";" & Wksht.Cells(1, 18) & "!$A:$A;1;FALSE);" & Chr(34) & "MISSING" & Chr(34) & ")". Make sure that Wksht.Cells(1, 18) really contains name of worksheet your are trying to address. If this cell is blank, you will receive previously mentioned error.

Putting complex formula to a cell

I want to put a formula to a cell and the values that I will be using is based on another cell(not a fix cell).
This is the formula if it is on the excel's formula bar.
=IF(AND(D9=0,J9<>0),100%,IFERROR(K9/D9,0))
But I cannot use this in vba because the formula should be flexible in every cell that I will be using this. Here's my code(I know its not good.)
ws.Range("L" & src1).Formula = "=IF(AND(" & ws.Range("D" & src1).Value & "=0," & ws.Range("J" & src1).Value & "<>0),100%,IFERROR(" & ws.Range("K" & src1).Value / ws.Range("D" & src1).Value & ",0))"
Assuming src1 is an integer value, I believe you want:
ws.Range("L" & src1).Formula = "=IF(AND(D" & src1 & "=0,J" & src1 & "<>0),100%,IFERROR(K" & src1 & "/D" & src1 & ",0))"

ranking data using vba

i come to ask your help i need to rank data using vba i have a block of results in column D and i want to rank them in column E without skiping any value so i tried this vba code but it gives me only zeros in all the column then my computer becom slow untill i close the excel file this is the vba code i am using if anyone can help me :
Sub Mactro5()
LastRow = Range("D" & Cells.Rows.Count).End(xlUp).Row
Range("E2:E" & LastRow).Formula = _
"=IF(D2=" & Chr(34) & Chr(34) & "," & Chr(34) & Chr(34) & ",SUMPRODUCT((D$2:D$" & LastRow & ">D2)/COUNTIF(D$2:D$" & LastRow & ",D$2:D$" & LastRow & "&" & Chr(34) & Chr(34) & "))+1)"
End Sub

Insert VBA into formula formatting?

Really quick question on how to format VBA in excel formulas. When you are inserting a formula into excel and you want to insert a variable from vba for example if b is a string you would use " & b & " is that the correct formatting? To illustrate the problem I have the code below and tried to use that formatting and well... I don't know why it wont work, I get a (Compile error: Expected: End of statement). Can anyone tell me where I am going wrong?
Dim HrsSTD As String
Dim HrsSAT As String
Dim HrsSUN As String
Dim HrsSTWN As String
Dim sdFormula
HrsSTD = ActiveCell.Address
Selection.Offset(0, 1).Select
HrsSAT = ActiveCell.Address
Selection.Offset(0, 1).Select
HrsSUN = ActiveCell.Address
Selection.Offset(0, 1).Select
HrsSTWN = ActiveCell.Address
sdFormula = "=IF((" & Range(NamedRange).Cells(2, 1).Address & _
"=""Please add a title"",0,VLOOKUP((" & Range(NamedRange).Cells(2, 1).Address & _
",'Tables (H)'!$H$2:$J$6,2,FALSE)* _
" & HrsSTD & "+VLOOKUP(" & Range(NamedRange).Cells(2, 1).Address & _
",'Tables (H)'!$H$2:$J$6,2,FALSE)* _
" & HrsSAT & "*1.25+VLOOKUP((" & Range(NamedRange).Cells(2, 1).Address & _
",'Tables (H)'!$H$2:$J$6,2,FALSE)*" & HrsSUN & "* _
1.5+VLOOKUP((" & Range(NamedRange).Cells(2, 1).Address & _
",'Tables (H)'!$H$2:$J$6,2,FALSE)*" & HrsSTWN & "*0.75)"
The code I would type into excel would be: But I want to change the A13's and the I16 (i.e. all the relative references) into variables in VBA
=IF(A13="Please add a title",0,VLOOKUP(A13,'Tables (H)'!$H$2:$J$6,2,FALSE)*F16+VLOOKUP(A13,'Tables (H)'!$H$2:$J$6,2,FALSE)*G16*1.25+VLOOKUP(A13,'Tables (H)'!$H$2:$J$6,2,FALSE)*H16*1.5+VLOOKUP(A13,'Tables (H)'!$H$2:$J$6,2,FALSE)*I16*0.75)
Is this what you are trying? Also I see that you haven't taken my advice from the previous answer.
One more tip. Break you code in simple parts. It is easier to understand.
The problem with your code is in the line
",'Tables (H)'!$H$2:$J$6,2,FALSE)* _
" & HrsSAT & "*1.25+VLOOKUP((" & Range(NamedRange).Cells(2, 1).Address & _
You can't write it like that. The first line doesn't have the ending ". You cannot carry it forward to the next line like that.
is this what you are trying?
Dim sFormula As String
Dim sAddr As String
sAddr = Range(NamedRange).Cells(2, 1).Address
sFormula = "=IF(" & sAddr & _
"=""Please add a title"",0,VLOOKUP(" & _
sAddr & ",'Tables (H)'!$H$2:$J$6,2,FALSE)*F16+VLOOKUP(" & _
sAddr & ",'Tables (H)'!$H$2:$J$6,2,FALSE)*G16*1.25+VLOOKUP(" & _
",'Tables (H)'!$H$2:$J$6,2,FALSE)*H16*1.5+VLOOKUP(" & _
sAddr & ",'Tables (H)'!$H$2:$J$6,2,FALSE)*I16*0.75)"