用 Python 给 Excel 表格截图(20250207)

ops/2025/2/11 14:30:31/

我搜索了网络上的方案,感觉把 Excel 表格转换为 HTML 再用 platwright 截图是比较顺畅的路径,因为有顺畅的工具链。如果使用的是 Windows 系统则不需要阅读此文,因为 win32com 库更方便。这篇文章中 Excel 转 HTML 的方案,主要弥补了网上其他方案中存在合并单元格的情况。代码为智谱清言帮助生成,有些变量控制还是需要自己改一下。


from openpyxl import load_workbook
from openpyxl.styles import Font, Border, Side, Alignment
from playwright.sync_api import sync_playwright
from datetime import datetime# 打开浏览器并截图
def capture_table_screenshot( url, output_file, table_selector):with sync_playwright() as p:browser = p.chromium.launch(headless=False)page = browser.new_page()# 注意这里需要加协议page.goto("file://" + url)# 等待表格元素加载完成page.wait_for_selector(table_selector)page.wait_for_timeout(1000)# 对表格元素进行截图table_element = page.locator(table_selector)table_element.screenshot(path=output_file)browser.close()# 默认合并单元格的文本内容是放在左上单元格的,如果不是,需要专门程序处理。
# 边框样式默认为1px solid
def read_excel(file_path):# data_only 将 Excel 表格里的公式计算成数值读取出来。wb = load_workbook( filename=file_path, data_only=True)ws = wb.active  # 读取活动工作表data = []merges = []  # 用于存储合并单元格的信息cell_styles = []# 读取合并单元格信息for merged_range in ws.merged_cells.ranges:start_row, start_col = merged_range.min_row, merged_range.min_colend_row, end_col = merged_range.max_row, merged_range.max_colmerges.append((start_row-1, start_col-1, end_row-1, end_col-1))for row in ws.iter_rows():row_data = []row_styles = []for cell in row:print(f"当前单元格的坐标:{cell.coordinate}")if cell.coordinate in ws.merged_cells.ranges:# 跳过合并单元格中的非起始单元格continue            if cell.value is not None:print(f"单元格的值:{cell.value}")row_data.append(str(cell.value))                else:row_data.append('')  # 空单元格填充空字符串# 读取单元格样式,提供默认值font = cell.font if cell.font else Font()border = cell.border if cell.border else Border()alignment = cell.alignment if cell.alignment else Alignment()print(f"单元格字体颜色:{font.color.index}")print(f"单元格边框样式:{border.top.style}")cell_style = {'font': {'name': font.name if font.name else 'Arial','size': font.size if font.size else 12,'bold': font.bold if font.bold else False,'italic': font.italic if font.italic else False,'color': font.color.rgb if font.color and font.color.rgb else '#000000'},'border': {'top': '1px solid' if border.top and border.top.style else None,'left': '1px solid' if border.left and border.left.style else None,'right': '1px solid' if border.right and border.right.style else None,'bottom': '1px solid' if border.bottom and border.bottom.style else None},'alignment': {'horizontal': alignment.horizontal if alignment.horizontal else None,'vertical': alignment.vertical if alignment.vertical else None}}row_styles.append(cell_style)print(f"转换后的单元格样式:{cell_style}")data.append(row_data)cell_styles.append(row_styles)      return data, merges, cell_styles# 该处默认只有同一行合并多列的情况。如果合并单元格占了两行,需要另外的处理。
def generate_html_table(data, merges, cell_styles):print(f"合并单元格的信息:{merges}")html = "<table style='border-collapse: collapse;'>\n"for row_idx, row in enumerate(data):print("-"*20)print(f"当前行的数据:{row}")html += "<tr>\n"# 设置一个跳过非首个合并单元格的标记skip_next_cell = 0for col_idx,cell in enumerate(row):if skip_next_cell > 0:skip_next_cell -= 1continue# 行号、列号从0开始print(f"当前单元格的值:{cell},行号:{row_idx},列号:{col_idx}")# 如果当前单元格为1行4列,则修改cell值if row_idx == 1 and col_idx == 4:# 获取今天的日期today = datetime.today()cell = formatted_date_no_leading_zeros = "截止 " + today.strftime("%-m 月 %-d 日")print(f"修改后的单元格值:{cell}")# 去除单元格样式style = cell_styles[row_idx][col_idx]if style:                font_style = f"font-family:{style['font']['name']}; font-size:{style['font']['size']}pt; " \f"font-weight:{'bold' if style['font']['bold'] else 'normal'}; " \f"font-style:{'italic' if style['font']['italic'] else 'normal'};"border_style = f"border-top:{style['border']['top']}; " \f"border-left:{style['border']['left']}; " \f"border-right:{style['border']['right']}; " \f"border-bottom:{style['border']['bottom']};"alignment_style = f"text-align:{style['alignment']['horizontal']}; " \f"vertical-align:{style['alignment']['vertical']};"if (row_idx, col_idx) in [(m[0], m[1]) for m in merges]:  # 检查当前单元格是否是合并单元格的起始单元格rowspan = [m[2] - m[0] + 1 for m in merges if m[0] == row_idx and m[1] == col_idx][0]colspan = [m[3] - m[1] + 1 for m in merges if m[0] == row_idx and m[1] == col_idx][0]if style:html += f"<td style='{font_style} {border_style} {alignment_style}' rowspan={rowspan} colspan={colspan}>{cell}</td>"else:html += f"<td rowspan={rowspan} colspan={colspan}>{cell}</td>"skip_next_cell = colspan - 1    # 跳过合并的列else:if style:html += f"<td style='{font_style} {border_style} {alignment_style}' >{cell}</td>"else:html += f"<td>{cell}</td>"html += "</tr>\n"html += "</table>"html = "<!DOCTYPE html><html><head><meta charset='UTF-8'><title>Excel Table</title></head><body>" + html + "</body></html>"return htmldef main():current_dir = 'reer'excel_file_path = current_dir + 'log/2re0207.xlsx'  # 替换为你的Excel文件路径html_file_path = current_dir + 'log/output.html'screenshot_file_path = current_dir + 'log/table_screenshot.png'data, merges, cell_styles = read_excel(excel_file_path)html_table = generate_html_table(data, merges, cell_styles)with open(html_file_path, 'w', encoding='utf-8') as file:file.write(html_table)# 调用函数,替换以下参数url = html_file_path  # 网页URLoutput_file = screenshot_file_path  # 输出文件路径table_selector = 'table'  # 表格的CSS选择器,根据实际情况调整capture_table_screenshot(url, output_file, table_selector)if __name__ == "__main__":main()


http://www.ppmy.cn/ops/157543.html

相关文章

8、Python 面试题解析:实例方法、静态方法和类方法的区别

Python 实例方法、静态方法和类方法详解 在 Python 中&#xff0c;实例方法、静态方法和类方法是三种不同类型的方法&#xff0c;它们的主要区别在于调用方式、参数传递和使用场景。以下从定义、语法、使用场景等方面全面解析&#xff0c;并附代码示例。 一、核心区别 方法类…

信创领域的PostgreSQL管理员认证

信创产业&#xff0c;全称为信息技术应用创新产业&#xff0c;是中国为应对国际技术竞争、保障信息安全、实现科技自立而重点发展的战略性新兴产业。其核心目标是通过自主研发和生态构建&#xff0c;逐步替代国外信息技术产品&#xff0c;形成自主可控的国产化信息技术体系。 发…

计算机毕业设计SpringBoot+Vue.js遗传算法自动排课系统(源码+文档+运行视频+讲解视频)

温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 温馨提示&#xff1a;文末有 CSDN 平台官方提供的学长联系方式的名片&#xff01; 作者简介&#xff1a;Java领…

深入剖析 JVM 垃圾收集器之 CMS 和 G1

在 Java 虚拟机&#xff08;JVM&#xff09;的世界里&#xff0c;垃圾收集器是一个至关重要的组件&#xff0c;它负责自动回收不再被使用的内存空间&#xff0c;保证应用程序的稳定运行。本文将着重介绍两种具有代表性的垃圾收集器&#xff1a;CMS&#xff08;Concurrent Mark …

【含文档+PPT+源码】基于微信小程序的校园志愿者管理系统的设计与实现

项目介绍 本课程演示的是一款 基于微信小程序的校园志愿者管理系统的设计与实现&#xff0c;主要针对计算机相关专业的正在做毕设的学生与需要项目实战练习的 Java 学习者。 1.包含&#xff1a;项目源码、项目文档、数据库脚本、软件工具等所有资料 2.带你从零开始部署运行本…

在线SQL转JSON-GO在线工具集

此工具提供多数据库 SQL 自动转换为 JSON 格式的工具&#xff0c;支持 MySQL、PostgreSQL、Oracle 等主流数据库。此工具将 SQL 查询结果转换为结构化的 JSON 数据&#xff0c;方便 JSON 处理和数据交换&#xff0c;优化数据管理和集成过程&#xff0c;提升工作效率。 gotool

【文本处理】如何在批量WORD和txt文本提取手机号码,固话号码,提取邮箱,删除中文,删除英文,提取车牌号等等一些文本提取固定格式的操作,基于WPF的解决方案

企业的应用场景 数据清洗&#xff1a;在进行数据导入或分析之前&#xff0c;往往需要对大量文本数据进行预处理&#xff0c;比如去除文本中的无关字符&#xff08;中文、英文&#xff09;&#xff0c;只保留需要的联系信息&#xff08;手机号码、固话号码、邮箱&#xff09;。…

【JVM详解二】常量池

一、常量池概述 JVM的常量池主要有以下几种&#xff1a; class文件常量池运行时常量池字符串常量池基本类型包装类常量池 它们相互之间关系大致如下图所示&#xff1a; 每个 class 的字节码文件中都有一个常量池&#xff0c;里面是编译后即知的该 class 会用到的字面量与符号引…