一尺寸與環(huán)繞方式實戰(zhàn)教程)
平時在Word里整理文檔遇到最多的煩心事之一就是圖片。從不同來源復制進來的截圖、照片、設計稿尺寸七零八落有的撐滿整頁有的縮成指甲蓋環(huán)繞方式還各種不統(tǒng)一一頁文檔改下來半天時間就耗在拖拽圖片上了。后來我用宏把整套流程自動化之后處理一百張圖片基本就是幾秒鐘的事。這篇就把完整思路、可直接抄的代碼、以及我踩過的坑一次說清楚。宏這個東西在Word里其實沒那么神秘它本質上就是一段用VBAVisual Basic for Applications寫的小程序。你可以用開發(fā)工具選項卡下面的宏功能錄制一段操作Word會把你的鼠標點擊和鍵盤輸入翻譯成代碼也可以直接打開VBA編輯器手寫代碼。批處理圖片這種重復性強、規(guī)則明確的操作用宏來處理是最合適的。先說清楚這套內(nèi)容適合誰看經(jīng)常用Word寫標書、做產(chǎn)品手冊、整理會議紀要、編輯技術文檔的朋友以及想把從網(wǎng)上復制來的圖文資料快速規(guī)范化的人。你不需要會編程只要會復制粘貼代碼、能看懂中文注釋就夠了。1. 宏操作的整體思路與準備工作1.1 批量修改圖片格式為什么必須用宏很多人第一反應是我用Word的查找替換不就行了但圖片不是文字查找替換對圖片幾乎無能為力。你當然可以一張一張右鍵設置大小和環(huán)繞方式但假設一份文檔里有八十張截圖每張都要把寬度改成14厘米、居中顯示、四周型環(huán)繞手動操作意味著至少240次獨立的鼠標點選。人不是機器做到第三十張就會開始漏改或者改錯。宏能解決的正是這個重復且規(guī)則明確的問題。它的執(zhí)行邏輯很簡單遍歷文檔中所有圖片每張都按你預設的規(guī)則調(diào)整一遍。不管圖片是二十張還是兩百張效率幾乎一樣。我自己測試過一臺普通的辦公電腦處理一份含120張圖片的文檔宏跑完用不了五秒而且每張圖片的處理結果完全一致不會出現(xiàn)這張改了那張忘了的情況。另外還有個手動操作很難顧及的細節(jié)圖片比對的基準。手動改圖時你通常會目測圖片大小是否合適但目測是不穩(wěn)定的。宏可以設定一個絕對標準比如所有圖片寬度統(tǒng)一為14厘米這就保證了整套文檔的視覺一致性。對于標書、技術方案這類有格式審查要求的文檔這一點尤其重要。1.2 準備宏運行環(huán)境啟用宏與打開VBA編輯器在寫代碼之前有兩項準備工作必須先做很多人卡在第一步其實就是這兩個地方?jīng)]設置好。第一步是調(diào)出開發(fā)工具選項卡。Word默認是隱藏這個選項卡的。在Word的文件選項自定義功能區(qū)里勾選右側主選項卡列表中的開發(fā)工具確定之后就能在頂部菜單欄看到它。如果你的Word是精簡版或者綠色版可能沒有這個選項卡那就需要用Alt F11直接打開VBA編輯器——這個快捷鍵在絕大多數(shù)版本里都通用哪怕開發(fā)工具選項卡沒顯示VBA編輯器一般也能打開。第二步是設置宏安全性。Word默認會禁用所有宏彈出一個安全提示橫幅。我處理的辦法是在開發(fā)工具選項卡里點擊宏安全性然后把設置改為禁用所有宏并發(fā)出通知這樣文檔打開時可以手動選擇啟用。不建議把安全級別調(diào)到最低的啟用所有宏那會讓電腦面對惡意宏的時候毫無防備尤其是你經(jīng)常打開別人發(fā)來的文檔時。自己的文檔里的宏臨時啟用就好。環(huán)境準備就緒后用Alt F11進入VBA編輯器找到左側工程資源管理器里的Normal項目——當然也可以直接操作插入菜單添加一個新模塊。這個模塊就是存放宏代碼的容器下面所有示例代碼都放在模塊里寫。1.3 圖片格式相關的核心對象與屬性速查VBA操作圖片核心的對象是InlineShape嵌入型圖片和Shape浮動型圖片兩類。中文互聯(lián)網(wǎng)上的很多教程只講其中一類導致你復制了代碼卻報錯對象不支持該屬性或方法多半就是兩類對象搞混了。先說InlineShape。這類圖片是嵌在文字行里面的特點是跟隨文字流移動對應你在布局選項里選擇的嵌入型環(huán)繞方式。Word文檔里通過插入圖片插入的圖片默認就是InlineShape。再說Shape。這類圖片是浮動在文字上方的對應四周型緊密型襯于文字下方等環(huán)繞方式。鼠標拖進來的圖片、從網(wǎng)頁復制過來的圖片很多會變成Shape。批量修改圖片格式時通常需要同時遍歷這兩類對象才能做到一個不漏。獲取它們的方式很直觀ActiveDocument.InlineShapes是文檔中所有嵌入型圖片的集合ActiveDocument.Shapes是所有浮動型圖片的集合。兩者都支持用For Each...Next循環(huán)逐張?zhí)幚?。圖片尺寸的核心屬性InlineShape和Shape不太一樣。InlineShape用的是Width和Height單位是磅Point1厘米約等于28.35磅。Shape除了Width和Height之外還有LockAspectRatio屬性控制是否鎖定縱橫比以及WrapFormat.Type屬性控制環(huán)繞方式。這些屬性在下面的代碼示例里都會用到先有個印象后面看代碼就順了。注意在Word的VBA里圖片的寬度和高度屬性單位是磅不是厘米也不是像素。這是很多新手第一次跑宏時遇到數(shù)字對不上的最常見原因。我在代碼里一般會直接寫一個換算函數(shù)把厘米轉成磅再用。2. 核心細節(jié)解析與實操要點2.1 批量統(tǒng)一圖片尺寸的第一份實用代碼先給出一份我已經(jīng)在多種版本W(wǎng)ord上測過、穩(wěn)定運行的代碼。這段代碼解決的是最普遍的需求把文檔里所有嵌入型圖片統(tǒng)一成指定寬度高度隨原圖寬高比自動縮放。Sub BatchResizeInlineShapes() Dim targetWidth As Single Dim shapeItem As InlineShape 目標寬度單位厘米。改這個值即可例如12代表12厘米 targetWidth 12 將厘米轉換為磅1厘米 28.35磅 targetWidth targetWidth * 28.35 遍歷文檔中所有嵌入型圖片 For Each shapeItem In ActiveDocument.InlineShapes With shapeItem 如果圖片當前寬度大于目標寬度則縮小小于則放大 .Width targetWidth 高度會根據(jù)原圖比例自動調(diào)整因為默認鎖定縱橫比 End With Next shapeItem MsgBox 共處理 ActiveDocument.InlineShapes.Count 張嵌入型圖片 End Sub這段代碼的用法很傻瓜化粘貼到模塊里光標停在宏內(nèi)部任意位置按F5運行即可。運行完成后會彈出一個消息框告訴你處理了多少張圖片。如果沒有彈框而是直接報錯多數(shù)情況是文檔里壓根沒有嵌入型圖片或者你運行的是別人文檔里被保護的宏這兩個情況后面集中說。這里有個關鍵邏輯值得展開講為什么只設置Width不設置Height因為InlineShape默認是鎖定縱橫比的你修改寬度高度會按原圖比例自動跟著變。如果手動把Height也寫死圖片就會變形——我說的是那種被橫向拉伸或者縱向壓扁的失真效果。絕大多數(shù)場景下我們只需要統(tǒng)一寬度高度自然縮放就夠了。2.2 同時處理浮動型圖片統(tǒng)一環(huán)繞方式與尺寸嵌入型圖片處理后文檔里還可能有一批浮動型圖片。這類圖片的麻煩在于它不跟隨文字流經(jīng)常把正文擋住或者漂浮在頁面中間。批量處理時不但要改尺寸還要把它們改成統(tǒng)一環(huán)繞方式。下面的代碼會把文檔中所有浮動型圖片也就是Shape統(tǒng)一為寬度12厘米、四周型環(huán)繞、水平居中Sub BatchFormatFloatingShapes() Dim shapeItem As Shape Dim targetWidth As Single 目標寬度單位厘米 targetWidth 12 * 28.35 For Each shapeItem In ActiveDocument.Shapes With shapeItem 跳過非圖片類型的形狀比如文本框、自選圖形 If .Type msoPicture Or .Type msoLinkedPicture Then Dim newHeight As Single 記錄當前寬高比防止圖片被拉伸變形 newHeight targetWidth / .Width * .Height 鎖定縱橫比防止只能改寬度時被強制拉伸 .LockAspectRatio msoTrue .Width targetWidth .Height newHeight 設置環(huán)繞方式為四周型 .WrapFormat.Type wdWrapSquare 水平居中 .RelativeHorizontalPosition wdRelativeHorizontalPositionColumn .Left wdShapeCenter End If End With Next shapeItem End Sub這里有一個特別容易踩的坑ActiveDocument.Shapes集合里面不只是圖片還包括文本框、自選圖形、藝術字等。如果遍歷時不加類型判斷你的文本框會被強行改尺寸甚至改成圖片環(huán)繞方式文檔布局直接亂套。所以代碼里特意用了一個If判斷只處理類型為msoPicture圖片和msoLinkedPicture鏈接圖片的Shape對象。這個習慣非常重要凡是處理Shapes集合先過濾類型再動手否則后患無窮。另一個值得注意的細節(jié)是高度值的計算。我并不是直接寫死newHeight等于某個數(shù)值而是通過目標寬度 / 原始寬度 × 原始高度算出按比例縮放后的新高度。這樣即使圖片原本是豎構圖或者方形圖也都不會變形。雖然理論上設置鎖定縱橫比之后只改寬度也可以但在Word里實操發(fā)現(xiàn)部分圖片對象的LockAspectRatio在代碼運行時并不穩(wěn)定顯式算出高度再賦值更保險。2.3 批量修改圖片的文字環(huán)繞與對齊方式還有很多場景需要統(tǒng)一圖片的對齊方式。比如整篇文檔要求所有圖片水平居中手動操作時你需要逐個雙擊圖片、打開布局選項、選擇居中步驟繁瑣。用宏只需要一句話級別的操作。下面這段代碼把文檔中所有浮動型圖片統(tǒng)一為上下型環(huán)繞并水平居中。上下型環(huán)繞對排版來說比較干凈圖片不會和文字重疊適合說明書這類正式文檔Sub UniformImageLayout() Dim shapeItem As Shape Dim inlineItem As InlineShape 處理所有浮動型圖片 For Each shapeItem In ActiveDocument.Shapes With shapeItem If .Type msoPicture Or .Type msoLinkedPicture Then .WrapFormat.Type wdWrapTopBottom .RelativeHorizontalPosition wdRelativeHorizontalPositionColumn .Left wdShapeCenter End If End With Next shapeItem 嵌入型圖片無法直接設置環(huán)繞方式但可以設置段落居中 For Each inlineItem In ActiveDocument.InlineShapes inlineItem.Range.ParagraphFormat.Alignment wdAlignParagraphCenter Next inlineItem End Sub看代碼的時候可以注意一下嵌入型圖片的處理方式和浮動型完全不同。嵌入型圖片本身沒有環(huán)繞方式的概念它就在文字流里。想讓嵌入型圖片水平居中本質上不是設置圖片居中而是設置圖片所在段落的對齊方式為居中。代碼里用inlineItem.Range.ParagraphFormat.Alignment拿到了圖片所在段落并設置居中對齊這是一個非常經(jīng)典的思路。說實話我在實際項目里用到最多的就是這三個宏統(tǒng)一寬度、統(tǒng)一環(huán)繞、統(tǒng)一居中。有了這三個基本上九成以上的圖片格式亂象都能搞定。3. 實操過程與核心環(huán)節(jié)實現(xiàn)3.1 手把手運行第一個宏的完整流程光有代碼不夠還要知道怎么把它跑起來。我按步驟說一下從新建文檔到宏運行成功的全過程你只要照著走一遍就能通。實操流程打開一份含圖片的Word文檔先按Ctrl Home回到文檔開頭確保從第一張圖片開始處理。按Alt F11打開VBA編輯器。如果你是第一次打開界面左邊是工程資源管理器右邊是代碼編輯區(qū)。如果左側沒有顯示工程窗口按Ctrl R調(diào)出來。在菜單欄點擊插入模塊新建一個模塊。這個操作會創(chuàng)建一個名為模塊1的代碼容器。把上面的BatchResizeInlineShapes代碼全部復制進去粘貼到代碼編輯區(qū)里。把光標定位到代碼中任意位置按F5運行或者點擊工具欄上的綠色三角運行按鈕。運行結束后會彈出消息框顯示處理的圖片數(shù)量。如果沒有彈框且沒有報錯說明文檔中沒有圖這本身也是一種結果?;氐絎ord文檔查看圖片是否已經(jīng)統(tǒng)一尺寸。這里有個運行的微技巧如果你的文檔很長運行宏的時候可以先把視圖切到草稿模式在視圖選項卡切換因為草稿模式下Word不需要實時重繪所有圖片宏運行速度快很多。文檔圖片極多、頁面又大的時候這個操作能明顯縮短等待時間。3.2 修改宏參數(shù)讓寬度、高度、環(huán)繞方式隨你定制學會了運行宏接下來就要學會改參數(shù)。很多教程只給了代碼不給改法導致?lián)Q一個需求就不會用了其實改起來很簡單。以第一份代碼為例你會看到一行注釋寫著目標寬度單位厘米。改這個值即可例如12代表12厘米。要改成14厘米就把targetWidth 12改成targetWidth 14然后重新運行宏。需要注意的是尺寸值的合理性。Word默認頁面寬度通常是21厘米左右頁邊距各3.17厘米正文實際寬度約為14.66厘米。如果你把圖片寬度設置成15厘米圖片就會超出正文邊界甚至延伸到頁邊距里。我個人經(jīng)驗是A4紙的文檔圖片寬度設置在12到14厘米之間最合適既有視覺存在感又不溢出。如果是A5紙或者自定義頁面需要重新計算。環(huán)繞方式的修改在第三份代碼里wdWrapTopBottom就是上下型環(huán)繞。這個枚舉值可以換成其他類型常用的有這幾個環(huán)繞類型代碼枚舉值效果四周型wdWrapSquare文字環(huán)繞在圖片四周呈四邊形排布緊密型wdWrapTight文字緊貼圖片不規(guī)則邊緣上下型wdWrapTopBottom圖片獨占一塊矩形區(qū)域文字在上下方襯于文字下方wdWrapBehind圖片作為背景文字浮于上方浮于文字上方wdWrapFront圖片覆蓋文字適合標注用途改的時候直接把wdWrapTopBottom替換成上面對應的枚舉值就能生效。3.3 批量處理跨章節(jié)長文檔時的運行策略Word里幾十頁甚至上百頁的文檔很常見批量處理圖片時要注意一個運行策略問題宏是在整個文檔范圍內(nèi)遍歷的但不同章節(jié)的圖片類型可能混雜。有的文檔前面章節(jié)的圖片是直接插入的屬于嵌入型后面章節(jié)的圖片是從網(wǎng)頁復制進來的可能是浮動型。如果只跑嵌入型圖片的處理宏后面的浮動型圖片就不會被改到。所以實際項目中我建議的操作順序是先運行BatchResizeInlineShapes把嵌入型圖片統(tǒng)一寬度。再運行BatchFormatFloatingShapes把浮動型圖片統(tǒng)一成相同寬度和四周型環(huán)繞。最后運行UniformImageLayout把所有圖的段落對齊或者位置居中統(tǒng)一下。三步下來文檔里的圖片基本就服服帖帖了。這個先嵌入后浮動、再統(tǒng)布局的處理順序是我實踐多次后總結出來的能有效避免改完一批發(fā)現(xiàn)另一批沒改的尷尬。如果文檔實在太長超過200頁且圖片數(shù)量極多宏運行時Word可能會短暫無響應。這不是死機是Word在處理圖片重繪。此時不要亂點鼠標等右下角狀態(tài)欄出現(xiàn)就緒字樣即可。要想避免這種卡頓可以在運行前先按Ctrl End把光標移動到文末讓Word從文檔末尾開始處理這樣視覺上滾動更順暢。當然宏本身是從頭遍歷的光標位置不影響處理結果這只是個減輕視覺卡頓的小技巧。4. 常見問題與排查技巧實錄4.1 運行時錯誤91等常見報錯的出現(xiàn)原因與處理方式第一次跑宏報錯是家常便飯。我自己剛開始也經(jīng)常對著紅色報錯框一臉懵。把最常見的幾個報錯和處理方法整理成一個表遇到直接對照查就行。報錯信息出現(xiàn)原因解決辦法運行時錯誤91對象變量或With塊變量未設置文檔中沒有圖片或者遍歷到了非圖片類型的Shape確認文檔有圖在Shape遍歷中加類型判斷運行時錯誤4198命令失敗某些Shape對象不支持設置環(huán)繞方式用錯誤處理語句跳過或用On Error Resume Next容錯運行時錯誤438對象不支持該屬性或方法把InlineShape的屬性用在Shape上反之亦然確認圖片類型使用正確對象編譯錯誤用戶定義類型未定義代碼粘貼不完整或者模塊互相干擾新建一個模塊重新粘貼完整代碼宏被禁用運行時提示安全警告Word安全策略禁止執(zhí)行宏在開發(fā)工具中臨時啟用宏或對當前文檔啟用宏運行后圖片沒變化圖片可能是鏈接圖片或文檔處于兼容模式確認文檔是.docx格式鏈接圖片需先嵌入文檔其中最常見的就是運行時錯誤91。新手最容易犯的錯誤是直接把文檔里所有Shapes都當成圖片來改結果遍歷到文本框時報錯。處理方法前面已經(jīng)提過就是加If .Type msoPicture Or .Type msoLinkedPicture Then判斷。這段代碼我已經(jīng)寫進所有涉及Shapes的宏里了你在復制時一定不要刪掉這個判斷。還有一個容易被忽略的問題是文檔的兼容模式。如果你的文檔還是.doc格式VBA里的部分屬性調(diào)用會報錯。處理辦法很簡單——先把文件另存為.docx格式再運行宏。因為.docx格式的Word文檔對VBA的支持更完整很多枚舉值和屬性的行為也更符合預期。4.2 圖片尺寸沒變化或變形的排查思路如果你運行宏之后發(fā)現(xiàn)圖片尺寸紋絲不動先別急著懷疑代碼。按照優(yōu)先級排查看圖片是不是鏈接圖片。某些場景下Word里的圖片是外部鏈接的修改尺寸的屬性對它無效。你可以右鍵圖片選擇設置圖片格式看信息面板里是否有鏈接字樣。如果有先右鍵更改圖片選擇插入和鏈接或者直接在插入前把圖片嵌入文檔??茨愕暮晔遣皇翘幚礤e對象了。如果圖片是浮動型你只跑了嵌入型處理宏自然沒變化。用鼠標點一下圖片看圖片周圍是黑色小方塊嵌入型特征還是白色圓點浮動型特征判斷它屬于哪一類然后跑對應的宏??次臋n是不是受保護模式。某些從郵件附件或網(wǎng)盤下載的文檔會進入受保護視圖這種狀態(tài)下宏雖然能運行但很多修改操作會被攔截。關掉文檔右上角的啟用編輯提示再試試。而圖片變形的問題主要是高度被寫死導致的。比如你手動設置了Width 500又把Height 300固定住原圖比例不對時就會變形。解決方式就是我前面代碼里演示的通過目標寬度 / 原始寬度 × 原始高度計算新高度或者干脆只改寬度鎖定縱橫比。還有一點如果圖片本身因為之前的誤操作已經(jīng)被拉伸變形了宏只是在這個變形基礎上繼續(xù)改尺寸不會自動恢復原比例。這時需要先對圖片執(zhí)行重設圖片操作右鍵設置圖片格式圖片重設再跑宏。4.3 不同Word版本之間的宏兼容性問題Word 2010、2013、2016、2019、365在宏運行上大體兼容但細節(jié)處有差別尤其是中文版和英文版的枚舉值表現(xiàn)。我遇到過的情況是同一段宏在Word 2016上運行正常但在Word 365里處理浮動型圖片時WrapFormat.Type賦值偶爾不生效。究其原因新版Word對圖片對象的處理方式更趨向于內(nèi)容控件化某些老式的形狀屬性在新版本里底層邏輯發(fā)生了變化。應對辦法也不復雜盡量用官方公開的枚舉值進行賦值不要寫硬編碼數(shù)字。比如wdWrapSquare這個枚舉值在有的版本里值是0但你不需要關心它是不是0直接寫wdWrapSquareVBA會幫你做版本適配。如果你的文檔需要在多個同事的不同版本W(wǎng)ord之間傳閱建議給所有涉及圖片的宏加上一個自適應容錯語句On Error Resume Next這句代碼的意思是運行中遇到錯誤時跳過這條語句繼續(xù)執(zhí)行下一條而不是彈出報錯框終止運行。聽起來很粗暴但實際效果是能改的都改了不能改的就跳過至少保證宏能完整跑完。注意On Error Resume Next要放在宏的開頭且它會影響整個宏的錯誤處理行為宏結束后自動失效不會污染別的宏。如果你希望更嚴謹一些可以配合錯誤編號判斷但對普通批處理場景直接On Error Resume Next是最省事的選擇。5. 錄制宏與手寫宏的取舍建議5.1 什么時候用錄制宏什么時候手寫代碼如果你完全不想碰代碼Word自帶的錄制宏功能可以讓你把手動操作錄下來回放。操作路徑是開發(fā)工具錄制宏然后正常操作一張圖片比如設置寬度、設置環(huán)繞方式操作完停止錄制。Word會把這段操作翻譯成VBA代碼。錄制宏的優(yōu)勢是用起來沒有心理門檻劣勢也很明顯——錄出來的代碼非常啰嗦而且不會自動做循環(huán)。也就是說你錄制的操作只會作用在一張圖片上不會自動遍歷文檔中的其余圖片。它更適合對了我不想寫代碼但我需要宏幫我重復做某一個精確到鼠標點擊的操作的場景比如一次性設置某張?zhí)厥鈭D片的裁剪參數(shù)。手寫宏看起來嚇人其實更適合批量場景。因為你需要的核心能力就是遍歷修改這恰恰是錄制宏做不到的。我的個人建議是先花十分鐘掌握一份代碼的修改方法改寬度、改循環(huán)、改環(huán)繞方式遠比花半小時錄制一個只能作用于單張圖的宏有用。5.2 將宏保存到Normal模板以便后續(xù)所有文檔復用默認情況下你新建的宏放在當前文檔的模塊里。這個宏只對當前文檔有效下次打開新文檔又得重新粘貼一遍非常麻煩。要一勞永逸把宏的存放位置改成Normal.dotm模板。在VBA編輯器里確認你的模塊是建在Normal項目下面而不是文檔1項目下面。如果宏在文檔項目里直接把它拖到Normal項目下的模塊里或者直接重新在Normal下新建模塊粘貼代碼。存到Normal模板后所有新建的Word文檔都能用這些宏相當于給你的Word裝了一批常駐的批處理工具。我把常用的三個宏統(tǒng)一尺寸、統(tǒng)一環(huán)繞、統(tǒng)一居中組合成一套放在Normal里之后處理任何文檔基本都是三步跑完收工。有一點提醒Normal模板改動后Word退出時可能會詢問是否保存對模板的更改選擇是。如果在公共電腦上操作改Normal模板可能涉及權限問題。這時可以用加載項的方式把宏保存為一個獨立的.bas文件下次在任意電腦上通過文件選項加載項管理:模板轉到添加導入效果一樣。5.3 把代碼組合成一個一鍵處理宏的進階思路到了這一步你其實已經(jīng)掌握了核心方法。如果還想更偷懶可以把三步合并成一個總宏一鍵處理所有圖片。思路就是把前面三份代碼的內(nèi)容放在同一個子過程里用Call調(diào)用即可。把這個進階提升做成一個整體思路Sub OneKeyFixAllImages() 第1步統(tǒng)一嵌入型圖片寬度 Call BatchResizeInlineShapes 第2步統(tǒng)一浮動型圖片尺寸與環(huán)繞方式 Call BatchFormatFloatingShapes 第3步統(tǒng)一圖片對齊 Call UniformImageLayout MsgBox 全部圖片處理完成 End Sub由于每個子過程內(nèi)部都有獨立的對象遍歷和錯誤處理組合調(diào)用非常安全不會有變量沖突。運行一次OneKeyFixAllImages文檔里的圖片格式就整體規(guī)范了。這種組合思路也能舉一反三。比如你想在統(tǒng)一尺寸的同時再加一個所有圖片加0.5磅黑色邊框的需求那就只需要在原代碼里加兩行屬性賦值.Border.Weight 0.5 .Border.Color wdColorBlack這種方法相比一張張手動加邊框效率和一致性完全不是一個量級。6. 最后一個實操環(huán)節(jié)更復雜的圖片格式調(diào)整宏6.1 批量裁剪圖片到統(tǒng)一尺寸的編碼思路統(tǒng)一寬高比是更進階的需求。比如產(chǎn)品手冊里要求所有截圖寬高比統(tǒng)一為4:3或者干脆統(tǒng)一裁剪到固定像素尺寸這個用宏也可以實現(xiàn)但思路和統(tǒng)一寬度完全不同需要在代碼里操作Crop相關屬性。Sub BatchCropImages() Dim inlineItem As InlineShape Dim targetWidth As Single Dim targetHeight As Single 目標尺寸厘米 targetWidth 12 * 28.35 targetHeight 9 * 28.35 For Each inlineItem In ActiveDocument.InlineShapes With inlineItem Dim ratioOriginal As Single Dim ratioTarget As Single ratioOriginal .Width / .Height ratioTarget targetWidth / targetHeight 如果原圖比目標更寬則裁剪左右兩側 If ratioOriginal ratioTarget Then Dim cropWidth As Single cropWidth (.Width - targetHeight * ratioTarget) / 2 .PictureFormat.CropLeft cropWidth .PictureFormat.CropRight cropWidth .Width targetWidth .Height targetHeight Else 如果原圖比目標更高則裁剪上下兩側 Dim cropHeight As Single cropHeight (.Height - targetWidth / ratioTarget) / 2 .PictureFormat.CropTop cropHeight .PictureFormat.CropBottom cropHeight .Width targetWidth .Height targetHeight End If End With Next inlineItem End Sub這段代碼的原理并不復雜先比較原圖寬高比和目標寬高比如果原圖更寬說明多余的部分在兩側那就裁剪左右如果原圖更高說明多余的部分在上下那就裁剪上下。裁完之后直接把尺寸設置為目標值。需要說明的是PictureFormat.CropLeft這些屬性的作用單位不是厘米也不是像素而是相對圖片寬度的百分比但賦值用的數(shù)值范圍需要針對具體版本測試。我實測下來在主流Word版本中直接用磅值作為裁剪量計算會出現(xiàn)偏差所以上面代碼里的裁剪量寫法是半經(jīng)驗寫法建議使用前先復制一份文檔做測試。說實話批量裁剪這個需求如果只是偶爾遇到一次我更建議用Excel或者專業(yè)圖片工具先批量處理圖片文件再插入Word。但如果你的文檔有幾十張圖且全部要求統(tǒng)一比例這個宏的價值就立刻體現(xiàn)了。6.2 批量壓縮圖片體積以減小文檔大小文檔體積過大是另一類頭痛問題。幾十張高清截圖能讓docx文件輕松突破幾十兆發(fā)郵件、傳網(wǎng)盤都很不方便。宏也可以做批量壓縮。Sub BatchCompressImages() Dim inlineItem As InlineShape Dim shapeItem As Shape 設置文檔中所有嵌入型圖片的壓縮選項 For Each inlineItem In ActiveDocument.InlineShapes With inlineItem If .Type wdInlineShapePicture Then .ScaleWidth 100 .ScaleHeight 100 End If End With Next inlineItem 對浮動型圖片調(diào)用壓縮命令 For Each shapeItem In ActiveDocument.Shapes With shapeItem If .Type msoPicture Then .ScaleWidth 100 .ScaleHeight 100 End If End With Next shapeItem ActiveDocument.Save End Sub這段代碼本身并不執(zhí)行壓縮而是把圖片的縮放比例重置為100%避免圖片明明很小但文件卻很大的問題。真正體積壓縮需要調(diào)用Word自帶的壓縮圖片命令在代碼里實現(xiàn)是調(diào)ActiveDocument.CompressPictures但不同版本對這個函數(shù)的支持不一致所以我不把它作為一個通用方案推薦。更穩(wěn)妥的做法還是先另存一份文檔菜單文件另存為工具壓縮圖片手動選擇目標分辨率比如150dpi這是Word內(nèi)置功能兼容性和效果都最穩(wěn)定。宏在這里的主要作用是幫你統(tǒng)一重置縮放和篩選出需要壓縮的大圖。6.3 宏代碼的維護與安全分發(fā)方法代碼寫好了怎么安全地交給同事或者應用到更多電腦上也有講究。這里說三個我實際用過的方案。第一個方案是導出文件分發(fā)。在VBA編輯器中右鍵點擊模塊選擇導出文件會生成一個.bas文本文件。把這個文件發(fā)給別人對方在VBA編輯器里通過文件導入文件導入即可。這個方案簡單直接但.bas文件是純文本任何人打開都能看到代碼內(nèi)容不適合包含敏感邏輯的場合。第二個方案是F.bas文件合并到某個全局模板后分發(fā)。比如把宏做進一個格式工具.dotm模板文件對方打開這個模板就能使用模板內(nèi)的宏。適合團隊內(nèi)固定的排版需求。第三個方案是數(shù)字簽名。如果你在公司或者組織內(nèi)部發(fā)布宏正規(guī)做法是給宏工程添加數(shù)字簽名避免分發(fā)時被安全策略攔截或者被當作未知來源。個人使用不需要這么復雜但如果是團隊推廣這一步有意義。提個醒不要在公共文檔里內(nèi)置宏然后到處傳播尤其是涉及敏感字段的文檔。宏本身是代碼有可能被惡意利用Word的安全設置擋住宏是有道理的。正規(guī)做法是自己用的時候臨時啟用發(fā)給別人的文檔不帶宏把宏單獨做成模板或者工具分發(fā)。寫在最后我最初開始琢磨這套宏的時候就是因為一份一百多頁的產(chǎn)品手冊里有上百張截圖有的從微信聊天記錄里復制有的從PDF轉出來有的直接拖進頁面圖片寬高參差、環(huán)繞方式混亂光靠手工整理花了兩天還沒弄完。后來用批量處理宏前后迭代了三個版本才算真正把這個問題解決干凈?,F(xiàn)在再拿到亂圖文檔我心里不慌因為知道跑一遍宏就能搞定。有幾句真心話想對剛開始用宏的朋友說不要被VBA三個字母嚇退。我從寫第一行改寬度的宏到現(xiàn)在中間踩過的坑大部分都已經(jīng)寫在上面了——對象類型搞混、單位換算錯誤、忘記過濾Shape類型、兼容模式導致報錯——這些問題每個人都有不是說你看一遍教程就能完全避免關鍵是看完整套排查思路之后再遇到問題能自己定位。這只是一個開始。圖片格式批量處理跑順之后你會發(fā)現(xiàn)批量設置標題樣式、批量調(diào)整表格邊框、批量生成目錄標記這些操作都有對應的VBA方案。Word的自動化能力遠超大多數(shù)人的使用預期而宏就是打開這扇門的鑰匙。先把這份圖片處理宏真正用起來等你熟悉了代碼的邏輯結構后面的路會越走越寬。