【问题标题】:How can I convert UTF-8 to UTF-16 in Excel VBA?如何在 Excel VBA 中将 UTF-8 转换为 UTF-16?
【发布时间】:2021-02-11 07:01:05
【问题描述】:

据我所知,Excel 使用 UTF-16 来表示字符串文字。我从控制台(Mac)/文件(Windows)读取,在这两种情况下,字符编码都是混乱的。我必须找到一个适用于两个平台的解决方案,所以 ADO 流不是一个选项。我做了一些调试,发现实际字节数是:

字节 |显示为 |应该是 |正确的字节 258,129 | Ă | △ | 193 258,356 | ĂŤ | Í | 205 313,176 | Ű | Ű | 219 313,144 | Ĺ | Ő | 213 258,347 | Ăś | ü | 220 258,8211 | Ă– | Ø | 214 258,353 | Ăš | Ú | 218 258,8220 | Ă“ | Ó | 211 258,8240 | É |埃| 201

(来自古老的匈牙利语测试短语ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP,其中包含我们所有的特殊字符)。 我正在寻找一种算法,它可以在 Mac 和 Windows 上产生正确的字符串。 谢谢!

【问题讨论】:

  • Mojibake:文件为 UTF-8,以cp1250(中欧)解释。 Python 中的证明:'ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP'.encode('utf-8').decode('cp1250','replace') 产生'Ă�RVĂŤZTŰRĹ� TĂśKĂ–RFĂšRĂ“GÉP'。反向方式是不可能的,恕我直言。使用正确的编码打开文件。
  • 在 Windows 上,我可以使用运行良好的 ADODB.Stream。在 Mac 上,我使用 libc.dylib 中的 popen/fread,它返回这样的字符串。知道如何从控制台读取 UTF-8 吗?

标签: excel vba utf-8 utf-16


【解决方案1】:

为了解决这个问题,我想出了以下函数,它可以成功转换 128 到 255 之间的字符

Private Function utf8ToUTF16(ByVal strText As String) As String
    Dim i&, l1%, l2%, l3%
    For i = 1 To Len(strText)
        l1 = Asc(Mid(strText, i, 1))
        If i <> Len(strText) Then l2 = Asc(Mid(strText, i + 1, 1))
        Select Case l1
        Case 194
            utf8ToUTF16 = utf8ToUTF16 & WorksheetFunction.Unichar(l2): i = i + 1
        Case 195
            utf8ToUTF16 = utf8ToUTF16 & WorksheetFunction.Unichar(l2 + &H40): i = i + 1
        Case 197
            utf8ToUTF16 = utf8ToUTF16 & WorksheetFunction.Unichar(l2 + &HC0): i = i + 1
        Case 203
            utf8ToUTF16 = utf8ToUTF16 & WorksheetFunction.Unichar(l2 + &H240): i = i + 1
        Case 226
            If l2 = 128 Then
                l3 = Asc(Mid(strText, i + 2, 1))
                utf8ToUTF16 = utf8ToUTF16 & WorksheetFunction.Unichar(l3 + &H1F80)
                i = i + 2
            ElseIf l2 = 130 Then
                l3 = Asc(Mid(strText, i + 2, 1))
                utf8ToUTF16 = utf8ToUTF16 & WorksheetFunction.Unichar(l3 + &H2000)
                i = i + 2
            End If
        Case Else
            utf8ToUTF16 = utf8ToUTF16 & Chr(l1)
        End Select
    Next i
End Function

现在将“ĂRVĂŤZTŰRĹ TĂśKĂ–RFĂšRĂ“GÉP”传递给此函数(从标准 UTF-8 编码文件中读取)将返回“ÁRVÍZTŰRŐ TÜKÖRFÚRÓGÉP”。

  • 注意:这肯定不是最有效的代码。每当我调用它时,我总是在尽可能短的字符串上使用它。目前我用它来解码 cURL 的结果,并传递整个 HTML 冻结它。

编辑

现在我有一些时间来清理它。

Private Function utf8ToUTF16(ByVal strText As String) As String
    Dim i&, l1&, l2&, l3&, l4&, l&
    For i = 1 To Len(strText)
        l1 = Asc(Mid(strText, i, 1))
        If i + 1 <= Len(strText) Then l2 = Asc(Mid(strText, i + 1, 1))
        If i + 2 <= Len(strText) Then l3 = Asc(Mid(strText, i + 2, 1))
        If i + 3 <= Len(strText) Then l4 = Asc(Mid(strText, i + 3, 1))
        Select Case l1
        Case 1 To 127
            l = l1
        Case 194 To 223
            l = ((l1 And &H1F) * 2 ^ 6) Or (l2 And &H3F)
            i = i + 1
        Case 224 To 239
            l = ((l1 And &HF) * 2 ^ 12) Or ((l2 And &H3F) * 2 ^ 6) Or (l3 And &H3F)
            i = i + 2
        Case 240 To 255
            l = ((l1 And &H7) * 2 ^ 18) Or ((l2 And &H3F) * 2 ^ 12) Or ((l3 And &H3F) * 2 ^ 6) Or (l4 And &H3F)
            i = i + 4
        Case Else
            l = 63 ' question mark
        End Select
        utf8ToUTF16 = utf8ToUTF16 & IIf(l < 55296, WorksheetFunction.Unichar(l), "?")
    Next i
End Function

据我所知,55295 (D7FF) 以上的字符不会出现,所以它会输出一个问号作为占位符。

【讨论】:

    【解决方案2】:

    我发现这个简单的 VBA 代码非常适合文本文件中的西班牙重音字符。给定一个带有 UTF-8 双字符的字符串,它会返回一个带有重音字符的字符串:

    Function UTF8to16(str As String) As String
    Dim position As Long, strConvert As String, codeReplace As Integer, strOut As String
    
    strOut = str
    position = InStr(strOut, Chr(195))
    
    If position > 0 Then
        Do Until position = 0
            strConvert = Mid(strOut, position, 2)
            codeReplace = Asc(Right(strConvert, 1))
            If codeReplace < 255 Then
                strOut = Replace(strOut, strConvert, Chr(codeReplace + 64))
            Else
                strOut = Replace(strOut, strConvert, Chr(34))
            End If
            position = InStr(strOut, Chr(195))
        Loop
    End If
    
    UTF8to16 = strOut
    
    End Function
    

    【讨论】:

      猜你喜欢
      • 2015-09-21
      • 2015-09-19
      • 1970-01-01
      • 2017-09-24
      • 1970-01-01
      • 2019-05-15
      • 2013-05-20
      • 2012-06-30
      相关资源
      最近更新 更多