Excel Forum - Porady, Pomoc,  Excel Help, Excel FAQ Strona Główna
 FAQ  RegulaminRegulamin  Szukaj   Użytkownicy   Grupy   Rejestracja   Profil   Twoje wiadomości   Zaloguj 


Poprzedni temat «» Następny temat
Przesunięty przez: Artik
27-09-2019, 00:06
Excel 2010 - Zaznaczanie checkbox'a na wstążce
Autor Wiadomość
Marti 
ExcelSpec



Wersja: Win Office 2010
Pomógł: 98 razy
Posty: 983
Wysłany: 24-04-2017, 08:18   Excel 2010 - Zaznaczanie checkbox'a na wstążce

Witam!
Przy pomocy Custom UI Editor For Microsoft Office zmodyfikowałem sobie wstążkę, tzn dobudowałem na końcu nową grupę i tam dorzuciłem kilka przycisków, m.in. pole checkbox.

Zaznaczanie bądź odznaczanie ręczne tego checboka na wstążce obsługuje kod:

Kod:
Sub x_serwis_on(control As IRibbonControl, pressed As Boolean)
If pressed = True Then
Call serwis_on
Else: Call serwis_off
End If
End Sub


Czy jest taka możliwość, aby innym kodem zmienić wartość tego checkbox'a?
Chciałbym, aby makro serwis_off uruchamiane przy zamykaniu pliku wymusiło automatyczne odznaczenie checkbox'a. Próbowałem zmieniać wartość zmiennej publicznej
Kod:
passed = False

ale to nic nie zmienia we wstążce.

Jakieś pomysły?

pozdrawiam
_________________
Najlepszym dowodem na to, że w kosmosie istnieje inteligencja, jest to, że się z nami nie kontaktują.
ID posta: 321400 Skopiuj do schowka
 
 
Artik 



Wersja: Win Office 365
Pomógł: 2888 razy
Posty: 9567
Wysłany: 24-04-2017, 09:18   

Marti napisał/a:
Chciałbym, aby makro serwis_off uruchamiane przy zamykaniu pliku wymusiło automatyczne odznaczenie checkbox'a.
Rozumiem, że chodzi o usunięcie zaznaczenia CheckBox-a.
W związku z tym pytanie: Czy nie jest tak, że po ponownym otwarciu pliku Checkbox jest zawsze niezaznaczony, bez względu na to w jakim stanie plik zamknąłeś?

Artik
ID posta: 321401 Skopiuj do schowka
 
 
Marti 
ExcelSpec



Wersja: Win Office 2010
Pomógł: 98 razy
Posty: 983
Wysłany: 24-04-2017, 09:35   

Jest dokładnie tak jak napisałeś ;-) , ale gdy się ktoś rozmyśla z zamykania pliku (a kod z BeforeClose już się wykonał) to wtedy jest taka sytuacja. To można oczywiście oprogramować i wiem jak to zrobić (podstawić w BeforeClose wlasne okno dialogowe
Kod:
MsgBox("Czy chcesz zapisać zmiany w '" & Me.Name & "'?"

, ale bardziej mi chodziło także o samą wiedzę, czy można ingerować w kontrolki wstążki.
_________________
Najlepszym dowodem na to, że w kosmosie istnieje inteligencja, jest to, że się z nami nie kontaktują.
ID posta: 321403 Skopiuj do schowka
 
 
Artik 



Wersja: Win Office 365
Pomógł: 2888 razy
Posty: 9567
Wysłany: 24-04-2017, 10:56   

W takim razie musisz przebudować kody XML i VBA
W XML musi się znaleźć
Kod:
<customUI ... OnLoad="MyAddInInitialize" ...>
oraz
Kod:
<checkBox label="Zrób coś" id="MyCheck1" onAction="x_serwis_on" getPressed="GetPressed" enabled="true"/>


a w VBA:
Kod:
Option Explicit

Public MyRibbon As IRibbonUI
Public g_Pressed As Boolean



Sub MyAddInInitialize(Ribbon As IRibbonUI)
    Set MyRibbon = Ribbon
End Sub


Sub x_serwis_on(control As IRibbonControl, pressed As Boolean)
    g_Pressed = pressed
   
    If pressed Then
        Call serwis_on
    Else
        Call serwis_off
    End If
End Sub


Sub GetPressed(control As IRibbonControl, ByRef returnedVal)
    returnedVal = g_Pressed
End Sub


Sub serwis_off()
    '...
    'tu musimy być pewni, że g_Pressed ma wartość False
   
    'unieważnienie kontrolki
    MyRibbon.InvalidateControl ("MyCheck1")
End Sub


Sub serwis_on()
    '...
    'tu musimy być pewni, że g_Pressed ma wartość True
   
    'unieważnienie kontrolki
    MyRibbon.InvalidateControl ("MyCheck1")
End Sub


Chyba, że coś pokręciłem ;-)

Artik
ID posta: 321404 Skopiuj do schowka
 
 
Marti 
ExcelSpec



Wersja: Win Office 2010
Pomógł: 98 razy
Posty: 983
Wysłany: 24-04-2017, 17:58   

Nie rozumiem działania tego
Kod:
'unieważnienie kontrolki
MyRibbon.InvalidateControl ("MyCheck1")


Generalnie prawie wszystko działa, ale nie to na czym mi tak bardzo zależało. Wymuszenie uruchomienia samego makra serwis_on (z innego makra poleceniem Call), powinno na końcu zaznaczyć checkbox na wstążce, a uruchomienie samego makra serwis_off powinno na końcu odznaczyć checkbox na wstążce, ale tak się nie dzieje.

Zmienna g_Pressed przymuje prawidłowe wartości, ale co ma zdziałać to?
Kod:
MyRibbon.InvalidateControl ("MyCheck1")


I jeszcze po co jest ten fragment?
Kod:
Sub GetPressed(control As IRibbonControl, ByRef returnedVal)
    returnedVal = g_Pressed
End Sub
_________________
Najlepszym dowodem na to, że w kosmosie istnieje inteligencja, jest to, że się z nami nie kontaktują.
ID posta: 321448 Skopiuj do schowka
 
 
Artik 



Wersja: Win Office 365
Pomógł: 2888 razy
Posty: 9567
Wysłany: 24-04-2017, 23:00   

Załącznik by się zdał, by widzieć całość konstrukcji. Wytnij wszystko co nie jest związane z zagadnieniem.

Artik
ID posta: 321457 Skopiuj do schowka
 
 
Tajan


Pomógł: 4630 razy
Posty: 10243
Wysłany: 24-04-2017, 23:38   

Marti, Kod:
Kod:
MyRibbon.InvalidateControl ("MyCheck1")
usuwa wszystkie dane powiązane z kontrolką "MyCheck1". Aby je odbudować automatycznie wywoływana jest procedura GetPressed w której jednym z argumentów jest zmienna returnedVal przekazująca wartość kontrolki. Ponieważ ta wartość jest przekazywana przez referencję, to zmieniając wartość tej zmiennej, nadajemy wartość dla kontrolki MyCheck1.
ID posta: 321459 Skopiuj do schowka
 
 
apollo
ExcelSpec


Pomógł: 1295 razy
Posty: 4482
Wysłany: 25-04-2017, 00:30   

Mi się wydaje, że to jest nieścisłe. Metoda InvalidateControl nic nie usuwa. To tylko wymuszenie uaktualniania kontrolki. Co się dzieje kiedy wywołujemy metodę InvalidateControl obiektu Ribbon?

Dla omówienia ograniczam do getPressed.

1. Jeśli nie ma getPressed to Ribbon nic nie robi. Czyli jeśli w danej chwili checkbox jest zaznaczony/niezaznaczony to nadal jest zaznaczony/niezaznaczony. Czyli nic nie zostało usunięte.

2. Jeśli jest getPressed to kiedy metoda InvalidateControl obiektu Ribbon jest wywołana to obiekt wywołuje getPressed w celu otrzymania stanu checkbox. Czyli ribbon wywołuje getPressed z "pustą tacą" returnedVal (pusta taca czyli returnedVal = FALSE). Kod może położyć na "tej tacy" stan checkbox, i ribbon wg wartości otrzymanej zwrotnie w returnedVal ustawia stan chceckbox. Zazwyczaj kiedy dostarczamy getPressed to znaczy, że chcemy zaznaczyć checkbox zależnie od czegoś. Sprawdzamy coś i zależnie od wyniku zwracamy na "tacy" returnedVal wartość True lub False. Oczywiście żeby zapamiętać bieżący stan checkbox to zazwyczaj ustawiamy zmienną curr_pressed i zwracamy curr_pressed.

Jeśli położymy na "tacy" returnedVal wartość False albo nic nie położymy to ribbon odznacza chceckbox. To odznaczenie jest skutkiem działania naszego kodu, który zwraca False lub nie zmieni wartości domyślnej returnedVal, a nie że InvalidateControl sama tak zdecyduje - usuwa.

Tak dla ścisłości ... Tak na wszelki wypadek ;-)
ID posta: 321462 Skopiuj do schowka
 
 
Artik 



Wersja: Win Office 365
Pomógł: 2888 razy
Posty: 9567
Wysłany: 25-04-2017, 04:16   

No to jeszcze raz, bo wcześniejszy kod pisałem na sucho, bez sprawdzenia. A po stwierdzeniu
Cytat:
Wymuszenie uruchomienia samego makra serwis_on (z innego makra poleceniem Call), powinno na końcu zaznaczyć checkbox na wstążce, a uruchomienie samego makra serwis_off powinno na końcu odznaczyć checkbox na wstążce, ale tak się nie dzieje.
zacząłem wątpić w swoje umiejętności. ;-)

Kod XML, przy założeniu, że dodajemy nową grupę w zakładce Developer, a w grupie jeden Checkbox:
Kod:
<customUI
    xmlns="http://schemas.microsoft.com/office/2006/01/customui"
    onLoad="MyAddInInitialize">
    <ribbon >
        <tabs >
            <tab  idMso="TabDeveloper" >
                <group
                    id="Group1"
                    label="Group1">
                    <checkBox
                        id="MyCheck1"
                        label="Zrób coś"
                        getPressed="getPressed"
                        onAction="x_serwis_on"/>
                </group >
            </tab >
        </tabs >
    </ribbon >
</customUI >

onLoad="MyAddInInitialize" "nakazuje" uruchomienie procedury MyAddInInitialize w trakcie ładowania pliku (otwierania go). getPressed="getPressed" "nakazuje" uruchomienie procedury getPressed, także przy ładowaniu pliku (trochę skrót myślowy), by sprawdzić (i ustawić) stan kontrolki w momencie wywołania tej procedury. Ponieważ w kodzie VBA zmienna globalna g_Pressed jeszcze nie jest zainicjowana, to posiada ona wartość False. Przypisanie parametrowi returnedVal wartości False skutkuje usunięciem zaznaczenia Checkbox-a (acz w momencie otwierania pliku on i tak nie był zaznaczony). Ciągnąc dalej wyjaśnienie XML-a, onAction="x_serwis_on" przypisuje nazwę procedury uruchamianej w momencie działania użytkownika na tą kontrolkę.

Teraz przejdźmy do VBA.
W momencie ładowania pliku wykonywana jest najpierw procedura MyAddInInitialize w której do zmiennej globalnej zostaje przypisany obiekt wstążki. Następnie wykonuje się procedura getPressed. Jak wcześniej wspomniałem odznacza (usuwa zaznaczenie) kontrolki gdyż zmienna g_Pressed, niezainicjowana, ma wartość False. I na tym kończy się (przy takim oprogramowaniu kontrolki) wywołanie procedur inicjujących przy otwarciu pliku.
Teraz użytkownik klika na kontrolkę. Uruchamia się procedura x_serwis_on. Mechanizm niezależny od nas przekazuje do parametru control obiekt klikniętej kontrolki, a do parametru pressed stan kontrolki (zaznaczona lub nie; oczywiście jako wartość logiczną). W procedurze dopiero teraz zostaje zainicjowana zmienna globalna g_Pressed do której przypisujemy stan kontrolki. Parametr control służy do identyfikacji kontrolki "o której mówimy" (tutaj akurat nieużywany), gdyż można tą samą procedurę podpiąć pod wiele kontrolek wstążki. W dalszej części procedury x_serwis_on wołamy procedury serwis_on lub serwis_off w zależności od stanu kontrolki. Przypomnę, że zmienna globalna g_Pressed przechowuje już prawidłową wartość stanu kontrolki. Załóżmy że wywołano procedurę serwis_on (g_Pressed = True). Na końcu procedury jest to, czego jeszcze nie chwyciłeś - unieważnienie kontrolki. Jak przedmówcy już wyjaśnili, użycie InvalidateControl spowoduje wzbudzenie procedur(y) inicjujących(-ej), w tym przypadku tylko jednej - getPressed. W niej teraz my ustawiamy stan kontrolki przypisując parametrowi returnedVal wartość zmiennej g_Pressed.
Jak by się dobrze wczytać, i jeszcze trochę poobserwować stan kontrolki w trakcie wykonania kodu można zauważyć, że w procedurze getPressed w zasadzie ustawiamy jeszcze raz ten sam stan, który kontrolka już posiada - przy otwieraniu pliku kontrolka niezaznaczona i ustawiamy returnedVal na False, a po jej zaznaczeniu myszą - na True. Więc po jakiego grzyba nam ta procedura, skoro ustawiamy to, co jest już ustawione? Ano właśnie dochodzimy do sedna problemu. Chcąc ingerować w stan kontrolki z "zewnątrz" (czytaj: innych procedur, które mają ustawić nam stan kontrolki) musimy to robić przez procedury tzw. wywołań zwrotnych (tutaj wywołaniem zwrotnym jest getPressed lub inne getCośtam). Nie da rady, jak w modelu Excela, odwołać się do właściwości jakiegoś obiektu. Musimy się posiłkować dodatkowymi zmiennymi lub sprawdzaniem pewnych warunków, by zmienić stan kontrolki.
Ogólnie więc do sprawy podchodzimy tak: najpierw gromadzimy sobie pewne dane w zmiennych globalnych, potem Invalidate (lub InvalidateControl), a w wywołaniach zwrotnych ustawiamy wartości pobierając je ze zmiennych globalnych.
Mam świadomość tego, że całe zagadnienie może wydawać się skomplikowane. Mi zrozumienie tego mechanizmu zajęło całkiem niemały okres czasu. Ale potem to już będzie z górki. :-)

Reszta z praktyki w załączniku.

Aaaa, jeszcze o podglądaniu w trybie krokowym. Nie zawsze jest to możliwe, gdyż możemy otrzymać komunikat
Cytat:
Can't execute code in break mode
Należy używać Brakepoint-ów (lub Stop-ów) i F5 zamiast F8. Po nabyciu pewnej wprawy można powrócić do F8, ale nie wszędzie - czasem nadal należy używać F5.

Artik

Test rxCheckBox.xlsm
Pobierz Plik ściągnięto 98 raz(y) 15.62 KB

ID posta: 321464 Skopiuj do schowka
 
 
Marti 
ExcelSpec



Wersja: Win Office 2010
Pomógł: 98 razy
Posty: 983
Wysłany: 25-04-2017, 08:42   

Dzięki wszystkim udzielającym odpowiedzi.
Artik - :danke
Wytłumaczone rewelacyjnie. Dzięki za poświęcony czas. (Chyba) rozumiem te zawiłości VBA z XML, albo przynajmniej tak mi się wydaje. ;-)
A tak w ogóle, to mój checkbox na wstążce się nie zaznaczał, bo w kodzie XML kontrolka nazywała się "Checkbox1" a w VBA miałem

Kod:
MyRibbon.InvalidateControl ("CheckBox1")


Prawie to samo, ale to "prawie" zrobiło różnicę :mrgreen:
_________________
Najlepszym dowodem na to, że w kosmosie istnieje inteligencja, jest to, że się z nami nie kontaktują.
ID posta: 321471 Skopiuj do schowka
 
 
Marti 
ExcelSpec



Wersja: Win Office 2010
Pomógł: 98 razy
Posty: 983
Wysłany: 08-01-2018, 13:12   

Witam.
Wracam do tematu wstążki.
Dołożyłem sobie kontrolkę "Combo1" która uruchamia inne 4 makra (predefiniowany filtry na arkusz).
Mam osobne makro które zdejmuje mi wszystkie autofiltry z arkusza i chciałbym wtedy również wyzerować wartość kontrolki "Combo1". Jak to zrobić?
_________________
Najlepszym dowodem na to, że w kosmosie istnieje inteligencja, jest to, że się z nami nie kontaktują.
ID posta: 337342 Skopiuj do schowka
 
 
Artik 



Wersja: Win Office 365
Pomógł: 2888 razy
Posty: 9567
Wysłany: 08-01-2018, 21:24   

Marti napisał/a:
Dołożyłem sobie kontrolkę "Combo1"
Gdzie? nie widzę. ;-)
Daj załącznik. Usuń makra dotyczące filtrowania za pomocą Combo, wstawiając tylko MsgBox-y w wywołaniach. Interesuje mnie jak ładujesz listę do Combo i jakich wywołań używasz. Gdzie ten przycisk (o ile to przycisk) do usuwania filtrów? Pewnie bym jeszcze parę pytań znalazł, dlatego wolę załącznik.

Artik
_________________
Persistence is a virtue in the world of programming.
ID posta: 337376 Skopiuj do schowka
 
 
Wyświetl posty z ostatnich:   
Odpowiedz do tematu
Nie możesz pisać nowych tematów
Możesz odpowiadać w tematach
Nie możesz zmieniać swoich postów
Nie możesz usuwać swoich postów
Nie możesz głosować w ankietach
Nie możesz załączać plików na tym forum
Możesz ściągać załączniki na tym forum
Dodaj temat do Ulubionych
Wersja do druku

Skocz do:  

Powered by phpBB modified by Przemo © 2003 phpBB Group
Theme xandgreen created by spleen& Programosy modified v0.3 by warna
Opieka techniczna www.marketingNET.pl

Archiwum

Strona używa plików cookies.

Kliknij tutaj, żeby dowiedzieć się jaki jest cel używania cookies oraz jak zmienić ustawienia cookie w przeglądarce.
Korzystając ze strony użytkownik wyraża zgodę na używanie plików cookies, zgodnie z bieżącymi ustawieniami przeglądarki.
Sprawdź, w jaki sposób przetwarzamy dane osobowe