I am using the below code:
Sub Evaluation_Formula()
Dim i As Long
With Worksheets("Sheet1")
i = .Evaluate("MIN(IF((LEFT($B$1:$B$89,5)*1)=C1,$B$1:$B$89,""""))")
.Range("F3").Value2 = i
End With
End Sub
However, the formula is limited to B89, how can I use Last Row in Column B in the formula ?
For all intents and purposes you are really only concerned with the last number in column B, not specifically the last row. To do that in a worksheet formula you would use something like this array formula.
=MIN(IF(--LEFT(B1:INDEX(B:B, MATCH(1E+99,B:B )),5)=C1, B1:INDEX(B:B, MATCH(1E+99,B:B))))
That can translate into your VBA Evaluate method like the following.
Sub Evaluation_Formula()
Dim i As Long
With Worksheets("Sheet1")
i = .Evaluate("MIN(IF(--LEFT(B1:INDEX(B:B, MATCH(1E+99,B:B )),5)=C1, B1:INDEX(B:B, MATCH(1E+99,B:B))))")
.Range("F3").Value2 = i
End With
End Sub
The double unary (aka double-minus or --) does the same job as multiplying the text result from the LEFT function by 1. There is no need to pass a zero-length string (e.g. "") in as the FALSE is sufficient for non-matches in the IF function. Since you are evaluating text into a formula, there is no need for the $ absolute markers.
Keep the . in .Evaluate or add the worksheet name to the cell references in the formula. Without it you run the risk of evaluating another worksheet's B1:B89 and C1 cells if Sheet1 does not hold the workbook's ActiveSheet property.
I guess this will post proper code:
Sub Evaluation_Formula_w_LR()
Dim i As Long
Dim LR As Long
With Worksheets("Sheet1")
LR = .Cells(.Rows.Count, 2).End(xlUp).Row
i = Evaluate("MIN(IF((LEFT($B$1:$B$" & LR & ",5)*1)=C1,$B$1:$B$" & LR & ",""""))")
.Range("F10").Value2 = i
End With
End Sub
Related
Hi i want to show an output to a specific cell at B column but i really don't have any idea on how to make it to show. Example: if "A2" has the record i want "B2" to show the output. If "A100" has the record, i want "B100" to show the output
Sub Testing()
Dim cell As Range
For Each cell In Range("A2:A4")
If cell.Value = "yes.com" Then
Range("B2:B4").Value = "Correct"
End If
Next
End Sub
The code above shows the output data "Correct" from "B2" to "B4" but what i want it to show on only the specific cell. Please Help
Currently you are looping through a range object. Per cell. One a small dataset this is fine but in your current attempt you'll need to change:
Range("B2:B4").Value = "Correct" for cell.Offset(0,1).value = "Correct"
As per my comment, you can do this a bit smarter/faster. Looping through worksheet cells is slow, certainly on large datasets (a 1000 rows is not that many yet to be honest). Nonetheless it's good to know that a good practice is to go through arrays. Let me show you below:
Sub Testing()
Dim lr As Long, x As Long
Dim arr As Variant
With Sheet1 'Change accordingly
lr = .Cells(.Rows.Count, 1).End(xlUp).Row
arr = .Range("A2:B" & lr)
For x = LBound(arr) To UBound(arr)
If arr(x, 1) = "yes.com" Then
arr(x, 2) = "correct"
End If
Next x
.Range("A2:B" & lr).Value = arr
End With
End Sub
So you can see a few things that will be helpfull:
A reference to a sheet (through a CodeName to refer to a range's parent. Without it, the macro will simply reference the ActiveSheet which is for obvious reasons not always the correct one.
I have made use of a dynamic sized array. The lr variable will get the last used row in column A, so you don't have to work through full qualified references no more.
The arr variable is an array which takes the values from the specified range into memory. Running through data in memory is much quicker than a loop/iteration over worksheet cells. This will become much more noticable when you would have even larger datasets.
I wrote the array back to the range in one go instead of several writings.
Hopefully that helped =)
As previously mentioned a 1000 rows is still not that much. Allthough I suggest you stick with the Array approach, you can also Evaluate column A and fill column B accordingly in one go instead of stepping through a range object. It's an array formula in disguise so not very quick on actual large datasets.
Sub Testing()
Dim lr As Long
Dim rng As Range
With Sheet1 'Change accordingly
lr = .Cells(.Rows.Count, 1).End(xlUp).Row
Set rng = .Range("A2:B" & lr)
rng.Columns(2).Value = .Evaluate("IF(" & rng.Columns(1).Address & "=""yes.com"",""correct"","""")")
End With
End Sub
Just try:
Sub test()
Dim i As Long
For i = 1 To Rows.Count
If Cells(i, 1) = "yes.com" Then Cells(i, 2) = "Correct"
Next
End Sub
It will loop through entire A column.
Alternatively, you can enter in B1 formula:
=IF(A1="yes.com","Correct","")
and drag it all the way down.
This is quite simple, I am aware, but something is going wrong for me. I simply want to subtract the values I have in column B from the values I have in column C and place these results in column Q.
I have assigned my strFormula(1) as a variant and then applied the equation to the strFormula(1). I have altered the following code from #Manhattan here on Stack Overflow :)
Sub FormulasNoLoops()
Dim strFormulas(1) As Variant
With ThisWorkbook.Sheets("Sheet1")
strFormulas(1) = "=(C2-B2)"
.Range("Q2:Q130").Formula = strFormulas
.Range("Q2:Q130").FillDown
End With
End Sub
There is no error when I run the script but also no result in column Q.
Ideally, I do not even want to enter the last cell of the column but maybe use .End(xlUp) somewhere.
Thanks all!
first
Dim strFormulas(1) As Variant
is creating an array with two items, 0,1
For one formula I would avoid the variable totally.
But if you want to use it just make it a string without the (1)
Dim strFormulas As String
Then load it:
strFormulas = "=(C2-B2)"
Also when you apply the formula to the whole range there is no need to fill down:
Sub FormulasNoLoops()
With ThisWorkbook.Sheets("Sheet1")
.Range("Q2:Q130").Formula = "=(C2-B2)"
End With
End Sub
Sub test()
Dim lastrow As Long
Dim rng As Range
last_row = ThisWorkbook.Worksheets("sheet1").Cells(Rows.Count, 1).End(xlUp).Row
Set rng = Range("C2:C" & last_row)
rng.Formula = "=B2-A2"
End Sub
1) My objective is the following one:
To replace the content of a cell with a conditional statement that is either "Monitorato" or "Non Monitorato". The Condition determining the type of statement is the output of a Vlookup function. IF vlookup finds a value I would have "Monitorato", while if this does not happen I would have "Non Monitorato".
2) By using traditional excel functions, the thing is solved In this way:
=IF(ISNA(VLOOKUP(cell to look for, range, column, false)),"Non Monitorato","Monitorato")
I then copy and paste this formula to all the cells below the one I wrote the initial formula
3) However I would like to implement this thing using VBA.
Moreover, there is an additional problem. The data are actually filtered, so I need to use the Vlookup function only on the filtered data. The Vlookup function should look for the first visible cell in the dataset.
4) The horrible code that I wrote is the following one:
Sub MyFunction()
Dim i As Long
Dim LastRow As Long
Dim FirstRow As Long
Dim Header As Range
Set Header = Range("d1")
FirstRow = Range(Header.Offset(1, 0), Header.End(xlDown)).SpecialCells(xlCellTypeVisible).Cells(1).Count
LastRow = ActiveSheet.UsedRange.Rows.SpecialCells(xlCellTypeVisible).Count
For i = FirstRow To LastRow
Sheets(1).Cells(FirstRow, 5) = Application.WorksheetFunction.VLookup(Sheets(1).Cells(i, 3), Sheets(1).Range("C2:D100"), 2)
Next i
End Sub
The error I am getting is
Unable to get the vlookup property of the worksheet function class
I would like to solve it, but I also know there must be an easier solution to the problem...
Thank you all!
There's actually several issues with the current code and it will not accomplish what you are after. See if this code works for you:
Sub Monitorato()
Dim ws1 as Worksheet
Set ws1 = Sheets(1)
Dim rLookup As Range, rCell as Range
With ws1
Set rLookup = .Range(.Range("D1"),.Range("D1").End(xlDown)).SpecialCells(xlCellTypeVisible)
For each rCell in rLookup
If Not .Range("C2:D100").Find(rCell.Offset(,-1).Value2) Is Nothing Then
rCell.Offset(,1).Value = "Monitorato"
Else
rCell.Offset(,1).Value = "Non-Monitorato"
End If
Next
End With
End Sub`
I am working on a workbook where there are 8 worksheets.
Names of worksheets:
[Hierarchy, wins, outlook, pcv, misses, losses, backdate, login].
In "Hierarchy" worksheet I want to apply the formula in a column B, up to the last value of that column B (which includes names of sales person). (I guess we will use a loop, I'm not sure which loop should I use.)
=COUNTIFS(wins!$AL:$AL,Hierarchy!$B4,wins!$P:$P,"Complete")
PS: I need help in above countif formula and loop (in VBA) to use that formula up to the last record in the column.
If you just need a result as opposed to filling formulas down the column in a worksheet, you could use one of these options:
Fast one - only using loops:
Sub countifs_in_vba()
Dim Result As Long
Dim i As Long
Dim cell As Range
Dim wsHierarchy As Worksheet
Dim wsWins As Worksheet
Set wsHierarchy = ThisWorkbook.Sheets("Hierarchy")
Set wsWins = ThisWorkbook.Sheets("wins")
For Each cell In Intersect(wsHierarchy.Range("B:B"), wsHierarchy.UsedRange)
For i = 1 To wsWins.Cells.SpecialCells(xlCellTypeLastCell).Row
If cell.Value = wsWins.Cells(i, "AL").Value And wsWins.Cells(i, "P").Value = "Complete" Then
Result = Result + 1
End If
Next
Next
MsgBox Result
End Sub
Slower one - employing Application.WorksheetFunction:
Sub countifs_in_vba2()
Dim Result As Long
Dim cell As Range
Dim wsHierarchy As Worksheet
Dim wsWins As Worksheet
Set wsHierarchy = ThisWorkbook.Sheets("Hierarchy")
Set wsWins = ThisWorkbook.Sheets("wins")
For Each cell In Intersect(wsHierarchy.Range("B:B"), wsHierarchy.UsedRange)
Result = Result + Application.WorksheetFunction.CountIfs(wsWins.Range("AL:AL"), cell.Value, wsWins.Range("P:P"), "Complete")
Next
MsgBox Result
End Sub
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