Excel Macro VB Run-time error: Automation Error [duplicate] - vba

I know I've seen references to this issue before, but I have tried several of the suggestions and I am still getting the error. I have a workbook that assembles data from another book and generates a report. I then want to make a new workbook, copy the report information into the new book, save the new book and close it, and then move on to the next report. It should do this around 10 times. In the part of my code where I am copying and pasting the sheets, I am getting an error
Error -2147417848 Automation error The object invoked has
disconnected from its clients
I have checked other postings about this error, and tried the suggested solutions without any results. the interesting thing is that sometimes it will make it through 5 cycles of code before breaking, sometimes only 2. The only consistency is that it always breaks in the same place
fromBook.Sheets("Report").Copy Before:=newBook.Sheets("Sheet1")
I have option Explicit at the top of the module, and I have checked to make sure that there are not any globals inside of the sub it is breaking in. That being said, It's entirely possible I have overlooked something. I also put a "timer" in at one point to make sure that the excel sheets were not walking over each other.
I could really use the help!
Here is my sub's code:
Sub CreateAndSave(ByRef Reg As Integer, ByVal j As Integer)
Dim fromBook As Workbook
Dim fromSheet As Worksheet
Dim newBook As Workbook
Dim fileExists As Boolean
Dim i As Integer
Dim Holder As Integer
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Set fromBook = Application.Workbooks("Region_Audit_Report")
Set newBook = Workbooks.Add
With newBook
.SaveAs Filename:="G:\DataTeam\ExcelDev\Audit Report\Region Workbooks\Region" & Reg & " " & Month(Date) & "-" & Day(Date) & "-" & Year(Date) & ".xlsx" _
, FileFormat:=xlOpenXMLWorkbook
End With
Set newBook = Application.Workbooks("Region" & Reg & " " & Month(Date) & "-" & Day(Date) & "-" & Year(Date) & ".xlsx")
fromBook.Sheets("Report").Copy Before:=newBook.Sheets("Sheet1")
fromBook.Sheets("MonthData").Copy After:=newBook.Sheets("Report")
newBook.Sheets("MonthData").Range("A1") = "Month"
newBook.Sheets("MonthData").Range("B1") = "Store#"
newBook.Sheets("MonthData").Range("C1") = "District"
newBook.Sheets("MonthData").Range("D1") = "Region"
newBook.Sheets("MonthData").Range("E1") = "Due Date"
newBook.Sheets("MonthData").Range("F1") = "Comp Date"
newBook.Sheets("MonthData").Range("G1") = "# of Errors"
newBook.Sheets("MonthData").Range("H1") = "Late?"
newBook.Sheets("MonthData").Range("I1") = "Complete?"
newBook.Sheets("MonthData").Range("A1:I1").Interior.ColorIndex = 43
newBook.Save
newBook.Close
Application.DisplayAlerts = True
End Sub

I have had this problem on multiple projects converting Excel 2000 to 2010. Here is what I found which seems to be working. I made two changes, but not sure which caused the success:
1) I changed how I closed and saved the file (from close & save = true to save as the same file name and close the file:
...
Dim oFile As Object ' File being processed
...
[Where the error happens - where aArray(i) is just the name of an Excel.xlsb file]
Set oFile = GetObject(aArray(i))
...
'oFile.Close SaveChanges:=True - OLD CODE WHICH ERROR'D
'New Code
oFile.SaveAs Filename:=oFile.Name
oFile.Close SaveChanges:=False
2) I went back and looked for all of the .range in the code and made sure it was the full construct..
Application.Workbooks("workbook name").Worksheets("worksheet name").Range("G19").Value
or (not 100% sure if this is correct syntax, but this is the 'effort' i made)
ActiveSheet.Range("A1").Select

I have just met this problem today: I migrated my Excel project from Office 2007 to 2010. At a certain point, when my macro tried to Insert a new line (e.g. Range("5:5").Insert ), the same error message came. It happens only when previously another sheet has been edited (my macro switches to another sheet).
Thanks to Google, and your discussion, I found the following solution (based on the answer given by "red" at answered Jul 30 '13 at 0:27): after switching to the sheet a Cell has to be edited before inserting a new row. I have added the following code:
'=== Excel bugfix workaround - 2014.08.17
Range("B1").Activate
vCellValue = Range("B1").Value
Range("B1").ClearContents
Range("B1").Value = vCellValue
"B1" can be replaced by any cell on the sheet.

You must have used the object, released it ("disconnect"), and used it again. Release object only after you're finished with it, or when calling Form_Closing.

I had this same problem in a large Excel 2000 spreadsheet with hundreds of lines of code. My solution was to make the Worksheet active at the beginning of the Class. I.E. ThisWorkbook.Worksheets("WorkSheetName").Activate
This was finally discovered when I noticed that if "WorkSheetName" was active when starting the operation (the code) the error didn't occur. Drove me crazy for quite awhile.

Couple of things to try...
Comment out the second "Set NewBook" line of code...
You already have an object reference to the workbook.
Do your SaveAs after copying the sheets.

The error in the below line of code (as mentioned by the requestor-William) is due to the following reason:
fromBook.Sheets("Report").Copy Before:=newBook.Sheets("Sheet1")
The destination sheet you are trying to copy to is closed. (Here newbook.Sheets("Sheet1")).
Add the below statement just before copying to destination.
Application.Workbooks.Open ("YOUR SHEET NAME")
This will solve the problem!!

Related

Macro on called workbook intermittent with it's function

What I have is a macro that is designed to open other workbooks and refresh the contents within those workbooks. All of these work except one of them is intermittent, and by that I mean most times it works exactly as required, but randomly it will bring up an error stating the macro cannot be found. I haven't found so far a point which I can pinpoint where it does this so it has been difficult to debug.
below is the code:
Call Shell("K:\ASA_Reporting\Audits\MDA\ListCompletedAudits.bat")
' This wait has been added to allow the command to run in Console
Application.Wait (Now() + TimeValue("00:00:10"))
ThisWorkbook.Worksheets("Bits n Pieces").Range("G14").Value = "True"
Dim wb1 As Workbook
'This is to update the 5S Audit Dashboard
Set wb1 = Workbooks.Open("K:\ASA_Reporting\Audits\Audit Dashboard v002.xlsb", True, False, , , "password")
Application.Run "'Audit Dashboard v002.xlsb'!Refresh5S"
wb1.Close savechanges:=True
Stop
The point which has a commented out section "This is to update the 5S Audit Dashboard" is the code which is where the issue is occurring. The section above that in regards to the waiting 10 seconds is to correct a different issue which is unrelated to the 5S.
I know that the Macro is correct as it works on the 5S workbook, and it does work most times through my updater, but as I've said on occasion is brings up an error stating the macro does not exist.
I have checked the code what is being called (shown below) but I cannot any errors in this.
Sub Refresh5S()
Application.ScreenUpdating = False
Application.DisplayAlerts = False
Dim datasheet As Worksheet
Set datasheet = ThisWorkbook.Worksheets("Data Sheet")
Dim wb As Workbook
Dim ws As Worksheet
Set wb=Workbooks.Open("\\bosch.com\dfsrb\dfsuk\loc\wo\dept\service\ASA_Reporting\Audits
\5S Audit Master v2.xlsx", True, True)
Set ws = wb.Worksheets("Counts")
datasheet.Range("W6:Z21").Value = ws.Range("B5:E20").Value
datasheet.Range("AB6:AC400").Value = ws.Range("H5:I399").Value
datasheet.Range("AD6:AG400").Value = ws.Range("K5:N399").Value
datasheet.Range("AH6:AH400").Value = ws.Range("O5:O399").Value
wb.Close False
MsgBox "Thank you for your patience." & vbNewLine & vbNewLine & "The figures
should update in a few seconds.", vbInformation
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
I thought I had found the answer on a Microsoft help page titled "Macro in Excel Stops After A Workbook.Open Command" However that was for when you press the shift key, and that is not happening in this instance, it is being left to it's on devices.
https://support.microsoft.com/en-us/help/555263
Does anyone have any idea why it randomly decides the Macro in the 5S workbook doesn't exist?
Edit:
Tried the below and it worked for the day without issue, then today the problem came back with the following error:
The code has not been changed except for the suggestions below, which worked for a day.
The issue was in the end with Excel, as the latest updates of Office have now resolved this issue.

Application-Defined or Object-defined error - Qualifying References Excel

Trying to hammer out bugs in my code. Currently trying to do some very simple, open worksheet, copy and paste data over. Trying to do it all without using .Select or .Activate. Hitting "Application-defined or Object defined error", which, from reading the other threads on the matter, probably means that my statements aren't fully qualified. However, I can't figure out how they're not fully qualified - other posts on the topic seem to be missing a "." somewhere in the code, but my attempts to fix it haven't gotten anywhere. Heavily truncated code as follows (If you don't see it dimmed/defined, it's elsewhere)
Sub CopyPaste()
Dim CitiReportEUR As Workbook
Dim CitiReportPathEUR As String
CitiReportPathEUR = Range("CitiReportPathEUR")
Workbooks.Open Filename:=CitiReportPathEUR
Set CitiReportEUR = ActiveWorkbook
LastRowCiti = CitiReportEUR.Sheets(1).Range("I" & Rows.Count).End(xlUp).Row
Set RngCitiEUR = CitiReportEUR.Sheets(1).Range("A1:CT" & LastRowCiti).SpecialCells(xlCellTypeVisible)
Set CabReport.Sheets("CITI").Range("C1").Resize(RngCitiEUR.Rows.Count).Value = RngCitiEUR.Value
End Sub
Currently the error is occurring when I define the range. I've had problems historically with pasting into the range as well... but that's an issue for when I can actually get the code to run that far!
Rows.Count is implicitly working with the ActiveSheet.
The use of Set when assigning values to the Value property of a Range is inappropriate. Set should only be used when assigning a reference to an object.
The Resize probably needs to cater for the number of columns in the source as well as rows.
This code is more explicit:
Sub CopyPaste()
Dim CitiReportEUR As Workbook
Dim CitiReportPathEUR As String
CitiReportPathEUR = Range("CitiReportPathEUR")
Set CitiReportEUR = Workbooks.Open(Filename:=CitiReportPathEUR)
With CitiReportEUR.Sheets(1)
LastRowCiti = .Range("I" & .Rows.Count).End(xlUp).Row
Set RngCitiEUR = .Range("A1:CT" & LastRowCiti).SpecialCells(xlCellTypeVisible)
End With
CabReport.Sheets("CITI").Range("C1").Resize(RngCitiEUR.Rows.Count, RngCitiEUR.Columns.Count).Value = RngCitiEUR.Value
End Sub

Two issues - saving changes in an instantiated workbook, and activating other workbooks

I have two spreadsheets; I'll call them spreadsheet 1 and spreadsheet 2. Spreadsheet one has a function which generates days of the month, and if it's at the end of the month, it is trying to call the module/sub in spreadsheet 2. This is to generate both "daily" reports and "monthly" reports.
At this point, there are two errors: the first is when I am trying to save the new instance of spreadsheet 2 that I created. The error is that it asks to save the workbook in a macro-free format. I simply want to save it! Not to make any changes to formatting. I am not even sure that it is trying to save changes to the instantiated book object.
the second is in spreadsheet 2, even though I set it to be active sheet (I think), the activesheet still comes up as the worksheet on spreadsheet 1 that runs the macro in the first place.
Any help is appreciated.
Option Explicit
Public Function LastWeekOfMonth() As Boolean
'finds the current date
Dim CurrentDate As Date
CurrentDate = CDate(ActiveSheet.Cells(FIRST_DATA_ROW, 1))
'find filepath and filename of the monthly documentation file
Dim mFilePath As String
Dim mFileName As String
mFilePath = "F:\Project Sweep\Kim Checklist\Barry Polinsky\Brathwaite, Tamika\"
mFileName = Cells(3, 4) & ".m_d.xlsm"
'if it is the last week of the month, write a monthly report, and return true to continue with the face to face paperwork
If (31 - Day(CurrentDate)) <= 7 Then
'write a monthly report
Dim app As New Excel.Application
Dim book As Excel.Workbook
' app.Visible = False 'Visible is False by default, so this isn't necessary
Set book = app.Workbooks.Add(mFilePath & mFileName)
'run the subroutine CheckSpreadsheet in module WriteReport in target book
app.Run "'" & mFilePath & mFileName & "'!" & "WriteReport" & ".CheckSpreadsheet", book
' CheckSpreadsheet (book)
'error next line
book.Save
book.Close
app.Quit
Set app = Nothing
LastWeekOfMonth = True
'if it is not, simply continue with the face to face paperwork
Else
LastWeekOfMonth = False
End If
End Function
In the target worksheet, in module WriteReport, subroutine CheckSpreadsheet, the following code is located.
Option Explicit
Public Sub CheckSpreadsheet(wbook As Excel.Workbook)
Set wosheet = wbook.Sheets("Monthly")
wosheet.Cells(5, 5) = "Hello world!"
End Sub
Don't need to have another instance of Excel, the property to hide a workbook is Windows, in order to hide the excel windows used by the workbook. Also bear in mind that a workbook can have more than one window.
If you are sure that the workbook you want to hide has only one window use this line:
Workbooks("WbkName").Windows(1).Visible = False
If the workbook has several windows use this procedure:
Sub Wbk_Hide()
Dim wbk As Workbook, wdw As Window
Set wbk = Workbooks("WbkName") 'Update as required
For Each wdw In wbk.Windows
wdw.Visible = False
Next
End Sub
I believe this changes the scope of your procedures, let me know otherwise.

Selection.OnAction = "Workbookname!Macroname"

Say you have two Workbooks one called “MyWorkbook” and the other called “PatchMyWorkbook”. Both workbooks are open at the save time. The “PatchMyWorkbook” has a macro to add a button and assign an existing macro of “MyWorkbook” to “MyWorkbook” The existing macro in “MyWorkbook” is called “PrintPage”
Windows(“MyWorkbook”).Activate
Sheets("Sheet1").Activate
ActiveSheet.Buttons.Add(665.25, 43.5, 89.25, 45).Select
Selection.OnAction = "PrintPage"
This does not cause an error while the “PatchMyWorkbook” code executes but the newly added buttons macro will point to “’PatchMyWorkbook’!PrintPage” rather than just “PrintPage” of the “MyWorkbook”
Question: How can you set the “OnAction” for a macro button across workbooks so that the macro will point to the current workbook not the workbook from where the macro has been created?
In my opinion .OnAction property should be set in this way:
Selection.OnAction = myWbk.Name & "!PrintPage"
By the way, the idea from your comment (changed a bit below):
Selection.OnAction = "'" & myWbk.Name & "'" & "!" & "PrintPage"
is working for me as well (Excel 2010).
You need to include the name of the sheet or module where PrintPage is defined.
Dim methodName As String
With <module or sheet where 'PrintPage' is defined>
methodName = "'" & MyWbk.Name & "'!" & .CodeName & ".PrintPage"
End With
MyWbk.Sheets("Sheet1").Shapes("ButtonName").OnAction = methodName
The single quotes surrounding MyWbk.Name are important.
A quick and easy way is :
workbooks("name_of_workbook").Worksheets("name_of_sheet").Shapes("name_of_button").OnAction = "name_of_your_macro"
Just substitute the different "name_of_..." by your names.
Does it work?

Error Handling on external Macro

I am just wondering if it would be possible to do error handling on an external macro. Basically what I want to achieve is I have have thousands of excel workbooks that come in daily and I want to open each of them and run the macro from them (easily done just use the Application.run feature )
Application.Run ("'" & ActiveWorkbook & "'!Export")
What I want to achieve is I want to run error resolving function if that external macro incurs an error.
This is what I have so far
Dim str_SearchFile, str_FileName, str_SearchPath As String
Dim wb_WorkBook As Workbook
Application.ScreenUpdating = False
Application.DisplayAlerts = False
str_ThisBook = ActiveWorkbook.Name 'Set the current workbook for later reference
str_SearchPath = Sheets("Control Panel").Range("E2")
str_SearchFile = Sheets("Control Panel").Range("E2") & "\*.xls*" 'Sets the file type to search for
str_NextFile = Dir(str_SearchFile, vbDirectory) 'Sets the amount of files in the directory matching the criterea (.xls)
Do While Len(str_NextFile) > 0
On Error Resume Next
Set wb_WorkBook = Workbooks.Open(Filename:=str_SearchPath & "\" & str_NextFile, Password:="")
If Err.Number = 0 Then
On Error GoTo 0
Application.Run ("'" & str_NextFile & "'!Export")
str_FileName = str_SearchPath & "\Done" & "\" & str_NextFile
wb_WorkBook.Save
wb_WorkBook.Close
FileCopy (str_SearchPath & "\" & str_NextFile), str_FileName
Kill (str_SearchPath & "\" & str_NextFile)
End If
str_NextFile = Dir
Loop
Application.ScreenUpdating = True
Application.DisplayAlerts = True
End Sub
Any Advise is very welcome!
Thank you in advance
You won't be able to get this to work the way you are trying.
The MSDN on On Error Statement indicates that it (emphasis added):
Enables an error-handling routine and specifies the location of the
routine within a procedure; can also be used to disable an
error-handling routine.
The VBE Glossary defines a procedure as:
A named sequence of statements executed as a unit. For example,
Function, Property, and Sub are types of procedures. A procedure name
is always defined at module level. All executable code must be
contained in a procedure. Procedures can't be nested within other
procedures.
This means that calling error handling before calling the macro in the other book, will be ignored in the called macro (confirmed through testing).
The only way that you would be able to enable error handling would be to actually modify the code in the workbook prior to calling the macro... which is very complicated. For your reference, here is a webpage giving an example of editing project code from VBA.
The easiest way I would deal with this is to change your external workbook's "Export" sub into a function that returns a value - Say an integer.
What you can then do is put error trapping into that function and, based upon the outcome of the procedure it can return, say:
0 = All Went Well
1 = Failed to do XXX
2 = Failed to do YYY
You could then change your code to something like this:
Select Case Application.Run ("'" & str_NextFile & "'!Export")
Case 0
MsgBox "All Went Well"
Case 1
MsgBox "Failed to do XXX"
Case 2
MsgBox "Failed to do YYY"
End Select
This will allow you to put the error trapping where it belongs and know how the procedure ran.
hope this helps