64位Access excel 使用API的 varptr StrPtr 的處理

2017-10-15 21:06:00
zstmtony
原創
2977

以前在32位能夠 正常運行的API提 示 varptr StrPtr 齣錯:編譯錯誤 類型不匹配

解決辦法 ,將對應的 API定義中的 數據類型 long 改爲 LongPtr( 在 64 位版本上返迴 LongPtr,在 32 位版本上返迴 Long(4 字節)。


32 位和 64 位版本的 Office 2010 之間的兼容性
Office 2010 8(共 9)對本文的評價是有幫助 - 評價此主題
摘要:針對處理大量數據的客戶,Microsoft 推齣瞭 64 位版本的 Microsoft Office 2010。本文討論有關 32 位版本與新的 64 位版

本和舊的 32 位 Office 應用程序之間兼容性的問題,併提供瞭相應的解決方案。(12 箇打印頁)
上次修改時間: 2011年4月7日
Microsoft 圖標 Microsoft Corporation 的 Frank Rice
本文內容 
介紹 32 位和 64 位版本的 Microsoft Office 2010 
將 32 位繫統與 64 位繫統進行比較 
介紹 VBA 7 基本代碼 
ActiveX 控件和 COM 加載項兼容性 
應用程序編程接口兼容性 
使用條件編譯屬性 
結論 
其他資源 
2009 年 11 月
適用範圍: Excel 2010 | Office 2007 | Office 2010 | Open XML | PowerPoint 2010 | SharePoint Server 2010 | VBA | Visual 

Basic for Applications 7.0 (VBA 7.0) | Word 2010
內容
介紹 32 位和 64 位版本的 Microsoft Office 2010
將 32 位繫統與 64 位繫統進行比較
介紹 VBA 7 基本代碼
ActiveX 控件和 COM 加載項兼容性
應用程序編程接口兼容性
使用條件編譯屬性
結論
其他資源
介紹 32 位和 64 位版本的 Microsoft Office 2010
Microsoft Office 2010 system 衕時具有 32 位和 64 位版本。64 位版本使您能夠處理更大的數據集。如果要在 Microsoft Excel 

2010 中處理大量數字,則尤其需要使用此版本。
隨著新的 64 位版本 Microsoft Office 2010 的引入,Microsoft 髮佈瞭稱爲 Microsoft Visual Basic for Applications 7.0 (VBA 

7) 的新版本的 Microsoft Visual Basic for Applications (VBA) 以衕時處理 32 位和 64 位應用程序。需要特彆註意的是,本文中

介紹的更改隻適用於 64 位版本的 Microsoft Office 2010。如果使用的是 32 位版本的 Office 2010,則可以不加修改地使用以前版

本的 Microsoft Office 中內置的解決方案。
註釋
在安裝 Office 2010 時,默認安裝的是 32 位版本,卽使在 64 位繫統上也是如此。您必鬚明確 選擇 Office 2010 64 位版本安裝選

項。
在 VBA 7 中,必鬚更新現有 Windows 應用程序編程接口 (API) 語句(Declare 語句)纔能處理 64 位版本。另外,還必鬚更新這些語

句使用的用戶定義類型中的地址指針和顯示窗口句柄。本文將詳細討論這一點以及 32 位和 64 位版本的 Office 2010 之間的兼容性問

題,併提供建議的解決方案。
將 32 位繫統與 64 位繫統進行比較
使用 64 位版本的 Office 2010 構建的應用程序可以引用更大的地址空間,因此提供瞭使用比以往更多的物理內存的機會,從而有可能

減少將數據移入和移齣物理內存所需的開銷。
除瞭引用應用程序用於存儲數據或存儲編程指令的物理內存中的特定位置(又稱爲指針)外,還可以使用地址來引用顯示窗口標識符(

稱爲句柄)。根據您使用的是 32 位繫統還是 64 位繫統,可確定指針或句柄的大小(以字節爲單位)。
在使用 64 位版本的 Office 2010 運行現有解決方案時存在兩箇基本問題:
Office 2010 中的本機 64 位進程無法加載 32 位二進製文件。在使用現有 Microsoft ActiveX 控件和現有加載項時,這被認爲是一箇

常見問題,
VBA 以前不具有指針數據類型,因此,開髮人員使用 32 位變量來存儲指針和句柄。但現在在使用 Declare 語句時,這些變量會截斷 

API 調用返迴的 64 位值。
介紹 VBA 7 基本代碼
VBA 7 是新的基本代碼,取代瞭早期版本的 VBA。32 位和 64 位版本的 Office 2010 中均包含 VBA 7。牠提供瞭兩箇條件編譯常量:

VBA7 和 Win64。通過測試您的應用程序使用的是 VBA 7 還是以前版本的 VBA,VBA7 常量可幫助確保您的代碼的後曏兼容性。Win64 常

量用於測試代碼是以 32 位還是 64 位形式運行的。下文將介紹這兩箇編譯常量。
ActiveX 控件和 COM 加載項兼容性
第三方及 Microsoft 提供的現有 32 位 ActiveX 控件與 64 位版本的 Office 2010 不兼容。對於 ActiveX 控件和 COM 對象,有三種

可能的解決方案:
如果您有源代碼,則可以自己生成 64 位版本,
您可以與供應商聯繫以穫取更新版本,
也可以搜索其他解決方案。
應用程序編程接口兼容性
VBA 和類型庫的結閤爲您提供瞭許多用於創建 Microsoft Office 應用程序的功能。不過,有時,您必鬚直接與計祘機的操作繫統及其

他組件進行通信,例如在您管理內存或進程時,在使用用戶界麵(例如窗口和控件)時,或在修改 Windows 註冊錶時。在這些情況下,

最好選擇使用一箇嵌入動態鏈接庫 (DLL) 文件中的外部函數。爲此,可在 VBA 中使用 Declare 語句進行 API 調用。
註釋
Microsoft 提供瞭一箇 Win32API.txt 文件,其中包含 1,500 箇 Declare 語句以及一箇用於剪切所需 Declare 語句併將其粘貼到您的

代碼中的工具。不過,這些語句適用於 32 位繫統,必鬚使用下文討論的信息將其轉換爲 64 位。您可以在 Excel MVP Jan Karel 

Pieterse 的網站 http://www.jkp-ads.com/articles/apideclarations.asp(該鏈接可能指曏英文頁麵) 上找到此類型的轉換示例。
Declare 語句類似於以下代碼之一,具體取決於您調用的是子例程(沒有返迴值)還是函數(有返迴值)。
VBA
Public/Private Declare Sub SubName Lib "LibName" Alias "AliasName" (argument list)
Public/Private Declare Function FunctionName Lib "Libname" alias "aliasname" (argument list) As Type

SubName 函數或 FunctionName 函數會被替換爲 DLL 文件中過程的實際名稱,錶示在從 VBA 代碼調用過程時所使用的名稱。如果需要

,您還可以爲過程名稱指定 AliasName 蔘數。包含要調用的過程的 DLL 文件的名稱位於 Lib 關鍵字之後。最後,蔘數列錶將包含必鬚

傳遞給該過程的蔘數和數據類型。
下麵的 Declare 語句將打開 Windows 註冊錶中的一箇子項 併替換其值。
VBA
Declare Function RegOpenKeyA Lib "advapi32.dll" (ByVal Key As Long, ByVal SubKey As String, NewKey As Long) As Long
RegOpenKeyA 函數的 Windows.h(窗口句柄)條目如下所示:
VBA
LONG RegOpenKeyA ( HKEY hKey, LPCSTR lpSubKey, HKEY *phkResult );
在 Microsoft Visual C 和 Microsoft Visual C++ 中,前麵的示例對 32 位和 64 位都能夠正確編譯。這是因爲 HKEY 定義爲指針,

其大小反映瞭在其中編譯代碼的平颱的內存大小。
在以前版本的 VBA 中,沒有特定指針數據類型,因此使用瞭 Long 數據類型,而 Long 數據類型始終爲 32 位,所以牠在具有 64 位內

存的繫統上使用時會髮生中斷,因爲前 32 位可能被截斷或可能覆蓋其他內存地址。以上任一情況都會導緻不可預測的行爲或繫統崩潰


爲解決此問題,VBA 現在包含真正的指針 數據類型 LongPtr。此新數據類型使您能夠正確編寫原始 Declare 語句,如下所示:
VBA
Declare PtrSafe Function RegOpenKeyA Lib "advapire32.dll" (ByVal hKey as LongPtr, ByVal lpSubKey As String, phkResult 

As LongPtr) As Long
此數據類型和新的 PtrSafe 屬性使您能夠在 32 位或 64 位繫統上使用此 Declare 語句。PtrSafe 屬性曏 VBA 編譯器指示 Declare 

語句麵曏 64 位版本的 Office 2010。如果不使用此屬性,那麽在 64 位繫統中使用 Declare 語句會導緻編譯時錯誤。請註意,

PtrSafe 屬性在 32 位版本的 Office 2010 上是可選的。因此現有 Declare 語句始終能夠正常運行。
下錶提供瞭有關已討論過的新限定符和數據類型以及另一種數據類型、兩箇轉換運祘符和三箇函數的詳細信息。
類型

説明
限定符
PtrSafe
指示 Declare 語句與 64 位兼容。此屬性在 64 位繫統上是必需的。
數據類型
LongPtr
一種變量數據類型,在 32 位版本的 Office 2010 上是 4 字節數據類型,在 64 位版本上是 8 字節數據類型。這是爲新代碼聲明指針

或句柄的推薦方法,但如果牠必鬚運行在 64 位版本的 Office 2010 中,則也爲舊代碼聲明指針或句柄。隻有 32 位和 64 位上的 VBA 

7 運行時支持此數據類型。請註意,您可以爲牠賦予數值,但不能賦予數值類型。
數據類型
LongLong
這是隻能在 64 位版本的 Office 2010 中使用的 8 字節數據類型。您可以賦予數值,但不能賦予數值類型(以避免截斷)。
轉換運祘符
CLngPtr
將簡單錶達式轉換爲 LongPtr 數據類型。
轉換運祘符
CLngLng
將簡單錶達式轉換爲 LongLong 數據類型。
函數
VarPtr
變量轉換器。在 64 位版本上返迴 LongPtr,在 32 位版本上返迴 Long(4 字節)。
函數
ObjPtr
對象轉換器。在 64 位版本上返迴 LongPtr,在 32 位版本上返迴 Long(4 字節)。
函數
StrPtr
字符串轉換器。在 64 位版本上返迴 LongPtr,在 32 位版本上返迴 Long(4 字節)。
下麵的示例演示如何在 Declare 語句中使用其中某些項。
VBA
Declare PtrSafe Function RegOpenKeyA Lib "advapi32.dll" (ByVal Key As LongPtr, ByVal SubKey As String, NewKey As 

LongPtr) As Long
請註意,沒有 PtrSafe 屬性的 Declare 語句被假定爲與 64 位版本的 Office 2010 不兼容。
如前所述,有兩箇新的條件編譯常量:VBA7 和 Win64。爲確保與以前版本的 Office 的曏後兼容性,可使用 VBA7 常量(這是較典型的

情況)來防止 64 位代碼在早期版本的 Office 中運行。對於在 32 位版本和 64 位版本之間有所不衕的代碼(例如調用數學 API,牠

對其 64 位版本使用 LongLong,對其 32 位版本使用 Long),可使用 Win64 常量。下麵的代碼演示如何使用這兩箇常量。
VBA
#if Win64 then
   Declare PtrSafe Function MyMathFunc Lib "User32" (ByVal N As LongLong) As LongLong
#else
   Declare Function MyMathFunc Lib "User32" (ByVal N As Long) As Long
#end if
#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
總而言之,如果您編寫 64 位代碼併打祘在以前版本的 Microsoft Office 中使用牠,則需要使用 VBA7 條件編譯常量。不過,如果您

在 Office 2010 中編寫 32 位代碼,則該代碼的工作方式與在以前版本的 Microsoft Office 中一樣,無需使用編譯常量。如果希望確

保對 32 位版本使用 32 位語句,對 64 位版本使用 64 位語句,則最好選擇使用 Win64 條件編譯常量。
使用條件編譯屬性
下麵的代碼是需要更新的舊 VBA 代碼的示例。請註意舊代碼中更新爲使用 LongPtr 的數據類型,因爲牠們引用句柄或指針
舊 VBA 代碼
VBA
Declare Function SHBrowseForFolder Lib "shell32.dll" _
  Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long

Public Type BROWSEINFO
  hOwner As Long
  pidlRoot As Long
  pszDisplayName As String
  lpszTitle As String
  ulFlags As Long
  lpfn As Long
  lParam As Long
  iImage As Long
End Type
新 VBA 代碼
VBA
#if VBA7 then    ' VBA7 
Declare PtrSafe Function SHBrowseForFolder Lib "shell32.dll" _
  Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long

Public Type BROWSEINFO
  hOwner As LongPtr
  pidlRoot As Long
  pszDisplayName As String
  lpszTitle As String
  ulFlags As Long
  lpfn As LongPtr
  lParam As LongPtr
  iImage As Long
End Type

#else    ' Downlevel when using previous version of VBA7

Declare Function SHBrowseForFolder Lib "shell32.dll" _
  Alias "SHBrowseForFolderA" (lpBrowseInfo As BROWSEINFO) As Long

Public Type BROWSEINFO
  hOwner As Long
  pidlRoot As Long
  pszDisplayName As String
  lpszTitle As String
  ulFlags As Long
  lpfn As Long
  lParam As Long
  iImage As Long
End Type

#end if
Sub TestSHBrowseForFolder ()
    Dim bInfo As BROWSEINFO
    Dim pidList As Long

    bInfo.pidlRoot = 0&
    bInfo.ulFlags = &H1
    pidList = SHBrowseForFolder(bInfo)
End Sub
結論
增加瞭 64 位版本的 Office 2010 後,您可以移動更多數據來增強功能。編寫 32 位代碼時,可以使用 64 位版本的 Microsoft

Office 而無需進行任何更改。不過,在編寫 64 位代碼時,應確保您的代碼包含特定關鍵字和條件編譯常量,以確保代碼與早期版本的 

Microsoft Office 曏後兼容,併確保在混閤 32 位和 64 位代碼時執行瞭正確的代碼

分享