Vlookup in vba to find values between two worksheets - excel

I'm trying to grab the values from a different worksheet and match them to the their sister data in my main sheet in column A but I'm having issues with getting the right results, I was thinking of going the Vlookup route but I can't quite get it to work properly. I found a funky way of getting it done but I'm trying to save just the values and not the formula itself.
This is what I tried at first
Sub matchID()
'Dim wb As Workbook
'Set wb = ActiveWorkbook
'
'With wb.Sheets("Data")
' .Range("E2:E" & .Range("A" & .Rows.Count).End(xlUp).Row).Formula = "=VLOOKUP(A2,ID!A:B,2,FALSE)"
'End With
'the above works but need to save values and not formula
It kinda works but I need that values and not the formula, my plan is to find the data I need and then save a copy of the file as a csv
I tried using a different method but I'm running into runtime error '1004'
I'm still learning VBA so I feel like I'm spinning my wheels right now.
Can someone show me what I'm doing wrong?
Sub matchID()
'this is what I'm trying to get to work but unsure if I will still end up with formula and not just values
Dim result As String
Dim sheet As Worksheet
Dim lrow As Integer
Dim i As Integer
Set sheet = ActiveWorkbook.Sheets("Data")
lrow = sheet.UsedRange.Rows(sheet.UsedRange.Rows.Count).Row
For i = 2 To lrow
result = Application.WorksheetFunction.VLookup("A2", Sheets("ID").Range("A:B"), 2, False)
Cells(i, 5).Value = result
Next
End Sub
I'm trying to lookup all IDs(in column B) from my second sheet("ID") using the values in column A from my primary sheet("Data") and then populate the all results in column E in my primary sheet to their match.
My first try kinda worked but instead of leaving just the value it leaves the formula in the cell e.g. =VLOOKUP(A2,ID!A:B,2,FALSE) when really I'm looking for just the value 8447 that it shows before clicking on the cell.

If you want to get rid of the formula, just paste as values:
Sub matchID()
Dim wb As Workbook
Set wb = ActiveWorkbook
With wb.Sheets("Data")
.Range("E2:E" & .Range("A" & .Rows.Count).End(xlUp).Row).Formula = "=VLOOKUP(A2,ID!A:B,2,FALSE)"
.Range("E2:E" & .Range("A" & .Rows.Count).End(xlUp).Row).Value = .Range("E2:E" & .Range("A" & .Rows.Count).End(xlUp).Row).Value
End With
End Sub

Related

Auto fill a formula down a column but skipping already populated cells

After numerous failed attempts I am really hoping someone can with my problem. It theory what I am trying to do sounds easy enough but I have spent hours on it today with no success.
I have tried all the possible solutions from this thread but to no avail: Excel vba Autofill only empty cells
Also looked here : https://www.mrexcel.com/board/threads/macro-to-copy-cell-value-down-until-next-non-blank-cell.660608/
I am looking to autofill a formula down a column(a vlookup from another sheet) but if there is already populated cells then to skip and continue the formula in the next available blank cell. For example, in rows A2:A10, row A5 has a value in it, so the formula gets into in A2, then fills to A4, then skips A5, then continues in A6 to A10.
This below code works the first time you use it but then on the second run it debugs with a "Run-time error '1004' - No cells were found". I noticed it it putting the formula into the first cell (B2) and then debugging out.
Sub FillDownFormulaOnlyBlankCells()
Dim wb As Workbook
Dim ws1, ws2 As Worksheet
Dim rDest As Range
Set wb = ThisWorkbook
Set ws1 = Sheets("Copy From")
Set ws2 = Sheets("Copy To")
ws2.Range("A1").Formula = "=IFERROR(IF(VLOOKUP(A2,'Copy From'!A:B,2,FALSE)=0,"""",VLOOKUP(A2,'Copy From'!A:B,2,FALSE)),"""")"
Set rDest = Intersect(ActiveSheet.UsedRange, Range("B2:B300").Cells.SpecialCells(xlCellTypeBlanks))
ws2.Range("B2").Copy rDest
End Sub
Please, try the next code:
Sub FillDownFormulaOnlyBlankCells()
Dim wb As Workbook, ws1 As Worksheet, rngBlanc As Range
Set wb = ThisWorkbook
Set ws1 = wb.Sheets("Copy From")
On Error Resume Next
Set rngBlanc = ws1.Range("B2:B" & ws1.rows.count.End(xlUp).row).SpecialCells(xlCellTypeBlanks)
On Error GoTo 0
If Not rngBlanc Is Nothing Then
rngBlanc.Formula = "=IFERROR(IF(VLOOKUP(A2,'Copy From'!A:B,2,FALSE)=0,"""",VLOOKUP(A2,'Copy From'!A:B,2,FALSE)),"""")"
Else
MsgBox "No blanc rows exist in B:B column..."
End If
End Sub
After running it once and do not create any empty cell, of course there will not be any blanc cells, anymore, at a second run...
Thanks to FaneDuru for his suggestion but I actually came up with an alternative solution to my problem which I though I would post as it might help others with a similar issue.
On a separate sheet, I created 3 columns, first column is names I already have, 2nd column are the new names and the 3rd column is there to combine the first 2 columns together, then use this code to combine first 2 columns :
Sub MergeColumns()
Dim wb As Workbook
Dim ws1 As Worksheet
Dim LastRow As Long, i As Long
Set ws1 = Sheets("Your Sheet Name")
LastRow = ws1.Range("F" & Rows.Count).End(xlUp).Row
For i = 2 To LastRow
If ws1.Range("G" & i) <> "" Then
ws1.Range("I" & i) = ws1.Range("H" & i).Text & "" & ws1.Range("G" & i).Text
Else: ws1.Range("I" & i) = ws1.Range("H" & i)
End If
Next i
End Sub
Obviously changing the sheet name and columns letter to suit your requirements.

Method Range of Object Worksheet failed excel VBA

I have been stuck on a particular problem I am having with an excel visual basic macro.
I have written a script to simply paste a dynamic range of data from one worksheet to the other, The sheet that is being pasted to is a running sheet that updates to the next empty row each time new data is sent to it.
For certain ranges of data my code breaks and gives me the 1004 error.
I have looked at multiple similar questions and they don't seem to have given me any solutions.
I will first post my code then a data set that works and a data set that does not.
Private Sub RunningSheetClick_Click()
Dim lastrow As Long
Dim Vals As Range
Dim copyWS As Worksheet
Dim pasteWS As Worksheet
Set pasteWS = Sheets("Full List")
Set copyWS = Sheets("Macro Test")
Setlastrow = Sheets("Full List").Range("A" & Rows.count).End(xlUp).Row + 1
copyWS.Activate
' the following line is where my error appears
Set Vals = copyWS.Range("B3:S" & copyWS.Range("B3").End(xlDown))
Vals.Select
Vals.Copy _
Destination:=pasteWS.Range("A" & lastrow)
End Sub
This is a data set that works and exports correctly to the sheet "Full List"
This is a data set that does not, I believe it has to do with column B and the strings that are in those cells as compared to the integers in the first data set
Any help would be appreciated, thank you for taking the time
This is bad syntax that should never work. You just cannot concatenate a range object onto a string and expect a valid range object. I suspect it works with numbers since copyWS.Range("B3").End(xlDown) is returning its cell value by default. So if the value at the bottom of column B was 99, you would be resolved to Range("B3:S99").
Set Vals = copyWS.Range("B3:S" & copyWS.Range("B3").End(xlDown))
It should be something like,
with copyWS
Set Vals = .Range(.cells(3, "B"), .cells(rows.count, "B").end(xlup).offset(0, 17))
end with

Using VLookup in VBA to reference another Excel file

I'm trying to program a VLookup Table in VBA that references another file. Here is a simple outline of my goal:
Look up value in cell A2 in another Excel file
Pull the information in from column 2 of the other Excel file and place in Cell B2
Move on to cell A3 and repeat the process until there are no more entries left in column A
Here is the code that I already have. I keep getting an error that says "Unable to get the VLookup property of the WOrksheetFunction class." I checked the other posts referencing that error but they were not of any help. Do you all see an error in my code? Or does anyone have a better way of accomplishing this task?
Sub SBEPlannerAdder()
Dim wbk As Workbook
Set wbk = Workbooks.Open("C:\Users\user\Documents\Support File\Planner.xlsx")
With Sheets("Sheet1")
' Selects the first cell to check
Range("A2").Select
Dim x As Variant
x = wbk.Worksheets("Sheet1").Range("A1:C1752")
' Loops through all rows until an empty row is found
Do Until IsEmpty(ActiveCell)
Range(ActiveCell.Offset(0, 1) & ActiveCell.Row).Value = Application.WorksheetFunction.VLookup((ActiveCell.Column & ActiveCell.Row), x, 2, 0)
ActiveCell.Offset(1, 0).Select
Loop
End With
Call wbk.Close(False)
End Sub
When you open a workbook, it becomes the active workbook. It seems you were never passing control back to the target workbook.
Sub SBEPlannerAdder()
Dim rw As Long, x As Range
Dim extwbk As Workbook, twb As Workbook
Set twb = ThisWorkbook
Set extwbk = Workbooks.Open("C:\Users\user\Documents\Support File\Planner.xlsx")
Set x = extwbk.Worksheets("Sheet1").Range("A1:C1752")
With twb.Sheets("Sheet1")
For rw = 2 To .Cells(Rows.Count, 1).End(xlUp).Row
.Cells(rw, 2) = Application.VLookup(.Cells(rw, 1).Value2, x, 2, False)
Next rw
End With
extwbk.Close savechanges:=False
End Sub
See How to avoid using Select in Excel VBA macros for more methods on getting away from relying on select and activate to accomplish your goals.
It depends on whether you plan to do this as a one off or repeatedly. I'm assuming repeatedly since doing this manually is not all that difficult.
The first thing I would look at is your arguments. The first two should be ranges. So to be clear, perhaps you could do something like
Dim x As Range
set x = wbk.Worksheets("Sheet1").Range("A1:C1752")
...
Range(ActiveCell.Offset(0, 1) & ActiveCell.Row).Value = Application.WorksheetFunction.VLookup(Range(Activecell.Address), x, 2, 0)
The important bits are making sure your first two arguments are Ranges for the Vlookup function.

Error 1004 AutoFill

The error is being thrown on the line
ThisWorkbook.Sheets("data").Range("AJ2:AM2").AutoFill Destination:=Range("AJ2:AM" & localLastRow)
It was previously cooperating, but after I corrected another error it seems that it doesn't want to play nice anymore. The source is contained within the destination. I am just not sure where the problem is coming from.
Any help would be very appreciated.
I have posted the entire macro below. It will eventually be one that is called into a main macro.
Sub FormulaUpdate()
'
' FormulaUpdate Macro
' Updates Columns AJ through AS
'
Dim localLastRow As Long
Dim sourceLastRow As Long
Dim wbName As String
Dim wbPath As String
Dim sourceSheet As Worksheet
Dim sourceRange As Range
Dim thisSheet As Worksheet
Application.ScreenUpdating = False
'sets strings from user's selection of Item Branch Report
wbPath = GetFile("Select Item Branch Report to be Used")
wbName = GetFilenameFromPath(wbPath)
Workbooks.Open(wbPath, ReadOnly:=True).Activate
'sets workseets to be referenced
Set sourceSheet = ActiveWorkbook.Sheets(1)
Set thisSheet = ThisWorkbook.Sheets("data")
'counts rows in selected item branch report for use elsewhere in macro
sourceLastRow = sourceSheet.Range("A" & Rows.Count).End(xlUp).Row
'range for use in vlookup formula, for both system leadtime and order min columns
Set sourceRange = sourceSheet.Range("B1:BG" & sourceLastRow)
'Counts rows in this workbook for use elswhere in macro
localLastRow = thisSheet.Range("A" & Rows.Count).End(xlUp).Row
'uses formulas in cells to autofill the data
thisSheet.Range("AJ2:AM2").AutoFill Destination:=thisSheet.Range("AJ2:AM" & localLastRow)
'loops through each row of both the system lead time, and the order min column, and sets the value from item branch report
For i = 2 To localLastRow
thisSheet.Range("AN" & i).Value = Application.WorksheetFunction.VLookup(thisSheet.Range("C" & i), sourceRange, 53, False)
thisSheet.Range("AP" & i).Value = Application.WorksheetFunction.VLookup(thisSheet.Range("C" & i), sourceRange, 58, False)
Application.StatusBar = "Referencing IBR: " & i & " of " & localLastRow & ": " & Format(i / localLastRow, "0%")
Next i
'uses formulas in cells to autofill the data
thisSheet.Range("AO2").AutoFill Destination:=thisSheet.Range("AO2:AO" & localLastRow)
thisSheet.Range("AQ2:AS2").AutoFill Destination:=thisSheet.Range("AQ2:AS" & localLastRow)
Workbooks(wbName).Close (False)
I mention above that is the wrong solution. Read this for background on why relying on Select and Activate methods is usually problematic, and should be avoided at all times. You have already encountered one frustrating problem -- which is that you need to keep track of which sheet is "active" and constantly update the code to have the appropriate sheet "active". This makes for sloppy code that is difficult to navigate, and more expensive to execute.
The appropriate solution would be to fully qualify your range, for example:
ThisWorkbook.Sheets("data").Range("AJ2:AM2").AutoFill Destination:=ThisWorkbook.Sheets("data").Range("AJ2:AM" & localLastRow)
Why?
Because, as you observe, an unqualified range always refers to the ActiveSheet. One solution (the wrong one) is to continuously make the right sheet Active. The right solution is to fully qualify your ranges, especially when working across multiple workbooks or worksheets.

How to concatenate text from a column into a new column? VBA Excel

I'm new to vba programming and I would like to work on a function to fix salutations in an excel file.
To start, I would just like to append a Dear " to a name in the first column, and put this value in the next column, so that I would end up with the name in the first column and "Dear name" in the next column.
The function I have so far, is putting "Dear " in the next column, but it is not appending that to the text in the first column. Could someone help me correct my code?
Sub letterSalutationFixer()
Dim letterSalutationColumn As Range
Set letterSalutationColumn = Columns(1)
For Each Cell In letterSalutationColumn
Cell.Offset(, 1).Value = "Dear " & Cell.Text
Next
End Sub
PS. I do realise that I don't necessarily need to do this programmatically since it doesn't take that long to do with the functions already available, but I eventually want to expand this to fix other data with more complexity - and just thought I could start with something simple.
Many thanks in advance!
The reason it's blank is that Cell is equivalent to the whole column. You're close though. If you did...
For Each Cell In letterSalutationColumn.Cells
..l it would cycle through each cell.
However, the way it's written, it would cycle through each cell in the whole column, which could crash Excel, or at least slow things way down.
Here's a reworked version of what you're trying to do. It only acts on the cells in column A with content:
Sub Salutation()
Dim ws As Excel.Worksheet
Dim LastRow As Long
Dim NameRange As Excel.Range
Dim cell As Excel.Range
Set ws = ActiveSheet
With ws
LastRow = .Range("A" & .Rows.Count).End(xlUp).Row
Set NameRange = .Range("A2:A" & LastRow)
For Each cell In NameRange
cell.Offset(, 1) = "Dear " & cell.Text
Next cell
End With
End Sub
It also declares all variables, something you want to get in the habit of doing. Do a search on Option Explicit to learn how to force yourself to.
It also uses a With statement to fully qualify Object references, so that instead of just referring to Column(1) or Range(something) you're specifying that it's in ws, which has been set to the ActiveSheet.
Another way is the VBA alternative of
Using a formula in column B that runs the concatenation against the used part of column A (ie in B1 ="Dear " &A1 etc)
The formula then is copied over itself as a value to remove the formula
code
Sub QuickCon()
Dim rng1 As Range
Set rng1 = Range([a1], Cells(Rows.Count, "A").End(xlUp))
With rng1.Offset(0, 1)
.FormulaR1C1 = "=""Dear "" &RC[-1]"
.Value = .Value
End With
End Sub

Resources