
一、背景需求
刚开学,能干的Q老师已经把"四大教育"的安排表发我了。两个分园班级数量相等,内容通用。

参考以下文件,复用代码,制作新学期的"X大教育内容"
二、重制Word模版
因为老电脑坏了,所以根据前期CSDN备份记录中的Word模版样式,重新制作Word模版



修改模版
(一)一分园模版(这个doc,就是复制了00样例自我保护(2.3月).doc)

把"园区、年级、标题主题、活动主题(主、副)、活动名称、活动目标、活动流程、活动反思"班级照片格子。分别做好



(二)制作Excel的英文表头

python
'''
一分园托小班四大教育4个主题,每个主题4个 共16个 - 完整工作流
1. 生成占位符Excel
2. 根据Excel生成Word文档
3. 处理Word文档(aaa转手动换行符、空格缩进)
4. 打包成RAR
豆包、Deepseek、阿夏
20260910
'''
import pandas as pd
import os
# ========== 路径配置 ==========
BASE_PATH = r'D:\Python最终内容\20260906四大教育\分园'
CLASS_NAME = "一分园托小班"
EDU_THEME = "全部主题"
EXCEL_PATH = os.path.join(BASE_PATH, f"20260305{CLASS_NAME}四大教育({EDU_THEME}).xlsx")
# 表头字段(和生成word脚本完全对齐)
columns = [
'garden','name0','name1','grade','name2',
'year', 'month', 'topic', 'goal',
'procedure', 'reflection','ts',
]
def create_empty_excel_header_only():
"""只生成仅有表头的Excel,没有数据行"""
os.makedirs(BASE_PATH, exist_ok=True)
df = pd.DataFrame(columns=columns)
df.to_excel(EXCEL_PATH, index=False)
print(f"✅ 已生成仅带表头的Excel")
print(f"📂 文件路径:{EXCEL_PATH}")
print(f"📋 表头:{columns}")
if __name__ == "__main__":
create_empty_excel_header_only()



(三)在豆包里面做AI
请根据附件 1-4 计划书的内容,填写附件 6 的模版,具体字数和格式参考附件 5,输出的格式是横版表格形式,只要输出: 1. 大标题上的园区,"总园中班" 中的 "总园"(garden)、 2. 大标题上的 "" 里面的内容,如总园大班幼儿 "光盘行动" 活动方只要光盘行动四个字,括号也不要(name0)、 3. 活动主题,如主题:学习雷锋好榜样,争做文明好娃娃 ------ 总园中班幼儿 "学雷锋" 活动,提取 "学习雷锋好榜样,争做文明好娃娃" 写入(name1)------ 后面的都不要 4. 年级(grade)就是总园中班幼儿 "学雷锋" 活动中的 "中班" 5. 活动副标题(name2,副标题只要 "" 里面的内容,"" 也不要,如总园大班幼儿 "学雷锋" 活动,就是只要学雷锋)、 6。活动年(数字)、 7. 活动月(数字)、 8. 活动名称源自活动主题 (name1),但不要一摸一样,差不多意思的 9. 活动目标(用 1.2...... 活动目标也要写在一个单元格内。每个目标中间用 aaa,不要有空格) 10、活动流程 (所有内容要写在一个单元格内,大标题前面写一、二、三、但是一、二、三、后面不要 aaa、序号和大标题的后面用 aaa 分割,每个一、二、三标题下面写的正文内容是一段,,每段至少 50 字,整个活动流程不超过 220 字,范例如下 一、开场暖场:喜迎新年 aaa1. 老师穿着新年元素服装,以欢快的新年音乐迎接幼儿入园,2. 引导幼儿互相问候 "新年好",感受节日的热闹氛围。aaa 二、创意手工:新年献礼 aaa1. 幼儿分组进行手工创作,老师巡回指导。2. 鼓励幼儿发挥想象力,装饰自己的作品。aaa)三、创意手工:新年献礼 aaa1. 幼儿分组进行手工创作,老师巡回指导。2. 鼓励幼儿发挥想象力,装饰自己的作品。aaa)写一、二、或一、二、三。每个下面有 1.2 或 1.2.3. 一段文字至少 20 字, 11. 活动反思(250 字), 横向表格形式,,。,提取关键字母的内容,用横向表格形式,提取关键字母的内容,用横向表格形式,在 TS 里面写入相关内容可以拍写什么照片(比如,幼儿站在电视机前介绍节气、幼儿吃饭光盘照片等,是幼儿园可以操作的内容,每篇写 1-3 条拍照建议,三条建议1.2.3.用aaa分割)我希望活动目标 2 条 aaa 分割 ,活动流程里面的流程一里面 aaa1,aaa2.aaa3,流程二下面有 aaa1,aaa2,aaa3,流程三下面有 aaa1,aaa2,aaa3。活动流程的 2.3 前面都要加 aaa
把四份计划书都附件上传








保存,关闭Excel。
(四)Excel写入Word


python
'''
一分园托小班四大教育4个主题,每个主题4个 共16个 - 完整工作流
1. 生成占位符Excel
2. 根据Excel生成Word文档
3. 处理Word文档(aaa转手动换行符、空格缩进)
4. 打包成RAR
豆包、Deepseek、阿夏
20260910
'''
import pandas as pd
from docxtpl import DocxTemplate
from docx import Document
from docx.enum.text import WD_BREAK
from docx.shared import Pt
from docx.oxml.ns import qn
import os
import sys
import subprocess
import zipfile
import shutil
# ========== 全局路径配置(只需修改这里) ==========
# 根路径 - 所有文件都基于这个路径
BASE_PATH = r'D:\Python最终内容\20260906四大教育\分园'
# 班级名称
kindgarden='一分园'
CLASS_NAME = "一分园托小班"
# 教育主题
EDU_THEME = "全部主题"
# ==============================================
# 根据基础路径生成所有子路径
EXCEL_PATH = os.path.join(BASE_PATH, f"20260305一分园托小班四大教育(全部主题).xlsx")
TEMPLATE_PATH = os.path.join(BASE_PATH, "01 一分园四大教育模版.docx")
OUTPUT_FOLDER = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}")
PROCESSED_FOLDER = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}最终")
RAR_PATH = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}最终.rar")
ZIP_PATH = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}最终.zip")
# 设置控制台编码
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# def step1_generate_excel():
# """第一步:生成占位符Excel文件"""
# print("\n" + "="*60)
# print("第一步:生成占位符Excel文件")
# print("="*60)
# # 创建数据框
# df = pd.DataFrame(columns=[
# 'garden','name0','name1','grade','name2','year', 'month', 'topic', 'goal', 'procedure', 'reflection','ts',
# ])
# # 保存为Excel文件
# df.to_excel(EXCEL_PATH, index=False)
# print(f"✅ Excel文件已生成:{EXCEL_PATH}")
# input('\n请先在Excel中填入AI生成的内容,然后按回车键继续...')
# return True
def step2_generate_word_from_excel():
"""第二步:根据Excel生成Word文档"""
print("\n" + "="*60)
print("第二步:根据Excel生成Word文档")
print("="*60)
# 创建输出文件夹
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
# 存储生成的文件路径
generated_files = []
# 检查关键文件是否存在
if not os.path.exists(EXCEL_PATH):
print(f"❌ 错误:安排表不存在 - {EXCEL_PATH}")
return False
if not os.path.exists(TEMPLATE_PATH):
print(f"❌ 错误:模板文件不存在 - {TEMPLATE_PATH}")
return False
# 读取安排表
schedule = pd.read_excel(EXCEL_PATH)
# 确保列是字符串类型,避免nan显示
new_columns = ['garden','name0','name1','grade','name2','year', 'month', 'topic', 'goal', 'procedure', 'reflection', 'classroom', 'teachers','ts']
for col in new_columns:
if col in schedule.columns:
schedule[col] = schedule[col].astype(str).replace('nan', '')
# 设置默认值
if 'year' not in schedule.columns:
schedule['year'] = '2026'
if 'month' not in schedule.columns:
schedule['month'] = '3'
if 'garden' not in schedule.columns:
schedule['garden'] = '一分园'
if 'classroom' not in schedule.columns:
schedule['classroom'] = CLASS_NAME
if 'teachers' not in schedule.columns:
schedule['teachers'] = '待定'
# 保存安排表(覆盖原文件)
schedule.to_excel(EXCEL_PATH, index=False)
print(f"✅ 已保存安排表")
print(f"📊 安排表共有 {len(schedule)} 行数据")
# 验证模板文件
try:
test_doc = Document(TEMPLATE_PATH)
print("✅ 模板文件验证通过,开始生成文档...")
except Exception as e:
print(f"❌ 模板文件无效: {e}")
return False
# 批量生成文档
for index, row in schedule.iterrows():
try:
tpl = DocxTemplate(TEMPLATE_PATH)
# 获取班级名
classroom = str(row['classroom']) if pd.notna(row['classroom']) else CLASS_NAME
original_classroom = classroom.strip()
# 格式化班级名称
classroom_str = original_classroom
if len(classroom_str) >= 3 and classroom_str[1].isdigit():
formatted_class = f"{classroom_str[0]}({classroom_str[1]}){classroom_str[2:]}"
elif '(' in classroom_str or '(' in classroom_str:
formatted_class = classroom_str
else:
formatted_class = classroom_str
# 获取教师姓名
teacher_name = str(row['teachers']) if pd.notna(row['teachers']) and str(row['teachers']) != 'nan' else "待定"
# 构建模板上下文
context = {
"grade": str(row['grade']) if pd.notna(row['grade']) and str(row['grade']) != 'nan' else '',
"name0": str(row['name0']) if pd.notna(row['name0']) and str(row['name0']) != 'nan' else '',
"name1": str(row['name1']) if pd.notna(row['name1']) and str(row['name1']) != 'nan' else '',
"name2": str(row['name2']) if pd.notna(row['name2']) and str(row['name2']) != 'nan' else '',
"year": str(row['year']) if pd.notna(row['year']) and str(row['year']) != 'nan' else '2026',
"month": str(row['month']) if pd.notna(row['month']) and str(row['month']) != 'nan' else '3',
"garden": str(row['garden']) if pd.notna(row['garden']) and str(row['garden']) != 'nan' else '一分园',
"topic": str(row['topic']) if pd.notna(row['topic']) and str(row['topic']) != 'nan' else '',
"goal": str(row['goal']) if pd.notna(row['goal']) and str(row['goal']) != 'nan' else '',
"procedure": str(row['procedure']) if pd.notna(row['procedure']) and str(row['procedure']) != 'nan' else '',
"reflection": str(row['reflection']) if pd.notna(row['reflection']) and str(row['reflection']) != 'nan' else '',
"classroom": formatted_class,
"teachers": teacher_name,
"date": str(row['date']) if 'date' in row and pd.notna(row['date']) else '',
"week": str(row['week']) if 'week' in row and pd.notna(row['week']) else '',
"leader": str(row['leader']) if 'leader' in row and pd.notna(row['leader']) else '',
"ts": str(row['ts']) if 'ts' in row and pd.notna(row['ts']) else '',
}
# 渲染模板
tpl.render(context)
# 保存文档到临时文件
temp_path = os.path.join(OUTPUT_FOLDER, f"temp_{index}.docx")
tpl.save(temp_path)
# 打开文档进行样式修复
doc = Document(temp_path)
# 修复反思部分的字体大小(确保是小四12磅)
modified = False
if doc.tables:
for table in doc.tables:
if len(table.rows) >= 6:
# 反思部分在第6行(索引5)
reflection_row = table.rows[5]
# 反思部分通常是合并单元格,所以取第一个单元格
if len(reflection_row.cells) >= 1:
reflection_cell = reflection_row.cells[0]
for paragraph in reflection_cell.paragraphs:
for run in paragraph.runs:
# 设置为小四(12磅)
run.font.size = Pt(12)
# 确保是宋体
run.font.name = '宋体'
# 中文字体设置
run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
modified = True
if modified:
print(f" ✅ 修复反思部分字体为小四宋体")
# 生成文件名
month_str = str(row['month']) if pd.notna(row['month']) and str(row['month']) != 'nan' else str(index+1)
# try:
# month_formatted = f"{int(month_str):02d}月"
# except:
month_formatted = f"{month_str}月"
topic_short = str(row['name0'])[:] if pd.notna(row['name0']) and str(row['name0']) != 'nan' else '四大教育'
# filename = f"{month_formatted}_{kindgarden}_{original_classroom}_四大教育_{topic_short}_{CLASS_NAME[2]}()班.docx"
# 客户要求样式大班XX教育(3月).docx
filename = f"{topic_short}({month_formatted}).docx"
file_full_path = os.path.join(OUTPUT_FOLDER, filename)
# 保存修复后的文档
doc.save(file_full_path)
# 删除临时文件
if os.path.exists(temp_path):
os.remove(temp_path)
generated_files.append(file_full_path)
print(f"✅ 生成文档: {filename}")
except Exception as e:
print(f"❌ 生成第{index+1}行文档失败: {str(e)}")
import traceback
traceback.print_exc()
continue
print(f"\n📊 文档生成完成!共生成 {len(generated_files)} 个文档")
print(f"📂 文档保存在: {OUTPUT_FOLDER}")
return True
def process_word_document(input_path, output_path):
"""处理单个Word文档(aaa转手动换行符、空格缩进 + 修复字体大小)"""
try:
doc = Document(input_path)
modified = False
# 修复反思部分的字体大小(确保是小四)
if doc.tables:
for table in doc.tables:
if len(table.rows) >= 6:
reflection_row = table.rows[5]
if len(reflection_row.cells) >= 1:
reflection_cell = reflection_row.cells[0]
for paragraph in reflection_cell.paragraphs:
for run in paragraph.runs:
# 设置为小四(12磅)
if run.font.size != Pt(12):
run.font.size = Pt(12)
run.font.name = '宋体'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
modified = True
for table in doc.tables:
for row_idx, row in enumerate(table.rows, 1):
for col_idx, cell in enumerate(row.cells, 1):
# 收集所有需要处理的段落
paragraphs_to_process = []
for para_idx, para in enumerate(cell.paragraphs):
if 'aaa' in para.text:
paragraphs_to_process.append((para_idx, para))
# 添加空格缩进(第2列第7行)
if col_idx == 2 and row_idx == 7:
if para.text and not para.text.startswith(''):
para.text = '' + para.text
modified = True
# 处理包含aaa的段落
for para_idx, para in paragraphs_to_process:
# 保存原格式
runs_info = []
for run in para.runs:
runs_info.append({
'text': run.text,
'bold': run.bold,
'italic': run.italic,
'underline': run.underline,
'font_name': run.font.name,
'font_size': run.font.size,
'color': run.font.color.rgb if run.font.color else None
})
# 按aaa分割文本
full_text = para.text
parts = full_text.split('aaa')
# 清除原段落
para.clear()
# 重新添加分段内容
for i, part in enumerate(parts):
if part.strip(): # 如果有内容
# 创建新run并尝试保留原格式
run = para.add_run(part)
if runs_info:
# 使用第一个run的格式(简化处理)
run.bold = runs_info[0]['bold']
run.italic = runs_info[0]['italic']
run.underline = runs_info[0]['underline']
if runs_info[0]['font_name']:
run.font.name = runs_info[0]['font_name']
if runs_info[0]['font_size']:
run.font.size = runs_info[0]['font_size']
if runs_info[0]['color']:
run.font.color.rgb = runs_info[0]['color']
# 如果不是最后一段,添加手动换行符
if i < len(parts) - 1:
para.add_run().add_break(WD_BREAK.LINE)
modified = True
# 保存文档
doc.save(output_path)
# 如果保存成功
if os.path.exists(output_path):
return True, modified
else:
return False, False
except Exception as e:
print(f" 错误: {str(e)}")
import traceback
traceback.print_exc()
return False, False
def step3_process_documents():
"""第三步:处理生成的Word文档"""
print("\n" + "="*60)
print("第三步:处理Word文档(aaa转手动换行符、空格缩进)")
print("="*60)
# 创建输出文件夹
os.makedirs(PROCESSED_FOLDER, exist_ok=True)
print(f"输入文件夹: {OUTPUT_FOLDER}")
print(f"输出文件夹: {PROCESSED_FOLDER}")
print("-" * 60)
# 检查输入文件夹
if not os.path.exists(OUTPUT_FOLDER):
print(f"❌ 错误: 输入文件夹不存在!")
return False
# 获取所有docx文件
docx_files = [f for f in os.listdir(OUTPUT_FOLDER)
if f.lower().endswith('.docx')]
if not docx_files:
print(f"⚠️ 没有找到docx文件!")
return False
print(f"\n✅ 找到 {len(docx_files)} 个docx文件")
print("-" * 60)
# 处理文件
success = 0
for i, filename in enumerate(docx_files, 1):
print(f"[{i}/{len(docx_files)}] {filename}")
input_path = os.path.join(OUTPUT_FOLDER, filename)
output_filename = filename.replace('.docx', '.doc')
output_path = os.path.join(PROCESSED_FOLDER, output_filename)
result, modified = process_word_document(input_path, output_path)
if result:
if modified:
print(f" ✅ 已处理并保存")
else:
print(f" ⚠️ 无修改内容,已复制")
success += 1
else:
print(f" ❌ 处理失败")
print()
print(f"\n✅ 处理完成!成功处理 {success}/{len(docx_files)} 个文件")
print(f"📂 处理后文档保存在: {PROCESSED_FOLDER}")
return True
def check_winrar_installed():
"""检查WinRAR是否安装"""
possible_paths = [
r"C:\Program Files\WinRAR\WinRAR.exe",
r"C:\Program Files (x86)\WinRAR\WinRAR.exe"
]
for path in possible_paths:
if os.path.exists(path):
return path
return None
def step4_pack_to_rar():
"""第四步:打包成RAR文件"""
print("\n" + "="*60)
print("第四步:打包成RAR文件")
print("="*60)
# 检查最终文件夹是否存在
if not os.path.exists(PROCESSED_FOLDER):
print(f"❌ 错误:最终文件夹不存在 - {PROCESSED_FOLDER}")
return False
# 检查文件夹内是否有文件
files = os.listdir(PROCESSED_FOLDER)
if not files:
print(f"⚠️ 警告:最终文件夹为空,没有文件可打包")
return False
print(f"📁 待打包文件夹: {PROCESSED_FOLDER}")
print(f"📊 文件夹内共有 {len(files)} 个文件")
# 方法1:尝试使用WinRAR(如果已安装)
winrar_path = check_winrar_installed()
if winrar_path:
try:
print("🔄 正在使用WinRAR打包...")
# 构建WinRAR命令
cmd = [
winrar_path,
'a', # 添加到压缩文件
'-ep1', # 不保存路径信息
'-r', # 递归子目录
RAR_PATH,
f'{PROCESSED_FOLDER}\\*.*'
]
# 执行命令
result = subprocess.run(cmd, capture_output=True, text=True)
if os.path.exists(RAR_PATH):
size = os.path.getsize(RAR_PATH) / 1024 # KB
print(f"✅ 打包成功!")
print(f"📦 RAR文件: {RAR_PATH}")
print(f"📏 文件大小: {size:.2f} KB")
return True
else:
print("⚠️ WinRAR打包失败,尝试使用ZIP替代...")
return create_zip_backup()
except Exception as e:
print(f"⚠️ WinRAR打包出错: {str(e)}")
print("⚠️ 尝试使用ZIP替代...")
return create_zip_backup()
else:
print("⚠️ 未找到WinRAR,将使用ZIP格式打包...")
return create_zip_backup()
def create_zip_backup():
"""创建ZIP备份(当WinRAR不可用时)"""
try:
print("🔄 正在创建ZIP压缩文件...")
# 创建ZIP文件
with zipfile.ZipFile(ZIP_PATH, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(PROCESSED_FOLDER):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, PROCESSED_FOLDER)
zipf.write(file_path, arcname)
if os.path.exists(ZIP_PATH):
size = os.path.getsize(ZIP_PATH) / 1024 # KB
print(f"✅ ZIP打包成功!")
print(f"📦 ZIP文件: {ZIP_PATH}")
print(f"📏 文件大小: {size:.2f} KB")
# 询问是否要重命名为RAR(虽然实际上是ZIP)
print("\n注:由于系统没有安装WinRAR,已生成ZIP格式文件")
print("如需RAR格式,请手动安装WinRAR后重新运行此步骤")
return True
else:
print("❌ ZIP打包失败")
return False
except Exception as e:
print(f"❌ ZIP打包出错: {str(e)}")
return False
def main():
"""主函数 - 执行完整工作流"""
print("\n" + "="*60)
print("一分园四大教育 - 完整工作流")
print("="*60)
print(f"基础路径: {BASE_PATH}")
print(f"班级: {CLASS_NAME}")
print(f"主题: {EDU_THEME}")
print("="*60)
# 自动执行完整工作流(不需要用户选择)
print("\n开始执行完整工作流...")
# # 第一步:生成Excel
# if not step1_generate_excel():
# print("❌ 第一步失败,程序终止")
# return
# 第二步:生成Word文档
if not step2_generate_word_from_excel():
print("❌ 第二步失败,程序终止")
return
# 第三步:处理文档
if not step3_process_documents():
print("❌ 第三步失败,程序终止")
return
# 第四步:打包成RAR
step4_pack_to_rar()
print("\n" + "="*60)
print("🎉 完整工作流执行完成!")
print("="*60)
print(f"\n📂 生成的文件位置:")
print(f"1. Excel占位符文件: {EXCEL_PATH}")
print(f"2. 原始Word文档: {OUTPUT_FOLDER}")
print(f"3. 处理后的Word文档: {PROCESSED_FOLDER}")
# 显示打包文件
if os.path.exists(RAR_PATH):
print(f"4. RAR压缩包: {RAR_PATH}")
elif os.path.exists(ZIP_PATH):
print(f"4. ZIP压缩包: {ZIP_PATH}")
print("="*60)
if __name__ == "__main__":
main()






字数真的很统一,所以都是照片班级显示在第一页最后一行




还是有一份字数不一样,班级显示在第二页上

(四)发给负责人




四、二分园四大教育
同样方式做二分园,
(一)Word模版修改

'
(二)制作Excel标题

python
'''
二分园托小班四大教育4个主题,每个主题4个 共16个 - 完整工作流
1. 生成占位符Excel
2. 根据Excel生成Word文档
3. 处理Word文档(aaa转手动换行符、空格缩进)
4. 打包成RAR
豆包、Deepseek、阿夏
20260910
'''
import pandas as pd
import os
# ========== 路径配置 ==========
BASE_PATH = r'D:\Python最终内容\20260906四大教育\分园'
CLASS_NAME = "二分园托小班"
EDU_THEME = "全部主题"
EXCEL_PATH = os.path.join(BASE_PATH, f"20260305{CLASS_NAME}四大教育({EDU_THEME}).xlsx")
# 表头字段(和生成word脚本完全对齐)
columns = [
'garden','name0','name1','grade','name2',
'year', 'month', 'topic', 'goal',
'procedure', 'reflection','ts',
]
def create_empty_excel_header_only():
"""只生成仅有表头的Excel,没有数据行"""
os.makedirs(BASE_PATH, exist_ok=True)
df = pd.DataFrame(columns=columns)
df.to_excel(EXCEL_PATH, index=False)
print(f"✅ 已生成仅带表头的Excel")
print(f"📂 文件路径:{EXCEL_PATH}")
print(f"📋 表头:{columns}")
if __name__ == "__main__":
create_empty_excel_header_only()



(二)豆包AI生成
请根据附件 1-4 计划书的内容,填写附件 6 的模版,具体字数和格式参考附件 5,输出的格式是横版表格形式,只要输出: 1. 大标题上的园区,"总园中班" 中的 "总园"(garden)、 2. 大标题上的 "" 里面的内容,如总园大班幼儿 "光盘行动" 活动方只要光盘行动四个字,括号也不要(name0)、 3. 活动主题,如主题:学习雷锋好榜样,争做文明好娃娃 ------ 总园中班幼儿 "学雷锋" 活动,提取 "学习雷锋好榜样,争做文明好娃娃" 写入(name1)------ 后面的都不要 4. 年级(grade)就是总园中班幼儿 "学雷锋" 活动中的 "中班" 5. 活动副标题(name2,副标题只要 "" 里面的内容,"" 也不要,如总园大班幼儿 "学雷锋" 活动,就是只要学雷锋)、 6。活动年(数字)、 7. 活动月(数字)、 8. 活动名称源自活动主题 (name1),但不要一摸一样,差不多意思的 9. 活动目标(用 1.2...... 活动目标也要写在一个单元格内。每个目标中间用 aaa,不要有空格) 10、活动流程 (所有内容要写在一个单元格内,大标题前面写一、二、三、但是一、二、三、后面不要 aaa、序号和大标题的后面用 aaa 分割,每个一、二、三标题下面写的正文内容是一段,,每段至少 50 字,整个活动流程不超过 220 字,范例如下 一、开场暖场:喜迎新年 aaa1. 老师穿着新年元素服装,以欢快的新年音乐迎接幼儿入园,2. 引导幼儿互相问候 "新年好",感受节日的热闹氛围。aaa 二、创意手工:新年献礼 aaa1. 幼儿分组进行手工创作,老师巡回指导。2. 鼓励幼儿发挥想象力,装饰自己的作品。aaa)三、创意手工:新年献礼 aaa1. 幼儿分组进行手工创作,老师巡回指导。2. 鼓励幼儿发挥想象力,装饰自己的作品。aaa)写一、二、或一、二、三。每个下面有 1.2 或 1.2.3. 一段文字至少 20 字, 11. 活动反思(250 字), 横向表格形式,,。,提取关键字母的内容,用横向表格形式,提取关键字母的内容,用横向表格形式,在 TS 里面写入相关内容可以拍写什么照片(比如,幼儿站在电视机前介绍节气、幼儿吃饭光盘照片等,是幼儿园可以操作的内容,每篇写 1-3 条拍照建议,三条建议 1.2.3. 用 aaa 分割)我希望活动目标 2 条 aaa 分割 ,活动流程一下面有 aaa1,aaa2.aaa3,流程二下面有 aaa1,aaa2,aaa3,流程三下面有 aaa1,aaa2,aaa3,改成是二分园,





(三)写入word模版占位符替换


python
'''
二分园大班四大教育4个主题,每个主题4个 共16个 - 完整工作流
1. 生成占位符Excel
2. 根据Excel生成Word文档
3. 处理Word文档(aaa转手动换行符、空格缩进)
4. 打包成RAR
豆包、Deepseek、阿夏
20260310
'''
import pandas as pd
from docxtpl import DocxTemplate
from docx import Document
from docx.enum.text import WD_BREAK
from docx.shared import Pt
from docx.oxml.ns import qn
import os
import sys
import subprocess
import zipfile
import shutil
# ========== 全局路径配置(只需修改这里) ==========
# 根路径 - 所有文件都基于这个路径
BASE_PATH = r'D:\Python最终内容\20260906四大教育\分园'
# 班级名称
kindgarden='二分园'
CLASS_NAME = "二分园托小班"
# 教育主题
EDU_THEME = "全部主题"
# ==============================================
# 根据基础路径生成所有子路径
EXCEL_PATH = os.path.join(BASE_PATH, f"20260305二分园托小班四大教育(全部主题).xlsx")
TEMPLATE_PATH = os.path.join(BASE_PATH, "01 二分园四大教育模版.docx")
OUTPUT_FOLDER = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}")
PROCESSED_FOLDER = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}最终")
RAR_PATH = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}最终.rar")
ZIP_PATH = os.path.join(BASE_PATH, f"01 ({CLASS_NAME})四大教育_{EDU_THEME}最终.zip")
# 设置控制台编码
if sys.platform == 'win32':
import io
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8')
# def step1_generate_excel():
# """第一步:生成占位符Excel文件"""
# print("\n" + "="*60)
# print("第一步:生成占位符Excel文件")
# print("="*60)
# # 创建数据框
# df = pd.DataFrame(columns=[
# 'garden','name0','name1','grade','name2','year', 'month', 'topic', 'goal', 'procedure', 'reflection','ts',
# ])
# # 保存为Excel文件
# df.to_excel(EXCEL_PATH, index=False)
# print(f"✅ Excel文件已生成:{EXCEL_PATH}")
# input('\n请先在Excel中填入AI生成的内容,然后按回车键继续...')
# return True
def step2_generate_word_from_excel():
"""第二步:根据Excel生成Word文档"""
print("\n" + "="*60)
print("第二步:根据Excel生成Word文档")
print("="*60)
# 创建输出文件夹
os.makedirs(OUTPUT_FOLDER, exist_ok=True)
# 存储生成的文件路径
generated_files = []
# 检查关键文件是否存在
if not os.path.exists(EXCEL_PATH):
print(f"❌ 错误:安排表不存在 - {EXCEL_PATH}")
return False
if not os.path.exists(TEMPLATE_PATH):
print(f"❌ 错误:模板文件不存在 - {TEMPLATE_PATH}")
return False
# 读取安排表
schedule = pd.read_excel(EXCEL_PATH)
# 确保列是字符串类型,避免nan显示
new_columns = ['garden','name0','name1','grade','name2','year', 'month', 'topic', 'goal', 'procedure', 'reflection', 'classroom', 'teachers','ts']
for col in new_columns:
if col in schedule.columns:
schedule[col] = schedule[col].astype(str).replace('nan', '')
# 设置默认值
if 'year' not in schedule.columns:
schedule['year'] = '2026'
if 'month' not in schedule.columns:
schedule['month'] = '3'
if 'garden' not in schedule.columns:
schedule['garden'] = '二分园'
if 'classroom' not in schedule.columns:
schedule['classroom'] = CLASS_NAME
if 'teachers' not in schedule.columns:
schedule['teachers'] = '待定'
# 保存安排表(覆盖原文件)
schedule.to_excel(EXCEL_PATH, index=False)
print(f"✅ 已保存安排表")
print(f"📊 安排表共有 {len(schedule)} 行数据")
# 验证模板文件
try:
test_doc = Document(TEMPLATE_PATH)
print("✅ 模板文件验证通过,开始生成文档...")
except Exception as e:
print(f"❌ 模板文件无效: {e}")
return False
# 批量生成文档
for index, row in schedule.iterrows():
try:
tpl = DocxTemplate(TEMPLATE_PATH)
# 获取班级名
classroom = str(row['classroom']) if pd.notna(row['classroom']) else CLASS_NAME
original_classroom = classroom.strip()
# 格式化班级名称
classroom_str = original_classroom
if len(classroom_str) >= 3 and classroom_str[1].isdigit():
formatted_class = f"{classroom_str[0]}({classroom_str[1]}){classroom_str[2:]}"
elif '(' in classroom_str or '(' in classroom_str:
formatted_class = classroom_str
else:
formatted_class = classroom_str
# 获取教师姓名
teacher_name = str(row['teachers']) if pd.notna(row['teachers']) and str(row['teachers']) != 'nan' else "待定"
# 构建模板上下文
context = {
"grade": str(row['grade']) if pd.notna(row['grade']) and str(row['grade']) != 'nan' else '',
"name0": str(row['name0']) if pd.notna(row['name0']) and str(row['name0']) != 'nan' else '',
"name1": str(row['name1']) if pd.notna(row['name1']) and str(row['name1']) != 'nan' else '',
"name2": str(row['name2']) if pd.notna(row['name2']) and str(row['name2']) != 'nan' else '',
"year": str(row['year']) if pd.notna(row['year']) and str(row['year']) != 'nan' else '2026',
"month": str(row['month']) if pd.notna(row['month']) and str(row['month']) != 'nan' else '3',
"garden": str(row['garden']) if pd.notna(row['garden']) and str(row['garden']) != 'nan' else '二分园',
"topic": str(row['topic']) if pd.notna(row['topic']) and str(row['topic']) != 'nan' else '',
"goal": str(row['goal']) if pd.notna(row['goal']) and str(row['goal']) != 'nan' else '',
"procedure": str(row['procedure']) if pd.notna(row['procedure']) and str(row['procedure']) != 'nan' else '',
"reflection": str(row['reflection']) if pd.notna(row['reflection']) and str(row['reflection']) != 'nan' else '',
"classroom": formatted_class,
"teachers": teacher_name,
"date": str(row['date']) if 'date' in row and pd.notna(row['date']) else '',
"week": str(row['week']) if 'week' in row and pd.notna(row['week']) else '',
"leader": str(row['leader']) if 'leader' in row and pd.notna(row['leader']) else '',
"ts": str(row['ts']) if 'ts' in row and pd.notna(row['ts']) else '',
}
# 渲染模板
tpl.render(context)
# 保存文档到临时文件
temp_path = os.path.join(OUTPUT_FOLDER, f"temp_{index}.docx")
tpl.save(temp_path)
# 打开文档进行样式修复
doc = Document(temp_path)
# 修复反思部分的字体大小(确保是小四12磅)
modified = False
if doc.tables:
for table in doc.tables:
if len(table.rows) >= 6:
# 反思部分在第6行(索引5)
reflection_row = table.rows[5]
# 反思部分通常是合并单元格,所以取第一个单元格
if len(reflection_row.cells) >= 1:
reflection_cell = reflection_row.cells[0]
for paragraph in reflection_cell.paragraphs:
for run in paragraph.runs:
# 设置为小四(12磅)
run.font.size = Pt(12)
# 确保是宋体
run.font.name = '宋体'
# 中文字体设置
run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
modified = True
if modified:
print(f" ✅ 修复反思部分字体为小四宋体")
# 生成文件名
month_str = str(row['month']) if pd.notna(row['month']) and str(row['month']) != 'nan' else str(index+1)
# try:
# month_formatted = f"{int(month_str):02d}月"
# except:
month_formatted = f"{month_str}月"
topic_short = str(row['name0'])[:] if pd.notna(row['name0']) and str(row['name0']) != 'nan' else '四大教育'
# filename = f"{month_formatted}_{kindgarden}_{original_classroom}_四大教育_{topic_short}_{CLASS_NAME[2]}()班.docx"
# 客户要求样式大班XX教育(3月).docx
filename = f"{topic_short}({month_formatted}).docx"
file_full_path = os.path.join(OUTPUT_FOLDER, filename)
# 保存修复后的文档
doc.save(file_full_path)
# 删除临时文件
if os.path.exists(temp_path):
os.remove(temp_path)
generated_files.append(file_full_path)
print(f"✅ 生成文档: {filename}")
except Exception as e:
print(f"❌ 生成第{index+1}行文档失败: {str(e)}")
import traceback
traceback.print_exc()
continue
print(f"\n📊 文档生成完成!共生成 {len(generated_files)} 个文档")
print(f"📂 文档保存在: {OUTPUT_FOLDER}")
return True
def process_word_document(input_path, output_path):
"""处理单个Word文档(aaa转手动换行符、空格缩进 + 修复字体大小)"""
try:
doc = Document(input_path)
modified = False
# 修复反思部分的字体大小(确保是小四)
if doc.tables:
for table in doc.tables:
if len(table.rows) >= 6:
reflection_row = table.rows[5]
if len(reflection_row.cells) >= 1:
reflection_cell = reflection_row.cells[0]
for paragraph in reflection_cell.paragraphs:
for run in paragraph.runs:
# 设置为小四(12磅)
if run.font.size != Pt(12):
run.font.size = Pt(12)
run.font.name = '宋体'
run._element.rPr.rFonts.set(qn('w:eastAsia'), '宋体')
modified = True
for table in doc.tables:
for row_idx, row in enumerate(table.rows, 1):
for col_idx, cell in enumerate(row.cells, 1):
# 收集所有需要处理的段落
paragraphs_to_process = []
for para_idx, para in enumerate(cell.paragraphs):
if 'aaa' in para.text:
paragraphs_to_process.append((para_idx, para))
# 添加空格缩进(第2列第7行)
if col_idx == 2 and row_idx == 7:
if para.text and not para.text.startswith(''):
para.text = '' + para.text
modified = True
# 处理包含aaa的段落
for para_idx, para in paragraphs_to_process:
# 保存原格式
runs_info = []
for run in para.runs:
runs_info.append({
'text': run.text,
'bold': run.bold,
'italic': run.italic,
'underline': run.underline,
'font_name': run.font.name,
'font_size': run.font.size,
'color': run.font.color.rgb if run.font.color else None
})
# 按aaa分割文本
full_text = para.text
parts = full_text.split('aaa')
# 清除原段落
para.clear()
# 重新添加分段内容
for i, part in enumerate(parts):
if part.strip(): # 如果有内容
# 创建新run并尝试保留原格式
run = para.add_run(part)
if runs_info:
# 使用第一个run的格式(简化处理)
run.bold = runs_info[0]['bold']
run.italic = runs_info[0]['italic']
run.underline = runs_info[0]['underline']
if runs_info[0]['font_name']:
run.font.name = runs_info[0]['font_name']
if runs_info[0]['font_size']:
run.font.size = runs_info[0]['font_size']
if runs_info[0]['color']:
run.font.color.rgb = runs_info[0]['color']
# 如果不是最后一段,添加手动换行符
if i < len(parts) - 1:
para.add_run().add_break(WD_BREAK.LINE)
modified = True
# 保存文档
doc.save(output_path)
# 如果保存成功
if os.path.exists(output_path):
return True, modified
else:
return False, False
except Exception as e:
print(f" 错误: {str(e)}")
import traceback
traceback.print_exc()
return False, False
def step3_process_documents():
"""第三步:处理生成的Word文档"""
print("\n" + "="*60)
print("第三步:处理Word文档(aaa转手动换行符、空格缩进)")
print("="*60)
# 创建输出文件夹
os.makedirs(PROCESSED_FOLDER, exist_ok=True)
print(f"输入文件夹: {OUTPUT_FOLDER}")
print(f"输出文件夹: {PROCESSED_FOLDER}")
print("-" * 60)
# 检查输入文件夹
if not os.path.exists(OUTPUT_FOLDER):
print(f"❌ 错误: 输入文件夹不存在!")
return False
# 获取所有docx文件
docx_files = [f for f in os.listdir(OUTPUT_FOLDER)
if f.lower().endswith('.docx')]
if not docx_files:
print(f"⚠️ 没有找到docx文件!")
return False
print(f"\n✅ 找到 {len(docx_files)} 个docx文件")
print("-" * 60)
# 处理文件
success = 0
for i, filename in enumerate(docx_files, 1):
print(f"[{i}/{len(docx_files)}] {filename}")
input_path = os.path.join(OUTPUT_FOLDER, filename)
output_filename = filename.replace('.docx', '.doc')
output_path = os.path.join(PROCESSED_FOLDER, output_filename)
result, modified = process_word_document(input_path, output_path)
if result:
if modified:
print(f" ✅ 已处理并保存")
else:
print(f" ⚠️ 无修改内容,已复制")
success += 1
else:
print(f" ❌ 处理失败")
print()
print(f"\n✅ 处理完成!成功处理 {success}/{len(docx_files)} 个文件")
print(f"📂 处理后文档保存在: {PROCESSED_FOLDER}")
return True
def check_winrar_installed():
"""检查WinRAR是否安装"""
possible_paths = [
r"C:\Program Files\WinRAR\WinRAR.exe",
r"C:\Program Files (x86)\WinRAR\WinRAR.exe"
]
for path in possible_paths:
if os.path.exists(path):
return path
return None
def step4_pack_to_rar():
"""第四步:打包成RAR文件"""
print("\n" + "="*60)
print("第四步:打包成RAR文件")
print("="*60)
# 检查最终文件夹是否存在
if not os.path.exists(PROCESSED_FOLDER):
print(f"❌ 错误:最终文件夹不存在 - {PROCESSED_FOLDER}")
return False
# 检查文件夹内是否有文件
files = os.listdir(PROCESSED_FOLDER)
if not files:
print(f"⚠️ 警告:最终文件夹为空,没有文件可打包")
return False
print(f"📁 待打包文件夹: {PROCESSED_FOLDER}")
print(f"📊 文件夹内共有 {len(files)} 个文件")
# 方法1:尝试使用WinRAR(如果已安装)
winrar_path = check_winrar_installed()
if winrar_path:
try:
print("🔄 正在使用WinRAR打包...")
# 构建WinRAR命令
cmd = [
winrar_path,
'a', # 添加到压缩文件
'-ep1', # 不保存路径信息
'-r', # 递归子目录
RAR_PATH,
f'{PROCESSED_FOLDER}\\*.*'
]
# 执行命令
result = subprocess.run(cmd, capture_output=True, text=True)
if os.path.exists(RAR_PATH):
size = os.path.getsize(RAR_PATH) / 1024 # KB
print(f"✅ 打包成功!")
print(f"📦 RAR文件: {RAR_PATH}")
print(f"📏 文件大小: {size:.2f} KB")
return True
else:
print("⚠️ WinRAR打包失败,尝试使用ZIP替代...")
return create_zip_backup()
except Exception as e:
print(f"⚠️ WinRAR打包出错: {str(e)}")
print("⚠️ 尝试使用ZIP替代...")
return create_zip_backup()
else:
print("⚠️ 未找到WinRAR,将使用ZIP格式打包...")
return create_zip_backup()
def create_zip_backup():
"""创建ZIP备份(当WinRAR不可用时)"""
try:
print("🔄 正在创建ZIP压缩文件...")
# 创建ZIP文件
with zipfile.ZipFile(ZIP_PATH, 'w', zipfile.ZIP_DEFLATED) as zipf:
for root, dirs, files in os.walk(PROCESSED_FOLDER):
for file in files:
file_path = os.path.join(root, file)
arcname = os.path.relpath(file_path, PROCESSED_FOLDER)
zipf.write(file_path, arcname)
if os.path.exists(ZIP_PATH):
size = os.path.getsize(ZIP_PATH) / 1024 # KB
print(f"✅ ZIP打包成功!")
print(f"📦 ZIP文件: {ZIP_PATH}")
print(f"📏 文件大小: {size:.2f} KB")
# 询问是否要重命名为RAR(虽然实际上是ZIP)
print("\n注:由于系统没有安装WinRAR,已生成ZIP格式文件")
print("如需RAR格式,请手动安装WinRAR后重新运行此步骤")
return True
else:
print("❌ ZIP打包失败")
return False
except Exception as e:
print(f"❌ ZIP打包出错: {str(e)}")
return False
def main():
"""主函数 - 执行完整工作流"""
print("\n" + "="*60)
print("二分园四大教育 - 完整工作流")
print("="*60)
print(f"基础路径: {BASE_PATH}")
print(f"班级: {CLASS_NAME}")
print(f"主题: {EDU_THEME}")
print("="*60)
# 自动执行完整工作流(不需要用户选择)
print("\n开始执行完整工作流...")
# # 第一步:生成Excel
# if not step1_generate_excel():
# print("❌ 第一步失败,程序终止")
# return
# 第二步:生成Word文档
if not step2_generate_word_from_excel():
print("❌ 第二步失败,程序终止")
return
# 第三步:处理文档
if not step3_process_documents():
print("❌ 第三步失败,程序终止")
return
# 第四步:打包成RAR
step4_pack_to_rar()
print("\n" + "="*60)
print("🎉 完整工作流执行完成!")
print("="*60)
print(f"\n📂 生成的文件位置:")
print(f"1. Excel占位符文件: {EXCEL_PATH}")
print(f"2. 原始Word文档: {OUTPUT_FOLDER}")
print(f"3. 处理后的Word文档: {PROCESSED_FOLDER}")
# 显示打包文件
if os.path.exists(RAR_PATH):
print(f"4. RAR压缩包: {RAR_PATH}")
elif os.path.exists(ZIP_PATH):
print(f"4. ZIP压缩包: {ZIP_PATH}")
print("="*60)
if __name__ == "__main__":
main()

出现两个月月

excle里面有月

正确的是只有数字,没有月


月变成数字后,文件名就正常了




(四)发给负责人


感悟:
复用代码,把半年前做的"五大教育"代码继续优化一下
不做input回车暂停,拆分成两个:
1.制作Excel标题列+黏贴AI生成的表格文字
2.把Excel内容贴入docx内。
最后不能忘记把word模版上传(每年都要word里面的2026第一学期和该文档包含的班级们的名称)

