本帖最后由 baitang36 于 2022-7-15 09:24 编辑
是否是数据类型造成的,64位和32位不同。
以下是网上搜到的:
LongPtr (32 位系统上为 Long 整数,在 64 位系统上为 LongLong) 变量存储为:
在 32 位系统上,签名的 32 位 (4 字节) 数字,值范围从 -2,147,483,648 到 2,147,483,647
在 64 位系统上,签名的 64 位 (8 字节) 数字,值范围为 -9,223,372,036,854,775,808 到 9,223,372,036,854,775,807
有关在 64 位 Office 中运行旧 VBA 代码的问题是,尝试将 64 位加载到 32 位数据类型中会截断 64 位数量。 这会导致内存溢出、代码中出现异常结果以及可能的应用程序失败。 为了解决此问题并使 VBA 代码能够在 32 位和 64 位环境中正常工作,已向 VBA 中添加几种语言功能。 [color=var(--theme-hyperlink)]此文档底部的表对新的 VBA 语言功能进行了汇总。 三个重要的新增功能是 LongPtr 类型别名、LongLong 数据类型和 PtrSafe 关键字。 [color=var(--theme-hyperlink)] LongPtr。 VBA 现在包括变量类型别名 LongPtr。 LongPtr 解析为的实际数据类型取决于正在运行的 Office 版本;LongPtr 在 32 位版本的 Office 中解析为 Long,LongPtr 在 64 位版本的 Office 中解析为 LongLong。 将 LongPtr 用于指针和句柄。 [color=var(--theme-hyperlink)] LongLong。 LongLong 数据类型是仅在 64 位版本的 Office 中可用的带符号的 64 位整数。 对 64 位整数使用 LongLong。 转换函数必须用于为更小整型显式分配 LongLong(包括 64 位平台上的 LongPtr)。 不允许“LongLong”到更小的整数的隐式转换。 [color=var(--theme-hyperlink)] PtrSafe。 PtrSafe 关键字断言 Declare 语句可在 64 位版本的 Office 中安全运行。
[backcolor=var(--theme-primary-background)][color=var(--theme-primary-dark)] 重要 现在,所有 Declare 语句在 64 位版本的 Office 中运行时,都必须包括 PtrSafe 关键字。 请务必了解,只将 PtrSafe 关键字添加到 Declare 语句只是表示 Declare 语句显式面向 64 位。 语句中需要存储 64 位的所有数据类型(包括返回值和参数)仍必须进行修改,以保留 64 位数量。
[backcolor=var(--theme-info-background)][color=var(--theme-info-dark)] 备注 建议的语法是,将 Declare 语句与 PtrSafe 关键字一起使用。 包括 PtrSafe 的 Declare 语句可在 32 位和 64 位平台上的 VBA7 开发环境中正常运行。 若要确保在 VBA7 及早期版本中实现向后兼容性,请使用以下构造: [color=var(--theme-text)][backcolor=var(--theme-code-header)][size=0.8]VB复制[color=var(--theme-success-invert) !important][backcolor=var(--theme-success-base) !important][size=1.125]
#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 语句示例: [backcolor=var(--theme-code-header)][size=0.8]VB复制[color=var(--theme-success-invert) !important][backcolor=var(--theme-success-base) !important][size=1.125]
Declare Function GetActiveWindow Lib "user32" () As Long下面的 VBA Declare 语句示例已修改为包括 PtrSafe 限定符但仍使用 32 位返回值: [backcolor=var(--theme-code-header)][size=0.8]VB复制[color=var(--theme-success-invert) !important][backcolor=var(--theme-success-base) !important][size=1.125]
Declare PtrSafe Function GetActiveWindow Lib "user32" () As Long若要重做,必须将 Declare 语句修改为包括 PtrSafe 限定符,并且必须更新语句中需要保留 64 位数量的所有变量,以使这些变量使用 64 位数据类型。 下面是一个 VBA Declare 语句示例,它已修改为包括 PtrSafe 关键字,并已更新为使用适当的 64 位 (LongPtr) 数据类型: [backcolor=var(--theme-code-header)][size=0.8]VB复制[color=var(--theme-success-invert) !important][backcolor=var(--theme-success-base) !important][size=1.125]
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 版本。 请注意,如果需要执行不同的逻辑(例如,需要在大型 Excel 项目中操作 64 位值),则可以使用 Win64 条件编译常量,如以下部分所示。
|