【办公类-109-06】20250824一分园“国旗下讲话”批量模板(托班小班4周轮流1次)

背景需求:

新搭档是“语言文字”工作负责人,未开学就发布了“国旗下讲话”的模板。

发言班级安排表

班主任填写模板

 

之前我长期在总园带班,总园班级多(10个以上),一学期最多轮到3次,所以就直接做了。

但是到了一分园只有4个班,就是4周轮到一次,一共5次。频率很高。(二分园也只有4个班)

既然图表里已有周次、日期、发言题目、轮值院长、班级的信息,为什么不用python的模板写入方式把模板都做好,样式规范统一。

 

一、制作excle表:把word里面的表格复制到excle内,拆分表格,修改英文标题、更改日期形式,添加班主任

周次week,从汉字变成数字,拖拉变成数字日期

 

日期date,原来是9月8日(只有年月),把一列复制到deepseek,让它改成年.月.日的格式

 

班主任teachers:手动复制教工名单

 

行政老师leader +班级classroom ,复制到AI,拆分成表格形式两列

虽然没有孩子,但是标题写上student1-student6,

 

二、word模板修改

1、把基础信息填好,学生所在位置留好,

2、教师讲话内容只留一行,黏贴文字后表格自然会变长

3、活动掠影只留一行,插入两张照片后表格自然会变长

三、编程代码(4份)

把安排表和模板和以前的一份“python模板插入代码”放入AI编程

代码展示1.0



'''
国旗下讲话模板批量01 没有学生名字
deep seek 、阿夏
20250824
'''
import pandas as pd
from docxtpl import DocxTemplate
import os
from docx import Document
 
# 设置路径
zpath = r'C:Usersjg2yXRZOneDrive桌面202509一分院 国旗下讲话'
temp = zpath + r'模版'
os.makedirs(temp, exist_ok=True)
 
# 读取安排表x
schedule = pd.read_excel(zpath + '模版国旗下的讲话总安排(一分部) 2025.9.xlsx')
 
# 首先检查模板文件是否存在且是有效的Word文件
template_path = zpath + '模板一分园(小 1 班)国旗下的讲话(第 2 周).docx'
 
if not os.path.exists(template_path):
    print(f"错误:模板文件不存在 - {template_path}")
    exit()
 
try:
    # 尝试打开模板文件检查是否有效
    doc = Document(template_path)
    print("模板文件检查通过,开始生成文档...")
except Exception as e:
    print(f"模板文件无效: {e}")
    print("请确保模板文件是有效的Word文档 (.doc 或 .docx)")
    exit()
 
# 遍历安排表的每一行
for index, row in schedule.iterrows():
    try:
        # 每次重新读取模板,确保每次都是干净的模板
        tpl = DocxTemplate(template_path)
        
        # 构建上下文数据
        context = {
            "date": str(row['date']),  # 确保日期是字符串
            "week": str(row['week']),
            "teachers": str(row['teachers']),
            "classroom": str(row['classroom']),
            "topic": str(row['topic']),
            "leader": str(row['leader']),
            "s1": str(row['s1']) if pd.notna(row['s1']) else "",
            "s2": str(row['s2']) if pd.notna(row['s2']) else "",
            "s3": str(row['s3']) if pd.notna(row['s3']) else "",
            "s4": str(row['s4']) if pd.notna(row['s4']) else "",
            "s5": str(row['s5']) if pd.notna(row['s5']) else ""
        }
        
        # 渲染模板
        tpl.render(context)
        
        # 保存文件,文件名包含周次和班级信息
        filename = f"国旗下的讲话_{row['week']}_{row['classroom']}.docx"
        full_path = os.path.join(temp, filename)
        tpl.save(full_path)
        
        print(f"已生成: {filename}")
        
    except Exception as e:
        print(f"生成第{index+1}行数据时出错: {str(e)}")
        continue
 
print("所有文档生成完成!")

 

除了孩子名字是空的,其他时间、班级、周次、班主任、行政、主题内容都有了

 

 

那么5个学生的名单怎么插入?把我收集的22个班级点名册放入文件夹里。

把班级信息表excle和之前的excle都上传,并在刚才可质性代码最后写上如何提取小班孩子的信息(都是25人,正好轮5次,每次就拆分5人)

运行后报错,我发现一分院是2个托班(每班20人),2个小班(每班25人)

代码展示2.0(只抽小1-2、托1-2)



'''
国旗下讲话模板批量02 随机抽取5个一组的孩子名字
deep seek 、阿夏
20250824
'''
 
import pandas as pd
from docxtpl import DocxTemplate
import os
from docx import Document
import numpy as np
 
# 设置路径
zpath = r'C:Usersjg2yXRZOneDrive桌面202509一分院 国旗下讲话'
temp = zpath + r'模版'
os.makedirs(temp, exist_ok=True)
 
# 读取班级信息表
class_info_path = zpath + '班级信息表.xlsx'
class_info = pd.read_excel(class_info_path, sheet_name=None)  # 读取所有工作表
 
# 读取安排表
schedule_path = zpath + '模版国旗下的讲话总安排(一分部) 2025.9.xlsx'
schedule = pd.read_excel(schedule_path)
 
# 确保s1-s5列是字符串类型
for col in ['s1', 's2', 's3', 's4', 's5']:
    if col in schedule.columns:
        schedule[col] = schedule[col].astype(str)
        # 将"nan"转换为空字符串
        schedule[col] = schedule[col].replace('nan', '')
 
# 为每个班级创建学生姓名分组(托班4人一组,小班5人一组)
class_groups = {}
for sheet_name, df in class_info.items():
    if sheet_name not in ['模板'] and '班' in sheet_name:  # 跳过模板表,只处理班级表
        # 过滤掉空姓名
        students = df[df['姓名'].notna()]['姓名'].tolist()
        
        # 根据班级类型确定每组人数
        if '托' in sheet_name:
            # 托班:4人一组
            group_size = 4
        elif '小' in sheet_name:
            # 小班:5人一组
            group_size = 5
        else:
            # 其他班级默认5人一组
            group_size = 5
        
        # 按指定人数分组
        groups = [students[i:i+group_size] for i in range(0, len(students), group_size)]
        class_groups[sheet_name] = groups
        print(f"班级 {sheet_name}: {len(students)} 名学生,分成 {len(groups)} 组(每组{group_size}人)")
 
# 更新安排表中的学生姓名
for index, row in schedule.iterrows():
    classroom = row['classroom']
    # 将"小1班"转换为"小1班"格式(去掉括号)
    clean_classroom = classroom.replace('(', '').replace(')', '')
    
    if clean_classroom in class_groups:
        groups = class_groups[clean_classroom]
        # 使用循环分组,如果组数不够就从头开始
        group_index = index % len(groups)
        students = groups[group_index]
        
        # 更新安排表
        for i in range(5):  # s1-s5最多5个位置
            col_name = f's{i+1}'
            if i < len(students):
                schedule.at[index, col_name] = students[i]
            else:
                schedule.at[index, col_name] = ""
 
# 保存更新后的安排表
updated_schedule_path = zpath + '模版国旗下的讲话总安排(一分部) 2025.9_已填充.xlsx'
schedule.to_excel(updated_schedule_path, index=False)
print(f"已保存更新后的安排表: {updated_schedule_path}")
 
# 现在使用更新后的安排表生成文档
# 首先检查模板文件是否存在且是有效的Word文件
template_path = zpath + '模板一分园(小 1 班)国旗下的讲话(第 2 周).docx'
 
if not os.path.exists(template_path):
    print(f"错误:模板文件不存在 - {template_path}")
    exit()
 
try:
    # 尝试打开模板文件检查是否有效
    doc = Document(template_path)
    print("模板文件检查通过,开始生成文档...")
except Exception as e:
    print(f"模板文件无效: {e}")
    print("请确保模板文件是有效的Word文档 (.doc 或 .docx)")
    exit()
 
# 遍历安排表的每一行生成文档
for index, row in schedule.iterrows():
    try:
        # 每次重新读取模板,确保每次都是干净的模板
        tpl = DocxTemplate(template_path)
        
        # 格式化班级名称(小1班 -> 小(1)班)
        classroom_str = str(row['classroom'])
        if len(classroom_str) >= 3:
            formatted_classroom = f"{classroom_str[0]}({classroom_str[1]}){classroom_str[2:]}"
        else:
            formatted_classroom = classroom_str
        
        # 构建上下文数据
        context = {
            "date": str(row['date']),
            "week": str(row['week']),
            "teachers": str(row['teachers']),
            "classroom": formatted_classroom,
            "topic": str(row['topic']),
            "leader": str(row['leader']),
            "s1": str(row['s1']) if pd.notna(row['s1']) and str(row['s1']) != 'nan' else "",
            "s2": str(row['s2']) if pd.notna(row['s2']) and str(row['s2']) != 'nan' else "",
            "s3": str(row['s3']) if pd.notna(row['s3']) and str(row['s3']) != 'nan' else "",
            "s4": str(row['s4']) if pd.notna(row['s4']) and str(row['s4']) != 'nan' else "",
            "s5": str(row['s5']) if pd.notna(row['s5']) and str(row['s5']) != 'nan' else ""
        }
        
        # 渲染模板
        tpl.render(context)
        
        # 格式化周次(第1周 -> 第01周)
        week_num = str(row['week']).replace('第', '').replace('周', '')
        try:
            week_formatted = f"第{int(week_num):02d}周"
        except:
            week_formatted = str(row['week'])
        
        # 保存文件
        filename = f"{week_formatted}_一分园_{row['classroom']}_国旗下的讲话_({row['topic']}).docx"
        full_path = os.path.join(temp, filename)
        tpl.save(full_path)
        
        print(f"已生成: {filename}")
        
    except Exception as e:
        print(f"生成第{index+1}行数据时出错: {str(e)}")
        continue
 
print("所有文档生成完成!")

这里还改了docx的名称,使它看上更为规范

但是我核对了一下小2班的名单,发现小2班第1次讲话(第3周)里面出现的五个姓名是5-10号,我希望是1-5号,小2班第5次讲话(第19周)里面出现的五个姓名是11-15号,我希望是20-25号,

显然代码里抽取5个一组的顺序是打乱的。

代码展示3.0(按顺序5个5个抽取)



'''
国旗下讲话模板批量03 按照学号顺序依次出现55个一组的孩子名字
deep seek 、阿夏
20250824
'''
 
import pandas as pd
from docxtpl import DocxTemplate
import os
from docx import Document
import numpy as np
 
# 设置路径
zpath = r'C:Usersjg2yXRZOneDrive桌面202509一分院 国旗下讲话'
temp = zpath + r'202509一分园国旗下讲话模版'
os.makedirs(temp, exist_ok=True)
 
# 读取班级信息表
class_info_path = zpath + '班级信息表.xlsx'
class_info = pd.read_excel(class_info_path, sheet_name=None)  # 读取所有工作表
 
# 读取安排表
schedule_path = zpath + '模版国旗下的讲话总安排(一分部) 2025.9.xlsx'
schedule = pd.read_excel(schedule_path)
 
# 确保s1-s5列是字符串类型
for col in ['s1', 's2', 's3', 's4', 's5']:
    if col in schedule.columns:
        schedule[col] = schedule[col].astype(str)
        # 将"nan"转换为空字符串
        schedule[col] = schedule[col].replace('nan', '')
 
# 为每个班级创建学生姓名列表(按学号排序)
class_students = {}
for sheet_name, df in class_info.items():
    if sheet_name not in ['模板'] and '班' in sheet_name:  # 跳过模板表,只处理班级表
        # 按学号排序并过滤掉空姓名
        students = df[df['姓名'].notna()].sort_values('学号')['姓名'].tolist()
        class_students[sheet_name] = students
        print(f"班级 {sheet_name}: {len(students)} 名学生")
 
# 为每个班级创建索引跟踪器
class_index_tracker = {class_name: 0 for class_name in class_students.keys()}
 
# 更新安排表中的学生姓名
for index, row in schedule.iterrows():
    classroom = row['classroom']
    # 将"小1班"转换为"小1班"格式(去掉括号)
    clean_classroom = classroom.replace('(', '').replace(')', '')
    
    if clean_classroom in class_students:
        students = class_students[clean_classroom]
        current_index = class_index_tracker[clean_classroom]
        
        # 根据班级类型确定每组人数
        if '托' in clean_classroom:
            # 托班:4人一组
            group_size = 4
        elif '小' in clean_classroom:
            # 小班:5人一组
            group_size = 5
        else:
            # 其他班级默认5人一组
            group_size = 5
        
        # 获取当前组的5名学生
        selected_students = []
        for i in range(group_size):
            if current_index < len(students):
                selected_students.append(students[current_index])
                current_index += 1
            else:
                # 如果到末尾,从头开始
                current_index = 0
                selected_students.append(students[current_index])
                current_index += 1
        
        # 更新索引跟踪器
        class_index_tracker[clean_classroom] = current_index
        
        # 更新安排表
        for i in range(5):  # s1-s5最多5个位置
            col_name = f's{i+1}'
            if i < len(selected_students):
                schedule.at[index, col_name] = selected_students[i]
            else:
                schedule.at[index, col_name] = ""
        
        print(f"第{index+1}行 {clean_classroom}: {selected_students}")
 
# 保存更新后的安排表
updated_schedule_path = zpath + '模版国旗下的讲话总安排(一分部) 2025.9_已填充.xlsx'
schedule.to_excel(updated_schedule_path, index=False)
print(f"已保存更新后的安排表: {updated_schedule_path}")
 
# 现在使用更新后的安排表生成文档
# 首先检查模板文件是否存在且是有效的Word文件
template_path = zpath + '模板一分园(小 1 班)国旗下的讲话(第 2 周).docx'
 
if not os.path.exists(template_path):
    print(f"错误:模板文件不存在 - {template_path}")
    exit()
 
try:
    # 尝试打开模板文件检查是否有效
    doc = Document(template_path)
    print("模板文件检查通过,开始生成文档...")
except Exception as e:
    print(f"模板文件无效: {e}")
    print("请确保模板文件是有效的Word文档 (.doc 或 .docx)")
    exit()
 
# 遍历安排表的每一行生成文档
for index, row in schedule.iterrows():
    try:
        # 每次重新读取模板,确保每次都是干净的模板
        tpl = DocxTemplate(template_path)
        
        # 格式化班级名称(小1班 -> 小(1)班)
        classroom_str = str(row['classroom'])
        if len(classroom_str) >= 3:
            formatted_classroom = f"{classroom_str[0]}({classroom_str[1]}){classroom_str[2:]}"
        else:
            formatted_classroom = classroom_str
        
        # 构建上下文数据
        context = {
            "date": str(row['date']),
            "week": str(row['week']),
            "teachers": str(row['teachers']),
            "classroom": formatted_classroom,
            "topic": str(row['topic']),
            "leader": str(row['leader']),
            "s1": str(row['s1']) if pd.notna(row['s1']) and str(row['s1']) != 'nan' else "",
            "s2": str(row['s2']) if pd.notna(row['s2']) and str(row['s2']) != 'nan' else "",
            "s3": str(row['s3']) if pd.notna(row['s3']) and str(row['s3']) != 'nan' else "",
            "s4": str(row['s4']) if pd.notna(row['s4']) and str(row['s4']) != 'nan' else "",
            "s5": str(row['s5']) if pd.notna(row['s5']) and str(row['s5']) != 'nan' else ""
        }
        
        # 渲染模板
        tpl.render(context)
        
        # 格式化周次(第1周 -> 第01周)
        week_num = str(row['week']).replace('第', '').replace('周', '')
        try:
            week_formatted = f"第{int(week_num):02d}周"
        except:
            week_formatted = str(row['week'])
        
        # 保存文件
        filename = f"{week_formatted}_一分园_{row['classroom']}_国旗下的讲话_({row['topic']}).docx"
        full_path = os.path.join(temp, filename)
        tpl.save(full_path)
        
        print(f"已生成: {filename}")
        
    except Exception as e:
        print(f"生成第{index+1}行数据时出错: {str(e)}")
        continue
 
print("所有文档生成完成!")

 

这次正确了,出现的第1组的5个孩子的名字

最后生成了一个包含所有基础信息的模板文件夹

现在就可以打包发给我搭档了

 

四、合并docx,在线编辑

平时我感觉国旗下讲话都是学期结束(2026年1月)统一提交的,一个个文件发出去,再收回来,也很费时,需要看核对哪个班级没有写。最后一个一个文件打开再打印、排序也麻烦。

 

所以我想把模板文件夹里的所有docx合并成一个docx,然后金山表单共享填写。

deepseek几乎每天都有一段时间卡死,换豆包改写

代码展示4.0(批量做各班的表+合并所有表+金山WPS在线共享编辑)



'''
国旗下讲话模板批量04 按照学号顺序依次出现5个5个一组的孩子名字+合并docx,在线填写
deep seek 、豆包、阿夏
20250824
'''
 
import pandas as pd
from docxtpl import DocxTemplate
import os
from docx import Document
import numpy as np
 
# 设置路径
zpath = r'C:Usersjg2yXRZOneDrive桌面202509一分院 国旗下讲话'
temp = zpath + r'202509一分园国旗下讲话模版'
os.makedirs(temp, exist_ok=True)
 
# 读取班级信息表
class_info_path = zpath + '班级信息表.xlsx'
class_info = pd.read_excel(class_info_path, sheet_name=None)  # 读取所有工作表
 
# 读取安排表
schedule_path = zpath + '模版国旗下的讲话总安排(一分部) 2025.9.xlsx'
schedule = pd.read_excel(schedule_path)
 
# 确保s1-s5列是字符串类型
for col in ['s1', 's2', 's3', 's4', 's5']:
    if col in schedule.columns:
        schedule[col] = schedule[col].astype(str)
        # 将"nan"转换为空字符串
        schedule[col] = schedule[col].replace('nan', '')
 
# 为每个班级创建学生姓名列表(按学号排序)
class_students = {}
for sheet_name, df in class_info.items():
    if sheet_name not in ['模板'] and '班' in sheet_name:  # 跳过模板表,只处理班级表
        # 按学号排序并过滤掉空姓名
        students = df[df['姓名'].notna()].sort_values('学号')['姓名'].tolist()
        class_students[sheet_name] = students
        print(f"班级 {sheet_name}: {len(students)} 名学生")
 
# 为每个班级创建索引跟踪器
class_index_tracker = {class_name: 0 for class_name in class_students.keys()}
 
# 更新安排表中的学生姓名
for index, row in schedule.iterrows():
    classroom = row['classroom']
    # 将"小1班"转换为"小1班"格式(去掉括号)
    clean_classroom = classroom.replace('(', '').replace(')', '')
    
    if clean_classroom in class_students:
        students = class_students[clean_classroom]
        current_index = class_index_tracker[clean_classroom]
        
        # 根据班级类型确定每组人数
        if '托' in clean_classroom:
            # 托班:4人一组
            group_size = 4
        elif '小' in clean_classroom:
            # 小班:5人一组
            group_size = 5
        else:
            # 其他班级默认5人一组
            group_size = 5
        
        # 获取当前组的5名学生
        selected_students = []
        for i in range(group_size):
            if current_index < len(students):
                selected_students.append(students[current_index])
                current_index += 1
            else:
                # 如果到末尾,从头开始
                current_index = 0
                selected_students.append(students[current_index])
                current_index += 1
        
        # 更新索引跟踪器
        class_index_tracker[clean_classroom] = current_index
        
        # 更新安排表
        for i in range(5):  # s1-s5最多5个位置
            col_name = f's{i+1}'
            if i < len(selected_students):
                schedule.at[index, col_name] = selected_students[i]
            else:
                schedule.at[index, col_name] = ""
        
        print(f"第{index+1}行 {clean_classroom}: {selected_students}")
 
# 保存更新后的安排表
updated_schedule_path = zpath + '模版国旗下的讲话总安排(一分部) 2025.9_已填充.xlsx'
schedule.to_excel(updated_schedule_path, index=False)
print(f"已保存更新后的安排表: {updated_schedule_path}")
 
# 现在使用更新后的安排表生成文档
# 首先检查模板文件是否存在且是有效的Word文件
template_path = zpath + '模板一分园(小 1 班)国旗下的讲话(第 2 周).docx'
 
if not os.path.exists(template_path):
    print(f"错误:模板文件不存在 - {template_path}")
    exit()
 
try:
    # 尝试打开模板文件检查是否有效
    doc = Document(template_path)
    print("模板文件检查通过,开始生成文档...")
except Exception as e:
    print(f"模板文件无效: {e}")
    print("请确保模板文件是有效的Word文档 (.doc 或 .docx)")
    exit()
 
# 遍历安排表的每一行生成文档
for index, row in schedule.iterrows():
    try:
        # 每次重新读取模板,确保每次都是干净的模板
        tpl = DocxTemplate(template_path)
        
        # 格式化班级名称(小1班 -> 小(1)班)
        classroom_str = str(row['classroom'])
        if len(classroom_str) >= 3:
            formatted_classroom = f"{classroom_str[0]}({classroom_str[1]}){classroom_str[2:]}"
        else:
            formatted_classroom = classroom_str
        
        # 构建上下文数据
        context = {
            "date": str(row['date']),
            "week": str(row['week']),
            "teachers": str(row['teachers']),
            "classroom": formatted_classroom,
            "topic": str(row['topic']),
            "leader": str(row['leader']),
            "s1": str(row['s1']) if pd.notna(row['s1']) and str(row['s1']) != 'nan' else "",
            "s2": str(row['s2']) if pd.notna(row['s2']) and str(row['s2']) != 'nan' else "",
            "s3": str(row['s3']) if pd.notna(row['s3']) and str(row['s3']) != 'nan' else "",
            "s4": str(row['s4']) if pd.notna(row['s4']) and str(row['s4']) != 'nan' else "",
            "s5": str(row['s5']) if pd.notna(row['s5']) and str(row['s5']) != 'nan' else ""
        }
        
        # 渲染模板
        tpl.render(context)
        
        # 格式化周次(第1周 -> 第01周)
        week_num = str(row['week']).replace('第', '').replace('周', '')
        try:
            week_formatted = f"第{int(week_num):02d}周"
        except:
            week_formatted = str(row['week'])
        
        # 保存文件
        filename = f"{week_formatted}_一分园_{row['classroom']}_国旗下的讲话_({row['topic']}).docx"
        full_path = os.path.join(temp, filename)
        tpl.save(full_path)
        
        print(f"已生成: {filename}")
        
    except Exception as e:
        print(f"生成第{index+1}行数据时出错: {str(e)}")
        continue
 
print("所有文档生成完成!")

除了模板文件夹,还有一份合并docx

发现回车符和分页符不在一行上,就会多占一个空行,

 

 

改了几次,还是有回车和换行符,

最后我在word的模板里把这个回车符间距从1.5倍改成固定值1磅

现在都看不见回车符,分页符看上去贴着表格(实际回车符存在)可以让表格最大化控制在一页内,又能让文字尽可能多一点

 

把word发到手机,用WPS转成可编辑的文件。

五、发给同事,学期再用

搭档表示很有趣。

 

感悟:

1、Ai编程批量,实现模板的个性化批量制作,提高数据准确性(基本信息都填好,格式完全相同,减少人工自主填写出现的差异,还能根据需求批量调整)

2、AI数据整理:快速将各类数据转化为需要的样式。不用excle进行转换。

3、共享编辑:WPS的共享编辑可以实时更新数据,实现单一文本(如果大家都自己编辑自己的,合并也需要时间和经历)便于快速检查,提醒填写,最终下载一个文件,能快速批量打印。

 

 

 

 

 

 

 

 

 

 

© 版权声明
THE END
如果内容对您有所帮助,就支持一下吧!
点赞0 分享
评论 抢沙发

请登录后发表评论

    暂无评论内容