最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

vba - Excel stacking exact worksheets and sheets on top of each other (each worksheet has same sheet names) - Stack Overflow

programmeradmin4浏览0评论

If anyone can help please as I cannot find this situation I am looking into on the web. I find examples but they all put into one sheet not honour the originally named sheet name. I have given example of input and output sheets below:-

I have multiple excel worksheets but these worksheets have the same sheet names in each e.g.

a.xlsx. first sheet "fred" with columns:

VAR1 VAR2
1 a

If anyone can help please as I cannot find this situation I am looking into on the web. I find examples but they all put into one sheet not honour the originally named sheet name. I have given example of input and output sheets below:-

I have multiple excel worksheets but these worksheets have the same sheet names in each e.g.

a.xlsx. first sheet "fred" with columns:

VAR1 VAR2
1 a

second sheet "bill" with columns:

VAR98 VAR99
4 c

b.xlsx first sheet also called "fred" with columns:

VAR1 VAR2
2 b

second sheet also called "bill" with columns

VAR98 VAR99
5 x

I would want to set each excel worksheet on top of each other into a new worksheet called consolidated.xlsx but I want to retain the name of the source file into the first column of each sheet. I also want to retain the sheet names as they are consistent in each worksheet.

The result I would like: new worksheet completed called consolidated.xlsx first sheet: "fred" contains columns:

SOURCE VAR1 VAR2
a.xlsx 1 a
b.xlsx 2 b

second sheet "bill" contains columns:

SOURCE VAR98 VAR99
a.xlsx 4 c
b.xlsx 5 x

For the input excel spreadsheets I want to be able to select the folder to loop through the names so don't want the code to have a.xlsx, b.xlsx. Also I want the code to dynamically read the sheet names in each sheet I don't want code to have them named as fred and bill etc. That said I know the sheets are consistently named across each worksheet that will be used and I know that the column names equally are going to be the same. When the rows in each separate worksheet gets concatenated/set into the same sheet name ideally I don't want any blank rows as I would like to be able to filter easily.

Please if anyone can help as I find nothing on forums that preserve the sheets from the original source file they only put everthing into a new sheet called sheet1 which I don't want. I hope this all makes sense?

The code I am currently using is this but it only appends to the first sheet everything but I want it to do a setting the sheets on top of each other in the same format they were originally into a master excel file. I also want to keep the source file as a column so within a sheet I can identify where the append has come from

Sub ConsolidateWorkbooks()
    Dim ws As Worksheet
    Dim wsDest As Worksheet
    Dim wbSource As Workbook
    Dim wbDest As Workbook
    Dim lastRow As Long
    Dim fileDialog As fileDialog
    Dim filePath As Variant
    Dim fileChosen As Integer
   
    ' Create a new workbook for consolidation
    Set wbDest = Workbooks.Add
   
    ' Open file dialog to select workbooks
    Set fileDialog = Application.fileDialog(msoFileDialogFilePicker)
    fileDialog.AllowMultiSelect = True
    fileDialog.Filters.Add "Excel Files", "*.xls; *.xlsx; *.xlsm", 1
    fileChosen = fileDialog.Show
   
    If fileChosen <> -1 Then Exit Sub ' Exit if no files are chosen
   
    ' Loop through each selected file
    For Each filePath In fileDialog.SelectedItems
        Set wbSource = Workbooks.Open(filePath)
       
        ' Loop through each worksheet in the source workbook
        For Each ws In wbSource.Worksheets
            On Error Resume Next
            Set wsDest = wbDest.Worksheets(ws.Name)
            On Error GoTo 0
           
            ' If the worksheet does not exist in the destination workbook, create it
            If wsDest Is Nothing Then
                Set wsDest = wbDest.Worksheets.Add(After:=wbDest.Sheets(wbDest.Sheets.Count))
                wsDest.Name = ws.Name
            End If
           
            ' Find the last row in the destination worksheet
            If Application.WorksheetFunction.CountA(wsDest.Cells) = 0 Then
                lastRow = 1
            Else
                lastRow = wsDest.Cells(wsDest.Rows.Count, "A").End(xlUp).Row + 1
            End If
           
            ' Copy and paste values from source to destination worksheet
            ws.UsedRange.Copy
            wsDest.Cells(lastRow, 1).PasteSpecial Paste:=xlPasteValues
        Next ws
       
        ' Close the source workbook without saving
        wbSource.Close SaveChanges:=False
    Next filePath
   
    ' Clean up
    Application.CutCopyMode = False
    Set wbSource = Nothing
    Set wbDest = Nothing
    Set fileDialog = Nothing
End Sub

Thanks Rob

Share Improve this question edited Mar 20 at 13:56 Rob Oakley asked Mar 19 at 12:14 Rob OakleyRob Oakley 112 bronze badges 5
  • 5 Hi and welcome to S.O. Please note that this is not a free code writing service. That said, if you could edit your question to show us the code you have so far and an explanation of how it fails to achieve the desired goal, we'll be happy to take a look and suggest a solution. You may also want to consider providing sample data and expected outcome as tables – cybernetic.nomad Commented Mar 19 at 13:00
  • Sorry this is my bad I am new to this group. I have added code now which is the closest I have got to solving this one – Rob Oakley Commented Mar 20 at 10:17
  • 1 I have voted to reopen your question, but there are two more votes necessary. Not sure if this will happen since your ChatGPT code doesn't come close. Either way, feel free to download my working file from my Google Drive. On the top-right is the download icon. – VBasic2008 Commented Mar 20 at 13:10
  • Sheets with the same name share the same columns, but are the columns always in the same order? – Tim Williams Commented Mar 20 at 16:03
  • Thanks, yes sheets with same name share the same column names and column names are always in the same order. If you like the excels started out as a empty template with column names fixed and different users have added different data but I want to pull all this together into one big file to examine the differences in user input visually. – Rob Oakley Commented Mar 20 at 16:16
Add a comment  | 

1 Answer 1

Reset to default 0

Consolidate Workbooks

  • It is assumed that all the selected workbooks have the same worksheets with the same columns and the data is contiguous with one row of headers.
  • In the first iteration, all sheets of the workbook are copied to a new workbook, the destination workbook, in one go and the formatting and formulas are removed. In the subsequent iterations, each source worksheet's data (no headers) is copied as values below the existing data in the corresponding worksheets of the destination workbook.
  • In all destination worksheets, a column is added to hold the names of the workbooks where the data came from.
Sub ConsolidateWorkbooks()
    
    Const SOURCE_COLUMN_TITLE As String = "Source"
    
    ' Open file dialog to select workbooks.
    Dim sFilePaths As FileDialogSelectedItems
    With Application.FileDialog(msoFileDialogFilePicker)
        .AllowMultiSelect = True
        .Filters.Add "Excel Files", "*.xls; *.xlsx; *.xlsm", 1
        If .Show = 0 Then Exit Sub ' cancelled
        Set sFilePaths = .SelectedItems
    End With
        
    Dim IsFirstWorkbook As Boolean: IsFirstWorkbook = True
    
    Application.ScreenUpdating = False
    
    Dim swb As Workbook, sws As Worksheet, srg As Range
    Dim sFilePath As Variant, swbName As String, RowsCount As Long
    Dim dwb As Workbook, dws As Worksheet, drg As Range, dcell As Range
        
    ' Loop through the selected files.
    For Each sFilePath In sFilePaths
        ' Open the source workbook.
        Set swb = Workbooks.Open(sFilePath)
        swbName = swb.Name
        ' Copy values.
        If IsFirstWorkbook Then ' first workbook
            swb.Worksheets.Copy
            Set dwb = Workbooks(Workbooks.Count)
            For Each dws In dwb.Worksheets
                With dws.Range("A1").CurrentRegion
                    .ClearFormats
                    .Value = .Value
                    RowsCount = .Rows.Count - 1
                    If RowsCount > 0 Then
                        With .Columns(1).Offset(, .Columns.Count)
                            .Cells(1) = SOURCE_COLUMN_TITLE
                            .Resize(RowsCount).Offset(1).Value = swbName
                        End With
                    End If
                End With
            Next dws
            IsFirstWorkbook = False
        Else ' all but first workbook
            For Each sws In swb.Worksheets
                Set dws = Nothing
                On Error Resume Next
                    Set dws = dwb.Worksheets(sws.Name)
                On Error GoTo 0
                If dws Is Nothing Then ' sheet doesn't exist
                    sws.Copy After:=dwb.Sheets(dwb.Sheets.Count)
                    Set dws = dwb.Sheets(dwb.Sheets.Count)
                    With dws.Range("A1").CurrentRegion
                        .ClearFormats
                        .Value = .Value
                        RowsCount = .Rows.Count - 1
                        If RowsCount > 0 Then
                            With .Columns(1).Offset(, .Columns.Count)
                                .Cells(1) = SOURCE_COLUMN_TITLE
                                .Resize(RowsCount).Offset(1).Value = swbName
                            End With
                        End If
                    End With
                Else ' sheet exists
                    With dws.Range("A1").CurrentRegion
                        Set dcell = .Cells(1).Offset(.Rows.Count)
                    End With
                    With sws.Range("A1").CurrentRegion
                        RowsCount = .Rows.Count - 1
                        If RowsCount > 0 Then
                            Set srg = .Resize(RowsCount).Offset(1)
                            Set drg = dcell.Resize(RowsCount, srg.Columns.Count)
                            drg.Value = srg.Value
                            drg.Columns(1).Offset(, drg.Columns.Count) _
                                .Value = swbName
                        End If
                    End With
                End If
            Next sws
        End If
        ' Close the source workbook.
        swb.Close SaveChanges:=False
    Next sFilePath
    
    Application.ScreenUpdating = True
    
    MsgBox "Workbooks consolidated.", vbInformation

End Sub

与本文相关的文章

发布评论

评论列表(0)

  1. 暂无评论