View Full Version : Solved: Execute multiple subs or one large sub
rob0923
07-07-2009, 12:42 PM
Hi,
This may be bit of a basic question, but if you are writing a program to do several different things, such as create dirs, push values from excel to word, save the files and create a pdf from word. Would you create four seperate subs? If so how would you run all of them without manually going to each one, or would you write one large one?
Thanks,
mdmackillop
07-07-2009, 02:23 PM
Your macros need to work and to be maintainable. This is easier if they are not too lengthy. Splitting up a large routine to a series of smaller tasks means you can test and debug individually. If you need to make changes, the consequences are easier to follow. You can easily call a series of macros from one main code. eg
Sub Main()
Call Macro1
Call Macro2
Call Macro3
End Sub
As shown in the Folders question (http://vbaexpress.com/forum/showpost.php?p=189529&postcount=2), you can pass parameters to another macro to carry out repeated tasks. If you need to return a value, then use a Function eg
Sub Test
Msgbox MyValue(2)
End Sub
Function MyValue(x as long)
MyValue = x^3
End Function
Bob Phillips
07-07-2009, 03:56 PM
Plus you can spread the procedures over multiple code modules.
rob0923
07-07-2009, 05:58 PM
I noticed with the sub using arrays "DoMkDir sub" did not show on the macro list. I guess I have alot to learn! What did you mean by spread procedures over multiple code modules?
mdmackillop
07-08-2009, 12:35 AM
I noticed with the sub using arrays "DoMkDir sub" did not show on the macro list. I guess I have alot to learn! What did you mean by spread procedures over multiple code modules?
If you create several single purpose formatting macros, eg Adding borders, colours, fonts etc., then organize them in one module named for example modFormatting. Functions could go in another, Sorting/Filtering in others and so on.
A macro which requires a parameter does not appear in the macro list. It cannot be run from a shortcut or button as it needs another procedure to provide the parameter.
Don't worry about having a lot to learn. The more you do, the more you find that there is still even more!
rob0923
07-08-2009, 06:49 AM
I'll get the hang of it once I do something that requires something like that. I still have a few more steps in the program I am writing that I am not too sure how to do yet, but for example. If I push excel to word in the first sub (eg - Sub pushtoword) and end that sub the next sub I want to save the word file (eg - Private Sub saveasworddoc)
Is there any way to make the Objects that were dimmed. Such as, ("Word.Application") in the first sub to transfer to the next sub, This would be to save the Word.ActiveDocument that was created in the first Sub.
mdmackillop
07-08-2009, 07:14 AM
Can you post your code as it is now, or a sample workbook?
rob0923
07-08-2009, 07:38 AM
As you will notice I have dim appWrd and dim objDoc twice because I ended the sub and I was getting an error that it was not specified in the next sub. However I am not sure in the second sub that I am making a new word doc rahter then trying to save the existing word active word document
I do have other subs in between these (create directories, that you helped me with) but thought I'd keep it out to keep the code size down a bit.
Option Explicit
Public Sub MergetoTemplate()
Dim appWrd As Object
Dim objDoc As Object
Dim FilePath As String
Dim FileName As String
Dim appExl As Excel.Workbook
Dim ExlNm As Excel.Name
Dim NmSaveper As Range
'Start Push Excel to Word
'Turn some stuff off while macro is running
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
'Assign the word file path and name to
FilePath = ThisWorkbook.Path & "\Template"
FileName = "Sales_Temp.doc"
'Set instance of active workbook
Set appExl = ActiveWorkbook
'Open specified Word File
Set appWrd = CreateObject("Word.Application")
'Open specified word file, and Error if File cannot be found
On Error Resume Next
Set objDoc = appWrd.Documents.Add(FilePath & "\" & FileName)
'Error Handling
If objDoc Is Nothing Then
MsgBox "Unable to find the Word file", vbCritical, "File Not Found"
appWrd.Quit
Set appWrd = Nothing
Exit Sub
End If
'Loop through names in the Workbook
For Each ExlNm In appExl.Names
'Place into bookmark if Excel name match Word bookmark
If objDoc.Bookmarks.Exists(ExlNm.Name) Then
objDoc.Bookmarks(ExlNm.Name).Range.Text = Format(Range(ExlNm.Value), "$#,##0.00")
End If
Next ExlNm
'Set Excel ranges for paste into bookmarks
Set NmSaveper = Worksheets("Sheet1").Range("B4")
'Set NumberFormat for Excel ranges other then "$#,##0.00"
With objDoc.Bookmarks
.Item("NmSave").Range.InsertAfter Format((NmSaveper.Value), "#%")
End With
'Turn some stuff back on
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayAlerts = True
'Display word
appWrd.Visible = True
Call SaveWord
End Sub
Private Sub SaveWord()
'Save Word
Dim NmComp
Dim WrdPth As String
Dim appWrd As Object
Dim TodayDate As String
Dim objDoc As Object
Set appWrd = GetObject(, "Word.Application")
'Set Active document
Set WordDoc = Word.ActiveDocument
'Company Value
NmComp = Worksheets("Sheet1").Range("B1")
'Get date for file string
TodayDate = Format(Date, "mm.dd.yyyy")
'Set Path
WrdPth = ThisWorkbook.Path & "\" & NmComp & "_" & TodayDate & "\Word"
'Save file
objDoc.SaveAs WrdPth & "\" & NmComp & "_" & TodayDate & ".doc"
'Quit
applWrd.Quit
End Sub
Bob Phillips
07-08-2009, 08:02 AM
One way
Public Sub WordControl()
Dim appWrd As Object
'Turn some stuff off while macro is running
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
'Open specified Word File
Set appWrd = CreateObject("Word.Application")
If MergetoTemplate(appWrd) Then
'only continue if last function completed okay
'Turn some stuff back on
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayAlerts = True
'Display word
appWrd.Visible = True
Call SaveWord(appWrd)
End If
appWrd.Quit
Set appWrd = Nothing
End Sub
Public Function MergetoTemplate(ByRef WordApp As Object) As Boolean
Dim objDoc As Object
Dim FilePath As String
Dim FileName As String
Dim appExl As Excel.Workbook
Dim ExlNm As Excel.Name
Dim NmSaveper As Range
'Start Push Excel to Word
'Assign the word file path and name to
FilePath = ThisWorkbook.Path & "\Template"
FileName = "Sales_Temp.doc"
'Set instance of active workbook
Set appExl = ActiveWorkbook
'Open specified word file, and Error if File cannot be found
On Error Resume Next
Set objDoc = WordApp.Documents.Add(FilePath & "\" & FileName)
'Error Handling
If objDoc Is Nothing Then
MsgBox "Unable to find the Word file", vbCritical, "File Not Found"
MergetoTemplate = False
End If
'Loop through names in the Workbook
For Each ExlNm In appExl.Names
'Place into bookmark if Excel name match Word bookmark
If objDoc.Bookmarks.Exists(ExlNm.Name) Then
objDoc.Bookmarks(ExlNm.Name).Range.Text = Format(Range(ExlNm.Value), "$#,##0.00")
End If
Next ExlNm
'Set Excel ranges for paste into bookmarks
Set NmSaveper = Worksheets("Sheet1").Range("B4")
'Set NumberFormat for Excel ranges other then "$#,##0.00"
With objDoc.Bookmarks
.Item("NmSave").Range.InsertAfter Format((NmSaveper.Value), "#%")
End With
MergetoTemplate = True
End Function
Private Function SaveWord(ByRef WordApp As Object) As Boolean
Dim NmComp
Dim WrdPth As String
Dim TodayDate As String
Dim objDoc As Object
'Set Active document
Set objDoc = WordApp.ActiveDocument
'Company Value
NmComp = Worksheets("Sheet1").Range("B1")
'Get date for file string
TodayDate = Format(Date, "mm.dd.yyyy")
'Set Path
WrdPth = ThisWorkbook.Path & "\" & NmComp & "_" & TodayDate & "\Word"
'Save file
objDoc.SaveAs WrdPth & "\" & NmComp & "_" & TodayDate & ".doc"
End Function
mdmackillop
07-08-2009, 08:20 AM
A small point to using dates in file names; if you need to sort/list them by date in the Explorer window, then consider using
TodayDate = Format(Date, "yyyy.mm.dd")
rob0923
07-08-2009, 08:45 AM
I will test this out when I get on a PC. I am assuming I can use a private function to Save the Excel document as well (It will have a protection on it too) and then last I need to make word to a pdf and save the pdf, but I think I'll do one thing at a time.
i am assuming that I will need to call a word macro to print with pdfcreator.
Thanks for all your quick replies!
rob0923
07-08-2009, 11:41 AM
Thanks for all your help! This is working great. You are definatly masters at this! :) I will attempt to create a pdf out of the word doc now..
Thanks again!
rob0923
08-07-2009, 06:46 PM
Hi,
Another question regarding this vba. When I want to set up an Error Handler. For example once the VBA has transfered the data using the private function as xld used above.
How would I set up an Error Handler so it goes to another sub and will kill the vba without proceeding to ever called sub after an error has been found. I possible would like it to close the word application down and delete any files/directories have been created.
I have tried
On Error Goto Err1
Exit Function
Err1:
Call Error1
Private Sub Error1()
Msg Box = ""
End Sub
However it will still return to the main sub and continue the main trying to create directories and pdf the document, but will create a debug error.
Thanks in advance
Bob Phillips
08-08-2009, 02:47 AM
If you add an error handler in the top level module, and don't re-issue an On Error at any later point, the original error handler will still be operational in the called procedures, so any error there will be directed back to the top module error handler. Here you can do any tidying up needed, probably best to use
Err1:
On Error Resum Next
'delete any files required
Exit Sub
If you only have the information to know what to tidy up in the called procedures, it is more complex. In this case, it is best to set an erro handler in each, and pass control back up the chain, testing for success as you go.
Something like this
Option Explicit
Public ErrMsg As String
Public Function TopLevel()
On Error GoTo Top_Error
ErrMsg = ""
'do some stuff
If Not SecondLevel_1 Then Err.Raise 99999
'do some more stuff
If Not SecondLevel_2 Then Err.Raise 99999
Exit Function
Top_Error:
MsgBox "An unexpected error has occurred" & vbNewLine & vbNewLine & ErrMsg, vbOKOnly + vbCritical, "My App"
End Function
Private Function SecondLevel_1() As Boolean
On Error GoTo S1_Error
SecondLevel_1 = True
'do some stuff
MkDir "C:\secondlevel_1" '<<<< just for testing
MsgBox "SecondLevel_1" '<<<< just for testing
S1_Exit:
'any tidy-up code whether successful or not goes here
Exit Function
S1_Error:
SecondLevel_1 = False
If ErrMsg = "" Then ErrMsg = _
"Error " & Err.Number & " - " & Err.Description & vbNewLine & vbNewLine & _
"SecondLevel_1"
Call Tidyup
Resume S1_Exit
End Function
Private Function SecondLevel_2() As Boolean
On Error GoTo S2_Error
SecondLevel_2 = True
'do some stuff
If Not ThirdLevel_1 Then Err.Raise 99999
S2_Exit:
'any tidy-up code whether successful or not goes here
Exit Function
S2_Error:
SecondLevel_2 = False
If ErrMsg = "" Then ErrMsg = _
"Error " & Err.Number & " " & Err.Description & vbNewLine & vbNewLine & _
"SecondLevel_2"
Call Tidyup
Resume S2_Exit
End Function
Private Function ThirdLevel_1() As Boolean
On Error GoTo T1_Error
ThirdLevel_1 = True
'do some stuff
Debug.Print 1 / 0 '<<<< force an error
T1_Exit:
'any tidy-up code whether successful or not goes here
Exit Function
T1_Error:
ThirdLevel_1 = False
If ErrMsg = "" Then ErrMsg = _
"Error " & Err.Number & " - " & Err.Description & vbNewLine & vbNewLine & _
"ThirdLevel_1"
Call Tidyup
Resume T1_Exit
End Function
Private Function Tidyup()
'add any tidy-up code that you could on failure need here
On Error Resume Next
RmDir "C:\secondlevel_1"
RmDir "C:\secondlevel_2"
End Function
rob0923
08-08-2009, 09:42 AM
Thanks for the quick responce. Just to mae sure I have this correct.
The code would be something like below. There are more steps, but I took some functions out due to the size.
Perferably if it come up with an error creating the directories theres no need to try to save anything and just by pass the remainder of the functions. Or if C10 is empty which is required to create the directories is empty a box pops up requiring them to enter something for C10.
Option Explicit
Public ErrMsg As String
Public Function CreateReport()
Dim appWrd As Object
Dim appExl As Object
On Error GoTo Top_Error
ErrMsg = ""
'Turn some stuff off while macro is running
Application.ScreenUpdating = False
Application.EnableEvents = False
Application.DisplayAlerts = False
'Set instance for Word
Set appWrd = CreateObject("Word.Application")
'Set instance for Excel
Set appExl = Excel.Application
If MergetoTemplate(appWrd) Then
'only continue if last function completed okay
'Turn some stuff back on
Application.ScreenUpdating = True
Application.EnableEvents = True
Application.DisplayAlerts = True
'Display word
appWrd.Visible = True
'Call sub to create dir's
If Not Createdir() Then Err.Raise 99999
'Call SaveWord
'Call SaveWord(appWrd)
End If
Set appExl = Nothing
Set appWrd = Nothing
Top_Error:
MsgBox "An unexpected error has occurred" & vbNewLine & vbNewLine & ErrMsg, vbOKOnly + vbCritical, "My App"
appWrd.Quit
Set appExl = Nothing
Set appWrd = Nothing
End Function
Public Function MergetoTemplate(ByRef Wordapp As Object) As Boolean
Dim objDoc As Object
Dim FilePath As String
Dim FileName As String
Dim ExlNm As Excel.Name
Dim NmSaveper As Range
Dim exlWbk As Excel.Workbook
'Start Push Excel to Word
'Assign the word file path and name to
FilePath = ThisWorkbook.Path & "\Template"
FileName = "Sales_Temp.doc"
'Set instance of active workbook
Set exlWbk = ActiveWorkbook
'Open specified word file, and Error if File cannot be found
On Error Resume Next
Set objDoc = Wordapp.Documents.Add(FilePath & "\" & FileName)
'Error Handling
If objDoc Is Nothing Then
MsgBox "Unable to find the Word file", vbCritical, "File Not Found"
MergetoTemplate = False
End If
'Loop through names in the Workbook
For Each ExlNm In exlWbk.Names
'Place into bookmark if Excel name match Word bookmark
If objDoc.Bookmarks.Exists(ExlNm.Name) Then
objDoc.Bookmarks(ExlNm.Name).Range.Text = Format(Range(ExlNm.Value), "$#,##0.00")
End If
Next ExlNm
'Set Excel ranges for paste into bookmarks
Set NmSaveper = Worksheets("Sheet1").Range("B4")
'Set NumberFormat for Excel ranges other then "$#,##0.00"
With objDoc.Bookmarks
.Item("NmSave").Range.InsertAfter Format((NmSaveper.Value), "#%")
End With
MergetoTemplate = True
Set objDoc = Nothing
End Function
Private Function SaveWord(ByRef Wordapp As Object) As Boolean
Dim NmComp
Dim WrdPth As String
Dim TodayDate As String
Dim objDoc As Object
'Set Active document
Set objDoc = Wordapp.ActiveDocument
'Company Value
NmComp = Worksheets("Cover Sheet").Range("C10")
'Get date for file string
TodayDate = Format(Date, "yyyy.mm.dd")
'Set Path
WrdPth = ThisWorkbook.Path & "\Saved_Quotes" & "\" & NmComp & "_" & TodayDate & "\Word"
'Save file
objDoc.SaveAs WrdPth & "\" & NmComp & "_" & TodayDate & ".doc"
Set objDoc = Nothing
End Function
Private Function Createdir() As Boolean
'Set Directories for Company.Value
Dim NmComp
Dim msg As Long 'Inform user message
Dim TodayDate As String
Dim TopDirectory As String
Dim MainDirectory As String
'First check if value in B1
If Worksheets("Cover Sheet").Range("C10") <> "" Then
'Yes
NmComp = Worksheets("Cover Sheet").Range("C10")
Else
'No value in "C10"
On Error GoTo Createdir_Err
End If
Createdir = True
'Get date for Dir string
TodayDate = Format(Date, "yyyy.mm.dd")
'Build Main directory string
MainDirectory = ThisWorkbook.Path & "\Saved_Quotes"
'Build top directory string
TopDirectory = ThisWorkbook.Path & "\Saved_Quotes" & "\" & NmComp & "_" & TodayDate
'Check Main Dir
If Dir(MainDirectory, vbDirectory) = "" Then
MkDir MainDirectory
End If
'Check parent. No parent, no kids.
If Dir(TopDirectory, vbDirectory) = "" Then
'Doesn't exist. Create it and all subdirectories
MkDir TopDirectory
End If
S1_Exit:
'any tidy-up code whether successful or not goes here
Exit Function
Createdir_Err:
Createdir = False
If ErrMsg = "" Then ErrMsg = _
"Error " & Err.Number & " - " & Err.Description & vbNewLine & vbNewLine & _
"Create Directories"
Call Tidyup
Resume S1_Exit
End Function
Private Function Tidyup()
'add any tidy-up code that you could on failure need here
On Error Resume Next
RmDir "C:\secondlevel_1"
RmDir "C:\secondlevel_2"
End Function
Powered by vBulletin® Version 4.2.5 Copyright © 2025 vBulletin Solutions Inc. All rights reserved.