最近我經常在word 裏面寫東西,發現程序代碼拷貝到word 裏面就沒有了在代碼編輯器裏面的那種語法高亮的效果,感覺不爽。於是我上網搜了搜,發現目前在word 中實現語法高亮的方法主要是通過安裝一個插件。由於我先天的對插件比較反感,所以自己動手,使用word 等office 軟件都支持的VBA (Visual BAsic For Application) 寫了一個語法高亮的宏。
這個宏的功能比較簡單,就是利用得到文檔中選中部分的代碼,然後分詞,判斷該詞的類別,然後着色。我現在使用的分詞方法是VBA 提供的,大部分情況下和我們預期的比較一致。但是在某些情況下,比如連續的分隔符,這種分詞方法會和C 語言分析器的分詞結果不同的。
這個宏除了可以語法着色,還可以爲代碼標註行號。(聽說侯捷在《word 排版藝術》一書中也有一個爲代碼添加行號的宏。不知道他的宏和我的宏是否雷同。如有雷同,純屬巧合:)
Private Function isKeyword(w) As Boolean
Dim keys As New Collection
With keys
.Add " if": .Add "else": .Add "switch": .Add "case": .Add "default": .Add "break"
.Add "goto": .Add "return": .Add "for": .Add "while": .Add "do": .Add "continue"
.Add "typedef": .Add "sizeof": .Add "NULL": .Add "new": .Add "delete": .Add "throw"
.Add "try": .Add "catch": .Add "namespace": .Add "operator": .Add "this": .Add "const_cast"
.Add "static_cast": .Add "dynamic_cast": .Add "reinterpret_cast": .Add "true"
.Add "false": .Add "null": .Add "using": .Add "typeid": .Add "and": .Add "and_eq"
.Add "bitand": .Add "bitor": .Add "compl": .Add "not": .Add "not_eq": .Add "or"
.Add "or_eq": .Add "xor": .Add "xor_eq"
End With
isKeyword = isSpecial(w, keys)
End Function
Private Function isSpecial(ByVal w As String, ByRef col As Collection) As Boolean
For Each i In col
If w = i Then
isSpecial = True
Exit Function
End If
Next
isspeical = False
End Function
Private Function isOperator(w) As Boolean
Dim ops As New Collection
With ops
.Add "+": .Add "-": .Add "*": .Add "/": .Add "&": .Add "^": .Add ";"
.Add "%": .Add "#": .Add "!": .Add ":": .Add ",": .Add "."
.Add "||": .Add "&&": .Add "|": .Add "=": .Add "++": .Add "--"
.Add "'": .Add """"
End With
isOperator = isSpecial(w, ops)
End Function
Private Function isType(ByVal w As String) As Boolean
Dim types As New Collection
With types
.Add "void": .Add "struct": .Add "union": .Add "enum": .Add "char": .Add "short": .Add "int"
.Add "long": .Add "double": .Add "float": .Add "signed": .Add "unsigned": .Add "const": .Add "static"
.Add "extern": .Add "auto": .Add "register": .Add "volatile": .Add "bool": .Add "class": .Add " private"
.Add "protected": .Add "public": .Add "friend": .Add "inlIne": .Add "template": .Add "virtual"
.Add "asm": .Add "explicit": .Add "typename"
End With
isType = isSpecial(w, types)
End Function
Sub SyntaxHighlight()
Dim wordCount As Integer
Dim d As Integer
' set the style of selection
Selection.Style = "ccode"
d = 0
wordCount = Selection.Words.Count
Selection.StartOf wdWord
While d < wordCount
d = d + Selection.MoveRight(wdWord, 1, wdExtend)
w = Selection.Text
If isKeyword(Trim(w)) = True Then
Selection.Font.Color = wdColorBlue
ElseIf isType(Trim(w)) = True Then
Selection.Font.Color = wdColorDarkRed
Selection.Font.Bold = True
ElseIf isOperator(Trim(w)) = True Then
Selection.Font.Color = wdColorBrown
ElseIf Trim(w) = "//" Then
'lIne comment
Selection.MoveEnd wdLine, 1
commentWords = Selection.Words.Count
d = d + commentWords
Selection.Font.Color = wdColorGreen
Selection.MoveStart wdWord, commentWords
ElseIf Trim(w) = "/*" Then
'block comment
While Selection.Characters.Last <> "/"
Selection.MoveLeft wdCharacter, 1, wdExtend
Selection.MoveEndUntil ("*")
Selection.MoveRight wdCharacter, 2, wdExtend
Wend
commentWords = Selection.Words.Count
d = d + commentWords
Selection.Font.Color = wdColorGreen
Selection.MoveStart wdWord, commentWords
End If
'move the start of selection to next word
Selection.MoveStart wdWord
Wend
' prepare For set lIne number
Selection.MoveLeft wdWord, wordCount, wdExtend
SetLIneNumber
End Sub
Private Sub SetLIneNumber()
Dim lines As Integer
lines = Selection.Paragraphs.Count
Selection.StartOf wdParagraph
For l = 1 To lines
lIneNum = l & " "
If l < 10 Then
lIneNum = lIneNum & " "
End If
Selection.Text = lIneNum
Selection.Font.Bold = False
Selection.Font.Color = wdColorAutomatic
p = Selection.MoveDown(wdLine, 1, wdMove)
Selection.StartOf wdLine
Next l
End Sub
下面是我給出的使用說明,原文沒給出使用說明。
使用方法:
1) 首先爲當前文檔新定義一個樣式,命名爲"ccode",專門用來對c代碼進行格式化。由於是代碼,所以推薦中文使用宋體(註釋中),而英文使用等寬字體(courier new)。建立樣式的步驟:在word2003中,“格式” → “新樣式”
2)將上面的vba代碼拷貝到文檔中,步驟:在word2003中,“工具” → “宏” → ”VB編輯器“ → ”Normal工程“ → ”Microsoft Word 對象“ ,雙擊 ”thisDocument"對象,將上面的代碼拷貝到新開的窗口中。當然你也可以把ccode樣式和highlight腳本保存到normal模板中,這樣以後你再寫代碼的時候就可以直接用了,不用自己再辛苦定義這些了。
3)選定代碼文本,然後執行highlight腳本: “格式” → “宏” → “宏”, 選擇SyntaxHighlight宏,然後執行就可以了。
如果想定製語法高亮,那麼修改上面的腳本就是了。