指定 PtrSafe 以在导入 Windows API 时同时使用 32 位和 64 位 Excel

了解 Windows API PtrSafe 声明。使用Excel VBA编码时,您可以查看导入和使用Windows API时偶尔遇到的PtrSafe相关错误的原因和解决方法。

1. Windows API PtrSafe 错误发生示例代码

此代码导入并声明 Windows API Sleep、OutputDebugString。

Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)

(注意:上面的代码是 日志记录模式:利用 OutputDebugString 和 DebugView – 生产力技能 (prodskill.com) 这是 中介绍的代码。)

2. Windows API PtrSafe 错误信息

编辑或编译VBA代码时,出现如下错误。

VBA 컴파일 오류: Declare 문 PtrSafe 특성 표시 필요
VBA 编译错误:Declare 语句 PtrSafe 属性需要被标记

——————————————-
Microsoft Visual Basic for Applications
——————————————-

这是一个编译错误:

您需要更新此项目中的代码才能在 64 位系统上使用它。查看并更新 Declare 语句并使用 PtrSafe 属性对其进行标记。

3. 导致 Windows API PtrSafe 错误的原因

64bit是从MS-Office 2010开始支持的,这是因为之后在64bit Excel中导入Windows API时必须指定PtrSafe关键字。

参考: 此项目中的代码必须更新才能在 64 位系统上使用 – Office |微软文档

Compile error when you edit a VBA macro in the 64-bit version of an Office 2010 program
在 64 位版本的 Office 2010 程序中编辑 VBA 宏时出现编译错误

下面粘贴了上述 URL 的一些摘录。


症状

考虑以下情况:

  • 您编写使用 Declare 语句的 Microsoft Visual Basic for Applications (VBA) 宏代码。
  • 您的 VBA 宏代码使用编译常量。例如,您的宏代码使用以下编译常量之一:
    • #I如果VBA7
    • #I如果是Win64
  • 您在条件块中使用 #Else 块。在 #Else 块中,您使用设计用于在 Microsoft Visual Basic for Applications 6.0 中运行的 Declare 语句的语法。
  • 您在 64 位版本的 Microsoft Office 2010 程序中编辑代码。
  • 您尝试更改 #Else 块中的 Declare 语句。

在这种情况下,您会收到以下错误消息:

Microsoft Visual Basic for Applications

Compile error:

The code in this project must be updated for use on 64-bit
systems. Please review and update Declare statements and then
mark them with the PtrSafe attribute.

4. 如何修复 Windows API PtrSafe 错误

MS-Office 2010的VBA版本是7.0,之前的是6.x。由于从VBA 7.0开始就需要PtrSafe关键字,所以Windows API导入代码可以根据VBA版本是否高于7.0来划分声明。

参考: PtrSafe 关键字 (VBA) |微软文档

PtrSafe keyword
PtrSafe 关键字

下面粘贴了上述 URL 的一些摘录。


PtrSafe 关键字

  • 文章
  • 09/14/2021
  • 2分钟阅读
  • 5 贡献者

这 PtrSafe 在这种情况下使用关键字: Declare 语句.

宣布 声明与 PtrSafe 关键字是推荐的语法。声明包含的语句 PtrSafe 只有在所有数据类型在 宣布 需要存储64位数量的语句(参数和返回值)更新为使用 龙龙 对于 64 位积分或 长指针 用于指针和句柄。

为确保与 VBA 版本 6 及更早版本的向后兼容性,请使用以下结构:

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

在 64 位版本的 Office 中运行时, 宣布 陈述必须包括 PtrSafe 关键词。这 PtrSafe 关键字断言 宣布 语句在 64 位开发环境中运行是安全的。

添加 PtrSafe 关键字 宣布 声明仅表示 宣布 该语句明确针对 64 位。语句中需要存储 64 位(包括返回值和参数)的所有数据类型仍必须通过使用任一方法修改为容纳 64 位量 龙龙 对于 64 位积分或 长指针 用于指针和句柄。


您只需要确定定义的是“VBA7”常量还是“Win64”常量。在这种情况下,请使用编译器指令 #If 语法。

代码结构如下:

'방법1
#If VBA7 Then
    '64bit Windows API import
#Else
    '32bit Windows API import
#End If

'방법2
#If Win64 Then
    '64bit Windows API import
#Else
    '32bit Windows API import
#End If

'방법1, 방법2는 동일한 효과가 있으므로 한 방법을 선택하면 됨

5.解决Windows API PtrSafe错误的示例代码

5.1.在 32 位和 64 位 Excel 中混合使用时

#If VBA7 Then 'For 64 Bit Systems
    Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
    Private Declare PtrSafe Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
#Else 'For 32 Bit Systems
    Public Declare Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As Long)
    Private Declare Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)
#End If

5.2.如果仅在 64 位 Excel 中使用

如果保证它只会在 64 位 Excel 中使用,请只使用一个指定 PtrSafe 关键字的语句。

Public Declare PtrSafe Sub Sleep Lib "kernel32" (ByVal dwMilliseconds As LongPtr)
Private Declare PtrSafe Sub OutputDebugString Lib "kernel32" Alias "OutputDebugStringA" (ByVal lpOutputString As String)

发表回复

您的电子邮箱地址不会被公开。 必填项已用*标注

zh_CN简体中文