在Excel自动化中获得Range“set difference”最有效的方法是什么?

给定一对范围,其中一个已知包含另一个范围的元素:

src = ActiveSheet.UsedRange sel = src.SpecialCells(xlCellTypeVisible) 

什么是最有效的方法来获得一个新的范围,代表这两个范围之间的设置差异,即在src中的单元格是不是sel

这可以通过使用循环遍历src的单元格来完成,但是这要求m * n自动化调用m n范围,这没有很好的性能,而且我希望涉及更less的远程API调用。

我不认为有什么比循环src中的每个单元格更好的方法。 Excel.Application对象具有相交function,该function告诉您哪些单元格包含在两个或更多范围内,但不是相反。 你也可以执行一个联合,只给你一个在两个或多个范围内的所有细胞的范围…

但我认为你将不得不通过每个单元格在src中,看看它是否在sel …

 Function GetInvisibleCells() As Range Dim src As Range, sel As Range Set src = ActiveSheet.UsedRange Set sel = src.SpecialCells(xlCellTypeVisible) Dim Isection As Range Set Isection = Application.Intersect(src, sel) Dim Result As Range Dim cl As Range For Each cl In src ' Go find all the cells in range2 that aren't in Isection If Application.Intersect(cl, Isection) Is Nothing Then ' Cl is not in sel If Not Result Is Nothing Then Set Result = Range(Result, cl) Else Set Result = cl End If ' Debug.Print Cl.Address & " is in " & src.Address & " and not in " & sel.Address End If Next cl Application.Intersect Set GetInvisibleCells = Result End Function 

这里有几种方法

你有没有尝试使用Excel的内置公式来过滤数据? 例如,如果单元格A2中的值在列D中find,则下面的公式将打印“是”。在您的情况下,您可以简单地抓取所有没有相应“是”的单元格。

 =IF(MATCH(A2,D:D, 0)>0,"Yes","No") 

为了扩展汤姆E的答案,我遇到的一个问题是,当没有匹配时, =MATCH()返回=MATCH() #N/A ,整个函数不喜欢。

要解决这个问题,可以对公式进行如下修改:

 =IF(ISNA(MATCH(A2,D:D, 0)),"No","Yes") 

ISNA()有效地将数字转换为“ Yes ,将ISNA() #N/A (不匹配)转换为“ No ,这正是我们想要的。 请注意,由于ISNA()function,我不得不翻转“是”和“否”的顺序。

这是另外一种方法。 根据MSDN的ColumnDifferences方法引用 :“ 返回一个Range对象,它表示所有的内容与每列中的比较单元格不同的单元格 ”。

基于这个我应用了以下策略:

(1)将src的内容存储到Variant

(2)用完全随机的东西代替sel的内容。

(3)使用ColumnDifferences方法获取所需的范围。

(4)返回存储在Variantsrc的原始值。

执行上述步骤如下:

 Dim src As Range, sel As Range, rngDiff As Range, varTempStorage As Variant Dim icnt1 As Long, icnt2 As Long Set src = ActiveSheet.UsedRange Set sel = src.SpecialCells(xlCellTypeVisible) ' Store the src values in a variant varTempStorage = src.Value ' Fill up the visible range with something random sel.Value = "something completely random" ' Will return an error if nothing is found so needs appropriate error handling ' If it works, it should set rngDiff to point to the hidden cells only Set rngDiff = src.ColumnDifferences(Comparison:=src(1,1)) ' Pass data from variant to range - method taken from CPearson's website Set src = src(1, 1) src.Resize(UBound(varTempStorage, 1), UBound(varTempStorage, 2)).Value = varTempStorage ' Have a look at the output For icnt1 = 1 To rngDiff.Rows.Count For icnt2 = 1 To rngDiff.Columns.Count Debug.Print " address: "; rngDiff(icnt1, icnt2).Address; " value: "; rngDiff(icnt1, icnt2) Next icnt2 Next icnt1 

RowDifferences方法应该给出相同的结果 – 这是因为我们replace了可见范围内的所有单元格,所以两个方法的行为方式相同。

我通过在第1 – 17行和第A – U列中生成随机数字,并通过隐藏第7 – 10行检查了上述情况,并完成了这项工作。