Excel 比较两个列表-VBA
我正在尝试使用VBA比较和匹配Excel中的两个列表。我不能使用Vlookup函数,因为其中一个列表是使用不同的软件生成的,然后每周导出到新的工作簿中。为了说明的目的 前两张名单 如上图所示,名称大部分已经匹配,通常只需向下移动一个单元格即可匹配。下面是我想要的最终结果。我通常手动执行此操作,但我认为必须有一种方法同时检查两个列表中的每个名称,以检查每一行是否匹配,如果不匹配,则执行两个操作之一 如果主列表包含WeeklyList不包含的名称,请在WeeklyList中留一个空格-如Ebony所示 如果WeeklyList包含一个主列表中没有的名称,则按其相应的字母顺序将该名称添加到主列表中,如Sally所示 后两个列表 我假设这可以通过使用循环和一些IF语句来实现,只是不确定是否应该将其放入数组或字典中 到目前为止,我已经建立了动态行-如下所示Excel 比较两个列表-VBA,excel,vba,Excel,Vba,我正在尝试使用VBA比较和匹配Excel中的两个列表。我不能使用Vlookup函数,因为其中一个列表是使用不同的软件生成的,然后每周导出到新的工作簿中。为了说明的目的 前两张名单 如上图所示,名称大部分已经匹配,通常只需向下移动一个单元格即可匹配。下面是我想要的最终结果。我通常手动执行此操作,但我认为必须有一种方法同时检查两个列表中的每个名称,以检查每一行是否匹配,如果不匹配,则执行两个操作之一 如果主列表包含WeeklyList不包含的名称,请在WeeklyList中留一个空格-如Ebony
Sub TwoLists()
MasterListRows = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
WeeklyListRows = Sheet1.Cells(Rows.Count, 2).End(xlUp).Row
Set MasterListRange = Sheet1.Range("D2:D" & MasterListRows)
Set WeeklyListRange = Sheet1.Range("E2:E" & WeeklyListRows)
End Sub
感谢您的帮助
谢谢,试试看
Sub TwoLists()
Dim Masterlistrange As Range
Dim WeeklyListRange As Range
Dim vMaster As Variant
Dim vWeek As Variant
Dim MasterListRows As Long
Dim WeeklyListRows As Long
Dim vR() As Variant
Dim i As Long, n As Long, j As Long
Dim isExist As Boolean
Dim Ws As Worksheet
MasterListRows = Sheet1.Cells(Rows.Count, 4).End(xlUp).Row '<~~ Correct column number
WeeklyListRows = Sheet1.Cells(Rows.Count, 5).End(xlUp).Row '<~~ Correct column number
Set Masterlistrange = Sheet1.Range("D2:D" & MasterListRows)
Set WeeklyListRange = Sheet1.Range("E2:E" & WeeklyListRows)
vMaster = Masterlistrange
vWeek = WeeklyListRange
For i = 1 To UBound(vWeek, 1)
If WorksheetFunction.CountIf(Masterlistrange, UCase(vWeek(i, 1))) Then
n = n + 1
ReDim Preserve vR(1 To 2, 1 To n)
vR(1, n) = UCase(vWeek(i, 1))
vR(2, n) = vWeek(i, 1)
Else
n = n + 1
ReDim Preserve vR(1 To 2, 1 To n)
vR(1, n) = UCase(vWeek(i, 1))
vR(2, n) = vWeek(i, 1)
End If
Next i
For j = 1 To UBound(vMaster, 1)
isExist = False
For i = 1 To UBound(vWeek, 1)
If vMaster(j, 1) = UCase(vWeek(i, 1)) Then
isExist = True
Exit For
End If
Next i
If Not isExist Then
n = n + 1
ReDim Preserve vR(1 To 2, 1 To n)
vR(1, n) = vMaster(j, 1)
End If
Next j
Set Ws = Sheets.Add '<~~ Sheets("Your seetname")
With Ws
.Range("a1").Resize(1, 2) = Sheet1.Range("d1").Resize(1, 2).Value
.Range("a2").Resize(n, 2) = WorksheetFunction.Transpose(vR)
.Range("a1").CurrentRegion.Sort .Range("a1"), xlAscending, Header:=xlYes
End With
End Sub
子列表()
调暗主列表范围作为范围
朦胧的一周,像射程一样奇怪
Dim vMaster作为变体
Dim vWeek作为变体
暗淡的主列表行与长的行相同
朦胧的周线和长的一样
Dim vR()作为变量
暗i为长,n为长,j为长
Dim isExist为布尔型
将Ws设置为工作表
MasterListRows=Sheet1.Cells(Rows.Count,4).End(xlUp).Row'这是字典对象和范围.Sort()方法的一个可能应用:
Sub TwoLists()
Dim MasterListRows As Long, WeeklyListRows As Long
MasterListRows = Sheet1.Cells(Rows.Count, 1).End(xlUp).Row
WeeklyListRows = Sheet1.Cells(Rows.Count, 2).End(xlUp).Row
Dim MasterListRange As Range, WeeklyListRange As Range
Set MasterListRange = Sheet1.Range("D2:D" & MasterListRows)
Set WeeklyListRange = Sheet1.Range("E2:E" & WeeklyListRows)
Dim dict As Object
Set dict = CreateObject("Scripting.Dictionary")
Dim cel As Range
For Each cel In MasterListRange
dict(UCase(cel.Value)) = 1
Next
For Each cel In WeeklyListRange
dict(UCase(cel.Value)) = cel.Value
Next
Range("F2").Resize(dict.Count) = Application.Transpose(dict.keys)
Range("G2").Resize(dict.Count) = Application.Transpose(dict.items)
Range("F2:G2").Resize(dict.Count).Sort key1:=Range("F1")
With Range("G2").Resize(dict.Count)
If WorksheetFunction.CountA(.Cells) > 0 Then .SpecialCells(xlCellTypeConstants, xlNumbers).ClearContents
End With
End Sub
顺便说一句,我不明白为什么要将MasterListRows
调整到A列和WeeklyListRows
到B列last not empty cells行索引,而masterlistrage
和WeeklyListRange
分别位于D列和E列:您可能需要使用:
MasterListRows = Sheet1.Cells(Rows.Count, 4).End(xlUp).Row
WeeklyListRows = Sheet1.Cells(Rows.Count, 5).End(xlUp).Row
相反使用阵列和Excel Office 365功能的替代方法
Function getUniques(aRange As Range, bRange As Range)
Dim a As Long: a = aRange.Rows.Count
Dim b As Long: b = bRange.Rows.Count
'add bRange items to aRange
Dim addedRange As Range
Set addedRange = aRange.Offset(a).Resize(b, 1)
addedRange.Value = bRange.Value ' add bRange items temporarily to get all
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'get all uniques as 1-based 2-dim "vertical" array ...
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dim all: all = Evaluate("=SORT(UNIQUE(D2:D" & (a + b + 1) & "))")
'...and add 2nd column (needed in OP)
all = Application.Index(all, Evaluate("row(1:" & UBound(all) & ")"), Array(1, 1))
addedRange = vbNullString ' clear temporary items in addedRange
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'identify master elements not contained in weeklyListRange
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'(1-based 2-dim array with either row numbers of found elements or Error value 2042)
Dim nums: nums = Compare(aRange, bRange, bSort:=True) ' << see function Compare() below
'...remove not existing weekly list items in corresponding row (2nd column)
Dim i As Long
For i = 1 To UBound(nums)
If IsError(nums(i, 1)) Then all(i, 2) = "***" ' empty 2nd column
Next i
'return all as function result
getUniques = all
End Function
“我假设这可以通过使用循环和一些IF语句来实现,只是不确定是否应该将其放入数组或字典中?”
我对这个(后期)答案的刺激是演示数组方法和变换的巧妙组合
通过Application.Index()
和Application.Match()
(如果s或循环,请尽量避免使用If
和UNIQUE()
的新的动态Office 365功能
返回列表或范围中唯一值的列表。
在这些“工作表”函数上应用Evaluate
,可以将找到的值分配给二维数组,例如
myArray=Evaluate(“=SORT(UNIQUE(D2:D17))”)
注意事项:
此功能当前可用于每月频道中的Office 365订户。
从2020年7月开始,Office 365订户将通过半年一次的渠道获得该服务
我的目的是展示一个有趣的循环替代品,
但不能与上述解决方案以牢度或美感相竞争
示例呼叫
Sub testUnique()
With Sheet1
'[1a] get lastRows (differ from values in D:E, see OP!)
Dim MasterListRows As Long, WeeklyListRows As Long
MasterListRows = .Cells(.Rows.Count, 1).End(xlUp).Row
WeeklyListRows = .Cells(.Rows.Count, 2).End(xlUp).Row
'[1b] get related ranges
Dim MasterListRange As Range, WeeklyListRange As Range
Set MasterListRange = .Range("D2:D" & MasterListRows)
Set WeeklyListRange = .Range("E2:E" & WeeklyListRows)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'[2] get complete set of all uniques in columns D:E
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
' Caveat: function uses Office365 UNIQUE() + SORT()
Dim allUniques
allUniques = getUniques(MasterListRange, WeeklyListRange)
'[3] write results to target
Dim tgt As Range
Set tgt = .Range("F2").Resize(UBound(allUniques), 1)
'write uniques to columns F:G
tgt.Resize(Columnsize:=2) = allUniques ' needs 2 columns
'(optional/cosmetic) - adapt upper case vs proper case
tgt.Offset(0, 0) = Evaluate("UPPER(" & tgt.Address & ")")
tgt.Offset(0, 1) = Evaluate("PROPER(" & tgt.Offset(0, 1).Address & ")")
End With
End Sub
帮助功能
Function getUniques(aRange As Range, bRange As Range)
Dim a As Long: a = aRange.Rows.Count
Dim b As Long: b = bRange.Rows.Count
'add bRange items to aRange
Dim addedRange As Range
Set addedRange = aRange.Offset(a).Resize(b, 1)
addedRange.Value = bRange.Value ' add bRange items temporarily to get all
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'get all uniques as 1-based 2-dim "vertical" array ...
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Dim all: all = Evaluate("=SORT(UNIQUE(D2:D" & (a + b + 1) & "))")
'...and add 2nd column (needed in OP)
all = Application.Index(all, Evaluate("row(1:" & UBound(all) & ")"), Array(1, 1))
addedRange = vbNullString ' clear temporary items in addedRange
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'identify master elements not contained in weeklyListRange
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
'(1-based 2-dim array with either row numbers of found elements or Error value 2042)
Dim nums: nums = Compare(aRange, bRange, bSort:=True) ' << see function Compare() below
'...remove not existing weekly list items in corresponding row (2nd column)
Dim i As Long
For i = 1 To UBound(nums)
If IsError(nums(i, 1)) Then all(i, 2) = "***" ' empty 2nd column
Next i
'return all as function result
getUniques = all
End Function
谢谢,这比我想象的要复杂得多。最终的结果非常接近,它现在只有重复的名字。为了避免重复的值,您可能会考虑使用@ JeHHRID,我改进了我的回答。end@Jehhred,那么您以前的数据呢?刚刚在另一台计算机上尝试了这个,它成功了,谢谢!好的我在发布之前测试了它,所以它必须工作。除非你有MAC电脑,否则它不能依赖于电脑。您也可以将答案标记为已接受,以指导未来的读者…感谢您的方法。-仅供参考,您可能会对我(晚些时候)的答案感兴趣,该答案演示了数组方法和较新的Office 365函数的组合:+)@HTH,内容如下:范围(“G2”)。如果工作表函数.CountA(.Cells)>0,则调整大小(dict.Count)。特殊单元格(xlCellTypeConstants,xlNumbers).ClearContents以
结尾。如果两个列表完全匹配,即不需要进行任何更改,是否仍可以绕过pastespecial。在完美列表中,我得到一条运行时1004:未找到单元格错误消息。Sheet1是工作表的代码名。这与图纸(1)不同。它出现在vb中的project explorer中,与图纸的顺序索引号不同。我想你可能会乱用它,因为你在一个文件中,而不是在另一个文件中。我知道有这样一个功能,但我还没有使用365,所以我还没有应用它。内容很好。
Function Compare(aRange As Range, bRange As Range, Optional bSort As Boolean = False)
'Note : called by the above help function
'Purpose: check the aRange array and return a 1-based 2-dim array containing
' a) row numbers of corresponding elements in bRange or
' b) Error value 2042 entries
'Hint : note that the 2nd MATCH argument is also a 1-dim array (differring from usual function calls)
Dim a, b
If bSort Then
a = Evaluate("=SORT(" & aRange.Address & ")")
b = Application.Transpose(Evaluate("=SORT(" & bRange.Address & ")"))
Else
a = aRange: b = Application.Transpose(bRange)
End If
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
Compare = Application.Match(a, b, 0)
'~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
End Function