piątek, 25 grudnia 2015

• VBA 7.0 i MS Access 2010+

Na stronie Alexa Gorbatcheva pod adresem http://alexgorbatchev.com/SyntaxHighlighter/ znalazłem skrypt służący do podświetlania (kolorowania) elementów składniowych kodu źródłowego programu. Na swoim blogu Kevin Junghans w artykule Adding SyntaxHighlighter to Blogger Dynamic Views przedstawił, jak zastosować SyntaxHighlighter na swoim blogu. Początkowo skorzystałem z rad Kevina, ale po pewnym czasie opracowałem swój sposób na zastosowanie skryptu służącego do kolorowania składni. Ale o tym będzie później. Na razie przejdę do właściwego tematu, jakim jest 64-bitowy Access, a raczej 64-bitowe VBA 7.0.

Microsoft Office 2010+ jest obecnie dostępny w wersji 32 i 64-bitowej. Wersja 64 bitowa umożliwia pracę ze znacznie większymi zbiorami danych. Możliwość ta jest szczególnie ważna podczas pracy z dużą ilością danych w programie Microsoft Excel 2010+. Wraz z wprowadzeniem nowej, 64 bitowej, wersji pakietu Microsoft Office 2010+, wprowadzono nową wersję Visual Basic for Applications (VBA) pod nazwą VBA 7.0, która przeznaczona jest do pracy zarówno w 32-bitowych i 64-bitowych aplikacjach.
Niestety, jedynie wersja 32 bitowa pakietu Office 2010+ pozwala nadal używać 32 bitowe dodatki dla pakietu Office oraz korzystanie ze „starego” kodu bez konieczności jakichkolwiek modyfikacji w kodzie VBA. Wszystkie dodatkowe wtyczki dla Office będą działały jedynie w 32 bitowej wersji, gdyż nie są one zgodne z 64 bitowym Officem. Próba instalacji jakiegokolwiek dodatku (pluginu) zakończy się niepowodzeniem. Jeśli więc zdecydujmy się na zainstalowanie 64 bitowego Office, to musimy się liczyć z pewnymi ograniczeniami funkcjonalności 64 bitowego Office w porównaniu do jego 32 bitowej wersji.

Nowości i zmiany w VBA 7.0

• VBA7 - stała kompilacji warunkowej
Umożliwia sprawdzenie, czy uruchomiona aplikacja używa VBA 7.0 (64 bitowego lub 32 bitowego), czy poprzedniej 32 bitowej wersji VBA (6.0). Zwracana wartość VBA7 = TRUE informuje, że uruchomiona została aplikacja pakietu Office w wersji 2010 lub nowszej.
• Win64 - stała kompilacji warunkowej
Pozwala stwierdzić, czy uruchomiona została 32 bitowa, czy 64 bitowa wersja pakietu Microsoft Office.
 
Public Sub testVBA()
 ' Sprawdź wersję VBA
 #If VBA7 Then
   ' środowisko VBA 7 (wersja 32 lub 64 bitowa MS Office +2010+)
   #If Win64 Then
      ' 64-bitowe środowisko VBA 7.
      MsgBox "Kod VBA 7 uruchomiony w 64-bitowej wersji MS Office 2010+"
   #Else
      ' 32-bitowe środowisko VBA 7.
      MsgBox "Kod VBA 7 uruchomiony w 32-bitowej wersji MS Office 2010+"
   #End If
 #Else
   ' Środowisko wersji VBA 6, lub wersji niższej
   MsgBox "Kod VBA uruchomiony w wersji VBA 6 lub niższej."
 #End If

End Function
 
• PtrSafe - kwalifikator
Używany jest do deklarowania procedur i funkcji z zewnętrznych bibliotek DLL w 64 bitowym VBA 7. Określa, że deklaracja funkcji jest zgodna z 64 bitowymi środowiskami programistycznymi. Atrybut ten jest obowiązkowy w systemach 64 bitowych. Deklarując funkcję z zewnętrznej biblioteki należy za każdą instrukcją Declare umieścić atrybut (kwalifikator, słowo kluczowe) PtrSafe. Należy także zmienić 32 bitowe odwołania do uchwytów i wskaźników na zgodne z typem LongPtr, a 64 bitowym argumentom przypisać nowy typ danych LongLong. Aby zapewnić wsteczną kompatybilność z VBA w wersji 6.0 atrybut PtrSafe nie jest wymagany w 32 bitowym środowisku VBA 7, ale nic nie stoi na przeszkodzie, by kwalifikator ten stosować w 32 bitowym środowisku VBA 7.
 
#If VBA7 Then
   ' Aplikacja używa 32 lub 64-bitowej wersji VBA 7 (Office 2010 i wyższe wersje).
   ' Zastosuj atrybut PtrSafe po instrukcji Declare
   Public Declare PtrSafe Function...
#Else
   ' Aplikacja używa 32 bitowej wersji VBA 6 (Office 2007 i niższe wersje)
   ' Nie używaj atrybutu PtrSafe po instrukcji Declare
   Public Declare Function...
#End If
 
• LongLong - typ danych
8 bajtowy typ danych. Przechowuje liczby w przedziale wartości od -9.223.372.036.854.775.808 do 9.223.372.036.854.775.807. Typ ten jest dostępny tylko w 64 bitowym środowisku (w 64 bitowej wersji pakietu Office).
• LongPtr - typ danych
W 64 bitowym środowisku VBA 7 jest to 8 bajtowa liczba typu LongLong. W 32 bitowym środowisku VBA 7 jest to liczba 4 bajtowa typu Long. Typ ten (LongPtr) jest zalecany przy deklarowaniu uchwytów i wskaźników w obu środowiskach VBA 7 (64 i 32 bitowym). Korzystanie z typu LongPtr umożliwia pisanie kodu, który będzie działał zarówno w 32 jak i 64 bitowym środowisku VBA 7.
Typ LongPtr obsługiwany jest tylko w VBA 7 (zarówno w 32 bitowym jak i 64 bitowym środowisku).
Ponieważ 32 bitowe VBA nie miało takiego typu, więc w przypadku zadeklarowania wskaźnika (uchwytu) jako typ Long, wszystkie zmienne 64 bitowe zostały by „ucięte” do wartości 32 bitowej i mogłyby wskazywać na nieprawidłowy uchwyt (wskaźnik).
 
 ' Sprawdź wersję VBA
 #If VBA7 Then
    ' Aplikacja używa 32 lub 64-bitowej wersji VBA 7 (Office 2010 i wyższe wersje).
    ' Zastosuj atrybut PtrSafe po instrukcji Declare
    ' i zmień deklaracje uchwytów i wskaźników na typ LongPtr
     Public Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" ( _
                                                  ByVal hwnd As LongPtr, _
                                                  ByVal wMsg As Long, _
                                                  ByVal wParam As LongPtr, _
                                                  lParam As Any) As LongPtr
 #Else
    ' Aplikacja używa 32 bitowej wersji VBA 6 (Office 2007 i niższe wersje)
    ' Nie używaj atrybutu PtrSafe po instrukcji Declare
    ' deklaracje uchwytów i wskaźników są typu Long
     Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
                                                  ByVal hwnd As Long, _
                                                  ByVal wMsg As Long, _
                                                  ByVal wParam As Long, _
                                                  lParam As Any) As Long
 #End If
 

Ponieważ atrybut PtrSafe nie jest wymagany w 32 bitowym środowisku VBA 7, możemy skorzystać ze stałej kompilacji Win64 i typu LongLong, bez używania typu LongPtr.

 
 ' Sprawdź, czy środowisko VBA jest 64 bitowe
 #If Win64 Then
    ' Aplikacja używa 64-bitowej wersji VBA 7 (Office 2010 i wyższe wersje).
    ' Zastosuj atrybut PtrSafe po instrukcji Declare
    ' i zmień deklaracje uchwytów i wskaźników na typ LongLong
     Public Declare PtrSafe Function SendMessage Lib "user32" Alias "SendMessageA" ( _
                                                  ByVal hwnd As LongLong, _
                                                  ByVal wMsg As Long, _
                                                  ByVal wParam As LongLong, _
                                                  lParam As Any) As LongLong
 #Else
    ' Aplikacja używa 32 bitowej wersji VBA 7 (Office 2010+) lub VBA 6 (Office 2007-)
    ' Nie używaj atrybutu PtrSafe po instrukcji Declare
    ' deklaracje uchwytów i wskaźników powinny być typu Long
     Public Declare Function SendMessage Lib "user32" Alias "SendMessageA" ( _
                                                  ByVal hwnd As Long, _
                                                  ByVal wMsg As Long, _
                                                  ByVal wParam As Long, _
                                                  lParam As Any) As Long
 #End If
 

Powiem szczerze. Nie wiem która metoda deklaracji jest optymalna. Czy korzystanie ze stałej kompilacji VBA7 i typu LongPtr do deklaracji uchwytów i wskaźników, czy korzystanie ze stałej kompilacji Win64 i typu LongLong do deklaracji uchwytów i wskaźników w środowisku 64 bitowym, a typu Long w 32 bitowych VBA 7 i VBA 6.