棋行天下黄 发表于 2021-5-20 13:59

关于带隐藏区域的EXCELL表格用python循环截图方法

# coding:utf-8
import time
from win32com.client import Dispatch
from PIL import ImageGrab   
from PIL import Image
from ctypes import windll# 导入剪切板模块

def excel_catch_screen(filename, sheetname, screen_area, hidden_flag, rows_hidden, new_shape_name):
    try:
      """(r"E:\每日报表\延销售日进度通报.xlsx", "各门店日销售", "A1:J10",True,"3:34",'YB001')"""
      print(new_shape_name + "截图程序开始运行")
      # 清空剪切板,保证截图时剪切板不至于空间已满,无法保存,
      if windll.user32.OpenClipboard(None):# 打开剪切板
            windll.user32.EmptyClipboard()# 清空剪切板
            windll.user32.CloseClipboard()# 关闭剪切板
      excel = Dispatch('Excel.Application')
      excel.Quit()# 非常重要,这是反复实践得来的,先退出excell进程,否则极易粘贴截图出错,重复执行时容易死循环!
      excel.Visible = True# 可视化
      excel.DisplayAlerts = False# 是否显示警告
      wb = excel.Workbooks.Open(filename)# 打开excel
      ws = wb.Sheets(sheetname)# 选择sheet
      # 似乎有理由认为,在缓慢或负载很重的计算机上,Excel会对页面上的复杂对象进行“延迟处理”,即在以某种方式访问对象之前不会对其进行渲染。
      # 另一种方法是循环遍历对象。如果是这种情况,那么它是Excel的CopyPicture实现的一个错误,它不会在尝试复制之前强制复制对象。当复制方法发现目标范围的渲染尚未就绪时,它只会抛出错误而不是强制渲染范围。
      # 反复实践,在截图时相应几个地方停顿一秒能大幅减少截图错误发生
      time.sleep(1)
      ws.Select()# 页面实际切换必须用.Select(),如果.select无效,不会变化,切记!!
      if hidden_flag:
            ws.Rows(rows_hidden).EntireRow.Hidden = True# 如果需要隐藏,则表格隐藏区域进行隐藏

      time.sleep(1)
      ws.Range(screen_area).CopyPicture()# 复制图片区域
      ws.Cells(1, 1).Select()# 复制图片区域
      time.sleep(2)
      ws.Paste()# 粘贴 ws.Paste(ws.Range('A1'))# 将图片移动到具体位置
      excel.Selection.ShapeRange.Name = new_shape_name# 将刚刚选择的Shape重命名,避免与已有图片混淆
      # time.sleep(3)

      ws.Shapes(new_shape_name).Copy()# 选择图片
      if hidden_flag:
            ws.Rows(rows_hidden).EntireRow.Hidden = False
      img = ImageGrab.grabclipboard()# 获取剪贴板的图片数据
      img_name = new_shape_name + ".png"
      # 在Pycharm 2020版本实验保存JPG格式会报cannot write mode RGBA as JPEG错误,故保存为png
      # 在Pycharm 2020版本之前的2019版本可以直接保存为JPG
      time.sleep(2)
      # 在Pycharm 2020以后的版本直接保存为PNG在发送图片在微信上时图片背景会是黑色
      im = img.convert("RGBA")
      x, y = im.size
      print(im.size)
      p = Image.new('RGBA', im.size, (255, 255, 255))
      p.paste(im, (0, 0, x, y), im)
      time.sleep(1)
      p.save('E:\\每日报表\\' + img_name)
      # 以上是解决Pycharm 2020以后的版本直接保存为PNG在发送图片在微信上时图片背景会是黑色的问题
      print(new_shape_name + "已成功实现截图")
      wb.Close(SaveChanges=0)# 关闭工作薄,不保存
      # excel.Application.Quit# 退出excel一定不要用这
      excel.Quit()# 退出excel用这,多次运行时截图不能保存需要此语句
    except Exception as e:
      print(e)
      # 必须要加入此异常,如果不加入sleep停顿,不先退出excell进程,在多次截图情况下,有三分之一的概率发生错误,甚至死循环
      # 捕捉到的错误为'NoneType object hasno attribute save'
      # 在VBA截图各种代码下,多次循环截图都有偶尔截图保存为空白的情况,反复实践,用python截图这个程序最完善
      # (-2147352567, '发生意外。', (0, 'Microsoft Excel', 'Microsoft Excel 无法粘贴数据。', 'xlmain11.chm', 0, -2146827284), None)
      # 如出现上面这句错误,可能由于各种循环,当文件读写速度较快的时候,上一个Excel未关闭,下一个就打开,导致出现以上问题
      time.sleep(1)
      return excel_catch_screen(filename, sheetname, screen_area, hidden_flag, rows_hidden, new_shape_name)
      # 截图失败重新截图
   
filename = r"E:\每日报表\延保及销售日进度通报.xlsx"
sheetname = '各门店日销售'
excel_catch_screen(filename, sheetname, "A1:U41", False, "3:41", 'YB001')# 延保每日通报表一级截图
excel_catch_screen(filename, sheetname, "A1:U106", True, "3:41", 'YB002')# 延保每日通报表二级截图
excel_catch_screen(filename, sheetname, "A1:U191", True, "3:106", 'YB003')# 延保每日通报表二级截图

棋行天下黄 发表于 2021-5-20 14:07

目前用这段代码,循环截图目前100%正确,完美运行!

棋行天下黄 发表于 2021-5-20 14:36

这段代码截图在家里独显电脑上截图同一表格,同一区域保存的图片有300K,非常清晰,而在单位一个集成显卡电脑上保存只100K(和家里电脑同一WIN10系统,同一pycharm版本,所有模块版本一致,CPU级别差不多),发到微信上有点模糊,不知道原因,请高手指点并修改!

xedeno 发表于 2021-5-20 14:59

显卡的话是分辨率不一样么

棋行天下黄 发表于 2021-5-20 15:06

xedeno 发表于 2021-5-20 14:59
显卡的话是分辨率不一样么

分辨率完全一样,所以没搞懂原因!

dongse 发表于 2021-5-20 15:48

棋行天下黄 发表于 2021-5-21 15:58

if hidden_flag:
            ws.Rows(rows_hidden).EntireRow.Hidden = False
time.sleep(3)# 补充,这里漏了一个停顿,否则还有可能发生截图错误的发生
      img = ImageGrab.grabclipboard()# 获取剪贴板的图片数据
追记
页: [1]
查看完整版本: 关于带隐藏区域的EXCELL表格用python循环截图方法