【问题标题】:Unable to populate unique values in third sheet comparing the values of the second sheet to the first one无法在第三张工作表中填充唯一值,将第二张工作表的值与第一个工作表的值进行比较
【发布时间】:2020-01-17 21:03:44
【问题描述】:

我在 Excel 工作簿中有三张工作表 - main、specimen 和 output。工作表main 和speciment 包含一些信息。两张纸中的一些信息是相同的,但很少有不同的。我的意图是将这些信息粘贴到output 中,这些信息在speciment 中可用,但在main 中不可用。

我尝试过 [目前它填充了许多产生重复的单元格]:

Sub getData()
    Dim cel As Range, celOne As Range, celTwo As Range
    Dim ws As Worksheet: Set ws = ThisWorkbook.Worksheets("main")
    Dim ws1 As Worksheet: Set ws1 = ThisWorkbook.Worksheets("specimen")
    Dim ws2 As Worksheet: Set ws2 = ThisWorkbook.Worksheets("output")


    For Each cel In ws.Range("A2:A" & ws.Cells(Rows.Count, 1).End(xlUp).row)
        For Each celOne In ws1.Range("A2:A" & ws1.Cells(Rows.Count, 1).End(xlUp).row)
            If cel(1, 1) <> celOne(1, 1) Then ws2.Range("A" & Rows.Count).End(xlUp).Offset(1, 0).value = celOne(1, 1)
        Next celOne
    Next cel
End Sub

main 包含:

UNIQUE ID   FIRST NAME          LAST NAME
A0000477    RICHARD NOEL        AARONS 
A0001032    DON WILLIAM         ABBOTT 
A0290191    REINHARDT WESTER    CARLSON 
A0290284    RICHARD WARREN      CARLSON 
A0002029    RAYMOND MAX         ABEL 
A0002864    DARRYL SCOTT        ABLING 
A0003916    GEORGES YOUSSEF     ACCAOUI 

specimen 包含:

UNIQUE ID   FIRST NAME       LAST NAME
A0288761    ROBERT HOWARD    CARLISLE 
A0290284    RICHARD WARREN   CARLSON 
A0290688    THOMAS A         CARLSTROM 
A0002029    RAYMOND MAX      ABEL 
A0002864    DARRYL SCOTT     ABLING 

output 应包含 [预期]:

UNIQUE ID   FIRST NAME      LAST NAME
A0288761    ROBERT HOWARD   CARLISLE 
A0290688    THOMAS A        CARLSTROM 

我怎样才能做到这一点?

【问题讨论】:

    标签: excel vba


    【解决方案1】:

    如果您有最新版本的 Excel,带有 FILTER 函数和动态数组,您可以使用 Excel 公式来完成。

    我将您的 Main 和 Specimen 数据更改为表格。

    然后您可以在输出工作表上将此公式输入到单个单元格中:

    =FILTER(specTbl,ISNA(MATCH(specTbl[UNIQUE ID],mnTbl[UNIQUE ID],0)))
    

    其余字段将自动填充结果。

    对于 VBA 解决方案,我喜欢使用字典和 VBA 数组来提高速度。

    'set reference to microsoft scripting runtime
    '  or use late-binding
    Option Explicit
    Sub findMissing()
        Dim wsMain As Worksheet, wsSpec As Worksheet, wsOut As Worksheet
        Dim dN As Dictionary, dM As Dictionary
        Dim vMain As Variant, vSpec As Variant, vOut As Variant
        Dim I As Long, v As Variant
    
    With ThisWorkbook
        Set wsMain = .Worksheets("Main")
        Set wsSpec = .Worksheets("Specimen")
        Set wsOut = .Worksheets("Output")
    End With
    
    'Read data into vba arrays for processing speed
    With wsMain
        vMain = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=3)
    End With
    
    With wsSpec
        vSpec = .Range(.Cells(1, 1), .Cells(.Rows.Count, 1).End(xlUp)).Resize(columnsize:=3)
    End With
    
    'add ID to names dictionary
    Set dN = New Dictionary
    For I = 2 To UBound(vMain, 1)
        dN.Add Key:=vMain(I, 1), Item:=I
    Next I
    
    'add missing ID's to missing dictionary
    Set dM = New Dictionary
    For I = 2 To UBound(vSpec, 1)
        If Not dN.Exists(vSpec(I, 1)) Then
            dM.Add Key:=vSpec(I, 1), Item:=WorksheetFunction.Index(vSpec, I, 0)
        End If
    Next I
    
    'write results to output array
    ReDim vOut(0 To dM.Count, 1 To 3)
        vOut(0, 1) = "UNIQUE ID"
        vOut(0, 2) = "FIRST NAME"
        vOut(0, 3) = "LAST NAME"
    I = 0
    For Each v In dM.Keys
        I = I + 1
        vOut(I, 1) = dM(v)(1)
        vOut(I, 2) = dM(v)(2)
        vOut(I, 3) = dM(v)(3)
    Next v
    
    Dim R As Range
    With wsOut
        Set R = .Cells(1, 1)
        Set R = R.Resize(UBound(vOut, 1) + 1, UBound(vOut, 2))
    
        With R
            .EntireColumn.Clear
            .Value = vOut
            .Style = "Output"
            .EntireColumn.AutoFit
        End With
    End With
    
    End Sub
    

    两者都显示相同的结果(除了公式解决方案不会带来列标题;但您可以在上述原始公式上方的单元格中使用公式 =mnTbl[#Headers] 来做到这一点)。

    【讨论】:

    • 我还没有测试您的代码的选项。一旦我这样做了,我会告诉你的。谢谢。
    • 脚本抛出此错误Named argument not found 指向这一行dN.Add key:=vMain(I, 1), item:=I。
    • @robots.txt 无论我使用早期绑定还是后期绑定,它都可以正常工作。您是否对我提供的代码进行了任何更改?
    • @robots.txt 你不会碰巧在使用 Excel for Mac 吗?
    • 我在 Windows @Ron 中使用 Excel。
    【解决方案2】:

    另一种选择是将每个范围内的每一行的值连接起来并将它们存储在数组中。

    然后比较数组并输出唯一值。

    在这种情况下,您的唯一性来自评估整行,而不仅仅是唯一 ID。

    请阅读代码的 cmets 并根据您的需要进行调整。

    Public Sub OutputUniqueValues()
    
        Dim mainSheet As Worksheet
        Dim specimenSheet As Worksheet
        Dim outputSheet As Worksheet
    
        Dim mainRange As Range
        Dim specimenRange As Range
    
        Dim mainArray As Variant
        Dim specimenArray As Variant
    
        Dim mainFirstRow As Long
        Dim specimenFirstRow As Long
    
        Dim outputCounter As Long
    
        Set mainSheet = ThisWorkbook.Worksheets("main")
        Set specimenSheet = ThisWorkbook.Worksheets("specimen")
        Set outputSheet = ThisWorkbook.Worksheets("output")
    
        ' Row at which the output range will be printed (not including headers)
        outputCounter = 2
    
        ' Process main data ------------------------------------
    
        ' Row at which the range to be evaluated begins
        mainFirstRow = 2
    
        ' Turn range rows into array items
        mainArray = ProcessRangeData(mainSheet, mainFirstRow)
    
    
        ' Process specimen data ------------------------------------
    
        ' Row at which the range to be evaluated begins
        specimenFirstRow = 2
    
        ' Turn range rows into array items
        specimenArray = ProcessRangeData(specimenSheet, specimenFirstRow)
    
        ' Look for unique values and output results in sheet
        OutputUniquesFromArrays outputSheet, outputCounter, mainArray, specimenArray
    
    End Sub
    
    Private Function ProcessRangeData(ByVal dataSheet As Worksheet, ByVal firstRow As Long) As Variant
    
    
        Dim dataRange As Range
        Dim evalRowRange As Range
    
        Dim lastRow As Long
        Dim counter As Long
    
        Dim dataArray As Variant
    
        ' Get last row in sheet (column 1 = column A)
        lastRow = dataSheet.Cells(dataSheet.Rows.Count, 1).End(xlUp).Row
        ' Set the range of specimen sheet
        Set dataRange = dataSheet.Range("A" & firstRow & ":C" & lastRow)
    
        ' Redimension the array to the number of rows in range
        ReDim dataArray(dataRange.Rows.Count)
    
        counter = 0
    
        ' Join each row values so it's easier to compare them later and add them to an array
        For Each evalRowRange In dataRange.Rows
    
            ' Use Trim function if you want to omit the first and last characters if they are spaces
            dataArray(counter) = Trim(evalRowRange.Cells(1).Value) & "|" & Trim(evalRowRange.Cells(2).Value) & "|" & Trim(evalRowRange.Cells(3).Value)
    
            counter = counter + 1
    
        Next evalRowRange
    
        ProcessRangeData = dataArray
    
    End Function
    
    Private Sub OutputUniquesFromArrays(ByVal outputSheet As Worksheet, ByVal outputCounter As Long, ByVal mainArray As Variant, ByVal specimenArray As Variant)
    
        Dim specimenFound As Boolean
        Dim specimenCounter As Long
        Dim mainCounter As Long
    
        ' Look for unique values ------------------------------------
    
        For specimenCounter = 0 To UBound(specimenArray)
    
            specimenFound = False
    
            ' Check if value in specimen array exists in main array
            For mainCounter = 0 To UBound(mainArray)
    
                If specimenArray(specimenCounter) = mainArray(mainCounter) Then specimenFound = True
    
            Next mainCounter
    
            If specimenFound = False Then
                ' Write values to output sheet
                outputSheet.Range("A" & outputCounter).Value = Split(specimenArray(specimenCounter), "|")(0)
                outputSheet.Range("B" & outputCounter).Value = Split(specimenArray(specimenCounter), "|")(1)
                outputSheet.Range("C" & outputCounter).Value = Split(specimenArray(specimenCounter), "|")(2)
                outputCounter = outputCounter + 1
            End If
    
        Next specimenCounter
    End Sub
    

    【讨论】:

      猜你喜欢
      • 2015-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-04-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多