Help combining VBA automation macros

EricA2

New Member
Joined
Dec 15, 2011
Messages
43
I've spent a lot of time trying to learn the language of VBA, through watching Mr. Excel videos, googling, and forum surfing. I'm looking to combine macros to run. I've picked up so far that it's as simple as:

Code:
sub xxx()[INDENT]Dim ws As Worksheet
For Each ws in ActiveWorkbook.Worksheets
[/INDENT][INDENT][INDENT]xxx code xxx
[/INDENT][/INDENT][INDENT]Next ws
[/INDENT]End Sub
and incorporated it into my macros. The problem I'm having is that I constantly either get an error on the sub dimension (xxx in this case) or that it doesn't understand the "ws" after the final Next? In my used code (bottom of post), it's supposed to cause that macro to loop through all of the sheets in the workbook, after the workbook is created by the first macro. When I try running them together, the macro stops on the "ws" as mentioned before, but separately, the first part runs fine, and the second part still gets stuck.

It makes logical sense to me that it should work, and according to all of the places online that I've been fortunate enough to come across, it's the same logical argument/variables, so it should all work, but for whatever reason, it just doesn't seem to be working for me.

Anyway, here is the code I'm using, scraped together from wonderful people who have been kind enough to post it on the web to share with the world:

Code1:
Code:
Option Explicit

Private myFiles() As String
Private Fnum As Long

Function Get_File_Names(MyPath As String, Subfolders As Boolean, _
                        ExtStr As String, myReturnedFiles As Variant) As Long

    Dim Fso_Obj As Object, RootFolder As Object
    Dim SubFolderInRoot As Object, file As Object

    'Add a slash at the end if the user forget it
    If Right(MyPath, 1) <> "\" Then
        MyPath = MyPath & "\"
    End If

    'Create FileSystemObject object
    Set Fso_Obj = CreateObject("Scripting.FileSystemObject")

    Erase myFiles()
    Fnum = 0

    'Test if the folder exist and set RootFolder
    If Fso_Obj.FolderExists(MyPath) = False Then
        Exit Function
    End If
    Set RootFolder = Fso_Obj.GetFolder(MyPath)

    'Fill the array(myFiles)with the list of Excel files in the folder(s)
    'Loop through the files in the RootFolder
    For Each file In RootFolder.Files
        If LCase(file.Name) Like LCase(ExtStr) Then
            Fnum = Fnum + 1
            ReDim Preserve myFiles(1 To Fnum)
            myFiles(Fnum) = MyPath & file.Name
        End If
    Next file

    'Loop through the files in the Sub Folders if SubFolders = True
    If Subfolders Then
        Call ListFilesInSubfolders(OfFolder:=RootFolder, FileExt:=ExtStr)
    End If

    myReturnedFiles = myFiles
    Get_File_Names = Fnum
End Function


Sub ListFilesInSubfolders(OfFolder As Object, FileExt As String)
'Origenal SubFolder code from Chip Pearson
'http://www.cpearson.com/Excel/RecursionAndFSO.htm
'Changed by Ron de Bruin, 27-March-2008
    Dim SubFolder As Object
    Dim fileInSubfolder As Object

    For Each SubFolder In OfFolder.Subfolders
        ListFilesInSubfolders OfFolder:=SubFolder, FileExt:=FileExt

        For Each fileInSubfolder In SubFolder.Files
            If LCase(fileInSubfolder.Name) Like LCase(FileExt) Then
                Fnum = Fnum + 1
                ReDim Preserve myFiles(1 To Fnum)
                myFiles(Fnum) = SubFolder & "\" & fileInSubfolder.Name
            End If
        Next fileInSubfolder

    Next SubFolder
End Sub

Function RDB_Last(choice As Integer, rng As Range)
'Ron de Bruin, 5 May 2008
' 1 = last row
' 2 = last column
' 3 = last cell
    Dim lrw As Long
    Dim lcol As Integer

    Select Case choice

    Case 1:
        On Error Resume Next
        RDB_Last = rng.Find(What:="*", _
                            after:=rng.Cells(1), _
                            Lookat:=xlPart, _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByRows, _
                            SearchDirection:=xlPrevious, _
                            MatchCase:=False).Row
        On Error GoTo 0

    Case 2:
        On Error Resume Next
        RDB_Last = rng.Find(What:="*", _
                            after:=rng.Cells(1), _
                            Lookat:=xlPart, _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByColumns, _
                            SearchDirection:=xlPrevious, _
                            MatchCase:=False).Column
        On Error GoTo 0

    Case 3:
        On Error Resume Next
        lrw = rng.Find(What:="*", _
                       after:=rng.Cells(1), _
                       Lookat:=xlPart, _
                       LookIn:=xlFormulas, _
                       SearchOrder:=xlByRows, _
                       SearchDirection:=xlPrevious, _
                       MatchCase:=False).Row
        On Error GoTo 0

        On Error Resume Next
        lcol = rng.Find(What:="*", _
                        after:=rng.Cells(1), _
                        Lookat:=xlPart, _
                        LookIn:=xlFormulas, _
                        SearchOrder:=xlByColumns, _
                        SearchDirection:=xlPrevious, _
                        MatchCase:=False).Column
        On Error GoTo 0

        On Error Resume Next
        RDB_Last = rng.Parent.Cells(lrw, lcol).Address(False, False)
        If Err.Number > 0 Then
            RDB_Last = rng.Cells(1).Address(False, False)
            Err.Clear
        End If
        On Error GoTo 0

    End Select
End Function
Code 2
Code:
Option Explicit

'The example below will copy the first worksheet from each file in a new workbook
'It copy as values because the PasteAsValues argument = True

'First we call the Function "Get_File_Names" to fill a array with all file names
'There are three arguments in this Function that we can change

'1) MyPath = the folder where the files are
'2) Subfolders = True if you want to include subfolders
'3) ExtStr = file extension of the files you want to merge
'   ExtStr examples are: "*.xls" , "*.csv" , "*.xlsx"
'   "*.xlsm" ,"*.xlsb" , for all Excel file formats use "*.xl*"
'   Do not change myReturnedFiles:=myFiles


'Then if there are files in the folder we call the macro "Get_Sheet"
'There are three arguments in this macro that we can change


'1) PasteAsValues = True to paste as values (recommend)
'2) SourceShName = sheet name, if "" it will use the SourceShIndex
'3) SourceShIndex = to avoid problems with different sheet names use the index (1 is the first worksheet)
'   Do not change myReturnedFiles:=myFiles


Sub RDB_Copy_Sheet()
    Dim myFiles As Variant
    Dim myCountOfFiles As Long

    myCountOfFiles = Get_File_Names( _
                     MyPath:="C:\Documents and Settings\xxx\My Documents\xxx", _
                     Subfolders:=False, _
                     ExtStr:="123*.*", _
                     myReturnedFiles:=myFiles)

    If myCountOfFiles = 0 Then
        MsgBox "No files that match the ExtStr in this folder"
        Exit Sub
    End If

    Get_Sheet _
            PasteAsValues:=True, _
            SourceShName:="", _
            SourceShIndex:=1, _
            myReturnedFiles:=myFiles

End Sub


' Note: You not have to change the macro below, you only
' edit and run the RDB_Copy_Sheet above.

Sub Get_Sheet(PasteAsValues As Boolean, SourceShName As String, _
              SourceShIndex As Integer, myReturnedFiles As Variant)
    Dim mybook As Workbook, BaseWks As Worksheet
    Dim CalcMode As Long
    Dim SourceSh As Variant
    Dim sh As Worksheet
    Dim I As Long

    'Change ScreenUpdating, Calculation and EnableEvents
    With Application
        CalcMode = .Calculation
        .Calculation = xlCalculationManual
        .ScreenUpdating = False
        .EnableEvents = False
    End With

    On Error GoTo ExitTheSub

    'Add a new workbook with one sheet
    Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)


    'Check if we use a named sheet or the index
    If SourceShName = "" Then
        SourceSh = SourceShIndex
    Else
        SourceSh = SourceShName
    End If

    'Loop through all files in the array(myFiles)
    For I = LBound(myReturnedFiles) To UBound(myReturnedFiles)
        Set mybook = Nothing
        On Error Resume Next
        Set mybook = Workbooks.Open(myReturnedFiles(I))
        On Error GoTo 0

        If Not mybook Is Nothing Then

            'Set sh and check if it is a valid
            On Error Resume Next
            Set sh = mybook.Sheets(SourceSh)

            If Err.Number > 0 Then
                Err.Clear
                Set sh = Nothing
            End If
            On Error GoTo 0

            If Not sh Is Nothing Then
                sh.Copy after:=BaseWks.Parent.Sheets(BaseWks.Parent.Sheets.Count)

                On Error Resume Next
                ActiveSheet.Name = mybook.Name
                On Error GoTo 0

                If PasteAsValues = True Then
                    With ActiveSheet.UsedRange
                        .Value = .Value
                    End With
                End If

            End If
                                   
            'Close the workbook without saving
            mybook.Close savechanges:=False
        End If

        'Open the next workbook
    Next I

    ' delete the first sheet in the workbook
    Application.DisplayAlerts = False
    On Error Resume Next
    BaseWks.Delete
    On Error GoTo 0
    Application.DisplayAlerts = True

ExitTheSub:
    'Restore ScreenUpdating, Calculation and EnableEvents
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = CalcMode
    End With
End Sub
code 3

Code:
Sub replaceallblanks()
'
' ReplaceAllBlanks Macro
' Macro recorded 6/17/2003 by xxx
'
' Keyboard Shortcut: Ctrl+m
'
Dim LastRow As Integer
Dim LastColumn As String
Dim WorkSheetName As String

LastColumn = Cells.Find(What:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByColumns).Column
LastRow = Cells.Find("*", Range("A1"), xlFormulas, , xlByRows, xlPrevious).Row



nrows = LastRow
LastColumn = LastColumn

'This removes the bad characters
        
For x = 1 To LastColumn
    For n = 2 To nrows
        
        If IsError(Cells(n, x)) Then
        Cells(n, x) = 0
    Else
    End If
        If Cells(n, x) = "" Then
        Cells(n, x) = Cells((n - 1), x)
    Else
    End If
    Next
Next

End Sub
I'm trying to tie them together. I understand that right now Code 1 and 2 are tied together, and executed by selecting macro "RDB_Copy_Sheet"

I've tried adding "Call Fill_All_Blanks" before the end of Code 2, and I've tried by adding the full code for Fill_All_Blanks after the end of Code 2, with VBA showing a break there between them, recognizing it as a different command(?).

The point of this whole project is to pull all individual spreadsheets dumped in "C:\Documents and Settings\xxx\My Documents\xxx" which were an output of another program, all starting with 123, and putting them in one excel workbook, then applying macro 3 to the sheets, filling in data that the original program leaves in the spreadsheet as a result of how it outputs its query. I only need the third item since I'll be using the outputs to import into further sheets which then have vlookups run on them, and it needs to be able to pull all of that info for the vlookups to work.

Basically I'm very new to this, this is my first big project, and I've gone through dozens of tutorials, demos, and projects from all over the web to learn how to properly execute this. I hope this forum can help, since it seems to be full of a wealth of information from very talented individuals.

Thank you in advance for your help!
 

Excel Facts

Show numbers in thousands?
Use a custom number format of #,##0,K. Each comma after the final 0 will divide the displayed number by another thousand
EricA2,

When you say...
I've tried adding "Call Fill_All_Blanks" before the end of Code 2, and I've tried by adding the full code for Fill_All_Blanks /QUOTE]
Is Fill_All_Blanks meant to call the Sub replaceallblanks, as per your code 3 above?

Tony
 
Upvote 0
EricA2,

When you say...
I've tried adding "Call Fill_All_Blanks" before the end of Code 2, and I've tried by adding the full code for Fill_All_Blanks /QUOTE]
Is Fill_All_Blanks meant to call the Sub replaceallblanks, as per your code 3 above?

Tony

Yes. The reason I did so is because I tried it both with "Fill_All_Blanks" (the title that it has when pulled up in the Excel macro run dialogue) as well as with "replaceallblanks" (the defined Sub in the code), and they both came up with the same errors. Fill_All_Blanks comes up with Sub or Function not Defined, and replaceallblanks comes up with "Expected variable or procedure, not module" when using with the call command, placed at the end of Code 2, just above End Sub.
 
Upvote 0
EricA2,

'Sub or Function not Defined' indicates that the sub or function does not exist. If you have re-named a sub or function then any reference to to it's old name will fail in this way.
'Expected variable or procedure not vba module' indicates that you have a code module with the same name as a procedure within the module.

So, check your modules and subs and give them suitable discreet names.

Re code 3.......

You can see that this code was at some time assigned to a keyboard shortcut. The code is designed to act upon the Active sheet only!!!!

Any reference to objects such as Range or Cell without a leading "." (point) can only reference the active sheet.
Code 3 could be called toloop through all sheets in the workbook but unless each sheet in turn was selected to become the 'Active' sheet, the code would only ever influence the original active sheet.

VBA is an Object orientated language and if you are not specific in telling it which objects to work with then it either fails totally or gives the wrong answers.

See how you get on with the revised code below.
Put it in a code module. Name the module if you wish or just accept the default Module1 / 2 etc. Change the name of the sub if you wish.

I am assuming that this code will not be called until you have all of your required sheets copied int the single workbook. IE the Active workbook.
You should then be able to run / call this code in any way you wish.

The changed will loop thro' each sheet in the workbook.
Using the With Sht / End With statements means that within those statements we use the shorthand of .Range, .Cells etc to reference the objects associated with each sheet in turn. '*****

Code:
Sub Remove_All_Blanks()
'
' ReplaceAllBlanks Macro
' Macro recorded 6/17/2003 by xxx
'
' Keyboard Shortcut: Ctrl+m
'
Dim LastRow As Integer
Dim LastColumn As String
'Dim WorkSheetName As String ''**** redundant as sub is acting on active workbook
For Each Sht In ActiveWorkbook.Sheets  '******
With Sht '******
LastColumn = .Cells.Find(What:="*", SearchDirection:=xlPrevious, SearchOrder:=xlByColumns).Column
LastRow = .Cells.Find("*", .Range("A1"), xlFormulas, , xlByRows, xlPrevious).Row
 
nrows = LastRow
LastColumn = LastColumn
'This removes the bad characters
 
For x = 1 To LastColumn
    For n = 2 To nrows
 
        If IsError(.Cells(n, x)) Then
        .Cells(n, x) = 0
    Else
    End If
        If .Cells(n, x) = "" Then
        .Cells(n, x) = .Cells((n - 1), x)
    Else
    End If
    Next
Next
End With '******
Next Sht  '******
End Sub

I hope that make some sort of sense and helps you out.

Tony
 
Upvote 0
EricA2,

'Sub or Function not Defined' indicates that the sub or function does not exist. If you have re-named a sub or function then any reference to to it's old name will fail in this way.
'Expected variable or procedure not vba module' indicates that you have a code module with the same name as a procedure within the module.

So, check your modules and subs and give them suitable discreet names.

Re code 3.......

You can see that this code was at some time assigned to a keyboard shortcut. The code is designed to act upon the Active sheet only!!!!

Any reference to objects such as Range or Cell without a leading "." (point) can only reference the active sheet.
Code 3 could be called toloop through all sheets in the workbook but unless each sheet in turn was selected to become the 'Active' sheet, the code would only ever influence the original active sheet.

VBA is an Object orientated language and if you are not specific in telling it which objects to work with then it either fails totally or gives the wrong answers.

See how you get on with the revised code below.
Put it in a code module. Name the module if you wish or just accept the default Module1 / 2 etc. Change the name of the sub if you wish.

I am assuming that this code will not be called until you have all of your required sheets copied int the single workbook. IE the Active workbook.
You should then be able to run / call this code in any way you wish.

The changed will loop thro' each sheet in the workbook.
Using the With Sht / End With statements means that within those statements we use the shorthand of .Range, .Cells etc to reference the objects associated with each sheet in turn. '*****

I hope that make some sort of sense and helps you out.

Tony

Tony,

Thank you so much for your assistance. Your code worked perfectly, and I can now add the "call Remove_All_Blanks" into the prior macros, and it performs all of it's functions in sequence perfectly. I'm incredibly excited since this is a huge time saver for me.

As I'm trying to understand the logic behind what is going on, I apologize for being a bit dim on the subject. As much as computers have been a tremendous part of my life (I'm a computer gaming/hardware nut, basically my only consistent hobby over my adolescent/adult lifetime), I've never been able to understand programming, almost of any type (from BASIC to HTML to VBA). I'm glad that I've got such fantastic resources to help me get a better grasp on the subject here with this forum though!

I definitely took note of the "." placed before any of the specific variables that I want to apply across multiple sheets, and now I also recognize that all sheets will be active (or be considered when the macro runs) when not specified as individual sheets, and the macro doesn't look for an active sheet.

One point of confusion I still have though is in the way Sht is still used to identify a sheet within the workbook, but isn't specified/labeled as a dimension with something similar to "Dim Sht as Worksheet." It is still used as a variable name to identify working with a worksheet within workbook.

Still lots to learn, but I'm very happy to have found a seemingly welcoming community where to learn and expand and grow!
 
Upvote 0
EricA2,

It's good to hear that the code mods worked and that you are excited at the prospect of getting to grips with vba. It's amazing what even us lesser Excel'ers can achieve with a bit of knowledge, a bit of imagination and lots of perseverance although, it can at times prove to be a bit frustrating.
Just to clarify a couple of points raised in your response above.....

1. Generally, it is not essential that you declare all variables and objects in your code.
Some folk do it as habit or for them, 'good practice'.

2. In the absence of any other information, code thinks you will be referring to objects of the Active sheet. If so you can omit the ".".

3. The looping of each object in a group of objects such as each Sht in Worksheets is special in as much as the primary object within Worksheets is the sheet. Sht could be XXX but once stated you can then refer to it and it's objects using Sht.Range(.... or xxx.Range(.... etc.

4. If you create a With / End With, say With Sheets('Sheet1")........ End With. Then anywhere within those statements you can refer to that sheets objects using .Range(... etc. If however your code needs to influence any other sheet or its objects then you must fully specify that sheet/object. Eg Sheets("Sheet2").Range("A1").Value

I hope that is perhaps a tad clearer?
There are literally thousands of Excel tutorial videos up on YouTube most notably from MrExcel himself. There is perhaps not so much on vba but it is out there.

If you really want a start and can afford $30 then you will get the download version of MrExcel's (Bill Jelen) vba live tutorials. This will give you a great basic understanding.

Good luck if you do.
Tony
 
Upvote 0
1. Generally, it is not essential that you declare all variables and objects in your code.
Some folk do it as habit or for them, 'good practice'.
Hi Tony,

Just to add to your point, Chip Pearson wrote an excellent article describing good practice for declaring variables in VBA (along with loads of other excellent topics on his website):
http://www.cpearson.com/excel/DeclaringVariables.aspx
 
Upvote 0
EricA2,

It's good to hear that the code mods worked and that you are excited at the prospect of getting to grips with vba. It's amazing what even us lesser Excel'ers can achieve with a bit of knowledge, a bit of imagination and lots of perseverance although, it can at times prove to be a bit frustrating.
Just to clarify a couple of points raised in your response above.....

I hope that is perhaps a tad clearer?
There are literally thousands of Excel tutorial videos up on YouTube most notably from MrExcel himself. There is perhaps not so much on vba but it is out there.

If you really want a start and can afford $30 then you will get the download version of MrExcel's (Bill Jelen) vba live tutorials. This will give you a great basic understanding.

Good luck if you do.
Tony

Thank you again very much Tony. Your assistance really helped. I've been using the macros successfully, and am pursing learning more about them. After the holidays I'll pick up Mr. Excel's vba live tutorials (can't afford them yet).

What is funny to me about learning VBA is that I have a hard time putting out new code, however when someone shows me the solution, it's one of those "facepalm" moments, because right away I see it, see how simple it really is, and see how logical it is. I sit there and wonder why I couldn't do something that simple in the first place. Oh well, I guess that's part of the learning process!

I'm really looking forward to using VBA in my future prospects, and hopefully at work it can help me earn a promotion :biggrin: , or even allow me to help others with their assignments/projects. I now see the potential that there is in the workplace for VBA to really automate/assist in some of the more boring and simple tasks that I imagine most office workers who deal with any data encounter regularly. We need a marketing campaign for people to see the potential!

Thank you again for opening my eyes!
 
Upvote 0

Forum statistics

Threads
1,223,236
Messages
6,170,915
Members
452,366
Latest member
TePunaBloke

We've detected that you are using an adblocker.

We have a great community of people providing Excel help here, but the hosting costs are enormous. You can help keep this site running by allowing ads on MrExcel.com.
Allow Ads at MrExcel

Which adblocker are you using?

Disable AdBlock

Follow these easy steps to disable AdBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the icon in the browser’s toolbar.
2)Click on the "Pause on this site" option.
Go back

Disable AdBlock Plus

Follow these easy steps to disable AdBlock Plus

1)Click on the icon in the browser’s toolbar.
2)Click on the toggle to disable it for "mrexcel.com".
Go back

Disable uBlock Origin

Follow these easy steps to disable uBlock Origin

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back

Disable uBlock

Follow these easy steps to disable uBlock

1)Click on the icon in the browser’s toolbar.
2)Click on the "Power" button.
3)Click on the "Refresh" button.
Go back
Back
Top