超级宏对于H不是的每个项目,U为空

问题描述 投票:-1回答:1

Example data我试图想出一个宏,它将填充“Pass On”选项卡,其中“H”表中没有“QC-Completed”的每个项目的“数据”选项卡中的相应数据或U列中的容器。

我还没有接近。

excel vba
1个回答
1
投票

请尝试以下方法。

处理:

A)定义过滤范围

我通过查找基于第1行和第A列的最后使用的行和列来定义要使用的范围,并将其存储在filterRange变量中。

B)清除任何现有的过滤器

我确保没有现有的过滤器:

wsSource.AutoFilterMode = False

请注意,我已将源表和目标表放入工作表变量中以便于参考?

C)应用过滤条件

然后我使用该范围来应用这两个标准:

With filterRange

        .AutoFilter
        .AutoFilter Field:=filterField1, Criteria1:="<>" criterion1, Operator:=xlFilterValues
        .AutoFilter Field:=filterField2, Criteria1:=criterion2

请注意,我已经使用常量来保存感兴趣的列,并使用过滤条件来处理例如: filterField1criterion1。这意味着,如果您决定更改应用过滤器的方式,则可以在代码顶部轻松调整这些内容。显然仍然限于两列但很容易看到你如何扩展它。

D)提取感兴趣的列并对其进行排序

现在,因为我们不希望所有过滤后的数据需要做三件事:

1)获取所有过滤的数据

因此,以下内容使用.AutoFilter.Range对象来获取过滤范围,然后使用Resize排除标题行。我们已经在另一张表中有一个标题。这被转储到一个数组中,因为它从工作表中读入的是Option Base 1,而不是0. 0是数组的正常下限。

With wsSource.AutoFilter.Range

    dataArray = .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count) 'exclude header

End With

2)将其减少到感兴趣的列

3)按指定的顺序排列那些列S,AD,B,C,E,H,L

通过使用指定要按所需顺序保留的列的数组来实现2和3。

 Dim columnsToKeep() As Variant
 columnsToKeep = Array(19, 30, 2, 3, 5, 8, 12)

然后创建一个数组来保存要写入工作表的结果,resultArray,你知道它将具有与你已经拥有的数组相同的行数dataArray,并且将具有与中的项目相同的列数columnsToKeep阵列即UBound(columnsToKeep) + 1。注意+ 1,因为该数组使用默认的base 0选项。

我们循环dataArray的行,然后,在这个循环中,我们循环columnsToKeep指定的列。这意味着我们可以使用columnsToKeep(currentColumn)dataArray中显示的顺序从源数组columnsToKeep返回指定列中的值。为了确保将其加载到resultArray中,列编号从1开始,另外一个columnCounter变量用于指定输出列。

For currentRow = LBound(dataArray, 1) To UBound(dataArray, 1)

        columnCounter = 0

        For currentColumn = LBound(columnsToKeep) To UBound(columnsToKeep)

            columnCounter = columnCounter + 1
            resultArray(currentRow, columnCounter) = dataArray(currentRow, columnsToKeep(currentColumn))

        Next currentColumn

    Next currentRow

E)将结果写入第二张表

最后,我们将所有内容写入标题下方的另一个表格:

  wsTarget.Range("A2").Resize(UBound(resultArray, 1), UBound(resultArray, 2)) = resultArray

码:

Option Explicit

Public Sub CopyData()

    'Range("H1").Select
    Dim wb As Workbook
    Dim wsSource As Worksheet
    Dim wsTarget As Worksheet
    Const filterField1 As Long = 8               'Column H
    Const filterField2 As Long = 21              'Column U
    Const criterion1 As String = "QC-Completed"
    Const criterion2 As String = vbNullString

    Set wb = ThisWorkbook
    Set wsSource = wb.Worksheets("Data")
    Set wsTarget = wb.Worksheets("Pass On")

    Dim lastRowSource As Long
    lastRowSource = wsSource.Cells(wsSource.Rows.Count, "A").End(xlUp).Row

    Dim lastColumnSource As Long
    lastColumnSource = wsSource.Range("A1").SpecialCells(xlCellTypeLastCell).Column

    Dim filterRange As Range
    Set filterRange = wsSource.Range(wsSource.Cells(1, 1), wsSource.Cells(lastRowSource, lastColumnSource))

    wsSource.AutoFilterMode = False
    Dim dataArray As Variant

    With filterRange

        .AutoFilter
        .AutoFilter Field:=filterField1, criteria1:="<>" & criteria1, Operator:=xlFilterValues
        .AutoFilter Field:=filterField2, criteria1:=criteria2

        With wsSource.AutoFilter.Range

             dataArray = .Offset(1, 0).Resize(.Rows.Count - 1, .Columns.Count) 'exclude header

        End With

    End With

    Application.CutCopyMode = False              'Clear clipboard

    Dim columnsToKeep() As Variant
    columnsToKeep = Array(19, 30, 2, 3, 5, 8, 12) 'determine output columns to keep and their orser

    Dim currentRow As Long
    Dim currentColumn As Long
    Dim resultArray() As Variant
    ReDim resultArray(1 To UBound(dataArray, 1), 1 To UBound(columnsToKeep) + 1)
    Dim columnCounter As Long

    For currentRow = LBound(dataArray, 1) To UBound(dataArray, 1)

        columnCounter = 0

        For currentColumn = LBound(columnsToKeep) To UBound(columnsToKeep)

            columnCounter = columnCounter + 1
            resultArray(currentRow, columnCounter) = dataArray(currentRow, columnsToKeep(currentColumn))

        Next currentColumn

    Next currentRow

    wsTarget.Range("A2").Resize(UBound(resultArray, 1), UBound(resultArray, 2)) = resultArray

End Sub

参考文献:

  1. A Better Way to Copy Filtered Rows Using VBA
  2. AutoFilter macro for "does not contain"
  3. Find last row, column or last cell
© www.soinside.com 2019 - 2024. All rights reserved.