python脚本处理excel,将Group分解再组合

最近的需求是写脚本进行excel的文档批处理。替换某个单元格的公式,内容等。
一开始用的是openpyxl库。遇到的坑是,脚本执行后excel内的图片全部丢失。
查到的解决方式为:

pip install pillow

安装图片相关的库就可以。确实大部分的图片都正常保存下来了。
但是出现了新的坑。运行的时候会出现告警

\openpyxl\reader\drawings.py:59: UserWarning: wmf image format is not supported so the image is being dropped
  warn(msg)

导致一部分内容丢失。一开始一直在查找怎么处理wmf文件。但是感觉处理都很麻烦。因为报错是在load_workbook这一步,所以查到的那些在加载完成后把wmf格式的图片修改为其他格式之类的操作根本无法完成。
后面尝试过用pandas。但是pandas更多用于数据的清洗,分析。并不适合用来修改excel。用pandas处理文件会导致原来的各种格式都没了,只剩下单纯的数据。
最后的解决办法是用xlwings库。这个库可以正常打开,处理和保存excel。不会丢失任何的图片。
之后我去看文档到底哪里有wmf图片。发现是一个Group,在openpyxl库内会被识别为wmf文件。
在这里插入图片描述

这个Group 113是几个矩形组成的,用于每层文档审核人插入签名图片,内部包含很多小的Group和rectangle。
我的下一个需求刚好是做一个一键插入签名图片的脚本。签名图片需要插入到Group 113内的Group 88内。

 
import os
import xlwings
app = xw.App(visible=False, add_book=False) # 程序可见,只打开不新建工作薄
app.display_alerts = False # 警告关闭
app.screen_updating = False # 屏幕更新关闭
try:
    workbook = app.books.open(path2)
    sheet = workbook.sheets['sheet名字']
    for cell in sheet.shapes:
        print(cell.name)
    workbook.close()
    app.quit() # 关闭程序
    os.system("pause")    
except Exception as e:
    print(e)
    app.quit() # 关闭程序    
    os.system("pause")    

放置图片的那个shape名字叫Group 88,是这个Group 113的一部分。我发现遍历shapes是遍历不出来这个小group的,但是我直接调用这个名字,可以打印出来他的shape部分信息。就很迷惑。
最后是调用Ungroup,将这个组合取消合并,就可以打印出所有的shapes了。

                        group = sheet.shapes['Group 113']
                        group.api.Ungroup()
                        cr = sheet.shapes['Group 88']  #承认
                        print(cr.left, cr.top, cr.width, cr.height)        
                        sheet.pictures.add('xx.png', left=cr.left, top=cr.top, width=cr.width, height=cr.height)

这里是插入图片的流程。我是将图片插入在Group113内的Group88内。在添加的时候指定位置和大小。
执行完毕后图片插入是成功的,大小也正常。但是文档中的对象变成了很多个,原本整个Group是可以随意拖拽,保持形状整体移动的,现在是单个分散的shapes,一拖动就散架了。
在这里插入图片描述
这个将Ungroup后的shapes重新Group的过程,找了很久才找到正确的函数。跟chatgpt斗智斗勇很多轮。

                        groupMem = []
                        for cell in sheet.shapes:
                            if(cell.type != 'picture' and cell.type != "comment"):
                                groupMem.append(cell.name)
                        print(groupMem)
                        newGroup = sheet.api.Shapes.Range(groupMem).Group()
                        newGroup.Name = 'Group 113'

这样就可以实现想要的需求。判断条件根据自己的需求做对应更改。
注意api需要在sheet和Shapes中间,
注意Shapes的S大写,
注意Range的R大写。
注意Group在最后。
注意重命名时Name的N也是大写。

chatgpt建议我用了VBA宏等各种方式,还有sheet.shapes.api.group(groupMem),等各种函数。
每次都报错。api的位置,group的位置,range的有无,各种坑都踩过。用VBA宏也各种报错。
只有上面这个能实现。

最后贴一下完整代码。我这边是批处理路径下所有表格的某个sheet。需要根据实际需求做对应修改。

 
import os
import xlwings

import xlwings as xw

retval = os.getcwd()
print("当前工作目录为 %s" % retval)
app = xw.App(visible=False, add_book=False) # 程序可见,只打开不新建工作薄
app.display_alerts = False # 警告关闭
app.screen_updating = False # 屏幕更新关闭

try:
#多层的for循环可能有些冗余,可自行修改。写好能用我就没改
    for root, ds, fs in os.walk(retval):
        os.chdir(retval)
        for d in ds:    
            path = os.path.join(root, d)
            for root1, ds1, fs1 in os.walk(path):
                for f1 in fs1:
                    if(f1.endswith('.xlsx') and f1.startswith('~') == False):
                        path2 = os.path.join(root1, f1)
                        print(path2)
                        workbook = app.books.open(path2)
                        sheet = workbook.sheets['sheetName']
                        group = sheet.shapes['Group 113']
                        group.api.Ungroup()
                        cr = sheet.shapes['Group 88'] 
                        print(cr.left, cr.top, cr.width, cr.height)        
                        sheet.pictures.add('xx.png', left=cr.left, top=cr.top, width=cr.width, height=cr.height)
                        groupMem = []
                        for cell in sheet.shapes:
                        #判断条件注意修改
                            if(cell.type != 'picture' and cell.type != "comment"):
                                groupMem.append(cell.name)
                        print(groupMem)
                        newGroup = sheet.api.Shapes.Range(groupMem).Group()
                        newGroup.Name = 'Group 113'
                        workbook.save()
                        workbook.close()

        break
    app.quit() # 关闭程序
    os.system("pause")    
except Exception as e:
    print(e)
    app.quit() # 关闭程序    
    os.system("pause")    

OK,结束。这几天脚本写下来,觉得xlwings才是最好用的python处理excel的库。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值