Python Inject VBA Macro into XLSM File
Introduction
雖然在 Python 中可以通過 openpyxl
套件來很好的操作 Excel 讀寫,但當想要在檔案中插入 VBA macro 時便沒有辦法依靠 openpyxl
。不過我們仍然可以透過 pywin32 套件來操作 Windows API,達到在 Excel 檔案中插入 VBA macro 的需求。
在本篇文章中將會提到:
- 透過
pywin32
對 XLSM 檔案插入 VBA macro。 - 解決在過程中會出現的「檔案信任」的問題。
- 將程式碼包裝為類(class)以方便使用,以及其使用範例。
- 如何透過
openpyxl
建立可插入 VBA macro 的 XLSM 檔案。
Steps
Install pywin32 Package
1 | pip3 install pywin32 |
Example
1 | from win32com.client import Dispatch |
需要特別注意的是,餵給 com_instance.Workbooks.Open
的檔案路徑必須是絕對路徑,若是相對路徑將會引發錯誤。舉例而言,當我們餵入 ./vba_test_src.xlsm
會得到這樣的結果:
1 | pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', "Sorry, we couldn't find ./vba_test_src.xlsm. Is it possible it was moved, renamed or deleted?", 'xlmain11.chm', 0, -2146827284), None) |
因此我們可以通過 os
package 來將路徑轉換為絕對路徑後再餵入:
1 | import os |
Programmatic Access
若依照上述範例中的程式碼直接執行,將會引發錯誤:
1 | pywintypes.com_error: (-2147352567, 'Exception occurred.', (0, 'Microsoft Excel', 'Programmatic access to Visual Basic Project is not trusted\n', 'xlmain11.chm', 0, -2146827284), None) |
這是因為出於安全原因,在預設情況下這樣的行為(對 Visual Basic Project 的程式性存取)是被禁止的,因此我們需要信任文件來讓我們程式可以順利執行。接下來將說明如何解決這樣的問題。
Access by Editing File Settings
開啟檔案,並前往 File -> Options -> Trust Center -> Trust Center Settings -> Macro Settings -> activate checkmark on Trust access to the VBA project object model
.
雖然這項解法只需要勾選選項並進行文件信任,但每個檔案都需要在執行程式前先設定過,為了使程式能夠更自動化的執行,我們可以通過另外一種解法來達到。
Access by Code
1 | $ pip3 install pywin32 |
1 | import winreg |
Solution
最後可以將上面的範例整合組合成一個 Python class (GitHub: ychsieh95/Python-VBA-Writer),使我們更有效方便的去使用它:
Example
1 | from vba_macro_writer import VbaMacroWriter |
Remark
Create XLSM File by openpyxl
若需要在 openpyxl
中建立一個新的 Workbook 並在中插入 VBA macro,需要先將檔案儲存為 .xlsm
並重新儲存:
1 | import openpyxl |
在儲存後再透過前述方法插入 VBA macro。