ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[求助] 怪哉,怪种的Replace函数——求开塞!

[复制链接]

TA的精华主题

TA的得分主题

发表于 2020-2-14 14:05 | 显示全部楼层 |阅读模式
本帖最后由 weiyingde 于 2020-2-14 21:18 编辑

怪哉,怪种的Replace函数——求开塞!
这两天,与我交往几年了的Replace竟然这样折腾我!不知是我的蠢笨,还是它的狡猾,Replace对我来说,竟是这样的熟悉和陌生!!由此推之,在整个Office家族中,该有多少个“Replace”的存在!!!2010年,开启了我与Excel、Word和PowerPoint的摸爬滚打;而今,十年过去了……而我,我对它还是如此的无知,想想真令人汗颜和后怕!!尽管如此,问题如鲠在喉,只好厚着脸皮,仍旧发这个低级和幼稚的求助,愿过路人,搭手施援,排忧解惑,老朽先谢了。
问题是这样的。
“EnToCh”是YZC51发的一个帖子中的中英文互译的函数,帖子见http://club.excelhome.net/thread-1508743-1-1.html五楼,代码如下:
Public Function EnToCh(rng As String)
    Dim xml
    Dim URL$, EngSentence$
    Set xml = CreateObject("MSXML2.XMLHTTP")
    Debug.Print Asc(rng)
    aasc = Asc(rng)
    If aasc > 64 And aasc < 123 Then
        URL = "https://translate.google.cn/m?hl=en&sl=enN&tl=zh-CN&ie=UTF-8&prev=_m&q=" & rng
    Else
        URL = "https://translate.google.cn/m?hl=en&sl=zh-CN&tl=enN&ie=UTF-8&prev=_m&q=" & GetURL(rng) '在这个地方引用
    End If
    With xml
      .Open "GET", URL, False
      .send
       If InStr(.responseText, "<div dir=""ltr"" class=""t0"">") > 0 Then
            EnToCh = Split(Split(.responseText, "<div dir=""ltr"" class=""t0"">")(1), "</div><")(0)
        End If
    End With
End Function

Function GetURL$(txt$) '
    For i = 1 To Len(txt)
        txt1 = Mid(txt, i, 1)
        If Abs(Asc(txt1)) < 128 Then
            GetURL = GetURL & txt1
        Else
            GetURL1 = Application.Hex2Bin(Left(Hex(AscW(txt1)), 2), 8)
            GetURL1 = GetURL1 & Application.Hex2Bin(Right(Hex(AscW(txt1)), 2), 8)
            GetURL1 = Application.Replace(Application.Replace(GetURL1, 11, , 10), 5, , 10)
            GetURL2 = "%E" & Application.Bin2Hex(Left(GetURL1, 4))
            GetURL2 = GetURL2 & "%" & Application.Bin2Hex(Mid$(GetURL1, 5, 8))
            GetURL2 = GetURL2 & "%" & Application.Bin2Hex(Mid$(GetURL1, 13, 8))
            GetURL = GetURL & GetURL2
        End If
    Next
End Function
主函数“EnToCh”包含一个名为“GetURL”,为了将“EnToCh”推荐给Excel VBA的两兄弟——Word VBA 和PowerPoint VBA,需要对其子函数“GetURL”进行改造,否则将会导致它在新环境中调皮捣蛋,于是不得不对其中使用的“Replace”动动手术,手术很小很快,自认为很成功,看不出有什么问题:
Function GetURLA$(txt$) '……………
    For i = 1 To Len(txt)
        txt1 = Mid(txt, i, 1)
        If Abs(Asc(txt1)) < 128 Then
            GetURL = GetURL & txt1
        Else
          With Application.WorksheetFunction
          'Application在VBA代码中等同于Application.WorksheetFunction吧?将源代码对应的地方改一下,
          '应该没问题吧,可是,你试一试,在“EnToCh”函数引用“GetURL”改为“GetURLA”,试一试,保证运行不了。
          '郁闷呀…………………………
          '此处不能运行,下面的函数“GetURLX”是对应在Word中的函数,仍然不能运行。
               GetURL1 = .Hex2Bin(Left(Hex(AscW(txt1)), 2), 8)
               GetURL1 = GetURL1 & .Hex2Bin(Right(Hex(AscW(txt1)), 2), 8)
               GetURL1 = .Replace(.Replace(GetURL1, 11, , 10), 5, , 10)
               GetURL2 = "%E" & .Bin2Hex(Left(GetURL1, 4))
               GetURL2 = GetURL2 & "%" & .Bin2Hex(Mid$(GetURL1, 5, 8))
               GetURL2 = GetURL2 & "%" & .Bin2Hex(Mid$(GetURL1, 13, 8))
               GetURLA = GetURLA & GetURL2
          End With
        End If
    Next
End Function
出乎意料,弹出“参数不可选”对话框,“GetURLA”函数居然罢工了!!


看看元凶:
Application.Replace(Application.Replace(GetURL1, 11, , 10), 5, , 10)
“Replace”在其中捣鬼!!

“Replace”,熟悉的Replace,我还不认识你吗?!
我知道,在Excel中,有两处Replace函数的存在:
1、一个是VBA工程函数:Repalce。它在VBA代码中有两种写法:
⑴直接使用:sr=replace("中华人民共和国公民", "人民共和国公民", "老百姓")。
⑵加个VBA:sr = VBA.replace("中华人民共和国公民", "人民共和国公民", "老百姓")。
2、另一个是WorksheetFunction中的replace工作表函数。在Excel VBA中使用该函数也有两种写法:
⑴sr = Application.WorksheetFunction.replaceApplication.Replace("中华人民国共和国公民", 3, 7, "老百姓")
⑵sr = Application.Replace("中华人民国共和国公民", 3, 7, "老百姓")
结论:
⑴在Excel中确有两个Replace函数:一个是VBA工程函数,一个是Excel工作表函数,且两个函数在VBA代码中的写法不一样。
⑵两个函数的参数个数类型不一样:工程函数Replace有三个参数,都是字符串类型;工作表函数Replace四个函数:一、四时字符串,二、三两个参数是integer类型的,是数字。
⑶根据你在Excel代码中的写法,推断这个Replace应该是工作表函数。
试验:
试验一:在Excel VBA环境下。
用两个例子进行测试:sr1=“Yes”    sr2=“很好”
主函数“EnToCh”分别调用子函数“GetRUL”“GetRULA”的结果如下:
甲、测试参数:sr1
调用“GetRUL”  msgbox EnToCh(sr1)——“是”,运行正常;
调用“GetRULA”  msgbox EnToCh(sr1)——“是”,运行正常;
乙、测试参数:sr2
调用“GetRUL”  msgbox EnToCh(sr1)——“是”,运行正常;
调用“GetRULA”  msgbox EnToCh(sr1)——不能运行,弹出“参数不可选”。
试验二:在Word VBA环境下,效果如同Excel环境一样。
结论:参数为英文,实现英文转中文,两个子程序都能运行。说明“GetRULA”中的Replace是工作表函数。
试验三:保持子函数中文如sr1=“很好”参数不变,分别以“GetRUL”“GetRULA”再试验。
甲、在Excel VBA中:
With Application.WorksheetFunction
……
GetURL1 = VBA.Replace(VBA.Replace(GetURL1, 11, 10), 5, 10)
……
end with
……结果虽是乱码,可能是查找和替换的地方不对,但Replace能出结果,运行正常,按写法,毋庸置疑Replace是VBA工程函数。
乙、在Word VBA中。
With Excel. Application.WorksheetFunction
……
⑴GetURL1 = .Replace(.Replace(GetURL1, 11, , 10), 5, , 10)
⑵GetURL1 = VBA.Replace(VBA.Replace(GetURL1, 11, , 10), 5, , 10)
⑶GetURL1 = VBA.Replace(VBA.Replace(GetURL1, 11, 10), 5, 10)
……
end with
实验结果和推断:
⑴弹出“要求对象”对话框,说明“Repalce”的父对象不是“Excel. Application.WorksheetFunction”,简言之,“Replace”不是Excel工作表函数。
⑵弹出“参数不可选”对话框,说明“Repalce”。在Office家族的“三剑客”Excel、Word和PPT VBA中有工程函数VBA,是处理字符串的好手,在正则、Word替换和查找中经常用到。它有三个参数,如 ReplaceApplication.Replace("中华人民国共和国公民", “公民”, "老百姓")=“中华人民国共和国老百姓”,此例可以看出,三个参数都是字符串;而Excel工作表函数Replace,如 Application.WorksheetFunction.replaceApplication.Replace("中华人民国共和国公民", 3, 7, "老百姓")=“中华人民国共和国老百姓”,有四个参数,一、四两个是字符串式参数,二、三两个是数值型参数。参看原表达式:Replace(GetURL1, 11, , 10), 5, , 10),基本都是数值,特别是二、三(第三个没有?省略了?)两个,尽管第三没有了,所以肯定地说它是Excel工作表函数的可能性很大。
⑶尽管是VBA工程函数的可能性不是很大,试一试,擦掉一个空参数(也就是抹掉一个蛮有参数的英文逗号)结果弹出“运行时错误,要求对象”……说明也不是参数的问题……
反复试验, Replace,仿佛是一个顽劣的,始终不肯应允,不肯放行……
呜呼哀哉!!多重验证,花了我两天的时间,始终没看懂你这个Replace的真容!
你这个挠心烧脑的Replace,你到底何路神仙,那方妖孽?
期盼E友、老师、大侠借我一双慧眼,将你辨识!!
在线^^^^^^^^^
盼你回音^^^^^^
参数不可选.png

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-2-14 14:07 | 显示全部楼层
附件如下,请下载看看

附件【请分别在Word和Excel工程中试验】.rar

110.72 KB, 下载次数: 3

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-2-14 16:31 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
再次请教,借大侠老师的一点时间,排忧解难。

TA的精华主题

TA的得分主题

发表于 2020-2-14 19:07 | 显示全部楼层
1、工作表函数Replace()与VBA函数Replace()有差别。
Application.Replace(GetURL1, 11, , 10)
原代码用Replace()的目的是给GetURL1在11位置上插入“10”,改为VBA.Replace()不可以。

2、参数不可选的原因是VBA函数中的参数不能不能忽略,不仅仅是Replace(),Offset()等函数也一样,该函数中,写上0就可以:
Application.WorksheetFunction.Replace(GetURL1, 11, 0, 10)

3、曾经有个帖子专门讨论过VBA引用工作表函数的各种写法的异同:
Application.
WorksheetFunction
Application.WorksheetFunction.
本例也证实:
Application.Replace() 与 Application.WorksheetFunction.Replace() 确实有不同的地方。


评分

1

查看全部评分

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-2-14 19:11 | 显示全部楼层
山菊花 发表于 2020-2-14 19:07
1、工作表函数Replace()与VBA函数Replace()有差别。
Application.Replace(GetURL1, 11, , 10)
原代码用Re ...

谢谢山版主,经老师点拨,茅塞顿开,太感谢了!

TA的精华主题

TA的得分主题

发表于 2020-2-14 21:08 | 显示全部楼层

TA的精华主题

TA的得分主题

 楼主| 发表于 2020-2-14 21:15 | 显示全部楼层
zopey 发表于 2020-2-14 21:08
汉字 转utf8,编码为3个字节。

谢谢指教,能否详细讲解一下,我对这些内容一无所知。

TA的精华主题

TA的得分主题

发表于 2020-2-14 22:11 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
weiyingde 发表于 2020-2-14 21:15
谢谢指教,能否详细讲解一下,我对这些内容一无所知。

摘抄一部分:

1、ASCII编码是1个字节;

2、Unicode编码通常是2个字节,如果统一成Unicode编码,乱码问题从此消失了。
但是,如果你写的文本基本上全部是英文的话,用Unicode编码比ASCII编码需要多一倍的存储空间;

3、UTF-8编码把一个Unicode字符根据不同的数字大小编码成1-6个字节,是“可变长编码”。
常用的英文字母被编码成1个字节,汉字通常是3个字节,只有很生僻的字符才会被编码成4-6个字节。
如果你要传输的文本包含大量英文字符,用UTF-8编码就能节省空间。

Unicode符号范围         |    UTF-8编码方式
  (十六进制)                 |  (二进制)
0000 0000-0000 007F |  0xxxxxxx
0000 0080-0000 07FF |  110xxxxx 10xxxxxx
0000 0800-0000 FFFF |   1110xxxx 10xxxxxx 10xxxxxx
0001 0000-0010 FFFF |  11110xxx 10xxxxxx 10xxxxxx 10xxxxxx


TA的精华主题

TA的得分主题

发表于 2020-2-14 22:26 | 显示全部楼层
[广告] Excel易用宝 - 提升Excel的操作效率 · Excel / WPS表格插件       ★免费下载 ★       ★ 使用帮助
举例1:
「知」字的码位 77E5 属于第三行的范围:

7       7        E       5         
0111 0111 1110 0101  二进制的 77E5
----------------------------  
        0111     011111    100101 二进制的 77E5
1110XXXX 10XXXXXX 10XXXXXX 模版(上表第三行)
11100111 10011111 10100101 代入模版   
E      7        9      F       A      5

这就是将「知」的 77E5 按照 UTF-8 编码为E79FA5 的过程。


练习1:
"严"的unicode是  4E25(0100 1110 0010 0101)
"严"的UTF-8编码是  E4B8A5(11100100 10111000 10100101)

TA的精华主题

TA的得分主题

发表于 2020-2-15 21:44 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
zopey 发表于 2020-2-14 22:26
举例1:
「知」字的码位 77E5 属于第三行的范围:
  1. Sub pey_test()
  2. MsgBox GetURLC("知")
  3. MsgBox GetURLC("严")
  4. End Sub


  5. Function GetURLC$(txta$)
  6.     Dim a() As Byte
  7.     a = txta
  8.         
  9.     b1 = (a(0) And &H3F) + &H80
  10.     b2 = (a(1) And &HF) * 4 + (a(0) And &HC0) / 64 + &H80
  11.     b3 = (a(1) And &HF0) / 16 + &HE0

  12.     GetURLC = "%" & Hex(b3) & "%" & Hex(b2) & "%" & Hex(b1)
  13. End Function
复制代码


您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

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

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

GMT+8, 2024-4-25 18:09 , Processed in 0.036579 second(s), 11 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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