【问题标题】:copy/paste range of cells x times based on condition根据条件复制/粘贴单元格范围 x 次
【发布时间】:2021-10-03 10:37:23
【问题描述】:

我想用精确范围的数据填充板上的每个空单元格。

我有两个工作表;

-worksheets("Board")

- worksheets("FinalBoard")

在工作表 worksheets("Board") 我有以下板;

Category Fruits-1 Fruits-2 Fruits-3
A Banana Cherries Orange
D Apple Mango Strawberries
B Pineapple Watermelon Grenade

仅当标题以“Fruits”开头并将它们粘贴到工作表 worksheets("FinalBoard") 的一个列中时,我才想选择每列数据。我可以使用以下代码对名为 Fruits 的列执行此操作;

Sub P_Fruits()

 Dim wsInput As Worksheet
    Dim wsOutput As Worksheet
    Dim lRowInput As Long
    Dim lRowOutput As Long
    Dim lCol As Long
    Dim i As Long
    Dim n As Long
    Dim s As String
    Dim col As String
    
    '~~>  Sheets settings
    Set wsInput = Sheets("Board")
    Set wsOutput = Sheets("FinalBoard")

       
With wsInput
        '~~> Find last column in Row 2
        lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
        
        '~~> loop through columns
        For i = 1 To lCol
            '~~>  research criterias
            If .Cells(1, i).Value2 Like "Fruit-*" Then
                '~~> Get columns name
                col = Split(.Cells(, i).Address, "$")(1)
                
                '~~> Get the last row in that column
                lRowInput = .range(col & .Rows.Count).End(xlUp).row
                
                '~~> Find the next row to write to
               If lRowOutput = 0 Then
                    lRowOutput = 2
               Else
                    lRowOutput = wsOutput.range("B" & wsOutput.Rows.Count).End(xlUp).row + 1
                End If
                
                '~~> Copy-paste in the 2nd worksheet every data if the headers is found
                .range(col & "2:" & col & lRowInput).Copy _
                wsOutput.range("B" & lRowOutput)
                
      
            End If
      Next i
end with

end sub 

但是我想为“类别”列这样做,并将类别的类型放在 A 列中每个水果的前面,从而多次重复复制的范围类别,最多worksheets("Board") 中有以“Fruits”开头的标题。我试图在前一个代码中添加一个额外的代码,但它没有用。这是我想要的结果;

Category-pasted Fruits-pasted
A Banana
D Apple
B Pineapple
A Cherries
D Melon
B Watermelon
A Orange
D Strawberries
B Grenade

这是我添加的代码所拥有的...

Category-pasted Fruits-pasted
Banana
Apple
Pineapple
Cherries
Melon
Watermelon
Orange
Strawberries
Grenade
A
D
B

我的结局代码;

Sub Fruits_add()

 Dim wsInput As Worksheet
    Dim wsOutput As Worksheet
    Dim lRowInput As Long
    Dim lRowOutput As Long
    Dim lCol As Long
    Dim i As Long
    Dim n As Long
    Dim s As String
    Dim col As String
    
    '~~>  Sheets settings
    Set wsInput = Sheets("Board")
    Set wsOutput = Sheets("FinalBoard")

       
With wsInput
        '~~> Find last column in Row 2
        lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
        
        '~~> loop through columns
        For i = 1 To lCol
            '~~>  research criterias
            If .Cells(1, i).Value2 Like "Fruit-*" Then
                '~~> Get column name
                col = Split(.Cells(, i).Address, "$")(1)
                
                '~~> Get the last row in that column
                lRowInput = .range(col & .Rows.Count).End(xlUp).row
                
                '~~> Find the next row to write to
               If lRowOutput = 0 Then
                    lRowOutput = 2
               Else
                    lRowOutput = wsOutput.range("B" & wsOutput.Rows.Count).End(xlUp).row + 1
                End If
                
                '~~> Copy-paste
                .range(col & "2:" & col & lRowInput).Copy _
                wsOutput.range("B" & lRowOutput)
                
      
            End If
      Next i
      
 'Code to repeat category type added     
With wsInput
        '~~> Find last column in Row 2
        lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
        
        '~~> loop through columns
        For i = 1 To lCol
        
         '~~>  research criterias
            If .Cells(1, i).Value2 Like "Category*" Then
                '~~> Get column name
                col = Split(.Cells(, i).Address, "$")(1)
                
                '~~> Get the last row in that column
                lRowInput = .range(col & .Rows.Count).End(xlUp).row
                
                '~~> Find the next row to write to
               If lRowOutput = 0 Then
                    lRowOutput = 2
               Else
                    lRowOutput = wsOutput.range("A" & wsOutput.Rows.Count).End(xlUp).row + 1
                End If
                
                '~~> copy-paste each category type in column A
                .range(col & "2:" & col & lRowInput).Copy _
                wsOutput.range("A" & lRowOutput)
                
                
                
         End If
      Next i
End With

      
      
End With

我觉得我已经接近解决方案了。非常感谢你们的帮助,谢谢!

【问题讨论】:

  • 您不需要两个循环 - 您的第一个循环已经有了正确的行。只需在 " '~~> 之后添加第二行代码复制粘贴 .range(col & "2:" & col & lRowInput).Copy _ wsOutput.range("B" & lRowOutput)" 并将其发送到 A 列从第 1 列
  • 你的结局代码有If .Cells(1, i).Value2 Like "Fruit-*"(没有)所以我不明白你是如何用标题Fruits-1得到那个输出的
  • 我刚刚编辑并删除了“s”,因为标题以“fruit”开头,不包含任何“s”...

标签: excel vba if-statement foreach


【解决方案1】:

正如我在 cmets 中解释的那样,如果您已经找到正确的行,则不需要第二个循环 - 尽早获取类别列并稍后重用它

你可以先在顶部添加这个变量声明

Dim col As String

然后继续执行第一个循环的代码(删除第二个循环

With wsInput
        '~~> Find last column in Row 2
        lCol = .Cells(1, .Columns.Count).End(xlToLeft).Column
        
        '~~> loop through columns
        For i = 1 To lCol

添加此项以首先检索类别

            If .Cells(1, i).Value2 Like "Category*" Then
            '~~> Get column name
               colCat = Split(.Cells(, i).Address, "$")(1)                
            End If

            '~~>  research criterias
            If .Cells(1, i).Value2 Like "Fruit-*" Then
                '~~> Get column name
                col = Split(.Cells(, i).Address, "$")(1)
                
                '~~> Get the last row in that column
                lRowInput = .range(col & .Rows.Count).End(xlUp).row
                
                '~~> Find the next row to write to
               If lRowOutput = 0 Then
                    lRowOutput = 2
               Else
                    lRowOutput = wsOutput.range("B" & wsOutput.Rows.Count).End(xlUp).row + 1
                End If
                
                '~~> Copy-paste
                .range(col & "2:" & col & lRowInput).Copy _
                wsOutput.range("B" & lRowOutput)
                

然后添加这个以粘贴类别

            '~~> copy-paste each category type in column A
            .range(colCat & "2:" & colCat & lRowInput).Copy _
            wsOutput.range("A" & lRowOutput)
      
            End If
      Next i
End With

        

【讨论】:

  • 花了更长的时间,但它最终奏效了!非常感谢!
  • 但是我有一个问题,如果必须添加额外的条件来根据标题获取列数据怎么办?(不仅仅是类别和水果数据列?)
  • 我认为最好在一个新问题中提出这个问题,其中包含您尝试过的新示例数据和新代码
【解决方案2】:

此代码将产生所需的结果,但使用了不同的方法。

它所做的第一件事是将源数据读入一个数组,然后遍历该数组并从标题以“水果”开头的每一列中提取水果/类别。

Option Explicit

Sub Fruits_add()
Dim wsInput As Worksheet
Dim wsOutput As Worksheet
Dim arrDataIn As Variant
Dim arrDataOut As Variant
Dim idxCol As Long
Dim idxRow As Long
Dim cnt As Long

    '~~>  Sheets settings
    Set wsInput = Sheets("Board")
    Set wsOutput = Sheets("FinalBoard")

    ' assumes data on 'Board' starts in A1
    With wsInput
        arrDataIn = .Range("A1").CurrentRegion.Value
    End With
    
    ReDim arrDataOut(1 To 2, 1 To UBound(arrDataIn, 1) * UBound(arrDataIn, 2))
    
    For idxCol = LBound(arrDataIn, 2) To UBound(arrDataIn, 2)
        If arrDataIn(1, idxCol) Like "Fruits*" Then
            For idxRow = LBound(arrDataIn, 1) + 1 To UBound(arrDataIn, 1)
                cnt = cnt + 1
                arrDataOut(1, cnt) = arrDataIn(idxRow, 1)
                arrDataOut(2, cnt) = arrDataIn(idxRow, idxCol)
            Next idxRow
        End If
    Next idxCol
    
    If cnt > 0 Then
        ReDim Preserve arrDataOut(1 To 2, 1 To cnt)
    End If
    
    With wsOutput
        .Range("A1:B1").Value = Array("Category-pasted", "Fruit-pasted")
        .Range("A2").Resize(cnt, 2) = Application.Transpose(arrDataOut)
    End With
    
End Sub

【讨论】:

  • 使用数组肯定会更快。干得好。
猜你喜欢
  • 2014-12-27
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-09-06
  • 2021-03-18
  • 1970-01-01
  • 1970-01-01
  • 2014-07-03
相关资源
最近更新 更多