1

I am new to VBA (and Excel for that matter) so please keep that in mind when reviewing my code. This is also my first post here!

I am trying to complete and refine my file, but I have run into a error that I cannot seem to fix or even understand. I have searched this site (and many others) and found many people with this same error, but their resolutions are irrelevant and/or don't solve my problem.

This is the error I receive:

Error Message

"Automation Error. The object invoked has disconnected from its clients."

If I click debug, end, or help, Excel crashes and (sometimes) reopens an recovered file. SO frustrating!

I have managed to locate the line of code that causes this:

templateSheet.Copy After:=indexSheet

templateSheet and indexSheet are defined references to specific worksheets

The gist of what happens within this part of my file:

I've created a userform and a form control button. The button shows the userform. The userform has two fields asking the user to enter names. The code (all in the userform) checks all worksheet names.

  1. If the name exists, it tells the user to choose a different name.
  2. If the name doesn't exist, a hidden template sheet (templateSheet) is copied and pasted after the homepage sheet (indexSheet) and renamed based on the user input.
  3. A table on the homepage gets a new row and a hyperlink to the new sheet is added.
  4. There is additional code that adds values to cells on multiple sheets and formats that text.

All of this works perfectly for 21 runs. On the 22nd run, without fail, the automation error pops up and Excel crashes.

This happens on windows with Excel 2010, 2011, and 2016 (I've yet to test other versions on Excel) on a range of Windows versions. Bizzarly, the file works PERFECTLY on my 2013 MacBook pro with Excel 2011.. no errors at all.

The code I provide at the end of this post is the majority of the code within the file. At first, I thought it may be a memory issue but I think this is a pretty simple file, something excel and my desktop should be able to handle.

What I've done so far to try to fix it:

  • Option explicit
  • Keep templateSheet visible at all times
  • Create a separate Excel template file and call that from the userform
  • Changed .Activate and .Select to defined ranges
  • Copy and paste the new template sheet without specifying where to put it
  • Made sure all calls to sheets included specific "path" (ThisWorkbook.)

Inefficient workaround:

The only thing that prevents this error is code to save, close, and reopen the file. Obviously, this is time consuming and not efficient. I found this code online:

    wb.Save
    Application.OnTime Now + TimeValue("00:00:01"), Application.Workbooks.Open(filePath)
    wb.Close (True)

Finally:

As I stated, I am new to VBA, coding, and this site. Any suggestions to my code, relevant to this issue or not, are greatly appreciated. I have included all the code from my UserForm.

Private Sub OkButton_Click()

'Dont update the screen while the macro runs
Application.ScreenUpdating = False

    'Sheet and workbook variables
    Dim wb As Workbook
    Dim indexSheet As Worksheet, templateSheet As Worksheet
    Dim templateCopy As Worksheet, newSheet As Worksheet

    'Table and new row variables
    Dim Tbl As ListObject
    Dim NewRow As ListRow

    'Variables to group shapes based on
    'need to hide or show them
    Dim hideShapes() As Variant, showShapes() As Variant
    Dim hideGroup As Object, showGroup As Object

    'Misc variables
    Dim i As Integer
    Dim exists As Boolean
    Dim filePath As String

    'Variables to assign ranges
    Dim scenarioRng As Range
    Dim traceabilityFocus As Range
    Dim testCaseRng As Range
    Dim statusRng As Range
    Dim newSheetTestCaseRng As Range
    Dim newSheetStatusRng As Range
    Dim newSheetFocus As Range
    Dim newSheetDateRng As Range

    'Create array of shapes based on visibility rules
    hideShapes = Array("TextBox 2", "Rectangle 1")
    showShapes = Array("TextBox 15", "TextBox 14", "TextBox 13", "TextBox 11", "StatsRec", "Button 10")

    'To reference Traceability Matrix sheet
    Set indexSheet = ThisWorkbook.Sheets("Traceability Matrix")
    'To reference Template sheet
    Set templateSheet = ThisWorkbook.Sheets("TestCase_Template")
    'To reference traceability matrix table
    Set Tbl = indexSheet.ListObjects("TMatrix")
    'Set hideShapes to a hide group
    Set hideGroup = indexSheet.Shapes.Range(hideShapes)
    'Set show shapes to a show group
    Set showGroup = indexSheet.Shapes.Range(showShapes)
    'To reference this workbook
    Set wb = ThisWorkbook
    'Get file path of this workbook and set it to string
    filePath = wb.FullName


    'If the userform fields are empty then show error message
    If ScenarioNameBox.Value = "" Or TestCaseNameBox.Text = "" Then
            MsgBox ("Please complete both fields.")
    'If the userform fields are completed and a worksheet with
    'the same name exists, set boolean to true
    Else
        For i = 1 To Worksheets.Count
        If ThisWorkbook.Worksheets(i).Name = TestCaseNameBox.Value Then
            exists = True
    End If
    'Iterate through all worksheets
    Next i

    'If test case name already exists, show error message
    If exists Then
        MsgBox ("This test case name is already in use. Please choose another name.")
    'If test case name is unique, update workbook
    Else
        'Copy template sheet to after traceability matrix sheet
        templateSheet.Copy After:=indexSheet 'LOCATION OF ERROR!!!
        'Ensure template sheet is hidden
        templateSheet.Visible = False

        'To reference copy of template
        Set templateCopy = ThisWorkbook.Sheets("TestCase_Template (2)")

        'Rename template sheet to the test case name
        templateCopy.Name = TestCaseNameBox.Value
        'To reference re-named template sheet
        Set newSheet = ThisWorkbook.Sheets(TestCaseNameBox.Value)
        'Show new sheet
        newSheet.Visible = True

        'Set focus to traceability matrix
        Set traceabilityFocus = indexSheet.Range("A1")

        'Add a new row
        Set NewRow = Tbl.ListRows.Add(AlwaysInsert:=True)

        'Set ranges for cells in traceability table
        Set scenarioRng = indexSheet.Range("B" & NewRow.Range.Row)
        Set testCaseRng = scenarioRng.Offset(0, 1)
        Set statusRng = testCaseRng.Offset(0, 1)

        'Set scenario cell with name and format
        With scenarioRng
            .FormulaR1C1 = ScenarioNameBox.Value
            .HorizontalAlignment = xlGeneral
            .Font.Name = "Arial"
            .Font.Size = 12
        End With

        'Set test case cell with name, hyperlink to sheet, and format
        With testCaseRng
            .FormulaR1C1 = TestCaseNameBox.Value
            .Hyperlinks.Add Anchor:=testCaseRng, Address:="", SubAddress:=newSheet.Name & "!A1", TextToDisplay:=newSheet.Name
            .HorizontalAlignment = xlGeneral
            .Font.Name = "Arial"
            .Font.Size = 12
        End With

        'Set trial status as Incomplete and format
        With statusRng
            'Set new test case to "Incomplete"
            .Value = "Incomplete"
            .Font.Name = "Arial"
            .Font.Size = 12
            .Font.Color = vbBlack
        End With

        'Show or hide objects
        hideGroup.Visible = False
        showGroup.Visible = True

        'Set ranges for cells in test case table
        Set newSheetTestCaseRng = newSheet.Range("C2")
        Set newSheetStatusRng = newSheet.Range("C12")
        Set newSheetDateRng = newSheet.Range("C5")

        'Insert test case name into table
        newSheetTestCaseRng.Value = TestCaseNameBox.Value
        'Add todays date to Date Created
        newSheetDateRng.Value = Date
        'Set status to "Incomplete"
        newSheetStatusRng.Value = "Incomplete"
        'End with cursor at beginning of table
        newSheet.Activate
        Range("C3").Activate


        'wb.Save
        'Application.OnTime Now + TimeValue("00:00:01"), Application.Workbooks.Open(filePath)
        'wb.Close (True)


        'Close the userform
        Unload Me

        End If

    End If

    'Update screen
    Application.ScreenUpdating = True

End Sub

===========================================================================

Update:

Using the code provided by @DavidZemens the error acts differently. Normally, the userform closes after each sheet is created. @DavidZemens suggested leaving the form open so the user can make as many sheets as they need in one go. This method allows me to create a seemingly unlimited amount of sheets WITHOUT error. Read: at the 22 sheet mark, there is no error.

However, if I manually close the userform after making more than 22 sheets and then reopen it to create a new sheet, the automation error pops up again and excel crashes.

The new code that causes this error is here:

 With templateSheet
        .Visible = xlSheetVisible
        .Copy Before:=indexSheet 'ERRORS HERE!!
        .Visible = xlSheetVeryHidden

Another thing worth mentioning: In the project explorer it lists all my sheets with their names. But, there are extra sheets in there that have the workbook icon next to them. I did not create any of there workbooks or worksheets and my macros do not create or even call any workbook other than ThisWorkbook.

Community
  • 1
  • 1
Ryan
  • 13
  • 1
  • 5
  • Quick test - just try `Sheets("TestCase_Template").Copy after:=Sheets("Traceability Matrix")` and see if that works? – BruceWayne Apr 27 '17 at 16:34
  • When I use `Sheets("TestCase_Template").Copy after:=Sheets("Traceability Matrix")` I get the same automation error and excel crashes. If I do just `Sheets("TestCase_Template").Copy Sheets("Traceability Matrix")` I get "Run-time error '-2147417848 (80010108)': Method 'Copy' of object '_Worksheet' failed." but Excel does NOT crash @BruceWayne – Ryan Apr 27 '17 at 16:58
  • Does this help? http://stackoverflow.com/questions/17302918/excel-vba-automation-error-the-object-invoked-has-disconnected-from-its-clients – SJR Apr 27 '17 at 17:14
  • Does seem reminiscent of memory errors I had while copying sheets in Excel 2003 *yeeeears* ago. I don't think it should be necessary to Save/Close/Reopen the file, but it may be necessary to periodically *Save* the file. Also, try moving the `Unload Me` to after the call to `ScreenUpdating` at the very end of the procedure. Just a thought. – David Zemens Apr 27 '17 at 17:18
  • Also, you've assigned `Set wb=ThisWorkbook` but many points in your code refer to `ThisWorkbook` rather than the variable `wb`. While there may be reason for this in some cases, usually I would say go with one or the other but not mixed. – David Zemens Apr 27 '17 at 17:19
  • `newSheet` and `templateCopy` also appear to refer to the same object. I have some ideas to tweak your code, will post answer and see if that helps. – David Zemens Apr 27 '17 at 17:24
  • @SJR Unfortunately, those solutions do not work in my case. – Ryan Apr 27 '17 at 17:25
  • @DavidZemens Thanks! I updated my code with your suggestions. Good to know, but doesn't fix my problem. I wondered if somehow I had referenced a different workbook, object, or whatever without knowing. That's what led me to include Option Explicit and ThisWorkbook to all my sheet calls. That's about the extent of my knowledge with that so I look forward to seeing what you come up with. – Ryan Apr 27 '17 at 17:31

3 Answers3

0

I don't have any idea if this will solve the problem, but I tried to clean up the code a bit. See if this helps. I created about 28 sheets without any error.

There is some consolidation/cleanup but I wouldn't expect that to be substantial. However, I did remove the call to Unload Me which isn't strictly necessary (the user can always close out of the form manually, and by omitting that line we also allow the user to create as many sheets as he or she wants without having to launch the form anew each time).

Option Explicit
Private Sub OkButton_Click()

'Dont update the screen while the macro runs
Application.ScreenUpdating = False

    'Sheet and workbook variables
    Dim wb As Workbook
    Dim indexSheet As Worksheet, templateSheet As Worksheet
    Dim templateCopy As Worksheet, newSheet As Worksheet

    'Table and new row variables
    Dim Tbl As ListObject
    Dim NewRow As ListRow

    'Variables to group shapes based on
    'need to hide or show them
    Dim hideShapes() As Variant, showShapes() As Variant
    Dim hideGroup As Object, showGroup As Object

    'Misc variables
    Dim i As Integer
    Dim exists As Boolean
    Dim filePath As String

    'Variables to assign ranges
    Dim scenarioRng As Range
    Dim traceabilityFocus As Range
    Dim testCaseRng As Range
    Dim statusRng As Range
    Dim newSheetTestCaseRng As Range
    Dim newSheetStatusRng As Range
    Dim newSheetFocus As Range
    Dim newSheetDateRng As Range

    'Create array of shapes based on visibility rules
    hideShapes = Array("TextBox 2", "Rectangle 1")
    showShapes = Array("TextBox 15", "TextBox 14", "TextBox 13", "TextBox 11", "StatsRec", "Button 10")
    'To reference this workbook
    Set wb = ThisWorkbook
    'To reference Traceability Matrix sheet
    Set indexSheet = wb.Sheets("Traceability Matrix")
    'To reference Template sheet
    Set templateSheet = wb.Sheets("TestCase_Template")
    'To reference traceability matrix table
    Set Tbl = indexSheet.ListObjects("TMatrix")
    'Set hideShapes to a hide group
    Set hideGroup = indexSheet.Shapes.Range(hideShapes)
    'Set show shapes to a show group
    Set showGroup = indexSheet.Shapes.Range(showShapes)
    'Get file path of this workbook and set it to string
    filePath = wb.FullName

    'If the userform fields are empty then show error message
    If ScenarioNameBox.Value = "" Or TestCaseNameBox.Text = "" Then
            MsgBox "Please complete both fields."
            GoTo EarlyExit
    'If the userform fields are completed and a worksheet with
    'the same name exists, set boolean to true
    Else
        On Error Resume Next
        Dim tmpWS As Worksheet
        ' This will error if sheet doesn't exist
        Set tmpWS = wb.Worksheets(TestCaseNameBox.Value)
        exists = Not (tmpWS Is Nothing)
        On Error GoTo 0
    End If

    'If test case name already exists, show error message
    If exists Then
        MsgBox "This test case name is already in use. Please choose another name."
        GoTo EarlyExit
    'If test case name is unique, update workbook
    Else
        'Copy template sheet to after traceability matrix sheet
        With templateSheet
            .Visible = xlSheetVisible
            .Copy Before:=indexSheet
            .Visible = xlSheetVeryHidden
        End With
        Set newSheet = wb.Sheets(indexSheet.Index - 1)
        With newSheet
            newSheet.Move After:=indexSheet
            'Rename template sheet to the test case name
            .Name = TestCaseNameBox.Value
            'To reference re-named template sheet
            .Visible = True
            'Set ranges for cells in test case table
            Set newSheetTestCaseRng = .Range("C2")
            Set newSheetStatusRng = .Range("C12")
            Set newSheetDateRng = .Range("C5")

            'Insert test case name into table
            newSheetTestCaseRng.Value = TestCaseNameBox.Value
            'Add todays date to Date Created
            newSheetDateRng.Value = Date
            'Set status to "Incomplete"
            newSheetStatusRng.Value = "Incomplete"
            'End with cursor at beginning of table
            .Activate
            .Range("C3").Activate
        End With

        'Set focus to traceability matrix
        Set traceabilityFocus = indexSheet.Range("A1")
        'Add a new row
        Set NewRow = Tbl.ListRows.Add(AlwaysInsert:=True)
        'Set ranges for cells in traceability table
        Set scenarioRng = indexSheet.Range("B" & NewRow.Range.Row)
        Set testCaseRng = scenarioRng.Offset(0, 1)
        Set statusRng = testCaseRng.Offset(0, 1)

        'Set scenario cell with name and format
        With scenarioRng
            .FormulaR1C1 = ScenarioNameBox.Value
            .HorizontalAlignment = xlGeneral
            .Font.Name = "Arial"
            .Font.Size = 12
        End With

        'Set test case cell with name, hyperlink to sheet, and format
        With testCaseRng
            .FormulaR1C1 = TestCaseNameBox.Value
            .Hyperlinks.Add Anchor:=testCaseRng, Address:="", SubAddress:=newSheet.Name & "!A1", TextToDisplay:=newSheet.Name
            .HorizontalAlignment = xlGeneral
            .Font.Name = "Arial"
            .Font.Size = 12
        End With

        'Set trial status as Incomplete and format
        With statusRng
            'Set new test case to "Incomplete"
            .Value = "Incomplete"
            .Font.Name = "Arial"
            .Font.Size = 12
            .Font.Color = vbBlack
        End With

        'Show or hide objects
        hideGroup.Visible = False
        showGroup.Visible = True

        wb.Save
    End If

EarlyExit:
    'Update screen
    Application.ScreenUpdating = True

End Sub
David Zemens
  • 53,033
  • 11
  • 81
  • 130
  • Wow! I really appreciate your help. Good call on removing the `Unload Me`. Thanks for making things a little more sophisticated! I'll post again if it fixes the bug. – Ryan Apr 27 '17 at 19:20
  • So this code ALMOST fixes my problem. When I leave the userform button open (as implemented by you) to create sheet after sheet, the error does not come up and the file does not crash. However, if I create more than 22 sheets and then manually close the userfrom, reopen it, and use it to create another sheet, I get the automation error again. Any ideas? – Ryan Apr 28 '17 at 13:53
  • @Ryan not particularly :( Two things you could try: Run the [compatibility check](http://stackoverflow.com/a/35004911/1467082) and disable calculation during runtime with `Application.Calculation = xlCalculationManual` at the beginning of the procedure. Remember to set it back to `xlCalculationAutomatic` before exiting the sub. – David Zemens Apr 28 '17 at 15:02
  • @Ryan can you also show the code for "The button shows the userform"? I don't suspect that to be a problem but you never know, and there may be different way to handle that form. – David Zemens Apr 28 '17 at 15:03
  • The compatibility does not work. The entire code for the button is just `TestCaseUserForm.Show`. I'm thinking I'll find the root of the problem if I can figure out why my project explorer is showing non-existent workbooks that I did not create. – Ryan Apr 28 '17 at 15:23
  • Hmmm yes that could contribute to a problem for sure. Have you rebooted? If not, try that and keep an eye on that Project Explorer window and see if the same sort of phantom workbooks start appearing. You could even add a breakpoint in the code to Break when `Application.Workbooks.Count > 1` (obviously this requires testing with no other workbooks open). – David Zemens Apr 28 '17 at 15:36
  • Only other thing I might suggest is that in your button event, do: `Dim uf as New TestCaseUserForm: uf.Show`. I'm not sure if `New`ing up your userform would help but it's worth trying at least. – David Zemens Apr 28 '17 at 15:37
  • I found a solution to the problem, sort of... I decided to create a new Excel file, format it how I wanted it look, then copy and paste all my/your code into the new file. I completed all of this without switching to a different computer. Now, no matter what machine or version I'm using, the error doesn't show up. I'm not exactly sure why this worked because I didn't alter any code. The problem obviously has something to do with switching computers while building the code/file. Beyond that, I can't explain it. Regardless, thank you for all your help. I hope this "solution" helps others in need – Ryan May 02 '17 at 17:10
  • @Ryan it's sometimes the case that a file, or vb code modules become corrupted, and when this happens, strange errors (like the one you've seen) are often a symptom. When all else fails, and I can't believe I didn't think to mention this, I recreate the file from scratch (like you did) and usually the error no longer occurs. Cheers. – David Zemens May 02 '17 at 17:13
0

hope this helps - I was updating a table with UserForm but at the same time had a named range defined which was reading the column values from the same table using INDIRECT. After removing the named range all works fine.

0

If you tried everything reasonable in your code and still has the error... Try the following solution I found in internet, running compatibility troubleshooter (worked in my case):

  1. Open MS Excel (Any File or new file)
  2. Pull up Task Manager (using <Ctrl + alt + del>)
  3. Click on MS Office or Excel Icon in Background Processes, Right click, and select properties
  4. Under Compatibility, Click "Run Compatibility Troubleshooter"
  5. When finished running, test file again (press testing button), if it works right, click apply settings to this program. If it doesn't work, click next and choose from the options. (I chose that it worked in previous version of Windows (Windows 7) Then click Next again.
  6. Test file again, and it worked.

I hope it helps.

Marcelo
  • 1
  • 1