1. 程式人生 > >VBA在32位下沒問題,到64位異常報錯

VBA在32位下沒問題,到64位異常報錯

隱式 ati else 但是 設置 判斷代碼 報錯 重要 位或

64 位 Visual Basic for Applications 概述


Microsoft Visual Basic for Applications (VBA) 是 Microsoft Office 附帶的 Visual Basic 版本。在 Microsoft Office 2010 中,VBA 包括可使 VBA 代碼同時在 32 位和 64 位環境中正確運行的語言功能。


註意:默認情況下,Office 2010 安裝 32 位版本。在安裝過程中,您必須明確選擇安裝 64 位版本。



對於在 Office 2010 版本之前(VBA 版本 6 和更早版本)編寫的 VBA 代碼,需要修改為在 64 位 Office 版本中運行,否則在 64 位平臺上運行時會導致錯誤。這是因為,VBA 版本 6 和更早版本完全以 32 位平臺為目標,而且通常包含 Declare 語句,這些語句調用的 Windows API 使用 32 位數據類型的指針和句柄。因為 VBA 版本 6 和更早版本沒有用於指針或句柄的特定數據類型,所以,它使用 Long 數據類型(一種 32 位 4 字節的數據類型)來引用指針和句柄。64 位環境中的指針和句柄為 8 字節 64 位數。這些 64 位數不能包含在 32 位數據類型中。



註意:只有在 64 位版本的 Microsoft Office 中運行 VBA 代碼時,才需要修改 VBA 代碼。



在 64 位 Office 中運行舊 VBA 代碼的問題在於,將 64 位加載到 32 位數據類型中會截斷 64 位數。這會導致內存溢出、代碼中出現意外結果,並且可能導致應用程序故障。

為解決此問題,以使 VBA 代碼能同時在 32 位和 64 位環境中正確運行,新版 VBA 中增加了幾項語言功能。此文檔底部的表總結了這些新的 VBA 語言功能。有三個重要的新增功能,分別是:LongPtr 類型別名、LongLong 數據類型和 PtrSafe 關鍵字。




LongPtr - 現在,VBA 包括一種可變類型別名:LongPtr。LongPtr 實際解析為哪種數據類型取決於它在哪種 Office 版本中運行:在 32 位版本的 Office 中 LongPtr 解析為 Long,在 64 位版本的 Office 中 LongPtr 解析為 LongLong。LongPtr 用於指針和句柄。
LongLong - LongLong 數據類型為有符號的 64 位整數,僅在 64 位版本的 Office 中可用。LongLong 用於 64 位整數。必須使用轉換函數將 LongLong(包括 64 位平臺上的 LongPtr)顯式賦予較小的整型。不允許將 LongLong 隱式轉換為較小的整數。
PtrSafe - PtrSafe 關鍵字聲明 Declare 語句可以在 64 位版本的 Office 中安全運行。
現在,在 64 位版本的 Office 中運行時,所有 Declare 語句必須都包括 PtrSafe 關鍵字。必須理解,僅僅將 PtrSafe 關鍵字添加到 Declare 語句中只是表示 Declare 語句顯式針對 64 位,而語句中需要存儲 64 位(包括返回值和參數)的所有數據類型仍須經過修改才能保存 64 位數。



註意:帶有 PtrSafe 關鍵字的 Declare 語句為建議的語法。包括 PtrSafe 的 Declare 語句可同時在 32 位和 64 位平臺上的 VBA7 開發環境中正確工作。為確保在 VBA7 中以及更早版本中的向後兼容性,請使用下面的構造:


#If Vba7 Then
Declare PtrSafe Sub...
#Else
Declare Sub...
#EndIf


請考慮下列 Declare 語句示例。在 64 位版本的 Office 中運行未經修改的 Declare 語句會導致一個錯誤,該錯誤指出 Declare 語句未包括 PtrSafe 限定符。修改後的 VBA 示例中包含 PtrSafe 限定符,但請註意,返回值(指向活動窗口的一個指針)返回 Long 數據類型。在 64 位 Office 上,這是錯誤的,因為指針應為 64 位。PtrSafe 限定符告知編譯器 Declare 語句針對 64 位,因此該語句可以正常執行。但是返回值沒有更新為 64 位數據類型,因此被截斷,從而返回錯誤的值。



未修改的舊 VBA Declare 語句示例:


Declare Function GetActiveWindow Lib "user32" () As Long



修改後的 VBA Declare 語句示例,其中包括 PtrSafe 限定符,但仍使用 32 位返回值:

Declare PtrSafe Function GetActiveWindow Lib "user32" () As Long



再次重申,您除了必須修改 Declare 語句來包括 PtrSafe 限定符外,還必須更新語句中所有需要保存 64 位數的變量,以便這些變量使用 64 位數據類型。

修改後的 VBA Declare 語句示例,其中包括 PtrSafe 關鍵字,並且更新為使用正確的 64 位 (LongPtr) 數據類型:

Declare PtrSafe Function GetActiveWindow Lib "user32" () As LongPtr



總而言之,對於要在 64 位版本的 Office 中運行的代碼,您需要找到並修改所有現有 Declare 語句以使用 PtrSafe 限定符。同時,還需要找到並修改這些 Declare 語句內所有引用句柄或指針的數據類型以使用新的 64 位兼容的 LongPtr 類型別名,並且需要使用新的 LongLong 數據類型保存 64 位整數的類型。此外,還必須更新任何包含指針或句柄以及 64 位整數的用戶定義類型 (UDT),使之使用 64 位數據類型,同時,必須驗證所有變量賦值是否正確,以防止發生類型不匹配錯誤。

編寫可同時在 32 位和 64 位 Office 上運行的代碼
若要編寫可同時在 32 位和 64 位版本的 Office 上運行的代碼,只需對所有指針和句柄值使用新的 LongPtr 類型別名來代替 Long 或 LongLong 即可。LongPtr 類型別名將解析為正確的 Long 或 LongLong 數據類型,具體取決於運行的是哪種 Office 版本。請註意,如果您需要執行不同的邏輯(例如,您需要在大型 Microsoft Excel 項目中使用 64 位值),可以使用 Win64 條件編譯常量,如下面一節所示。

編寫可同時在 Microsoft Office 2010(32 位或 64 位)以及以前版本的 Office 上運行的代碼
若要編寫可同時在新版本和舊版本的 Office 中運行的代碼,可以使用新的 VBA7 與 Win64 條件編譯器常量的組合。Vba7 條件編譯器常量用來判斷代碼是否在 VB 編輯器版本 7(Office 2010 附帶的 VBA 版本)中運行。Win64 條件編譯常量用於判斷正在運行哪種 Office 版本(32 位還是 64 位)。

#if Vba7 then
‘ 代碼正在新 VBA7 編輯器中運行
#if Win64 then
‘ 代碼正在 64 位版本的 Microsoft Office 中運行
#else
‘ 代碼正在 32 位版本的 Microsoft Office 中運行
#end if
#else
‘ 代碼正在 VBA 版本 6 或更早版本中運行
#end if



#If Vba7 Then
Declare PtrSafe Sub...
#Else
Declare Sub...
#EndIf





VBA7 語言更新總結
下表總結了新增的 VBA 語言功能,並給出每個新增功能的解釋:



名稱 類型 描述
PtrSafe 關鍵字 聲明 Declare 語句針對 64 位系統。在 64 位上是必需的。
LongPtr 數據類型 該類型別名映射為 32 位系統上的 Long,或 64 位系統上的 LongLong。
LongLong 數據類型 8 字節的數據類型,只在 64 位系統上可用。數字類型。-9,223,372,036,854,775,808 到 9,223,372,036,854,775,807 範圍內的整數。LongLong 只是 64 位平臺上的有效聲明類型。此外,不能將 LongLong 隱式轉換為較小的類型(例如,不能將 LongLong 賦予 Long)。這樣做的目的是防止不慎將指針截斷。允許顯式強制轉換,所以在上例中,可以將 CLng 應用於 LongLong,並將結果賦予 Long。(只在 64 位平臺上有效。)
^ LongLong 類型聲明字符 顯式將文字值聲明為 LongLong。聲明大於最大 Long 值的 LongLong 文字時是必需的(否則它將隱式轉換為 double)。
CLngPtr 類型轉換函數 將簡單表達式轉換為 LongPtr。
CLngLng 類型轉換函數 將簡單表達式轉換為 LongLong 數據類型。(只在 64 位平臺上有效。)
vbLongLong VarType 常量 VarType 常量。
DefLngPtr DefType 語句 將一系列變量的默認數據類型設置為 LongPtr。
DefLngLng DefType 語句 將一系列變量的默認數據類型設置為 LongLong。

原地址:http://www.excelpx.com/thread-325983-1-1.html

VBA在32位下沒問題,到64位異常報錯