Test if Range has a Name in Excel - 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

Related

is there away how to handle error 13 in vba

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/

Run-Time Error '91' - Declared objects correctly and same syntax works in lines above

I am at my wits end trying to decode this error I am getting.
In the syntax below, the line which throws up the error is NumColumnsTarget = .Range("A1").End(xlToRight).Column
As far as I can tell, I have assigned all the objects correctly. One thing I have noticed is that changing the order in which the Range variables are declared in (Ie: NumRowsTarget, NumColumnsTarget, NumColumnsLOP, NumRowsLOP as opposed to NumRowsLOP, NumColumnsLOP, NumRowsTarget, NumColumnsTarget) will change which variable throws the Run-Time error up and I am lost for a reason why. Any thoughts?
Option Explicit
Sub MergeRecords()
Application.ScreenUpdating = False
Dim TargetRecordArray(), LOPRecordArray() As Variant
Dim ws As Worksheet
Dim i, j As Integer
Dim LOPSerialNo, TargetSerialNo As String
Dim NumRowsLOP, NumColumnsLOP, NumRowsTarget, NumColumnsTarget As Range
Set ws = ThisWorkbook.Sheets("LOP Records")
With ws
NumRowsLOP = .Range("A1").End(xlDown).Row
NumColumnsLOP = .Range("A1").End(xlToRight).Column
End With
Set ws = ThisWorkbook.Sheets("Target Records")
With ws
NumRowsTarget = .Range("A1").End(xlDown).Row
NumColumnsTarget = .Range("A1").End(xlToRight).Column
End With
End Sub
Edit: I am a fool. Thanks to all.

Error handling in a loop using Resume Next

as a newcomer to VBA any help would be appreciated. The basic point of my program is to loop through columns of the spreadsheet and count the number of non-blank cells in each column, within a specified range.
Here is an example of what my spreadsheet looks like.
1
2
3
1
thing
2
thing
3
thing
When all the cells in the column are blank, VBA throws out a 1004 error, no cells found. What I want to do is say, if a 1004 error occurs, set the count of the non-blank cells (nonBlank = 0) equal to zero, and if no error occurs, count normally. In something like Python, I'd use try/except. Here is my attempt.
For i = 1 To 3
On Error Resume Next
Set selec_cells = Sheet1.Range(Sheet1.Cells(FirstRow, i), Sheet1.Cells(LastRow, i)).SpecialCells(xlCellTypeVisible).Cells.SpecialCells(xlCellTypeConstants)
If Err.Number <> 1004 Then
nonBlank = 0
Else
nonBlank = selec_cells.Count
End If
On Error GoTo -1
Next i
My issue is, when I run this code, it spits out 0 every time, even though column 2 should return 3. Thank you!
Edit: selec_cells is what throws out the error.
Error Handling
There is no On Error Goto -1 in VBA, it's a VB thing (those are links to different pages). A tip would be if you google VBA stuff, just put VBA in front of what you're looking for.
When using On Error Resume Next (defer error trapping), you should 'apply' it on a line or two maximally and 'close' with On Error Goto 0 (disable error trapping) or with another error handler.
Your usage of On Error Resume Next is unacceptable because in this particular case we can test the range: 1. defer error handling, 2. try to set the range, 3. disable error handling. If there was an error the range will not be set hence If Not rg Is Nothing Then which could be translated to something like 'If rg Is Something Then' (double negation) or If a reference to a range has been created Then.
The second solution illustrates a case where the main error handler is handling all errors except the SpecialCells error which has its own error handler. Resume Next means continue with the line after the line where the error occurred. Note the Exit Sub line and note Resume ProcExit where the code is redirected to a label.
The following illustrates two ways how you could handle this. At this stage, I would suggest you use the first one and remember to use the 'closing' On Error Goto 0 whenever you use On Error Resume Next (a line or two).
The Code
Option Explicit
Sub testOnErrorResumeNext()
Const FirstRow As Long = 2
Const LastRow As Long = 11
Dim rg As Range ' ... additionally means 'Set rg = Nothing'.
Dim nonBlank As Long ' ... additionally means 'nonBlank = 0'.
Dim j As Long
For j = 1 To 3 ' Since it's a column counter, 'j' or 'c' seems preferred.
' Since you're in a loop, you need the following line.
Set rg = Nothing
On Error Resume Next
Set rg = Sheet1.Range(Sheet1.Cells(FirstRow, j), _
Sheet1.Cells(LastRow, j)).SpecialCells(xlCellTypeVisible) _
.Cells.SpecialCells(xlCellTypeConstants)
On Error GoTo 0
If Not rg Is Nothing Then
nonBlank = rg.Cells.Count
Else
' Since you're in a loop, you need the following line.
nonBlank = 0
End If
Debug.Print nonBlank
Next j
End Sub
Sub testOnError()
On Error GoTo clearError
Const FirstRow As Long = 2
Const LastRow As Long = 11
Dim rg As Range ' ... additionally means 'Set rg = Nothing'.
Dim nonBlank As Long ' ... additionally means 'nonBlank = 0'.
Dim j As Long
For j = 1 To 3 ' Since it's a column counter, 'j' or 'c' seems preferred.
' Since you're in a loop, you need the following line.
Set rg = Nothing
On Error GoTo SpecialCellsHandler
Set rg = Sheet1.Range(Sheet1.Cells(FirstRow, j), _
Sheet1.Cells(LastRow, j)).SpecialCells(xlCellTypeVisible) _
.Cells.SpecialCells(xlCellTypeConstants)
On Error GoTo clearError
If Not rg Is Nothing Then
nonBlank = rg.Cells.Count
End If
Debug.Print nonBlank
Next j
ProcExit:
Exit Sub ' Note this.
SpecialCellsHandler:
' Since you're in a loop, you need the following line.
nonBlank = 0
Resume Next
clearError:
MsgBox "Run-time error '" & Err.Number & "': " & Err.Description
Resume ProcExit
End Sub
My preference is, wherever possible, to encapsulate the line of code that may cause an error in its own function. The function returns true or false to indicate whether or not there is an error and an out parameter is used to return the value that you want.
This keeps the error testing confined within a very short well defined function.
Sub ttest()
Dim mySheet As Excel.Worksheet
Set mySheet = ThisWorkbook.Sheet1
Dim myIndex As Long
Dim myNonBlank as long
For myIndex = 1 To 3
If AllCellsAreBlank(mySheet.Range(ThisWorkbook.Sheet1.Cells(myFirstRow, myIndex), mySheet.Cells(myLastRow, myIndex)), myIndex, mySelectCells) Then
myNonBlank = 0
Else
myNonBlank = mySelectCells.Count
End If
Next
End Sub
Public Function AllCellsAreBlank(ByRef ipRange As Excel.Range, ByVal ipIndex As Long, ByRef opSelectCells As Range) As Boolean
On Error Resume Next
set opSelectCells = ipRange.SpecialCells(xlCellTypeVisible).Cells.SpecialCells(xlCellTypeConstants)
AllCellsAreBlank = Err.Number <> 0
On Error GoTo 0
End Function
For reference the prefixes I use are
ip: for an input only parameter
iop: for an input parameters that will be changed by the method
op: for a parameter only used to return a value
my: any variable declared within a Method.
I's also suggest you acquire the habit of meaningful descriptive names, myRow, myCol are much more meaningful than i,j, and of ensuring you use fully qualified references rather than the implicit use of the activesheet.

VBA: Use "Find" to get the row of a value / fixing object variable errors

I need to use the "find" function to get the row of a value, where that value is defined from another worksheet, but I keep getting object-variable not defined errors even when I try defining everything.
I was initially able to get the code below to work. (I paste the "test" version of the code that only uses a small range of 20 cells. The result is placed in cell "A1" to make sure it works correctly in testing.)
X = Range("D6").Value
Range("A1").Value = Range("D2:D20").Find(X).Row
But when I use this line in a large data set, I keep getting error 91 ("Object variable or With block variable not set").
So instead, I try code that defines everything more explicitly, but for the life of me, I can't get this code to work even on the small test set. (I also include a few lines that I've tried but that also produce errors.)
Sub Test3()
Sheets("2017").Select
Dim X As Long
X = Range("D6").Value
Dim ws As Worksheet
Set ws = Worksheets("2017")
Dim SearchRange As Range
Dim FindRow As Range
Set SearchRange = ws.Range("D2", ws.Range("D20").End(xlUp))
Set FindRow = SearchRange.Find(X, LookIn:=xlValues, lookat:=xlWhole)
If Not FindRow Is Nothing Then ReturnRowNumber = FindRow.Row
'Range("A1").Value = FindRow 'Running this row gives application-defined error 1004
Dim i_2017 As Long
i_2017 = FindRow.Rows(1) 'All of these rows give object variable not set error 91
'i_2017 = FindRow
'i_2017 = FindRow.Rows.Item(1)
Range("A1").Value = i_2017 'Check that the sub returns 6
End Sub
If I try to return "FindRow" in cell "A1", I get error 1004 ("Application-defined or object-defined error")
If I try to store "FindRow" as another variable or use the "Item" property, I get error 91 ("Object variable or With block variable not set")
You need to enclose all of your code that assumes FindRow has actually been found inside your If Not FindRow is Nothing statement.
Sub Test3()
Dim ws As Worksheet: Set ws = ThisWorkbook.Sheets("2017")
Dim Found As Range, ReturnRowNumber As Long
Set Found = ws.Range("D:D").Find (ws.Range("D6"), LookIn:=xlValues, LookAt:=xlxWhole)
If Not Found Is Nothing Then
'All code that assumes your value is found goes HERE
ReturnRowNumber = Found.Row
Range("A1").Value = Found
Else
'All code that assumed your value is NOT found goes HERE
MsgBox ws.Range("2017") & ": Not Found in Range"
End If
End Sub

I am unable to get the proper syntax for my Goal Seek routine

Here is my routine.
Private Sub CommandButton1_Click()
' Mass Goal Seek
Dim Taddr, Gaddr, Aaddr As Range
Dim currPart As String
Dim MaxParts, prt As Integer
Dim ARange, TRange, GRange As Range
Dim NumEq, i As Long
MaxParts = 15
For prt = 1 To MaxParts
currPart = Worksheets("Data Entry").Range("Header")(prt)
Worksheets("Item Data").Range("prt_2").Value = prt
Set Taddr = ThisWorkbook.Names("TRange").RefersToRange
Set Aaddr = ThisWorkbook.Names("ARange").RefersToRange
Set Gaddr = ThisWorkbook.Names("GRange").RefersToRange
If Worksheets("Data Entry").Range("Header")(prt) Like "Molding***" Then
Exit Sub
End If
NumEq = Aaddr.Rows.Count
For i = 1 To NumEq
'MsgBox ("The Part Number is: " & currPart & " The Value is: " & Taddr(i).Value)
If Gaddr(i).Value <> "" Then
Taddr(i).GoalSeek goal:=Gaddr(i), changingcell:=Aaddr(1)
Gaddr(i).Value = ""
End If
Next i
Next
End Sub
The line with the goal seek always errors and I have tried many different syntax lines.
It gives a
Run-time error '1004': Application-defined or object-defined error.
You are getting Error '1004': Application-defined or object-defined error because the GoalSeek cell Taddr(i) must contain a formula that refers directly or indirectly to the ChangingCell Aaddr(1)
I would recommend stepping through your code and checking if
Taddr(i) refers to the cell you think it should refer to
It contains a formula which directly/indirectly refers to ChangingCell
Here is a simple way to reproduce the error
Sub Sample()
Range("A10").GoalSeek Goal:=100, ChangingCell:=Range("A1")
End Sub
Here A10 doesn't have any formula.
Now let's add a formula to A10 referring to A1 and run the same code

Resources