[VBA] For Each Cell

mateuszl95
Użytkownik
Użytkownik
Posty: 97
Rejestracja: 14 paź 2009, o 20:11
Płeć: Mężczyzna
Lokalizacja: Kruszwica
Podziękował: 17 razy
Pomógł: 8 razy

[VBA] For Each Cell

Post autor: mateuszl95 »

Potrzebuję funkcji, która przeszuka wskazany zakres komórek, a następnie sprawdzi w domyślnej kolejności ten obszar i wskaże, która przeszukiwana komórka spełnia założone kryterium (taka komórka jest tylko jedna). Kod:

Kod: Zaznacz cały

Function gdzie(szukana_wartosc, obszar)
Dim i
i = 0
Dim c As Variant
For Each c In Range(obszar)
i = i + 1
        If c.Value = szukana_wartosc Then
        gdzie = i
        End If
    Next
End Function
Formuła =gdzie(0;A2:D2) nie działa. W czym tkwi błąd?
Próbowałem również zamiast: Dim c as Variant -> Dim c as Range, ale też bez skutku.
Komórka zwraca komunikat #ARG!
Ostatnio zmieniony 3 paź 2014, o 20:56 przez Afish, łącznie zmieniany 1 raz.
Powód: Poprawa wiadomości.
a4karo
Użytkownik
Użytkownik
Posty: 22203
Rejestracja: 15 maja 2011, o 20:55
Płeć: Mężczyzna
Lokalizacja: Bydgoszcz
Podziękował: 38 razy
Pomógł: 3753 razy

[VBA] For Each Cell

Post autor: a4karo »

Spróbuj tak:

Kod: Zaznacz cały

Function gdzie(szukana_wartosc as Variant, obszar as Range)
Dim i
i = 0
Dim c As Variant
For Each c In obszar.cells
i = i + 1
        If c.Value = szukana_wartosc Then
        gdzie = i
        End If
    Next
End Function
Ale w ten sposób dostanies numere i i nie będziesz wiedział o którą komórkę chodzi. lepiej zwróc jej adres bezwzględny.
mateuszl95
Użytkownik
Użytkownik
Posty: 97
Rejestracja: 14 paź 2009, o 20:11
Płeć: Mężczyzna
Lokalizacja: Kruszwica
Podziękował: 17 razy
Pomógł: 8 razy

[VBA] For Each Cell

Post autor: mateuszl95 »

Gdybym wyciągał adres bezwzględny, to później musiałbym z tego adresu wyciągać nr kolumny ale dzięki za to mam kolejne pytanie: jakich błędów unikam definiując w nazwie funkcji typ wprowadzanych danych? Pytam m.in. dlatego, że po usunięciu typu danych funkcja również działa jak należy.
a4karo
Użytkownik
Użytkownik
Posty: 22203
Rejestracja: 15 maja 2011, o 20:55
Płeć: Mężczyzna
Lokalizacja: Bydgoszcz
Podziękował: 38 razy
Pomógł: 3753 razy

[VBA] For Each Cell

Post autor: a4karo »

Jak nie podasz typu danych, to zakladany jest typ Variant. Podanie typu pozwala zoptymalizowac kod oraz wpływa na czytelnośc kodu i latwośc debugowania.

Numer kolumny możesz wyciągną od razu pisząc gdzie=c.column (podobnie wiersz: c.row)
OShon
Użytkownik
Użytkownik
Posty: 65
Rejestracja: 4 mar 2014, o 00:32
Płeć: Mężczyzna
Lokalizacja: VBATools | Kraków | Poland | Europe | Earth | SolSystem | SomewareInSpace
Podziękował: 1 raz
Pomógł: 7 razy

[VBA] For Each Cell

Post autor: OShon »

Podstawowy błąd to założenie że funkcja ma nic nie zwracać (jak to jest pow.)
Nie zwraca procedura, która też może mieć deklarowane zmienne wejściowe.

Czyli powinno być:

Kod: Zaznacz cały

Sub gdzie(szukana_wartosc as Variant, obszar as Range)
A funkcja ma dać nam coś na wyjściu. W tym przypadku chyba liczbę typu Long:

Kod: Zaznacz cały

Function gdzie(szukana_wartosc as Variant, obszar as Range) as Long
Efektywnie też jest, aby po spełnieniu warunku wyjść z pętli.
Dlatego że jeśli mamy w obszarze do przepatrzenia wszystkie kolumny to mamy ich 16k. Jak znajdzie to powinna skończyć literować (wykona się szybciej).

Kod: Zaznacz cały

Exit For
Zmienna c podawana w pętli nie może być variantem, ale powinna być zakresem. Ponieważ to tego zakresu wartość badamy .Value:

Kod: Zaznacz cały

Dim c as Range
Zmienna wejściowa szukana_wartosc nie powinna być tez variantem, ponieważ ten typ ma ograniczenie w wartości (jak małe sprawdź w helpie). A lepiej przyjąć String, a jeśli po sprawdzeniu okaże sie liczbą to przypisanie do Byte, Integer albo Long

Kod: Zaznacz cały

if isnumeric(szukana_wartosc) true then '...
a4karo
Użytkownik
Użytkownik
Posty: 22203
Rejestracja: 15 maja 2011, o 20:55
Płeć: Mężczyzna
Lokalizacja: Bydgoszcz
Podziękował: 38 razy
Pomógł: 3753 razy

[VBA] For Each Cell

Post autor: a4karo »

Podstawowy błąd to założenie że funkcja ma nic nie zwracać (jak to jest pow.)
Nie zwraca procedura, która też może mieć deklarowane zmienne wejściowe.
Ależ ta funkcja zwraca Variant o nazwie takiej, jak funkcja (przypisanie gdzie=i)
Zmienna c podawana w pętli nie może być variantem, ale powinna być zakresem. Ponieważ to tego zakresu wartość badamy .Value:
Gwoli ścisłości: może byc Variant, ale lepiej, żeby była Range, fakt.

Z reszta pełna zgoda
ODPOWIEDZ