Elektroda.pl
Elektroda.pl
X
Proszę, dodaj wyjątek www.elektroda.pl do Adblock.
Dzięki temu, że oglądasz reklamy, wspierasz portal i użytkowników.

[vba][excel] - Jak sprawdzić numer indeksu kontrolki na UserForm

siwek62 28 Sty 2013 15:13 2859 8
  • #1 28 Sty 2013 15:13
    siwek62
    Poziom 11  

    Witam chciałby spytać czy można a jeżeli tak to jak odczytać w kodzie vba nr indeksu kontrolki na User Form. W swoim kodzie często posługuje się metodą Controls(n)... zamiast nazwą controlki. Jeśli znam numer ideksu kontrolki, której ma dotyczyć działanie to sprawa jest prosta ale nie potrafię znaleźć odpowiedzi jak w trakcie wykonywania kodu odczytać indeks.
    Doszedłem w swoich poszukiwaniach jak dowiedzieć się jaki indeks ma dana kontrolka:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Przykładowe wykorzystanie informacji o nr indeksu kontrolki:
    Mam na swoim UserForm kilkanaście TextBoxów które wymagają wpisania wartości numerycznej, jeżeli użytkownik nie wpisze wartości numerycznej to chcę wyświetlić stosowny komunikat
    Kod: vb
    Zaloguj się, aby zobaczyć kod

    Potrzebny mi numer ideksu kontrolki, którą Updejtował urzytkownik.

    0 8
  • Pomocny post
    #2 28 Sty 2013 15:42
    marcinj12
    Poziom 40  

    Witam,
    Możesz to zrobić prościej - przekazując referencję do kontrolki jako argument funkcji.
    Przykład:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Możesz też zrobić walidację zbiorczą, np. po kliknięciu przycisku sprawdzić, czy wypełniono wszystkie textboxy umieszczone wewnątrz ramki Frame:
    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Według mnie posługiwanie się indeksem kontrolki jest raz że ryzykowne (jak dodasz nową kontrolkę na formę a nie zmienisz czegoś w kodzie - odwołujesz się już do innej), a dwa - żeby ustalić indeks kontrolki "w trakcie" działania kodu, i tak musisz znać jej nazwę - więc lepiej odwołać się do niej od razu po nazwie.

    0
  • #3 28 Sty 2013 17:02
    siwek62
    Poziom 11  

    Dzięki, jak zwykle jesteś niezawodny. Wykorzystam pierwsze rozwiązanie.
    Co do indeksów to fakt, jest to trochę denerwujące, że trzeba pamiętać o kolejności umieszczania na formie jeśli się chcę mieć je jakoś uporządkowane. Kiedyś próbowałem znaleźć odpowiedz czy da się zmieniać ideksy po umieszczeniu ich na formie i wyszło mi że nie.
    A co do odwoływania się do indeksów to tak sobie myślę, że czasami trzeba. Np mam taki fragment kodu:

    Kod: vb
    Zaloguj się, aby zobaczyć kod

    Kontrolki są w jednakowych Framach i mogę je sobie ukrywać bądz odkrywać w pętli. Kombinuje teraz jak takie odwołanie do nazwy można by zastosować, które bardzo mi się podoba a do tej pory nigdzie się na nie nie natknąłem. Super bardzo dziękuje znowu wiem trochę więcej.

    0
  • #4 28 Sty 2013 18:02
    czeles
    Poziom 15  

    Nie jest potrzebne odwoływanie się do Indexu kontrolki (z powodów przedstawionych w poprzednich odpowiedziach) ponieważ wystarczy nazwać TextBoxy np. TxBx_1, TxBx_2... TxBx_n i w pętli odwoływać się do nich:

    Kod: vb
    Zaloguj się, aby zobaczyć kod

    0
  • #5 28 Sty 2013 19:29
    siwek62
    Poziom 11  

    No tak masz rację, trochę za szybko pomyślałem. Prawdę mówiąc to stosuje także tą metodę w innych miejscach i teraz widzę, że mógłbym zrezygnować z indeksów. Ale zatrzymałem się na kolejnej przeszkodzie dotyczącej przekazywania referencji. Mam następujący kod obsługujący zdarzenie Change lub AfterUpdate (nie mogę się zdecydować, które jest właściwsze) kontrolki:

    Kod: vb
    Zaloguj się, aby zobaczyć kod

    Takich pól mam 90, podzielonych na 10 framów identyfikuje je przez wartość zmiennych vWi i vPo. Pola są różnego typu i w procedurze wart_pola robie różne cuda w zależności od tego z której kontrolki tam trafię, także tam chcę umieścić sprawdzanie czy wartość jest liczbą (ale oczywiście nie tylko). I teraz, jak przekazać referencję kontrolki żeby móc ją następnie przekazać dalej?
    Na razie znalazłem rozwiązanie, które jest połączeniem nowego ze starym:
    Kod: vb
    Zaloguj się, aby zobaczyć kod

    0
  • #6 28 Sty 2013 22:18
    marcinj12
    Poziom 40  

    Przyznam że nie do końca rozumiem o co chodzi...

    Jeśli mówimy o Change lub AfterUpdate - to zależy, kiedy chcesz akcję wykonac. Change będzie się wykonywała po każdej zmianie w kontrolce, i np. przy wpisywaniu 5 znakowego tekstu w textboxie wykona się pięć razy. AfterUpdate wykona się w tym czasie raz, ale dopiero przy po opuszczeniu pola.

    Jeśli zaś chodzi o tą akcję wartości kontrolki, to pytanie czy potrzebujesz tych wartości vWi i vPo do czegoś, oprócz ustalenia z której kontrolki akcja pochodzi?
    Jak pisałem w #2, mógłbyś zrobić po prostu:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Uproszczając przykład, można przekazywać referencję dalej, do kolejnych funkcji:
    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Jeżeli potrzebujesz mieć jakieś dodatkowe informacje przypisane do kontrolki, zawsze możesz wykorzystać atrybut TAG.

    0
  • #7 28 Sty 2013 23:16
    siwek62
    Poziom 11  

    O to mi chodziło, nie wpadłem na to żeby dwa razy przekazać tą samą zmienną. Wartości vWi i vPo potrzebuje bo o od tego zależy jakie wartości z tablicy mi pobiera. Myślę, że to rozwiązuje problem.
    Co do Change i AfterUpdate to oczywiście znam tą właściwość dlatego skłaniam się raczej do AfterUpdate ale czasami obserwuje niepożądane działanie. Np w tym przypadku gdy wartość nie jest liczbą, chciałbym żeby fokus zosatł w polu edytowanym a tak się niestety nie dzieje:

    Kod: vb
    Zaloguj się, aby zobaczyć kod

    Focus ustawia się w kontrolce o kolejnym TabIndex lub w kontrolce wskazanej myszką, w zależności czy użyje tabulatora czy myszki żeby wyjść z kontrolki.

    I jeszcze jedno, do procedury wartosc_pola odwoluje sie nie tylko z kontrolki typu TextBox ale także CheckBox. Odwołując się do wartosc_pola w twojej propozycji, nie można nie podać parametru. Jak to obejść?

    Już wiem - Optional

    0
  • #8 29 Sty 2013 01:12
    marcinj12
    Poziom 40  

    Żaby zachować focusa na kontrolce, musisz wykorzystać zdarzenie, które pozwala anulować akcję, np.BeforeUpdate, w sposób podobny do tego:

    Kod: vb
    Zaloguj się, aby zobaczyć kod


    Jeżeli parametr funkcji może być różnych typów, to użyj ogólnego typu: MSForms.Control, a wewnątrz, za pomocą np. TypeName() i ifów lub selecta sprawdź, jakiego typu jest kontrolka i w zależności od tego wykonaj odpowiednią akcję, np.
    Kod: vb
    Zaloguj się, aby zobaczyć kod

    0
  • #9 29 Sty 2013 11:24
    siwek62
    Poziom 11  

    Ok, dzięki za pomoc.

    Pozdrawiam Tomek

    0