VBA基础
VBA 向64位转换需要注意的事项
2015-01-11 22:07:59

64 位 Visual Basic for Applications Overview

Office 2013   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 位平台且通常包含使用指针和句柄的 32 位数据类型调入 Windows API 的 Declare 语句。由于 VBA 版本 6 和早期版本没有指针或句柄的特定数据类型,因此它将使用作为 32 位 4 字节数据类型的 Long 数据类型来引用指针和句柄。64 位环境中的指针和句柄是 8 字节 64 位数量。这些 64 位数量无法在 32 位数据类型中保留。 注释注释 仅当 VBA 代码在 64 位版本的 Microsoft Office 中运行需要修改此代码。 有关在 64 位 Office 中运行旧 VBA 代码的问题是,尝试将 64 位加载到 32 位数据类型中会截断 64 位数量。这会导致内存溢出、代码中出现异常结果以及可能的应用程序失败。 为了解决此问题并使 VBA 代码能够在 32 位和 64 位环境中正常工作,已向 VBA 中添加几种语言功能。此文档底部的表汇总了新的 VBA 语言功能。增添的三项重要功能为 LongPtr 类型别名、LongLong 数据类型和 PtrSafe 关键字。 LongPtr – VBA 现在包括变量类型别名:LongPtr。LongPtr 解析为的实际数据类型取决于正在运行的 Office 版本:LongPtr 在 32 位版本的 Office 中解析为 Long,LongPtr 在 64 位版本的 Office 中解析为 LongLong。对指针和句柄使用 LongPtr。 LongLong – LongLong 数据类型是仅在 64 位版本的 Office 中可用的带符号的 64 位整数。对 64 位整数使用 LongLong。转换函数必须用于为更小整型显式分配 LongLong(包括 64 位平台上的 LongPtr)。不允许从 LongLong 到更小整型的隐式转换。 PtrSafe – PtrSafe 关键字断言 Declare 语句可在 64 位版本的 Office 中安全运行。 所有 Declare 语句在 64 位版本的 Office 中运行时,现在都必须包括 PtrSafe 关键字。将 PtrSafe 关键字添加到 Declare 语句仅意味着,Declare 语句将显式面向 64 位,并且该语句中所有需要存储 64 位的数据类型(包括返回值和参数)仍必须修改为保留 64 位数量,了解这一点很重要。 注释注释 建议的语法是,将 Declare 语句与 PtrSafe 关键字一起使用。包括 PtrSafe 的 Declare 语句可在 32 位和 64 位平台上的 VBA7 开发环境中正常运行。若要确保在 VBA7 及早期版本中实现向后兼容性,请使用以下构造: VBA #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 语句示例: VBA Declare Function GetActiveWindow Lib “user32″ () As Long VBA Declare 语句示例已修改为包括 PtrSafe 限定符但仍使用 32 位返回值: VBA Declare PtrSafe Function GetActiveWindow Lib “user32″ () As Long 若要重做,您必须将 Declare 语句修改为包括 PtrSafe 限定符,并且您必须更新语句中需要保留 64 未数量的所有变量以使这些变量使用 64 位数据类型。 VBA Declare 语句示例已修改为包括 PtrSafe 关键字,并已更新为使用适当的 64 位 (LongPtr) 数据类型: VBA Declare PtrSafe Function GetActiveWindow Lib “user32″ () As LongPtr 总之,为了让代码在 64 位版本的 Office 中运行,您需要找到所有现有 Declare 语句并将其修改为使用 PtrSafe 限定符。您还需要找到并修改这些 Declare 语句中所有引用句柄或指针的数据类型以使用新的 64 位兼容的 LongPtr 类型别名,以及需要保留 64 位整型和新的 LongLong 数据类型的类型。此外,您必须更新包含指针或句柄的所有用户定义类型 (UDT) 和 64 位整型以使用 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 条件编译器常量用于确定代码是否在版本 7 的 VB 编辑器(Office 2010 附带的 VBA 版本)中运行。Win64 条件编译常量用于确定正在运行哪个版本的 Office(32 位或 64 位)。 VBA #if Vba7 then ‘ Code is running in the new VBA7 editor #if Win64 then ‘ Code is running in 64-bit version of Microsoft Office #else ‘ Code is running in 32-bit version of Microsoft Office #end if #else ‘ Code is running in VBA version 6 or earlier #end if

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

VBA7 语言更新摘要 下表汇总了新 VBA 语言增添功能,并提供了每项增添功能的说明: 名称 类型 说明 PtrSafe 关键字 断言 Declare 语句是面向 64 位系统的。在 64 位系统上是必需的。 LongPtr 数据类型 映射到 32 位系统上的 Long 或 64 位系统上的 LongLong 的类型别名。 LongLong 数据类型 仅在 64 位系统上可用的 8 字节数据类型。数值类型。范围在 -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。