• Hi All

    Please note that at the Chandoo.org Forums there is Zero Tolerance to Spam

    Post Spam and you Will Be Deleted as a User

    Hui...

  • When starting a new post, to receive a quicker and more targeted answer, Please include a sample file in the initial post.

VBA help on loop and copy specific range

Anand307

Member
I have approximately 30 workbooks in a folder (Named serially) and looking to loop through all the files and copy a specific range from each workbook one below the other, I have a code from internet, which I tried to amend to suite my case, but iam unable to get through doing this so easy, please help -



The sheet name in workbook would be as BreakMetrics and it would be hidden when the workbook is opened, hence we need to first unhide this sheet BreakMetrics and then copy range D170:F170 to a new workbook one below the other along with the source file name in adjacent column, help appreciated.



Attached a sample workbook for test purpose.
 

Attachments

  • Test 1.xlsm
    76.2 KB · Views: 7
Code:
Option Explicit
Sub RDB_Merge_Data_Browse()
    Dim myFiles As Variant
    Dim myCountOfFiles As Long
    Dim oApp As Object
    Dim oFolder As Variant
    Set oApp = CreateObject("Shell.Application")
     'Browse to the folder
    Set oFolder = oApp.BrowseForFolder(0, "Select folder", 512)
    If Not oFolder Is Nothing Then
        myCountOfFiles = Get_File_Names( _
        MyPath:=oFolder.Self.path, _
        Subfolders:=False, _
        ExtStr:="*.xl*", _
        myReturnedFiles:=myFiles)
        If myCountOfFiles = 0 Then
            MsgBox "No files that match the ExtStr in this folder"
            Exit Sub
        End If
        Get_Data _
        FileNameInA:=False, _
        PasteLink:=True, _
        SourceShName:="Break metrics", _
        SourceShIndex:=2, _
        SourceRng:="D170:F170", _
        StartCell:="", _
        myReturnedFiles:=myFiles
    End If
End Sub

Sub Get_Data(FileNameInA As Boolean, PasteLink As Boolean, SourceShName As String, _
    SourceShIndex As Integer, SourceRng As String, StartCell As String, myReturnedFiles As Variant)
    Dim SourceRcount As Long
    Dim sourceRange As Range, destrange As Range
    Dim mybook As Workbook, BaseWks As Worksheet
    Dim rnum As Long, 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
        .DisplayAlerts = False
    End With
     'Add a new workbook with one sheet named "Combine Sheet"
     ' come back later and see if I can change this to my template workbook with Set BaseWks = Activeworkbook.Activeworksheets(Sheet1)
    Set BaseWks = Workbooks.Add(xlWBATWorksheet).Worksheets(1)
    BaseWks.Name = "Combine Sheet"
     'Set start row for the Data
    rnum = 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
            If LCase(SourceShName) <> "all" Then
                 'Set SourceRange and check if it is a valid range
                On Error Resume Next
                If StartCell <> "" Then
                    With mybook.Sheets(SourceSh)
                        Set sourceRange = .Range(StartCell & ":" & RDB_Last(3, .Cells))
                         'Test if the row of the last cell >= then the row of the StartCell
                        If RDB_Last(1, .Cells) < .Range(StartCell).Row Then
                            Set sourceRange = Nothing
                        End If
                    End With
                Else
                    With mybook.Sheets(SourceSh)
                        Set sourceRange = Application.Intersect(.UsedRange, .Range(SourceRng))
                    End With
                End If
                If Err.Number > 0 Then
                    Err.Clear
                    Set sourceRange = Nothing
                Else
                     'if SourceRange use all columns then skip this file
                    If sourceRange.Columns.count >= BaseWks.Columns.count Then
                        Set sourceRange = Nothing
                    End If
                End If
                On Error GoTo 0
                If Not sourceRange Is Nothing Then
                     'Check if there enough rows to paste the data
                    SourceRcount = sourceRange.Rows.count
                    If rnum + SourceRcount >= BaseWks.Rows.count Then
                        MsgBox "Sorry there are not enough rows in the sheet to paste"
                        mybook.Close SaveChanges:=False
                        BaseWks.Parent.Close SaveChanges:=False
                        GoTo ExitTheSub
                    End If
                     'Set the destination cell
                    If FileNameInA = True Then
                        Set destrange = BaseWks.Range("B" & rnum)
                        With sourceRange
                            BaseWks.Cells(rnum, "A"). _
                            Resize(.Rows.count).Value = myReturnedFiles(i)
                        End With
                    Else
                        Set destrange = BaseWks.Range("A" & rnum)
                    End If
                     'Copy/paste the data
                    If PasteLink = True Then
                        With sourceRange
                            Set destrange = destrange. _
                            Resize(.Rows.count, .Columns.count)
                        End With
                        destrange.Value = sourceRange.Value
                    Else
                        sourceRange.Copy destrange
                    End If
                    rnum = rnum + SourceRcount
                End If
                 'Close the workbook without saving
                mybook.Close SaveChanges:=False
            Else
                 'Loop through all sheets in mybook
                For Each sh In mybook.Worksheets
                     'Set SourceRange and check if it is a valid range
                    On Error Resume Next
                    If StartCell <> "" Then
                        With sh
                            Set sourceRange = .Range(StartCell & ":" & RDB_Last(3, .Cells))
                            If RDB_Last(1, .Cells) < .Range(StartCell).Row Then
                                Set sourceRange = Nothing
                            End If
                        End With
                    Else
                        With sh
                            Set sourceRange = Application.Intersect(.UsedRange, .Range(SourceRng))
                        End With
                    End If
                    If Err.Number > 0 Then
                        Err.Clear
                        Set sourceRange = Nothing
                    Else
                         'if SourceRange use almost all columns then skip this file
                        If sourceRange.Columns.count > BaseWks.Columns.count - 2 Then
                            Set sourceRange = Nothing
                        End If
                    End If
                    On Error GoTo 0
                    If Not sourceRange Is Nothing Then
                         'Check if there enough rows to paste the data
                        SourceRcount = sourceRange.Rows.count
                        If rnum + SourceRcount >= BaseWks.Rows.count Then
                            MsgBox "Sorry there are not enough rows in the sheet to paste"
                            mybook.Close SaveChanges:=False
                            BaseWks.Parent.Close SaveChanges:=False
                            GoTo ExitTheSub
                        End If
                         'Set the destination cell
                        If FileNameInA = True Then
                            Set destrange = BaseWks.Range("C" & rnum)
                            With sourceRange
                                BaseWks.Cells(rnum, "A"). _
                                Resize(.Rows.count).Value = myReturnedFiles(i)
                                BaseWks.Cells(rnum, "B"). _
                                Resize(.Rows.count).Value = sh.Name
                            End With
                        Else
                            Set destrange = BaseWks.Range("A" & rnum)
                        End If
                         'Copy/paste the data
                        If PasteLink = True Then
                            With sourceRange
                                Set destrange = destrange. _
                                Resize(.Rows.count, .Columns.count)
                            End With
                            destrange.Link = sourceRange.Value
                        Else
                            sourceRange.Copy destrange
                        End If
                        rnum = rnum + SourceRcount
                    End If
                Next sh
                 'Close the workbook without saving
                mybook.Close SaveChanges:=False
            End If
        End If
         'Open the next workbook
    Next i
     'Set the column width in the new workbook
    BaseWks.Columns.AutoFit
ExitTheSub:
     'Restore ScreenUpdating, Calculation and EnableEvents
    With Application
        .ScreenUpdating = True
        .EnableEvents = True
        .Calculation = CalcMode
        .DisplayAlerts = False
    End With
End Sub

Existing code.
 
Upload sample of workbook where you copy data from.

Likely, you don't need most of checks performed on the code you posted, with shorter/simpler code.
 
...not the workbook to consolidate other workbooks. Sample of workbook where the data is kept (with sample data set).
 
The previous attached is the sample workbook(i have just provided one sample workbook) similarly there are 30 workbooks named serially in a folder. the sheet that we are looking into would be hidden(BreakMetrics ), and the range in this sheet (BreakMetrics ) is D170:F170 needs to be copied from every workbook in folder to a new output file.
 
Ok, but what's the file name convention. And how should each line be identified?

Should the file name be used to identify where each copied line came from?
 
Try this. No need to unhide sheet.

Code:
Sub copyRange()
Dim sWb As Workbook
Dim sWs As Worksheet, dWs As Worksheet
Dim fd As FileDialog
Dim MyPath As String
Dim lRow As Long

Set fd = Application.FileDialog(msoFileDialogFolderPicker)
Set dWs = ThisWorkbook.Worksheets("Sheet1") 'Change worksheet as needed

With fd
    .Title = "Select a Target Folder"
    .AllowMultiSelect = False
    .InitialFileName = "C:\Test\" 'Change this to initial folder of your choice
    If .Show <> -1 Then GoTo NextCode
    MyPath = .SelectedItems(1) & "\"
End With

NextCode:
    MyPath = MyPath
    If MyPath = "" Then Exit Sub
   
currpath = Dir(MyPath)

Do While currpath <> ""
    If InStr(currpath, ".xl") > 0 Then
        Set sWb = Workbooks.Open(MyPath & currpath)
        Set sWs = sWb.Sheets("BreakMetrics ")
        lRow = dWs.Cells(Rows.Count, 1).End(xlUp).Row + 1 'Change Column index as needed
        sWs.Range("D170:F170").Copy
        dWs.Cells(lRow, 1).PasteSpecial Paste:=xlPasteValues
        dWs.Cells(lRow, 4).Value = currpath
        sWb.Close False
    End If
    currpath = Dir()
Loop

End Sub
 

Attachments

  • Sample_Macro.xlsb
    15.9 KB · Views: 4
Back
Top