0

I use On Error Resume Next too much in my VBA. It's a lazy habit.

The following will autofit certain columns if the sheet has not already been deleted from the workbook - if it has been deleted then an error is raised and the compiler moves to the next line of code.

What other approach can I use to achieve the same result?

On Error Resume Next
    bkExampleWorkbook.Sheets("Foo").Columns("E:G").AutoFit
    bkExampleWorkbook.Sheets("Bar").Columns("K:M").AutoFit
On Error GoTo 0
Community
  • 1
  • 1
whytheq
  • 34,466
  • 65
  • 172
  • 267
  • 2
    I like your idea and I would stick to it. If there is any reason that you have to change it I would possibly use `for` loop which would check each existing sheet name. If names of sheets match than appropriate columns would be deleted. I don't provide code as I don't consider it very effective. – Kazimierz Jawor Mar 18 '13 at 10:57
  • 2
    I agree with Kee Jaw. This error handling code is close to the *standard* way of running it. A little tidier to set a `Set ws = sheets("Foo")` object then test `If Not Ws is Nothing Then ws.Columns("E:G").AutoFit` etc. – brettdj Mar 18 '13 at 11:25
  • 1
    @brettdj ..._standards_ in _Excel-VBA_ !! I'll explore using your tidier method. – whytheq Mar 18 '13 at 12:07
  • Duplicate of [Excel VBA If WorkSheet("wsName") Exists](http://stackoverflow.com/questions/6040164/excel-vba-if-worksheetwsname-exists). See Tim William's answer. – brettdj Mar 18 '13 at 22:15
  • @brettdj ...I've ended up using a loop in order to avoid having to test for an error: the reference to an existing answer is therefore not needed – whytheq Mar 19 '13 at 20:31
  • The looping answer was also in that thread. – brettdj Mar 19 '13 at 21:20

1 Answers1

4

Assuming you are working with the same sheet names and only want to resize them if they exist you can start with a function to make it easy to see if they exist and resize them if they do:

The basics

Function AutoFitSheetRange(objWorkBook As Workbook, _
                           strSheetName As String, _
                           strSheetRange As String) As Boolean

    Dim sheet As Worksheet, boolSheetFound As Boolean
    For Each sheet In objWorkBook.Worksheets
        If sheet.Name Like strSheetName Then
            boolSheetFound = True
            Exit For
        End If
    Next
    If boolSheetFound Then
        objWorkBook.Sheets(strSheetName).Range(strSheetRange).AutoFit
        AutoFitSheetRange= True
    Else
        AutoFitSheetRange= False
    End If
End Function

Using it

You can then loop over your sheets in whatever way suits you to resize a specific range (and shorthand it as columns):

AutoFitSheetRange bkExampleWorkbook, "Foo", "E:G"
AutoFitSheetRange bkExampleWorkbook, "Bar", "K:M"

Not forgetting to add error handling

You don't want to get rid of error handling but you want the function to make sure you still handle errors but more elegantly than On Error Resume Next which can cause undesirable results:

'Error Handled version
Function AutoFitSheetRange(objWorkBook As Workbook, _
                           strSheetName As String, _
                           strSheetRange As String) As Boolean
On Error Goto AutoFitSheetRangeError

    Dim sheet As Worksheet, boolSheetFound As Boolean
    For Each sheet In objWorkBook.Worksheets
        If sheet.Name Like strSheetName Then
            boolSheetFound = True
            Exit For
        End If
    Next

    If boolSheetFound Then 'Resize the range!
        objWorkBook.Sheets(strSheetName).Range(strSheetRange).AutoFit
        AutoFitSheetRange = True
    Else
        AutoFitSheetRange = False
    End If

Exit Function ' No error hit so exit

AutoFitSheetRangeError:
    AutoFitSheetRange = False
    Debug.Print Err.Message 'Print out the debug error
End Function

Flexible error responses!

This gives you the flexibility to then see if the columns were resized regardless of errors occuring and so making future decisions easier:

If AutoFitSheetRange(bkExampleWorkbook, "Foo", "E:G") Then
    MsgBox "I couldn't resize Foo! Doing nothing."
End If
If AutoFitSheetRange(bkExampleWorkbook, "Bar", "K:M") Then
    'Do something here
End If

I haven't had the chance to test this myself but let me know how it goes.

Edit:

In light of a comment by @brettdj, I thought it best to separate the function for checking sheet existance to make it a little more concise. If all you want to do is check a sheet exists then this function is more than enough:

'Error Handled version
Function SheetExists(objWorkBook As Workbook, strSheetName As String) As Boolean
On Error Goto SheetExistsError

    Dim sheet As Worksheet 
    For Each sheet In objWorkBook.Worksheets
        If sheet.Name Like strSheetName Then
            SheetExists = True
            Exit Function
        End If
    Next

SheetExistsError:
    SheetExists = False
    Debug.Print "Couldn't find sheet " & Err.Description 'Print out the debug error
End Function
Tom 'Blue' Piddock
  • 2,131
  • 1
  • 21
  • 36
  • This is a long way to test for existence. – brettdj Mar 18 '13 at 11:24
  • @brettdj, the only part that actually tests for existance is `If sheet.Name Like strSheetName Then boolSheetFound = True Exit For End If` I just like encapsulating things properly and note leaving incomplete code/logic. – Tom 'Blue' Piddock Mar 18 '13 at 12:20
  • @blue You are looping through every worksheet if no match is found - needless looping is a long route to go. – brettdj Mar 18 '13 at 12:48
  • 1
    @brettdj I understand the ideal of not looping needlessly but if you need to ensure that something exists or not and prefer to not ignore every error that can occur then it wouldn't be needless looping. It may be a long routed way but it is a secure way which allows for proper error handling. Using `On Error Resume Next` will not allow you to do this. I'll swap a negligible efficiency difference for the ability to capture errors any day. – Tom 'Blue' Piddock Mar 18 '13 at 13:02
  • I think this approach is ok - but it depends on the context. For my purpose it seems ok as there are a maximum of about 10 sheets in each book ...so no massive efficiency loss. I have one routine which creates 50 workbooks - each with over 50 worksheets - I'll not implement this solution there! – whytheq Mar 18 '13 at 13:34
  • 1
    @whytheq I just tested it on a workbook with 150 sheets with 1000x1000 cells of string data. Once with "Sheet75" the other with "WhiteTolietSheetPaper". Both returned in under 1 ms. You'll be absolutely fine using this on 50 worksheets plus. – Tom 'Blue' Piddock Mar 18 '13 at 13:55
  • @Blue thanks for testing - the big program isn't broken (so I'll not bother fixing for now) but I will use this answer in the report I'm currently upgrading – whytheq Mar 18 '13 at 14:06
  • Awesome, glad it helped. Don't forget to accept if it works for you. :) – Tom 'Blue' Piddock Mar 18 '13 at 15:27
  • @Blue, I think you misunderstand me. Your code is a lengthy solution (lines of code) to what is normally handled by testing for not nothing, or an error message. See [here](http://www.rondebruin.nl/exist.htm), [here2](http://www.cpearson.com/excel/SheetNameFunctions.aspx) – brettdj Mar 18 '13 at 22:14
  • @brettdj I understand the usage of `On Error Resume Next` being a standard use solution and only taking up 4 lines of code. However @whytheq asked for a solution specifically without checking for an error as it says in the title, which is exactly what I gave in a short and (even with a for loop) incredibly efficient error handled solution. I still feel that testing for an error to occur is the wrong way to approach a problem if there is an easy alternative. – Tom 'Blue' Piddock Mar 19 '13 at 11:00