百度360必应搜狗淘宝本站头条
当前位置:网站首页 > 技术资源 > 正文

Python自动化:Excel一键填充Word,自动格式调整!效率提升万倍

off999 2024-12-13 15:37 18 浏览 0 评论

在繁忙的职场中,你是否也遇到过这样的烦恼:辛苦整理完Excel数据后,还要手动复制到Word文档中,调整格式,甚至因为数据变更而忘记修改Word内容?今天,就让我们一起探索如何用Python自动化办公,将Excel中的数据一键填充到Word模板中,并且还能自动调整好格式!让工作更高效!



背景故事

小李是一家大型公司的中层管理,每天都需要汇总各种数据,并撰写报告给不同层级的领导。然而,数据汇总完毕后,他还需要花费大量时间将Excel中的数据复制到Word文档中,并调整格式。更糟糕的是,当Excel数据发生变更时,他很容易忘记修改对应的Word内容,导致报告出现错误,这个过程中最让他头疼的就是复制粘贴和格式调整的工作,机械地重复性工作渐渐消磨掉了他的激情和热情。

解决方案

为了解决小明的困扰,我们引入了Python自动化办公的解决方案。通过Python的强大功能,我们可以编写一个脚本,自动读取Excel中的数据,并填充到Word文档的对应表格中。同时,我们还能通过脚本自动调整Word文档的格式,确保生成的报告既准确又美观。

实战操作

此例要求将Excel档的“收货数据”填写到Word档的“收货记录”中去,并加总收货数量。模板是下面这样的,需要将Excel里面的信息插入到模板表里。

模板文档:

填充完模板后得到的理想结果:

Excel数据信息:


首先,从excel里提取数据

#从Excel表中提取数据
from openpyxl import load_workbook
wb = load_workbook("收货数据.xlsx")
ws = wb.active
data=[]
for row in range(2,ws.max_row+1):
    seq = ws["A"+str(row)].value
    supplier = ws["B"+str(row)].value
    material_pn = ws["C"+str(row)].value
    material_model = ws["D"+str(row)].value
    desp = ws["E"+str(row)].value
    qty = ws["F"+str(row)].value
    date = ws["G"+str(row)].value.date()
    info = [seq, supplier, material_pn, material_model, desp, qty, date]
    data.append(info)

检查一下提取到数据

其次,对数据进行相应的加总

#定义数量加总函数
def Sum_list(list):
    s = 0
    for i in list: #累加列表中的所有数
        s+=i
    return s


#加总数量列的所有数字
qty_list=[]
for i in data:
    qty_list.append(i[5]) #数量在内层列表的第6个位置,索引是5
sum_qty= Sum_list(qty_list) #调用加总函数加总
sum_qty

接着,调整格式,合并单元格等

def Merge_cells(table,target_list,start_row,col):
    '''
    table: 是需要操作的表格
    target_list: 是目标列表,即含有重复数据的列表
    start_row: 是开始行,即表格中开始比对数据的行(需要将标题除开)
    col: 是需要处理数据的列
    '''
    start = 0 #开始行计数
    end = 0 #结束行计数
    reference = target_list[0] #设定基准,以列表中的第一个字符串开始
    for i in range(len(target_list)): #遍历列表
        if target_list[i] != reference: #开始比对,如果内容不同执行如下
            reference = target_list[i] #基准变成列表中下一个字符串
            end = i - 1 
            table.cell(start+start_row,col).merge(table.cell(end+start_row,col))
            start = end + 1
        if i == len(target_list) - 1: #遍历到最后一行,按如下操作
            end = i
            table.cell(start+start_row,col).merge(table.cell(end+start_row,col))


然后,往word表格里按格式写入word里

#数据提取即处理完毕后,就可以往Word的表格中写入数据了
from docx import Document
doc = Document("收货记录模板.docx")
#读取word文档中的第一个表格的第二和第三列除标题和尾部总数行的数据
table = doc.tables[0] #已确定是第一个表格,其索引是0
supplier = [] #存储供应商名称
pn = [] #存储物料编码
for i in data:
    supplier.append(i[1])
    pn.append(i[2])
#按需增加行,以便填写数据
for i in range(len(supplier)): #模板中已经有一行了,所以总共只需增加len(supplier)行
    table.add_row() 
#增加好行后先做合并单元格操作
Merge_cells(table,supplier,1,1) #开始合并行为2,索引为1;供应商名称是在2列,索引为1
Merge_cells(table,pn,1,2) #开始合并行为2,索引为1;物料编码是在3列,索引为2


#写入数据到表格
for row in range(1,len(supplier)+1):
    for col in range(7):        
        table.cell(row,col).text = str(data[row-1][col])


max_row = len(table.rows) #获取最大一行
qty_row = max_row-1 #确定需要写入加总数据的一行
table.cell(qty_row,5).merge(table.cell(qty_row,5)) #合并右下角用于填写数量的两个单元格
table.cell(qty_row,4).text = '总数:'
table.cell(qty_row,5).text = str(sum_qty)


doc.save("收货记录.docx")

最后,对word里的表格进行格式处理

from docx.table import _Cell
from docx.oxml import OxmlElement
from docx.oxml.ns import qn


def Set_cell_border(cell: _Cell, **kwargs):
    """
    设置单元格边框函数
    使用方法:
    Set_cell_border(
        cell,
        top={"sz": 12, "val": "single", "color": "#FF0000", "space": "0"},
        bottom={"sz": 12, "color": "#00FF00", "val": "single"},
        start={"sz": 24, "val": "dashed", "shadow": "true"},
        end={"sz": 12, "val": "dashed"},
    )
    传入参数有cell, 即单元格;top指上边框;bottom指下边框;start指左边框;end指右边框。
    "sz"指线的粗细程度;"val"指线型,比如单线,虚线等;"color"指颜色,颜色编码可百度;
    "space"指间隔,一般不设置,设置的值大于0会导致线错开;"shadow"指边框阴影
    """
    tc = cell._tc
    tcPr = tc.get_or_add_tcPr()


    tcBorders = tcPr.first_child_found_in("w:tcBorders")
    if tcBorders is None:
        tcBorders = OxmlElement('w:tcBorders')
        tcPr.append(tcBorders)


    for edge in ('start', 'top', 'end', 'bottom', 'insideH', 'insideV'):
        edge_data = kwargs.get(edge)
        if edge_data:
            tag = 'w:{}'.format(edge)


            element = tcBorders.find(qn(tag))
            if element is None:
                element = OxmlElement(tag)
                tcBorders.append(element)


            for key in ["sz", "val", "color", "space", "shadow"]:
                if key in edge_data:
                    element.set(qn('w:{}'.format(key)), str(edge_data[key]))


#定义单元格填充颜色函数
from docx.oxml.ns import nsdecls
from docx.oxml import parse_xml
def Set_Background_Color(cell,rgbColor):
    shading_elm = parse_xml(r'<w:shd {} w:fill="{color_value}"/>'.format(nsdecls('w'),color_value = rgbColor)) #固定写法,照抄即可
    cell._tc.get_or_add_tcPr().append(shading_elm)


from docx.enum.text import WD_ALIGN_PARAGRAPH #设置水平居中对齐需要用到的库
from docx.enum.table import WD_ALIGN_VERTICAL #设置垂直居中对齐需要用到的库
from docx.shared import Cm # 长度单位(厘米cm用到的库)
from docx import Document


doc = Document("收货记录.docx") #打开word文件
table= doc.tables[0]
max_row = len(table.rows) #获取表格总行数


#1.最后一行中,“总数”两个字要加粗
run = table.cell(max_row-1,4).paragraphs[0].runs[0] # 获取最后一行第五列对应单元格中的文字块,即“总数”字样所在单元格
run.font.bold = True #将文字块设置为粗体


#2.最后一行的行高要调大一点,现在这样扁扁的,难看
table.rows[max_row-1].height = Cm(1) # 将最后一行的行高设置为1厘米


#3.最后一行那几个空单元格有框线,太碍眼,得去掉,将总数及左边两个cell左边框和下边框设成白色
for i in range(3):
    cell = table.cell(max_row-1,i)
    Set_cell_border(
            cell,
            bottom={"color": "#FFFFFF"},
            start={"color": "#FFFFFF" },
            end={"color": "#FFFFFF"}
        )


cell_1 = table.cell(max_row-1,3)
Set_cell_border(cell_1,start={"color": "#FFFFFF" },bottom={"color": "#FFFFFF"})


cell_2 = table.cell(max_row-1,6)
Set_cell_border(cell_2,end={"color": "#FFFFFF" },bottom={"color": "#FFFFFF"})


#4.各单元格水平和垂直方向都要居中对齐
for row in range(1,max_row):
    for col in range(len(table.columns)):
        table.cell(row,col).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
        table.cell(row,col).vertical_alignment = WD_ALIGN_VERTICAL.CENTER


#5.数量列≥85的,底色设置为橙色
qty = [] #存储数量信息
#读取第二行到29行,第2,3列中的数据
for i in range(1,max_row-1):
    qty_info = table.rows[i].cells[5].text #cells[5]指表格第6列
    qty.append(int(qty_info))


#将数量≥85的单元格填色
row=1 #行计数器
for i in qty:
    if i>=85:
        cell = table.cell(row,5) #第6列数据为数量,列索引是5
        Set_Background_Color(cell,"98F5FF") #填充颜色,"98F5FF"是蓝色的编码
    row+=1 #跳转到下一行      


doc.save("收货记录-整理.docx")



总结与展望

通过Python自动化办公,我们可以轻松实现Excel数据到Word文档的自动填充和格式调整。这不仅提高了工作效率,还减少了人为错误的可能性。未来,我们还可以进一步探索Python自动化办公的更多应用场景,如邮件自动发送、PPT自动制作等。让我们一起用技术改变生活,享受更加高效的工作体验吧!

关注公众号,私信“word"获取本篇文章的代码和示例数据。

相关推荐

Linux 网络协议栈_linux网络协议栈

前言;更多学习资料(包含视频、技术学习路线图谱、文档等)后台私信《资料》免费领取技术点包含了C/C++,Linux,Nginx,ZeroMQ,MySQL,Redis,fastdfs,MongoDB,Z...

揭秘 BPF map 前生今世_bpfdm

1.前言众所周知,map可用于内核BPF程序和用户应用程序之间实现双向的数据交换,为BPF技术中的重要基础数据结构。在BPF程序中可以通过声明structbpf_map_def...

教你简单 提取fmpeg 视频,音频,字幕 方法

ffmpeg提取视频,音频,字幕方法(HowtoExtractVideo,Audio,SubtitlefromOriginalVideo?)1.提取视频(ExtractVi...

Linux内核原理到代码详解《内核视频教程》

Linux内核原理-进程入门进程进程不仅仅是一段可执行程序的代码,通常进程还包括其他资源,比如打开的文件,挂起的信号,内核内部的数据结构,处理器状态,内存地址空间,或多个执行线程,存放全局变量的数据段...

Linux C Socket UDP编程详解及实例分享

1、UDP网络编程主要流程UDP协议的程序设计框架,客户端和服务器之间的差别在于服务器必须使用bind()函数来绑定侦听的本地UDP端口,而客户端则可以不进行绑定,直接发送到服务器地址的某个端口地址。...

libevent源码分析之bufferevent使用详解

libevent的bufferevent在event的基础上自己维护了一个buffer,这样的话,就不需要再自己管理一个buffer了。先看看structbufferevent这个结构体struct...

一次解决Linux内核内存泄漏实战全过程

什么是内存泄漏:程序向系统申请内存,使用完不需要之后,不释放内存还给系统回收,造成申请的内存被浪费.发现系统中内存使用量随着时间的流逝,消耗的越来越多,例如下图所示:接下来的排查思路是:1.监控系统中...

彻底搞清楚内存泄漏的原因,如何避免内存泄漏,如何定位内存泄漏

作为C/C++开发人员,内存泄漏是最容易遇到的问题之一,这是由C/C++语言的特性引起的。C/C++语言与其他语言不同,需要开发者去申请和释放内存,即需要开发者去管理内存,如果内存使用不当,就容易造成...

linux网络编程常见API详解_linux网络编程视频教程

Linux网络编程API函数初步剖析今天我们来分析一下前几篇博文中提到的网络编程中几个核心的API,探究一下当我们调用每个API时,内核中具体做了哪些准备和初始化工作。1、socket(family...

Linux下C++访问web—使用libcurl库调用http接口发送解析json数据

一、背景这两天由于一些原因研究了研究如何在客户端C++代码中调用web服务端接口,需要访问url,并传入json数据,拿到返回值,并解析。 现在的情形是远程服务端的接口参数和返回类型都是json的字符...

平衡感知调节:“系统如人” 视角下的架构设计与业务稳定之道

在今天这个到处都是数字化的时代,系统可不是一堆冷冰冰的代码。它就像一个活生生的“数字人”,没了它,业务根本转不起来。总说“技术要为业务服务”,但实际操作起来问题不少:系统怎么才能快速响应业务需求?...

谈谈分布式文件系统下的本地缓存_什么是分布式文件存储

在分布式文件系统中,为了提高系统的性能,常常会引入不同类型的缓存存储系统(算法优化所带来的的效果可能远远不如缓存带来的优化效果)。在软件中缓存存储系统一般可分为了两类:一、分布式缓存,例如:Memca...

进程间通信之信号量semaphore--linux内核剖析

什么是信号量信号量的使用主要是用来保护共享资源,使得资源在一个时刻只有一个进程(线程)所拥有。信号量的值为正的时候,说明它空闲。所测试的线程可以锁定而使用它。若为0,说明它被占用,测试的线程要进入睡眠...

Qt编写推流程序/支持webrtc265/从此不用再转码/打开新世界的大门

一、前言在推流领域,尤其是监控行业,现在主流设备基本上都是265格式的视频流,想要在网页上直接显示监控流,之前的方案是,要么转成hls,要么魔改支持265格式的flv,要么265转成264,如果要追求...

30 分钟搞定 SpringBoot 视频推拉流!实战避坑指南

30分钟搞定SpringBoot视频推拉流!实战避坑指南在音视频开发领域,SpringBoot凭借其快速开发特性,成为很多开发者实现视频推拉流功能的首选框架。但实际开发中,从环境搭建到流处理优...

取消回复欢迎 发表评论: