如果满足条件,使用 VBA 将唯一行复制到另一个电子表格

Use VBA to copy unique rows to another spreadsheet if condition is met

我是 VBA 的新手,如有任何帮助,我们将不胜感激!

我的办公室正在协调美国各地的职位申请。当人们申请时,他们会选择他们愿意在哪两个州工作。所有申请信息都手动输入到工作表 A 中,该工作表有很多列,但有 5 个重要的列:唯一 ID、名字、姓氏、首选州1 , 首选状态 2。此工作表每天更新。

我有 50 张工作表(美国每个州一张)。我编写了 VBA 代码,在创建状态工作表时将电子表格 A 中的每一行复制到 50 个状态工作表中。

我需要将每天添加到电子表格 A 的新信息复制到相应的状态电子表格中。所有选择州的申请人都需要进入州工作表(州优先顺序无关紧要)。

例如,今天,电子表格 A 可能是:

ID First Name Last Name State1 State2
111 Bob Belcher New Jersey Alaska
222 Rose Nylund Minnesota Florida
333 Beef Tobin Alaska California

因此阿拉斯加电子表格将具有:

ID First Name Last Name
111 Bob Belcher
333 Beef Tobin

明天,工作表 A 可以添加新人(ID 444 和 555),我只想将选择阿拉斯加的新人添加到阿拉斯加工作表(ID 555 Colin Robinson)。

ID First Name Last Name State1 State2
111 Bob Belcher New Jersey Alaska
222 Rose Nylund Minnesota Florida
333 Beef Tobin Alaska California
444 Charlie Bucket New York Florida
555 Colin Robinson New York Alaska

我是根据 A 列中的唯一 ID 使用此代码,但它没有考虑不同的状态。

Sub Copy ()
Dim sh1 As Worksheet, sh2 As Worksheet, lr As Long, rng As Range
Set sh1 = Sheet4
Set sh2 = Sheet1
lr = sh1.Cells(Rows.Count, 1).End(xlUp).Row
Set rng = sh1.Range("B2:B" & lr)
For Each c In rng
    If WorksheetFunction.CountIf(sh2.Range("B:B"), c.Value) = 0 Then
        sh2.Range("B" & sh2.Cells(Rows.Count, 1).End(xlUp).Row)(2).Resize(1, 5) = c.Resize(1, 5).Value
    End If
Next
End Sub 

如果我想要的唯一宏是在电子表格 A 中,而您只想使用 copy-paste 来传输数据而不是 sql。

,那么我会这样做

注意:以下带*的项目,您可以录制一个宏来为您生成代码并将其粘贴到您的函数中以快速拼凑代码。

  1. 首先设置ScreenUpdating=false 来消除屏幕 闪烁。
  2. 创建要循环的状态名称数组。
  3. 在循环中,对电子表格应用过滤器以将行减少到仅与当前“状态”匹配的行*
  4. 打开其他文件 - 请务必使用状态名称命名文件,以便您可以使用数组引用文件名。 (参见 Workbooks.Open)
  5. 通过在州电子表格的 A1* 处插入行进行粘贴。
  6. Select 全部并执行菜单选项数据-->删除重复项*

如果您的数据使 #6 成为问题,则需要更多代码来检查现有数据。

再见, 肖恩

在If之前的For循环中,添加

Set sh2 = ThisWorkbook.Worksheets(c.Offset(, 3).Value2)

这要求州列中的值与州 sheet 姓名

完全匹配

要处理第二个状态,请使用 Offset(, 4)

重复 Set 和 If 块

如果此代码太慢,请考虑切换到变体数组方法

将数据导出到多个工作表

  • 为避免创建重复项,我添加了第 6 个 (sfrCol) 标志列,该列将在传输的每一行中包含 "Yes" (sFlag)。该代码只是在寻找任何内容,因此您可以使用任何您喜欢的值。
  • 代码将首先在此标志列中找到第一个可用单元格以引用未传输的数据范围。
  • 然后它将循环遍历该范围内的行并相应地传输(复制)这些行,必要时创建新的工作表,否则,将这些行追加到已写入的数据之后。
Option Explicit

Sub ExportByCountry()
    
    ' Source
    Const sName As String = "A" ' Worksheet Name
    Const slrCol As Long = 1 ' Last Row Column
    Const sfrCol As Long = 6 ' Flag Column
    Const sFlag As String = "Yes"
    Dim stCols As Variant: stCols = VBA.Array(1, 2, 3) ' Transfer Columns
    Dim scCols As Variant: scCols = VBA.Array(4, 5) ' Country Columns
    ' Destination
    Const dfCol As Long = 1 ' First Column
    Const dfRow As Long = 1 ' First Row
    ' Workbook
    Dim wb As Workbook: Set wb = ThisWorkbook ' workbook containing this code
    
    Dim sws As Worksheet: Set sws = wb.Worksheets(sName)
    
    Dim stUpper As Long: stUpper = UBound(stCols)
    Dim scUpper As Long: scUpper = UBound(scCols)
    Dim dtCount As Long: dtCount = stUpper + 1
    Dim dHeaders As Variant: ReDim dHeaders(0 To stUpper)
    
    Dim srg As Range
    Dim srCount As Long
    Dim dt As Long
    
    With sws.Range("A1").CurrentRegion ' (with headers)
        ' Write headers to an array.
        For dt = 0 To stUpper
            dHeaders(dt) = .Cells(dt + 1).Value
        Next dt
        srCount = .Rows.Count
        ' Reference the source data range (no headers)
        Set srg = .Resize(srCount - 1).Offset(1)
    End With
     
    Dim sfCell As Range
    s
    ' Reference the first available cell in the flag column ('sfCell').
    With srg.Columns(sfrCol)
        Set sfCell = .Find("*", , xlFormulas, , , xlPrevious)
        If sfCell Is Nothing Then
            Set sfCell = .Cells(1)
        ElseIf sfCell.Row = srCount Then
            MsgBox "Data already transferred.", vbExclamation
            Exit Sub
        Else
            Set sfCell = sfCell.Offset(1)
        End If
    End With
    
    ' Reference the not flagged range ('srg').
    Set srg = srg.Resize(srCount - sfCell.Row + 1).Offset(sfCell.Row - 2)
    srCount = srg.Rows.Count
    
    ' Write the range to the source array ('sData').
    Dim sData As Variant: sData = srg.Value
    Dim dtData As Variant: ReDim dtData(0 To stUpper) ' Transfer Data Array
    
    Dim dws As Worksheet
    Dim drrg As Range ' Destination Row Range
    Dim sr As Long ' Source Row Counter
    Dim sc As Long ' Source Country Column Counter
    
    For sr = 1 To srCount
        For sc = 0 To scUpper
            ' Attempt to create a reference to the destination worksheet.
            On Error Resume Next
                Set dws = wb.Worksheets(sData(sr, scCols(sc)))
            On Error GoTo 0
            If dws Is Nothing Then ' worksheet doesn't exist
                ' Add a new worksheet, rename it and write the headers.
                Set dws = wb.Worksheets.Add(After:=wb.Sheets(wb.Sheets.Count))
                dws.Name = sData(sr, scCols(sc))
                dws.Cells(dfRow, dfCol).Resize(, dtCount).Value = dHeaders
            'Else ' worksheet exists; do nothing
            End If
            ' Write the values from the row ('sr') of the source array
            ' to the transfer data array.
            For dt = 0 To stUpper
                dtData(dt) = sData(sr, stCols(dt))
            Next dt
            ' Reference the first 'available' destination row range.
            With dws.Columns(dfCol)
                Set drrg = .Find("*", , xlFormulas, , , xlPrevious) _
                    .Offset(1).Resize(, dtCount)
            End With
            ' Write the values from the transfer data array
            ' to the destinaton row range.
            drrg.Value = dtData
            
            Set dws = Nothing
        Next sc
        ' Write the flag.
        srg.Cells(sr, sfrCol).Value = sFlag
    Next sr
    
    sws.Select
    'wb.Save
    
    MsgBox "Data transferred.", vbInformation
    
End Sub