2010-10-06 5 views
45

powiedzmy mam następujący kod:Pętla przez każdą komórkę w zakresie komórek przy podawaniu obiekt Range

Sub TestRangeLoop() 
    Dim rng As Range 
    Set rng = Range("A1:A6") 

    ''//Insert code to loop through rng here 
End Sub 

Chcę być w stanie wykonać iterację kolekcji Range obiektów dla każdej komórki określonej w rng. Koncepcyjnie, chciałbym to zrobić tak:

For Each rngCell As Range in rng 
    ''//Do something with rngCell 
Next 

wiem mogę rozwiązać ten problem parsowania rng.Address i budowanie Range przedmiotów ręcznie, ale mam nadzieję, że jest bardziej bezpośredni sposób, że nie obejmuje parsowanie ciągów.

Odpowiedz

72
Sub LoopRange() 

    Dim rCell As Range 
    Dim rRng As Range 

    Set rRng = Sheet1.Range("A1:A6") 

    For Each rCell In rRng.Cells 
     Debug.Print rCell.Address, rCell.Value 
    Next rCell 

End Sub 
+1

To działało idealnie, ale jestem zaskoczony, dlaczego zadziałało, ponieważ 'Cells' jest tylko obiektem' Range'. W rzeczywistości usunąłem '.Cells' z' rRng' w linii 'For Each' i nadal działało. Co z 'Range' sprawia, że ​​wygląda jak zbiór' Range'ów? Dziękuję bardzo za Twoją pomoc! –

+7

http://www.dailydoseofexcel.com/archives/2004/07/07/the-strange-object/ Właściwość Komórki jest domyślną właściwością w tym kontekście, dlatego właśnie działa bez niej. W innych kontekstach właściwość domyślna to właściwość Value. Wszystkie obiekty Range są naprawdę obiektami kolekcji, które zawierają obiekty Range - do chyba nieskończoności. Zasięg jest zdecydowanie dziwnym obiektem i łamie paradygmat zbierania obiektów/przedmiotów na każdym kroku. Ale w większości przypadków po prostu działa. :) –

+0

dzięki za dodatkowy wgląd.Szkoda, że ​​nie dowiedziałem się, że "to po prostu działa" z 'Range' około 4 lata temu, kiedy zacząłem robić programowanie VBA :-). –

11

Można użyć Range.Rows, Range.Columns lub Range.Cells. Każda z tych kolekcji zawiera obiekty Range.

Oto jak można zmodyfikować przykład Dicka tak aby pracować z Rows:

Sub LoopRange() 

    Dim rCell As Range 
    Dim rRng As Range 

    Set rRng = Sheet1.Range("A1:A6") 

    For Each rCell In rRng.Rows 
     Debug.Print rCell.Address, rCell.Value 
    Next rCell 

End Sub 

And Columns:

Sub LoopRange() 

    Dim rCell As Range 
    Dim rRng As Range 

    Set rRng = Sheet1.Range("A1:A6") 

    For Each rCol In rRng.Columns 
     For Each rCell In rCol.Rows 
      Debug.Print rCell.Address, rCell.Value 
     Next rCell 
    Next rCol 

End Sub 
+0

Jak wykorzystać te właściwości do utworzenia pętli. Bawiłem się właściwościami "Range", takimi jak te, o których wspomniałeś, i nie potrafię wymyślić, jak ich użyć, by przekazać mi potrzebne informacje. –

2

sporządzić notatkę na odpowiedź Dicka, to jest prawidłowe, ale nie polecam używania pętli For Each. Dla każdego tworzy tymczasowe odwołanie do komórki COM za kulisami, do których nie masz dostępu (czego potrzebujesz w celu jej usunięcia).

Zobacz więcej dyskusji następujący:

How do I properly clean up Excel interop objects?

Aby zilustrować problem, spróbuj dla każdego przykładu, należy zamknąć aplikację, i spojrzeć na Menedżerze zadań. Powinieneś zobaczyć, że wystąpienie programu Excel wciąż działa (ponieważ wszystkie obiekty nie zostały poprawnie usunięte).

Czystsze sposób obsłużyć to jest do kwerendy arkusza przy użyciu ADO:

http://technet.microsoft.com/en-us/library/ee692882.aspx

+0

Nie sądzę jednak, że te ostrzeżenia dotyczą tego pytania. Ben używa VBA, prawdopodobnie w tym samym wystąpieniu programu Excel, co zakresy, z którymi pracuje. – jtolle

+2

Używam tylko VBA. Doceniam słowo "ostrożność", ale to szczególne rozwiązanie polega na tym, że po prostu odkładam pętlę po komórkach, aby wygenerować kod SQL, a więc mogę skończyć. Odmiana -mikrypt-i-ruch-z-moim-życiem. –

+3

Whoops; masz rację :-) Sądziłem, że pracujesz z VB.Net i zostałeś całkowicie sprowadzony na złą drogę przez mój własny umysł. Przepraszam za to. –

0

mam wskrzesza zmarłych tu, ale dlatego, że zasięg może być zdefiniowana jako "A:", używając a dla każdej pętli kończy się potencjalna nieskończona pętla. Rozwiązaniem, o ile mi wiadomo, jest użycie pętli Do Until.

Do Until Selection.Value = "" 
    Rem Do things here... 
Loop 
+2

Jeśli nie używasz ostatnio wypełnionej komórki patrząc od dołu do góry (np. '.range (.cells (1, 1), .cells (.rows.count, 1) .end (xlup))'), a następnie używając [Metoda przecięcia] (https://msdn.microsoft.com/en-us/library/office/aa195772 (v = office.11) .aspx) z pełną kolumną i właściwością [.UsedRange w arkuszu kalkulacyjnym] (https://msdn.microsoft.com/en-us/library/office/ff840732.aspx) (np. 'Intersect (.columns (1), .usedrange)') lub prawdopodobnie właściwość [Range.CurrentRegion] (https: // msdn .microsoft.com/en-us/library/office/ff196678.aspx) (np. '.cells (1, 1) .currentregion.columns (1)') jest dość efektywne. – Jeeped