3

In the context of an error handling code, I would like to verify if the user has given to the current sheet the same name of another one into the same workbook (action forbidden, of course). So the way I intuitively tried to verify this was simply to loop through all the sheets and comparing the names:

For Each sh In ThisWorkbook.Sheets
    If sh.Name = ThisWorkbook.ActiveSheet.Name Then
        'error handling here
    End If
Next sh

However, this is a huge logic fall in the case when:

1) The user is editing, let's say, the sheet number 3; 2) The sheet with the same name is at the position number 5;

In that case, the condition sh.Name = ThisWorkbook.ActiveSheet.Name would be met for sure because the sheet is compared to itself.

So, I wonder: how to understand if sh is not ThisWorkbook.ActiveSheet?

I had thought the task it could have simply been solved with a simple object comparison:

If (sh Is Not ThisWorkbook.ActiveSheet) And (sh.Name = ThisWorkbook.ActiveSheet.Name) Then

but this raises a compile error, namely Object does not support this property or method. Could anyone please help me finding the lack of logic in my code's structure?

OTHER INFORMATION

I have tried to manage the case through the Err.Description and the Err.Number, but the first is OS-language dependent and the second is the same for other types of error I need to handle differently.

Moreover, the sheets (names and contents) are contained into a .xlam add-in so the user can change the contents through custom user-forms but not through the Excel Application.

More in general, let's say that I would like to know how can I perform the comparison, even if a work-around in this specific case is possible, in order to use this method for future developments I already plan to do and that cannot be managed through the default VBA error handler.

Matteo NNZ
  • 11,930
  • 12
  • 52
  • 89
  • Is the user giving "the same name to another sheet" in VBA code or through manual input? Because manual input gives you an error: _"That sheet name is already in use. Enter a sheet name that is not in use by another sheet."_ – Chrismas007 Jan 06 '15 at 15:14
  • @Christmas007, The name is input through a textbox on a UserForm, and updates itself into the `TextBox_Change` event. I have already tried managing through the `Err.Description` but the message is raised into the OS language and this would cause cross-languages issues. Tried also through the error-code, but it's the same of other cases that must be managed differently. Moreover, I'd just like to know how to properly compare the two objects because I will need it furtherly when no specific error is raised. – Matteo NNZ Jan 06 '15 at 15:20
  • 1
    @GeneSkuratovsky please read my above comment for better understanding of the context. The sheets are contained into an Add-In so the user changes names and contents of the sheet through user-forms, while never seeing the sheet on the desktop. That's (unfortunately) why I need to build a custom error handler :( – Matteo NNZ Jan 06 '15 at 15:21
  • Does the userform change the name of the Active (at that very moment) sheet? – Gene Skuratovsky Jan 06 '15 at 15:27
  • @GeneSkuratovsky, yes, exactly. It starts with an `On Error GoTo Handler` and then changes the name, so if we enter the handler is because an error occurred. Even in this case, as I wrote to RubberDuck, I know I might just perform the check first and change the name then, but I'd like to avoid work-arounds and rather know if there's a direct way to perform an object instance comparison. – Matteo NNZ Jan 06 '15 at 15:31
  • 1
    Just realized that there's a bug in your logic: "The user is editing, let's say, the sheet number 3; 2) ***The sheet with the same name** is at the position number 5*" It's impossible to create two or more sheets with the same name. – Maciej Los Jan 06 '15 at 16:40
  • @MaciejLos, you're perfectly right, I have just realized this. Well, I'd say that I leave this question just for the precious content you and two other users have added to it, but I agree on the fact that otherwise it wouldn't have reason to exist! – Matteo NNZ Jan 06 '15 at 17:11
  • @MatteoNNZ, i didn't say: delete this question ;) Cheers, Maciej. – Maciej Los Jan 06 '15 at 21:36

3 Answers3

4

Just check the index of the worksheet along with the name. Only error (or whatever) if the name matches, but the index doesn't.

Option Explicit

Public Sub test()
    Dim wb As Workbook
    Dim ws As Worksheet

    Set wb = ThisWorkbook
    Set ws = wb.ActiveSheet

    Dim wsToCheck As Worksheet
    For Each wsToCheck In wb.Worksheets
        If ws.Name = wsToCheck.Name And ws.Index <> wsToCheck.Index Then
            'do something
        End If
    Next
End Sub

Of course, you could always just test for object equality using the Is operator too, or inequality in your specific case.

Public Sub test2()
    Dim wb As Workbook
    Dim ws As Worksheet

    Set wb = ThisWorkbook
    Set ws = wb.ActiveSheet

    Dim wsToCheck As Worksheet
    For Each wsToCheck In wb.Worksheets
        If Not ws Is wsToCheck Then
            'do something
            Debug.Print ws.Name
        End If
    Next
End Sub
Community
  • 1
  • 1
RubberDuck
  • 11,933
  • 4
  • 50
  • 95
  • Very bright move, cannot deny an upvote. However, I'd still like to know if it's possible to perform an instance comparison. What I mean is that `sh` and `ThisWorkbook.ActiveSheet` might turn to be the same object instance. I will accept this answer lately if we don't discover how to perform the comparison I was asking for. Thanks a lot for your time :) – Matteo NNZ Jan 06 '15 at 15:29
  • 1
    Well, it turned it was just a stupid syntax error, I was writing `sh Is Not` instead of `Not sh Is`. I have suggested this edit and accepted your answer as it fully answers my question! – Matteo NNZ Jan 06 '15 at 15:36
  • I am upvoting your answer for the second (excellent) answer. However the first part might fail in case we have two identical workbooks and the queried worksheets are respective sheets from those two workbooks (they'll have the same name and index, **but** different workbooks behind). – Ister Feb 21 '18 at 09:35
4

You've got an incorrect syntax with "Not"; it should be this:

If (Not sh Is ThisWorkbook.ActiveSheet) And (sh.Name = ThisWorkbook.ActiveSheet.Name) Then
RubberDuck
  • 11,933
  • 4
  • 50
  • 95
-1

There's no reason to loop through the collection of sheets. Use this:

Function IsWshExists(ByVal wbk As Workbook, ByVal wshName As String) As Boolean
Dim wsh As Worksheet

On Error Resume Next
Set wsh = wbk.Worksheets(wshName)

IsWshExists = (Err.Number = 0)

Set wsh = Nothing
End Function

Usage:

If Not IsWshExists(ThisWorkbook, "Sheet2") Then 
    'you can add worksheet ;)
    'your logic here
End If
Maciej Los
  • 8,468
  • 1
  • 20
  • 35
  • 2
    It works, but relying on an error handler and resuming next is pretty dang hacky. – RubberDuck Jan 06 '15 at 15:40
  • 1
    Mmm, this lacks a bit actually. If I pass an empty string as name, the function will tell me the worksheet exists while this is not true, won't it? – Matteo NNZ Jan 06 '15 at 15:43
  • Ha, ha, ha! @RubberDuck, using "Resume Next" isn't "dang hacky" (whatever it means), but pretty good programming practice. There is only one condition: the programmer must be consious of usage such of trick. – Maciej Los Jan 06 '15 at 15:45
  • If you are going to write `On Error Resume Next` you better turn it off when you are done with that one error handling instance... `On Error GoTo 0`... – Chrismas007 Jan 06 '15 at 15:46
  • 1
    The general error handling approach Maceej Los is okay - but you should test for `If Not wsh is Nothing` etc, Matteo NNZ raises a fair point as the way you have run this – brettdj Jan 06 '15 at 15:47
  • No, @Chrismas007, because the code does not need to fired again in case of error. – Maciej Los Jan 06 '15 at 15:48
  • When put into a larger sub, you need to turn error checking back on. – Chrismas007 Jan 06 '15 at 15:49
  • 1
    @Chrismas007 he actually doesn't need to in this case, but yes. What you are saying is best practice in general. – RubberDuck Jan 06 '15 at 15:49
  • @brettdj, there is no reason to check if wsh is nothing. Function will return false if worksheet does not exists (even if empty string has been passed). – Maciej Los Jan 06 '15 at 15:51
  • 1
    @MaciejLos, I really appreciate your time and yours is actually a cool approach for many problems. What I mean is just that, in my context, I need to know if another sheet with the same name exists. Your function would work perfectly fine in that case, but it would raise the same result (i.e. Existing) even if I pass an invalid name such as an empty string or a string containing a special character like *, : etc. You see my point? :) – Matteo NNZ Jan 06 '15 at 15:53
  • @MatteoNNZ, not sure... If i understand you well, you want to check if worksheet exists (by its name) and nothing else. Probably, you need to check if workseet with given name exists, before you change its name. Is there anything what i missed? – Maciej Los Jan 06 '15 at 16:18