2

I'm working on a project that requires the following:

I would like a Macro to loop through a folder and search for a certain worksheet then grab all the tabs from this worksheet and move them to a consolidated workbook

Is it possible to find a worksheet based on a certain string in the worksheet name? ex: Financial_data_401kk.xls

Could you search by this string "401kk"?

Im new to VBA and this is what i have so far

Sub ConsolidateSheets()

Dim Path as String
Dim File As String

Dim wb1 as Workbook, wb2 as Workbook    

Path = "G:\Operations\test\"    
File = Dir(Path & "*401kk*")

Set wb1 = Wworkbooks("book1.xlsm")
Set wb2 = Workbooks(File)

For Each sh in wb2
    sh.copy After:=wb1.sheets(wb1.sheets.count)
Next

End Sub
pnuts
  • 58,317
  • 11
  • 87
  • 139
Abd
  • 23
  • 1
  • 7

2 Answers2

2

Building on this EE article you could do this.

Key update are these two lines

strFileName = Dir(strFolderName & "\*401kk*.xls*")
strDefaultFolder = "G:\Operations\test\"

The first point searches for your specific string with Dir as per Loop through files in a folder using VBA? so only the requireed workbooks are manipulated.

code

Public Sub ConsolidateSheets()
    Dim Wb1 As Workbook
    Dim Wb2 As Workbook
    Dim ws1 As Worksheet
    Dim ws2 As Worksheet
    Dim ws3 As Worksheet
    Dim rng1 As Range
    Dim rng2 As Range
    Dim rng3 As Range
    Dim rngArea As Range
    Dim lrowSpace As Long
    Dim lSht As Long
    Dim lngCalc As Long
    Dim lngRow As Long
    Dim lngCol As Long
    Dim X()
    Dim bProcessFolder As Boolean
    Dim bNewSheet As Boolean

    Dim StrPrefix
    Dim strFileName As String
    Dim strFolderName As String

    'variant declaration needed for the Shell object to use a default directory
    Dim strDefaultFolder As Variant


    bProcessFolder = True


    'set default directory here if needed
    strDefaultFolder = "G:\Operations\test\"

    'If the user is collating all the sheets to a single target sheet then the row spacing
    'to distinguish between different sheets can be set here
    lrowSpace = 1

    If bProcessFolder Then
        strFolderName = BrowseForFolder(strDefaultFolder)
        'Look for xls, xlsx, xlsm files
        strFileName = Dir(strFolderName & "\*401kk*.xls*")
    Else
        strFileName = Application _
                      .GetOpenFilename("Select file to process (*.xls*), *.xls*")
    End If

    Set Wb1 = Workbooks.Add(1)
    Set ws1 = Wb1.Sheets(1)
    If Not bNewSheet Then ws1.Range("A1:B1") = Array("workbook name", "worksheet count")

    'Turn off screenupdating, events, alerts and set calculation to manual
    With Application
        .DisplayAlerts = False
        .EnableEvents = False
        .ScreenUpdating = False
        lngCalc = .Calculation
        .Calculation = xlCalculationManual
    End With

    'set path outside the loop
    StrPrefix = strFolderName & IIf(bProcessFolder, "\", vbNullString)

    Do While Len(strFileName) > 0
        'Provide progress status to user
        Application.StatusBar = Left("Processing " & strFolderName & "\" & strFileName, 255)
        'Open each workbook in the folder of interest
        Set Wb2 = Workbooks.Open(StrPrefix & strFileName)
        If Not bNewSheet Then
            'add summary details to first sheet
            ws1.Cells(Rows.Count, "A").End(xlUp).Offset(1, 0) = Wb2.Name
            ws1.Cells(Rows.Count, "A").End(xlUp).Offset(0, 1) = Wb2.Sheets.Count
        End If
        For Each ws2 In Wb2.Sheets
            If bNewSheet Then
                'All data to a single sheet
                'Skip importing target sheet data if the source sheet is blank
                Set rng2 = ws2.Cells.Find("*", ws2.[a1], xlValues, , xlByRows, xlPrevious)

                If Not rng2 Is Nothing Then
                    Set rng1 = ws1.Cells.Find("*", ws1.[a1], xlValues, , xlByRows, xlPrevious)
                    'Find the first blank row on the target sheet
                    If Not rng1 Is Nothing Then
                        Set rng3 = ws2.Range(ws2.UsedRange.Cells(1), ws2.Cells(rng2.Row, "A"))
                        'Ensure that the row area in the target sheet won't be exceeded
                        If rng3.Rows.Count + rng1.Row < Rows.Count Then
                            'Copy the data from the used range of each source sheet to the first blank row
                            'of the target sheet, using the starting column address from the source sheet being copied
                            ws2.UsedRange.Copy ws1.Cells(rng1.Row + 1 + lrowSpace, ws2.UsedRange.Cells(1).Column)
                        Else
                            MsgBox "Summary sheet size exceeded. Process stopped on " & vbNewLine & _
                                   "sheet: " & ws2.Name & vbNewLine & "of" & vbNewLine & "workbook: " & Wb2.Name
                            Wb2.Close False
                            Exit Do
                        End If
                        'colour the first of any spacer rows
                        If lrowSpace <> 0 Then ws1.Rows(rng1.Row + 1).Interior.Color = vbGreen
                    Else
                        'target sheet is empty so copy to first row
                        ws2.UsedRange.Copy ws1.Cells(1, ws2.UsedRange.Cells(1).Column)
                    End If
                End If
            Else
                'new target sheet for each source sheet
                ws2.Copy after:=Wb1.Sheets(Wb1.Sheets.Count)
                'Remove any links in our target sheet
                With Wb1.Sheets(Wb1.Sheets.Count).Cells
                    .Copy
                    .PasteSpecial xlPasteValues
                End With
                On Error Resume Next
                Wb1.Sheets(Wb1.Sheets.Count).Name = ws2.Name
                'sheet name already exists in target workbook
                If Err.Number <> 0 Then
                    'Add a number to the sheet name till a unique name is derived
                    Do
                        lSht = lSht + 1
                        Set ws3 = Wb1.Sheets(ws2.Name & " " & lSht)
                    Loop While Not ws3 Is Nothing
                    lSht = 0
                End If
                On Error GoTo 0
            End If
        Next ws2
        'Close the opened workbook
        Wb2.Close False
        'Check whether to force a DO loop exit if processing a single file
        If bProcessFolder = False Then Exit Do
        strFileName = Dir
    Loop

    'Remove any links if the user has used a target sheet
    If bNewSheet Then
        With ws1.UsedRange
            .Copy
            .Cells(1).PasteSpecial xlPasteValues
            .Cells(1).Activate
        End With
    Else
        'Format the summary sheet if the user has created separate target sheets
        ws1.Activate
        ws1.Range("A1:B1").Font.Bold = True
        ws1.Columns.AutoFit
    End If

    With Application
        .CutCopyMode = False
        .DisplayAlerts = True
        .EnableEvents = True
        .ScreenUpdating = True
        .Calculation = lngCalc
        .StatusBar = vbNullString
    End With
End Sub


Function BrowseForFolder(Optional OpenAt As Variant) As Variant
'From Ken Puls as used in his vbaexpress.com article
'http://www.vbaexpress.com/kb/getarticle.php?kb_id=284

    Dim ShellApp As Object
    'Create a file browser window at the default folder
    Set ShellApp = CreateObject("Shell.Application"). _
                   BrowseForFolder(0, "Please choose a folder", 0, OpenAt)

    'Set the folder to that selected.  (On error in case cancelled)
    On Error Resume Next
    BrowseForFolder = ShellApp.self.Path
    On Error GoTo 0

    'Destroy the Shell Application
    Set ShellApp = Nothing

    'Check for invalid or non-entries and send to the Invalid error
    'handler if found
    'Valid selections can begin L: (where L is a letter) or
    '\\ (as in \\servername\sharename.  All others are invalid
    Select Case Mid(BrowseForFolder, 2, 1)
    Case Is = ":"
        If Left(BrowseForFolder, 1) = ":" Then GoTo Invalid
    Case Is = "\"
        If Not Left(BrowseForFolder, 1) = "\" Then GoTo Invalid
    Case Else
        GoTo Invalid
    End Select

    Exit Function

Invalid:
    'If it was determined that the selection was invalid, set to False
    BrowseForFolder = False
End Function
Community
  • 1
  • 1
brettdj
  • 54,857
  • 16
  • 114
  • 177
  • Thank you so much it seems to work well except for a the part i failed to mention in my first post.. I would like the new tabs to be moved to an existing workbook. Basically i would like to run the macro from the consolidated workbook and add the new tabs to the end of the existing tabs – Abd Dec 20 '15 at 23:23
  • Never mind i figured it out.. I just set Wb1 = ThisWorkbook – Abd Dec 21 '15 at 15:17
  • I am getting an error when one of the worksheets has a pivot table. Is there a way to work around that? – Abd Dec 29 '15 at 20:35
  • I would like to modify to code below to do the following: Instead of copying and pasting the content of each tab to a new workbook, i would like to move the whole tab over to the new workbook without(Create another copy on the new workbook).. The goal is to be able to move all the content. The issue with the current way of moving the data is that it doesn't bring over the images – Abd Jan 15 '16 at 15:47
0

You can manipulate the following to suit your needs. add multiple OR clauses in the if statement, and adjust the folder paths appropriately! it will transfer the sheets into the workbook which is holding the code!

Sub main()

Dim fso As New Scripting.FileSystemObject
Dim file As Scripting.file
Dim fldr As Scripting.Folder
Dim wb As Excel.Workbook
Set fldr = fso.GetFolder("c:\excelfiles\")
Dim target As String

Dim cwb As Workbook
Set cwb = ActiveWorkbook

For Each file In fldr.Files()
target = file.Name

If file.Name = "tasks.xlsx" Then
i = 1
Application.Workbooks.Open (fldr.Path & "\" & file.Name)
Set wb = Application.Workbooks(target)
    For Each sht In wb.Sheets
         If wb.Sheets(i).Name = "home" Then
            wb.Sheets(i).Copy after:=cwb.Sheets(1)
            i = i + 1
        End If
    Next
End If
Next

Set wb = Nothing
Set file = Nothing
Set fldr = Nothing
Set xls = Nothing
Set fso = Nothing

End Sub
brettdj
  • 54,857
  • 16
  • 114
  • 177
dford07
  • 47
  • 6
  • This doesn't get to the question. It opens only a single file - rather than a number of files based on a string - and then looks to copy only 1 sheet named "home". Which was not specified by the OP – brettdj Dec 17 '15 at 04:34