Z postu z dnia 25 grudnia 2015 r. • VBA 7.0 i MS Access 2010+ „mniej więcej wiemy” (co nie znaczy, że mniej niż więcej ☺, że w pakiecie Office 2010+ wprowadzono nową wersję Microsoft Visual Basic for Applications (VBA) oznaczoną jako VBA 7.0. Wersja ta poprawia wydajność aplikacji w 64 bitowych środowiskach. Równocześnie umożliwia tworzenie aplikacji zgodnych z wcześniejszymi wersjami pakietu Office (2007 i wersje niższe). Aby umożliwić przystosowanie kodu do konkretnej wersji pakietu Office wprowadzono dwie nowe stałe kompilacji warunkowej:
- VBA7
- • pozwala ustalić, czy używane jest nowe środowisko VBA 7.0, czy też starsze wersje VBA.
- Win64
- • umożliwia sprawdzenie, czy środowisko VBA jest 64 bitowe, czy 32 bitowe.
oraz nowy kwalifikator:
- PtrSafe
- • używany do deklarowania procedur i funkcji z zewnętrznych bibliotek DLL w VBA 7 (zawsze w 64 bitowym środowisku VBA7, opcjonalnie w 32 bitowym)
• Jak zadeklarować i uruchomić funkcje API w MS Access 2010+
API - Application Programming Interface jest to zbiór funkcji i procedur znajdujących się w plikach dll (Dynamic Link Library). Inaczej mówiąc są to biblioteki dołączane dynamicznie.
- Podstawowe biblioteki w systemie Windows to:
- • USER32.dll - funkcje zarządzania środowiskiem Windows
- • KERNEL32.dll - funkcje zarządzania funkcjami systemu operacyjnego
- • GDI32.dll - Graphics Device Interface - funkcje zarządzające wyprowadzaniem danych na zewnętrzne urządzenia.
Jak zadeklarować i wywołać funkcje API, tak by prawidłowo działały zarówno w 32-bitowym, jak i 64-bitowym środowisku VBA 7.0 oraz w wersjach niższych VBA możemy dowiedzieć się na portalu MSDN (Microsoft Developer Network), na stronie: Working with VBA in the 32-bit and 64-bit Versions of Office 2010. Skorzystajmy więc z rad Microsoftu:
Applies to: Microsoft Office 2010
Published: May 2010
Provided by: Frank Rice, Microsoft CorporationJak używać stałej kompilacji VBA7 dowiemy się na podstawie przykładowej funkcji DisplayExcelWindowSize zwracającej położenie i wymiary okna głównego programu Excel 2010. W tym celu musimy zadeklarować strukturę RECT oraz dwie funkcje API:
• funkcję FindWindow znajdującą okno o określonej klasie i (lub) tytule,
• funkcję GetWindowRect określającą położenie i wymiary okna.Ponieważ deklaracje tych funkcji są różne w wersji 32 i 64 bitowej, należy zastosować stałą kompilacji warunkowej VBA7 przekierowującą kompilator do odpowiedniej sekcji kodu.
Funkcja DisplayExcelWindowSize wywołuje FindWindowi GetWindowRect i wyświetla okno komunikatu z położeniem i wymiarami okna programu Excel 2010.
' A user-defined type to store the window dimensions.
Type RECT
Left As Long
Top As Long
Right As Long
Bottom As Long
End Type
' Test which version of VBA you are using.
#If VBA7 Then
' API function to locate a window.
Declare PtrSafe Function FindWindow Lib "user32" _
Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As LongPtr
' API function to retrieve a window's dimensions.
Declare PtrSafe Function GetWindowRect Lib "user32" ( _
ByVal hwnd As LongPtr, _
lpRect As RECT) As Long
#Else
' API function to locate a window.
Declare Function FindWindow Lib "user32" _
Alias "FindWindowA" ( _
ByVal lpClassName As String, _
ByVal lpWindowName As String) As Long
' API function to retrieve a window's dimensions.
Declare Function GetWindowRect Lib "user32" ( _
ByVal hwnd As Long, _
lpRect As RECT) As Long
#End If
Sub DisplayExcelWindowSize()
Dim hwnd As Long, uRect As RECT
' Get the handle identifier of the main Excel window.
hwnd = FindWindow("XLMAIN", Application.Caption)
' Get the window's dimensions into the RECT UDT.
GetWindowRect hwnd, uRect
' Display the result.
MsgBox "The Excel window has these dimensions:" & _
vbCrLf & " Left: " & uRect.Left & _
vbCrLf & " Right: " & uRect.Right & _
vbCrLf & " Top: " & uRect.Top & _
vbCrLf & " Bottom: " & uRect.Bottom & _
vbCrLf & " Width: " & (uRect.Right - uRect.Left) & _
vbCrLf & " Height: " & (uRect.Bottom - uRect.Top)
End Sub
Po zapoznaniu się z kodem ze strony Microsoftu, pozostało tylko przekopiowanie kodu do modułu programu Excel 2010 (wersja 64 bitowa)
i uruchomienie funkcji DisplayExcelWindowSize (...), by uzyskać informacje o położeniu i wymiarach głównego okna programu Excel 2010.
W dobrym zwyczaju jest skompilowanie kodu przed jego uruchomieniem.
No i ZONK !
Kompilator zgłasza błąd „Niezgodność typów”. I co najgorsze (nie dla mnie), kompilator ma rację.
Zgodnie z deklaracją, funkcja FindWindow (...) zwraca typ LongPtr, który w 64 bitowym środowisku jest liczbą
typu LongLong.
„Zamiatając pod dywan”, szybko zmieniamy deklarację uchwytu okna hwnd:
Dim hwnd As Long
na
Dim hwnd As LongPtr
lub
Dim hwnd As LongLong
i możemy cieszyć się wynikiem:
Wszystko by było dobrze, gdyby nie pakiet Office w wersjach 2007 i niższych. Próba kompilacji poprawionego kodu w środowisku VB6 kończy się niepowodzeniem.
Kompilator wyświetla okno komunikatu informujące, że napotkał „Niezdefiniowany typ użytkownika” i podświetla linię kodu zawierającą deklarację uchwytu okna:
Dim hwnd As LongPtr.
Podobny błąd wystąpi, gdybyśmy zadeklarowali uchwyt okna hwnd jako typ LongLong.
I nie ma się czemu dziwić, ponieważ wersja VBA 6.0 Office 2007 i wersji niższych nie obsługuje typów LongPtr
i LongLong.
Aby kod działał prawidłowo w VBA 7.0 i wersjach niższych VBA musimy więc poprawić deklarację uchwytu okna hwnd, tak by był
prawidłowego typu w obu wersjach VBA.
W tym celu powinniśmy skorzystać ze stałej kompilacji warunkowej Win64 i typu LongLong
Sub DisplayExcelWindowSize() #If Win64 Then Dim hwnd As LongLong #Else Dim hwnd As Long #End If
lub ze stałej kompilacji warunkowej VBA7 i typu LongPtr
Sub DisplayExcelWindowSize()
#If VBA7 Then
Dim hwnd As LongPtr
#Else
Dim hwnd As Long
#End If
Dim uRect As RECT
' Get the handle identifier of the main Excel window.
hwnd = FindWindow("XLMAIN", Application.Caption)
' Get the window's dimensions into the RECT UDT.
GetWindowRect hwnd, uRect
' Display the result.
MsgBox "The Excel window has these dimensions:" & _
vbCrLf & " Left: " & uRect.Left & _
vbCrLf & " Right: " & uRect.Right & _
vbCrLf & " Top: " & uRect.Top & _
vbCrLf & " Bottom: " & uRect.Bottom & _
vbCrLf & " Width: " & (uRect.Right - uRect.Left) & _
vbCrLf & " Height: " & (uRect.Bottom - uRect.Top)
End Sub




Brak komentarzy:
Prześlij komentarz