ExcelHome技术论坛

 找回密码
 免费注册

QQ登录

只需一步,快速开始

快捷登录

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

[解决多音字]汉字转拼音的完美解决方案[12.11.29更新]

  [复制链接]

TA的精华主题

TA的得分主题

发表于 2019-5-15 13:45 | 显示全部楼层
[广告] VBA代码宝 - VBA编程加强工具 · VBA代码随查随用  · 内置多项VBA编程加强工具       ★ 免费下载 ★      ★使用手册
本帖已被收录到知识树中,索引项:文本转换
WIn8 64位运行不了

TA的精华主题

TA的得分主题

发表于 2019-5-16 08:53 | 显示全部楼层
谢谢分享,好用!

TA的精华主题

TA的得分主题

发表于 2019-6-10 20:15 | 显示全部楼层
感谢大神的贡献,谢谢,使用中非常方便,也有一个问题恳请大侠抽时间更正一下, o的声调标注不准确

TA的精华主题

TA的得分主题

发表于 2019-8-9 22:20 | 显示全部楼层
本帖最后由 Nonenever 于 2019-8-11 08:36 编辑

希望能支持 64 Excel
自己改了一下,运行不了,不知道这个问题咋解决,类模块的内容没有看懂,网上搜索着改了一下,但一运行就死了
QQ图片20190811082711.png
  1. Option Explicit
  2. Private Type GUID '自定义的类型
  3.     Data1 As Long
  4.     Data2 As Integer
  5.     Data3 As Integer
  6.     Data4(0 To 7) As Byte
  7. End Type

  8. Private Type VB_MORRSLT '自定义的类型
  9.     dwSize As Long          '4
  10.     pwchOutput As Long      '4
  11.     cchOutput As Integer    '2+(2)
  12.     Block1 As Long          '4
  13.     pchInputPos As Long     '4
  14.     pchOutputIdxWDD As Long '4
  15.     pchReadIdxWDD As Long   '4
  16.     paMonoRubyPos As Long   '4
  17.     pWDD As Long            '4
  18.     cWDD As Integer         '2
  19.     pPrivate As Long        '4
  20.     BLKBuff As Long         '4
  21. End Type

  22. #If VBA7 Then
  23. Private Declare PtrSafe Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
  24.         (Destination As Any, Source As Any, ByVal Length As Long)

  25. Private Declare PtrSafe Function CLSIDFromString Lib "ole32.dll" _
  26.         (ByVal lpszProgID As LongLong, pCLSID As GUID) As LongLong
  27. 'CLSIDFromString: 将字符串方式表达的GUID转换为CLSID结构

  28. Private Declare PtrSafe Function CoCreateInstance Lib "ole32" ( _
  29.         rclsid As GUID, ByVal pUnkOuter As Long, _
  30.         ByVal dwClsContext As Long, riid As GUID, _
  31.         ByRef ppv As Long) As Long
  32. 'CoCreateInstance,函数名。用指定的类标识符创建一个Com对象,用指定的类标识符创建一个未初始化的对象
  33. Private Declare PtrSafe Function DispCallFunc Lib "oleaut32" _
  34.         (ByVal pvInstance As Long, ByVal oVft As Long, _
  35.         ByVal cc As Long, ByVal vtReturn As Integer, _
  36.         ByVal cActuals As Long, prgvt As Integer, _
  37.         prgpvarg As Long, pvargResult As Long) As Long

  38. Private Declare PtrSafe Sub CoTaskMemFree Lib "ole32" (pv As Long)
  39. 'CoTaskMemFree是一种函数,此函数用于释放被分配的内存块。
  40. #Else
  41. Private Declare Sub MoveMemory Lib "kernel32" Alias "RtlMoveMemory" _
  42.         (Destination As Any, Source As Any, ByVal Length As Long)

  43. Private Declare Function CLSIDFromString Lib "ole32.dll" _
  44.         (ByVal lpszProgID As Long, pCLSID As GUID) As Long

  45. Private Declare Function CoCreateInstance Lib "ole32" ( _
  46.         rclsid As GUID, ByVal pUnkOuter As Long, _
  47.         ByVal dwClsContext As Long, riid As GUID, _
  48.         ByRef ppv As Long) As Long

  49. Private Declare Function DispCallFunc Lib "oleaut32" _
  50.         (ByVal pvInstance As Long, ByVal oVft As Long, _
  51.         ByVal cc As Long, ByVal vtReturn As Integer, _
  52.         ByVal cActuals As Long, prgvt As Integer, _
  53.         prgpvarg As Long, pvargResult As Long) As Long

  54. Private Declare Sub CoTaskMemFree Lib "ole32" (pv As Long)

  55. #End If


  56. Dim MSIME_GUID As GUID          'MSIME's GUID
  57. Dim IFELanguage_GUID As GUID    'IFELanguage's GUID
  58. Dim IFELanguage As Long       'Pointer to IFELanguage interface  IFELanguage接口指针
  59. Dim PinYinArray() As String
  60. Dim HzLen As Integer
  61. Dim pvSeperator As String
  62. Dim pvUseSeperator As Boolean
  63. Dim pvInitialOnly As Boolean
  64. Dim pvOnlyOneChar As Boolean
  65. Dim pvNonChnUseSep As Boolean

  66. Public Function GetPinYin(HzStr As String) As String
  67.     Dim i As Integer
  68.     Dim Py As String
  69.     Dim IsPy As Boolean
  70.     GetPinYin = ""
  71.     If IFELanguage = 0 Then
  72.         GetPinYin = "未发现运行环境,请安装微软拼音2.0以上版本!"
  73.         Exit Function
  74.     End If
  75.     If HzStr = "" Then Exit Function
  76.     HzLen = Len(HzStr)
  77.     Call IFELanguage_GetMorphResult(HzStr)
  78.     For i = 1 To HzLen
  79.         Py = PinYinArray(i)
  80.         IsPy = Py <> ""
  81.         If Not IsPy Then Py = Mid(HzStr, i, 1)
  82.         GetPinYin = GetPinYin & Py & IIf(IsPy, pvSeperator, "")
  83.     Next i
  84.     If IsPy And pvSeperator <> "" Then GetPinYin = Left(GetPinYin, Len(GetPinYin) - 1)
  85. End Function

  86. Private Function IFELanguage_GetMorphResult(HzStr As String) As String
  87.     Dim ret As Long
  88.     Dim pArgs(0 To 5) As Long
  89.     Dim vt(0 To 5) As Integer
  90.     Dim Args(0 To 5) As Long
  91.     Dim ResultPtr As Long
  92.     Dim TinyM As VB_MORRSLT
  93.     Dim Py() As Byte
  94.     Dim i As Integer
  95.     Dim j As Integer
  96.     Dim PinyinIndexArray() As Integer
  97.     IFELanguage_GetMorphResult = ""
  98.     If IFELanguage = 0 Then Exit Function
  99.     Args(0) = &H30000
  100.     Args(1) = &H40000100
  101.     Args(2) = Len(HzStr)
  102.     Args(3) = StrPtr(HzStr)
  103.     Args(4) = 0
  104.     Args(5) = VarPtr(ResultPtr)
  105.     For i = 0 To 5
  106.         vt(i) = vbLong
  107.         pArgs(i) = VarPtr(Args(i)) - 8
  108.     Next
  109.     Call DispCallFunc(IFELanguage, 20, 4, vbLong, 6, vt(0), pArgs(0), ret)
  110.     Call MoveMemory(TinyM, ByVal ResultPtr, Len(TinyM))
  111.     ReDim PinyinIndexArray(0 To HzLen - 1)
  112.     ReDim PinYinArray(1 To HzLen)
  113.     If TinyM.cchOutput > 0 Then
  114.         ReDim Py(0 To TinyM.cchOutput * 2 - 1)
  115.         Call MoveMemory(Py(0), ByVal TinyM.pwchOutput, TinyM.cchOutput * 2)
  116.         IFELanguage_GetMorphResult = Py
  117.         Call MoveMemory(PinyinIndexArray(0), ByVal TinyM.paMonoRubyPos + 2, HzLen * 2)
  118.         j = 0
  119.         For i = 0 To HzLen - 1
  120.             PinYinArray(i + 1) = VBA.Mid(IFELanguage_GetMorphResult, j + 1, PinyinIndexArray(i) - j)
  121.             j = PinyinIndexArray(i)
  122.         Next i
  123.     End If
  124.     Call CoTaskMemFree(ByVal ResultPtr)
  125. End Function
  126. Private Sub IFELanguage_Open()
  127.     Dim ret As Long
  128.      Debug.Print " IFELanguage_Open   0:" & IFELanguage 'Excel 已停止工作 的位置
  129.     Call DispCallFunc(IFELanguage, 4, 4, vbLong, 0, 0, 0, ret)
  130.      Debug.Print " IFELanguage_Open   1 :" & IFELanguage
  131.     Call DispCallFunc(IFELanguage, 12, 4, vbLong, 0, 0, 0, ret)
  132.      Debug.Print " IFELanguage_Open    2:" & IFELanguage
  133. End Sub
  134. Private Sub IFELanguage_Close()
  135.     Dim ret As Long
  136.     If IFELanguage = 0 Then Exit Sub
  137.     Call DispCallFunc(IFELanguage, 8, 4, vbLong, 0, 0, 0, ret)
  138.     Call DispCallFunc(IFELanguage, 16, 4, vbLong, 0, 0, 0, ret)
  139. End Sub
  140. Private Function GenerateGUID()
  141.     Dim Rlt As LongLong
  142. '       Debug.Print "Rlt :" & Rlt
  143.     Rlt = CLSIDFromString(StrPtr("MSIME.China"), MSIME_GUID)
  144. '    StrPtr:返回真正的UNICODE字符串缓冲区的地址
  145.     'IFELanguage GUID = "{019F7152-E6DB-11d0-83C3-00C04FDDB82E}"
  146.     With IFELanguage_GUID
  147.         .Data1 = &H19F7152
  148.         .Data2 = &HE6DB
  149.         .Data3 = &H11D0
  150.         .Data4(0) = &H83
  151.         .Data4(1) = &HC3
  152.         .Data4(2) = &H0
  153.         .Data4(3) = &HC0
  154.         .Data4(4) = &H4F
  155.         .Data4(5) = &HDD
  156.         .Data4(6) = &HB8
  157.         .Data4(7) = &H2E
  158.     End With
  159.     GenerateGUID = Rlt = 0
  160. End Function
  161. Private Sub Class_Initialize() '类初始化
  162.     IFELanguage = 0
  163.     pvSeperator = " "
  164.     GenerateGUID
  165.     If CoCreateInstance(MSIME_GUID, 0, 1, IFELanguage_GUID, IFELanguage) = 0 Then Call IFELanguage_Open
  166. End Sub
  167. Private Sub Class_Terminate() '类终止
  168.     If IFELanguage <> 0 Then Call IFELanguage_Close
  169. End Sub



复制代码


汉字转拼音带声调-更改为支持 64位office-有问题运行不了.rar

221.23 KB, 下载次数: 73

有问题运行不了

TA的精华主题

TA的得分主题

发表于 2019-10-3 09:32 | 显示全部楼层
smhf_6 发表于 2019-3-2 08:26
对多音字有一定的识别功能,但仍有一定的差错率,当然这不是楼主造成的,比如工商银行,大家都知道读hang,  ...

说的不错,可不可以将常见多音字整理出来,另外编写代码,整合到本程序之中?
到能实现,将是一个不错的实用程序。

TA的精华主题

TA的得分主题

发表于 2019-10-3 09:46 | 显示全部楼层
在ppt上用,弹出如下问题窗口,请问大侠,这是为什么?
弹出问题,为什么?.png

TA的精华主题

TA的得分主题

发表于 2020-1-23 11:04 | 显示全部楼层
Nonenever 发表于 2019-8-9 22:20
希望能支持 64 Excel
自己改了一下,运行不了,不知道这个问题咋解决,类模块的内容没有看懂,网上搜索着 ...

将代码中“LongLong”改成“Long”试试

TA的精华主题

TA的得分主题

发表于 2020-1-26 11:49 | 显示全部楼层
您好,我下载了您的“汉字转拼音的完美解决方案[12.11.29更新]”字符串中出现非中文就不显示了,这是为什么?
HztoPy_20121129.rar 001.jpg

TA的精华主题

TA的得分主题

发表于 2020-1-26 11:51 | 显示全部楼层
ttui 发表于 2007-3-30 10:50
最初版本,请不要使用了。&nbsp;服了服了,上传附件如此难

您好,我下载了您的“汉字转拼音的完美解决方案[12.11.29更新]”字符串中出现非中文就不显示了,这是为什么?
HztoPy_20121129.rar

image.png

TA的精华主题

TA的得分主题

发表于 2020-2-15 15:35 | 显示全部楼层
shenjianrong163 发表于 2020-1-26 11:49
您好,我下载了您的“汉字转拼音的完美解决方案[12.11.29更新]”字符串中出现非中文就不显示了,这是为什么 ...

我在Win8.1上使用,也出现了这种状况,只要输入的字符串还有非中文就不行。
经观察发现这种字符串的转换结果,要么第一个字符必然是Chr(0),要么长度为0。
根据这个规律,我们可以逐字检查字符串,把能转换的部分截取出来,不能转换的保留,最后拼接即可。

提供一个做法作为参考,我是直接针对TinyM结构体判断的:
首先仿造GetMorphResult做一个判断函数。
  1. Private Function IFEL_Test(ch As String) As Boolean
  2.     Dim varg As Variant
  3.     Dim probe As Byte
  4.    
  5.     Args.cwchInput = 1
  6.     Args.pwchInput = strptr(ch)
  7.    
  8.     Call DispCallFunc(lpIFEL, 20, 4, vbLong, 6, vt(0), pArgs(0), varg)
  9.     Call CopyMemory(TinyM, ByVal pResult, Len(TinyM))

  10.     '正常情况下,对于非拼音,返回长度应该为0
  11.     If TinyM.cchOutput = 0 Then
  12.         IFEL_Test = True
  13.     Else
  14.         Call CopyMemory(probe, ByVal TinyM.pwchOutput, 1)
  15.         '如果第一个字符是\0,肯定不正常
  16.         IFEL_Test = probe
  17.     End If
  18.    
  19.     Call CoTaskMemFree(ByVal pResult)
  20. End Function
复制代码

然后我给GetMorphResult添加了一个偏移量参数,因为只是对源字符串的中间一部分转化。
  1. Private Function IFEL_GetMorphResult(HzStr As String, Offset As Long) As String
  2. ......
  3.     If TinyM.cchOutput > 0 Then
  4.     ......
  5.         For i = 0 To HzLen - 1
  6.             PinYinArray(i + Offset) = VBA.Mid(IFEL_GetMorphResult, j + 1, PinyinIndexArray(i) - j)
  7.             j = PinyinIndexArray(i)
  8.         Next i
  9.     End If
  10.     ......
  11. End Function
复制代码

最后组合起来用
  1. Private Sub SegmentalMorph(HzStr As String)
  2.     Dim i As Long, j As Long
  3.     Dim ch As String * 1

  4.     For i = 1 To Len(HzStr)
  5.         ch = Strings.Mid$(HzStr, i, 1)
  6.         
  7.         '遇到非中文时,总是会使j=0
  8.         '所以如果j>0,那么之前一定有中文字符
  9.         If IFEL_Test(ch) Then
  10.             If j = 0 Then j = i     '遇到中文字符,如果j=0,表示这是一连串中文的开始
  11.         ElseIf j Then
  12.             Call IFEL_GetMorphResult(Strings.Mid$(HzStr, j, i - j), j)
  13.             j = 0
  14.         End If
  15.     Next i

  16.     '如果最后一个字符为中文,便不会触发转化,需要手动补充
  17.     If j Then Call IFEL_GetMorphResult(Right$(HzStr, i - j), j)
  18.    
  19. End Sub
复制代码
您需要登录后才可以回帖 登录 | 免费注册

本版积分规则

关闭

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

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

GMT+8, 2024-4-25 20:38 , Processed in 0.042110 second(s), 7 queries , Gzip On, MemCache On.

Powered by Discuz! X3.4

© 1999-2023 Wooffice Inc.

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

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

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