• 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.

Amendment help in the macro

Jagdev Singh

Active Member
Hi Experts

The Attached macro is working fine when I have to extract data from several sheets into one sheet. This worked fine when the different sheets consist of only one tab/sheet in it. Is it possible to amend the code and the macro picks all the sheets/tabs available in the sheet instead of only one.

Regards,
JD
 

Attachments

  • Merge_different_sheet_tool.xls
    52 KB · Views: 7
Hi Experts,

I think the code which needs to be tweaked is this:
Code:
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
 
Hi Experts

Please help me to tweak the above code to extra data from all the sheets and tabs instead of extracting the first tab from the sheet.

Regards
JD
 

Hi,

you had posted a sub procedure but where is main code calling it ?!

If by hell you just found it on the net and had thrown it to this forum,
just forget it !

________________________________________________________
Je suis Charlie
 
Hi Marc

The macro attached in the thread contains the main procedure with the sub procedure as well. The code I pasted in the above thread is where I feel needs amendment to meet my need.

The macro is working fine to extract one tab from the sheet. I want to exact all the tab from the sheet. I am looking to amend the code to make it exact all the tabs from the sheet.

Regards
JD
 

Nothing to tweak to this procedure made to get a sheet
if your ever read its parameters !

Just be logical and modify the main code …
 
Hi Marc

The main code is as follow. Please help me with the amendment.

Code:
Option Explicit
Sub Copy_Sheet()
    Dim myFiles As Variant
    Dim myCountOfFiles As Long
 
    myCountOfFiles = Get_File_Names( _
                    MyPath:=InputBox("Enter a full path to workbooks"), _
                    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_Sheet _
            PasteAsValues:=True, _
            SourceShName:="", _
            SourceShIndex:=1, _
            myReturnedFiles:=myFiles
 
End Sub

Rest of the function codes are as follow:

Code:
Option Explicit
 
Private myFiles() As String
Private Fnum As Long
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
 
 
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)
 
    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)
 
    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
 

Before to call GetSheet procedure, use a loop like
For W& = 1 To Worksheets.Count

Amend the call of the GetSheet procedure with this variable W
as worksheet index …

And don't forget Next statment to close the loop, very beginner level …
 
Hi Marc

I followed the instruction but unclear with the call "GetSheet Procedure"

Code:
Sub Copy_Sheet()
    Dim myFiles As Variant
    Dim myCountOfFiles As Long
 
    myCountOfFiles = Get_File_Names( _
                    MyPath:=InputBox("Enter a full path to workbooks"), _
                    Subfolders:=False, _
                    ExtStr:="*.xl*", _
                    myReturnedFiles:=myFiles)
 
    If myCountOfFiles = 0 Then
        MsgBox "No files that match the ExtStr in this folder"
        Exit Sub
    End If
For W = 1 To Worksheets.Count
    Get_Sheet _
            PasteAsValues:=True, _
            SourceShName:="", _
            SourceShIndex:=1, _
            myReturnedFiles:=myFiles
            Next
 
End Sub
 

You forgot this :
Amend the call of the GetSheet procedure with this variable W
as worksheet index …
Actualy you call the sheet index #1 … :rolleyes:
____________________________________________________________
To code is not to Copy / Paste …
 
Hi Marc

I amended the code and it is working, but still not extracting data from both the sheets/tab in case if a sheet contains data in 2 tabs. The code is still picking the data from the first tab only.

Code:
Sub Copy_Sheet()
    Dim myFiles As Variant
    Dim myCountOfFiles As Long
    Dim W As Integer
    myCountOfFiles = Get_File_Names( _
                    MyPath:=InputBox("Enter a full path to workbooks"), _
                    Subfolders:=False, _
                    ExtStr:="*.xl*", _
                    myReturnedFiles:=myFiles)
    If myCountOfFiles = 0 Then
        MsgBox "No files that match the ExtStr in this folder"
        Exit Sub
    End If
For W = 1 To Worksheets.Count
    Get_Sheet _
            PasteAsValues:=True, _
            SourceShName:="", _
            SourceShIndex:=W, _
            myReturnedFiles:=myFiles
            Next
End Sub
 

So you have to follow the code with step by step mode (hit F8 key)

to find out where the problem is …
 
Hi Marc

I tried that as well. The loop which we added in the code is not picking the tabs, which ideally it should. It is just executing once and moving out to sub procedure "Get_Sheet". The rest of the operation is done in the subprocedure. I believe something needs to be done with the subprocedure. Which I highlighted in the thread above.

Code:
For W = 1 To Worksheets.Count
    Get_Sheet _
            PasteAsValues:=True, _
            SourceShName:="", _
            SourceShIndex:=W, _
            myReturnedFiles:=myFiles
            Next

Regards,
JD
 

Ask to the one who made this so smart code …

When you pick up a code which not really does what you need,
you'll waste more time to understand and amend it than creating your own !
 
True Mark! Ideally it was filling my requirement. I think it is better to leave it here and I should think of creating the one seperately to match my need.

Thanks for all your support Marc.

Regards,
JD
 
Hi Experts

The below code suits my need. Currently the code is pasting the data from multiple sheets into the same macro sheet. Is it possible to create a new sheet and the data from the multiple sheets paste in the new sheet.

Code:
Option Explicit
Declare Function SHGetPathFromIDList Lib "shell32.dll" _
Alias "SHGetPathFromIDListA" (ByVal pidl As Long, ByVal _
pszpath As String) As Long
Declare Function SHBrowseForFolder Lib "shell32.dll" _
Alias "SHBrowseForFolderA" (lpBrowseInfo As BrowseInfo) _
As Long
Public Type BrowseInfo
    hOwner As Long
    pIDLRoot As Long
    pszDisplayName As String
    lpszTitle As String
    ulFlags As Long
    lpfn As Long
    lParam As Long
    iImage As Long
End Type
Function GetDirectory(Optional msg) As String
    On Error Resume Next
    Dim bInfo As BrowseInfo
    Dim path As String
    Dim r As Long, x As Long, pos As Integer
   
    'Root folder = Desktop
    bInfo.pIDLRoot = 0&
   
    'Title in the dialog
    If IsMissing(msg) Then
        bInfo.lpszTitle = "Please select the folder of the excel files to copy."
    Else
        bInfo.lpszTitle = msg
    End If
   
    'Type of directory to return
    bInfo.ulFlags = &H1
   
    'Display the dialog
    x = SHBrowseForFolder(bInfo)
   
    'Parse the result
    path = Space$(512)
    r = SHGetPathFromIDList(ByVal x, ByVal path)
    If r Then
        pos = InStr(path, Chr$(0))
        GetDirectory = Left(path, pos - 1)
    Else
        GetDirectory = ""
    End If
End Function
Sub CombineFiles()
    Dim path            As String
    Dim FileName        As String
    Dim LastCell        As Range
    Dim Wkb            As Workbook
    Dim WS              As Worksheet
    Dim ThisWB          As String
   
    ThisWB = ThisWorkbook.Name
    Application.EnableEvents = False
    Application.ScreenUpdating = False
    path = GetDirectory
    FileName = Dir(path & "\*.xls", vbNormal)
    Do Until FileName = ""
        If FileName <> ThisWB Then
            Set Wkb = Workbooks.Open(FileName:=path & "\" & FileName)
            For Each WS In Wkb.Worksheets
                Set LastCell = WS.Cells.SpecialCells(xlCellTypeLastCell)
                If LastCell.Value = "" And LastCell.Address = Range("$A$1").Address Then
                Else
                    WS.Copy After:=ThisWorkbook.Sheets(ThisWorkbook.Sheets.Count)
                End If
            Next WS
            Wkb.Close False
        End If
        FileName = Dir()
    Loop
    Application.EnableEvents = True
    Application.ScreenUpdating = True
   
    Set Wkb = Nothing
    Set LastCell = Nothing
End Sub
 
Back
Top