【问题标题】:Merge Excel workbooks to one Worksheet将 Excel 工作簿合并到一个工作表
【发布时间】:2020-06-03 07:58:51
【问题描述】:

我正在尝试将 250 个数据库 Excel 工作簿合并到一个连续的工作表中。
所有工作簿都具有相同类型的数据,具有相同的标题。

我已尝试使用此 VBA 代码:

Sub mergeFiles()
    'Merges all files in a folder to a main file.
    
    'Define variables:
    Dim numberOfFilesChosen, i As Integer
    Dim tempFileDialog As fileDialog
    Dim mainWorkbook, sourceWorkbook As Workbook
    Dim tempWorkSheet As Worksheet
    
    Set mainWorkbook = Application.ActiveWorkbook
    Set tempFileDialog = Application.fileDialog(msoFileDialogFilePicker)
    
    'Allow the user to select multiple workbooks
    tempFileDialog.AllowMultiSelect = True
    
    numberOfFilesChosen = tempFileDialog.Show
    
    'Loop through all selected workbooks
    For i = 1 To tempFileDialog.SelectedItems.Count
        
        'Open each workbook
        Workbooks.Open tempFileDialog.SelectedItems(i)
        
        Set sourceWorkbook = ActiveWorkbook
        
        'Copy each worksheet to the end of the main workbook
        For Each tempWorkSheet In sourceWorkbook.Worksheets
            tempWorkSheet.Copy after:=mainWorkbook.Sheets(mainWorkbook.Worksheets.Count)
        Next tempWorkSheet
        
        'Close the source workbook
        sourceWorkbook.Close
    Next i
    
End Sub

代码工作正常,但它为每个工作簿创建一个新工作表,而不是将数据复制到 1 个工作表的底行。

【问题讨论】:

  • 它的行为与代码设计的完全一样:tempWorkSheet.Copy after:=mainWorkbook.Sheets(mainWorkbook.Worksheets.Count)... 您需要获取页面内容并将其删除。每次,在最后一行数据之后。我避免了“复制”,因为它不是最好的方法……那么,您是否希望将工作表内容从第二行复制到包含数据的最后一行?它的所有列都填充到同一行?如果不是,哪些被视为参考(最长)?
  • 要记住的一点是 Excel 对每张工作表的行数限制。如果超过了,就会报错。
  • 工作簿的行数不同。所以我有工作簿:'Fleet A' 列 A 到 G 充满了汽车信息,如 VIN 型号等。工作簿车队 A 可能包含 50 辆汽车(行),工作簿车队 B 可能包含 5000 辆汽车。我想将所有工作簿合并成一个连续的汽车文件(行)
  • @AndreasKamper:我的问题不同......让我换个说法:在'Fleet A'中,所有列都填充了同一行的数据?我的意思是,如果我计算 A:A 列的最后一个空行,那是否正确?除此之外,如果您的工作表中将移动数据的主工作簿中的工作表为空(可能是第一次),则标题也将被复制。从第二个文件开始,要移动的范围将从第二行(标题除外)开始到保存数据的最后一行(即使这个文件与另一个文件不同)。 我的理解正确吗
  • 没错

标签: excel vba merge


【解决方案1】:

我准备了一种非常快速的数据移动方法(使用数组并在内存中工作),避免复制和粘贴。

  1. 在您的声明区域复制此新声明:

    Dim sh As Worksheet, arrCopy As Variant, lastR As Long

  2. 在循环之前复制此代码行 (For i = 1 To ...):

    Set sh = mainWorkbook.Sheets(mainWorkbook.Worksheets.count) 'You can use here your sheet where the data will be collected. I used the last sheet for easy testing reason

  3. 将现有代码 (tempWorkSheet.Copy after:=mainWorkbook.Sheets(mainWorkbook.Worksheets.Count)) 替换为下一个代码:

    lastR = sh.Range("A" & sh.Rows.count).End(xlUp).row

    arrCopy = tempWorkSheet.Range(tempWorkSheet.Range("A" & IIf(lastR = 1, 1, 2)), _ tempWorkSheet.Range("A1").SpecialCells(xlLastCell)).Value sh.Range("A" & lastR + IIf(lastR = 1, 0, 1)).Resize(UBound(arrCopy, 1), _ UBound(arrCopy, 2)).Value = arrCopy

我的解决方案将复制所有工作表内容(包括标题)以在空工作表的情况下收集数据,然后,数据范围从第二行开始。

您的完整代码应该是为了工作(未经测试):

Sub mergeFiles()
'Define variables:
Dim numberOfFilesChosen, i As Integer
Dim tempFileDialog As FileDialog
Dim mainWorkbook, sourceWorkbook As Workbook
Dim sh As Worksheet, arrCopy As Variant, lastR As Long
Dim tempWorkSheet As Worksheet, lastRtemp As Long

Set mainWorkbook = Application.ActiveWorkbook
Set tempFileDialog = Application.FileDialog(msoFileDialogFilePicker)

'Allow the user to select multiple workbooks
tempFileDialog.AllowMultiSelect = True

numberOfFilesChosen = tempFileDialog.Show

'You can use here your sheet where the data will be collected. I used the last sheet for easy testing reason
Set sh = mainWorkbook.Sheets(mainWorkbook.Worksheets.count)

    'Loop through all selected workbooks
    For i = 1 To tempFileDialog.SelectedItems.count

        'Open each workbook
        Workbooks.Open tempFileDialog.SelectedItems(i)

        Set sourceWorkbook = ActiveWorkbook

        'Copy each worksheet to the end of the main workbook
        Set tempWorkSheet = sourceWorkbook.Worksheets(1)
            lastR = sh.Range("A" & sh.Rows.count).End(xlUp).row
            lastRtemp = tempWorkSheet.Range("A" & tempWorkSheet.Rows.count).End(xlUp).row
            If lastRtemp < 2 Then
                MsgBox "The workbook " & tempWorkSheet.Name & " contains less the two rows..."
            Else
                arrCopy = tempWorkSheet.Range(tempWorkSheet.Range("A" & IIf(lastR = 1, 1, 2)), _
                  tempWorkSheet.Range("A1").SpecialCells(xlLastCell)).Value
                sh.Range("A" & lastR + IIf(lastR = 1, 0, 1)).Resize(UBound(arrCopy, 1), _
                                        UBound(arrCopy, 2)).Value = arrCopy
            End If

        'Close the source workbook
        sourceWorkbook.Close
    Next i
End Sub

【讨论】:

【解决方案2】:

我使用以下宏将许多 CSV 文件合并到一个新工作簿的一个工作表中。您可能需要进行一些更改以满足您的需要

Sub GetFromCSVs()
  Dim WB As Workbook
  Dim R As Range
  Dim bFirst As Boolean
  Dim stFile As String
  Dim stPath As String
  stPath = "D:\CSV Files\" ' change the path to suit
  stFile = Dir(stPath & "*.csv")
  'bFirst = True
  Set R = Workbooks.Add(xlWorksheet).Sheets(1).Range("A1")
  Do Until stFile = ""
    Set WB = Workbooks.Open(stPath  & stFile, ReadOnly:=True)
    'If bFirst Then
     ' WB.Sheets(1).Range("A1").CurrentRegion.Copy Destination:=R
      WB.Sheets(1).Range(Selection, Range("A1").SpecialCells(xlLastCell)).Copy Destination:=R
      Set R = R.Offset(R.SpecialCells(xlLastCell).Row + 1 - R.Row, 0)

      'Set R = Range("A1").Offset(ActiveCell.SpecialCells(xlLastCell).Row, 0)
      'bFirst = False
    'Else
      'WB.Sheets(1).Range("A1").CurrentRegion.Columns(2).Copy Destination:=R
      'Set R = R.Offset(, 1)
    'End If
    WB.Close saveChanges:=False
    stFile = Dir()  ' next file
  Loop
End Sub

【讨论】:

  • 我认为 Set WB = Workbooks.Open(stPath &amp; stFile, ReadOnly:=True) 应该是 Set WB = Workbooks.Open(stFile, ReadOnly:=True) 因为 stFile 已经定义为包含 stPath
  • 另外,请注意它会复制源表中的列标题。如果您不希望它们在循环之前设置 bFirst = true 并更改循环代码后使用注释掉的 if 条件 If bFirst Then
  • 当我尝试运行此代码时,它会打开一个新工作表,但不会从我的数据库中添加任何数据。我应用错了吗?
  • 检查文件扩展名,我共享的代码是“*.csv”)。如果您的来源是 excel 文件,请使用 stFile = Dir(stPath &amp; "*.xls*")
  • 文件是 .csv
猜你喜欢
  • 2015-09-07
  • 1970-01-01
  • 1970-01-01
  • 2014-12-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多