is there away how to handle error 13 in vba - excel

Hello
I have an error 13 on my vlookup all the time ,when I execute vlookup on my sheet it works soon vba doesn't I am looking for help
here is my code , all the columns are Text in my sheet
Sub address_change()
Dim updatesheet As Variant
Dim sbw As String
Dim Param As String
Dim entier As Integer
Dim fname As String
Dim tsk As Task
Dim rg As Variant
Dim ws As Sheets
Dim wb As Excel.Workbook
Dim appXLS As Object
Dim entxls As Object
Dim i As Integer
Set appXLS = CreateObject("Excel.Application")
If appXLS Is Nothing Then
MsgBox ("XLS not installed")
End If
fname = ActiveProject.Path & "\" & Dir(ActiveProject.Path & "\addresses.xlsx")
MsgBox (fname)Set wb = appXLS.Workbooks.Open(fname, False)
Set rg = appXLS.Worksheets("sheet2").Range("A:U")
appXLS.Visible = TrueMsgBox (appXLS.Application.Value)
On Error Resume Next
For Each tsk In ActiveProject.Tasks
Param = tsk.Text2
If tsk.OutlineLevel = 2 Then
updatesheet = appXLS.Application.VLookup(Param, rg, 16, False)
If Err.Number <> 0 Then
tsk.Text13 = "No match 32"
Else
tsk.Text13 = updatesheet
End If
End If
Next tsk
End Sub

There are two ways to use the Excel VLookup (and similar functions like Match) with VBA, and they differ.
Application.VLookup (the version you are using) will return an error value Error 2042 if the search term cannot be found. This is not a runtime error, this is a return value. Error values are a special data type in VBA (they are not strings, the Error 2042 is just the representation of it). To be precise, this error is the #N/A that you see in Excel if a Vlookup fails.
You write the result into variable updatesheet, that is fine as it is declared as Variant, and a variant can hold an error value. However, now you check if an error occurred and as this is not the case, it will try to assign the error value to tsk.Text13 and this gives you a type mismatch error (I assume that tsk.Text13 expects a string).
Instead of checking for a runtime error as you do, you need to check if updatesheet contains an error value, this is done using the IsError-function. In this case, you could also use the Application.IsNA()-function.
The alternative is to use WorksheetFunction.Vlookup, this will throw a runtime error if can't find the search term, and you need to wrap this into Error handling.
Use either the one or the other method:
updatesheet = appXLS.VLookup(Param, rg, 16, False)
If appXLS.IsNA(updatesheet) Then
tsk.text13 = "No match 32"
Else
tsk.text13 = updatesheet
End If
updatesheet = "No match 32"
On Error Resume Next
updatesheet = appXLS.WorksheetFunction.VLookup(Param, rg, 16, False)
On Error GoTo 0
tsk.text13 = updatesheet
For further reading, I recommend https://rubberduckvba.wordpress.com/2021/02/15/worksheetfunction-and-errors/

Related

Test if Range has a Name in Excel

I am attempting to determine if a range has a name and keep getting an error message.
My code looks like this:
Dim rCell As Range
Dim sName As String
Set rCell = Range("A1")
If Not rCell.Name Is Nothing Then sName = rCell.Name
And produces the following error message:
Run-time error '1004':
Application-defined or object-defined error
I have also tried replacing the
If Not rCell.Name Is Nothing Then sName = rCell.Name line with sName = rCell.Name and even Debug.Print rCell.Name but keep getting the same error.
What am I doing wrong?
Range.Name throws a RTE 1004 if the range is not named. One alternative is to try to assign to a Name object.
Note that you probably want the Name.Name property.
Set rCell = Range("A1")
On Error Resume Next
Dim n As Name
Set n = Nothing ' only including in case you are planning to use this approach in a loop.
Set n = rCell.Name
On Error GoTo 0
If not n Is Nothing Then
sName = n.Name ' Name.Name, not Range.Name
End If

Still Run time error 1004 'Unable to get the VLookup property of the WorksheetFunction class

I got this error and I tried to fixed with many solution, but I don't know why this error is happening. Could you help me to fix this problem? In this code I have twice used VLookup function same source, different only Worksheet name and column. Another one can compile this code and don't have any error.
I'm doing, VLookup item on column B of worksheet "ImportData2" match with column A of worksheet "Noallocate" if match show result of VLookup at column Q of worksheet "ImportData2"
get this error
Source code:
'Vlook up function no import
Dim Vrow1 As Long
Dim myLookupValue1 As String
Dim myFirstColumn1 As Long
Dim myLastColumn1 As Long
Dim myColumnIndex1 As Long
Dim myFirstRow1 As Long
Dim myLastRow1 As Long
Dim myVLookupResult1 As String
Dim myTableArray1 As Range
For Vrow1 = 2 To 99999
myLookupValue1 = Workbooks("ExpenseData.xlsm").Worksheets("ImportData2").Range("B" & Vrow).Value
myFirstColumn1 = 1
myLastColumn1 = 2
myColumnIndex1 = 2
myFirstRow1 = 2
myLastRow1 = Workbooks("ExpenseData.xlsm").Worksheets("Noallocate").Range("b1").End(xlDown).Row
With Workbooks("ExpenseData.xlsm").Worksheets("Noallocate")
Set myTableArray1 = .Range(.Cells(myFirstRow1, myFirstColumn1), .Cells(myLastRow1, myLastColumn1))
End With
myVLookupResult1 = WorksheetFunction.VLookup(myLookupValue1, myTableArray1, myColumnIndex1, False) 'xxx
Workbooks("ExpenseData.xlsm").Worksheets("ImportData").Range("Q" & Vrow).Value = myVLookupResult1 'xxx
Next 'end function no import
Try the next code, please. It would be a good habit to have 'Option Explicit' on top of your module. This will oblige you to declare all variables. It looks, your code iterates using Vrow1 but inside the loop you used Vrow... I discovered it only after trying to make your code a little friendlier. It is not good to use big variables name instead of 1, 2. This can only make the code more difficult to be understood by looking at it. As short it would be, as easy to be understood and debugged:
Sub testVlookup()
Dim Wb As Workbook, Vrow1 As Long, lastRDat As Long, wsNoall As Worksheet
Dim wsImpD2 As Worksheet, myLookupValue1 As String, myLastRow1 As Long
Dim myVLookupResult1 As String, myTableArray1 As Range
Set Wb = Workbooks("ExpenseDataMcframe.xlsm")
Set wsNoall = Wb.Worksheets("Noallocate")
Set wsImpD2 = Wb.Worksheets("ImportData2")
myLastRow1 = wsNoall.Range("b" & Rows.count).End(xlUp).Row
lastRDat = wsImpD2.Range("B" & Rows.count).End(xlUp).Row
For Vrow1 = 2 To lastRDat
myLookupValue1 = wsImpD2.Range("B" & Vrow1).value
Set myTableArray1 = wsNoall.Range(wsNoall.Cells(2, 1), wsNoall.Cells(myLastRow1, 2))
On Error Resume Next 'for the case when lookup_value is not found
myVLookupResult1 = WorksheetFunction.VLookup(myLookupValue1, myTableArray1, 2, False) 'xxx
If Err.Number <> 0 Then
Err.Clear: On Error GoTo 0
Wb.Worksheets("ImportData").Range("Q" & Vrow1).value = "Not a mach"
Else
Wb.Worksheets("ImportData").Range("Q" & Vrow1).value = myVLookupResult1 'xxx
End If
On Error GoTo 0
Next
End Sub
When the lookup_value is not found, the code will return (on Q:Q column) "Not a match" and you must check the specific code/whatever it is...

Runtime error 1004 - Unable to get the PageRange property of the PivotTable class

When the code is applied to a pivot table that has no PageRange property the code fails with the error in the title
I tried to apply a boolean variable to
sh.PivotTables(i).PageRange
but that did not work either
Sub TestPivotPaste2()
Dim wb As Workbook
Dim sh As Worksheet
Set wb = ActiveWorkbook
Set sh = wb.Worksheets(7)
c = sh.PivotTables.Count
If c > 0 Then
For i = 1 To c
If Not sh.PivotTables(i).PageRange.Count = 0 Then
Debug.Print c
Else
GoTo nextpiv
End If
nextpiv:
Next i
Else
MsgBox ("NoPivot")
End If
End Sub
the expected result is to be able to discern the pivot tables where the PageRange property is true or false, but it only works when the range exists.
Try this function
Function pageRangeExists(pt as PivotTable) as Boolean
Dim test as Range
On Error Resume Next
Set test = pt.PageRange
On Error Go To 0
pageRangeExists = Not test Is Nothing
End Function
Since PageRange is a range object, you have to test if the range exists or is valid first, as trying to act against a range that is not there will produce an error.
And with that your for loop can be simplified
For i = 1 To c
If pageRangeExists(sh.PivotTables(i)) Then
Debug.Print c
End If
Next i
The GoTo statement is superfluous as it is logic already embedded in a for loop.

Using INDEX MATCH in VBA with Variable Lookup Locations

I am having trouble using variables within the lookup criteria in Index Match. Some background: I use the following code to set a variable's value to the row # of whatever cell contains "Current" within column B:
Dim rowHeaderNum As Integer
rowHeaderNum = 0
On Error Resume Next
rowHeaderNum = Application.Match("Current", ActiveSheet.Range("B:B"), 0)
On Error GoTo 0
Then I use the below to store the column # of the cell within the row 'rowHeaderNum' that contains the value "CurrentActual" to another variable:
Dim currActColNum As Integer
currActColNum = 0
currActColNum = Application.Match("CurrentActual", Rows(rowHeaderNum & ":" & rowHeaderNum), 0)
Below is the Index Match line that I can't get to work:
Dim currActRev As Double
currActRev = Application.Index(Columns(currActColNum), Application.Match("Gross Operating Profit", Columns("N:N"), 0))
currActRev will store a dollar amount. The Match function will always use column N as the lookup array. When I run the Index Match line I get a
type mismatch
error in the debugger.
Using WorksheetFunction …
Application.Match and On Error Resume Next does not work, because Application.Match does not throw exceptions you need to use WorksheetFunction.Match instead.
According to the documentation the WorksheetFunction.Match method it returns a Double so you need to Dim RowHeaderNum As Double.
Dim RowHeaderNum As Double
'RowHeaderNum = 0 'not needed it is always 0 after dim
On Error Resume Next
RowHeaderNum = Application.WorksheetFunction.Match("Current", ActiveSheet.Range("B:B"), False)
On Error GoTo 0
Furthermore you need to check if RowHeaderNum is 0 and stop proceeding otherwise the following code will fail because row 0 does not exist.
If RowHeaderNum = 0 Then
MsgBox "'Current' not found."
Exit Sub
End If
You need to do exactly the same here
Dim CurrActColNum As Double
On Error Resume Next
CurrActColNum = Application.WorksheetFunction.Match("CurrentActual", Rows(RowHeaderNum), False)
On Error GoTo 0
If CurrActColNum = 0 Then
MsgBox "'CurrentActual' not found."
Exit Sub
End If
Finally the WorksheetFunction.Index method returns a Variant not a Double and you need error handling here too.
Dim currActRev As Variant
On Error Resume Next
currActRev = Application.WorksheetFunction.Index(Columns(CurrActColNum), Application.WorksheetFunction.Match("Gross Operating Profit", Columns("N:N"), False))
On Error GoTo 0
Debug.Print currActRev 'print result in immediate window
Using Application …
Note that you can also use the Application.Match and Application.Index (without WorksheetFunction) but then you cannot use On Error … and you have to check for errors using IsError(). Also your variables need to be declared as Variant then because Application.Match can either return a typo Double or a type Error.
Dim RowHeaderNum As Variant
RowHeaderNum = Application.Match("Current", ActiveSheet.Range("B:B"), False)
If IsError(RowHeaderNum) Then
MsgBox "'Current' not found."
Exit Sub
End If
Dim CurrActColNum As Variant
CurrActColNum = Application.Match("CurrentActual", Rows(RowHeaderNum), False)
If IsError(CurrActColNum) Then
MsgBox "'CurrentActual' not found."
Exit Sub
End If
Dim currActRev As Variant, currMatch As Variant
currMatch = Application.Match("Gross Operating Profit", Columns("N:N"), False)
If Not IsError(currMatch) Then
currActRev = Application.Index(Columns(CurrActColNum), currMatch)
End If
Debug.Print currActRev 'print result in immediate window

Index match in VBA referencing a table

I want to update a line in my table based on a cell in another sheet, and to that end I intend to use the index match function. When I run the code below I get the error that it cannot get the property of the match function class.
What is the correct syntax in this regard?
Sub Update_Customer()
' Declarations
Dim rng as listobject
Dim wf as application.worksheetfunction
Dim cs_sht as string
Set rng = Sheets(1).ListObjects("Table_Customer")
Set ws = ThisWorkbook.ActiveSheet
cs_sht = ws.Name
' ERROR RUNNING THIS LINE vvvvv
wf.Index(rng.ListColumns("Firstname"), wf.Match(cs_sht, rng.ListColumns("Customer ID"), 0)) = ws.Range("C_Firstname").Value
End Sub
Excel functions need to be nested, because a cell's value needs to be parsed as a single step.
VBA code doesn't need to do that. VBA instructions work best and are easier to debug when you split them and make them do as little work as possible.
So instead of this:
wf.Index(rng.ListColumns("Firstname"), wf.Match(cs_sht, rng.ListColumns("Customer ID"), 0))
Split it up:
Dim matchResult As Long
matchResult = WorksheetFunction.Match(cs_sht, rng.ListColumns("Customer ID").DataBodyRange, 0)
Dim indexResult As Variant
indexResult = WorksheetFunction.Index(rng.ListColumns("FirstName").DataBodyRange, matchResult)
Note that you'll get a run-time error if either function fails to find what it's looking for. Use On Error to handle that case:
On Error GoTo CleanFail
Dim matchResult As Long
matchResult = WorksheetFunction.Match(...)
...
Exit Sub
CleanFail:
MsgBox "Could not find record for '" & cs_sht & "'." & vbNewLine & Err.Description
End Sub
Get rid of wf. There's no use to copy object references of objects that are already global. The fewer global variables you use, the better.
if the first name changes I can update the table to match the new name from my worksheet
You can't just assign the indexResult to a new value. The indexResult isn't holding a reference to any cell, it's just the result of the INDEX worksheet function. You need to use that result to get the cell you want to modify:
Dim targetCell As Range
Set targetCell = rng.ListColumns("FirstName").DataBodyRange.Cells(indexResult)
targetCell.Value = ws.Range("C_Firstname").Value

Resources