Word VBA程序读取Emoji字符(4个字节)为“ 12”

San*_*ssi 17 vba ms-word emoji

我创建了一个文档,其中仅包含一个通过标准+ 快捷方式插入的“竖起” 表情符号(Unicode代码点U + 1F44D):Windows;

Windows +;  表情符号的快捷方式

但是我不能用VBA得到它的实际代码点

我得到了这些值(调试):

text = 12
length = 2
arrBytes = { 49, 0, 50, 0 }
Run Code Online (Sandbox Code Playgroud)

使用以下子过程:

Sub test()
    Dim text As String
    Dim length As Integer
    Dim arrBytes() As Byte
    text = ActiveDocument.Range.Characters(1).text
    length = Len(ActiveDocument.Range.Characters(1).text)
    arrBytes = ActiveDocument.Range.Characters(1).text
End Sub
Run Code Online (Sandbox Code Playgroud)

但是,如果我通过菜单Insert>> Symbol字体“ Segoe UI Emoji”>> U+1F44D(竖起)插入了相同的表情符号,则相同的Sub过程将获得我期望的值(在调试中; ??不是“真实”字符,它们是替代的)代码点,它们分别没有任何意义):

text = ??
length = 2
arrBytes = { 61, 216, 77, 220 }
Run Code Online (Sandbox Code Playgroud)

(有关信息,此代码将两个字符解码为&#x1F44D

如果使用Windows+ 插入表情符号,如何确定实际字符;(要求用户选择上述解决方法不是我的问题的一部分)

附录5月26日:@Florent B.的解决方案可在我的所有3台计算机上使用(ActiveDocument.Content.InsertXML ActiveDocument.Content.XML)。重新加载XML可能会对VBA程序产生影响,例如,它对图像“ Shape ID”进行了重新编号,但这是另一回事了。

5月22日增补:对于带Windows+ 的符号;,我只能在XML文档Range对象的属性中找到正确的值(4个字节{61、216、77、220}),但是这要求我解析整个XML并确定哪些XML字符与Range对象的哪个位置相对应,不幸的是,我觉得它需要很多知识或假设。这是XML的一部分,在这里我可以看到4个字节(<w:t>??</w:t>其中??对应于4个字节):

  <?xml version="1.0" standalone="yes"?>
  <?mso-application progid="Word.Document"?>
  <w:wordDocument ...>
    ... (around 23.000 characters)
    <w:body>
      <wx:sect>
        <w:p wsp:rsidR="002703DB" wsp:rsidRDefault="003926FB">
          <w:r>
            <w:rPr>
              <w:rFonts w:ascii="Segoe UI Emoji" w:h-ansi="Segoe UI Emoji"/>
              <wx:font wx:val="Segoe UI Emoji"/>
            </w:rPr>
            <w:t>??</w:t>
          </w:r>
        </w:p>
        <w:sectPr wsp:rsidR="002703DB" wsp:rsidSect="002849CD"><w:pgSz w:w="11906"
                w:h="16838"/><w:pgMar w:top="1417" w:right="1417" w:bottom="1417"
                w:left="1417" w:header="708" w:footer="708" w:gutter="0"/><w:cols
                w:space="708"/><w:docGrid w:line-pitch="360"/></w:sectPr>
      </wx:sect>
    </w:body>
  </w:wordDocument>
Run Code Online (Sandbox Code Playgroud)

当我插入表情符号作为符号时,XML 几乎相同,还有另外两个“ rFonts”:

    <w:body>
      <wx:sect>
        <w:p wsp:rsidR="00CD420D" wsp:rsidRDefault="00CD420D">
          <w:r>
            <w:rPr>
              <w:rFonts w:ascii="Segoe UI Emoji" w:fareast="Segoe UI Emoji"
                    w:h-ansi="Segoe UI Emoji" w:cs="Segoe UI Emoji"/>
              <wx:font wx:val="Segoe UI Emoji"/>
            </w:rPr>
            <w:t>??</w:t>
          </w:r>
        </w:p>
        <w:sectPr wsp:rsidR="00CD420D" wsp:rsidSect="002849CD"><w:pgSz w:w="11906"
                w:h="16838"/><w:pgMar w:top="1417" w:right="1417" w:bottom="1417"
                w:left="1417" w:header="708" w:footer="708" w:gutter="0"/><w:cols
                w:space="708"/><w:docGrid w:line-pitch="360"/></w:sectPr>
      </wx:sect>
    </w:body>
  </w:wordDocument>
Run Code Online (Sandbox Code Playgroud)

PS:我可以重现该问题的计算机/软件:

  • 计算机1(联想X230):
    • MS Word Office 365 1904(16.0.11601.20174)32位,Windows 10专业版10.0.17763 x64
    • 同样在升级到Office 365 1907 16.0.11901.20176,MSO(16.0.11901.20070)32位,Windows 10 Professional 1809 17763.652 x64之后
  • 电脑2:
    • MS Word Office 365 1904(16.0.11601.20184)64位,Windows 10 Professional 1809 17763.503 x64
  • 计算机3(戴尔):
    • MS Word Office 365 ProPlus 1808(16.0.10730.20334)64位,Windows 10企业版10.0.17763 x64

San*_*ssi 1

这是我的最终信念和发现。

根据 AAA 对 Excel、Powerpoint 和 Word 执行的测试,这可能是 MS Word VBA 中的一个错误。有些人没有这个错误(参见评论)。

VBA 对象为表情符号提供了无效值,但 XML 属性是正确的。XML 太复杂而难以解析,因此 Florent B. 在注释中找到了最简单的解决方法,其中包括“从自身重新创建文档”:

ActiveDocument.Content.InsertXML ActiveDocument.Content.XML
Run Code Online (Sandbox Code Playgroud)

不幸的是,就我个人而言,它可能会产生一些附带影响,例如形状 ID 被重新编号。

因此,我扩展了上面的代码,仅更正原始文档中的表情符号字符,其余部分保持不变,方法是:

  • 将 XML 复制到文档,
  • 然后解析新文档中文本长度大于 1 的每个字符(即 Unicode 基本多语言平面之外的字符,也包含表情符号和许多其他字符),
  • 还解析原始文档(假设字符的顺序应与新文档中的相同,并且它们的文本长度相同),
  • 将这些字符从新文档复制回原始文档,
  • 关闭新文档。

好吧,宏运行时间更长,但我找不到更好的解决方案。

这是我的简化代码(您可能会对 Range 对象的无用集合感到惊讶,其中每个 Range 都是一个 Character 对象,事实上我没有提供该函数的原始代码,该函数Split_Into_Ranges更大但速度更快,但它有效并很好地演示了子中的解决方案correct_emojis):

ActiveDocument.Content.InsertXML ActiveDocument.Content.XML
Run Code Online (Sandbox Code Playgroud)