作品展示——docx台账汇总,每页20条
背景需求:
近期上级要求“一屏一码”,幼儿园每个电子屏使用后都要进行开机、关机的记录。安全主任分配工作后,每个园区的每个电子屏都有专人负责登记。
为了便于每月末的台账提交(只要电子版),我设计了一个问卷星的提交系统。
从3月1日开始到3月29日,总部的三位老师都是通过问卷星填写电子屏使用台账。
-----------------------------------------------------------------------------------------------------------------------
今天是4月4日,安全主任要求各园区提交电子版台账。
于是我开始用Python设计一款自动从EXCLE里调取数据,填写word模板的代码
1、制作docx模板
模板是XLSX格式,并不便于A4打印,因此我把内容复制到docx,制作word模板。
2、从问卷星下载xls
下载一份xlsx
有许多的内容
删除不是3月的内容
内容分析:
1、需要G:W列的内容。但不需要“跳过”的内容
2、读取的所有内容,拆分7个一组(一行7个内容)
3、判断一共有几个7元素组,答案是66个,它在60-80的范围内,因此80-66=14,还缺14个空格子组成的7组:
4、把提取出来的内容进行拆分或合并
(1)如果格子里面有空,就添加7个空
(2)其他情况下,需要拆分(黄色拆分)和合并(蓝色部分)
5、把80*7个修订过的元素集合,再次拆分成4份(一页20行*7个元素)
6、读取一个有页码的横版模板,作为Word合并时的模板
7、为Word合并后第一行会有空行(页码模板自带),需要删除
整体代码
'''
电子屏台账2024年3月,docx,每页20条
作者:AI对话大师
时间:2024年4月3日
'''
print('----1、读取EXCEL内容并合并成关键列表------')
month=int(input('几月?\n'))
import os
import pandas as pd
folder_path = r'C:\Users\jg2yXRZ\OneDrive\桌面\电子屏每月'
file_name = '256967506_按文本_Jg2y各园部重点部位电子屏、播控系统_71_71.xlsx'
file_path = os.path.join(folder_path, file_name)
# 按列读取
# df = pd.read_excel(file_path)
# columns = df.columns[6:23] # G列到W列的列索引范围
# all_data = []
# for column in columns:
# column_data = df[column].tolist()
# all_data.extend(column_data)
# print(all_data)
# 按行读取
df = pd.read_excel(file_path)
rows = df.iloc[:, 7:21].values.tolist() # G列到W列的数据,按行转换为列表
all_data = []
for row in rows:
row_data = [cell for cell in row if not pd.isnull(cell)and cell != '(跳过)']
all_data.extend(row_data)
print(all_data)
print(len(all_data))
# 462
print('----1、读取EXCEL内容并合并成关键列表------')
import pandas as pd
df = pd.read_excel(file_path)
num_rows = df.shape[0]
print("行数:", num_rows)
#66
# 每行有几个内容
h=int(len(all_data)/num_rows)
print(h)
# # 拆分成7个一组
nested_lists = [all_data[i:i+h] for i in range(0, len(all_data), h)]
print(nested_lists)
print(len(nested_lists))
# # 66
# 判断是否能够凑满20行,凑不满,补空
for z in range(20,220,20):
if z <= len(nested_lists)<z+20:
print(f"{len(nested_lists)} 在范围 {z}-{z+20} 内")
# 补多少的空格
kong=z+20-len(nested_lists)
print(kong)
# 一个列表里面有7个空
w = [''] * h
# 需要14个这种7空的嵌套列表
v = [w] * kong
print(v)
# 把实际的填写内容+补充的空格,凑满20的倍数页
nested_lists=nested_lists+v
print(nested_lists)
print(len(nested_lists))
# 80
# 拆分合并每个格子的内容
new=[]
for n in range(len(nested_lists)): # 66行
# 如果读取的第一个内容为空
if nested_lists[n][1]=='':
for g in range(h):
new.append('')
else:
# 添加序号不用加0
new.append(n+1)
# 电子屏ID '总园 校门口电子屏 402XXXXXXXX TY2021XXXXXX'
split_list = nested_lists[n][1].split(' ')
print(split_list)
# 将空格切开变成列表
new.append(split_list[2])
# 资产编号
new.append(split_list[3])
# 时间 (日期+时间
new.append(nested_lists[n][2][:4]+'年'+nested_lists[n][2][5:7]+'月'+ \
nested_lists[n][2][-2:]+'日'+str(nested_lists[n][3])+':'+str('%02d'%nested_lists[n][4]))
# 操作内容
new.append(nested_lists[n][5])
# 进出人员 (负责人)
new.append(nested_lists[n][0])
# 审核领导(园所管理主任)
new.append(nested_lists[n][6])
print(new)
print(len(new))
# 560 /7/20=4页
print('----2、读取docx模板的数量------')
# 读取word的行列数
from docx import Document
doc_name = '电子屏台账模板.docx'
doc_path = os.path.join(folder_path, doc_name)
# 打开文档
doc = Document(doc_path)
# 获取第一个表格
table = doc.tables[0]
# 获取表格的行数和列数
num_rows = len(table.rows)
num_cols = len(table.columns)
print("行数:", num_rows)
# 22
print("列数:", num_cols)
# 7
# 每页格子的坐标
bg=[]
for a in range(2,22):
for b in range(7):
bg.append('{}{}'.format('%02d'%a,'%02d'%b))
print(bg)
print(len(bg))
# 140
# 拆分成4页每页20个个一组
c=int(len(new)/4)
content_lists = [new[i:i+c] for i in range(0, len(new), c)]
print(content_lists)
print(len(content_lists))
# 4 拆20行内容一组,一共4个嵌套列表
# 列表new内容写入docx模板,第一页写入20行*7的内容
import os,time
from docx import Document
from docx.shared import Pt, RGBColor
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT
from docx.oxml.ns import qn
from docx2pdf import convert
from PyPDF2 import PdfMerger
# 多少份(必须双数)
ziti = '宋体'
size = 14
imagePath = folder_path+r'\零时Word'
if not os.path.exists(imagePath):
os.makedirs(imagePath)
for n in range(len(content_lists)):
doc = Document(doc_path)
# for b in range(0):
table = doc.tables[0]
for t in range(len(bg)):
pp, qq, k = int(bg[t][0:2]), int(bg[t][2:4]), content_lists[n][t]
run = table.cell(pp, qq).paragraphs[0].add_run(str(k))
run.font.name = ziti
run.font.size = Pt(size)
run.bold = False
run.font.color.rgb = RGBColor(0, 0, 0)
r = run._element
r.rPr.rFonts.set(qn('w:eastAsia'), ziti)
table.cell(pp, qq).paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER
doc.save(imagePath+fr'\{n:02d}.docx')
time.sleep(2)
print('-----3、创建一个带页码的docx,合并word模板------')
from docx import Document
from docx.enum.section import WD_SECTION_START
import os
from docx.shared import Cm
# # 创建一个带页码的空Document对象,并把页眉页脚边距改小
source_dir = imagePath # 文件夹路径
combined_doc = Document(folder_path+r'\页码.docx')
# 读取“整理”里面的docx的内容
docx_files = []
for file_name in os.listdir(source_dir):
if file_name.endswith(".docx"):
docx_files.append(os.path.join(source_dir, file_name))
for file in docx_files:
doc = Document(file)
for element in doc.element.body:
combined_doc.element.body.append(element)
output_file = folder_path + fr'\2024年{month}月(总园)电子屏台账.docx' # 输出文件路径
combined_doc.save(output_file)
print('-----4、把“合并docx"的第一段回车删除。(页码模板自带)---')
doc = Document(output_file)
# 删除第1个段落(都只有一个回车)
for i in [0,1]:
dell_paragraph = doc.paragraphs[i]
doc._element.body.remove(dell_paragraph._element)
doc.save(output_file)
time.sleep(3)
# 删除word临时文件夹
import shutil
shutil.rmtree(imagePath)
终端运行:
20*4页(实际66个)
把零食Word里面的四分内容合并在一个docx内,删除”零食文件夹“
作品展示
第1页
第2页
第4页
合并样式展示
感悟:
1、以后每月末,下载问卷星的xlsx,删除非当月的内容,用代码生成当月的“电子屏台账”
2、目前代码只包含“总园台账”,分园电子屏数量比总园少,因而负责人自己手动填写电子台账,没有扫码登记在问卷星里。后续继续探索三个园区,三个台账的制作方法