EXCEL VBA -Getting #NAME? - excel

I am trying to get user' id fro another excel file. On Main excel file there is only one column with username. I wrote below but it return #Name? instead of id.
Dim i As Integer
Dim LastRow As Integer
Dim LastColumn As Integer
Dim Client_id As Variant
Dim user_id As String
Dim Contract_id As Variant
Sub TestAdd()
LastRow = Worksheets("Sheet1").Cells(Rows.Count, 1).End(xlUp).Row
'Next
For i = 2 To LastRow
user_id = "=VLOOKUP(Range(Cells(i, 3)),[RefUser.xlsx]Sheet1!$A:$B,2,FALSE)"
Range(Cells(i, 2), Cells(LastRow, 2)).Value = user_id
Next
End Sub

This is not valid as a formula:
user_id = "=VLOOKUP(Range(Cells(i, 3)),[RefUser.xlsx]Sheet1!$A:$B,2,FALSE)"
Something like this would work:
user_id = "=VLOOKUP(C" & i & ",[RefUser.xlsx]Sheet1!$A:$B,2,FALSE)"
Then set that using .Formula and not .Value
You could set all these in one shot though. Try this:
Dim i As Integer
Dim LastRow As Integer
Sub TestAdd()
With Worksheets("Sheet1")
.Range("B2", .Cells(.Rows.Count, 1).End(xlUp).Offset(0,1)).Formula = _
"=VLOOKUP(C2,[RefUser.xlsx]Sheet1!$A:$B,2,FALSE)"
End With
End Sub

To use VLookup you need to provide some values to the function. The signature looks like VLOOKUP(lookup_value,table_array,col_index_num,range_lookup).
lookup_value is the value you are expecting to find.
table_array is the range of cells that has the lookup_value in the leftmost column.
col_index_num is the column number that contains the information you want to return when a match is found.
range_lookup is the match that you're looking for. 0 can be used as a shorthand for False.
Assuming your lookup_value is in cell C2 which corresponds to Cells(i,3) as i starts at 2, and your table_array is in Range("M1:N10"). You can use the formula =VLOOKUP(C2,$M$1:$N$10,2,0). By omitting the $ and leaving C2 as a relative reference you can apply it to the range you want the values to be calculated. This is much more efficient then looping through and applying the the same formula to each cell individually.
Sub AddLookupFormula()
Dim lastRow As Long
lastRow = Worksheets("Sheet1").Cells(Rows.Count, "A").End(xlUp).Row
Dim formulaRange As Range
Set formulaRange = ActiveSheet.Range(ActiveSheet.Cells(2, "B"), ActiveSheet.Cells(lastRow, "B"))
Dim firstLookupCell As String
firstLookupCell = formulaRange.Cells(1, 1).Offset(ColumnOffset:=1).Address(False, False)
Dim completedFormula As String
completedFormula = "=VLOOKUP(" & firstLookupCell & ",$M$1:$N$10,2,0)"
formulaRange.Formula = completedFormula
End Sub

Related

Trying to create a Vlookup formula via VBA Code

I have created a code to use Vlookup formula through VBA but i am stuck that how to fix it. It is very simple to lookup a range but i do not know what to do. Any help will be appreciated.
Sub Example()
Dim value As Range
Dim table As Range
Dim col_index As Range
Dim FinalResult As Variant
lRow = Sheet2.Cells(Rows.Count, 2).End(xlUp).Row
Set value = Sheet2.Range("A2")
Set table = Sheet1.Range("A2:D15")
Set col_index = Sheet2.Range("D2:D" & lRow)
FinalResult = Application.WorksheetFunction.VLookup(value, table, col_index, False)
End Sub
Here is the formula which is working perfectly
=VLOOKUP(Sheet2!A2,Sheet1!$A$2:$D$15,4,FALSE)
Edited
Sub Example()
Dim value As Range
Dim table As Range
Dim col_index As Range
Dim FinalResult As Variant
lRow = Sheet2.Cells(Rows.Count, 2).End(xlUp).Row
Set value = Sheet2.Range("A2")
Set table = Sheet1.Range("A2:D15")
FinalResult = Application.WorksheetFunction.VLookup(value, table, 4, False)
End Sub
Edited but still not working
Sub Example()
Dim rng As Range
Dim table As Range
Dim col_index As Range
Dim FinalResult As Variant
lRow = Sheet2.Cells(Rows.Count, 2).End(xlUp).Row
Set rng = Sheet2.Range("A2")
Set table = Sheet1.Range("A2:D15")
FinalResult = Application.WorksheetFunction.VLookup(rng, table, 4, False)
rng.value = FinalResult.value
End Sub
Assume you have two tables.
Your data table in "Sheet1"
Your output table where you want the result ("Sheet2").
To get the countries from the data sheet ("Sheet1") you would use the formula (I use ";" as separator as I use nordic version of excel):
=VLOOKUP(Sheet2!A2,Sheet1!$A$2:$D$15,4,FALSE)
So in VBA this would look like this:
Sub Example()
Dim tbl As Range
Dim col_index As Range
Dim Lookup_val As Long 'if you use a numerical number as in my example
'Dim Lookup_val As String 'if you use a text or words + numbers as lookup criteria
Dim FinalResult As Variant 'I would consider to use string or long... more specific declaration if you know the datatype to be retrieved.
lRow = Sheet2.Cells(Rows.Count, "B").End(xlUp).Row 'End row in the column we should WRTIE the answer from the vlookup function
EndRow = Sheet2.Cells(Rows.Count, "A").End(xlUp).Row 'End row of the range we would like to MATCH values
Set tbl = Sheet1.Range("A2:D15") 'Data table range
For i = 2 To EndRow 'What range we should loop through. We want to loop from row 2 until the last row in Column A for Sheet2
Lookup_val = Sheet2.Cells(i, "A").value 'Value that should be use as lookup value in the "vlookup function"
FinalResult = Application.WorksheetFunction.VLookup(Lookup_val, tbl, 4, False) 'Perform the vlookup function
Sheet2.Cells(i, "B").value = FinalResult 'write the result of the vlookup finding
Next i 'check next row (go to next lookup value)
End Sub
If the vlookup function can't match a value in the table it will give you an error. I usually fix it dirty by wrapping the function in a error handling line and you need to clear the FinalResult value for each iteration, i.e.:
For i = 2 To EndRow
FinalResult = "" 'To clear previous value from loop iteration
Lookup_val = Sheet2.Cells(i, "A").value
On Error Resume Next 'ignore error if no value found
FinalResult = Application.WorksheetFunction.VLookup(Lookup_val, tbl, 4, False)
On Error GoTo 0 'continue loop anyway
Sheet2.Cells(i, "B").value = FinalResult
Next i

how to get last row that has velue Excel VBA within a range

I am new to VBA Macro. i just want to know how to get the last row that has value within a range
Set MyRange = Worksheets(strSheet).Range(strColumn & "1")
GetLastRow = Cells(Rows.Count, MyRange.Column).End(xlUp).Row
this code could find the last row for the whole sheet.. i just want it to find the last non null value cells
(
like in this case in the picture.. for the ("A8") range, the last row result should be ("A9:B9")
"A9:B9" cannot be last row... It is a range.
If you need such a range, but based on the last empty row, starting from a specific cell, you can use the next approach:
Sub testLastRowRange()
Dim sh As Worksheet, myRange As Range, lastRow As Long, strColumn As String
Dim lastCol As Long, endingRowRng As Range, strSheet As String
strSheet = ActiveSheet.Name 'please, use here your real sheet name
Set sh = Worksheets(strSheet)
strColumn = "A"
Set myRange = sh.Range(strColumn & 8)
lastRow = myRange.End(xlDown).row
lastCol = myRange.End(xlToRight).Column
Set endingRowRng = sh.Range(sh.Cells(lastRow, myRange.Column), sh.Cells(lastRow, lastCol))
Debug.Print endingRowRng.address
End Sub
For your specific example you could use CurrentRegion property.
This is based on the ActiveCell which is not generally advisable.
Sub x()
Dim r As Range
Set r = ActiveCell.CurrentRegion
MsgBox r.Address
End Sub

Vlookup from another sheet and paste the result in another sheet

I need a help with a vlookup using vba as I was not able to find the solution on the web
The situation is I have three sheets
Sheet 1: Lookup value in cell B3 with a name
Sheet 1
Sheet 2: Lookup table with column name and surname
Sheet 2
Sheet 3: Result of the lookup value in cell B3 with surname
Sheet 3
You can refer to the images for better understanding
So the value in sheet 1 is my lookup value and the surname has to be printed in the sheet 3 and the table array is in sheet 2
The code which I tried is
Sub nameloopkup()
Dim name As String
Dim result As String
Dim myrange As Range
name = Worksheets("Sheet1").Range("B3").Value
myrange = Worksheets("Sheet2").Range("A:B").Value
result = Application.WorksheetFunction.VLookup(name, myrange, 2, False)
' the query does not run and i don't know how can i print the result in sheet 3
End sub
This might be quiet simple for many around here. But considering my amature level to VBA, I need some guidance regarding the same.
Any kind of help or suggestion is appreciated.
Actuall all you need to do is:
Sub nameloopkup()
Dim Name As String
Dim Result As String
Dim SearchIn As Variant 'variant to use it as array
Name = Worksheets("Sheet1").Range("B3").Value
SearchIn = Worksheets("Sheet2").Range("A:B").Value 'read data into array
On Error Resume Next 'next line errors if nothing was found
Result = Application.WorksheetFunction.VLookup(Name, SearchIn, 2, False)
On Error Goto 0
If Result <> vbNullString Then
Worksheets("Sheet3").Range("B3").Value = Result
Else
MsgBox "Nothing found"
End If
End Sub
Alternatively just write a formula:
Sub NameLookUpFormula()
Worksheets("Sheet3").Range("B3").Formula = "=VLOOKUP(Sheet1!B3,Sheet2!A:B,2,FALSE)"
End Sub
Here is what you could 2... There are 2 options, if you only need 1 entry of data, or if you need a whole array of data and picking each time what you need from it:
Option Explicit
Sub nameloopkup()
Dim C As Range, LastRow As Long, EmptyRow As Long, i As Long, arrData
Dim DictData As New Scripting.Dictionary 'You need to check Microsoft Scripting Runtime from references for this
Dim wsNames As Worksheet, wsTable As Worksheet, wsSurnames As Worksheet
'First thing, reference all your sheets
With ThisWorkbook
Set wsNames = .Sheets("Sheet1") 'change this as needed
Set wsTable = .Sheets("Sheet2")
Set wsSurnames = .Sheets("Sheet3")
End With
'Keep all the data in one dictionary:
With wsTable
LastRow = .Cells(.Rows.Count, 1).End(xlUp).Row 'last row on Sheet2
i = .Cells(1, .Columns.Count).End(xlToLeft).Column 'last column on Sheet2
arrData = .Range(.Cells(1, 1), .Cells(LastRow, i)).Value 'keep the data on the array
'This will throw an error if there are duplicates
For i = 2 To UBound(arrData)
DictData.Add arrData(i, 1), i 'keep tracking of every name's position ' also change for arrData(i, 2) if you only need the surname
Next i
End With
With wsNames
LastRow = .Cells(.Rows.Count, 2).End(xlUp).Row 'last row on Sheet1
For Each C In .Range("B3:B" & LastRow)
EmptyRow = wsSurnames.Cells(wsSurnames.Rows.Count, 1).End(xlUp).Row
wsSurnames.Cells(EmptyRow, 2) = DictData(C.Value) 'if you used arrData(i, 2) instead i
wsSurnames.Cells(EmptyRow, 2) = arrData(DictData(C.Value), 2) 'If you used i
Next C
End With
End Sub
myrange = Worksheets("Sheet2").Range("A:B").Value
result = Application.WorksheetFunction.VLookup(name, myrange, 2, False)
Here is your error. The second argument of Vlookup is a Range, not a String. As a range is an object, you also need to Set it:
Set myrange = Worksheets("Sheet2").Range("A:B")
result = Application.WorksheetFunction.VLookup(name, myrange, 2, False)

Need some help using setting variables to determine which cells I want to select in my range

The amount of cells in my data table changes every week so I'm using a count function to determine the number of cells with data then using that count as a variable to put into my range(cells(x,x),cells(x,x) function to select. But I'm having an issue with taking the count and converting it to a variable to use. This is a basic macro I'm putting together for something else i'm doing.
Sub format_table()
Dim x As Long
Dim y As Long
''count the number of rows in rawdata table
Dim LastRow As Integer
With ActiveSheet
LastRow = .Cells(.Rows.Count, "A").End(xlUp).Row
End With
x = LasRow
''count the number of columns in rawdata table
Dim LastCol As Integer
With ActiveSheet
LastCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
End With
y = LastCol
'''use the counted cells to determine a range to select
ActiveSheet.Range(Cells(1, 1), Cells(x, y)).Select
End Sub
I think you are having trouble trying to get the column number as the correct letter, right? Try something like this:
Sub Test()
Dim wb As Workbook
Set wb = ThisWorkbook
Dim ws As Worksheet
Set ws = wb.Sheets("Sheet1") '(replace with whatever sheet name is)
Dim lastRow as Integer, lastCol as Integer, lastColLet as Integer
'get the number value of the last row and column
lastRow = ws.Cells.Find("*", SearchOrder:=xlByRows, SearchDirection:=xlPrevious).Row
lastCol = ws.Cells.Find("*", SearchOrder:=xlByColumns, SearchDirection:=xlPrevious).Column
'uncomment the debug.print statements to see what it's getting for last row/column
'Debug.Print lastRow
'Debug.Print lastCol
'get the letter that the column number corresponds to
lastColLet = Letter(lastCol)
'Debug.Print lastColLet
ws.Range("A1:" & lastColLet & lastRow).Select
End Sub
Function Letter(ByVal lngCol As Long) As String
Dim vArr
vArr = Split(Cells(1, lngCol).Address(True, False), "$")
Letter = vArr(0)
End Function
It uses the function found here: Function to convert column number to letter? in order to convert the column # to a letter, then you can concat the letter and last row to select the way you wanted.
I guess your real issue is to decide what cells you actually need to select
your approach assumes that the left-upmost data cell is always in cell(1,1) and the down-right one is in the intersection of:
last non empty row in column 1, last non empty column in row 1
should that be the case, then you can go on with your code provided you change x = LasRow to x = LastRow...
should not that be the case then you could assume that the range is the one delimited by:
first non empty row in column 1, first non empty column in row 1
last non empty row in column 1, last non empty column in row 1
then you could use this code:
Function GetData() As Range
Dim firstRow As Long, firstColumn As Long
Dim LastRow As Integer, lastColumn As Long
With ActiveSheet
firstRow = .UsedRange.Rows(1).Row '<--| get first used row index
firstColumn = .UsedRange.Columns(1).Column '<--| get first used column index
LastRow = .Cells(.Rows.Count, firstColumn).End(xlUp).Row '<--| get the first used column last non empty cell row index
lastColumn = .Cells(firstRow, .Columns.Count).End(xlToLeft).Column '<--| get the first used rows last non empty cell column index
'return the range
Set GetData = .Range(Cells(firstRow, firstColumn), Cells(LastRow, lastColumn))
End With
End Function
and exploit it in your main code as follows:
Sub format_table()
With GetData '<-- use With-End With block to reference wanted object (Range) and avoid Select/Selection/Activate/ActiveXXX
'format the referenced range
.Font.Name=..
.Interior.Color=..
End With
End Sub
but the GetData() function may still be not the one you need, should data be "jagged" in columns and or/rows with first row/column not hosting the last column/cell
so maybe you simply need:
Sub format_table()
With ActiveSheet.UsedRange
'format the referenced range
' .Font.Name=..
' .Interior.Color=..
End With
End Sub

Inserting VBA formula into a defined Range

I'm looping through a table (Sheet4) in a worksheet and inserting an empty column between each original column. In the new, empty columns, I want to insert a VLookup function.
I has successfully inserted the columns and I have successfully held the proper range (proper number of rows too) in a variable called FormulaRange.
I'm having problems with the VLookup. I don't know if it's the way I'm storing my variables or if I need to have a paste function after my Vlookup. Can someone take a look and give me a hand?
*note - I stored FormulaRange as String becuase As Range wouldn't let me pass my code into the variable. As a result I can't use the FormulaRange.Formula Method.
If I were to manually input the VLookup I would write it as =VLOOKUP(B1,RosettaStone_Employees!$A$1:$B$5,2,FALSE) and then copy down the range.
Sub InsertColumnsAndFormulasUntilEndOfProductivityTable()
Dim ActivityRange As Range
Dim UserName As String
Dim FormulaRange As String
Dim i As Integer
Dim x As Long
Dim y As Long
Dim Startrow As String
Dim Lastrow As String
Sheet6.Activate
Set ActivityRange = Range("A1", Range("B1").End(xlDown))
Sheet4.Activate
Range("A1").Select
y = Sheet4.Cells(Rows.Count, 1).End(xlUp).Row - 1
x = (Sheet4.Cells(1, Columns.Count).End(xlToLeft).Column) * 2
For i = 1 + 2 To x Step 2
Columns(i).EntireColumn.Insert
Startrow = 2
Lastrow = y
UserName = Cells(1, i - 1)
FormulaRange = Cells(Startrow, i).Address & ":" & Cells(Lastrow + 1, i).Address
FormulaRange = "=VLookup(UserName, ActivityRange, 2, False)"
Next
End Sub
Thanks
Jonathan
I changed your code a little to get rid of the sheet activates. Also I changed a few things to ranges and included with blocks.
This is untested:
Sub InsertColumnsAndFormulasUntilEndOfProductivityTable()
Dim ActivityRange As Range
Dim UserName As String
Dim FormulaRange As Range
Dim i As Long
Dim x As Long
Dim y As Long
Dim Startrow As Long
Dim Lastrow As Long
With Sheet6
Set ActivityRange = .Range("A1", .Range("B1").End(xlDown))
End With
With Sheet4
y = .Cells(.Rows.Count, 1).End(xlUp).Row - 1
x = (.Cells(1, .Columns.Count).End(xlToLeft).Column) * 2
For i = 1 + 2 To x Step 2
.Columns(i).EntireColumn.Insert
Startrow = 2
Lastrow = y
UserName = .Cells(1, i - 1)
Set FormulaRange = .Range(.Cells(Startrow, i), .Cells(Lastrow + 1, i))
FormulaRange.FormulaR1C1 = "=VLookup(R1C[-1],'" & ActivityRange.Parent.Name & "'!" & ActivityRange.Address(1, 1, xlR1C1) & ", 2, False)"
'If you do not want dynamic formulas and just want the value
'then comment out the above and use the below.
'FormulaRange.Value = Application.Vlookup(UserName,ActivityRange,2,False)
Next
End With
End Sub
The R1C1 is a relative nomenclature. When it fills the formulas into the columns it will return the cell relative to the one into which the formula will be filled.
For example, above I use R1C[-1]. This says get the first row of the column directly to the left. So if the formula was being entered into B2 it would return A$1.
The [] denotes the relative address. Without the [] eg R1C1 it would indicate an absolute address and would return $A$1. So R1C1:R4C2 would return a range of $A$1:$B$4.

Resources