Znów ten office? Tak ;) szczerze, dużo rzeczy się nauczyłem i dużo rzeczy napotkałem i teraz chciałbym się nimi z wami podzielić. Dziś na tacę trafią event BeforeSave który istnieje w Excel i Word i który umożliwia nam anulowanie zapisania dokumentu, jeżeli zajdzie taka potrzeba, jak i poproszenie użytkownika o dodatkową akcję.

Kto wie jakie jest pierwszy problem? Ci którzy pomyśleli, że inaczej on działa dla Excel i dla Word to dostają piątkę. Brawo. Tak, event ten działa różnie dla Excel i dla Word. Do problemu jeszcze wrócimy,

Kto wie jakie jest drugi problem? Ci którzy pomyśleli, że inaczej on działa w zależności do wersji Office to dostają piątkę. Brawo. Ale to tego tematu jeszcze wrócimy.

Kto wie jaki jest trzeci problem? To jakie parametry on podaje w jakim momencie. Choć to już raczej feature można nazwać.

Kto wie jaki jest problem czwarty? Ten go zgadł: pisanie jednego kodu dla wielu wersji office, ten dostaje piątkę!. Brawo! :)

Ale zacznijmy po kolei rozwiązywać każdy problem albo i nie do końca rozwiązać.

Problem Pierwszy: Różnice między Word a Excel

Event znacząco się różni zachowaniem i kiedy jest on wywoływany. Przy wordzie, jest on wywoływany zaraz po wciśnięciu CTRL+S, w Excel to już działa inaczej. Jest on wywoływany w momencie wybranie pliku do zapisania. W Word pomijany jest po prostu ten krok.

Ale to jest różnica przy CTRL+S. Prosta, szybka do wychwycenia i o tych eventach, przy zapisie dokumentów już pisałem. Większa różnica zaczyna się kiedy zamykamy Excel i Word.

Pojawia nam się okno:

Co zrobić z dokumentem w trakcie zamykania Word
Co zrobić z dokumentem w trakcie zamykania Word

W którym mamy trzy opcje wyboru:

  • Zapisz
  • Nie zapisuj
  • Anuluj

W Word * (uwaga na problem nr 2), event BeforeSave zostanie wywołany tuż po kliknięciu przycisku Zapisz, w problemie nr 2 opisuje kolejny problem związany z drugim przyciskiem. Trzeci przycisk zaś nic nie robi.

Jeżeli w Word pod Zapisz zrobimy Cancel na event BeforeSave, dokument nie zostanie zamknięty ani zapisany.

W Excel, event BeforeSave zostanie wywołany nie po kliknięciu Zapisz, ale po wybraniu lokalizacji i nazwy pliku i kliknięciu zapisz. Próba anulowania eventu tutaj skończy się niezapisaniem pliku i ZAMKNIĘCIEM Excel. Czyli straceniem naszych zmian. Ciekawe? Bardzo. Pewne pomyślicie więc, że jest jakiś magiczny event jak BeforeClose który umożliwi nam zablokowanie zamykania? Nic bardziej mylnego. BeforeClose jest wywołany po kliknięciu na zamknięcie okna aplikacji a przed pojawieniem się ekranu z możliwymi opcjami wyboru co z danym arkuszem zrobić.

Ciekawy problem? Bardzo :) czy znam jego obejście w Excel? Nie. Nie udało mi się tego powstrzymać. Jedynie poinformowałem o tym użytkownika. Znacie na to obejście?

Problem Drugi: Różne działanie w zależności od wersji

O kolejny problemie częściowo wspomniałem już poprzednio. Tyczy on tego co się dzieje z Wordem jak klikniemy “nie zapisuj”. W końcu Nie zapisuj znaczy nie zapisuj więc co mogłoby się dziać?

A no, tyle, że od 2013 Nie zapisuj ZAPISUJE tymczasowy plik na wszelki wypadek. Mamy wtedy jakiś czas na to by się dobrać do pliku jakby się okazało, że jednak te zmiany są nam potrzebne. A to znaczy tyle, że event BeforeSave jest wywoływany kiedy klikamy “nie zapisuj”.

Jak możemy się przed tym bronić? Word ma własność IsInAutosave, która pozwala nam wykryć, czy ten event został wywołany przez Worda w tym wypadku “Nie zapisuj”. Trzeba jednak pamiętać, że własność ta nie jest dostępna w poprzednich wersjach office. Ale też poprzednie wersje nie mają tego problemu.

Problem ten istnieje tylko i wyłącznie w Word, w Excel nie.

I teraz dodatkowo miałem przypadek, który dział się na kompie jednego użytkownika i nie mogłem go powtórzyć na żadnym innym komputerze do którego miałem dostęp. Mianowicie, jak zamykaliśmy Word i kliknęliśmy “Nie zapisuj” to zdarzenie BeforeSave było wywołane, ale, aktywny dokument nie istniał. Czyli oficjalnie dokument został już zamknięty, Office właśnie się go z pamięci pozbywał, ale wrzucił nam zdarzenie BeforeSave… – Word 2007.

Problem Trzeci: Własności przekazywane do metody

Tutaj wszystko się rozbija o to kiedy event zostanie wywołany oraz w jakiej wersji office ;) Jeżeli klikamy CTRL+S w Excel, to zostanie on wywołany przed pokazaniem się dialogu i w metodzie będziemy mieli, że SaveDialogUI jest na true. Ale już przy zamykaniu zostanie on wywołany z SaveDialogUI na false mimo, że on nam się pokazał.

Do tego SaveDialogUI nie pokazuje się jak zapisujemy zmiany do istniejącego pliku jedynie, kiedy jest save as brane pod uwagę lub jest to pierwsze zapisanie pliku.

Problem Czwarty: Kod dla wielu wersji office

To już kwestia organizacyjna. Ale zaczynamy albo pisać specjalne wersje hendlerów per wersja, albo nasz handler rozgałęzia wykonanie zdarzenia na wiele metod, albo… robimy try/catch.

Nie jest to ani fajne, ani ładne. Do tego cały czas mogą dojść kolejne przypadki, w których nasz kod nie zadziała. Więc infrastruktura powinna nam pozwalać na wrzucanie tak zarwanych “special case” byśmy mogli to zweryfikować i w razie co zareagować specjalnie.

Ale po co ten punkt? A no właśnie po to byśmy o tym pamiętali. Coś co miało być piękne i szybkie, stało się nagle kilkuset linijkowym kolosem, który obsługuje różne wersje office i różne konkretne przypadki.

Podsumowanie

Programowanie pod office może być fun, ale dla mnie jest to bardziej hackowanie rzeczywistości i próba dostosowania narzędzia do moich potrzeb. Problemy są zarówno pod względem braku dokumentacji (rozsądnej) – czyli ja mam kłopot z zrozumieniem problemu co i jak, jak i problemy są po stronie MS – bugi, pytania, dlaczego tak a nie inaczej coś zostało zrealizowane. BeforeSave jest jednym z kilkunastu przykładów, gdzie programiści Office wykazali się pracą kreatywną.

I jak zauważyliście wspomniałem tutaj o Excel i Word. Dlaczego? Bo PowerPoint to zupełnie inna para kaloszy. Od początku tam jest z nim coś nie tak ;) nie licząc od nadużywania aplikacji do niecnych celów tworzenia nudnych prezentacji, po implementację samego rozwiązania. Ale o tym jeszcze będzie.