Python 挖坑式填充Excel模板内容(包括页眉/SheetName/logo)

纵览

Python处理Excel的方式--解压缩方式

在处理Excel中过程中,总是会遇到往已经存在的模板中填写特殊信息,一开始我使用的是常见的 openpyxl包,但是在我修改页眉中的字符时,发生页眉中的logo丢失现象,然后我就百度、ChatGPT搜索,最终找到了一种方法,那就是解压缩xlsx文件,然后修改内容,再进行压缩的方式实现修改内容的功能,利用的zipfile包,当然这个包应该是自带的吧,我使用的是Anaconda

1、导包

其中部分包没有用到

python 复制代码
import zipfile
import os
import shutil
from openpyxl import load_workbook
import pandas as pd

2、对模板文件进行解压缩

python 复制代码
# 模板Excel文件路径
excel_path = r'D:\MyPython\程序\模版.xlsx'
# 解压缩 Excel 文件
with zipfile.ZipFile(excel_path, 'r') as zip_ref:
	zip_ref.extractall('excel_temp')

3、对解压缩后文件层级进行介绍

运行上述代码,会在当前目录下,生成一个文件夹excel_temp,目录结构如下:

其中,主要关注的是xl文件夹里面的文件,文件内容意思如下:

路径 文件名 功能
excel_temp/xl/ sharedStrings.xml Excel中的所有单元格内容,除页脚、页眉外,所有的信息都在这里
excel_temp/xl/ workbook.xml sheetname修改位置
excel_temp/xl/worksheets/ styles.xml 修改单元格的样式
excel_temp/xl/worksheets/ sheet?.xml 页眉页脚修改区域修改位置,每个sheet对应1个文件
excel_temp/xl/drawings/_rels/ drawing1.xml.rels 页眉页脚修改区域修改位置,每个sheet对应1个文件图片路径的,如果模板中已经存在图片的,如果想要换个图标,可以通过覆盖下面的图片就行
excel_temp/xl/media/ image?.png 将新的文件覆盖掉对应的png文件就行,可以利用shutil.copy(替换图片路径,要被替换的路径)

4、准备需要载入的数据

替换模板数据,最重要的是先将你要替换的数据整理好,然后再在模板中相应的位置挖空,填充就行,我的数据格式是excel,如下:A列是替换名称,B到D列是数据,然后运行代码会生成填入B、C、D对应的数据的三个文件;

5、模板挖坑

打开模板文件,将需要替换的位置成相应的字符,比如:现在我想要替换发光点数量,输入发光点数量替换值,这个可以根据自己实际情况更换;

6、运行替换代码

excel_path是模板路径,soure_file数据文件;

python 复制代码
data_df = pd.read_excel(soure_file,sheet_name=0) #,usecols=[0,1]
# 将某一列(例如'index_column')设为索引
data_df.set_index('字段', inplace=True)
# 将DataFrame转换为字典
data_dict = data_df.to_dict()

# 删除值为NaN的键值对
data1_dict = {col: {index: value for index, value in data_dict[col].items() if pd.notna(value)} for col in data_dict}
# 修改页眉 文件
for keya in data1_dict.keys():
    # 解压缩 Excel 文件
    with zipfile.ZipFile(excel_path, 'r') as zip_ref:
        zip_ref.extractall('excel_temp')
    # 修改相关 XML 文件
    content_path = 'excel_temp/xl/sharedStrings.xml'
    workbook_path = 'excel_temp/xl/workbook.xml'
    for fm in os.listdir('excel_temp/xl/worksheets'):
        if '.xml' in fm:
            with open(f'excel_temp/xl/worksheets/{fm}', 'r+') as f:
                header_footer_xml = f.read()
                for key,value in data1_dict[keya].items():
                    header_footer_xml = header_footer_xml.replace(key+'替换值', str(value))
                f.seek(0)
                f.write(header_footer_xml)
                f.truncate()

    # 修改内容 文件
    with open(content_path, 'r+') as f:
        header_footer_xml = f.read()
        for key,value in data1_dict[keya].items():
            header_footer_xml = header_footer_xml.replace(key+'替换值', str(value))
        f.seek(0)
        f.write(header_footer_xml)
        f.truncate()

    # 修改类似:sheetname 这样的字符
    # 修改Sheetname文件
    with open(workbook_path, 'r+') as f:
        header_footer_xml = f.read()
        header_footer_xml = header_footer_xml.replace("SHEETNAME", data1_dict[keya]['SheetName'].replace('/',''))
        f.seek(0)
        f.write(header_footer_xml)
        f.truncate()

7、压缩文件

将修改后的文件,重新压缩,并且删除临时文件夹excel_temp

python 复制代码
# 重新压缩 Excel 文件
with zipfile.ZipFile(data1_dict[keya]['Name'].replace('/','')+'.xlsx', 'w') as zip_ref:
    for folder_name, subfolders, filenames in os.walk('excel_temp'):
        for filename in filenames:
            file_path = os.path.join(folder_name, filename)
            arcname = os.path.relpath(file_path, 'excel_temp')
            zip_ref.write(file_path, arcname)
# 删除临时文件夹
shutil.rmtree('excel_temp')

8、生成文件

运行完成后,会在当前目录下生成对应的文件,如果你想要放在其他路径可以修改data1_dict[keya]['Name'].replace('/','')+'.xlsx'这个位置的代码,利用os.path.join()进行路径拼接即可。

9、完成代码

文件存在关键信息,我就不展示了,代码如下:

python 复制代码
import zipfile
import os
import shutil
from openpyxl import load_workbook
import pandas as pd
# 修改页眉 文件
def get_file(excel_path, soure_file):
    data_df = pd.read_excel(soure_file,sheet_name=0) #,usecols=[0,1]
    # 将某一列(例如'index_column')设为索引
    data_df.set_index('序列', inplace=True)
    # 将DataFrame转换为字典
    data_dict = data_df.to_dict()

    # 删除值为NaN的键值对
    data1_dict = {col: {index: value for index, value in data_dict[col].items() if pd.notna(value)} for col in data_dict}

    for keya in data1_dict.keys():
        # 解压缩 Excel 文件
        with zipfile.ZipFile(excel_path, 'r') as zip_ref:
            zip_ref.extractall('excel_temp')
        # 修改相关 XML 文件
        content_path = 'excel_temp/xl/sharedStrings.xml'
        workbook_path = 'excel_temp/xl/workbook.xml'
        for fm in os.listdir('excel_temp/xl/worksheets'):
            if '.xml' in fm:
                with open(f'excel_temp/xl/worksheets/{fm}', 'r+') as f:
                    header_footer_xml = f.read()
                    for key,value in data1_dict[keya].items():
                        header_footer_xml = header_footer_xml.replace(key+'替换值', str(value))
                    f.seek(0)
                    f.write(header_footer_xml)
                    f.truncate()

        # 修改内容 文件
        with open(content_path, 'r+') as f:
            header_footer_xml = f.read()
            for key,value in data1_dict[keya].items():
                header_footer_xml = header_footer_xml.replace(key+'替换值', str(value))
            f.seek(0)
            f.write(header_footer_xml)
            f.truncate()

        # 修改类似:这样的字符
        # 修改Sheetname文件
        with open(workbook_path, 'r+') as f:
            header_footer_xml = f.read()
            header_footer_xml = header_footer_xml.replace("SHEETNAME", data1_dict[keya]['SheetName'].replace('/',''))
            f.seek(0)
            f.write(header_footer_xml)
            f.truncate()
        # 重新压缩 Excel 文件
        with zipfile.ZipFile(data1_dict[keya]['产品类别'].replace('/','')+'.xlsx', 'w') as zip_ref:
            for folder_name, subfolders, filenames in os.walk('excel_temp'):
                for filename in filenames:
                    file_path = os.path.join(folder_name, filename)
                    arcname = os.path.relpath(file_path, 'excel_temp')
                    zip_ref.write(file_path, arcname)
        # 删除临时文件夹
        shutil.rmtree('excel_temp')
excel_path = r'D:\MyPython\程序\Nan_Czy\流程单自动生成\模版.xlsx'
soure_file = r'D:\MyPython\程序\Nan_Czy\流程单自动生成\关键信息清单.xlsx'
get_file(excel_path, soure_file)

10、可能遇到的问题

  • 读取文件存在问题,需要在对应位置加上:encoding='utf-8'
  • 打开文件失败,肯定是替换的字符存在问题,需要一一排查;

结语

好的,本次遇到的问题已经解决并且记录下来了,希望能够帮助你!

相关推荐
Theodore_10222 小时前
4 设计模式原则之接口隔离原则
java·开发语言·设计模式·java-ee·接口隔离原则·javaee
网易独家音乐人Mike Zhou3 小时前
【卡尔曼滤波】数据预测Prediction观测器的理论推导及应用 C语言、Python实现(Kalman Filter)
c语言·python·单片机·物联网·算法·嵌入式·iot
安静读书3 小时前
Python解析视频FPS(帧率)、分辨率信息
python·opencv·音视频
----云烟----4 小时前
QT中QString类的各种使用
开发语言·qt
lsx2024064 小时前
SQL SELECT 语句:基础与进阶应用
开发语言
小二·4 小时前
java基础面试题笔记(基础篇)
java·笔记·python
开心工作室_kaic5 小时前
ssm161基于web的资源共享平台的共享与开发+jsp(论文+源码)_kaic
java·开发语言·前端
向宇it5 小时前
【unity小技巧】unity 什么是反射?反射的作用?反射的使用场景?反射的缺点?常用的反射操作?反射常见示例
开发语言·游戏·unity·c#·游戏引擎
武子康5 小时前
Java-06 深入浅出 MyBatis - 一对一模型 SqlMapConfig 与 Mapper 详细讲解测试
java·开发语言·数据仓库·sql·mybatis·springboot·springcloud
转世成为计算机大神5 小时前
易考八股文之Java中的设计模式?
java·开发语言·设计模式