ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[原创] 教你怎样判断InputBox是点击了取消还是返回了空值

[复制链接]

TA的精华主题

TA的得分主题

发表于 2012-5-27 12:54 | 显示全部楼层 |阅读模式
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖最后由 wangminbai 于 2012-5-27 12:59 编辑

今天看到了http://club.excelhome.net/thread-873153-1-1.html这个帖子,你面讲到了InputBox的一个小问题:
常规情况下无法区分用户是点击了取消按钮还是用户未作任何输入直接点击了确定按钮---因为这两种情况下它都会返回一个空字符串


其实这里可以用 StrPtr 函数来判断,StrPtr在VBA帮助里查找不到,应该算一个隐藏的函数,它主要用来返回真正的UNICODE字符串缓冲区的地址,他还有另外一个作用,就是:
能直观地告诉你空字符串和null字符串的不同。对于null字符串(vbNullString),StrPtr的返回值为0,而对于空字符串,函数的返回值为非零。   

如以下代码,就能够判断出用户是点击了取消按钮还是用户未作任何输入直接点击了确定按钮
  1. Sub Test()
  2.     Dim xStr As String
  3.     xStr = InputBox("InputBox 测试", "Mars Wang")
  4.     If StrPtr(xStr) <> 0 Then
  5.         MsgBox "用户点击了""确定""按钮!!!!!"
  6.     Else
  7.         MsgBox "用户点击了""取消""按钮或者直接关闭了对话框!!!!!"
  8.     End If
  9. End Sub
复制代码
具体见附件:
Test.zip (8.75 KB, 下载次数: 234)


评分

2

查看全部评分

TA的精华主题

TA的得分主题

发表于 2012-5-27 13:28 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2012-5-27 13:54 | 显示全部楼层
VarPtr、StrPtr和ObjPtr函数的用法
(录入日期:2000.11.27 阅读次数:395) 转载http://202.103.176.84/erun/adamyl/
作者:不详

--------------------------------------------------------------------------------

VarPtr、StrPtr和ObjPtr函数的用法


--------------------------------------------------------------------------------

发展历史

在Basic语言演变成QBasic,然后到Visual Basic之前,VarPtr函数就已经存在了。开始,这个函数存在于VB运行库1.0版中。通过声明可以调用这个函数:

Declare Function VarPtr Lib "vbrun100.dll" (Var As Any) As Long

数年之后,vbrun100.dll变成了msvbvm50.dll,但该函数的入口点却还在那儿。为了获取变量的地址,只须将变量名传递给该函数就行了。例如:

Dim l As Long
Debug.Print VarPtr(l)

类似地,为了获取字符串的指针,而非保存字符串的变量的指针,只须在变量名前加上ByVal即可。如:

Debug.Print VarPtr(s),VarPtr(ByVal s)

在VB3之前,用这种方法来获取字符串缓冲的指针是非常普遍的。但在VB4却遇到了一点麻烦。

ANSI/UNIDCODE问题

随着32位世界和VB4的到来,我们迈进了一半是UNICODE,一半是ANSI的Windows世界。而在此之前,是ANSI一统天下。在VB中,所有字符串按UNICODE保存,但所有的API调用却仍使用ANSI字符串。这就要求在调用API函数之前,将字符串从UNICODE转换成ANSI,函数执行结束后,将返回的字符串从ANSI转换成UNICODE。虽然大多数时候这种转换对用户来说是透明的,但这就使利我们不能将一个字符串类型的参数以UNICODE方式从VB传递给DLL。类似地,任何包含有字符串的结构在执行API调用时,也必须经过这种双重转换。

这种差异是如何影响VarPtr函数的呢?当一个字符串传递给VarPtr函数时,函数执行后所返回的地址是保存临时ANSI字符串的临时ANSI字符串或变量的地址。换句话说,这个地址并不是你声明的变量的真正地址。因此,对于字符串变量以及包括字符串的结构来讲,这个函数一点用也没有。

VB5来解决问题

为了能VarPtr能重新发挥作用,VB5(及Office97)加入了三个针对VBA类型库的入口点。这些入口点为VarPtr函数提供了内置的声明。这三个函数的作用是:

VarPtr:返回变量地址

StrPtr:返回真正的UNICODE字符串缓冲区的地址

ObjPtr:返回任何对象变量引用的地址

下面是这三个函数的具体用法。

StrPtr

该函数主要用来产生高效的UNICODE API调用。在VB4,UNICODE形式的API函数的调用必须借助于Byte数组,例如:

Declare Sub MyUnicodeCall Lib "MyUnicodeDll.dll" (pStr as Byte)

Sub MakeCall (MyStr as String)

Dim bTmp() as Byte
bTmp=MyStr & vbNullChar
MyUnicodeCall bTmp(0)
MyStr=bTmp
MyStr=left(MyStr, Len(MyStr)-1)

End Sub

如果使用StrPtr,上面的代码精简为:

Declare Sub MyUnicodeCall Lib "MyUnicodeDll.dll" (pStr as Byte)

Sub MakeCall (MyStr as String)

MyUnicodeCall StrPtr(MyStr)

End Sub

VarPtr/StrPtr/ObjPtr的执行速度非常非常快,因此调用UNICODE函数所赞成有系统负担实际上小于调用相对应的ANSI函数。因为前者不需进行转换。

StrPtr还能用于优化ANSI API函数的调用。在调用时使用StrConv和StrPtr就能避免将一个字符串变量多资传递给函数以及为每个调用而执行转换操作所造成的系统负担。例如原来的:

Declare Sub MyAnsiCall Lib "MyAnsiDll.dll" (ByVal pStr As String)

MyAnsiCall MyStr

现在变为:

Declare Sub MyAnsiCall Lib "MyAnsiDll.dll" (ByVal pStr As Long)

MyStr=StrConv(MyStr,vbFromUnicode)
MyAnsiCall StrPtr(MyStr)
MyStr=StrConv(MyStr,vbUnicode) 注释:并不总是要求

StrPtr还是唯一能直观地告诉你空字符串和null字符串的不同的方法。对于null字符串(vbNullString),StrPtr的返回值为0,而对于空字符串,函数的返回值为非零。

VarPtr

该函数能与要求包含有UNICODE字符串的结构的API调用一起使用。如果将一个MyUDTVariable变量(一个自定义类型的变量)传递给一个由ByRef UDTParam As MyUDT定义的参数,就会发生ANSI/UNICODE之间的转换。但是,如果将VarPtr(MyUDTVariable)传递给由ByVal UDTParam As Long定义的参数,则不会发生这样的转换。

有一点需要特别注意,在VB中指针的算法非常重要。此外,你必须计算元素的大小,因为VB不会帮你完成这项工作。你还必须处理缺乏无符号长整型数据类型的问题。下面的函数实现了无符号算法

Function UnsingedAdd (ByVal Start As Long, ByVal Incr As Long) As Long

Const SignBit As Long = &H80000000
UnsignedAdd=(Start Xor SignBit) + Incr Xor SignBit

End Function

ObjPtr

该函数返回由对象变量引用的接口指针。由于大多数对象都支持多重接口,因此搞清楚地址对应的是对象的哪一个接口就非常重要了。通常个函数用来放在集合中的对象。通过创建基于对象地址的关键字,你就可以在不需要启遍历整个集合中所有元素的情况下,轻松地将对象从集合中删除。在许多情况下,对象地址是唯一可靠的能作为关键字的东西,示例如下:

ObjCol.Add MyObj1,CStr(ObjPtr(MyObj1))

.....

ObjCol.Remove CStr(ObjPtr(MyObj1))

TA的精华主题

TA的得分主题

发表于 2012-12-4 20:57 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2015-4-9 21:10 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
作者的博客不错啊!

TA的精华主题

TA的得分主题

发表于 2017-10-11 11:21 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
这个有用,已经用上了。

TA的精华主题

TA的得分主题

发表于 2019-3-1 15:42 | 显示全部楼层
解决了我一个大问题,特意登录来感谢。

TA的精华主题

TA的得分主题

发表于 2019-3-5 20:26 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
同上,困扰了很长时间,感谢!

TA的精华主题

TA的得分主题

发表于 2019-11-9 08:36 | 显示全部楼层
MARK,随时都用得上,很实用

TA的精华主题

TA的得分主题

发表于 2020-3-27 13:32 | 显示全部楼层
如果inputbox选择的输入模式type:=8,即选择单元格区域,这样一来,第一步赋值给字符串变量是否就会出问题,可以改为变体类型,但对于变体类型变量,该函数是否支持?
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

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

GMT+8, 2024-11-17 04:43 , Processed in 0.049428 second(s), 12 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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