Here is a simplified version of my data
Here is the formula I am entering
In D22 I need to enter the same SUMIF formula but the criteria is `ActiveCell.Offset(-1, -1)'. How can I create this macro? I have close to 570 rows and data similar and need to condense the dates into just one.
Thanks
I expect the macro to be able to input the sumif formula referencing the range as column $C, the criteria as $ActiveCell.Offset$(-1,-1) and the sum range as the column of the active cell so D but not locked as the sum range will change.
Declare and set Range variables to the various ranges you require, then build the formula from those variables .Address properties. Use the various parameters of Address to set the required Absolute/Relative addressing and External references
Sub EnterSum()
Dim rCritera As Range
Dim rCriteriaRange As Range
Dim rSum As Range
Dim rFormula As Range
Set rCriteriaRange = ActiveSheet.Columns(3)
Set rCritera = ActiveCell.Offset(-1, -1)
Set rSum = ActiveCell.EntireColumn
Set rFormula = ActiveCell 'Q doesn't specify this cell, so adjust as needed
rFormula.Formula = "=SumIf(" & rCriteriaRange.Address(1, 1) & "," & rCritera.Address(1, 1) & "," & rSum.Address(0, 0) & ")"
End Sub
Example: if ActiveCell is D5 then result is =SUMIF($C:$C,$C$4,D:D)
Related
I just started learning Excel VBA and have success entering formulas into cells until trying to input a SUMIF formula that uses the criteria "<>". Here is a sample of the code that has an error:
Dim myRange As Range
Dim myDataRange As Range
Dim mySum As Range
Dim myReason As Range
Set myRange = Cells.Find("Year").CurrentRegion
Set myDataRange = Intersect(myRange, myRange.Offset(1))
Set mySum = myDataRange.Columns(12)
Set myReason = myDataRange.Columns(14)
ActiveCell.Formula = "=SUMIF(" & myReason.Address(True,True) & ", ""<>" ," & mySum.Address(True,True) & """)"
The ultimate result would be to have a formula in the cell =SUMIF(myReason Range, "<>", mySum Range). It should add up all numbers where there is an empty cell in the myReason range.
I have managed to get the WorksheetFunction.SumIF(myReason, "<>", mySum) to work but it only has the formula result without showing the formula in the cell.
I thought about naming the ranges and then using the names, however, I will be copy / pasting these cells a couple of times into the same worksheet. It would cause issues with several cells having the same name.
Thank you for any help you can provide!
I am trying to make a macro using the SUMPRODUCT function together with SUMIF.
but when I run the macro I get …
run-time error 13.
I have tryed to make the same function just in a cell looking like this.
=SUMPRODUCT(SUMIF(B2:B3,K15:K18,L15:L18))
and it works fine, so I know the concept is proven.
Sub GrandTotal() 'Finds the last non-blank cell in a single row or column
Dim lRow As Long
Dim lCol As Long
Dim GrandTotal As Variant
Dim MyRg1 As Variant
Dim MyRg2 As Variant
Dim MyRg3 As Variant
'Find the last non-blank cell in column A(1)
lRow = Cells(Rows.Count, 1).End(xlUp).Row
'Find the last non-blank cell in row 1
lCol = Cells(1, Columns.Count).End(xlToLeft).Column
MsgBox "Last Row: " & lRow & vbNewLine & _
"Last Column: " & lCol
'set range
Set MyRg1 = Range("B2:B3")
'set criteria
Set MyRg2 = Range("$K$15:$K$18")
'set sum range
Set MyRg3 = Range("$L$15:$L$18")
For Each cell In Range(Cells(lRow, 2), Cells(lRow, lCol))
GrandTotal = WorksheetFunction.SumProduct(WorksheetFunction.SumIf(MyRg1, MyRg2, MyRg3))
cell.Value = GrandTotal
Next cell
End Sub
I have found some guides how to use the function in VBA and I followed the same princip, also i saw an other post here on stack that showed how to do, and yet I get the error.
hope some kind soul can help
First, each variable that is being assigned a Range object can be declared as a Range, instead of Variant. Also, the ranges that are being passed to SUMIF don't seem correct. The first argument or criteria range should be the same size as the third argument or sum range. So I am going to assume that the ranges assigned to MyRg1 and MyRg2 should be the other way around. So to start with we should have the following...
Dim MyRg1 As Range
Dim MyRg2 As Range
Dim MyRg3 As Range
'set criteria range
Set MyRg1 = Range("$K$15:$K$18")
'set criteria
Set MyRg2 = Range("B2:B3")
'set sum range
Set MyRg3 = Range("$L$15:$L$18")
Secondly, you won't be able to use WorksheetFunction.Sumproduct that way. You can, however, use the Evaluate method..
GrandTotal = Evaluate("SUMPRODUCT(SUMIF(" & MyRg1.Address & "," & MyRg2.Address & "," & MyRg3.Address & "))")
Note, though, the Evaluate method has a limitation. It does not accept more than 255 characters. In any case, since you want to transfer the result to a cell, you can first enter the actual formula in the cell, and then convert it into a value...
With cell
'enter the formula in the current cell
.Formula = "=SUMPRODUCT(SUMIF(" & MyRg1.Address & "," & MyRg2.Address & "," & MyRg3.Address & "))"
'convert the formula into a value
.Value = .Value
End With
Hope this helps!
After you have your function working, you can turn on the Macro Recorder, click the cell with the function you need, hit F2, and hit Enter. You will have VBA that does what you want.
Error 13 is a Type mismatch error. I looked up the documentation of WorksheetFunction.SumIf. It says the first argument should be of type Range, and the second and third a Variant. I can not test now, but try to declare MyRg1 as a Range.
This would be a good use for ConvertFormula since you have successfully built the formula in Excel, you just need VBA to generate the value. Note that convertformula cannot handle formulas over 255 characters.
Here's roughly how you could apply it. It's
Sub heresExample()
'formula with the cell in exitance
Dim fCell As Range
Set fCell = Range("G10") 'set this up with a formula that works for
'if you were to copy paste formula.
'Your original code modified
Dim cell As Range
For Each cell In Range(Cells(lRow, 2), Cells(lRow, lCol)).Cells
'Takes the formula and applies the value if from that exact cell.
'(you don't really need grand total)
GrandTotal = Evaluate(Application.ConvertFormula(fCell.Formula2R1C1, xlR1C1, xlA1, , cell))
cell.Value = GrandTotal
Next cell
End Sub
Excel VBA range formula is something like Sheet2.Range("A1").value.
You can, for example, refer to this address and change the value in that cell.
Now what I am looking for is to build this formula by using the contents of two cells; one cell says "Sheet2" and the other says "A1". How can I refer to these two cells in a formula so that it works the same way?
I have tried various dims and now end up without an error but not with the desired result. The current formula simply returns "Sheet2.Range("A1").value instead of its contents.
Sub AddressInCells()
'This is just for one reference. In reailty there is a table of references to loop through.
'For this example cell A1 in Sheet2 = "Text to take to sheet1"
Dim SheetSel As String
Dim CellSel As String
Dim ReferSel As String
With Sheet1
SheetSel = Cells(1, 1).Value
CellSel = Cells(1, 2).Value
ReferSel = SheetSel & ".range(" & Chr(34) & CellSel & Chr(34) & ").value"
MsgBox ReferSel
Sheet1.Range("D1").Value = ReferSel 'Results in "Sheet2.range("A1").value
Sheet1.Range("D2").Value = Sheet2.Range("A1").Value 'Results in Text to take to sheet1'
End With
End Sub
The expected result is that the formula works the "usual" way. It now simply returns a string.
I believe, instead you want to do:
ReferSel = Sheets(SheetSel).range(CellSel).value
You could try:
Option Explicit
Sub test()
Dim ws As Worksheet
Dim rng As Range
'With statement where the data are store. Change name if needed
With ThisWorkbook.Worksheets("Sheet1")
Set ws = ThisWorkbook.Worksheets(.Range("A1").Value)
Set rng = ws.Range(.Range("A2").Value)
End With
Debug.Print rng.Address
Debug.Print rng.Worksheet.Name
End Sub
You're trying to build a formula string, which follows this convention:
'<sheet name>!'<address>
The single-quotes are only strictly required if the sheet name contains a space, so this would be a valid formula:
=Sheet1!$A$1
But it's just good habit to always include them, so, you need to build your string from the values in those cells:
' offset the sheet name in single quotes, separate the sheet & address with !
ReferSel = "='" & SheetSel "'!" & CellSel
Sheet1.Range("D1").Formula = ReferSel
I'm a complete beginner to Excel VBA.
The following is code I've written that should iterate through a column in a sheet, filling values by referring to the column value to it's left and referring to another sheet in the same workbook to find what the correct corresponding value should be.
I've used a While loop so i can apply this VLOOKUP macro to each cell in the column ( only the lookup value, changes, which should be a variable denoting the column to the left) :
Dim result As String
Dim sheet As Worksheet
Dim rownum As Integer
Dim iterator As Integer
Dim lookup_value As String
Dim vlookupString1 As String
Set sheet = ActiveWorkbook.Sheets("datasheet")
rownum = sheet.Range("A1").End(xlDown).Row
Set iterator = 3
While iterator < rownum
lookup = "M" & iterator
vlookup1String = "=VLOOKUP(" & lookup & ",'GICS Sub-industry codes'!$A$2:$B$155,2,FALSE)"
With ActiveSheet.Cells
Range("N" & iterator).Select
Selection.Value = vlookup1String
End With
iterator = iterator + 1
End While
I'm getting an error # end while saying "expected if or select or sub..."
1) Have i made a syntax error?
2) Is my approach correct. I have observed this string approach to designing VLOOKUPS in vba only in one other place. It seemed best suited.
Fixing your code
You should use Wend not End While for your loop.
Cleaner Alternative
But you can fill an entire range in a single shot as below
It is better to "loop up" a range from the bottom using End(xlup) than to look down with End(xlDown) (which relies on no spaces)
You almost never need to use Select in VBA
Further explanation
rng1 sets a working range from the last used cell in column A in sheet datasheet to A3
rng1.Offset(0, Range("N1").Column - 1) says offset rng1 (which is column A) by 13 columns to use column N (ie OFFSET A by 14-1) for the formula insertion
I used the macro recorder to get the code you needed in column N for this part "=VLOOKUP(RC[-1],'GICS Sub-industry codes'!R2C1:R155C2,2,FALSE)".
IN R1C1 speak, RC[-1] means refer to the cell in the same row, but one column to the left. So in N3, the formula will start as =VLOOKUP(M4..), So in N30, the formula will start as `=VLOOKUP(M30..) etc
Suggested code
Sub QuickFill()
Dim ws As Worksheet
Dim rng1 As Range
Set ws = Sheets("datasheet")
Set rng1 = ws.Range(ws.[a3], ws.Cells(Rows.Count, "A").End(xlUp))
rng1.Offset(0, Range("N1").Column - 1).FormulaR1C1 = "=VLOOKUP(RC[-1],'GICS Sub-industry codes'!R2C1:R155C2,2,FALSE)"
End Sub
I'm trying to define a named range in Excel using VBA.
Basically, I have a variable column number. Then a loop runs to determine the first empty cell in that particular column.
Now I want to define a named range from row 2 of that particular column to the last cell with data in that column (first empty cell - 1).
For example, column 5 is specified, which contains 3 values. My range would then be (2,5)(4,5) if I'm correct.
I'm just wondering how to specify this range using only integers instead of (E2:E4).
Is it at all possible?
I found this code to define a named range:
'Change the range of cells (A1:B15) to be the range of cells you want to define
Set Rng1 = Sheets("Sheet1").Range("A1:B15")
ActiveWorkbook.Names.Add Name:="MyRange", RefersTo:=Rng1
Could anyone nudge me into the right direction to specify this range using integers only?
As your targeting a range of E2:E4 you would need to specify the cell locations. The below function might be of use to you, pass it the column number e.g. 5 and it will retunn the address so 5=E and 27=AA
ColLetter = ColNo2ColRef(colNo)
Set Rng1 = Sheets("Sheet1").Range(ColLetter & "2:" & ColLetter & "4")
ActiveWorkbook.Names.Add Name:="MyRange", RefersTo:=Rng1
Function ColNo2ColRef(ColNo As Long) As String
ColNo2ColRef = Split(Cells(1, ColNo).Address, "$")(1)
End Function
Hope this helps
EDIT: Or:
Set rng = Range(Cells(2, 5), Cells(4, 5)) 'E2:E4
ActiveWorkbook.Names.Add Name:="MyRange", RefersTo:=Rng
or alternatively
Sub test()
Set rng1 = Cells(2, 2) 'B2
Set rng2 = rng1.Resize(3, 1) 'B2:B4
'or
Set rng2 = Range(rng1, Cells(4, 2)) 'B2:B4
End Sub
or do it directly without looping using
With Sheet1
col = 5 'variable col
Set rng1 = .Range(.Cells(2, col), .Cells(.Rows.Count, col).End(xlUp))
End With
which is the same as
with sheet1
Set rng1 = .Range(.Range("E2"), .Range("E" & .Rows.Count).End(xlUp))
end with
EDIT: If you're setting up named ranges to change dynamically then you don't need VBA. Enter this directly into the named range in Excel and leave it to auto adjust automatically between E2 and whatever the last item is (assuming no blanks). =$E$2:INDEX($E$2:$E$5000,COUNTA($E$2:$E$5000)) (Extend 5000 if you need need more rows)