VBA VLOOKUP Convert to Values Gives #N/A - vba

I'm having some trouble with VLOOKUP in my VBA. Here's an example of the code I'm using:
Sub Macro15()
'
' Macro15 Macro
Dim LR As Long
LR = Cells(Rows.Count, "A").End(xlUp).Row
Range("B1:B" & LR).FormulaR1C1 = _
"=VLOOKUP(RC[-1],'https://internal_sharepoint_address
/[Vendor_Information.xlsx]Sheet1'!R3C3:R150C18,4,FALSE)"
Range("C1:C" & LR).FormulaR1C1 = _
"=VLOOKUP(RC[-2],'https://internal_sharepoint_address
/[Vendor_Information.xlsx]Sheet1'!R3C3:R150C18,5,FALSE)"
With Range("B1:C" & LR)
.Value = .Value
End With
End Sub
The problem is that the values in Columns B & C (the VLOOKUP formulas) return a value of #N/A.
However, if I stop the code before converting the formula to values (the "With Range("B1:C" & LR)" line), the VLOOKUP formula returns the correct values.
Also strange - if I clear the contents of Columns B & C and re-run the above code, the values return fine. If I try to add a second cycle to the VBA, however, it does NOT work.
Any wisdom that anyone can provide would be a huge help. I've been stuck on this for a long time, and I'm just at my wit's end.
Thanks all,
David

You'll probably need to add in a step that runs a calculation cycle before you try to replace with the value:
Application.Calculate
Edit from comment: I would imagine that retrieving lookup data from a linked workbook on a Sharepoint site would take awhile. Maybe add some delay loops? Can you make two separate macros (one ending with the formulas, and a second one starting at the Paste Values), and run them separately with a pause in between?

Related

Use VBA to replace sporadic #N/A cells with a formula

I have data that comes from different sources via Get Data/Connections that goes into a sheet/table called RawData. I have created a macro linked to a button the user must click to fill in some of the data in RawData with an index/match function that points to another workbook where the reservation number from RawData is matched to the other workbook to determine the length of stay.
I am not appending said workbook to the RawData table for different reasons. I can go that route if need be but I figured there would be an easier route before we cross that bridge. The issue I have is that once the macro is ran, the other workbook, at times, may not have the reservation data. In these cases, I had to manually determine this data.
This new data can be placed within my main workbook [but I currently have it in it's own workbook (LOSNAintoActualLOS.xlsm) as I've been running tests on making this work]. And the formula has to be pasted into the table because when the table refreshes, the row of data that would normally have the length of stay removes the formula and replaces it with it's original value, a blank cell.
What I need is for my code to loop through all the cells within the F column of a table, determine the cells with #N/A errors, then paste a formula in the error cell. I have done some research and can't seem to find something that suits my needs. I attempted doing this as a loop but seeing as I'm still pretty new to VBA coding, it's definitely not my strong suit.
Sub Macro2()
Dim r As Integer
LastRow = Range("B" & Rows.Count).End(xlUp).Row
With Worksheets("Sheet1").Range("F2:F" & LastRow)
For r = 2 To LastRow
If .IsError(Worksheets("Sheet1").Range("F" & r)).Value Then
.Formula = "INDEX(LOSNAintoActualLOS.xlsm!Table1[#Data],MATCH([#Reservation],LOSNAintoActualLOS.xlsm!Table1[Reservation],0),7)"
.Value = .Value
End If
Next r
End With
End Sub
When I run the code for my If statement I get Run-time error '438': Object doesn't support this property or method. If I remove the first period from .IsError I get Compile error: Invalid qualifier.
IsError is not part of Worksheets("Sheet1").Range("F2:F" & LastRow)
Switch it up like this.
Sub Macro2()
Dim r As Long
Dim LastRow As Long
LastRow = Worksheets("Sheet1").Range("B" & Rows.Count).End(xlUp).Row
For r = 2 To LastRow
With Worksheets("Sheet1").Range("F" & r)
If IsError(.Value) Then
.Formula = "INDEX(LOSNAintoActualLOS.xlsm!Table1[#Data],MATCH([#Reservation],LOSNAintoActualLOS.xlsm!Table1[Reservation],0),7)"
.Value = .Value
End If
End With
Next r
End Sub

Syntax error for INDEX formula using Macro

I'm getting a syntax error when I try to insert a formula in a cell using Macro. I can't seem to figure out what am I doing wrong? The formula works fine when I manually enter it. Here's my code:
ws3.Range("F2:F" & lastRow3).Formula = "=INDEX($L$1:INDEX(L:L,MATCH("ZZZ",D:D)),AGGREGATE(15,6,ROW($K$1:INDEX(K:K,MATCH("ZZZ",D:D)))/($K$1:INDEX(K:K,MATCH("ZZZ",D:D))=D2),COUNTIF($D$1:$D2,D2)))"
ws3 is the worksheet, and lastRow3 is just to autofill the contents by comparing to a column to the left. Any ideas why this is giving an error?
FYI: This formula is finding values in one column from another column and giving the adjacent entries.
When filling a full range it is best to use R1C1 format.
Also with using vba to set the last row there is no reason for all the INDEX(L:L,MATCH("ZZZ",D:D)) to find the last row, since the code itself can set it directly.
Use this:
ws3.Range("F2:F" & lastRow3).FormulaR1C1 = _
"=INDEX(R1C12:R" & lastrow & "C12,AGGREGATE(15,6,ROW(R1C11:R" & lastrow & "C11)/(R1C11:R" & lastrow & "C11=RC[-2]),COUNTIF(R1C4:RC4,RC[-2])))"

Copying Cells from Workbook to Workbook Results in "Subscript Out of Range"

Good day.
I am trying to write a code that will essentially select cells (left to right) from "A - M" and (downwards) up until the last used row.
Then, once selected, I was to copy them to another workbook.
This is the code that I tried to use:
ActiveWorkbook.Worksheets("Sheet1").Range("A1:M" & LastRow).Copy _
Workbooks("Converter.xlsm").Worksheets("Sheet1").Range("A1").CurrentRegion
Everything else in the code works except for this line.
And the result is this:
Run-time error '9':
Subscript out of range
Thanks.
PS. The "LastRow" Variable I used, I just pulled that out of a tutorial. That's not a personal user-defined variable, so I am not sure if that's actually from VBA's Documentation.
You mentioned you do not have a calculation for LastRow.
Always put Option Explicit at the top of your module. It forces you to declare your variables and will help you recognize if something you got from another coder is "built-in" or not.
See this post about determining the last row in a range.
From that post, you should have a calculation such as the following before your line of code ...
LastRow = Sheets("Sheet1").Range("A" & Sheets("Sheet1").Rows.Count).End(xlUp).Row
Please close all the workbooks and reopen and then try with below code
Sub test()
Dim lastrow As Long
lastrow = Range("A" & Rows.Count).End(xlUp).Row
ActiveWorkbook.Worksheets("Sheet1").Range("A1:M" & lastrow).Copy Workbooks("Converter.xlsm").Worksheets("Sheet1").Range("A1")
End Sub

Looping the whole cells to change a specific formula issue

I'm writing a function to change an entire column to new values using a formula, here's the code I'll elaborate more on the idea down there.
The problem is that it hangs and I have to rerun Excel and I'm not sure why.
Sub Button2_Click()
Dim i As Long
For i = 2 To Rows.Count
Cells(i, 4).Formula = "=B" & i & "+6*3600000/86400000+25569"
Next i
End Sub
So what's this about? I'm changing the fourth column to excel time because what I have in column B is epoch time, and this is the formula I'm using, it works with my case if I tried one by one, but for some reason it won't work as a whole. I'm not sure what's done wrong? But I'd appreciate your help.
Writing to cells one-by-one is very slow.
Writing formulas one-by-one is slower still, because each must be evaluated before Excel accepts them as formulas.
Doing this a million times can literally freeze Excel.
The solution is to write them all in one shot (no loops):
Sub Button2_Click()
[d2:d1048576] = "=B2+6*3600000/86400000+25569"
End Sub
' Another way of doing mass calculation is by using copy and paste method.
It will be better to convert the columns into values so that the sheet won't calculate again and again. It helps to prevent the sheet from hanging issues
Sub Button2_Click()
Range("D2").Formula = "=b1" & "+6*3600000/86400000+25569"
Range("D2").Copy
Range("D2:d1048576").PasteSpecial xlValues
Application.CutCopyMode = False
Range("D:D").Value = Range("D:D").Value
End Sub

Declaring last row references in Excel formulas through VBA

In an attempt to take one of my rudimentary programs, and develop it more I am in need of help referencing last row references in Excel formulas as well as dragging formulas down consistently to the last row of a document.
To elaborate I am attempting to reference the last row in an ever expanding mapping table in my vlookup formula. The reason I need this is because as this mapping table expands when I am no longer coding this program, I need my vlookup formula which will be generated every time I run the program to adapt to the ever changing size.
Also my more pressing issue is in regard to taking that vlookup formula and being able to drag it down to the last row of a worksheet. The worksheet will be static and the last row will range anywhere from 70,000 rows to 90,000 rows. I am trying to avoid loops in this scenario as this will already be a very demanding formula and I would hate to loop through each row.
Currently my rudimentary code looks like this (this was built as a proof of concept, I understand the current method isn't the most ingenious but it served its initial purpose).
Ath.Cells(1, x) = "Business"
Ath.Cells(2, x).Select
ActiveCell.FormulaR1C1 = "=IFERROR(VLOOKUP(RC[1],Mapping!R2C4:R264C5,2,0),VLOOKUP(LEFT(RC[1],2),Mapping!R1C3:R264C5,3,0))"
Ath.Range("d2").Copy
Range("d2:d90000").Select
ActiveSheet.Paste
Calculate
I namely want to change this
Ath.Range("d2").Copy
Range("d2:d90000").Select
ActiveSheet.Paste
and
ActiveCell.FormulaR1C1 = "=IFERROR(VLOOKUP(RC[1],Mapping!R2C4:R264C5,2,0),VLOOKUP(LEFT(RC[1],2),Mapping!R1C3:R264C5,3,0))"
Perhaps these?
Ath.Range("d2").Copy
Range("d2:d" & Range("D" & Rows.Count).End(xlUp).Row).Paste
ActiveCell.FormulaR1C1 = "=IFERROR(VLOOKUP(RC[1],Mapping!R2C4:R" & Sheets("Mapping").Range(ActiveCell.Offset(Rows.Count, -1)).End(xlUp).Row & "C5,2,0),VLOOKUP(LEFT(RC[1],2),Mapping!R1C3:R" & Sheets("Mapping").Range(ActiveCell.Offset(Rows.Count, -1)).End(xlUp).Row & "C5,3,0))"
Combining Dans answer with work of my own I have developed a solution.
Sub Formulas()
Dim Map As Worksheet
Dim Ath As Worksheet
Dim last As Long
Set Ath = Sheets("Athena IBT TEST")
Set Map = Sheets("Mapping")
last = Map.Cells(Rows.Count, "D").End(xlUp).Row
ActiveCell.FormulaR1C1 = "=IFERROR(VLOOKUP(RC[1],Mapping!R1C1:R" & last & "C4,4,0),IFERROR(VLOOKUP(LEFT(RC[1],3),Mapping!R1C2:R" & last & "C4,3,0),VLOOKUP(LEFT(RC[1],3),Mapping!R1C3:R" & last & "C4,2,0)))"
End Sub