How to shorten VBA code using repeated SUMIFS function? - vba

I have written up a number of SUMIFS in VBA based on the change of a value in cells
E.g. Cell A23 is a drop down menu with Total and UK
If A23 = "Total" Then
Result.Range("A24").Value = WorkSheetFunction.Sumifs(Range(B:B)),
Range(C:C)), "Year",
Range(D:D)), "Group")
If A23 = "UK" Then
Result.Range("A24").Value = WorkSheetFunction.Sumifs(Range(B:B)),
Range(C:C)), "Year",
Range(D:D)), "Group",
Range(E:E)), "UK")
Based on the example above, the second code is a repeat of the first code but with an additional range included to pick up "UK"
Instead of constantly rewriting it is there a way I can shortern the code so I can simply concatenate any additional range I want to include?
So ideally I could have something like:
Test = Result.Range("A24").Value = WorkSheetFunction.Sumifs(Range(B:B)),
Range(C:C)), "Year",
Range(D:D)), "Group"
If A23 = Total Then
A24 = Test)
If A23 = UK Then
A24 = Test &, Range(E:E), "UK")
Is this possible and if so how can I do it?

Could you enter the actual function in the cells, rather than do the worksheetfunction calculation in the vba? (doing worksheetfunction calculations won't actually enter the formula in the cells, just return the output value)
Something like this maybe:
Dim strFormula as String
strFormula = "=SUMIFS(B:B, C:C, ""Year"", D:D, ""Group"")"
'Thats the basic formula
If Result.Range("A23").Value = "UK" Then
strFormula = replace(strFormula, ")", "E:E, ""UK"")")
'that replaces the end bracket with the extra condition
End If
Result.Range("A4").FormulaA1 = strFormula

(this answer posted mainly in response to that second comment with the actual code included - although it looks like the actual operation you're doing is a bit different?)
So, as I said you need to simplify that code out a bit by saving the separate parts in variables
Dim strFormula as String
Dim rngLIC as Range
Dim rngRegion as Range
Dim rngYear as Range
Set rngLIC = Range(rngHeaders.Find(LIC) , rngHeaders.Find(LIC).End(xlDown))
Set rngRegion = Range(rngHeaders.Find(Year), rngHeaders.Find(Year).End(xlDown))
Set rngYear = Range(rngHeaders.Find(Year), rngHeaders.Find(Year).End(xlDown))
'and I think you'll need to add others for the extra bit you wanted to fix, but you get the pattern
strFormula = "=SUMIFS(" & _
rngLIC.Address(xlA1) & "," & _
rngRegion.Address(xlA1) & ", A23," & _
rngYear.Address(xlA1) & ", ""Year 0"")"
'Then add the replace bit I detailed above if necessary to add bits to the formula
That code should hopefully do xsactly the same as the code snippet you put in the comment. Does that help? (please vote up if it does because I'm trying to build my reputation!!)

Related

I have 3 excel formulas that I would like to fill ranges in a spreadsheet with, how can I make sure the cells change with the rows?

=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, " ")
=IF(N2=" ", " ",NETWORKDAYS(H2,TODAY()))
=IF(OR(O2 = " ", O2 <= 0), " ", (O2/N2)*100)
These are the three formulas, I want to make sure that as they are inserted into the worksheet the cell references will still change to match the rows they are on, as they would in a normal spreadsheet. Any advice would be much appreciated! (To clarify, I need to fill the ranges using VBA as the code I'm using clears the worksheet every time it is run.)
you could use FormulaR1C1 property of range object, which uses the "R1C1" notation for range addresses
for instance inserting your first formula in "A1" would be:
Range("A1").FormulaR1C1 = "=IF(AND(RC7<>100,TODAY()>=RC8, TODAY()<=RC9), RC5, "" "")"
where the pure R would assume the current cell row index, while C7 stands for a fixed (not varying with host cell position) 7th column index reference, and so on
If i have interpreted your question correctly, you need something like the below:
Option Explicit
Sub InsertFormula()
Dim i As Long
Dim n As Long
n = Cells(Rows.Count, 1).End(xlUp).Row
For i = 1 To n
Cells(i, 1).Formula = "=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, "" "")"
Next i
End Sub
replace the 1 in n=... with whichever column has the most rows of data
replace for i = 1 to whichever row it must begin form
You will notice i have added extra quotations to the end of the formula, this is needed as quotes in a formula in VBA must be enclosed... in more quotes lol
Apply this concept for the other formulas :)
Instead of absolute references like G2 you can use something along
.FormulaR1C1 = "=SUM(RC[-2]:R[5]C[-2])"
where R and C reference the offset from the current cell (positive: right or down, negative: up or left).
Use it in a way similar to this:
Dim c
For Each c In Selection
c.FormulaR1C1 = "=SUM(RC[-2]:R[5]C[-2])"
Next c
Relative References are adjusted when you set the formula to range of cells:
[A1:B2].Formula = "=C$1" ' now the formula in B2 will become "=D$1"
You can also set multiple formulas at once:
Range("K2:M9").Formula = Array("=IF(AND(G2<>100,TODAY()>=H2, TODAY()<=I2), E2, "" "")", _
"=IF(N2="" "", "" "",NETWORKDAYS(H2,TODAY()))", _
"=IF(OR(O2 = "" "", O2 <= 0), "" "", (O2/N2)*100)" )
or if each row has different formula:
[A1:Z3] = [{"=1";"=2";"=3"}]

VBA/Excel Find a string in a cell to determine the next cell's value

I need to find a string in a cell, and if that string is found, the cell next to it has to put that string in the next cell. In layman's terms:
IF "Medina" is found in a C3
put "ME" in cell D3;
ELSEIF "Brunswick" is found in C3
put "BR" in D3;
ELSE
put "OTH"in D3;
And this has to go through out the sheet, i.e., C4 & D4, C5 & D5, etc.
Thanks in advance
Sounds like you're looking for the InStr function (see this link: https://msdn.microsoft.com/en-us/library/8460tsh1(v=vs.90).aspx). Basically we want to check if there is a non-zero answer for this, which indicates the string can be found.
So you could do something like below. Note I just put in 40 as your last row arbitrarily, but you can change this as you need.
Dim indStartRow As Integer
Dim indEndRow As Integer
Dim i As Integer
indStartRow = 3
indEndRow = 40
For i = indStartRow To indEndRow
If InStr(Sheets("Sheetname").Range("C" & i).Value, "Medina") > 0 Then
Sheets("Sheetname").Range("D" & i).value = "ME"
ElseIf InStr(Sheets("Sheetname").Range("C" & i).Value, "Brunswick") > 0 Then
Sheets("Sheetname").Range("D" & i).value = "BR"
Else
Sheets("Sheetname").Range("D" & i).value = "OTH"
End If
Next i
I don't think you need VBA for this, Excel Formulas are sufficient. If you want your Selection criteria to be easily extendable, use this:
=IFERROR(INDEX($AB$1:$AB$2,MATCH($A1,$AA$1:$AA$2,0)),"Other")
This Formula is in B1, while A1 contains Medina, Brunswick, etc. AA1:AA2 contain Medina...Brunswick and AAB1:AAB2 ME...BR. It can be moved to a different sheet, and you can extend it by selecting the last cell and inserting whole rows. Later you may want to use named ranges, too.

Add =IFERROR function to formulas

I'm trying to add =IFERROR function to Excel formulas. Example original formula in active cell: =A1/B3, example new formula: =IFERROR(A1/B3;0). However it results in runtime error. The formula shown in the message box appears to be correct.
I've tested the same code for adding parentheses to formulas with the variables: First_part = "=(" and Last_Part = ")", which worked fine. I've also tested the same code with IF function using the variables:
First_part = "=IF(F1=2;" and Last_Part = ";0)", which also resulted in runtime error.
Sub Adding_IFERROR()
Dim Cell_Content As String
Dim First_Part As String
Dim Last_Part As String
Dim New_Cell_Content As String
First_Part = "=IFERROR("
Last_Part = ";0)"
'Remove the initial "=" sign from original formula
Cell_Content = ActiveCell.Formula
Cell_Content = Right(Cell_Content, Len(Cell_Content) - 1)
'Writing new formula
New_Cell_Content = First_Part & Cell_Content & Last_Part
MsgBox New_Cell_Content, vbOKOnly
ActiveCell.Formula = New_Cell_Content
End Sub
Is there any obvious reason to why it doesn't work?
You need to use commas instead of semicolons, when creating formulas by VBA.
So, change this:
Last_Part = ";0)"
to this:
Last_Part = ",0)"
After spending hours yesterday, I found the solution 5 seconds after posting the question.
Solution:
Last_Part = ",0"
I use semicolon ";" as separator in excel, but when inserting from VBA I had to use comma ",".

VBA Excel: Concatenate a range of cells

I am trying to concatenate a range of cells along a single row. This group of cells has a defined start but a variable end. I tried doing this, but it didn't work. I'm still learning the Syntax of VBA but I haven't seen anything that says this WON'T work. Any help is appreciated.
Dim hexVal As String
For i = 4 To N + 3
Cells(3, i) = Application.WorksheetFunction.Dec2Hex(Cells(2, i), 2) & " "
Next i
hexVal = CONCATENATE(Range(Cells(3,i),Cells(3,N+3))
End Sub
You do not need Concatenate(), but using & instead:
for i = 4 to N + 3
hexVal = hexVal & cells(3,i)
next i
That is in case you are just concatenate the strings and you do know the range needs to be concatenate.
HEre's your problem:
CONCATENATE(Range(Cells(3,i),Cells(3,N+3))
The Cells method returns a range object, the default property of which is the .Value property. So, this is equivalent to:
CONCATENATE(Range(Cells(3,i).Value,Cells(3,N+3).Value)
As such, it will ALWAYS FAIL unless those cells contain a valid address string.
Solution ... just use the built-in concatenator
hexVal = Range(Cells(3,i) & Cells(3,N+3))
Or:
hexVal = CONCATENATE(Range(Cells(3,i).Value,Cells(3,N+3).Value))

Get Excel cell background color hex value

I would like to obtain the background color of a cell in an Excel sheet using a UDF formula or VBA.
I found this UDF:
Public Function BColor(r As Range) As Long
BColor = r(1).Interior.ColorIndex
End Function
It can be used like this in a cell: =BColor(A1)
I'm not familiar with VBA, this returns some long value and I wonder if it is possible to obtain the hex value directly. Thank you!
try this
Function HexCode(Cell As Range) As String
HexCode = Right("000000" & Hex(Cell.Interior.Color), 6)
End Function
I tried the above code, but it returned a BGR value (as suggested)
However, this code returns a RGB Hex value.
I just can't get it to auto update.
Public Function HexCodeRGB(cell As Range) As String
HexCodeBGR = Right("000000" & Hex(cell.Interior.Color), 6)
HexCodeRGB = Right(HexCodeBGR, 2) & Mid(HexCodeBGR, 3, 2) & Left(HexCodeBGR, 2)
End Function
Good luck
Based on the best voted answer, here is an example of a real case, my case.
I supply it as a macro and a screenshots. I hope this can help someone out.
The VBA macro is simple but I'll paste it here. If you take a look at the attachment you will see that I have duplicated that column and cleared the color names in Spanish and titled the column "color", the I did run this macro:
Sub printHEXBGColor()
Set r = Range("myRange")
Dim HEXcolor As String
Dim i As Long
For i = 1 To r.Rows.Count
r.Cells(i, 1).Activate
HEXcolor = "#" + Right("000000" & Hex(ActiveCell.Interior.Color), 6)
ActiveCell = HEXcolor
Next i
End Sub
Screenshot of the result