用 Python 给 Excel 表格截图(20250207)

我搜索了网络上的方案,感觉把 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.rhkb.cn/news/14100.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

kafka消费端之消费者协调器和组协调器

文章目录 概述回顾历史老版本获取消费者变更老版本存在的问题 消费者协调器和组协调器新版如何解决老版本问题再均衡过程**第一阶段CFIND COORDINATOR****第二阶段&#xff08;JOINGROUP&#xff09;**选举消费组的lcader选举分区分配策略 第三阶段&#xff08;SYNC GROUP&…

Redis --- 使用Feed流实现社交平台的新闻流

要实现一个 Feed 流&#xff08;类似于社交媒体中的新闻流&#xff09;&#xff0c;通常涉及以下几个要素&#xff1a; 内容发布&#xff1a;用户发布内容&#xff08;例如文章、状态更新、图片等&#xff09;。内容订阅&#xff1a;用户可以订阅其他用户的内容&#xff0c;获…

6 maven工具的使用、maven项目中使用日志

文章目录 前言一、maven&#xff1a;一款管理和构建java项目的工具1 基本概念2 maven的安装与配置&#xff08;1&#xff09;maven的安装&#xff08;2&#xff09;IDEA集成Maven配置当前项目工程设置 maven全局设置 &#xff08;3&#xff09;创建一个maven项目 3 pom.xml文件…

Visual Studio(VS)没有显示垂直滚轮or垂直滚轮异常显示

前言&#xff1a; 前段时间&#xff0c;我换上了新电脑。满心欢喜地安装好 VS&#xff0c;准备大干一场时&#xff0c;却发现了一个小麻烦 —— 垂直滚轮显示异常&#xff08;如图 1&#xff09;。这种显示方式实在让我难以适应&#xff0c;每一次操作都觉得别扭。 于是&#…

Fiddler Classic(HTTP流量代理+半汉化)

目录 一、关于Fiddler (一) Fiddler Classic (二) Fiddler Everywhere (三) Fiddler Everywhere Reporter (四) FiddlerCore (五) 总结 二、 软件安全性 1. 软件安装包 2. 软件汉化dll 三、安装与半汉化 1. 正常打开安装包点击下一步安装即可&#xff0c;安装路径自…

时序数据库:Influxdb详解

文章目录 一、简介1、简介2、官网 二、部署1、安装2、配置&#xff08;1&#xff09;用户初始化 三、入门&#xff08;Web UI&#xff09;1、加载数据&#xff08;1&#xff09;上传数据文件&#xff08;2&#xff09;代码接入模板 2、管理存储桶&#xff08;1&#xff09;创建…

android 适配 api 35(android 15) 遇到的问题

首先升级 targetSdkVersion 和 compileSdkVersion 到 35&#xff0c;升级后发生的报错 一、 解决方案: 升级 gradle 和 gradle 插件版本 com.android.tools.build:gradle -> 8.3.0-alpha02 gradle-wrapper.properties : distributionUrl -> gradle-8.6-bin.zip htt…

【万字详细教程】Linux to go——装在移动硬盘里的Linux系统(Ubuntu22.04)制作流程;一口气解决系统安装引导文件迁移显卡驱动安装等问题

Linux to go制作流程 0.写在前面 关于教程Why Linux to go&#xff1f;实际效果 1.准备工具2.制作步骤 下载系统镜像硬盘分区准备启动U盘安装系统重启完成驱动安装将系统启动引导程序迁移到移动硬盘上 3.可能出现的问题 3.1.U盘引导系统安装时出现崩溃3.2.不影响硬盘里本身已有…

完美解决phpstudy安装后mysql无法启动

phpstudy数据库无法启动有以下几个原因。 **一、**自己在电脑上安装了MySQL数据库,MySQL的服务名为MySQL,这会与phpstudy的数据库的服务名发生冲突&#xff0c;从而造成phpstudy中的数据库无法启动&#xff0c;这时我们只需要将自己安装的MySQL的服务名改掉就行。 但是&#…

Class加载流程和运行时区域

目录 jvm是什么.class加载过程干预.class.class文件内容1 加载2-1 连接&#xff1a;验证&#xff08;class字节流的校验&#xff09;2-2 连接&#xff1a;准备&#xff08;分配内存&#xff0c;初始化默认值&#xff09;2-3 连接&#xff1a;解析3 class 初始化什么时候需要对类…

ESP32开发学习记录---》GPIO

she 2025年2月5日&#xff0c;新年后决定开始充电提升自己&#xff0c;故作此记,以前没有使用过IDF开发ESP32因此新年学习一下ESP32。 ESPIDF开发环境配置网上已经有很多的资料了&#xff0c;我就不再赘述&#xff0c;我这里只是对我的学习经历的一些记录。 首先学习一个…

pycharm集成通义灵码应用

在pycharm中安装通义灵码 1、打开files-settings 2、选中plugins-搜索”TONGYI Lingma“&#xff0c;点击安装 3.安装完成后在pycharm的右侧就有通义灵码的标签 4、登录账号 5、查看代码区域代码&#xff0c;每一个方法前面都多了通义灵码的标识&#xff0c;可以直接选择…

Git--使用教程

Git的框架讲解 Git 是一个分布式版本控制系统&#xff0c;其架构设计旨在高效地管理代码版本&#xff0c;支持分布式协作&#xff0c;并确保数据的完整性和安全性。 Git 的核心组件&#xff1a; 工作区&#xff08;Working Directory&#xff09;&#xff1a; 工作区是你在本…

力扣.270. 最接近的二叉搜索树值(中序遍历思想)

文章目录 题目描述思路复杂度Code 题目描述 思路 遍历思想(利用二叉树的中序遍历) 本题的难点在于可能存在多个答案&#xff0c;并且要返回最小的那一个&#xff0c;为了解决这个问题&#xff0c;我门则要利用上二叉搜索树中序遍历为有序序列的特性&#xff0c;具体到代码中&a…

7个国内能打开的AI绘画网站!新手福音!

以下是我收集的国内能打开的AI绘画网站。 1、6pen 网址&#xff1a;https://6pen.art/ 2、文心大模型 网址&#xff1a;https://wenxin.baidu.com/moduleApi/ernieVilg 3、Draft 网址&#xff1a;https://draft.art/ai- art/drawing 4、nightcafe 网址&#xff1a;https:/…

Redis数据库篇 -- Pipeline

一. 什么是Pipeline 在传统的请求-响应模式中&#xff0c;客户端与服务器之间的通信流程如下&#xff1a; 客户端发送一个命令到服务器。服务器接收命令并执行。服务器将执行结果返回给客户端。客户端接收结果后&#xff0c;发送下一个命令 在这种传统的模式下&#xff0c;…

Baumer工业相机堡盟相机的相机传感器芯片清洁指南

Baumer工业相机堡盟相机的相机传感器芯片清洁指南 Baumer工业相机1.Baumer工业相机传感器芯片清洁工具和清洁剂2.Baumer工业相机传感器芯片清洁步骤2.1、准备步骤2.2、清洁过程1.定位清洁工具2.清洁传感器3&#xff0e;使用吹风装置 Baumer工业相机传感器芯片清洁的优势设计与结…

【OS】AUTOSAR架构下的Interrupt详解(下篇)

目录 3.代码分析 3.1中断配置代码 3.2 OS如何找到中断处理函数 3.3 Os_InitialEnableInterruptSources实现 3.4 Os_EnableInterruptSource 3.5 DisableAllInterrupts 3.5.1Os_IntSuspendCat1 3.5.2 Os_InterruptDisableAllEnter 3.5.3 Disable二类中断 3.5.4 Disable一…

ASP.NET Core中间件Markdown转换器

目录 需求 文本编码检测 Markdown→HTML 注意 实现 需求 Markdown是一种文本格式&#xff1b;不被浏览器支持&#xff1b;编写一个在服务器端把Markdown转换为HTML的中间件。我们开发的中间件是构建在ASP.NET Core内置的StaticFiles中间件之上&#xff0c;并且在它之前运…

idea 找不到或者无法加载主类

idea项目&#xff0c;之前一直是正常运行的&#xff0c;放假了之后再回来就遇到启动不了的问题。 WebApplication这个类右键运行的时候&#xff0c;也提示找不到主类。 对于这种之前运行没有问题&#xff0c;突然出问题的项目。 我的点是没有改动代码和数据的情况下项目就跑不起…