Поскольку в приложениях Office 2010 встроен другой VBA (VBA7), в отличие от ранних версий Excel, требуется предусмотреть в коде макросов различных варианты вызова API-функций Windows, чтобы они сохранили свою работоспособность при работе в любой версии Office.
Кроме того, в 64-битных Windows синтаксис вызова функций WinAPI тоже немного отличается от 32-битных систем.
В общем случае, код, корректно работающий в 64-битной Windows, будет выглядеть примерно так:
#If Win64 Then Declare Function MyMathFunc Lib "User32" (ByVal N As LongLong) As LongLong #Else Declare Function MyMathFunc Lib "User32" (ByVal N As Long) As Long #End If
А это код, который не будет выдавать ошибку при работе в Office 2010:
#If VBA7 Then Declare PtrSafe Sub MessageBeep Lib "User32" (ByVal N AS Long) #Else Declare Sub MessageBeep Lib "User32" (ByVal N As Long) #End If
Как же добиться работоспособности кода на любом компьютере?
А вот как: добавляйте описания функций WinAPI для всех возможных конфигураций. Например, ниже приведён универсальный код для вызова WinAPI функции URLDownloadToFile:
#If Win64 Then #If VBA7 Then ' Windows x64, Office 2010 Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _ (ByVal pCaller As LongLong, ByVal szURL As String, ByVal szFileName As String, _ ByVal dwReserved As LongLong, ByVal lpfnCB As LongLong) As LongLong #Else ' Windows x64,Office 2003-2007 Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _ (ByVal pCaller As LongLong, ByVal szURL As String, ByVal szFileName As String, _ ByVal dwReserved As LongLong, ByVal lpfnCB As LongLong) As LongLong #End If #Else #If VBA7 Then ' Windows x86, Office 2010 Declare PtrSafe Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _ (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, _ ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long #Else ' Windows x86, Office 2003-2007 Declare Function URLDownloadToFile Lib "urlmon" Alias "URLDownloadToFileA" _ (ByVal pCaller As Long, ByVal szURL As String, ByVal szFileName As String, _ ByVal dwReserved As Long, ByVal lpfnCB As Long) As Long #End If #End If
Более подробно тема описана на сайте Microsoft
Ещё один пример - универсальная декларация функции GetTickCount:
#If Win64 Then #If VBA7 Then ' Windows x64, Office 2010 Declare PtrSafe Function GetTickCount Lib "Kernel32" () As LongLong #Else ' Windows x64,Office 2003-2007 Declare Function GetTickCount Lib "Kernel32" () As LongLong #End If #Else #If VBA7 Then ' Windows x86, Office 2010 Declare PtrSafe Function GetTickCount Lib "Kernel32" () As Long #Else ' Windows x86, Office 2003-2007 Declare Function GetTickCount Lib "Kernel32" () As Long #End If #End If
(добавлено позже)
Вообще, код достаточно писать в 2 вариантах (ветку Win64 не обязательно прописывать)
Для функций GetKeyState и Sleep, код будет выглядеть так:
(чтобы работало во всех версиях Office и Windows)
#If VBA7 Then ' Office 2010 Declare PtrSafe Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer Declare PtrSafe Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long) #Else ' Office 2003-2007 Declare Function GetKeyState Lib "user32" (ByVal nVirtKey As Long) As Integer Declare Sub Sleep Lib "Kernel32" (ByVal dwMilliseconds As Long) #End If
----------------
(добавлено ещё позже)
Ну а ещё правильнее будет написать так:
(c использованием LongPtr для версий Office, начиная с 2010)
#If VBA7 Then ' Office 2010-2013 Declare PtrSafe Function Beep Lib "kernel32" (ByVal dwFreq As LongPtr, ByVal dwDuration As LongPtr) As LongPtr #Else ' Office 2003-2007 Declare Function Beep Lib "kernel32" (ByVal dwFreq As Long, ByVal dwDuration As Long) As Long #End If