如何将Unicode字符串拆分为可读字符?

3
我有一个VBA公式函数,可以将字符串拆分并在每个字符之间添加空格。它只适用于Ascii字符串。但是我想对泰米尔语做同样的事情。由于它是Unicode,结果无法读取。它甚至拆分了辅助字符、上点、前缀、后缀辅助字符,这些字符在泰米尔语/印地语/卡纳达语/马拉雅拉姆语/所有印度语言中不应该被分开。那么,如何编写函数将泰米尔语单词拆分为可读字符。
Function AddSpace(Str As String) As String
    Dim i As Long
    For i = 1 To Len(Str)
        AddSpace = AddSpace & Mid(Str, i, 1) & " "
    Next i
    AddSpace = Trim(AddSpace)
End Function

添加空格并不是这个问题的重点。从任何语言的 Unicode 字符串中将其拆分为数组才是要求。
例如,单词 "பார்த்து" 应被分隔为 "பா ர் த் து",而不是作为 "ப ா ர ் த ் த ு"。正如您所看到的,前两个字母 "பா"(ப + ா)是结合在一起的。如果我试图手动在它们之间放置一个空格,在任何文字处理器中都无法这样做。如果您想进行测试,请将其放入记事本中,并在每个字符之间添加空格。它不允许您将其分开为("ப ா")。因此,“பார்த்து”应该被分隔为“பா ர் த் து”。这是泰米尔语等语言中的正确分隔方式。这就是我在 VBA 中努力实现的。

enter image description here

泰米尔语的字符编码表在这里。 泰米尔语/印地语/许多印度语言有(1)辅音,(2)独立元音,(3)依赖元音标记,(4)两部分依赖元音标记。在这4种类型中,前两种是单独的字母,没有问题。但是后两种是依赖的,它们不应该与其联合字符分开。例如,字母பா (ப + ் ),它包含一个独立的 (ப) 和一个依赖的 (ா) 字母。
如果这些信息还不足够,请评论我需要发布更多什么内容。
(注:通过@Codo的MS链接,在C#.Net中可以实现此功能)

我没有测试的方法,但可以研究一下StrConvTHIS。那个问题的答案中有使用StrConv将字符串拆分为数组的方法。然后你可以循环这个数组。 - Scott Craner
请编辑您的问题以分享一个MCVE。您如何调用AddSpace函数;特别是,它的参数来自哪里?据我所知,VBA在内部使用UCS-2? - JosefZ
@ScottCraner 我已经浏览了这些链接,但是它们是将单词分解成字节,而不是从泰米尔语或类似语言的字符串中分解为可读字符。 - Mg Bhadurudeen
2
泰米尔语有将“字符”组合成“图形符号”的复杂规则,而Unicode选择的表示方法也没有帮助。为了实现您的目标,您需要编写代码,了解Unicode代码点如何组合成字形簇。这在.NET中是可用的(https://learn.microsoft.com/en-us/dotnet/api/system.globalization.stringinfo.gettextelementenumerator?view=net-5.0),但必须从头开始在VBA中实现。 - Codo
@Codo 谢谢你,Codo。在 .net 中它运行得很好。所以我应该找到一种方法将其带到 VBA 中。再次感谢。 - Mg Bhadurudeen
显示剩余2条评论
4个回答

0
您可以将字符串分配给字节数组,因此以下内容可能有效。
Dim myBytes as Byte
myBytes = "Tamilstring"

每个字符生成两个字节。然后,您可以使用space$创建一个合适的字符串来创建第二个字节数组,其大小是第一个数组的两倍,然后使用for循环(步长为4)将每次从第一个数组复制两个字节到第二个数组中。最后,将字节数组重新分配给字符串。


我已经在我的问题中添加了更多信息。泰米尔语Unicode可能使用2个字节。但是可读的字母并不总是一个单独的2字节。它可能是一个组合的字母,我已经添加了这个信息。请检查。 - Mg Bhadurudeen
myBytes = StrConv(TextFromCellHavingTamilWord, vbFromUnicode, 1097) '1097是泰米尔语的区域设置ID,输出结果是一个奇怪的符号 myBytes(x) = "�" - Mg Bhadurudeen

0

尝试使用以下算法,它将把所有标点符号字符与字母字符连接起来。

redim letters(0) 
For i=1 To Len(Str) 
If ascW(Mid(Str,i,1)) >3005 And ascW(Mid(Str,i,1)) <3022 Then 
letters(UBound(letters)-1) = letters(UBound(letters)-1)+Mid(Str,i,1) 
Else REDIM PRESERVE
letters(UBound(letters) + 1) 
letters(UBound(letters)-1) = Mid(Str,i,1)
End If 
Next
 
MsgBox(join(letters, ", "))'return பா, ர், த், து,

0
你遇到的问题是你正在寻找Unicode所谓的扩展字形簇。
对于一个兼容Unicode的正则表达式引擎,只需使用/\X/
不确定如何在VBA中实现这一点。

0

参考问题中@ScottCraner在评论中提到的链接泰米尔字符编码

检查A2单元格中的结果,黄色高亮显示的是用于DepVow字符串的依赖元音符号。

Screenshot of the macro result

Sub Split_Unicode_String()
'https://dev59.com/1sHqa4cB1Zd3GeqP6cHt
Dim my_string As String
    'input string
Dim buff() As String
    'array of input string characters
Dim DepVow As String
    'Create string of Dependent vowel signs
Dim newStr As String
    'result string with spaces as desired
Dim i As Long

my_string = Range("A1").Value

ReDim buff(Len(my_string) - 1) 'array of my_string characters
For i = 1 To Len(my_string)
    buff(i - 1) = Mid$(my_string, i, 1)
    Cells(1, i + 2) = buff(i - 1)
    Cells(2, i + 2) = AscW(buff(i - 1)) 'used this for creating DepVow below
Next i

'Create string of Dependent vowel signs preceded and succeeded by comma
DepVow = "," & Join(Array(ChrW$(3006), ChrW$(3021), ChrW$(3009)), ",")
newStr = ""

For i = LBound(buff) To UBound(buff)
    If InStr(1, DepVow, ChrW$(AscW(buff(i + 1))), vbTextCompare) > 0 Then
        newStr = newStr & ChrW$(AscW(buff(i))) & ChrW$(AscW(buff(i + 1))) & " "
        i = i + 1
    Else
        newStr = newStr & ChrW$(AscW(buff(i))) & " "
    End If
Next i

'result string in range A2
Cells(2, 1) = Left(newStr, Len(newStr) - 1)

End Sub

第一个循环是为了显示my_string字符的结果数组,因此可以通过在DepVow中检查Mid$(my_string, i+1, 1)来进一步改进以适应一个循环。 - Naresh

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接