vlookup with dynamic lookup_value using VBA? - vba

I'm new to using the dynamic lookup value, I tried following the piece of advice from How to perform an excel vlookup with dynamic lookup_value using VBA? to fetch a value dynamically from another workbook.
This below code throws #Name? error.
Request your help to resolve the error.
Code Excerpt:
Dim ws As Worksheet
Dim dynamic_lookup_value As Range
Dim LocationRef As Range
Set ws = ActiveWorkbook.Worksheets("XYZ")
Set dynamic_lookup_value = ws.Cells(2, 1)
ActiveWorkbook.Names.Add Name:="dynamic_lookup_value", RefersTo:=Worksheets("XYZ").Cells(2, 1)
Set LocationRef = ws.Cells(2, ActiveColumn)
ActiveCell.FormulaR1C1 = _
"=IFERROR(VLOOKUP(" & dynamic_lookup_value.Address(0, 0) & ",'[ABC.xlsx]XYZ'!C1:C26,MATCH(""Location Description"",'[ABC.xlsx]XYZ'!R1C1:R1C26,0),)," & LocationRef.Address(0, 0) & ")"
After execution, the formula appears as
=IFERROR(VLOOKUP('A2','[HC report.xlsx]HC Report'!$A:$Z,MATCH("Location Description",'[HC report.xlsx]HC Report'!$A$1:$Z$1,0),),'G2')
Please note lookup value appears 'A2'(with single codes). Tried to declare the dynamic_lookup_value using the following piece of code but in vain.
ActiveWorkbook.Names.Add Name:="dynamic_lookup_value", RefersTo:=Worksheets("XYZ").Cells(2, 1)
If I manually remove the Singe code before and after the A2 and G2, then the formula works fine.
Request the experts advise to resolve this issue.
Many thanks,
Prabhu

New Answer:
Having been able to replicate you error, I think I have a solution: Replace your ActiveCell.FormulaR1C1 with ActiveCell.Formula. This solved it in my simple re-creation of the problem (using the immediate-window)
This works (sets a reference to cell A1 in cell A2, based on address of Cell A1:
Cells(2,2).Formula = "="&Cells(1,1).Address(0,0)
While this doesn't work (gives same issue with 'A1' in single quotes as you had): Cells(2,2).FormulaR1C1 = "="&Cells(1,1).Address(0,0)

I think there may be some confusion between named ranges and range variables in VBA. However, one problem in your formula is an inconsistent application or RC notation so you need
ActiveCell.FormulaR1C1 = _
"=IFERROR(VLOOKUP(" & dynamic_lookup_value.Address(0, 0, xlR1C1) & ",XYZ!C1:C26,MATCH(""Location Description"",XYZ!R1C1:R1C26,0),)," & LocationRef.Address(0, 0, xlR1C1) & ")"

Related

Excel VBA Conditional Formatting AND-Function

UPDATE:
I try to use conditional formatting for the following case:
If a cell in column C (starting with C9) Tabelle3.Range(Tabelle3.Cells(9, 3), Tabelle3.Cells(lastcell, 3))
is not empty Cell <>""
AND
fullfills a criteria which is stated in Tabelle4 Cell B2 Tabelle4.Range("B2")
its Interior.Color should be changed to Cellclr and its Font.Color to Fontclr
Start Old Post:
I looked through various posts about conditional formatting but I couldn't find any, that is preciously solving my problem.
I want to apply conditional formatting to a Excel workbook which will be constantly extanded. Therefore, I wrote the following code:
Sub ConForm()
Dim lastcell As Long
Dim Cellclr As Long
Dim Fontclr As Long
lastcell = Tabelle3.Range("A1048576").End(xlUp).Row
Cellclr = RGB(232, 245, 246)
Fontclr = RGB(26, 155, 167)
Set C = Tabelle3.Range(Tabelle3.Cells(9, 3), Tabelle3.Cells(lastcell, 3))
With C.FormatConditions.Add( _
Type:=xlExpression, _
Formula1:="=AND($C9<>"""";"$C9.Value <= Tabelle4.Range(""B2"").Value)")
.Interior.Color = Cellclr
.Font.Color = Fontclr
End With
End Sub
If I just use the following range and formula:
Range("C9")
Formula1:="=C9<>""""")
the code works out for Cell C9. However, as already mentioned, it should be this Formula
=AND($C9<>"""";"$C9.Value <= Tabelle4.Range(""B2"").Value
be applied for the range
Tabelle3.Range(Tabelle3.Cells(9, 3), Tabelle3.Cells(lastcell, 3))
Does someone know where I made a mistake/mistakes and how to solve this issue?
First, check the colours on your formatting to see what's a string and what's not - you have a mysterious extra " in the middle of your formula, which will prevent the code from compiling in the first place. You have also tried to put VBA code (Tabelle4.Range("B2").Value) into an Excel formula, which won't work.
If you want to fix the value of Tabelle4.Range("B2").Value when the macro is run, you can change
Formula1:="=AND($C9<>"""";"$C9.Value <= Tabelle4.Range(""B2"").Value)")
to
Formula1:="=AND($C9<>"""";$C9<=" & Tabelle4.Range("B2").Value & ")")
You need to concatenate the strings and values correctly.
Example:
MyVariable = "ccc"
result = "aaa" & "bbb" & MyVariable & "AnotherString"
'result is "aaabbbcccAnotherString"
I'm not sure what you tried but probably you meant something like
Formula1:="=AND($C9<>"""";" & Range("$C9").Value <= Tabelle4.Range("B2").Value & ")")
Or more likely something like
Formula1:="=AND($C9<>"""";$C9<=Tabelle4!B2)")
Update:
Formula1:="=AND($C9<>"""";$C9<=" & Tabelle4.Range("B2").Value & ")")

How to provide alternatives for vlookup in excel

I have created a macro to automate the building of a report. I want, in a part of a code, to provide the alternative to vlookup other values, if it cannot find them. I cannot make it run correctly. It does not crush or say anything, but the last alternative I give to it, it does not perform it. In more detail, it does not vlookup the value with "C2".
The last alternative is provided below
cell3.Formula = "=IF(ISERROR(VLOOKUP(A2&""P2"",MARM!A:G,7,0)),"""",IF(VLOOKUP(A2&""P2"",MARM!A:G,7,0)=0,"""",VLOOKUP(A2&""C2"",MARM!A:G,7,0)))"
The entire part of the code with vlookup is provided below
With Range("J2:J" & LastRow)
.Formula = "=IF(ISERROR(VLOOKUP(A2&""B2"",MARM!A:G,7,0)),"""",IF(VLOOKUP(A2&""B2"",MARM!A:G,7,0)=0,"""",VLOOKUP(A2&""B2"",MARM!A:G,7,0)))"
.Value = .Value
End With
Dim cell3 As Range
For Each cell3 In Range("J2:J" & LastRow)
If IsEmpty(cell3.Value) = True Then
cell3.Formula = "=IF(ISERROR(VLOOKUP(A2&""P2"",MARM!A:G,7,0)),"""",IF(VLOOKUP(A2&""P2"",MARM!A:G,7,0)=0,"""",VLOOKUP(A2&""C2"",MARM!A:G,7,0)))"
End If
Next cell3
This formula should work (based on your last comment):
IFERROR(VLOOKUP(A2&""B2"",MARM!A:G,7,0),IFERROR(VLOOKUP(A2&""P2"",MARM!A:G,7,0),IFERROR(VLOOKUP(A2&""C2"",MARM!A:G,7,0),""Not Found"")))
The problem I see is the one #Jeeped mentioned, that it will place the lookup against cell A2 for every row. That can be adjusted though, by changing each reference to A2 to
... (A" & cell3.Row & ""B2""...
or you can capture cell3.Row as a variable
Dim myRow as Long
myRow = cell3.Row
... (A" & myRow & ""B2""...
First thing I'm noticing is the cell3.Formula initial if-condition not having a condition:
"=If(
ISERROR(VLOOKUP(A2&""P2"",MARM!A:G,7,0)), _ 'PROBLEM; you have values, are they <> something?
"""", _ 'True-function
IF( _ 'False-function
VLOOKUP(A2&""P2"",MARM!A:G,7,0)=0, _ 'Has legit condition
"""", _ 'True-function
VLOOKUP(A2&""C2"",MARM!A:G,7,0) _ 'False-function
) _
)"
I would recommend saving a step and just not insert the formula using VBA but to have VBA do the math, similar to :
cell3.Formula= Application.IfError( Application.VLookup( ... etc.

Another >> Unable to set the FormulaArray property of the range class

I've researched as many of the "Unable to set the FormulaArray property of the range class" issues here and in other sites to troubleshoot a FormulaArray operation I'm trying to carry out in a table of data.
I've respected the 255 character limit in my formula taking into account R1C1, I've tried to insert the formula as a text string first. I've tried quite a few things.
Now I'm thinking my issue is with the fact that I'm trying to insert my formula only into blank cells because if I simplify my formula to only be =1+1 I still get the error. If I change .FormulaArray to .Formula to simply enter a standard formula I also get the same error. Is this operation not possible with blank cells?
The error occurs at the .FormulaArray = myFormula1 step.
To confirm, the formula by itself works (pasted further below) when entered into cells manually.
Sub ArrayMacro()
Dim myFormula1 As String
Dim myFormula2 As String
Dim myFormula3 As String
Dim myFormula4 As String
myFormula1 = "=IF(COUNTIFS(MLBtransactions!$D:$D,A$1,MLBtransactions!$A:$A,""<=""&$C2)>0,IF(INDEX(MLB," & "X_X_X)"
myFormula2 = "transactions!$A:$E,MATCH(1,(MLBtransactions!$D:$D=A$1)*(MLBtransactions!$A:$A<=$C2),0),," & "Y_Y_Y)"
myFormula3 = "5)=$A2,""DNP/SUS/MIN"",""with "" & INDEX(MLBtransactions!$A:$E,MATCH(A$1,MLBtransactions," & "Z_Z_Z)"
myFormula4 = "!$D:$D,0),5)),IF(COUNTIFS(MLBstats!$B:$B,A$1,MLBstats!$A:$A,$A2)=1,""DNP/SUS/MIN"",""LEAVE BLANK""))"
Sheets("Sheet1").Select
With Range("E2:AZ140").SpecialCells(4)
.FormulaArray = myFormula1
.Replace ",X_X_X)", myFormula2
.Replace ",Y_Y_Y)", myFormula3
.Replace ",Z_Z_Z)", myFormula4
End With
End Sub
Question update. Using With Range("E2:AZ140").SpecialCells(xlCellTypeBlanks) instead of With Range("E2:AZ140").SpecialCells(4) also ends with the same error.
Here is the full formula being used
=IF(COUNTIFS(MLBtransactions!$D:$D,A$1,MLBtransactions!$A:$A,"<="&$C2)>0,IF(INDEX(MLBtransactions!$A:$E,MATCH(1,(MLBtransactions!$D:$D=A$1)*(MLBtransactions!$A:$A<=$C2),0),5)=$A2,"DNP/SUS/MIN","with " & INDEX(MLBtransactions!$A:$E,MATCH(A$1,MLBtransactions!$D:$D,0),5)),IF(COUNTIFS(MLBstats!$B:$B,A$1,MLBstats!$A:$A,$A2)=1,"DNP/SUS/MIN","LEAVE BLANK"))
Testing with a simplified code (example below) led to the realization as YowE3K points out that myFormula1 needs to be valid in order for the procedure to work.
Sub ArrayMacro()
Dim myFormula1 As String
Dim myFormula2 As String
myFormula1 = "=1+1" & "+2+2"
myFormula2 = "+1+1"
Sheets("Sheet1").Select
With Range("h14:h16").SpecialCells(xlCellTypeBlanks)
MsgBox .Address
.FormulaArray = myFormula1
.Replace "+2+2)", myFormula2
End With
End Sub
When you set a formula using FormulaArray = ..., it needs to be a valid formula. (I think after each Replace the formula needs to continue being valid too, but I haven't tested that. Edit: No, if the Replace would create an invalid formula, it just doesn't process it - but it doesn't crash.)
Your problems all seem to stem from the use of invalid formulas in your myFormula1 variable.
I suggest you use the following:
Sub ArrayMacro()
Dim myFormula1 As String
Dim myFormula2 As String
Dim myFormula3 As String
Dim myFormula4 As String
myFormula1 = "=IF(COUNTIFS(MLBtransactions!$D:$D,A$1,MLBtransactions!$A:$A,""<=""&$C2)>0,IF(1232=$A2,""DNP/SUS/MIN"",""with ""&1233),1234)"
myFormula2 = "INDEX(MLBtransactions!$A:$E,MATCH(1,(MLBtransactions!$D:$D=A$1)*(MLBtransactions!$A:$A<=$C2),0),5)"
myFormula3 = "INDEX(MLBtransactions!$A:$E,MATCH(A$1,MLBtransactions!$D:$D,0),5)"
myFormula4 = "IF(COUNTIFS(MLBstats!$B:$B,A$1,MLBstats!$A:$A,$A2)=1,""DNP/SUS/MIN"",""LEAVE BLANK"")"
'Insert the formula
With Sheets("Sheet1").Range("E2:AZ140").SpecialCells(xlCellTypeBlanks)
.FormulaArray = myFormula1
.Replace "1232", myFormula2
.Replace "1233", myFormula3
.Replace "1234", myFormula4
End With
End Sub
Setting .FormulaArray to a range of cells in VBA is the same as pressing CTRL+SHIFT+ENTER while the entire range is selected. This is used when a single formula is returning an array of results and you want to display that array in the range of selected cells. This requires a contiguous range of cells to display the array. Trying to set .FormulaArray on a non-contiguous range of cells will fail, regardless of whether the formula is good or not.
I think you're trying to create an Array Formula that returns a single result after performing analysis on arrays; and you want this formula used in all blank cells.
In Excel, you would need to array-enter the formula into a single cell and then copy the formula into other cells.
Similarly, you need to do it in 2 steps in VBA. You need to first set the .FormulaArray for just one cell. This will also confirm that the formula is being constructed correctly in VBA. You can then copy that cell to all blank cells, using PasteSpecial if you only want to copy the formula.
Alternatively, you could loop through all blank cells setting the .FormulaArray individually, e.g.:
Dim raCell As Range
For Each raCell In Range("E2:AZ140")
If IsEmpty(raCell) Then raCell.FormulaArray = ...
Next
However, as you have dynamic references, you would need to construct the FormulaArray carefully to correctly determine the formula required based on the .Row and .Column of the current raCell.
Copy and paste would be safer if you have an "achor" point. Somewhere you know you can always enter the exact same formula and get the correct result when copied and pasted to all other cells.

How to add a Formula To Cell using VBA [duplicate]

This question already has answers here:
How do I put double quotes in a string in vba?
(5 answers)
Closed 1 year ago.
I am attempting to write some VBA which will add header text to 3 cells then fill a formula all the way down to the last row. I have written the below, which writes the headers no problems, but when it get's to my first .Formula it throws a
Application Defined or Object Defined error
What needs to be altered so that this macro will execute successfully? (The formulas were pulled directly from the formula in the cell, so I know they are valid formulas at least on the "front-end")
Function Gre()
Range("E2").Select
ActiveCell.FormulaR1C1 = "Under"
Range("F2").Select
ActiveCell.FormulaR1C1 = "Over"
Range("G2").Select
ActiveCell.FormulaR1C1 = "Result"
With Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row)
.Formula = "=IF(C2<B2,B2-C2,"")"
End With
With Range("F2:F" & Cells(Rows.Count, "C").End(xlUp).Row)
.Formula = "=IF(C2>B2,C2-B2,0)"
End With
With Range("G2:G" & Cells(Rows.Count, "C").End(xlUp).Row)
.Formula = "=IF(F2>0,'Issue',"")"
End With
End Function
The problem is likely that you are escaping the quotes with the formula.
What you need is:
.Formula = "=IF(C2>B2,B2-C2,"""")"
for the first one, for example. The other quotes need to be doubled as well.
As a side-note, it would also be best to specify the sheet you are working on with something like:
Dim ws as worksheet
Set ws = Sheets("mySheet")
ws.Range("E2").FormulaR1C1 = "Under"
etc.
If you don't do this, you can sometimes have errors happen while running the code.
As suggested by OpiesDad, to minimize ambiguity, avoid ActiveCell and the like.
Using Select will also slow down performance a lot compared to assigning to cells directly.
I'm pretty sure you need to escape quotes in Excel formulas inside of VBA by doubling the quotes, so a normal empty string becomes """". You also have Issue in single quotes in a formula, which I'm pretty sure will error in Excel; that should be in escaped double quotes as well.
I'm having a hard time figuring out what Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row) actually does, but it sounds like you want to select E2 to the last used row of the sheet. Avoid Rows.Count or just generally referring to the rows of a sheet, as that will go to row 10^31. Use Worksheet.UsedRange to get the range from the first row and column with content to the last row and column with content. This also includes empty strings and can be a bit tricky sometimes, but is usually better than dealing with thousands of extra rows.
Also,
You don't need to use With if your only enclosing one statement, although it won't cause any problems.
I would not mix use of Range.Formula and Range.FormulaR1C1 unless you have a reason to.
Function Gre()
Dim ws as Worksheet
Set ws = ActiveSheet
Dim used as Range
Set used = ws.UsedRange
Dim lastRow as Integer
lastRow = used.Row + used.Rows.Count - 1
ws.Range("E2").Formula = "Under"
ws.Range("F2").Formula = "Over"
ws.Range("G2").Formula = "Result"
ws.Range("E2:E" & lastRow).Formula = "IF(C2<B2, C2-B2, """")"
ws.Range("F2:F" & lastRow).Formula = "IF(C2<B2, C2-B2, 0)"
ws.Range("G2:G" & lastRow).Formula = "IF(F2>0, ""Issue"", """")"
End Function
The first issue is the selecting of cells. This requires the macro to select the cell, then determine the cell address. If you need to actually select a cell, use Application.ScreenUpdating = False. Then the macro doesn't have to show the cursor selection of a cell. Dropping the select and incorporating the range into the formula assignment code line like below will gain some speed/efficiency.
Range("E2").FormulaR1C1 = "Under"
Range("E2:E" & Cells(Rows.Count, "C").End(xlUp).Row) is the code version of selecting the last cell in a blank column (row 1048576), then using the keystroke of ctrl and the up key to determine the lowest/last used cell. This gets you a row count of 1 every time since the column is blank. Since you're looking for the last row. It may be faster to count down from the top. My favorite method for this is a loop. Increment a variable within a loop, while looking for the last row. Then, the variable can be used instead of your bottom up strategy.
t = 0
Do Until Range("C2").Offset(t, 0).Value = ""
t = t + 1
Loop
With Range("E2:E" & t)
.Formula = "=IF(C2<B2,B2-C2,"""")"
End With`
Just like TSQL, quote characters need their own quote characters.
.Formula = "=IF(C2<B2,B2-C2,"""")"
The Range Fillup VBA function can be utilized in this case to fill all cells from the bottom with a common formula, accounting for Excel Formula Reference Relativity. The code below starts with the range that we got from the loop counter. Next, we set a variable equal to the total rows in Excel minus the row corresponding to the counter row. Then, we resize the original region by the necessary rows and use the FillDown function to copy the first formula down.
Here's the resulting code. This will fill the range starting from the last row in Excel.
Sub Gre()
Range("E2").FormulaR1C1 = "Under"
Range("F2").FormulaR1C1 = "Over"
Range("G2").FormulaR1C1 = "Result"
Do While Range("e2").Offset(t, 0).Value <> ""
t = t + 1
Loop
Range("E2").Offset(t, 0).Formula = "=IF(C2<B2,B2-C2,"""")"
r1 = Range("e2").EntireColumn.Rows.Count
r2 = Range("E2").Offset(t, 0).Row
Range("E2").Offset(t, 0).Resize(r1 - r2, 1).FillDown
Range("F2").Offset(t, 0).Formula = "=IF(C2>B2,C2-B2,0)"
Range("F2").Offset(t, 0).Resize(r1 - r2, 1).FillDown
Range("G2").Offset(t, 0).Formula = "=IF(F2>0,""Issue"","""")"
Range("G2").Offset(t, 0).Resize(r1 - r2, 1).FillDown
End Sub
As well as using double quotes you may need to use 0 in the first two formula otherwise they may evaluate to empty strings. This may give unexpected results for the last formula i.e. incorrectly return "Issue".
If you do not have blank columns between your data and the 3 new columns you can use CurrentRegion to determine the number of rows:
Range("E2:E" & Cells.CurrentRegion.Rows.Count).Formula = "=if(C2'<'B2,B2-C2,0)"
Range("F2:F" & Cells.CurrentRegion.Rows.Count).Formula = "=if(C2>B2,C2-B2,0)"
Range("G2:G" & Cells.CurrentRegion.Rows.Count).Formula = if(F2>0,""Issue"","""")"
Please try the following sample hope it will help you to wright formula in VBA
Sub NewEntry()
Dim last_row As Integer
Dim sht1 As Worksheet
Dim StockName As String
Set sht1 = Worksheets("FNO MW")
last_row = Cells.Find(What:="*", After:=Range("A1"), SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
'MsgBox last_row
StockName = sht1.Cells(last_row, 1).Value
sht1.Cells(last_row, 1).Formula = "=RTD(""pi.rtdserver"", ,"" " & StockName & " "", ""TradingSymbol"")"
End Sub

Using variable columns in VBA Excel

While working on a macro in VBA I can't figure out the following issue:
This is a part of the code
ActiveCell.FormulaR1C1 = _
"=SUM(CreateResultsDebit!C[34])-DebitAnalysis!RC[-1]"
Range("B3").Select
ActiveCell.FormulaR1C1 = _
"=SUM(CreateResultsDebit!C[35])-DebitAnalysis!RC[-1]"
Range("B4").Select
Now, I have hardcoded the column reference C[34] and C[35]. Is there a way to use, for instance, an iterator as a variable between the brackets? If I try this myself it doesn't yield any result.
Thank you. Peter.
ok... you need to combine a variable and a string... it is like:
ActiveCell.FormulaR1C1 = "=SUM(CreateResultsDebit!C[" & i & "])-DebitAnalysis!RC[-1]"
to be a bit more specific: (in your code, you set the formula first and then select another cell... I assume that you want the C[34] in B2 and C[35] in B3......)
Dim i As Long
For i = 2 to 3
Range("B" & i).FormulaR1C1 = "=SUM(CreateResultsDebit!C[" & 32 + i & "])-DebitAnalysis!RC[-1]"
Next
In the first cycle (i = 2) it will go for cell B2 and use C[34] (32 + i). In the second cycle, those two values are 1 higher (if you go for i from 2 to 30, then it will go for cell B30 in last cycle and use C[62] in your formula)
EDIT
Another easy way is the use of R1C1 to set multiple cells. For this you would need to change your formula a bit and the code would look like this:
Range("B2:B9").FormulaR1C1 = "=SUM(INDEX(CreateResultsDebit!C[33]:C[51],,ROW()))-CreateResultsDebit!RC[-1]"
This would do the same without any loops ;)
Maybe this will be of help to you, if I understand you correctly. It will sum the columns from left to right and place them in one row consecutively.
Dim i as Integer
Dim iLastColumn as Long
Dim startRange as Range
Set startRange = Range("B3")
iLastColumn = Cells(1,Columns.Count).End(xlToLeft).Column
For i = 1 To iLastColumn
startRange.Offset(1,i).FormulaR1C1 = "=SUM(CreateResultsDebit!C[" & i & "])-DebitAnalysis!RC[-1]"
Next i