VBA - 将数据复制到主表并在每行旁边插入表单名称

时间:2018-04-04 13:11:11

标签: excel vba excel-vba

我有多张表,每张表只包含前两列中的数据:

A栏 - ID

B栏 - 名称

我正在尝试将所有这些工作表合并为主工作表。主表格的格式应为:

A栏 - 工作表名称(复制数据的位置)

B栏 - ID

C列 - 名称

我发现一个网站的代码或多或少会有这个代码,然而,在弄乱了它之后感觉像是永恒的我无法让它工作。

代码工作,从某种意义上说,它复制了正确的范围并将工作表名称输入到A列中,但是,它不会停留在主工作表中范围的“最后一行”,它会继续填充触发了整个列A和计算行的IF Statement,弹出msgbox(参见下面的代码)。此时,代码刚刚结束,并且没有机会执行剩余的工作表。

链接到网站:https://www.rondebruin.nl/win/s3/win002.htm

以下是原始网站的代码,对我将使用的范围进行一些小的调整:

Sub CopySheetNameToColumn()
Dim sh As Worksheet
    Dim DestSh As Worksheet
    Dim Last As Long
    Dim CopyRng As Range

    With Application
        .ScreenUpdating = False
        .EnableEvents = False
    End With

    'Delete the sheet "RDBMergeSheet" if it exist
    Application.DisplayAlerts = False
    On Error Resume Next
    ActiveWorkbook.Worksheets("RDBMergeSheet").Delete
    On Error GoTo 0
    Application.DisplayAlerts = True

    'Add a worksheet with the name "RDBMergeSheet"
    Set DestSh = ActiveWorkbook.Worksheets.Add
    DestSh.Name = "RDBMergeSheet"

    'loop through all worksheets and copy the data to the DestSh
    For Each sh In ActiveWorkbook.Worksheets
        If sh.Name <> DestSh.Name Then

            'Find the last row with data on the DestSh
            Last = LastRow(DestSh)

            'Fill in the range that you want to copy
            Set CopyRng = sh.Range("A:B")

            'Test if there enough rows in the DestSh to copy all the data
            If Last + CopyRng.Rows.count > DestSh.Rows.count Then
                MsgBox "There are not enough rows in the Destsh"
                GoTo ExitTheSub
            End If

            'This example copies values/formats, if you only want to copy the
            'values or want to copy everything look at the example below this macro
            CopyRng.Copy
            With DestSh.Cells(Last + 1, "B")
                .PasteSpecial xlPasteValues
                .PasteSpecial xlPasteFormats
                Application.CutCopyMode = False
            End With

            'Optional: This will copy the sheet name in the H column
            DestSh.Cells(Last + 1, "A").Resize(CopyRng.Rows.count).Value = sh.Name

        End If
    Next

ExitTheSub:

    Application.Goto DestSh.Cells(1)

    'AutoFit the column width in the DestSh sheet
    DestSh.Columns.AutoFit

    With Application
        .ScreenUpdating = True
        .EnableEvents = True
    End With

End Sub

功能:

Function LastRow(sh As Worksheet)
    On Error Resume Next
    LastRow = sh.Cells.Find(What:="*", _
                            After:=sh.Range("A1"), _
                            Lookat:=xlPart, _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByRows, _
                            SearchDirection:=xlPrevious, _
                            MatchCase:=False).Row
    On Error GoTo 0
End Function

Function LastCol(sh As Worksheet)
    On Error Resume Next
    LastCol = sh.Cells.Find(What:="*", _
                            After:=sh.Range("A1"), _
                            Lookat:=xlPart, _
                            LookIn:=xlFormulas, _
                            SearchOrder:=xlByColumns, _
                            SearchDirection:=xlPrevious, _
                            MatchCase:=False).Column
    On Error GoTo 0
End Function

3 个答案:

答案 0 :(得分:1)

而不是

Set CopyRng = sh.Range("A:B")

Set CopyRng = sh.Range("A1", sh.Range("B" & Rows.Count).End(xlUp))

因为前者覆盖了工作表的每一行,因此消息框和名称在整个工作表中运行。

答案 1 :(得分:1)

类似的东西:

Option Explicit

Sub CopySheetNameToColumn()

    Dim sh As Worksheet
    Dim DestSh As Worksheet
    Dim Last As Long
    Dim CopyRng As Range

    With Application
        .ScreenUpdating = False
        .EnableEvents = False
    End With

    Application.DisplayAlerts = False
    On Error Resume Next
    ActiveWorkbook.Worksheets("RDBMergeSheet").Delete
    On Error GoTo 0
    Application.DisplayAlerts = True


    Set DestSh = ActiveWorkbook.Worksheets.Add
    DestSh.Name = "RDBMergeSheet"

    For Each sh In ActiveWorkbook.Worksheets

        If sh.Name <> DestSh.Name Then

            Last = GetLastRow(DestSh, 1)

            With sh
                Set CopyRng = sh.Range("A1:B" & GetLastRow(sh, 1))
            End With

            If Last + CopyRng.Rows.Count > DestSh.Rows.Count Then
                MsgBox "There are not enough rows in the Destsh"
                GoTo ExitTheSub
            Else

               CopyRng.Copy IIf(Last = 1, DestSh.Cells(1, "B"), DestSh.Cells(Last + 1, "B"))

            End If

            If Last = 1 Then
                DestSh.Cells(Last, "A").Resize(CopyRng.Rows.Count).Value = sh.Name
            Else
                 DestSh.Cells(Last + 1, "A").Resize(CopyRng.Rows.Count).Value = sh.Name
            End If

        End If
    Next

ExitTheSub:

    Application.Goto DestSh.Cells(1)
    DestSh.Columns.AutoFit

    With Application
        .ScreenUpdating = True
        .EnableEvents = True
    End With

End Sub


Public Function GetLastRow(ByVal ws As Worksheet, Optional ByVal columnNumber As Long = 1) As Long

    With ws

      GetLastRow = .Cells(.Rows.Count, columnNumber).End(xlUp).Row

    End With

End Function

答案 2 :(得分:1)

你可以大大缩短这一点......有很多关于在主表上获取项目的帖子,仅从昨天就有4篇。

看看这个:

Dim lrSrc As Long, lrDst As Long, i As Long
For i = 1 To Sheets.Count
    If Not Sheets(i).Name = "Destination" Then
        lrSrc = Sheets(i).Cells(Sheets(i).Rows.Count, "A").End(xlUp).Row
        lrDst = Sheets("Destination").Cells(Sheets("Destination").Rows.Count, "A").End(xlUp).Row
        With Sheets(i)
            .Range(.Cells(2, "A"), .Cells(lrSrc, "B")).Copy Sheets("Destination").Range(Sheets("Destination").Cells(lrDst + 1, "B"), Sheets("Destination").Cells(lrDst + 1 + lrSrc, "C")) 'Assumes headers in first row aren't being copied
            Sheets("Destination").Range(Sheets("Destination").Cells(lrDst + 1, "A"), Sheets("Destination").Cells(lrDst + 1 + lrSrc, "A")).Value = Sheets(i).Name
        End With
    End If
 Next i

现已测试代码