
一、背景需求
(一)资料获取
今年我带中2班,问去年中2班(现大2班)的老师要了他们班的班级电子资料

发来的资料里面,育儿知识(家园小报)只有一个9月份的,应该每个月一份
分类整理

这个育儿知识(小报)的背景图还是很好看的

可惜只有一个月的,我不想再问大2班老师索要了,她说自己也是费力整理过的(两位老师分工写的班级电子资料,合并后难免也会有遗漏)
(二)制作思路
之前用豆包AI做了全园班级的"国旗下讲话""四大教育",展现出豆包AI编写文字的强大能力。
我想用豆包编写另外几个月家园小报的文字(表格形式),再用Python写入到word。
二、word模版制作
(根据现有的word模版制作,包含教师名字、家委会成员名字等)
(一)复制模版

(二)doc另存为docx


(三)把基础信息改成占位符


标题原来有一个特殊字体,而且是艺术字插入(可以卷曲),我现在没有这个字体,艺术字,所以还是改成普通的标题。

由于背景图在顶层,所以育儿知识几个字不好修改,改成放在文字下方

但是图片放在文字下方,还是不能编辑文字,就把图片缩小拖到别的地方,现在育儿知识(艺术字)就可以编辑了。


为了方便,我把艺术字框删除了,第一行重新做标题



第一段有370-380字

第一段改成congtent1



第二段大约350-360字



把背景图剪切,重新黏贴成图片,然后用冲蚀点中间,再把图片置于文字底部。这样文字就能够编辑了。不会被图片遮挡

三、EXCEL数据制作

(一)制作EXCEL的列标题




python
'''
育儿知识(中2班)
excle的列标题制作(占位符字母)
豆包、Deepseek、阿夏
2026096
'''
import pandas as pd
import os
# ========== 路径配置 ==========
BASE_PATH = r'D:\Python最终内容\20260906育儿知识中2'
CLASS_NAME = "中2班"
EDU_THEME = "全部主题"
date = '20260904'
EXCEL_PATH = os.path.join(BASE_PATH, f"{date}{CLASS_NAME}育儿知识({EDU_THEME}).xlsx")
# 表头字段【已改成docx模板里面{{}}内的标识符】
columns = [
'classroom','title','T1','T2','S',
'parent','content1','title2','content2',
'year', 'month'
]
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()


(二)根据9月份的育儿知识的word模版内容,制作10份符合节日制作EXCEL的列标题。
1.第1次





点击豆包表格右上角的复制

打开EXCEL,把内容黏贴



但是每行有三段,这样无法整段写入

2.第2次:每段用aaa连接






(三)Python代码


实验代码,不要用
python
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育儿知识中2'
CLASS_NAME = "中2班"
EDU_THEME = "全部主题"
date = '20260904'
# ==============================================
EXCEL_PATH = os.path.join(BASE_PATH, f"{date}{CLASS_NAME}育儿知识({EDU_THEME}).xlsx")
TEMPLATE_PATH = os.path.join(BASE_PATH, "育儿知识模版.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文件(字段和docx模板占位符一一对应)"""
# print("\n" + "="*60)
# print("第一步:生成占位符Excel文件")
# print("="*60)
# # 与docx模板{{}}一一对应,去掉大括号作为列名
# df = pd.DataFrame(columns=[
# 'classroom','title','T1','T2','S','parent',
# 'content1','title2','content2','year','month'
# ])
# df.to_excel(EXCEL_PATH, index=False)
# print(f"✅ Excel文件已生成:{EXCEL_PATH}")
# print(f"📋 Excel表头:{list(df.columns)}")
# # 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不存在 - {EXCEL_PATH}")
return False
if not os.path.exists(TEMPLATE_PATH):
print(f"❌ 错误:模板文件不存在 - {TEMPLATE_PATH}")
return False
schedule = pd.read_excel(EXCEL_PATH)
# 全部字段转为字符串,nan替换为空
excel_cols = ['classroom','title','T1','T2','S','parent','content1','title2','content2','year','month']
for col in excel_cols:
if col in schedule.columns:
schedule[col] = schedule[col].astype(str).replace('nan', '')
# 设置默认值
if 'classroom' not in schedule.columns:
schedule['classroom'] = CLASS_NAME
if 'T1' not in schedule.columns:
schedule['T1'] = '王'
if 'T2' not in schedule.columns:
schedule['T2'] = '张'
if 'S' not in schedule.columns:
schedule['S'] = '张三'
if 'parent' not in schedule.columns:
schedule['parent'] = '妈妈'
if 'year' not in schedule.columns:
schedule['year'] = '2026'
if 'month' not in schedule.columns:
schedule['month'] = '9'
schedule.to_excel(EXCEL_PATH, index=False)
print(f"✅ 已保存Excel")
print(f"📊 共有 {len(schedule)} 行数据")
try:
Document(TEMPLATE_PATH)
print("✅ 模板验证通过,开始生成文档...")
except Exception as e:
print(f"❌ 模板无效: {e}")
return False
for index, row in schedule.iterrows():
try:
tpl = DocxTemplate(TEMPLATE_PATH)
# 渲染上下文,完全匹配docx模板{{占位符}}
context = {
"classroom": str(row['classroom']) if pd.notna(row['classroom']) else CLASS_NAME,
"title": str(row['title']) if pd.notna(row['title']) else '',
"T1": str(row['T1']) if pd.notna(row['T1']) else '王',
"T2": str(row['T2']) if pd.notna(row['T2']) else '张',
"S": str(row['S']) if pd.notna(row['S']) else '张三',
"parent": str(row['parent']) if pd.notna(row['parent']) else '妈妈',
"content1": str(row['content1']) if pd.notna(row['content1']) else '',
"title2": str(row['title2']) if pd.notna(row['title2']) else '',
"content2": str(row['content2']) if pd.notna(row['content2']) else '',
"year": str(row['year']) if pd.notna(row['year']) else '2026',
"month": str(row['month']) if pd.notna(row['month']) else '9',
}
tpl.render(context)
temp_path = os.path.join(OUTPUT_FOLDER, f"temp_{index}.docx")
tpl.save(temp_path)
doc = Document(temp_path)
# ========== 修改这里:文件名:"年月"育儿知识(标题名称) ==========
month_str = str(row['month']) if pd.notna(row['month']) else str(index+1)
year_str = str(row['year']) if pd.notna(row['year']) else '2026'
title_short = str(row['title'])[:18] if pd.notna(row['title']) else '育儿知识'
filename = f"{year_str}.{month_str} 育儿知识({title_short}).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替换为手动换行符WD_BREAK.LINE"""
try:
doc = Document(input_path)
modified = False
# 遍历文档所有段落,处理aaa分隔符
for para in doc.paragraphs:
if 'aaa' in para.text:
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
})
full_text = para.text
parts = full_text.split('aaa')
para.clear()
for i, part in enumerate(parts):
if part.strip():
run = para.add_run(part)
if runs_info:
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']
run._element.rPr.rFonts.set(qn('w:eastAsia'), 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_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
output_path = os.path.join(PROCESSED_FOLDER, output_filename)
result, modified = process_word_document(input_path, output_path)
if result:
if modified:
print(f" ✅ aaa已替换换行,已保存")
else:
print(f" ⚠️ 无aaa标记,直接复制")
success += 1
else:
print(f" ❌ 处理失败")
print()
print(f"\n✅ 处理完成!成功处理 {success}/{len(docx_files)} 个文件")
print(f"📂 处理后文档保存在: {PROCESSED_FOLDER}")
return True
def check_winrar_installed():
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/ZIP"""
print("\n" + "="*60)
print("第四步:打包压缩文件")
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)}")
winrar_path = check_winrar_installed()
if winrar_path:
try:
print("🔄 使用WinRAR打包...")
cmd = [
winrar_path,
'a',
'-ep1',
'-r',
RAR_PATH,
f'{PROCESSED_FOLDER}\\*.*'
]
subprocess.run(cmd, capture_output=True, text=True)
if os.path.exists(RAR_PATH):
size = os.path.getsize(RAR_PATH) / 1024
print(f"✅ RAR打包成功!📏 {size:.2f} KB")
return True
else:
print("⚠️ WinRAR打包失败,切换ZIP")
return create_zip_backup()
except Exception as e:
print(f"⚠️ WinRAR异常:{e},切换ZIP")
return create_zip_backup()
else:
print("⚠️ 未检测WinRAR,生成ZIP")
return create_zip_backup()
def create_zip_backup():
try:
print("🔄 创建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:
fp = os.path.join(root, file)
arc = os.path.relpath(fp, PROCESSED_FOLDER)
zipf.write(fp, arc)
if os.path.exists(ZIP_PATH):
size = os.path.getsize(ZIP_PATH)/1024
print(f"✅ ZIP打包成功!📏 {size:.2f} KB")
print("注:如需RAR格式,请安装WinRAR后重新运行")
return True
else:
print("❌ ZIP打包失败")
return False
except Exception as e:
print(f"❌ ZIP出错:{e}")
return False
def main():
print("\n" + "="*60)
print("一分园|育儿知识(中2班)完整工作流")
print("="*60)
print(f"基础路径: {BASE_PATH}")
print(f"班级: {CLASS_NAME}")
print(f"业务: {EDU_THEME}")
print("="*60)
# # 第一步:生成Excel占位符(取消注释启用)
# if not step1_generate_excel():
# print("❌ 第一步失败,程序终止")
# return
# 第二步:生成Word
if not step2_generate_word_from_excel():
print("❌ 第二步失败,程序终止")
return
# 第三步:处理aaa换行
if not step3_process_documents():
print("❌ 第三步失败,程序终止")
return
# 第四步打包
step4_pack_to_rar()
print("\n" + "="*60)
print("🎉 全部流程完成!")
print("="*60)
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()

修改内容




修改1:段落前空格




修改2:去掉RAR

修改3 删除过度文件




修改4:文字少了,尝试增加文字数量








虽然改成400字,但有的内容还是很少。
改成450字





还是很少,我决定重新开一个豆包界面,用450字
请根据附件 1 里面的文字的样式,和附件 2 的占位符字母,帮我做 10 份差不多的育儿知识内容(2026 年 9-12 月,2027 年 1-6 月)根据季节和中班幼儿年龄特点编写差不多的内容。content1 大约 450 字,content2 大约 450 字,year 写 2026 或 2026,month 写数字,不要 "月",编写的内容做成表格形式。,T1 = 王 T2 = 张,S = 张三,parent = 妈妈。其中 content1 和 content2 的多段内容用 aaa 连接,


这次字多了一点,有一份还超过底部











我已经用了450字了,但是还是凑不满页面,所以考虑,增加行距。




很好!文字很满了

(四)修改班级、老师、家长姓名
那么把班级、老师、家长名字修改好。再手动消除几段文字。

'

'

再生成一次
python
'''
育儿知识(中2班)
1. 生成占位符Excel
2. 根据Excel生成Word文档
3. 处理Word文档(aaa转手动换行符、空格缩进)
豆包、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育儿知识中2'
CLASS_NAME = "中2班"
EDU_THEME = "全部主题"
date = '20260904'
# ==============================================
EXCEL_PATH = os.path.join(BASE_PATH, f"{date}{CLASS_NAME}育儿知识({EDU_THEME}).xlsx")
TEMPLATE_PATH = os.path.join(BASE_PATH, "育儿知识模版.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文件(字段和docx模板占位符一一对应)"""
# print("\n" + "="*60)
# print("第一步:生成占位符Excel文件")
# print("="*60)
# # 与docx模板{{}}一一对应,去掉大括号作为列名
# df = pd.DataFrame(columns=[
# 'classroom','title','T1','T2','S','parent',
# 'content1','title2','content2','year','month'
# ])
# df.to_excel(EXCEL_PATH, index=False)
# print(f"✅ Excel文件已生成:{EXCEL_PATH}")
# print(f"📋 Excel表头:{list(df.columns)}")
# # 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不存在 - {EXCEL_PATH}")
return False
if not os.path.exists(TEMPLATE_PATH):
print(f"❌ 错误:模板文件不存在 - {TEMPLATE_PATH}")
return False
schedule = pd.read_excel(EXCEL_PATH)
# 全部字段转为字符串,nan替换为空
excel_cols = ['classroom','title','T1','T2','S','parent','content1','title2','content2','year','month']
for col in excel_cols:
if col in schedule.columns:
schedule[col] = schedule[col].astype(str).replace('nan', '')
# 设置默认值
if 'classroom' not in schedule.columns:
schedule['classroom'] = CLASS_NAME
if 'T1' not in schedule.columns:
schedule['T1'] = '王'
if 'T2' not in schedule.columns:
schedule['T2'] = '张'
if 'S' not in schedule.columns:
schedule['S'] = '张三'
if 'parent' not in schedule.columns:
schedule['parent'] = '妈妈'
if 'year' not in schedule.columns:
schedule['year'] = '2026'
if 'month' not in schedule.columns:
schedule['month'] = '9'
schedule.to_excel(EXCEL_PATH, index=False)
print(f"✅ 已保存Excel")
print(f"📊 共有 {len(schedule)} 行数据")
try:
Document(TEMPLATE_PATH)
print("✅ 模板验证通过,开始生成文档...")
except Exception as e:
print(f"❌ 模板无效: {e}")
return False
for index, row in schedule.iterrows():
try:
tpl = DocxTemplate(TEMPLATE_PATH)
# 渲染上下文,完全匹配docx模板{{占位符}}
context = {
"classroom": str(row['classroom']) if pd.notna(row['classroom']) else CLASS_NAME,
"title": str(row['title']) if pd.notna(row['title']) else '',
"T1": str(row['T1']) if pd.notna(row['T1']) else '王',
"T2": str(row['T2']) if pd.notna(row['T2']) else '张',
"S": str(row['S']) if pd.notna(row['S']) else '张三',
"parent": str(row['parent']) if pd.notna(row['parent']) else '妈妈',
"content1": str(row['content1']) if pd.notna(row['content1']) else '',
"title2": str(row['title2']) if pd.notna(row['title2']) else '',
"content2": str(row['content2']) if pd.notna(row['content2']) else '',
"year": str(row['year']) if pd.notna(row['year']) else '2026',
"month": str(row['month']) if pd.notna(row['month']) else '9',
}
tpl.render(context)
temp_path = os.path.join(OUTPUT_FOLDER, f"temp_{index}.docx")
tpl.save(temp_path)
doc = Document(temp_path)
# 月份自动补0:9→09,1→01,11→11
month_str = str(row['month']) if pd.notna(row['month']) else str(index+1)
month_str = month_str.zfill(2)
year_str = str(row['year']) if pd.notna(row['year']) else '2026'
title_short = str(row['title'])[:18] if pd.notna(row['title']) else '育儿知识'
filename = f"{year_str}.{month_str} 育儿知识({title_short}).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替换为手动换行符WD_BREAK.LINE"""
try:
doc = Document(input_path)
modified = False
# 遍历文档所有段落,处理aaa分隔符
for para in doc.paragraphs:
if 'aaa' in para.text:
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
})
full_text = para.text
parts = full_text.split('aaa')
para.clear()
for i, part in enumerate(parts):
part = part.strip()
if part:
# 不是第一段,开头增加4个半角空格
if i > 0:
part = ' ' + part
run = para.add_run(part)
if runs_info:
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']
run._element.rPr.rFonts.set(qn('w:eastAsia'), 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_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
output_path = os.path.join(PROCESSED_FOLDER, output_filename)
result, modified = process_word_document(input_path, output_path)
if result:
if modified:
print(f" ✅ aaa已替换换行,已保存")
else:
print(f" ⚠️ 无aaa标记,直接复制")
success += 1
else:
print(f" ❌ 处理失败")
print()
print(f"\n✅ 处理完成!成功处理 {success}/{len(docx_files)} 个文件")
print(f"📂 处理后文档保存在: {PROCESSED_FOLDER}")
return True
def check_winrar_installed():
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/ZIP"""
print("\n" + "="*60)
print("第四步:打包压缩文件")
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)}")
winrar_path = check_winrar_installed()
if winrar_path:
try:
print("🔄 使用WinRAR打包...")
cmd = [
winrar_path,
'a',
'-ep1',
'-r',
RAR_PATH,
f'{PROCESSED_FOLDER}\\*.*'
]
subprocess.run(cmd, capture_output=True, text=True)
if os.path.exists(RAR_PATH):
size = os.path.getsize(RAR_PATH) / 1024
print(f"✅ RAR打包成功!📏 {size:.2f} KB")
return True
else:
print("⚠️ WinRAR打包失败,切换ZIP")
return create_zip_backup()
except Exception as e:
print(f"⚠️ WinRAR异常:{e},切换ZIP")
return create_zip_backup()
else:
print("⚠️ 未检测WinRAR,生成ZIP")
return create_zip_backup()
def create_zip_backup():
try:
print("🔄 创建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:
fp = os.path.join(root, file)
arc = os.path.relpath(fp, PROCESSED_FOLDER)
zipf.write(fp, arc)
if os.path.exists(ZIP_PATH):
size = os.path.getsize(ZIP_PATH)/1024
print(f"✅ ZIP打包成功!📏 {size:.2f} KB")
print("注:如需RAR格式,请安装WinRAR后重新运行")
return True
else:
print("❌ ZIP打包失败")
return False
except Exception as e:
print(f"❌ ZIP出错:{e}")
return False
def main():
print("\n" + "="*60)
print("一分园|育儿知识(中2班)完整工作流")
print("="*60)
print(f"基础路径: {BASE_PATH}")
print(f"班级: {CLASS_NAME}")
print(f"业务: {EDU_THEME}")
print("="*60)
# 第一步:生成Excel占位符(取消注释启用)
# if not step1_generate_excel():
# print("❌ 第一步失败,程序终止")
# return
# 第二步:生成Word
if not step2_generate_word_from_excel():
print("❌ 第二步失败,程序终止")
return
# 第三步:处理aaa换行
if not step3_process_documents():
print("❌ 第三步失败,程序终止")
return
# 第四步打包
# step4_pack_to_rar()
# ==========新增:删除OUTPUT_FOLDER临时输出文件夹 ==========
try:
if os.path.exists(OUTPUT_FOLDER):
shutil.rmtree(OUTPUT_FOLDER)
print(f"\n🗑️ 已删除临时文件夹:{OUTPUT_FOLDER}")
except Exception as e:
print(f"\n⚠️ 删除临时文件夹失败,请手动删除:{OUTPUT_FOLDER},错误信息:{str(e)}")
# ==========================================================
print("\n" + "="*60)
print("🎉 全部流程完成!")
print("="*60)
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里面删除)
运行后就是一页的

(五)把docx合并PDF便于打印
1.找以前的代码,复用代码

2.手动修改各类参数
把word保存为PDF(放到另外一个文件夹)






再把单个PDF转为图片JPG,制作园园通上传图片







第三个代码

python
'''
育儿知识(中2班)
把育儿知识202609-202706的docx转PDF,多个PDF合并PDF、转为图片
星火讯飞、阿夏
20260910
'''
from docx2pdf import convert
import os
from PyPDF2 import PdfMerger
import fitz # PyMuPDF
import time
BASE_PATH = r'D:\Python最终内容\20260906育儿知识中2'
CLASS_NAME = "中2班"
EDU_THEME = "全部主题"
date = '20260910'
new_folder = BASE_PATH + fr'\01 ({CLASS_NAME}){EDU_THEME}_最终'
PDF_folder = BASE_PATH + fr'\01 ({CLASS_NAME}){EDU_THEME}_PDF'
JPG_folder = BASE_PATH + fr'\01 ({CLASS_NAME}){EDU_THEME}_JPG'
# 创建文件夹
os.makedirs(PDF_folder, exist_ok=True)
os.makedirs(JPG_folder, exist_ok=True)
# ==========1.docx批量转PDF==========
docx_files = [f for f in os.listdir(new_folder) if f.endswith('.docx') and not f.startswith('~$')]
for docx in docx_files:
inputFile = os.path.join(new_folder, docx)
pdf_name = os.path.splitext(docx)[0] + '.pdf'
outputFile = os.path.join(PDF_folder, pdf_name)
print(f"正在转换word:{docx}")
convert(inputFile, outputFile)
time.sleep(2)
print('----------Word转PDF完成------------')
# ==========2.所有PDF合并为打印总PDF==========
print('----------开始合并PDF------------')
pdf_lst = [f for f in os.listdir(PDF_folder) if f.endswith('.pdf')]
pdf_lst.sort()
file_merger = PdfMerger()
for pdf in pdf_lst:
pdf_path = os.path.join(PDF_folder, pdf)
print(f"合并:{pdf_path}")
file_merger.append(pdf_path)
merged_pdf_path = os.path.join(BASE_PATH, f"{date}{CLASS_NAME}育儿知识{len(docx_files)}份_打印版.pdf")
file_merger.write(merged_pdf_path)
file_merger.close()
print(f"合并完成,输出:{merged_pdf_path}")
# ==========3.PDF文件夹每个PDF转JPG图片【PyMuPDF,无需poppler】==========
print('----------PDF批量转JPG图片------------')
for pdf_file in pdf_lst:
pdf_full_path = os.path.join(PDF_folder, pdf_file)
base_name = os.path.splitext(pdf_file)[0]
print(f"正在转图片:{pdf_file}")
doc = fitz.open(pdf_full_path)
for page_idx, page in enumerate(doc, start=1):
# zoom控制清晰度,zoom=2≈200DPI
mat = fitz.Matrix(2, 2)
pix = page.get_pixmap(matrix=mat)
jpg_filename = f"{base_name}.jpg"
jpg_save_path = os.path.join(JPG_folder, jpg_filename)
pix.save(jpg_save_path)
doc.close()
time.sleep(0.5)
print("\n✅全部任务完成:")
print(f"👉单份PDF目录:{PDF_folder}")
print(f"👉JPG图片目录:{JPG_folder}")
print(f"👉合并打印PDF:{merged_pdf_path}")






word模版上传
(不过没有什么复用可能,每个班级的育儿知识模版都不同。学期用的模版都不同,都要重新制作占位符字母)

四、分类整理
(一)word转入学期文件夹




(二)PDF 合并打印
明天就去彩打
