在python代码中调用vba宏的四种方法

在python代码中调用vba宏

工作以python为主体,但是遇到了一些word操作的需求(详见上一篇),这个需求用word自带的功能会很容易实现,于是就想着能不能用python调用宏来处理。

网上找了一圈,发现了一大堆方法(因为一个个都在我那诡异的工作环境下全失败了所以真的找了很多),给各位罗列一下。

本文使用win32com库。

①在文档中存入宏,直接调用。

import win32com
from win32com.client import Dispatch

def updateContent(url):
    docApp = win32com.client.DispatchEx('Word.Application')
    try:
        doc = docApp.Documents.Open(url)
        doc.Run('...宏名称,不用带括号...')
        doc.Save()
        print("宏运行成功")
    except Exception as e:
        print(e)
    #保证即使出错也能关掉窗口,否则后台会出现大量word进程且可能占用文件
    docApp.Quit()

if __name__ == "__main__":
    updateContent("D:/testdocx.docm")
    x = input()

遇到的问题:很显然,这需要文档中本来就有宏,而且必须得保存为docm格式。而且对于一个新文件,设置不当的话还得打开一下确定启用宏(即使开了低安全度视软件版本也有这个可能)。

②变体1:保存为docx格式

前略,try:
        doc = docApp.Documents.Open('原始url.docm')
        doc.Run('宏名称,不用带括号')
        docApp.DisplayAlerts = False
        doc.SaveAs('另一个url.docx')
        print("宏运行成功")
      except Exception as e:                               后略。 

如上所述。excel似乎需要更多类似DisplayAlerts = False的操作,但word只需要改变这一项即可不保存宏。

③变体2:从别的文件中调用宏

前略,try:
        doc = docApp.Documents.Open('原始url.docx')
        doc.Run('带宏文件url.docm!里面的一个宏名')
        doc.Save()
        print("宏运行成功")
      except Exception as e:                               后略。 

“!”符号使你能指定将另一个文件中的宏在本文件中运行。

两个变体的问题:
两个变体都涉及到了对复数文件的操作。这在我的电脑上是没有问题的,但是在实际工作用的电脑上一直报错pywintypes.com_error:(-2147352567,‘发生意外。’,(0,None,None,None,0,-2147024891),None)。

网上对这个问题的说明是文件占用(打开着),但是我很确信没有。排查测试的结果是只要只涉及一个文件必不报错,涉及多个文件必报错。

不知道是那台电脑上只有wps的原因还是纯内网+云电脑的环境有什么奇怪的设置。(我甚至报过’RPC服务器不可用’,完全不能理解为什么,明明好好地开着)

④为什么我之前没有搜到直接写代码的?

这是我使用的宏代码:(作用是更新目录且只更新页码,见上一篇文章

Sub UpdateContent()
  Dim aStory As Range
  Dim aField As Field
     For Each aStory In ActiveDocument.StoryRanges
        For Each aField In aStory.Fields
           if aField.Type == 37:
              aField.Update
        Next aField
     Next aStory
End Sub

这是我最后实际使用的python代码:

import win32com
from win32com.client import Dispatch


def updateContent(url):
    docApp = win32com.client.DispatchEx('Word.Application')
    try:
        doc = docApp.Documents.Open(url)
        for aRange in doc.StoryRanges:
            for aField in aRange.Fields:
                if aField.Type == 37:
                    aField.Update()
        doc.Save()
        print("目录更新成功")
    except Exception as e:
        print(e)
    #保证即使出错也能关掉窗口,否则后台会出现大量word进程且可能占用文件
    docApp.Quit()


if __name__ == "__main__":
    updateContent("D:/testdocx.docx")
    x = input()

是的,这就是巨硬的兼容力。直接用就完事了。没有文件问题,没有docxdocm的格式问题,甚至不需要“启用宏”。我浪费的一整天的时间究竟是……

根据MSDN的文档,VB整体都.net化了。所以基本都是可以直接用的。

!!!注意:!!!
python并不在.net文档列明的支持语言中,所以并不一定可以使用所有vb代码。但至少本文所涉的没有问题。建议各位具体使用时尝试一下,不行的话就用方法123,毕竟正常的电脑上是不该出现我遇到的问题的。

  • 6
    点赞
  • 82
    收藏
    觉得还不错? 一键收藏
  • 5
    评论
评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值