ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

搜索
EH技术汇-专业的职场技能充电站 妙哉!函数段子手趣味讲函数 Excel服务器-会Excel,做管理系统 Excel Home精品图文教程库
HR薪酬管理数字化实战 Excel 2021函数公式学习大典 Excel数据透视表实战秘技 打造核心竞争力的职场宝典
300集Office 2010微视频教程 数据工作者的案头书 免费直播课集锦 ExcelHome出品 - VBA代码宝免费下载
用ChatGPT与VBA一键搞定Excel WPS表格从入门到精通 Excel VBA经典代码实践指南
楼主: hyefeifei

[原创] 简单讲讲Copymemory这个函数

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2016-6-11 09:57 | 显示全部楼层
本帖已被收录到知识树中,索引项:Windows API应用
应该是程序自动做了ANSI的转换,例如tmp = StrConv(s1, vbFromUnicode)
这里的temp就变成5字节的了。

另外,以前一直不是很理解判断字符串是否为空常用len$(str)=0 而不用 str="",看了老师前面的讲解,豁然开朗。

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-6-11 20:43 | 显示全部楼层
本帖最后由 hyefeifei 于 2016-6-12 09:20 编辑


  这个贴子开的真是有些悔啊,没多少人看不说,制做这些图着实辛苦,不过即然开了,尽量坚持到底吧。

  当vba发现你要传递一个字符串参数给一个外部函数(copymemory)时,它会叫暂停,然后:

  a. 首先它把字符串由Unicode码转为ansi码

  b. 其次,它把转成ansi码的字符串变量传给函数

  c. 函数执行完后,它把得到的结果再由ansi码转回Unicode

  具体见下图:

   1.png

  关于unicode与ansi,你须知道下面一条就可以了:

  在unicode中,中文和英文字符都占2个字节,在ansi中,中文占2个字节,英文占1个字节。

  我们再看下面的例子:
  
  1.   Sub testn1()
  2.     Dim s1 As String
  3.     Dim s2 As String
  4.     s1 = "abcde混沌"
  5.     s2 = String$(7, 0)
  6.     CopyMemory ByVal s2, ByVal s1,7
  7.     Debug.Print s2
  8.   End Sub
复制代码


  虽然"abcde混沌"的长度为7,但得到的结果s2是:“abcde混”,刚才说了,转成ansi码时,英文字符占一个字节,中文字符占2个字节,这里一共有5个英文字符,2个中文字符,所以ansi的长度应该是9,把程序改为:

  1.   Sub testn1()
  2.     Dim s1 As String
  3.     Dim s2 As String
  4.     s1 = "abcde混沌"
  5.     s2 = String$(9, 0)
  6.     CopyMemory ByVal s2, ByVal s1,9
  7.     Debug.Print s2
  8.   End Sub
复制代码

  你会发现结果正确了。

  那么,难道字符串的长度每回我都要数一下吗?我们如何取得这个长度呢?你可以用:

  LenB(VBA.StrConv(s1, vbFromUnicode))

  来取字符串长度,程序修改如下:

  1.   Sub testn2()
  2.     Dim s1 As String
  3.     Dim s2 As String
  4.     Dim p As Long
  5.     s1 = "abcde混沌"
  6.     p = LenB(VBA.StrConv(s1, vbFromUnicode))
  7.     s2 = String$(p, 0)
  8.     CopyMemory ByVal s2, ByVal s1, p
  9.     Debug.Print s2
  10.   End Sub
复制代码

  看了以上的讲解,你也许觉得有些繁琐了,又要转换,又要计算长度,有没有绕过UA转换的方法呢?当然是有,我们看下图

   2.png

  Copymemory byval s2,byval s1,9 这种方式,是通过线路1,线路2,分别到郑家和王家的,我们也可以通过线路3到郑家,通过线路4到王家,代码为:

  Copymemory byval strptr(s2),byval strptr(s1),14

  当s1,s2在括号中时,vba就不会发现我们是在传字符串给函数,也就不会做转换了,此时,我们直接到郑家取14个长度的内容,放到王家,所以第三个参数为14,程序如下:

  1.   Sub testb1()
  2.     Dim s1 As String
  3.     Dim s2 As String
  4.     s1 = "abcde混沌"
  5.     s2 = String$(Len(s1), 0)               ‘这句要用len,实际会在内存分配14个字节空间
  6.     CopyMemory ByVal StrPtr(s2), ByVal StrPtr(s1), LenB(s1)      ‘这句要用lenb,要复制14个字节
  7.     Debug.Print s2
  8.   End Sub
复制代码

  我们看示意图,既然线路1,3可以到郑家,线路2,4可以到王家,那么我们可不可以这样组合:

  CopyMemory ByVal StrPtr(s2), ByVal s1,a

  不要这样做,因为这里参数2没转码,参数1转码,所以会得出错误的结果。

  待续……

评分

4

查看全部评分

TA的精华主题

TA的得分主题

发表于 2016-6-12 09:56 | 显示全部楼层
讲的很透彻,楼主继续加油!
CopyMemory ByVal s2, ByVal s1,5
CopyMemory s2,  s1,4
是不是使用ByVal 时传的是字符串的值,不使用ByVal时传的是字符串的地址,所以CopyMemory s2,  s1,4能把整个字符串传给s2

TA的精华主题

TA的得分主题

 楼主| 发表于 2016-6-12 10:17 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
mao471023 发表于 2016-6-12 09:56
讲的很透彻,楼主继续加油!
CopyMemory ByVal s2, ByVal s1,5
CopyMemory s2,  s1,4

你看我的图,byval s1 为1500,这等于告诉了copymemory 这辆小车"abcde"的地址,去的是郑家。
s1为1000,这等于告诉了“1500”的地址,去的是赵家。
我前面说过,copymemory的参数要传址,除非值本身是地址,才可传值。byval s1(1500)是abcde的地址,所以可以传给函数。有点罗嗦了,希望随着后面所讲能越来越清楚。

评分

1

查看全部评分

TA的精华主题

TA的得分主题

发表于 2016-9-5 20:50 | 显示全部楼层
这种原理性的帖子很好,虽然还看不大懂,谢谢楼主

TA的精华主题

TA的得分主题

发表于 2016-12-25 22:12 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2017-2-19 11:57 | 显示全部楼层
楼主不讲了啊?今天有时间拜读,感觉很厉害,可惜没有继续了。
楼主不要失望,这部分内容是底层原理,论坛上绝大部分都是冲着实际应用去的,所以看的人少,不代表没有价值啊!正所谓真理往往只掌握在少数人手里。

TA的精华主题

TA的得分主题

发表于 2017-6-18 18:47 | 显示全部楼层

TA的精华主题

TA的得分主题

发表于 2017-11-13 14:03 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
谢谢分享,虽然暂时没看懂

TA的精华主题

TA的得分主题

发表于 2017-11-13 15:38 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
非常精彩!希望楼主能够坚持下去,如果能够结合应用案例就更加精彩了!
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

最新热点上一条 /1 下一条

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

GMT+8, 2024-4-20 03:05 , Processed in 0.039630 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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