2009-02-27 8 views
0

donné une paire de plages, où l'on est connu pour contenir des éléments d'une autre:Quelle est la manière la plus efficace d'obtenir une «différence d'ensemble» Range dans Excel Automation?

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

ce qui est le plus efficace moyen d'obtenir une nouvelle gamme qui représente la différence de jeu entre ces deux gammes, à savoir la cellules dans src qui sont pas dans sel?

Cela peut être fait en utilisant une boucle sur les cellules src, mais cela nécessite m * n l'automatisation appelle à une m par n gamme, qui ne dispose pas de très bonnes performances, et j'espère que quelque chose qui implique moins API à distance appels.

Répondre

2

Je ne pense pas qu'il existe une meilleure façon que de boucler dans chaque cellule dans src. L'objet Excel.Application a la fonction Intersect, qui vous indique les cellules contenues dans deux plages ou plus, mais pas le contraire. Vous pouvez également effectuer une union qui vous donne juste une plage avec toutes les cellules dans deux ou plusieurs gammes ...

Mais je pense que vous allez devoir passer par chaque cellule dans src et voir si c'est dans 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 

Il y a quelques approches détaillées here

4

Avez-vous essayé d'utiliser des formules intégrées d'Excel pour filtrer les données? Par exemple, la formule suivante affichera "Oui" si la valeur de la cellule A2 se trouve dans la colonne D. Dans votre cas, vous pouvez simplement saisir toutes les cellules qui n'ont pas le "Oui" correspondant.

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

Pour étendre la réponse de Tom E, la seule question que j'ai est que quand il n'y a pas un match, =MATCH() retours #N/A, qui toute la fonction n'aime pas.

Pour résoudre ce problème, vous pouvez faire la modification suivante à l'équation:

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

Le ISNA() convertit efficacement un certain nombre de Yes et un #N/A (sans correspondance) à No, qui est ce que nous voulons. Notez que j'ai dû inverser l'ordre du Oui et du Non en raison des fonctions de ISNA().

0

Voici une autre façon de procéder. Selon la méthode ColumnDifferencesreference from MSDN: "Renvoie un objet Range représentant toutes les cellules dont le contenu est différent de la cellule de comparaison dans chaque colonne".

Sur la base de ce que j'applique la stratégie suivante:

(1) stocker le contenu de src à un Variant.

(2) Remplacez le contenu de sel par quelque chose de complètement aléatoire.

(3) Utilisez la méthode ColumnDifferences pour obtenir la plage désirée.

(4) Renvoyer les valeurs d'origine de src, qui sont stockées dans le Variant.

Une mise en œuvre des étapes ci-dessus suit:

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 

La méthode RowDifferences doit donner les mêmes résultats - c'est parce que nous remplaçons toutes les cellules dans le visible afin que les deux méthodes se comportent de la même façon.

J'ai vérifié ce qui précède en générant des nombres aléatoires dans les rangées 1 - 17 et les colonnes A - U, et en cachant les rangées 7 - 10 et il a fait le travail.

Questions connexes