在Word中使用VBA标记文档中的特殊字符
我完全不知道如何更好地处理这个过程 下面的宏分析文档中的每个字符,如果ASCII值大于255,它将对其应用特殊的字符样式-一些用于特定语言,如果不是这些语言的一部分,则仅使用“lang” 宏可以很好地工作,但是对于长文档,处理它需要很长时间。例如,我刚刚处理了一个147页(单行距)的文档,每页上有几行希腊语,用Word 2016 For Windows,它花了40分钟(相比之下,完全相同的文件和相同的代码在Mac上花了2分钟) 我可以对下面的代码做些什么来优化Windows 谢谢你的建议。 约翰在Word中使用VBA标记文档中的特殊字符,vba,ms-word,Vba,Ms Word,我完全不知道如何更好地处理这个过程 下面的宏分析文档中的每个字符,如果ASCII值大于255,它将对其应用特殊的字符样式-一些用于特定语言,如果不是这些语言的一部分,则仅使用“lang” 宏可以很好地工作,但是对于长文档,处理它需要很长时间。例如,我刚刚处理了一个147页(单行距)的文档,每页上有几行希腊语,用Word 2016 For Windows,它花了40分钟(相比之下,完全相同的文件和相同的代码在Mac上花了2分钟) 我可以对下面的代码做些什么来优化Windows 谢谢你的建议。 约翰
子检查特殊字符()
'此宏查找255以上的任何字符,并用适当的现有语言字符标记它们。
Dim ch As范围:设置ch=ActiveDocument.Characters(1)
做
计数器=计数器+1
中国选择
myValue=AscW(Selection.Text)
如果myValue>255,则
如果(myValue>8190且myValue<8225)或(myValue>288且myValue<381)或(myValue>701且myValue<704)或myValue=730,则
'忽略卷引号和音译标点符号
ElseIf(myValue>7935,myValue<8192)或(myValue>879,myValue<1024),然后
“希腊字符被应用了langgrk
选择.展开单位:=wdWord
Selection.Style=“langgrk”
ElseIf(myValue>1423,myValue<1535),然后
'希伯来文字符得到langheb应用
选择.展开单位:=wdWord
Selection.Style=“langheb”
如果myValue>7679且myValue<7830
'扩展音译字符得到langtrans应用//旧值//(myValue>288和myValue<381)或(myValue>701和myValue<704)
如果HCCP=True,则选择.展开单位:=wdWord
Selection.Style=“langtrans”
ElseIf(myValue>19968,myValue<40959)然后
"汉字应用朗琴"
选择.展开单位:=wdWord
Selection.Style=“langchin”
ElseIf(myValue>19968,myValue<40917)然后
"日文角色申请朗日文"
选择.展开单位:=wdWord
Selection.Style=“langjap”
其他的
如果HCCP=True,则选择.展开单位:=wdWord
Selection.Style=“lang”
如果结束
如果结束
DoNext:
端接头
由于某些原因,我的Word(2007)版本似乎不起作用,但这可能是需要研究的内容,而不是检查字符代码
加快Office VBA宏速度的一般方法是禁用屏幕更新:
Application.ScreenUpdating = False
' some slow code that causes the screen to be updated
Application.ScreenUpdating = True
这对您的情况应该有点帮助,因为您使用的是较慢的选择
,而不是范围
此外,直接检查字节值似乎比AscW快一点:
Sub test()
'Options.DefaultHighlightColorIndex = wdNoHighlight
'Range.HighlightColorIndex = wdNoHighlight ' used for testing to clear Highlight
Dim r As Range, t As Double: t = Timer
Application.ScreenUpdating = False
For Each r In Range.Characters ' For Each r In Range.Words is somehow about 2 times slower than .Characters
checkRange r
Next
Application.ScreenUpdating = True
Debug.Print Timer - t; Range.Words.Count; Range.Characters.Count; Range.End ' " 3.15625 8801 20601 20601 "
End Sub
Sub checkRange(r As Range)
Dim b() As Byte, i As Long, a As Long
b = r.Text ' converts the string to byte array (2 or 4 bytes per character)
'Debug.Print "'" & r & "'"; r.LanguageID; r.LanguageIDFarEast; r.LanguageIDOther
For i = 1 To UBound(b) Step 2 ' 2 bytes per Unicode codepoint
If b(i) > 0 Then ' if AscW > 255
a = b(i): a = a * 256 + b(i - 1) ' AscW
Select Case a
Case &H1F00 To &H1FFF: r.HighlightColorIndex = wdBlue: Exit Sub ' Greek Extended
Case &H3040 To &H30FF: r.HighlightColorIndex = wdPink: Exit Sub ' Hiragana and Katakana
Case &H4E00 To 40959: r.HighlightColorIndex = wdGreen: Exit Sub ' CJK Unified Ideographs
Case 55296 To 56319: ' ignore leading High Surrogates ?
Case 56320 To 57343: ' ignore trailing Low Surrogates ?
Case Else: r.HighlightColorIndex = wdRed: Debug.Print Hex(a), r.End - r.Start ' other
End Select
End If
Next
End Sub
代码中的一些Unicode代码点(如8190
)似乎有点不对劲,因此您可以在
查找并替换为格式化链接中的方法不是我需要的,因为它假定您已经知道要查找的字符。我试图识别文档中使用的任何特殊字符。如果它属于某些常见的范围,我会标记特定的语言,但其他任何被识别的语言都会应用通用的字符样式。谢谢。我将对此进行测试并让您知道。我原本禁用屏幕更新,但它并没有加速这一点,当人们看到空白屏幕这么长时间,他们认为它已经崩溃。所以我想让他们看到发生了什么总比什么都没有好。谢谢@Slai。您的方法在Windows上的效率要高得多-从40分钟减少到4分钟!(奇怪的是,这个版本在Mac上速度非常慢,所以我只保留了我在Mac上的旧方法。)@johnwangel 4分钟对我来说有点慢,因为在我的测试中,它在3秒内完成了10页。除了案件陈述之外,你还做了什么改变吗?事实上,没关系,因为我的测试只是改变了重点,而不是样式。这是一本35000字的书。
Sub test()
'Options.DefaultHighlightColorIndex = wdNoHighlight
'Range.HighlightColorIndex = wdNoHighlight ' used for testing to clear Highlight
Dim r As Range, t As Double: t = Timer
Application.ScreenUpdating = False
For Each r In Range.Characters ' For Each r In Range.Words is somehow about 2 times slower than .Characters
checkRange r
Next
Application.ScreenUpdating = True
Debug.Print Timer - t; Range.Words.Count; Range.Characters.Count; Range.End ' " 3.15625 8801 20601 20601 "
End Sub
Sub checkRange(r As Range)
Dim b() As Byte, i As Long, a As Long
b = r.Text ' converts the string to byte array (2 or 4 bytes per character)
'Debug.Print "'" & r & "'"; r.LanguageID; r.LanguageIDFarEast; r.LanguageIDOther
For i = 1 To UBound(b) Step 2 ' 2 bytes per Unicode codepoint
If b(i) > 0 Then ' if AscW > 255
a = b(i): a = a * 256 + b(i - 1) ' AscW
Select Case a
Case &H1F00 To &H1FFF: r.HighlightColorIndex = wdBlue: Exit Sub ' Greek Extended
Case &H3040 To &H30FF: r.HighlightColorIndex = wdPink: Exit Sub ' Hiragana and Katakana
Case &H4E00 To 40959: r.HighlightColorIndex = wdGreen: Exit Sub ' CJK Unified Ideographs
Case 55296 To 56319: ' ignore leading High Surrogates ?
Case 56320 To 57343: ' ignore trailing Low Surrogates ?
Case Else: r.HighlightColorIndex = wdRed: Debug.Print Hex(a), r.End - r.Start ' other
End Select
End If
Next
End Sub