Excel VBA Range και Cells

Εύρος και κελιά σε VBA

Τα υπολογιστικά φύλλα του Excel αποθηκεύουν δεδομένα σε κελιά. Τα κελιά ταξινομούνται σε γραμμές και στήλες. Κάθε κελί μπορεί να αναγνωριστεί από το σημείο τομής της σειράς και της στήλης του (Παράδειγμα Β3 ή R3C2).

Ένα εύρος Excel αναφέρεται σε ένα ή περισσότερα κελιά (π.χ. Α3: Β4)

Διεύθυνση κυψέλης

Σημείωση Α1

Στη σημειογραφία Α1, ένα κελί αναφέρεται με το γράμμα της στήλης του (από Α έως XFD) και ακολουθεί ο αριθμός σειράς (από 1 έως 1.048.576).

Στο VBA μπορείτε να ανατρέξετε σε οποιοδήποτε κελί χρησιμοποιώντας το Εύρος αντικειμένου.

123456789 Ανατρέξτε στο κελί Β4 στο τρέχον ενεργό φύλλοMsgBox Range ("B4")"Ανατρέξτε στο κελί Β4 στο φύλλο με το όνομα" Δεδομένα "MsgBox Worksheets ("Data"). Range ("B4")"Ανατρέξτε στο κελί Β4 στο φύλλο με το όνομα" Δεδομένα "σε άλλο βιβλίο εργασίας OPENμε το όνομα "Τα δεδομένα μου"Βιβλία εργασίας MsgBox ("Τα δεδομένα μου"). Φύλλα εργασίας ("Δεδομένα"). Εύρος ("B4")

Σημείωση R1C1

Στη Σημείωση R1C1 ένα κελί παραπέμπει με R ακολουθούμενο από Αριθμό Σειράς και μετά γράμμα «C» ακολουθούμενο από τον Αριθμό Στήλης. π.χ. το B4 σε συμβολισμό R1C1 θα αναφέρεται με R4C2. Στο VBA χρησιμοποιείτε το Αντικείμενο κελιών για χρήση συμβολισμού R1C1:

12 «Ανατρέξτε στο κελί R [6] C [4] δηλ. D6Κελιά (6, 4) = "D6"

Σειρά κυττάρων

Σημείωση Α1

Για να αναφέρετε σε περισσότερα από ένα κελιά χρησιμοποιήστε ένα ":" μεταξύ της αρχικής και της τελευταίας διεύθυνσης κελιού. Τα παρακάτω θα αναφέρονται σε όλα τα κελιά από το A1 έως το D10:

1 Εύρος ("A1: D10")

Σημείωση R1C1

Για αναφορά σε περισσότερα από ένα κελιά χρησιμοποιήστε ένα "," μεταξύ της αρχικής και της τελευταίας διεύθυνσης κελιού. Τα παρακάτω θα αναφέρονται σε όλα τα κελιά από το A1 έως το D10:

1 Εύρος (Κελιά (1, 1), Κελιά (10, 4))

Γράφοντας στα κελιά

Για να γράψετε τιμές σε ένα κελί ή συνεχόμενη ομάδα κελιών, απλώς ανατρέξτε στο εύρος, βάλτε ένα σύμβολο = και, στη συνέχεια, γράψτε την τιμή που θα αποθηκευτεί:

12345678910 «Αποθηκεύστε το F5 στο κελί με τη διεύθυνση F6Εύρος ("F6") = "F6"«Αποθηκεύστε το E6 σε κελί με διεύθυνση R [6] C [5], δηλαδή E6Κελιά (6, 5) = "Ε6"«Αποθηκεύστε το A1: D10 στην περιοχή A1: D10Εύρος ("A1: D10") = "A1: D10"' ήΕύρος (Κελιά (1, 1), Κελιά (10, 4)) = "A1: D10"

Διαβάζοντας από τα κελιά

Για να διαβάσετε τιμές από κελιά, απλώς ανατρέξτε στη μεταβλητή για να αποθηκεύσετε τις τιμές, βάλτε ένα σύμβολο = και, στη συνέχεια, αναφέρετε το εύρος που θα διαβαστεί:

1234567891011 Dim val1Dim val2«Διαβάστε από το κελί F6val1 = Εύρος ("F6")«Διαβάστε από το κελί Ε6val2 = Κελιά (6, 5)MsgBox val1Msgbox val2

Σημείωση: Για να αποθηκεύσετε τιμές από μια περιοχή κελιών, πρέπει να χρησιμοποιήσετε έναν πίνακα αντί για μια απλή μεταβλητή.

Μη συνεχόμενα κύτταρα

Για αναφορά σε μη συνεχόμενα κελιά χρησιμοποιήστε ένα κόμμα μεταξύ των διευθύνσεων κελιών:

123456 «Αποθηκεύστε 10 στα κελιά Α1, Α3 και Α5Εύρος ("A1, A3, A5") = 10«Αποθηκεύστε 10 στα κελιά A1: A3 και D1: D3)Εύρος ("A1: A3, D1: D3") = 10

Τομή κυττάρων

Για αναφορά σε μη συνεχόμενα κελιά χρησιμοποιήστε ένα διάστημα μεταξύ των διευθύνσεων κελιών:

123 'Αποθήκευση' Col D 'στο D1: D10«το οποίο είναι κοινό μεταξύ A1: D10 και D1: F10Εύρος ("A1: D10 D1: G10") = "Col D"

Μετατόπιση από κελί ή περιοχή

Χρησιμοποιώντας τη λειτουργία Offset, μπορείτε να μετακινήσετε την αναφορά από ένα δεδομένο εύρος (κελί ή ομάδα κελιών) με τον καθορισμένο αριθμό_στηλών και αριθμό_στηλών.

Offset Syntax

Εύρος. Offset (αριθμός_στροφών, αριθμός_στηλών)

Μετατόπιση από ένα κελί

12345678910111213141516 'OFFSET από ένα κελί Α1«Ανατρέξτε στο ίδιο το κελί«Μετακίνηση 0 σειρών και 0 στηλώνΕύρος ("A1"). Offset (0, 0) = "A1"«Μετακίνηση 1 γραμμών και 0 στηλώνΕύρος ("A1"). Offset (1, 0) = "A2"«Μετακίνηση 0 σειρών και 1 στηλώνΕύρος ("A1"). Offset (0, 1) = "B1"«Μετακίνηση 1 γραμμών και 1 στηλώνΕύρος ("A1"). Offset (1, 1) = "B2"«Μετακίνηση 10 σειρών και 5 στηλώνΕύρος ("A1"). Offset (10, 5) = "F11"

Μετατόπιση από μια γκάμα

123 «Μετακίνηση αναφοράς στο εύρος A1: D4 κατά 4 σειρές και 4 στήλες«Η νέα αναφορά είναι E5: H8Εύρος ("A1: D4"). Offset (4,4) = "E5: H8"

Ορισμός αναφοράς σε εύρος

Για να αντιστοιχίσετε ένα εύρος σε μια μεταβλητή εύρους: δηλώστε μια μεταβλητή τύπου Range και στη συνέχεια χρησιμοποιήστε την εντολή Set για να την ορίσετε σε μια περιοχή. Λάβετε υπόψη ότι πρέπει να χρησιμοποιήσετε την εντολή SET, καθώς το RANGE είναι αντικείμενο:

12345678 «Δηλώστε μια μεταβλητή εύρουςDim myRange as Range«Ορίστε τη μεταβλητή στο εύρος A1: D4Ορισμός myRange = Range ("A1: D4")'Εκτυπώνει $ A $ 1: $ D $ 4MsgBox myRange.Address

Αλλαγή μεγέθους εύρους

Η μέθοδος αλλαγής μεγέθους του αντικειμένου εύρους αλλάζει τη διάσταση του εύρους αναφοράς:

1234567 Dim myRange As Range'Εύρος αλλαγής μεγέθουςΟρισμός myRange = Range ("A1: F4")«Εκτυπώνει $ A $ 1: $ E $ 10Debug.Print myRange.Resize (10, 5). Διεύθυνση

Το επάνω αριστερό κελί της περιοχής αλλαγής μεγέθους είναι ίδιο με το επάνω αριστερό κελί του αρχικού εύρους

Αλλαγή μεγέθους σύνταξης

Εύρος. Αλλαγή μεγέθους (αριθμός_σειρών, αριθμός_στηλών)

OFFSET vs Αλλαγή μεγέθους

Το Offset δεν αλλάζει τις διαστάσεις του εύρους αλλά το μετακινεί κατά τον καθορισμένο αριθμό γραμμών και στηλών. Το μέγεθος δεν αλλάζει τη θέση του αρχικού εύρους αλλά αλλάζει τις διαστάσεις στον καθορισμένο αριθμό γραμμών και στηλών.

Όλα τα κελιά στο φύλλο

Το αντικείμενο Cells αναφέρεται σε όλα τα κελιά του φύλλου (1048576 σειρές και 16384 στήλες).

12 'Εκκαθάριση όλων των κελιών στα φύλλα εργασίαςCells.Clear

UsedRange

Η ιδιότητα UsedRange σάς δίνει το ορθογώνιο εύρος από το επάνω αριστερό κελί που χρησιμοποιείται στο κελί έως το δεξί κάτω μέρος που χρησιμοποιείται στο ενεργό φύλλο.

1234567 Dim ws Ως φύλλο εργασίαςΟρισμός ws = ActiveSheet'$ B $ 2: $ L $ 14 αν το L2 είναι το πρώτο κελί με οποιαδήποτε τιμή'και το L14 είναι το τελευταίο κελί με οποιαδήποτε τιμή στο'ενεργό φύλλοDebug.Print ws.UsedRange.Address

CurrentRegion

Η ιδιότητα CurrentRegion σας δίνει το συνεχόμενο ορθογώνιο εύρος από το επάνω αριστερό κελί έως το χρησιμοποιούμενο κελί δεξιά-κάτω που περιέχει το αναφερόμενο κελί/περιοχή.

1234567891011 Dim myRange As RangeΟρισμός myRange = Range ("D4: F6")«Εκτυπώνει $ B $ 2: $ L $ 14«Αν υπάρχει γεμάτη διαδρομή από D4: F16 έως B2 ΚΑΙ L14Debug.Print myRange.CurrentRegion.AddressΜπορείτε επίσης να αναφερθείτε σε ένα μόνο κελί εκκίνησηςΟρίστε myRange = Range ("D4") 'Εκτυπώνει $ B $ 2: $ L $ 14

Ιδιότητες εύρους

Μπορείτε να λάβετε τη διεύθυνση, τον αριθμό γραμμής/στήλης ενός κελιού και τον αριθμό των γραμμών/στηλών σε μια περιοχή όπως δίνεται παρακάτω:

123456789101112131415161718192021 Dim myRange As RangeΟρισμός myRange = Range ("A1: F10")'Εκτυπώνει $ A $ 1: $ F $ 10Debug.Print myRange.AddressΟρισμός myRange = Range ("F10")«Εκτυπώνει 10 για τη σειρά 10Debug.Print myRange.Row«Εκτυπώνει 6 για τη στήλη FDebug.Print myRange.ColumnΟρισμός myRange = Range ("E1: F5")'Εκτυπώνει 5 για αριθμό σειρών στο εύροςDebug.Print myRange.Rows.Count«Εκτυπώνει 2 για τον αριθμό των στηλών σε εύροςDebug.Print myRange.Columns.Count

Τελευταίο κελί σε φύλλο

Μπορείς να χρησιμοποιήσεις Σειρές. Αριθμός και Στήλες. Αριθμός ιδιότητες με Κύτταρα αντικείμενο για να λάβετε το τελευταίο κελί στο φύλλο:

1234567891011 «Εκτυπώστε τον αριθμό της τελευταίας σειράς«Εκτυπώνει 1048576Debug.Print "Σειρές στο φύλλο:" & Rows.Count«Εκτυπώστε τον τελευταίο αριθμό στήλης«Εκτυπώνει 16384Debug.Print "Στήλες στο φύλλο:" & Columns.Count«Εκτυπώστε τη διεύθυνση του τελευταίου κελιού'Εκτυπώνει $ 1048576 $ XFDDebug.Print "Address of Last Cell in the sheet:" & Cells (Rows.Count, Columns.Count)

Τελευταίος αριθμός σειράς σε μια στήλη

Η ιδιότητα END σας μεταφέρει το τελευταίο κελί της περιοχής και το End (xlUp) σας μεταφέρει στο πρώτο χρησιμοποιημένο κελί από αυτό το κελί.

123 Dim lastRow As LonglastRow = Κελιά (Rows.Count, "A"). Τέλος (xlUp). Row

Αριθμός στήλης τελευταίας χρήσης σε σειρά

123 Dim lastCol As LonglastCol = Κελιά (1, Στήλες. Αριθμός). Τέλος (xlToLeft). Στήλη

Η ιδιότητα END σας μεταφέρει το τελευταίο κελί της περιοχής και το End (xlToLeft) σας μεταφέρει στο πρώτο χρησιμοποιημένο κελί από αυτό το κελί.

Μπορείτε επίσης να χρησιμοποιήσετε τις ιδιότητες xlDown και xlToRight για να μεταβείτε στα πρώτα κάτω ή δεξιά χρησιμοποιημένα κελιά του τρέχοντος κελιού.

Ιδιότητες κυψέλης

Κοινές ιδιότητες

Ακολουθεί κώδικας για να εμφανίζονται οι ιδιότητες κυψέλης που χρησιμοποιούνται συνήθως

12345678910111213141516171819202122 Dim cell As RangeΟρισμός κελιού = Εύρος ("A1")κελί. ΕνεργοποιήστεΣφάλμα. Κυψέλη εκτύπωσης. Διεύθυνση'Εκτύπωση $ A $ 1Εντοπισμός σφαλμάτων. Κελί εκτύπωσης. Αξία«Εκτυπώνει 456' ΔιεύθυνσηΣφάλμα. Κυψέλη εκτύπωσης. Τύπος'Εκτυπώσεις = SUM (C2: C3)«ΣχόλιοDebug.Prell cell.Comment.Text' ΣτυλΣφάλμα. Κυψέλη εκτύπωσης. Στυλ«Μορφή κυψέληςDebug.Prell cell.DisplayFormat.NumberFormat

Κυτταρική γραμματοσειρά

Το αντικείμενο Cell.Font περιέχει ιδιότητες της γραμματοσειράς κυψέλης:

1234567891011121314151617181920 Dim cell As RangeΟρισμός κελιού = Εύρος ("A1")«Κανονική, πλάγια, έντονη και έντονη πλάγιαcell.Font.FontStyle = "Τολμηρή πλάγια γραφή"' Το ίδιο μεcell.Font.Bold = Truecell.Font.Italic = True"Ορίστε τη γραμματοσειρά σε Couriercell.Font.FontStyle = "Courier"«Ρύθμιση χρώματος γραμματοσειράςcell.Font.Color = vbBlue' ήcell.Font.Color = RGB (255, 0, 0)«Ρύθμιση μεγέθους γραμματοσειράςcell.Font.Size = 20

Αντιγραφή και επικόλληση

Επικόλληση όλων

Τα εύρη/κελιά μπορούν να αντιγραφούν και να επικολληθούν από τη μια θέση στην άλλη. Ο ακόλουθος κώδικας αντιγράφει όλες τις ιδιότητες του εύρους πηγής στο εύρος προορισμού (ισοδύναμο με CTRL-C και CTRL-V)

1234567 «Απλό αντίγραφοΕύρος ("A1: D20"). ΑντιγραφήΦύλλα εργασίας ("Φύλλο2"). Εύρος ("Β10"). Επικόλληση'ή"Αντιγραφή από το τρέχον φύλλο στο φύλλο με το όνομα" Sheet2 "Εύρος ("A1: D20"). Αντιγραφή προορισμού: = Φύλλα εργασίας ("Φύλλο2"). Εύρος ("B10")

Επικόλληση Ειδικού

Οι επιλεγμένες ιδιότητες του εύρους πηγής μπορούν να αντιγραφούν στον προορισμό χρησιμοποιώντας την επιλογή PASTESPECIAL:

123 "Επικολλήστε το εύρος ως τιμές μόνοΕύρος ("A1: D20"). ΑντιγραφήΦύλλα εργασίας ("Φύλλο2"). Εύρος ("Β10"). Επικόλληση Ειδική επικόλληση: = xlPasteValues

Ακολουθούν οι πιθανές επιλογές για την επιλογή Επικόλληση:

12345678910111213 «Επικόλληση ειδικών τύπωνxlPasteAllxlPasteAllExceptBordersxlPasteAllMergingConditionalFormatsxlPasteAllUsingSourceThemexlPasteColumnWidthsxlPasteCommentsxlPasteFormatsxlPasteFormulasxlPasteFormulasAndNumberFormatsxlPasteValidationxlPasteValuesΜορφές xlPasteValuesAndNumberFormats

Περιεχόμενα AutoFit

Το μέγεθος των γραμμών και των στηλών μπορεί να αλλάξει για να ταιριάζει στο περιεχόμενο χρησιμοποιώντας τον παρακάτω κώδικα:

12345 «Αλλάξτε το μέγεθος των σειρών 1 έως 5 για να ταιριάζουν με το περιεχόμενοΣειρές ("1: 5"). Αυτόματη προσαρμογή«Αλλάξτε το μέγεθος των στηλών Α σε Β για να ταιριάζουν με τα περιεχόμεναΣτήλες ("A: B"). AutoFit

Περισσότερα παραδείγματα εύρους

Συνιστάται να χρησιμοποιείτε Macro Recorder κατά την εκτέλεση της απαιτούμενης ενέργειας μέσω του GUI. Θα σας βοηθήσει να κατανοήσετε τις διάφορες διαθέσιμες επιλογές και πώς να τις χρησιμοποιήσετε.

Για κάθε

Είναι ευκολότερο να περιηγηθείτε σε μια περιοχή χρησιμοποιώντας Για κάθε κατασκευάστε όπως φαίνεται παρακάτω:

123 Για κάθε κελί εντός εμβέλειας ("A1: B100")«Κάνε κάτι με το κελίΕπόμενο κελί

Σε κάθε επανάληψη του βρόχου ένα κελί στην περιοχή εκχωρείται στη μεταβλητή c και οι προτάσεις στον βρόχο For εκτελούνται για αυτό το κελί. Ο βρόχος εξέρχεται όταν υποβληθούν σε επεξεργασία όλα τα κελιά.

Είδος

Η ταξινόμηση είναι μια μέθοδος αντικειμένου εύρους. Μπορείτε να ταξινομήσετε ένα εύρος καθορίζοντας επιλογές για ταξινόμηση σε Εύρος. Ταξινόμηση. Ο παρακάτω κώδικας θα ταξινομήσει τις στήλες A: C με βάση το κλειδί στο κελί C2. Η σειρά ταξινόμησης μπορεί να είναι xlAscending ή xlDescending. Κεφαλίδα: = xlΝαι πρέπει να χρησιμοποιηθεί εάν η πρώτη σειρά είναι η γραμμή κεφαλίδας.

12 Στήλες ("A: C"). Πλήκτρο ταξινόμησης1: = Εύρος ("C2"), _σειρά 1: = xlΑύξουσα, κεφαλίδα: = xlΝαι

Εύρημα

Η εύρεση είναι επίσης μια μέθοδος αντικειμένου εύρους. Βρίσκει το πρώτο κελί με περιεχόμενο που ταιριάζει με τα κριτήρια αναζήτησης και επιστρέφει το κελί ως αντικείμενο εύρους. Επιστρέφει Τίποτα αν δεν υπάρχει ταίρι.

Χρήση ΕύρεσηΕπόμενο μέθοδο (ή FindPrevious) για να βρείτε την επόμενη (προηγούμενη) εμφάνιση.

Ο ακόλουθος κώδικας θα αλλάξει τη γραμματοσειρά σε "Arial Black" για όλα τα κελιά της περιοχής που ξεκινούν με "John":

12345 Για κάθε c In Range ("A1: A100")Αν γ Like "John*" Τότεc.Font.Name = "Μαύρο Arial"Τέλος εανΕπόμενο γ

Ο ακόλουθος κώδικας θα αντικαταστήσει όλες τις εμφανίσεις του "To Test" στο "Passed" στο καθορισμένο εύρος:

12345678910 Με εύρος ("a1: a500")Ορίστε c =. Find ("To Test", LookIn: = xlValues)Αν όχι γ δεν είναι τίποτα τότεfirstaddress = γ. ΔιεύθυνσηΚάνωc.Value = "πέρασε"Ορίστε c =. FindNext (c)Βρόχος ενώ δεν είναι γ δεν είναι τίποτα και γ. Διεύθυνση πρώτης διεύθυνσηςΤέλος εανΤέλος με

Είναι σημαντικό να σημειωθεί ότι πρέπει να καθορίσετε ένα εύρος για τη χρήση του FindNext. Επίσης, πρέπει να δώσετε μια κατάσταση διακοπής, διαφορετικά ο βρόχος θα εκτελεστεί για πάντα. Κανονικά η διεύθυνση του πρώτου κελιού που βρίσκεται αποθηκεύεται σε μια μεταβλητή και ο βρόχος σταματά όταν φτάσετε ξανά σε αυτό το κελί. Πρέπει επίσης να ελέγξετε την περίπτωση όταν δεν βρεθεί τίποτα για να σταματήσει ο βρόχος.

Εύρος διεύθυνσης

Χρησιμοποιήστε το Range.Address για να λάβετε τη διεύθυνση σε A1 Style

123 MsgBox Range ("A1: D10"). Διεύθυνση' ήDebug.Print Range ("A1: D10"). Διεύθυνση

Χρησιμοποιήστε το xlReferenceStyle (προεπιλογή είναι το xlA1) για να λάβετε αποδέκτες σε στυλ R1C1

123 Εύρος MsgBox ("A1: D10"). Διεύθυνση (Στυλ αναφοράς: = xlR1C1)' ήDebug.Print Range ("A1: D10"). Διεύθυνση (Στυλ αναφοράς: = xlR1C1)

Αυτό είναι χρήσιμο όταν ασχολείστε με εύρη που είναι αποθηκευμένα σε μεταβλητές και θέλετε να επεξεργαστείτε μόνο για συγκεκριμένες διευθύνσεις.

Range to Array

Είναι πιο γρήγορο και ευκολότερο να μεταφέρετε ένα εύρος σε έναν πίνακα και στη συνέχεια να επεξεργαστείτε τις τιμές. Θα πρέπει να δηλώσετε τον πίνακα ως Παραλλαγή για να αποφύγετε τον υπολογισμό του μεγέθους που απαιτείται για τη συμπλήρωση του εύρους στον πίνακα. Οι διαστάσεις του πίνακα έχουν οριστεί ώστε να ταιριάζουν με τον αριθμό τιμών στο εύρος.

123456789 Dim DirArray ως παραλλαγή«Αποθηκεύστε τις τιμές στο εύρος του πίνακαDirArray = Εύρος ("a1: a5"). Τιμή'Βρόχος για την επεξεργασία των τιμώνΓια κάθε γ Στο DirArrayΣφάλμα. Εκτύπωση γΕπόμενο

Array to Range

Μετά την επεξεργασία, μπορείτε να γράψετε τον πίνακα πίσω σε μια περιοχή. Για να γράψετε τον πίνακα στο παραπάνω παράδειγμα σε μια περιοχή πρέπει να καθορίσετε μια περιοχή που το μέγεθος της ταιριάζει με τον αριθμό των στοιχείων στον πίνακα.

Χρησιμοποιήστε τον παρακάτω κώδικα για να γράψετε τον πίνακα στο εύρος D1: D5:

123 Εύρος ("D1: D5"). Τιμή = DirArrayΕύρος ("D1: H1"). Τιμή = Εφαρμογή. Μεταφορά (DirArray)

Λάβετε υπόψη ότι πρέπει να μεταφέρετε τον πίνακα εάν τον γράψετε σε μια σειρά.

Εύρος αθροίσματος

12 SumOfRange = Application.WorksheetFunction.Sum (Εύρος ("A1: A10"))Debug.Print SumOfRange

Μπορείτε να χρησιμοποιήσετε πολλές λειτουργίες που είναι διαθέσιμες στο Excel στον κώδικα VBA, καθορίζοντας Application.WorkSheetFunction. πριν από το όνομα συνάρτησης όπως στο παραπάνω παράδειγμα.

Εύρος καταμέτρησης

1234567 «Μετρήστε τον αριθμό των κελιών με αριθμούς στο εύροςCountOfCells = Application.WorksheetFunction.Count (Εύρος ("A1: A10"))Debug.Print CountOfCells«Αριθμός αριθμού μη κενών κελιών στο εύροςCountOfNonBlankCells = Application.WorksheetFunction.CountA (Εύρος ("A1: A10"))Debug.Print CountOfNonBlankCells

Συγγραφέας: Vinamra Chandra

Θα βοηθήσει στην ανάπτυξη του τόπου, μοιράζονται τη σελίδα με τους φίλους σας

wave wave wave wave wave