前几天做了一个 颜色填充 excel样式 的程序,后来需要将该excel截图保存,excel实在太大了,应为一个文件头都有十几k,上次的博客也写了截图,但是在我的电脑上不管怎么样都要花费5s甚至以上的时间,这时间花费太久了,前端也等不了这么久,于是找了好久没有找到方案.后来想起无头的 selelnium浏览器,想着这个能不能无头呢,于是抱着好奇的心情先查询了有没有无头的wps或者word之类的,但是度娘没有告诉我,于是我去看了一下xlwings wx模块中的App类中的源码,还真让我找到了无头模式的开启方式
类中是这么介绍的

  visible : bool, default None
        Returns or sets a boolean value that determines whether the app is visible. The default
        leaves the state unchanged or sets visible=True if the object doesn't exist yet.

度娘翻译

可见:bool,默认无

返回或设置用于确定应用程序是否可见的布尔值。默认值

保持状态不变,或者如果对象尚不存在,则设置visible=True。

于是我将我上个帖子的截图部分单独划分出出来

def create_save_img(file_path, sheetname,img_name):
    # 读取excel内容转换为图片
    from PIL import ImageGrab
    import xlwings as xw
    import pythoncom
    import os
    pythoncom.CoInitialize()
    # 使用xlwings的app启动
    app = xw.App(visible=False, add_book=False, )
    # 打开文件
    file_path = os.path.abspath(file_path)
    wb = app.books.open(file_path)
    # 选定sheet
    sheet = wb.sheets(sheetname)
    # 获取有内容的区域
    all = sheet.used_range
    # 复制图片区域
    all.api.CopyPicture()
    # 粘贴
    sheet.api.Paste()
    # 当前图片
    pic = sheet.pictures[-1]
    # 复制图片
    pic.api.Copy()
    # 获取剪贴板的图片数据
    img = ImageGrab.grabclipboard()
    # 保存图片
    img.save(img_name)
    # 删除sheet上的图片
    pic.delete()
    # 不保存,直接关闭
    wb.close()
    # 退出xlwings的app启动
    app.quit()
    pythoncom.CoUninitialize()  # 关闭多线程
    # os.remove(file_path)

这个函数优化后,两个文件运行时间最短为2.43s最长为3.26s
然后我还想继续优化一下,因为3s左右的延迟也是很多的了,于是优化后成了下面办法

def create_save_img(filename, sheetname, save_image_name):
    # 读取excel内容转换为图片
    import pythoncom
    from PIL import ImageGrab
    from win32com.client import DispatchEx
    img_name = save_image_name
    filename = os.path.abspath(filename)
    # excel多线程相关
    pythoncom.CoInitialize()
    # 启动excel
    excel = DispatchEx("Excel.Application")
    # 不显示Excel,而True可视化
    excel.Visible = False
    # 是否显示警告,关闭系统警告(保存时不会弹出窗口)
    excel.DisplayAlerts = True
    # 打开excel
    workbook = excel.workbooks.Open(filename)
    # 选择sheet
    sheet = workbook.worksheets[sheetname]
    # 有内容的区域
    screen_area = sheet.UsedRange
    # 复制图片区域
    screen_area.CopyPicture()
    # 粘贴
    sheet.Paste()
    # 将刚刚选择的Shape重命名,避免与已有图片混淆
    excel.Selection.ShapeRange.Name = img_name
    # 选择图片
    sheet.Shapes(img_name).Copy()
    # 获取剪贴板的图片数据
    img = ImageGrab.grabclipboard()
    # 保存图片
    img.save(img_name + '.png')
    # 关闭工作薄,不保存
    # workbook .Close(SaveChanges=0)
    # 关闭Excel文件,不保存
    workbook.Close(False)
    # 退出excel
    excel.Quit()
    # 这个地方很重要,杀死excel进程是这个地方起作用
    del excel
    # 关闭多线程
    pythoncom.CoUninitialize()
    # os.remove(filename)

这个函数修改后运行截图的时间明显短了很多,两个文件最短1.21s,最长1.85s
使用win32com api启动比xlwings快了很多,因为我的系统是windows的,所以就用win32com了

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐