摘要:針對處理大量數(shù)據(jù)的客戶,Microsoft 推出了 64 位版本的 Microsoft Office 2010。本文討論有關(guān) 32 位版本與新的 64 位版本和舊的 32 位 Office 應(yīng)用程序之間兼容性的問題,并提供了相應(yīng)的解決方案。(12 個打印頁) 上次修改時間: 2011年4月7日 Microsoft Corporation 的 Frank Rice 本文內(nèi)容 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 內(nèi)容 Microsoft Office 2010 system 同時具有 32 位和 64 位版本。64 位版本使您能夠處理更大的數(shù)據(jù)集。如果要在 Microsoft Excel 2010 中處理大量數(shù)字,則尤其需要使用此版本。 隨著新的 64 位版本 Microsoft Office 2010 的引入,Microsoft 發(fā)布了稱為 Microsoft Visual Basic for Applications 7.0 (VBA 7) 的新版本的 Microsoft Visual Basic for Applications (VBA) 以同時處理 32 位和 64 位應(yīng)用程序。需要特別注意的是,本文中介紹的更改只適用于 64 位版本的 Microsoft Office 2010。如果使用的是 32 位版本的 Office 2010,則可以不加修改地使用以前版本的 Microsoft Office 中內(nèi)置的解決方案。
在 VBA 7 中,必須更新現(xiàn)有 Windows 應(yīng)用程序編程接口 (API) 語句(Declare 語句)才能處理 64 位版本。另外,還必須更新這些語句使用的用戶定義類型中的地址指針和顯示窗口句柄。本文將詳細(xì)討論這一點以及 32 位和 64 位版本的 Office 2010 之間的兼容性問題,并提供建議的解決方案。 使用 64 位版本的 Office 2010 構(gòu)建的應(yīng)用程序可以引用更大的地址空間,因此提供了使用比以往更多的物理內(nèi)存的機會,從而有可能減少將數(shù)據(jù)移入和移出物理內(nèi)存所需的開銷。 除了引用應(yīng)用程序用于存儲數(shù)據(jù)或存儲編程指令的物理內(nèi)存中的特定位置(又稱為指針)外,還可以使用地址來引用顯示窗口標(biāo)識符(稱為句柄)。根據(jù)您使用的是 32 位系統(tǒng)還是 64 位系統(tǒng),可確定指針或句柄的大?。ㄒ宰止?jié)為單位)。 在使用 64 位版本的 Office 2010 運行現(xiàn)有解決方案時存在兩個基本問題:
VBA 和類型庫的結(jié)合為您提供了許多用于創(chuàng)建 Microsoft Office 應(yīng)用程序的功能。不過,有時,您必須直接與計算機的操作系統(tǒng)及其他組件進(jìn)行通信,例如在您管理內(nèi)存或進(jìn)程時,在使用用戶界面(例如窗口和控件)時,或在修改 Windows 注冊表時。在這些情況下,最好選擇使用一個嵌入動態(tài)鏈接庫 (DLL) 文件中的外部函數(shù)。為此,可在 VBA 中使用 Declare 語句進(jìn)行 API 調(diào)用。
Declare 語句類似于以下代碼之一,具體取決于您調(diào)用的是子例程(沒有返回值)還是函數(shù)(有返回值)。 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 函數(shù)或 FunctionName 函數(shù)會被替換為 DLL 文件中過程的實際名稱,表示在從 VBA 代碼調(diào)用過程時所使用的名稱。如果需要,您還可以為過程名稱指定 AliasName 參數(shù)。包含要調(diào)用的過程的 DLL 文件的名稱位于 Lib 關(guān)鍵字之后。最后,參數(shù)列表將包含必須傳遞給該過程的參數(shù)和數(shù)據(jù)類型。 下面的 Declare 語句將打開 Windows 注冊表中的一個子項 并替換其值。 Declare Function RegOpenKeyA Lib "advapi32.dll" (ByVal Key As Long, ByVal SubKey As String, NewKey As Long) As Long RegOpenKeyA 函數(shù)的 Windows.h(窗口句柄)條目如下所示: 在 Microsoft Visual C 和 Microsoft Visual C++ 中,前面的示例對 32 位和 64 位都能夠正確編譯。這是因為 HKEY 定義為指針,其大小反映了在其中編譯代碼的平臺的內(nèi)存大小。 在以前版本的 VBA 中,沒有特定指針數(shù)據(jù)類型,因此使用了 Long 數(shù)據(jù)類型,而 Long 數(shù)據(jù)類型始終為 32 位,所以它在具有 64 位內(nèi)存的系統(tǒng)上使用時會發(fā)生中斷,因為前 32 位可能被截斷或可能覆蓋其他內(nèi)存地址。以上任一情況都會導(dǎo)致不可預(yù)測的行為或系統(tǒng)崩潰。 為解決此問題,VBA 現(xiàn)在包含真正的指針 數(shù)據(jù)類型 LongPtr。此新數(shù)據(jù)類型使您能夠正確編寫原始 Declare 語句,如下所示: Declare PtrSafe Function RegOpenKeyA Lib "advapire32.dll" (ByVal hKey as LongPtr, ByVal lpSubKey As String, phkResult As LongPtr) As Long 此數(shù)據(jù)類型和新的 PtrSafe 屬性使您能夠在 32 位或 64 位系統(tǒng)上使用此 Declare 語句。PtrSafe 屬性向 VBA 編譯器指示 Declare 語句面向 64 位版本的 Office 2010。如果不使用此屬性,那么在 64 位系統(tǒng)中使用 Declare 語句會導(dǎo)致編譯時錯誤。請注意,PtrSafe 屬性在 32 位版本的 Office 2010 上是可選的。因此現(xiàn)有 Declare 語句始終能夠正常運行。 下表提供了有關(guān)已討論過的新限定符和數(shù)據(jù)類型以及另一種數(shù)據(jù)類型、兩個轉(zhuǎn)換運算符和三個函數(shù)的詳細(xì)信息。
下面的示例演示如何在 Declare 語句中使用其中某些項。 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 位版本之間有所不同的代碼(例如調(diào)用數(shù)學(xué) API,它對其 64 位版本使用 LongLong,對其 32 位版本使用 Long),可使用 Win64 常量。下面的代碼演示如何使用這兩個常量。 #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 的數(shù)據(jù)類型,因為它們引用句柄或指針 舊 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 代碼 #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 |
|