Excel 将所有数据复制到一张图纸中,循环VBA时出现问题

Excel 将所有数据复制到一张图纸中,循环VBA时出现问题,excel,vba,copy,Excel,Vba,Copy,您好,我正在尝试复制一组列,每个表的最后一行是什么。我得到了这个代码,但它只适用于一张工作表,而不是所有的工作表。我不知道如何让它在所有的纸上循环 我尝试过使用vba代码 Option Explicit Public Sub CombineDataFromAllSheets() Dim wksSrc As Worksheet, wksDst As Worksheet Dim rngSrc As Range, rngDst As Range Dim lngLastCol

您好,我正在尝试复制一组列,每个表的最后一行是什么。我得到了这个代码,但它只适用于一张工作表,而不是所有的工作表。我不知道如何让它在所有的纸上循环

我尝试过使用vba代码

Option Explicit
Public Sub CombineDataFromAllSheets()

    Dim wksSrc As Worksheet, wksDst As Worksheet
    Dim rngSrc As Range, rngDst As Range
    Dim lngLastCol As Long, lngSrcLastRow As Long, lngDstLastRow As Long

    'Notes: "Src" is short for "Source", "Dst" is short for "Destination"

    'Set references Pup-front
    Set wksDst = ThisWorkbook.Worksheets("Import")
    lngDstLastRow = LastOccupiedRowNum(wksDst) '<~ defined below (and in Toolbelt)!
    lngLastCol = LastOccupiedColNum(wksDst) '<~ defined below (and in Toolbelt)!

    'Set the initial destination range
    Set rngDst = wksDst.Cells(2, 1)

    'Loop through all sheets
    For Each wksSrc In ThisWorkbook.Worksheets

        'Make sure we skip the "Import" destination sheet!
        If wksSrc.Name <> "Import" Then

            'Identify the last occupied row on this sheet
            lngSrcLastRow = LastOccupiedRowNum(wksSrc)

            'Store the source data then copy it to the destination range
            With wksSrc
                Set rngSrc = .Range(.Cells(2, 1), .Cells(lngSrcLastRow, 9))
                rngSrc.Copy Destination:=rngDst
            End With

            'Redefine the destination range now that new data has been added
            lngDstLastRow = LastOccupiedRowNum(wksDst)
            Set rngDst = wksDst.Cells(2, 1)

        End If

    Next wksSrc

End Sub

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'INPUT       : Sheet, the worksheet we'll search to find the last row
'OUTPUT      : Long, the last occupied row
'SPECIAL CASE: if Sheet is empty, return 1
Public Function LastOccupiedRowNum(Sheet As Worksheet) As Long
    Dim lng As Long
    If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
        With Sheet
            lng = .Cells.Find(What:="*", _
                              After:=.Range("A1"), _
                              Lookat:=xlPart, _
                              LookIn:=xlFormulas, _
                              SearchOrder:=xlByRows, _
                              SearchDirection:=xlPrevious, _
                              MatchCase:=False).Row
        End With
    Else
        lng = 1
    End If
    LastOccupiedRowNum = lng
End Function

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'INPUT       : Sheet, the worksheet we'll search to find the last column
'OUTPUT      : Long, the last occupied column
'SPECIAL CASE: if Sheet is empty, return 1
Public Function LastOccupiedColNum(Sheet As Worksheet) As Long
    Dim lng As Long
    If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
        With Sheet
            lng = .Cells.Find(What:="*", _
                              After:=.Range("A1"), _
                              Lookat:=xlPart, _
                              LookIn:=xlFormulas, _
                              SearchOrder:=xlByColumns, _
                              SearchDirection:=xlPrevious, _
                              MatchCase:=False).Column
        End With
    Else
        lng = 1
    End If
    LastOccupiedColNum = lng
End Function
选项显式
公共子组合数据来自AllSheets()
将WKSRC标注为工作表,WKSST标注为工作表
变暗rngSrc As范围,rngDst As范围
暗淡的lngLastCol为长,LNGSRCSTASTROW为长,LNGDSTASTROW为长
注释:“Src”是“源”的缩写,“Dst”是“目的”的缩写
'将引用设置为Pup front
设置wksDst=ThisWorkbook.Worksheets(“导入”)

lngDstLastRow=lastOccupieDivertum(wksDst)“在下面的代码中,我试图遵守您的命名约定,但以稍微不同的方式处理了这个需求

源工作表名称加载到Variant
wksrcnames
。然后,我对每个
循环使用
,从每个源工作表复制数据。我相信这是从选定工作表加载数据的最简单方法

如果我正确解释了代码,则不会将源工作表的标题行复制到目标工作表。您只需将第2行从源工作表复制到最后一行。我也会这样做,但在复制任何数据行之前,我会从第一个源工作表复制标题行

我计划像你一样复制包括公式在内的数据。在例行活动结束时,我会:

  ' Copy data in wksDst over itself to convert formulae to values
  With wksDst
    Set rngDst = .Range(.Cells(1, 1), .Cells(lngDstNextRow - 1, lngLastCol)
  End With
  rngDst.Value = rngDst.Value
将整个工作表“导入”复制到自身,将所有公式转换为值。这项技术可能对您有效,但对我的测试数据无效,因为我在一些公式中包含了函数
Row()
。当我将一行从源工作表复制到“导入”时,该值更改为反映工作表“导入”中的行号。当我将公式转换为值时,我冻结了新值而不是原始值

我现在分两个阶段复制数据。第一阶段和你的一样。这将移动任何单元格级别的格式设置。然后将源值复制到变量,然后将变量复制到目标范围。这会将公式转换为其原始值

我想您会发现这段代码是不言自明的,但如果需要,可以提问:

Option Explicit

  ' You use literal 9 in your code for the number of columns.
  ' In six months or a year someone will add or remove a column.
  ' You will then have to search through your code for those 9s
  ' which identify the last column. You may be lucky and that
  ' is the only use of 9. If you had ever had to check code for
  ' a literal that was no longer correct, you would understand
  ' why I never use them. With a constant, change the constant
  ' and the code is fixed.

  ' Your code assumes one header row which is not copied to
  ' worksheet "Import".

  Const lngLastCol As Long = 9
  Const lngFirstDataRow As Long = 2
Public Sub CombineDataFromAllSheets()

  Dim wksSrc As Worksheet, wksDst As Worksheet
  Dim rngSrc As Range, rngDst As Range
  Dim lngSrcLastRow As Long, lngDstNextRow As Long
  Dim wksSrcNames As Variant, wksSrcName As Variant
  Dim CellValues As Variant

  'Notes: "Src" is short for "Source", "Dst" is short for "Destination"

  ' ThisWorkBook is the workbook containing the macro.  If you have
  ' multiple workbooks open, you have to be really careful to identify
  ' the correct workbook.  Sometimes you identify the workbook and
  ' sometimes you don't.  I have removed ThisWorkbook when you used it.

  'Set references Pup-front
  Set wksDst = Worksheets("Import")

  ' VBA.Array will set wksSrcNames to a zero-based array of worksheet
  ' names. To add another worksheet or change the sequence, just update
  ' this statement.
  wksSrcNames = VBA.Array("Pro Rates", "Weekly Labor")

  With wksDst
    ' Clear any previous data
    .Cells.EntireRow.Delete
  End With

  ' Copy the header rows , if any, from the first worksheet.
  ' I assume you have no formulae in your header row.
  If lngFirstDataRow > 1 Then
    Set wksSrc = Worksheets(wksSrcNames(0))
    With wksSrc
      Set rngSrc = .Range(.Cells(1, 1), .Cells(lngFirstDataRow - 1, lngLastCol))
    End With
    lngDstNextRow = 1
    rngSrc.Copy Destination:=wksDst.Cells(lngDstNextRow, 1)
  End If

  ' Prepare lngDstNextRow for first set of data rows
  lngDstNextRow = lngFirstDataRow

   For Each wksSrcName In wksSrcNames

    Set wksSrc = Worksheets(wksSrcName)
    lngSrcLastRow = LastOccupiedRowNum(wksSrc)
    With wksSrc
      Set rngSrc = .Range(.Cells(lngFirstDataRow, 1), .Cells(lngSrcLastRow, lngLastCol))
    End With
    With wksDst
      Set rngDst = .Range(.Cells(lngDstNextRow, 1), _
                          .Cells(lngDstNextRow + rngSrc.Rows.Count - 1, lngLastCol))
    End With
    ' Copy values, formulae and formats
    rngSrc.Copy Destination:=wksDst.Cells(lngDstNextRow, 1)
    ' Copy values
    CellValues = rngSrc.Value
    rngDst.Value = CellValues
    ' Prepare lngDstNextRow for next set of data rows
    lngDstNextRow = lngDstNextRow + rngSrc.Rows.Count

  Next

  With wksDst
    .Columns.AutoFit  ' Set column widths so data fits
  End With

End Sub

'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'INPUT       : Sheet, the worksheet we'll search to find the last row
'OUTPUT      : Long, the last occupied row
'SPECIAL CASE: if Sheet is empty, return 1
Public Function LastOccupiedRowNum(Sheet As Worksheet) As Long
    Dim lng As Long
    If Application.WorksheetFunction.CountA(Sheet.Cells) <> 0 Then
        With Sheet
            lng = .Cells.Find(What:="*", _
                              After:=.Range("A1"), _
                              Lookat:=xlPart, _
                              LookIn:=xlFormulas, _
                              SearchOrder:=xlByRows, _
                              SearchDirection:=xlPrevious, _
                              MatchCase:=False).Row
        End With
    Else
        lng = 1
    End If
    LastOccupiedRowNum = lng
End Function
选项显式
'您在代码中使用文字9表示列数。
“六个月或一年后,会有人添加或删除一列。
“然后,您必须在代码中搜索这些9
'来标识最后一列。你可能很幸运
'是9的唯一用法。如果您曾经检查过代码
“一个不再正确的文字,你会明白的
“为什么我从不使用它们。使用常量,更改常量
'代码是固定的。
'您的代码假定有一个未复制到的标题行
'工作表“导入”。
常量lngLastCol,长度=9
常量lngFirstDataRow的长度=2
公共子组合数据来自AllSheets()
将WKSRC标注为工作表,WKSST标注为工作表
变暗rngSrc As范围,rngDst As范围
变暗LNGSRCASTROW尽可能长,lngDstNextRow尽可能长
Dim WKSRCName作为变体,WKSRCName作为变体
将单元格值变为变量
注释:“Src”是“源”的缩写,“Dst”是“目的”的缩写
'此工作簿是包含宏的工作簿。如果你有
“打开了多个工作簿,您必须非常小心地识别
'正确的工作簿。有时您需要识别工作簿和
“有时候你不会。您使用此工作簿时,我已将其删除。
'将引用设置为Pup front
设置wksDst=工作表(“导入”)
'VBA.Array将WKSRCNames设置为工作表的从零开始的数组
“名字。要添加其他工作表或更改顺序,只需更新
"这句话,。
wksrcnames=VBA.Array(“按比例”、“每周人工”)
与西九龙文娱艺术区
'清除任何以前的数据
.Cells.EntireRow.Delete
以
'从第一个工作表复制标题行(如果有)。
'我假设您的标题行中没有公式。
如果lngFirstDataRow>1,则
设置WKSRC=工作表(WKSRC名称(0))
与WKSRC合作
设置rngSrc=.Range(.Cells(1,1),.Cells(lngFirstDataRow-1,lngLastCol))
以
lngDstNextRow=1
rngSrc.Copy Destination:=wksDst.Cells(lngDstNextRow,1)
如果结束
'为第一组数据行准备lngDstNextRow
lngDstNextRow=LNGFIRSTDATA行
对于WKSRCNAMES中的每个WKSRCNAMES
设置WKSRC=工作表(WKSRCNAME)
LNGSRCASTROW=Lastoccupiedochum(WKSRC)
与WKSRC合作
设置rngSrc=.Range(.Cells(lngFirstDataRow,1),.Cells(lngSrcLastRow,lngLastCol))
以
与西九龙文娱艺术区
设置rngDst=.Range(.Cells(lngDstNextRow,1)_
.Cells(lngDstNextRow+rngSrc.Rows.Count-1,lngLastCol))
以
'复制值、公式和格式
rngSrc.Copy Destination:=wksDst.Cells(lngDstNextRow,1)
'复制值
CellValues=rngSrc.Value
rngDst.Value=单元格值
'为下一组数据行准备lngDstNextRow
lngDstNextRow=lngDstNextRow+rngSrc.Rows.Count
下一个
与西九龙文娱艺术区
.Columns.AutoFit“设置列宽以便数据适合
以
端接头
'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''
'输入:工作表,我们将搜索以查找最后一行的工作表
'输出:长,最后占用的行
'特殊情况:如果工作表为空,则返回1
公共函数LastOccupiedum(工作表形式)长度为
随着时间的推移,液化天然气变得暗淡
如果Application.WorksheetFunction.CountA(Sheet.Cells)为0,则
用床单
lng=.Cells.Find(What:=“*”_
之后:=.范围(“A1”)_
看:=xlPart_
LookIn:=xl公式_
搜索顺序:=xlByRows_
搜索方向:=xlPrevious_