What does & do in VBA - vba

I am new to VBA, I got a question on &, What does the two & do in this code below, can we delete the last one?
Range("H2").Formula = "=COUNTIF(H4:H" & WKB2.Range("F" &
Rows.Count).End(xlUp).Row & ",""AMB"")"
Some other code has only one & but still working. for example:
ActiveSheet.Range("F5:F" & lastrow1 - 1).Formula = "=IF(C5>0,""CC"",""AMB"")"
what is the difference here.
Thanks in advance.

& is one of the two possible operators for string concatenations in VBA.
(+ is also possible, but IMO & is better)
E.g. "A" & "B" will result in "AB".
Or, to use one of your examples - let's say lastrow1 = 5, so lastrow1 - 1 = 4, so this:
ActiveSheet.Range("F5:F" & lastrow1 - 1)
...will become:
ActiveSheet.Range("F5:F4")

For Excel formula and VBA - Exactly where and whether 1 or 2 '&'s depends on your use case.
To concatenate with rest of formula you need &variable& (so 2 &s).
If there is nothing to concatenate at the end, but there is something at the beginning then use &variable.
If there is nothing to concatenate at the beginning but there is something to concatenate at end then use variable&.
If there is nothing to concatenate at beginning or at end, then just use variable.
Hope this makes sense.

Related

VBA - Copy / Paste to multiple columns with variable row start (array)

I'd like to shorten my code by putting multiple columns to one command.
I'm copying formulas from one row but specified columns and want to paste to another sheet in the same wksht. Just the row number is a variable. Maybe do this by an array?
As an example I'm pasting below not working code with only 3 columns.
Sub Copy()
Dim LastrowQ As Long
Dim LastrowR As Long
LastrowQ = Cells(Rows.Count, "B").End(xlUp).Row
LastrowR = LastrowQ + 1
Workbooks(Rep1).Worksheets("Formula").Range("A2, C2:F2, N2, V2:AD2").Copy
*Workbooks(Rep1).Worksheets("Report").Range("A" & LastrowR, "C" & LastrowR & ":F" & LastrowR, "N" & LastrowR, "V" & LastrowR & ":AD" & LastrowR).PasteSpecial Paste:=xlPasteFormulas*
End Sub
Could you please help to modify the code in paste part as it doesn't work right now? This would allow to make original code much shorter and hopefully faster.
What if I'd like to propagate function in second sheet from variable row till the specified row at the same time? ("A" & LastrowR & ":A" & LastrowS,...)
Thanks in advance

VBA script to insert INDEX/MATCH formula with dynamic reference/arrays

I'm looking to simply insert an INDEX/MATCH formula in the column next to an existing selection (this will be part of a larger Sub). The reference/look-up array in the formula needs to be dynamic.
So far I've managed to successfully insert the formula. However, the reference/lookup-arrays have been manually input by me as I know the current Range (which is likely to change):
Selection.Offset(0, 1) = "=INDEX($J$3:$J$31,MATCH(INDIRECT(""RC[-2]"",0),$H$3:$H$31,0))"
How can I amend the $J$3:$J$31 and the $H$3:$H$31 to update dynamically? I've had success separately with something like 'Range("J3", Range("J3").End(xlDown))', but I can't seem to work it into the code above.
You can integrate variables into the formula, it becomes a bit tricky, and I imagine there are better ways to accomplish this, but it's the method I use when I need dynamic ranges in formulas in VBA. I'll provide an example below that should help:
I'm assuming the J3 and H3 will remain the same, but the end of the range is what you expect to change. If this is not the case, let me know.
You're essentially replacing the "31" in your range reference with " & [variable] & " (quotes included).
EDIT: I use Sheet1 as an example for the row count; so just update that to whatever the applicable sheet & range would be.
Dim rCount As Long
rCount = Sheet1.Range("A" & Rows.Count).End(xlUp).Row
Selection.Offset(0, 1) = "=INDEX($J$3:$J$" & rCount & ",MATCH(INDIRECT(""RC[-2]"",0),$H$3:$H$" & rCount & ",0))"

Writing a formula as Syntax in VBA

I want to run a rank formula across a range of cells. I am scratching my head as to why it's not working. Lastrow is just the formula that counts the number of rows.
Range("B1:B" & Lastrow).Formula = "=RANK(A1,Offset(" & Chr$(36) & "A1" & Chr$(36) & "," & Lastrow & ",0))"
I feel like it's something wrong with Chr$(36), but when I try Chr(36) it doesn't work either. (removing these chr(36)'s and just having Offset(A1... etc) works fine).
Thanks in Advance!
It's hard to see what you want to do. The line of VBA code below will, at least, work.
Range("B1:B" & LastRow).Formula = "=RANK(ROW(),$A1:$A$" & LastRow & ",0)"
Your issue seems to be with the RANK() function. It has 3 arguments, (1) the rank, (2) the range in which to find the rank and (3) Ascending/Descending. In your formula the first argument is missing and your "Offset(" & Chr$(36) & "A1" & Chr$(36) & "," & LastRow" doesn't describe a range, read as Offset($A1$,300 with closing bracket missing.
My above formula suggests the Row number as rank, meaning 1 for Row 1, 2 for Row 2 etc. but descending, as indicated by the 3rd argument (taken from your formula) and, as second argument a range in column A between A1 and the LastRow. It probably isn't what you wanted but I hope you will be able to tweak it.

Application.VLookup function always returns #N/A

I am trying to use the Application.VLookup function in Visual Basic to find a value in a different workbook. However, whenever I use it, it always returns #N/A.
This is the layout of my function. LastRow() just returns the row number of the last row. SHORTAGE_SBT is a variable containing the source workbook name. SBT_Last is the last row of SHORTAGE_SBT. The ID that I'm searching with in in the B column, hence why I use "B" & ind to refer to it.
For ind = 4 To LastRow()
Range("H" & ind).Select
ActiveCell.Value = Application.VLookup("B" & ind, Workbooks(SHORTAGE_SBT).Sheets(1).Range("A14:DZ" & SBT_Last), Range("DZ1").Column, False)
Next
I have tried recording a macro for VLookup to see if it would help me understand the problem. The macro gave me this function, which worked but could not be used because it contains the hardcoded file name instead of using the variable.
Range("H" & ind).FormulaR1C1 = "=VLOOKUP(RC[-6],'[filename.xls]Sheet1'!R14C1:R2382C130, COLUMN(R[-3]C[122]), FALSE)"
I cannot see any significant difference between the way the macro lays out the arguments of the function as opposed to mine, other than using more direct references. I have tried using direct numbers in my code but doing so hasn't helped either.
Application.VLookup("B" & ind, Workbooks(SHORTAGE_SBT).Sheets(1).Range("A14:DZ" & SBT_Last), Range("DZ1").Column, False)
"B" & ind will be searched for "literally"; it will not be transformed into a range address because it is interpreted here by VBA, not by Excel. Try:
Application.VLookup(Range("B" & ind), Workbooks(SHORTAGE_SBT).Sheets(1).Range("A14:DZ" & SBT_Last), Range("DZ1").Column, False)
' ^^^^^^^^^^^^^^^^
Combine the two approaches:
Range("H" & ind).FormulaR1C1 = _
& "=VLOOKUP(RC[-6],'[" & Workbooks(SHORTAGE_SBT) _
& "]Sheet1'!R14C1:R2382C130, COLUMN(R[-3]C[122]), FALSE)"

Specifying cells and sheets in formula using VBA

I need my macro to input the following formula:
Worksheets("U_NEDC_COLD_online_0").Cells(3, A).formula = "=IF(" & Worksheets (U_NEDC_COLD_online_0).Cells(3, AA).Value & "=" & Worksheets(U_NEDC_COLD_online).Cells(3, AA).Value & ";" & Worksheets(U_NEDC_COLD_online).Cells(3, A).Value & ";" & Worksheets(U_NEDC_COLD_online_0).Cells(3, A).Value & ")"
I've also tried the same formula with the ".Address" property and it doesn't work. What am I doing wrong?
The final formula should look like this:
=IF($AA3 = U_NEDC_COLD_online!$AA3; U_NEDC_COLD_online!A3; U_NEDC_COLD_online_0!A3)
PS: Worksheets("U_NEDC_COLD_online_0") is not the same as Worksheets(U_NEDC_COLD_online_0). (its not a typo)
Thanks.
Use commas instead of semicolons to separate the arguments of the IF statement.
Your formula appears to have a circular relationship; the formula is going into cell A3 and references cell A3... I'll leave that to you to work out.
Always use Option Explicit. Once you put that line at the top of your module, you'll get the error: Variable not defined for the variables: A, AA, and possibly U_NEDC_COLD_online and U_NEDC_COLD_online_0 that you probably intended to use as string literals. (see next bullet for a workaround)
If U_NEDC_COLD_online_0 is truly a variable/constant name and is not equal to the string literal that you use elsewhere (e.g. U_NEDC_COLD_online_0), you should really change the variable name to something else!
If the only reason you are dynamically building the formula is to accommodate variable row indexes, use this where the 3 can be replaced by a variable:
Worksheets("U_NEDC_COLD_online_0").Cells(3, 1).Formula = "=IF($AA" & 3 & "=" & "U_NEDC_COLD_online!AA" & 3 & ", U_NEDC_COLD_online!A" & 3 & ", A" & 3 & ")"
If you don't even need variable row indexes, just use this:
Worksheets("U_NEDC_COLD_online_0").Range(A3).Formula = "=IF($AA3=U_NEDC_COLD_online!AA3, U_NEDC_COLD_online!A3, A3)"