Office Space:撰寫 Microsoft Office 應用程式指令碼的秘訣

Office Space

歡迎蒞臨 Office Space 專欄,這裡提供處理 Microsoft® Office 應用程式指令碼的秘訣。每週二和週四我們將刊出新的秘訣,若要參閱以前討論過的秘訣,請造訪 Office Space Archive (Office Space 過往文件)。您有關於系統管理指令碼方面的問題嗎?請將電子郵件傳送到 scripter@microsoft.com。我們無法保證能夠逐一回答每個問題,不過我們會盡力而為。

擷取 Microsoft Word 鍵盤快速鍵清單

只要是電玩迷一定聽過「速碼」(Cheat Codes,又稱密技)。玩家在遊戲主控台內輸入秘密訊息,或在搖桿上依照某順序按下一系列按鈕— 突然間財富暴增、長生不老、擁有神力。而在依死亡定勝負的遊戲裡,擁有無盡的生命真的很好,也難怪「速碼」英文叫做 Cheat Code,而不是 Fair Code (正當地玩遊戲),畢竟它帶著作弊性質。

您可能不知道,其實 Microsoft Word 也有自己的一套速碼。雖然這套速碼不能用來發財或發功 (就我所知的這套辦不到),但確實能讓您使用 Word 的功力大增。假設您用小寫字母輸入一個句子,又想把所有字都改成大寫。沒問題,只要選取文字然後按 Ctrl+Shift+A,噠啦!全都都變成大寫字母啦。想把另一個句子設定為隱藏文字?將句子反白,按一下 Ctrl+Shift+H 就可以了。這些密技林林種種,說不盡道不完。

不賴吧?但其實背後有個問題: 您大概記不得 Microsoft Word 所有的鍵盤快速鍵 (誰有空去記上百個快速鍵)。那上到哪裡去找 Microsoft Word 指令和相對應速碼的清單呢?

您是可以在 Word 說明檔裡面找到不少,也可以在網際網路上找到很多,但這樣也太沒創意了吧?這裡有個更酷的方法可以找到相同的資訊:


Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.ListCommands(True)


沒錯,用指令碼找,只要三行就可以找到。首先建立 Word.Application 物件的執行個體,接著把 Visible 屬定設定為 True,這樣就能啟動並能在畫面上看見 Word。然後再呼叫 ListCommands 方法,傳送 True 參數。True 參數會告訴 ListCommands 回傳所有內建和自訂的 Word 指令。如果把 False 傳給 ListCommands,表示只蒐集自訂指令。

這三行指令一執行完,Word 會自動建立一份看起來像這樣的文件:

Microsoft Word 指令

怎樣,很酷吧!第一欄 (Command Name) 列出 Word 指令,第二欄 (Modifiers) 和第三欄 (Key) 則列出該指令的鍵盤快速鍵 (如果有的話)。仔細看表格,您會發現 Address 指令沒有快速鍵,但 All Caps 指令有 (Ctrl+Shift+A):

Address

 

 

 

All Caps

Ctrl+Shift+

A

 


這份清單洋洋灑灑地列出 Microsoft Word 2003 裡成千個指令。三行指令碼清潔溜溜,不賴吧?

如果您很懶,應該說,更懶的話,大可就此打住,反正您已經學了靈巧的指令碼。但仔細想想,其實約四分之三的 Word 指令並沒有鍵盤快速鍵。這些缺了快速鍵的命令 (例如 Address) 和有快速鍵的指令在表中交雜在一起。如果我們只需要已經有所謂速碼的指令,就得費勁篩選資料。所以我們就想,是不是可以把指令碼再改進,把沒有鍵盤快速鍵的指令從清單中剔除掉?

您已經知道答案啦,當然沒問題,方法是人想出來的。目前沒有現成方法只列出具有快速鍵的指令,所以我們換個方法,先像之前一樣把所有指令列出來,然後一列列往下找出已經有鍵盤快速鍵的指令。有快速鍵就跳過去,沒有快速鍵就刪除那列。完畢後指令清單看起來像這樣:

Microsoft Word 指令

好多了!指令碼修改後,乍看之下有點複雜,但其實不過多幾行而已:


Set objWord = CreateObject("Word.Application")
objWord.Visible = True
objWord.ListCommands(True)

Set objDoc = objWord.Documents(1)
Set objTable = objDoc.Tables(1)

For i = 1 to objTable.Rows.Count
    strText = objTable.Cell(i,2).Range.Text 
    strText = strText & objTable.Cell(i,3).Range.Text
    intLength = Len(strText)
    If intLength <= 4 Then
        objTable.Rows(i).Delete
        i = i - 1
    End If
Next


好吧,我承認不只是「有點」複雜,容我為您一行行拆解。改寫過的指令碼前三行跟原來的一樣:先建立一個 Word 執行個體,呼叫 ListCommands 方法,把所有 Microsoft Word 指令自動建立成一個表格。 然後使用下兩行指令碼,建立一對物件參考。一個參考到目前文件 (objDoc),另一個參考到文件裡的第一個表格 (objTable):


Set objDoc = objWord.Documents(1)
Set objTable = objDoc.Tables(1)


因為文件裡只有一個表格,所以 objTable 目前向我們指出包含所有 Word 指令的表格。目前為止都很順利。

從這裡建立一個 For Next 迴圈,從 1 執行到表格的列數為止 (假設表格有 4,362 列,迴圈會從 1 跑到 4,362)。這就是下面這行指令碼的用途:


For i = 1 to objTable.Rows.Count


那我們在 For Next 迴圈裡面要做什麼?一開始先把 strText 變數設定為等於表格中儲存格 i, 2Text 屬性值。也就是說,儲存格 i, 2 裡輸入什麼,strText 就會包含什麼。在這裡稍微解釋一下,儲存格是由列號後接欄名組成的參考位置,這裡我們用 i 當作迴圈變數。第一次執行迴圈 i, 2,會參考第一列第二欄,第二次執行迴圈 i, 2 則參考第二列第二欄,依此類推。

接下來把 strText 目前的值加上 i, 3 儲存格裡的任何值,然後把這個值指定給 strText。為何要看第三欄和第二欄呢?是這樣的,大部分的鍵盤快速鍵是由一個輔助按鍵搭配另一個按鍵組成:例如,Ctrl+Shift 加上 A。但有些快速鍵是由單個按鍵構成 (例如 F1 代表 [說明])。所以不能光看第二欄,不能因為第二欄裡面沒資料,就斷定沒有快速鍵。比較周全的方法是把第二欄和第三欄的值合併起來。

將字串合併後,我們再使用 Len 函數計算字串內的字元數,這個數字會儲存在 intLength 變數內。從這裡開始指令碼就變得比較複雜。您瞧,Address 指令的輔助按鍵和其他鍵都是空的。您可能會以為這兩個儲存格裡面沒有文字,所以字元長度應該是 0,其實不然。「空白」儲存格裡頭其實包含一個換行字元和換行符號 (相當於按下鍵盤的 ENTER),所以這兩個看似空空如也的儲存格其實包含四個字元 (每個儲存格有一個換行字元和一個換行符號)。因此我們需要靠這行指令碼判斷字串長度是否為 4 或 4 個以下的字元:


If intLength <= 4 Then


如果字串包含 4 個或更少的字元,就可假設輔助按鍵和其他鍵欄位為空,否則字串必須有至少 5 個字元 (2 個換行字元,2 個換行符號,和至少 1 個其他字元)。如果字元數為 4 或更少,則執行下面兩行指令碼:


objTable.Rows(i).Delete
i = i - 1


第一行指令碼刪除表格中的目前資料列。第二行指令碼將 i 的值重新設定為 i–1。為什麼呢?這麼說好了,假設我們目前在表格的第 3 行。我們把這行刪了,下一行是不是變成第 4 行?答錯了,下一行應該變成第 3 行。因為把先前那個第 3 行刪掉後,表格裡所有的資料列都會往上移一列。所以先前的第 4 行就變成第 3 行。所以我們要調整 i 的值,確定不會略過任何一列。

不好意思,是有點複雜。您只要多練幾次這個指令碼,應該就懂了。萬一您真的想試試看,先警告您這個程式碼可能會跑 15 分鐘或更久,讀取這麼大的表格需要很多時間。沒錯,這個程式碼跑起來是需要一些時間,但俗話說:「好事多磨」。

顯示: