ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 效率神器,一键搞定繁琐工作
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
让更多数据处理,一键完成 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
查看: 2892|回复: 6

[原创] 一文讲透VBA 32位和64位的API声明

[复制链接]

TA的精华主题

TA的得分主题

发表于 2023-3-17 16:57 | 显示全部楼层 |阅读模式
本帖最后由 ivccav 于 2023-3-17 16:59 编辑




64位API声明,虽然没有技术含量,但还是有很多童鞋不太了解,因此我花了点时间撸点文字,希望能对需要的人有所帮助。

从Office 2010开始,分32位和64位两个版本可供安装,同时VBA6升级到VBA7。Office2010之前的版本只有32位,没有64位。

在32位平台上的API函数中指针和句柄都是32位,由于VBA6和早期版本中没有指针或句柄的特定数据类型,
可使用Long数据类型(4字节)代表指针和句柄,相安无事。
但到了64位环境,指针和句柄升级到64位(8字节),64位数据无法保存在32位数据类型中,
当64位API函数使用或者返回指针和句柄时,会被截断,造成的后果是内存溢出、代码异常,甚至应用程序崩溃。

为了解决此问题,并使VBA代码能够在32位和64位环境中都能正常工作,
VBA7中新增了2种数据类型LongPtr和LongLong ,和一个声明关键字PtrSafe:

LongPtr:指针数据类型。LongPtr会根据Office版本进行不同解析,32位版本的Office中解析为Long,64位版本的Office中解析为LongLong。
LongPtr只能用于VBA7中(Office2010开始VBA版本才升级到VBA7),用来代表指针和句柄。

LongLong:带符号的64位整数。该数据类型只能在64位版本的Office中使用。在需要使用非常巨大的数据时可使用 LongLong类型。

PtrSafe:指针安全关键字。PtrSafe关键字只能用在Declare声明语句中。
说是指针安全,但并不会真的安全,API函数中所有64位的参数和接收返回值,都必须重新定义为64位。

以上3个新功能无法在VBA6及其之前版本中使用。

想要代码在32位和64位环境下通用,可以使用条件编译。
条件编译的语法和if语句一样,只在if、else、elseif和end if关键字前面加“#”,下面举例说明:

先看一段代码:
#If VBA7 Then
         Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As Long
#Else
         Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
#EndIf

关键字前面带“#”,表示条件编译,VBA7是编译常数。
这段代码的意思是,如果VBA版本是VBA7,编译Declare PtrSafe Function...语句块,否则编译Declare Function语句块。
特别强调的是,VBA7常数不代表Office版本是32位或64位,仅仅指示VBA的版本是第7版。
在VBA7中,LongPtr数据类型可自动解析为32位和64位数据类型,这取决于安装的Office版本。
例子中hwnd是句柄,定义为LongPtr,VBA7会根据Office版本自动解析为32位或者64位数据类型。

因为LongLong只能用在64位Office版本中,如果需要使用该数据类型,
使用#If VBA7 And Win64 Then(当VBA7和Win64都为True时,才能确定Office是64位版本),如:

#if VBA7 then '  运行在VBA7中,可能是32位或64位
     Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As Long
     #if Win64 then '  运行在64位Office
         Dim i As LongLong
     #else '  运行在32位Office
             Dim i As Long
     #end if
#else ' 运行在VBA6及其之前版本,只有32位
    Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
#end if

条件编译可用于代码的任何位置,甚至是函数或过程中:

#If VBA7 Then
    Declare PtrSafe Function OpenClipboard Lib "user32" (ByVal hwnd As LongPtr) As Long
    Declare PtrSafe Function GetClipboardData Lib "user32" Alias "GetClipboardDataA" (ByVal wFormat As Long) As LongPtr
#Else
    Declare Function OpenClipboard Lib "user32" (ByVal hwnd As Long) As Long
    Declare Function GetClipboardData Lib "user32" Alias "GetClipboardDataA" (ByVal wFormat As Long) As Long
#End If

Const CF_BITMAP = 2&

Sub test()
    #If VBA7 Then
        Dim hBmp As LongPtr
    #Else
        Dim hBmp As Long
    #End If
   
    If OpenClipboard(0) Then
        hBmp = GetClipboardData(CF_BITMAP)
    End If
End Sub

注意上例中,GetClipboardData函数返回一个剪贴板上的位图句柄,需要根据不同Office版本,定义接收参数hBmp,hBmp存放句柄。
无论是API或函数的返回值,还是API或者自定义函数的参数,只要是64位数据类型,如句柄或指针,都需要重新定义,否则程序运行会异常。
所以需要了解API函数的参数或者返回值是什么,才能定义恰当的数据类型进行传递或接收。这可以查询互联网了解函数参数,也可以用API浏览。


我之前上传了一个API Viewer,方便大家写API声明,需要的可下载:

https://club.excelhome.net/thread-1424969-31-1.html

301,302楼

评分

8

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-3-17 19:57 来自手机 | 显示全部楼层
如果不使用LongLong数据格式,只需要
#If VBA7 then
#else
#end if
句式就能保证32/64位通用了

TA的精华主题

TA的得分主题

发表于 2023-3-21 14:01 | 显示全部楼层
看了你的解析,你是一个vba方面的高手。试问一下用vb6编译的dll,32位excel调用无问题,64位excel调用就提示有问题,请问有捷径解决吗。麻烦给个提示

TA的精华主题

TA的得分主题

发表于 2023-3-21 14:12 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-3-21 14:55 | 显示全部楼层
386026398 发表于 2023-3-21 14:01
看了你的解析,你是一个vba方面的高手。试问一下用vb6编译的dll,32位excel调用无问题,64位excel调用就提 ...

按微软官方说法:64位进程没法装载32位DLL, 而VB6只能编译32位的DLL,故不能使用。

我不是高手,也不吃编程这碗饭的,只偶尔逛逛论坛回答练练手,免得把学到的vb皮毛忘记了

TA的精华主题

TA的得分主题

 楼主| 发表于 2023-3-21 15:05 | 显示全部楼层


还能谷歌吗?需要科学上网吧

TA的精华主题

TA的得分主题

发表于 2023-3-21 15:33 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
ivccav 发表于 2023-3-21 15:05
还能谷歌吗?需要科学上网吧

用镜像,github,chatgpt,谷歌都用镜像
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

手机版|关于我们|联系我们|ExcelHome

GMT+8, 2024-11-15 20:43 , Processed in 0.030558 second(s), 9 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

沪公网安备 31011702000001号 沪ICP备11019229号-2

本论坛言论纯属发表者个人意见,任何违反国家相关法律的言论,本站将协助国家相关部门追究发言者责任!     本站特聘法律顾问:李志群律师

快速回复 返回顶部 返回列表