【问题标题】:Adding a column to multiple excel spreadsheets, with column entries being the name of the excel filename. Then combining sheets into one spreadsheet向多个 Excel 电子表格添加一列,列条目是 Excel 文件名的名称。然后将工作表合并到一个电子表格中
【发布时间】:2019-12-03 19:38:47
【问题描述】:

我需要将多个电子表格合并到一个工作簿中,还要合并到一个合并的电子表格中。每个文件有 1000 多行,三个目录大约有 40-50 个这样的文件。这些可以单独组合,因为它们代表三年的人事记录。

我有一个 VBA 宏,可以成功地将工作表放入一个工作簿中。我还有一个宏,用于将这些工作表组合到一个附加的电子表格中。但是,我需要在组合文件的第一行之后取出每个连续文件数据添加的标题行。

此外,我需要使用宏在每个文件中创建一列,每行填充文件名(这样,一旦与其他文件合并,就可以清楚每个数据点来自哪个源)或找到一个在组合工作表时执行此操作的宏。如果是前者使用对每个文件执行此操作的宏,在我使用单个电子表格组合宏之前,那么我需要的只是更新我的最终宏,它只为第一行放置一个标题行。以下是数据示例:

我需要最终文件在 A 中的列(新创建的列)中包含该行所来自的每个文件源的文件名。请参阅下面的示例,了解我希望组合结果的样子:

这是我用于将多个选项卡/电子表格组合到一个电子表格中的宏:

Sub Merge_Sheets()
    'Insert a new worksheet
    Sheets.Add

    'Rename the new worksheet
    ActiveSheet.Name = "YearlyCompilation"

    'Loop through worksheets and copy the to your new worksheet
    For Each ws In Worksheets
        ws.Activate

        'Don't copy the merged sheet again
        If ws.Name <> "YearlyCompilation" Then
            ws.UsedRange.Select
            Selection.Copy
            Sheets("YearlyCompilation").Activate

            'Select the last filled cell
            ActiveSheet.Range("A1048576").Select
            Selection.End(xlUp).Select

            'For the first worksheet you don't need to go down one cell
            If ActiveCell.Address <> "$A$1" Then
                ActiveCell.Offset(1, 0).Select
            End If

            'Instead of just paste, you can also paste as link, as values etc.
            ActiveSheet.Paste

        End If

    Next
End Sub

【问题讨论】:

  • 由于您似乎首先将所有工作表移动到一个工作簿中,您打算如何存储文件名?使用工作表名称是一种选择吗?
  • 是的,我的第一个宏具有代码,当导入单独的电子表格时,它会将它们导入的选项卡/工作表命名为原始文件的名称。如果您建议有一个宏可以将这些文件合并到一个工作表中,而无需先创建一个组合工作簿,请告诉我。对于 wbkSrcBook.Sheets 中的每个 wksCurSheet countSheets = countSheets + 1 wksCurSheet.Copy After:=wbkCurBook.Sheets(wbkCurBook.Sheets.Count) wbkCurBook.Sheets(wbkCurBook.Sheets.Count).Name = Left(wksCurSheet.Name & wbkSrcBook.Name , 31)
  • 这不太容易,我正在快速写一些东西,可以有效地解决您提出的问题。

标签: excel vba spreadsheet


【解决方案1】:

这可能是冗长的,并且可能错过了标记,但是下面的宏会将共享维度和标题行的多个工作表的值组合到一个新工作表中,其中包含文件名的附加列和只有一个标题行.

它不会保留源格式或公式,并且出于速度原因,它使用数组在 VBA 空间中构建新工作表。如果输入工作表的列数不同,我还包括错误检查。

Option Explicit

Public Sub Merge_Sheets()
    On Error GoTo ErrorHandler

    Dim ws As Worksheet
    Dim varInput() As Variant
    Dim varOutput() As Variant
    Dim colData As Collection
    Dim colWsName As Collection
    Dim lRows As Long
    Dim lColumns As Long
    Dim lOutputRow As Long
    Dim i As Long
    Dim j As Long
    Dim k As Long
    Dim l As Long

    OptimizationON

    Set colData = New Collection
    Set colWsName = New Collection

    'Loads source data into Array, then loads array into a collection
    For Each ws In ActiveWorkbook.Worksheets
        varInput() = ws.UsedRange.Value2
        colData.Add varInput()
        colWsName.Add ws.name

    Next ws

    lRows = 0
    lColumns = 0

    'Determines how many rows and columns the final output array will need
    For i = 1 To colData.Count
        lRows = lRows + UBound(colData(i))

        If i = 1 Then
            lColumns = UBound(colData(i), 2)

        Else
            If lColumns <> UBound(colData(i), 2) Then
                MsgBox "Input worksheets have a different number of columns!", vbCritical, "ERROR!"
                OptimizationOFF
                Exit Sub

            End If

        End If

    Next i

    lColumns = lColumns + 1
    lRows = lRows - i + 2

    'Initializes the output array
    ReDim varOutput(1 To lRows, 1 To lColumns)

    'Loads the data into the output array
    lOutputRow = 1
    l = 0

    For i = 1 To colData.Count
        If i > 1 Then l = 1

        For j = 1 To UBound(colData(i)) - l
            For k = 1 To UBound(colData(i), 2) + 1
                If k = 1 Then
                    If lOutputRow = 1 Then
                        varOutput(lOutputRow, k) = "Filename"

                    Else
                        varOutput(lOutputRow, k) = colWsName(i)

                    End If

                Else
                    varOutput(lOutputRow, k) = colData(i)(j + l, k - 1)

                End If
            Next k

            lOutputRow = lOutputRow + 1

        Next j

    Next i

    'Creates a new worksheet and loads the data into it
    Set ws = ActiveWorkbook.Sheets.Add

    ws.name = "YearlyCompilation"

    ArrayToWorksheet varOutput(), ws

ErrorHandler:
    OptimizationOFF

End Sub

Private Sub ArrayToWorksheet(ByVal varArray As Variant, ByRef ws As Worksheet)
    'Loads an array into a worksheet
    Dim range As range

    Set range = ws.range("A1")

    Debug.Assert range.Address = "$A$1"

    Set range = range.Resize(UBound(varArray, 1), UBound(varArray, 2))

    range.Value2 = varArray

End Sub

Private Sub OptimizationON()
    'Disables certain features to speed up calculation
    With Application
        .ScreenUpdating = False
        .DisplayStatusBar = False
        .Calculation = xlCalculationManual
        .EnableEvents = False
        .PrintCommunication = False

    End With

End Sub

Private Sub OptimizationOFF()
    'Re-enables disabled features
    With Application
        .ScreenUpdating = True
        .DisplayStatusBar = True
        .Calculation = xlCalculationAutomatic
        .EnableEvents = True
        .PrintCommunication = True
    End With

End Sub

【讨论】:

  • 太好了,非常感谢!我意识到的一件事是某些文件确实有不同数量的列。大约在 2017 年中,这些每周人事档案缺少一些字段,例如 PTO(带薪休假)。因此,错误消息按预期出现。您是否知道将这些单独组合的方法,或者我是否需要创建具有相同数量的列和字段的文件批次?在后者中,我需要将 2017 年分成具有相同字段编号的批次。
  • @PolicyGuy 宏不检查列标题,因此如果中间缺少列,则数据将未对齐。我真的建议您在合并之前将所有数据都放在相同的一般“形状”中。解决这个问题会使代码更加复杂。
  • @PolicyGuy 如果/当它符合您的需要时,请点赞并接受答案:)
  • 对,有道理。该宏确实适用于具有相同列数的电子表格。再次感谢朋友!我对此比较陌生。我如何接受答案?它说在我获得 15 声望之前我不能明显地投票。
  • @PolicyGuy 投票按钮下方应该有一个小复选标记
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-08-26
  • 2022-01-22
  • 1970-01-01
  • 2016-10-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多