Rem rng 要處理的範圍 ,arr 要處理的關鍵字 (預設為字串陣列)
Sub marking易學關鍵字(rng As Range, arr As Variant, Optional defaultHighlightColorIndex As word.WdColorIndex = word.wdYellow, _
Optional fontColor As word.WdColorIndex = word.wdRed, Optional allDoc As Boolean = False)
Dim xd As String, e, eArrKey, arrKey, startRng As Long, endRng As Long ', dict As Scripting.Dictionary
Dim examOK As Boolean, rngExam As Range, processCntr As Long, dictCoordinatesPhrase As New Scripting.Dictionary, key, isInPhrasesAvoid As Boolean, isFollowedAvoid As Boolean, isPrecededAvoid As Boolean
On Error GoTo eH
word.Options.defaultHighlightColorIndex = defaultHighlightColorIndex
examOK = True
If allDoc Then Set rng = rng.Document.Range
startRng = rng.start
endRng = rng.End
Set rngExam = rng.Document.Range
xd = rng.text
With rng.Find
.ClearFormatting
' .HitHighlight
' With .Replacement '現在不用 wdReplaceAll 引數的方法了
' .font.ColorIndex = fontColor 'wdRed
' .Highlight = True
' End With
For Each e In arr '遍歷每個要標識的關鍵字
' If e = "乾知大始" Then Stop 'just for test
If InStr(xd, e) > 0 Then '在有超連結等功能變數、隱藏文字時可能會miss,今測試並不會,待再測試。
rng.SetRange startRng, endRng
'If e = "豫" Then
isFollowedAvoid = Keywords.易學KeywordsToMark_ExamFollowedAvoid.Exists(e)
isPrecededAvoid = Keywords.易學KeywordsToMark_ExamPrecededAvoid.Exists(e)
isInPhrasesAvoid = Keywords.易學KeywordsToMark_ExamInPhraseAvoid.Exists(e)
If isFollowedAvoid Or isPrecededAvoid Or isInPhrasesAvoid Then
' '若有內嵌於的片語語詞(包含關鍵的片語語句)需查驗的話,就先記下要比對的位置集合
' '若後、前檢查都未過就不必了,故今再改移至內嵌之檢查,並以 dictCoordinatesPhrase.Count 來作判斷
' If isInPhrasesAvoid Then
' arrKey = Keywords.易學KeywordsToMark_ExamInPhraseAvoid(e)
' For Each eArrKey In arrKey '遍歷每個該避開的詞語,蒐集其在文件中的所在位置,以供後續比對
' 'Set rngExam = rngExam.Document.Range '弄錯了,已有allDoc參數控制是否操作整份文件
' rngExam.SetRange startRng, endRng '不需處理整份文件,就只就操作範圍內處置就可。感恩感恩 讚歎讚歎 南無阿彌陀佛 20240915
' With rngExam.Find
' Do While .Execute(eArrKey, , , , , , True, wdFindStop)
' '記下含有目前關鍵字的詞語片語語彙片段在範圍中的位置
' dictCoordinatesPhrase.Add rngExam.start, rngExam.End
' Loop
' End With
' Next eArrKey
' End If
Do While .Execute(e, , , , , , True, wdFindStop, True) '在範圍中尋遍關鍵字出現的位置
examOK = True '歸零
' rng.Select '偵錯用
If Not rng.Next Is Nothing Then
If rng.Next.Characters.Count > 0 Then
'後綴檢查
'If UBound(VBA.Filter(Keywords.易學KeywordsToMark_ExamFollowedAvoid(e), rng.Next.Characters(1).text)) < 0 Then
If isFollowedAvoid Then
arrKey = Keywords.易學KeywordsToMark_ExamFollowedAvoid(e)
For Each eArrKey In arrKey
If rng.End + VBA.Len(eArrKey) <= endRng Then '這樣的寫法,如果內含超連結等功能變數,恐怕就會失誤了!
rngExam.SetRange rng.End, rng.End + VBA.Len(eArrKey)
If VBA.StrComp(rngExam.text, eArrKey) = 0 Then '找到要避開的關鍵字
examOK = False '檢測不通過
Exit For
End If
End If
Next eArrKey
End If
If examOK Then
checkPrevious:
If Not rng.Previous Is Nothing Then
'前綴檢查
If rng.Previous.Characters.Count > 0 Then
'If UBound(VBA.Filter(Keywords.易學KeywordsToMark_ExamPrecededAvoid(e), rng.Previous.Characters(rng.Previous.Characters.Count).text)) < 0 Then
If isPrecededAvoid Then
arrKey = Keywords.易學KeywordsToMark_ExamPrecededAvoid(e)
For Each eArrKey In arrKey
If rng.start - VBA.Len(eArrKey) > -1 Then '這樣的寫法,如果內含超連結等功能變數,恐怕就會失誤了!
rngExam.SetRange rng.start - VBA.Len(eArrKey), rng.start
If VBA.StrComp(rngExam.text, eArrKey) = 0 Then '找到要避開的關鍵字
examOK = False '檢測不通過
Exit For
End If
End If
Next eArrKey
End If
If examOK Then
checkPhrases: '內嵌於檢查:關鍵字含在該避免的片語詞句檢查
'If Keywords.易學KeywordsToMark_ExamInPhraseAvoid.Exists(e) Then
If isInPhrasesAvoid Then
If dictCoordinatesPhrase.Count = 0 Then
GoSub buildDictCoordinatesPhrase
End If
For Each key In dictCoordinatesPhrase
'遍歷每個該避開的詞語片語座標
'若目前關鍵字內含於要避開的詞語片語語彙片段
If rng.start >= key And rng.End <= dictCoordinatesPhrase(key) Then
' rng.Select 'just for test
examOK = False '檢測不通過
Exit For
End If
Next key
' arrKey = Keywords.易學KeywordsToMark_ExamInPhraseAvoid(e)
' For Each eArrKey In arrKey '遍歷每個該避開的詞語,當先蒐集其位置在文件中所在位置,以供後續比對
' Set rngExam = rngExam.Document.Range
' With rngExam.Find
' Do While .Execute(eArrKey, , , , , , True, wdFindStop)
' '目前關鍵字內含於要避開的詞語片語語彙片段
' If rng.start >= rngExam.start And rng.End <= rngExam.End Then
'
'' rng.Select 'just for test
'
' examOK = False '檢測不通過
' Exit For
' End If
' Loop
' End With
' Next eArrKey
End If
'後、前、中三關都檢驗合格了
If examOK Then '合格才標識
With rng
processCntr = processCntr + 1
If processCntr Mod 35 = 0 Then SystemSetup.playSound 1 '播放音效以免誤以為當了
Rem 此檔可供效能測試,跑起來不知何故特別久! file:///H:\我的雲端硬碟\黃老師遠端工作\1易學雜著文本\非清人已初步標點\何良俊@四友齋叢說.docx
.HighlightColorIndex = defaultHighlightColorIndex
If .font.ColorIndex = wdAuto Then .font.ColorIndex = fontColor
End With
Else '片語詞句檢查未過
If rng.HighlightColorIndex = defaultHighlightColorIndex Then
With rng
' .Select 'just for test
.HighlightColorIndex = wdNoHighlight
.font.ColorIndex = wdAuto
End With
End If
End If
Else '前綴檢查未過
'If allDoc Then
If rng.HighlightColorIndex = defaultHighlightColorIndex Then
With rng
.HighlightColorIndex = wdNoHighlight
.font.ColorIndex = wdAuto
End With
End If
End If
End If
Else '如果前也無後也無
GoTo checkPhrases:
End If
Else '後綴檢查未過
'If allDoc Then
If rng.HighlightColorIndex = defaultHighlightColorIndex Then
With rng
.HighlightColorIndex = wdNoHighlight
.font.ColorIndex = wdAuto
End With
End If
End If
End If
Else '如果沒有下文
GoTo checkPrevious
End If
Loop 'Do While .Execute(e, , , , , , True, wdFindStop, True) '在範圍中尋遍關鍵字出現的位置
If dictCoordinatesPhrase.Count > 0 Then
dictCoordinatesPhrase.RemoveAll '歸零供下一個關鍵字使用
End If
'If Keywords.易學KeywordsToMark_ExamInPhraseAvoid.Exists(e) Then
' ……
' dictCoordinatesPhrase.Add rngExam.start, rngExam.End
Else '不用檢查直接取代(逕行標識)者
Do While .Execute(e, , , , , , True, wdFindStop, True) '此效能也不會比 wdReplaceAll 引數者慢,可見其內當亦係用類似之迴圈實作者也 20240919 感恩感恩 讚歎讚歎 南無阿彌陀佛
' .Parent.HighlightColorIndex = defaultHighlightColorIndex
' .Parent.Font.ColorIndex = fontColor
Rem 若寫成以下會有49DLL呼叫規格錯誤,這次重寫又不會了,可見是 VBE編譯器故障 20240920
With rng
.HighlightColorIndex = defaultHighlightColorIndex
If .font.ColorIndex = wdAuto Then .font.ColorIndex = fontColor
End With
Loop
' .Execute e, , , , , , True, wdFindStop, True, e, Replace:=wdReplaceAll '在含有超連結等格式化文字時會失靈
'rng.SetRange startRng, endRng'前已有
End If
End If
Next e '下一個打算要標識的關鍵字
End With
finish:
rng.SetRange startRng, endRng '設回原來的樣子才不會改變,於呼叫端才不會出錯
Set dictCoordinatesPhrase = Nothing
Exit Sub
buildDictCoordinatesPhrase:
'若有內嵌於的片語語詞(包含關鍵的片語語句)需查驗的話,就先記下要比對的位置集合
' 若後、前檢查都未過就不必了,故今再改移至內嵌之檢查,並以 dictCoordinatesPhrase.Count 來作判斷
If isInPhrasesAvoid Then
arrKey = Keywords.易學KeywordsToMark_ExamInPhraseAvoid(e)
For Each eArrKey In arrKey '遍歷每個該避開的詞語,蒐集其在文件中的所在位置,以供後續比對
'已有allDoc參數控制是否操作整份文件
rngExam.SetRange startRng, endRng '故不需處理整份文件,就只就操作範圍內處置就可。感恩感恩 讚歎讚歎 南無阿彌陀佛 20240915
With rngExam.Find
Do While .Execute(eArrKey, , , , , , True, wdFindStop)
' 記下含有目前關鍵字的詞語片語語彙片段在範圍中的位置
dictCoordinatesPhrase.Add rngExam.start, rngExam.End
Loop
End With
Next eArrKey
End If
Return
eH:
Select Case Err.Number
Case Else
MsgBox Err.Number & Err.Description
Debug.Print Err.Number & Err.Description
Resume
End Select
End Sub