Problem
Original text:
「幫我放進macdoc」
— Source: 使用者(2026-07-17,VBA 注入 no-op 之謎破案後)
zip 注入 vbaProject.bin 到 openpyxl 產的 xlsx 時,document-module 綁定缺失會讓 VBA 專案「看似正常、執行全滅」——巨集清單看得到、run VB macro 回成功,但沒有任何巨集真的執行。這個 gotcha 在網路上的 xlsm 注入教程幾乎沒人提,實戰花了一整個下午才破案,必須沉澱。
Type
docs
根因
vbaProject.bin 的 PROJECT stream(明文,MBCS 編碼)宣告 document modules:
Document=ThisWorkbook/&H00000000
Document=<carrier 的 sheet codeName>/&H00000000
綁定鍵在宿主端 XML:
| bin 宣告 |
宿主綁定鍵 |
缺失時的後果 |
Document=ThisWorkbook |
xl/workbook.xml 的 <workbookPr codeName="ThisWorkbook"/> |
致命:ThisWorkbook 物件無法解析 → 任何巨集一觸碰它就拋 429「ActiveX 元件無法產生物件」 |
Document=<sheet> |
各 xl/worksheets/sheetN.xml 的 <sheetPr codeName="..."/> |
次要:配對未定義(懸空 module 通常無害) |
openpyxl / LibreOffice 產的檔都不寫 codeName → 注入的 VBA 天生殘廢。
三個惡性疊加(為什麼難診斷)
- 429 被巨集自己的
On Error handler 吃掉 → 錯誤 MsgBox 一閃而過或被忽略,表面「執行完成」
- Mac Excel AppleScript
run VB macro 對解析失敗靜默回 exit 0(對不存在的巨集名也一樣!);詭異的是帶 module 限定名(Module.Sub)反而能觸發真執行並暴露錯誤
- 輸出恰好等於預期值時,no-op 與成功不可區分——靜態預填值本來就正確,巨集沒跑也「全對」
修法(注入器一併縫,純檔案層)
# xl/workbook.xml
<workbookPr/> → <workbookPr codeName="ThisWorkbook"/>
# xl/worksheets/sheetN.xml(每張)
<sheetPr .../> → <sheetPr codeName="工作表N" .../>
注意 <sheetPr> 可能帶既有屬性或不存在——regex 要處理三種形態,且絕不能產生重複的 sheetPr 元素(schema 違規 → Excel 靜默拒開,又是一個無聲失敗)。
驗收方法論(本案最大教訓)
驗收必須要求可觀察的狀態改變,不能只驗「結果正確」:
改輸入(利率 1.75% → 3%)→ 跑巨集 → 輸出必須改變(且與獨立實作的理論值一致)
→ 改回 → 輸出必須復原
實測修復後:42,112 格中恰好 310 格如 Python 引擎理論預測地改變——雙實作逐格吻合才算驗證完成。「跑了沒報錯 + 結果正確」在這個 bug class 面前毫無鑑別力。
Expected
Impact
- 沒有這頁,任何人(包括未來的 AI session)做 xlsm 注入都會掉進同一個「看似成功實為全滅」的洞,且平均要數小時才爬得出來
- 適用整個 OPC 家族(.docm/.pptm 的 document module 同理)
Refs #135, #136
Priority
P2
Problem
zip 注入
vbaProject.bin到 openpyxl 產的 xlsx 時,document-module 綁定缺失會讓 VBA 專案「看似正常、執行全滅」——巨集清單看得到、run VB macro回成功,但沒有任何巨集真的執行。這個 gotcha 在網路上的 xlsm 注入教程幾乎沒人提,實戰花了一整個下午才破案,必須沉澱。Type
docs
根因
vbaProject.bin的PROJECTstream(明文,MBCS 編碼)宣告 document modules:綁定鍵在宿主端 XML:
Document=ThisWorkbookxl/workbook.xml的<workbookPr codeName="ThisWorkbook"/>ThisWorkbook物件無法解析 → 任何巨集一觸碰它就拋 429「ActiveX 元件無法產生物件」Document=<sheet>xl/worksheets/sheetN.xml的<sheetPr codeName="..."/>openpyxl / LibreOffice 產的檔都不寫 codeName → 注入的 VBA 天生殘廢。
三個惡性疊加(為什麼難診斷)
On Errorhandler 吃掉 → 錯誤 MsgBox 一閃而過或被忽略,表面「執行完成」run VB macro對解析失敗靜默回 exit 0(對不存在的巨集名也一樣!);詭異的是帶 module 限定名(Module.Sub)反而能觸發真執行並暴露錯誤修法(注入器一併縫,純檔案層)
注意
<sheetPr>可能帶既有屬性或不存在——regex 要處理三種形態,且絕不能產生重複的 sheetPr 元素(schema 違規 → Excel 靜默拒開,又是一個無聲失敗)。驗收方法論(本案最大教訓)
驗收必須要求可觀察的狀態改變,不能只驗「結果正確」:
實測修復後:42,112 格中恰好 310 格如 Python 引擎理論預測地改變——雙實作逐格吻合才算驗證完成。「跑了沒報錯 + 結果正確」在這個 bug class 面前毫無鑑別力。
Expected
docs/opc-zip-surgery.md作為核心章節,或獨立成篇)inject_vba工具把 codeName 縫合做成內建步驟 + 把「狀態改變驗收」做成verify_macro_alive類工具Impact
Refs #135, #136
Priority
P2