Python自动化小技巧19——复制excel表放入word

案例背景

依旧是工作需要,文员工作就是这样,写各种报告,周报月报季报半年报。报告需要数据,数据在excel里面,每天都是复制粘贴....贼重复和枯燥,主要还费时间费神。

能自动化的尽量用代码去简化吧。比如我每次周报写在excel里面,然后又要复制到word里面去,还要排版什么的很麻烦。

流程都是固定的,所以代码来封装。下面来看看我这个案例。


明确要求

数据肯定是放在excel里面的,先填好,然后按照模板文字套,表里面很多sheet大概是这样:

 

 汇总1和汇总2就是我们填入每周的数据,然后写到后面具体的每周的周报里面去。每周的周报文字都是有模板的。

例如我的文字模板:

( 打码是怕信息泄露)

下面还有别的栏目,本周工作总结,工作计划什么的,都是一样,在代码里面字符串进行模板化套用,然后对着固定的格子修改就行。

因为不是从0开始写周报,是复制上一期的周报然后把这周的内容进行替换,不用代码手工写周报也是这么一个操作流程。我们用代码只是为了让这个重复的的流程简化而已。


代码实现

excel套模板
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt 
import seaborn as sns

plt.rcParams ['font.sans-serif'] ='SimHei'               #显示中文
plt.rcParams ['axes.unicode_minus']=False               #显示负号
import re
import openpyxl
information_row=28
datetime='8.7-8.13'
row_n=17           #周会材料要填的行

初始化一些参数,比如你数据放在excel表的哪一行,这周报日期是从哪一天到哪一天,还有周会材料写在表的第几行。 

读取excel一行的数据,这一行的数据就是本周的实际数据,我等下套模板里面去改的数据

wb = openpyxl.load_workbook('./周报/周报.xlsx',data_only=True)
ws = wb['汇总1']
rows = ws.iter_rows(min_row=information_row, max_row=information_row, min_col=2, max_col=25,values_only=True)
# 遍历每一行,并获取每个单元格的值
for row in rows:
    result1=list(row)
len(result1)

 24个数据,我把他们都拆卡命名:

(合同1,合同2,合同3,市场1,市场2,市场3,营业1,营业2,营业3,利润1,利润2,利润3,投资1,投资2,外营收1,外营收2,
外营收3,外利润1,外利润2,外利润3,应收账1,应收账2,应收账回1,应收账回2)=result1

套入模板:

text=f'''一、生产经营情况:本周及本年投资、营收、净利润、合同签约额、销售签约额、应收账款、应收账款回款额等关键指标增速、目标达成率等。
1、合同承接额:本周完成合同承接额{合同1:.3f}亿元,全年累计完成合同承接额{合同2:.2f}亿元,占年度目标15亿元的{合同3:.1f}%。
2、市场化业务承接额:本周完成集团外合同承接额{市场1:.2f}亿元,全年累计完成合同承接额{市场2:.2f}亿元,占年度目标15亿元的{市场3:.1f}%。
3、营业收入:本周完成营收{营业1:.2f}亿元,全年累计完成营收{营业2:.2f}亿元,占年度目标15亿元的{营业3:.2f}%。
4、净利润:本周实现净利润{利润1:.1f}万元,全年累计实现净利润{利润2:.1f}万元,占年度目标0.32亿元的{利润3:.1f}%。
5、投资额:本周完成投资额{投资1:.1f}亿元,全年累计完成投资额{投资2:.1f}亿元。
6、集团外营收:本周完成营收{外营收1*10000:.2f}万元,全年累计完成集团外营收{外营收2:.2f}亿元,占年度目标2亿元的{外营收3:.1f}%。
7、集团外净利润:本周完成{外利润1:.2f}万元,全年累计实现集团外净利润{外利润2:.2f}万元,占年度目标300万元的{外利润3:.1f}%。
8、应收账款:本周新增应收账款额{应收账1:.1f}万元,全年累计应收账款{应收账2:.1f}万元。
9、应收账款回款额:本周应收账款回款额{应收账回1:.1f}万元,全年累计应收账款回款额{应收账回2:.1f}万元。\n'''

把上一周的sheet周报读进来,然后复制一下为这周,修改sheet名称为本周时间,修改内容:

wb2 = openpyxl.load_workbook('./周报/周报.xlsx')
ws1 = wb2['7.10-7.16']
ws2 = wb2.copy_worksheet(ws1)
ws2.title = datetime
# 写入值到指定单元格
ws2.cell(row=3, column=2, value=text)

把第一行的日期也改一下:

ws2['A1'].value
a,b,c,d=ws2.title.replace('-','.').split('.')
ws2.cell(row=1, column=1, value=f'周重点工作事项通报表\n(2023年{a}月{b}日-{c}月{d}日)')

后面需要改的也进行一定的修改:

重点工作='''四、重点工作进展及亮点:本周开展的重点工作及亮点。   
项目保供:1、确料保供工作。
          2、保证各项材料供应。
市场开拓:1.完有限公司走访。
          2.完成贵编制工作。
          3.完成划分。
生产经营:1.接营公司认可;
          2.当枝行预验收;
          3.汉江目投标。'''
ws2.cell(row=6, column=2, value=重点工作)

内容我删了一部分,防止信息泄露。然后保存就行了。

# 保存 Excel 文件
wb2.save('周报.xlsx')

excel一个sheet复制到word里面去

我们刚刚这个表wb2是这周的周报,已经写入了excel里面了,但是我们还需要单独出一个word版,所以我们需要对这个表原封不动的放入word里面。

下面是我的代码,原封不动是很难的,因为样式,字体,表格高宽根本没办法挪过去的时候保持一致,只能按照下面这个代码思路来,先在word里面生产一个行和列数和wb2一样的表格,然后再遍历每一个格子填进去。

from docx.enum.section import WD_ORIENT
from docx import Document
from docx.shared import Cm, Pt
from docx.enum.table import WD_TABLE_ALIGNMENT, WD_ALIGN_VERTICAL
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml import OxmlElement
from docx.oxml.ns import qn

# 创建 Word 文档和表格对象
doc = Document()
doc.styles['Normal'].font.name = '仿宋_GB2312'
doc.styles['Normal'].font.size = Pt(11)
table = doc.add_table(rows=ws2.max_row, cols=ws2.max_column)
# 将 Excel 表格复制到 Word 表格中
for i, row in enumerate(ws2.iter_rows()):
    for j, cell in enumerate(row):
        table.cell(i, j).text = str(cell.value)

我这里还设置了页面方向和页边距,表格框线:

# 设置页面方向为横向
section = doc.sections[0]
new_width, new_height = section.page_height, section.page_width
section.orientation, section.page_width, section.page_height = \
    WD_ORIENT.LANDSCAPE, new_width, new_height
#页边距
section.top_margin = Cm(0.5)
section.bottom_margin = Cm(0.5)
section.left_margin = Cm(1.25)
section.right_margin = Cm(1.25)

# 设置表格框线
for row in table.rows:
    for cell in row.cells:
        for paragraph in cell.paragraphs:
            for run in paragraph.runs:
                run.font.name = '仿宋_GB2312'
                run.font.size = Pt(11)
                r = run._element.rPr.rFonts
                r.set(qn("w:eastAsia"),"仿宋_GB2312")
                tc = cell._element
                tcPr = tc.get_or_add_tcPr()
                tcBorders = OxmlElement('w:tcBorders')
                top = OxmlElement('w:top')
                top.set(qn('w:val'), 'single')
                top.set(qn('w:sz'), '4')
                tcBorders.append(top)
                bottom = OxmlElement('w:bottom')
                bottom.set(qn('w:val'), 'single')
                bottom.set(qn('w:sz'), '4')
                tcBorders.append(bottom)
                left = OxmlElement('w:left')
                left.set(qn('w:val'), 'single')
                left.set(qn('w:sz'), '4')
                tcBorders.append(left)
                right = OxmlElement('w:right')
                right.set(qn('w:val'), 'single')
                right.set(qn('w:sz'), '4')
                tcBorders.append(right)
                tcPr.append(tcBorders)

我上面代码其实设置了字体样式和大小的,但是我发现无效....只能继续使用我们自定义的样式函数了:

def set_style(paragraphs,style=u'仿宋_GB2312',size=16):
    for run in paragraphs.runs:
        run.font.name = style
        run.font.size = Pt(size)
        r = run._element.rPr.rFonts
        r.set(qn("w:eastAsia"),style)

然后我发现格子的高宽都是默认值,有的单元格还没合并,有的空白行不需要,所以我进行了下面的操作。(这些操作不是必要的,看你的报告需要什么格式就进行调整,可以模仿)

首先设置表格的高和宽:

#doc = Document('周test.docx')
table = doc.tables[0]
for cell in table.columns[0].cells:
    cell.width = Cm(1.95)
for cell in table.columns[1].cells:
    cell.width = Cm(23.5)

 然后设置第一行,也是标题进行合并居中,设置字体为黑体小三。


# Merge the first two cells in the first row 
cell_1 = table.cell(0, 0)
cell_2 = table.cell(0, 1)
cell_1.merge(cell_2)
cell_1.text = cell_1.text.replace('None', '').replace('\n', '')
# 设置字体
for paragraph in cell_1.paragraphs:
    paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    set_style(paragraph,u'黑体',16)

 对我们的第二行,表头进行居中设置,段前断后0行距,黑体11号大小


# 居中,单倍行距段前段后0,设置样式
for cell in table.row_cells(1):
    for paragraph in cell.paragraphs:
        paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
        paragraph.paragraph_format.space_before = Pt(0)
        paragraph.paragraph_format.space_after = Pt(0)
        set_style(paragraph,u'黑体',11)
        #for run in paragraph.runs:
#             run.bold = False
#             r = run._element.rPr.rFonts
#             r.set(qn("w:eastAsia"),"黑体")  

 对我们最左边的一列,从第三行开始进行单元格合并,然后去空白,垂直水平,每一段都水平居中,设置字体样式和大小

            
#合并,去掉none,居中,设置字体
merged_cell = table.cell(2, 0).merge(table.cell(7, 0))
merged_cell.text = merged_cell.text.replace('None', '').replace('\n', '')
merged_cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER

for paragraph in merged_cell.paragraphs:
    paragraph.alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
    set_style(paragraph,u"仿宋_GB2312",11)

 然后删除中间这两个里面的换行符,也就是空白行,设置一下样式,然后保存,就完成啦

#去空白
for cell in [table.cell(3, 1),table.cell(4, 1),table.cell(7, 1)]:
    cell.text = cell.text.replace('\n', '')
    for paragraph in cell.paragraphs:
        set_style(paragraph,u"仿宋_GB2312",11)
doc.save('周报.docx')

 


还没结束....领导还说这个工作计划和工作任务都要写入另外一个材料表,后面还有一个周例会材料,说白了就是把16行的内容复制到17行去,然后修改为本周的实际情况,我发现openpyxl在这里会出问题,会把前面的写好的样式都改了....所以这里使用了 xlwings库。可以不用看,我放上去是给个演示。

import xlwings as xw
book = xw.Book('./周报/周例会材料(**公司).xlsx')
sheet = book.sheets[0]

# 从第15行复制值到第16行,列从 A 到 I
for col in ["A", "B", "C", "D", "E", "F", "G", "H", "I"]:
    cell_to_copy = f"{col}{row_n-1}"
    destination_cell = f"{col}{row_n}"
    sheet.range(destination_cell).value = sheet.range(cell_to_copy).value

#要改的内容
营收情况=f'本周完成营收{营业1*10000:.0f}万元,全年累计完成营收{营业2*10000:.0f}万元'
重点工作1=重点工作.split('\n', 1)[1].replace(' ', '')
重点工作1=re.sub(r'\n(\d)', r'\1', 重点工作1)
近期计划1=近期计划.split('\n', 1)[1].replace(' ', '')
近期计划1=re.sub(r'\n(\d)', r'\1', 近期计划1).replace('其他内容', '其他工作')

#修改
sheet.range(f'C{row_n}').value = 营收情况
sheet.range(f'F{row_n}').value = 重点工作1
sheet.range(f'G{row_n}').value = 近期计划1
sheet.range(f'I{row_n}').value = datetime

#设置字体样式
sheet.range(f'F{row_n}').api.Font.Bold = False
sheet.range(f'G{row_n}').api.Font.Bold = False  #cell.api.Font.Name = '宋体'   cell.api.Font.Size = 10

#保存
book.save('周例会材料(远大公司).xlsx')
book.close()

  • 2
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

阡之尘埃

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值