Reputation: 1
I'm slowly learning VBA and have achieved some good stuff essentially cutting and pasting from forums, but now I'm stuck.
Using this script here: WordMVP I can open excel files from Word. No problem. However now I have reused this script so many times my modules are starting to get long. Can I split this up into different subs? And call the parts when I need them? e.g: (hacking the linked code to bits)
Put this in one separate sub:
Sub WorkOnAWorkbook(str As String)
Dim oXL As Excel.Application
Dim oWB As Excel.Workbook
Dim oSheet As Excel.Worksheet
Dim oRng As Excel.Range
Dim ExcelWasNotRunning As Boolean
'If Excel is running, get a handle on it; otherwise start a new instance of Excel
On Error Resume Next
Set oXL = GetObject(, "Excel.Application")
If Err Then
ExcelWasNotRunning = True
Set oXL = New Excel.Application
End If
On Error GoTo Err_Handler
'Open the workbook
Set oWB = oXL.Workbooks.Open(FileName:=str)
Exit Sub
Err_Handler:
MsgBox WorkbookToWorkOn & " caused a problem. " & Err.Description, vbCritical, _
"Error: " & Err.Number
End Sub
and this in another:
Sub release()
'Make sure you release object references.
Set oRng = Nothing
Set oSheet = Nothing
Set oWB = Nothing
Set oXL = Nothing
End Sub
and use them when I need them, e.g.:
Sub test()
Call WorkOnAWorkbook("somefile.xls")
oWB.Application.Run "Module1.TestMacro", "JasonX"
Call release()
End Sub
I get a 424 Object Required at oWB.Application.Run "Module1.TestMacro", "JasonX".
Is anything like this possible, part of me feels like I'm nearly there, part of me feels like I've totally screwed up, and part of me thinks its not possible...
Can anyone help please??
Thx a million.
Upvotes: 0
Views: 372
Reputation: 1826
You can't just break up code however you want because your object references need to exist in the sub you are using them in. However you can use functions to return an object, and thus could do something like put all the code for finding/creating the Excel object in a function that returns the object.
Function OpenExcelInstance() As Excel.Application
Dim oXL As Excel.Application
'If Excel is running, get a handle on it; otherwise start a new instance of Excel
On Error Resume Next
Set oXL = GetObject(, "Excel.Application")
If Err Then
ExcelWasNotRunning = True
Set oXL = New Excel.Application
End If
On Error GoTo Err_Handler
Set OpenExcelInstance = oXL
Exit Function
Err_Handler:
MsgBox WorkbookToWorkOn & " caused a problem. " & Err.Description, vbCritical, "Error: " & Err.Number
Set OpenExcelInstance = Nothing
End Function
And then your test sub would be reduced to (though this code has no error checking if for some reason the Excel reference wasn't created or the workbook could not be opened).
Sub test()
Dim oXL As Excel.Application
Dim oWB As Excel.Workbook
Set oXL = OpenExcelInstance()
Set oWB = oXL.Workbooks.Open(FileName:="somefile.xls")
oWB.Application.Run "Module1.TestMacro", "JasonX"
Set oXL = Nothing
Set oWB = Nothing
End Sub
Upvotes: 0
Reputation: 22866
You can shorten it to something like this (GetObject opens the file if it's not already opened):
Dim oWB As Object
Set oWB = GetObject("C:\somefile.xls", "Excel.Application")
oWB.Application.Visible = True ' optional show the Excel Application to check the full path to the Macro
oWB.Application.Run "Module1.TestMacro", "JasonX"
If oWB.Application.Workbooks.Count = 1 Then oWB.Application.Quit Else oWB.Close ' optional close the Excel Application or the Workbooks
Set oWB = Nothing
Upvotes: 1
Reputation: 1738
In your case the error occurs because oWB isn't declared in the sub that you are calling. Dim (declare), call/execute, and release all needs to happen in the same sub.
Upvotes: 0