
背景需求:
20250214作为信息员,我会每周去区里的“信息平台”上报“教育教学”相关的通讯。因此领导在周五把每周的周计划安排表(docx)发我。

因为之前做了校历、营养员的人数统计表、各班点名册、本班周计划教案。
【办公类-53-04】20250209Python模仿制作2024学年第二学期校历-CSDN博客文章浏览阅读432次,点赞14次,收藏5次。【办公类-53-04】20250209Python模仿制作2024学年第二学期校历
https://blog.csdn.net/reasonsummer/article/details/145537780?sharetype=blogdetail&sharerId=145537780&sharerefer=PC&sharesource=reasonsummer&spm=1011.2480.3001.8118【办公类-54-03】20250219营养员《每周人数统计表》(双休日、国定假日,变成灰色)-CSDN博客文章浏览阅读933次,点赞21次,收藏17次。【办公类-54-03】20250219营养员《每周人数统计表》(双休国定假涂成灰色)
https://blog.csdn.net/reasonsummer/article/details/145577907?spm=1001.2014.3001.5501【办公类-54-04】20250210班级点名册模版(双休国定假涂成灰色)2024学年第二学期,读取上学期名单-CSDN博客文章浏览阅读848次,点赞32次,收藏9次。【办公类-54-04】20250210班级点名册模版(双休国定假涂成灰色)2024学年第二学期,读取上学期名单
https://blog.csdn.net/reasonsummer/article/details/145583809?spm=1001.2014.3001.5501
所以,我立刻从这份周安排里看到了“周次、起止月日、周一到周五、五天年月”

运用营养员的7天思路,把每周安排里的日期都批量做好吧
WORD模版
把第一周的模版分析需要哪些数据:
1、标题栏:周次、一周的周一(年月)、一周的周五(年月)

2、侧边栏:一周的每天的日期(月、日)、星期(周一到周五)

我觉得还是统一做一周7天的模版(如4月27日周日调休上班),同时双休日也有部分老师或领导也要干活(参加工会活动或者带孩子们参加OM比赛等)
所以模版统一做成7天,星期一到日的汉字直接写模版里,标题日期统一写周一到周日的日期(年月日)


对应的EXCLE标题制作
'''
把领导的每周安排的模版的日期批量做好(1)——制作日期数字
如果有空格,全部要加一个空格,否则读取出来的年月日是一位小数浮点数
星火讯飞,阿夏
2025年2月14日
'''
# -*- coding: utf-8 -*-
import datetime
import openpyxl
from openpyxl.styles import Alignment, PatternFill
import time
import pandas as pd
import re
from openpyxl import load_workbook
# for
path=r'C:\Users\jg2yXRZ\OneDrive\桌面\20250214领导的每周安排模板'
# 1、制作基础日期表
title='2024学年第二学期校历'
tt=path+fr"\02-01 {title}.xlsx"
# 创建一个新的Excel工作簿
workbook = openpyxl.Workbook()
sheet = workbook.active
# 设置标题行
title_row = ["week", "D1", "D2", "D3", "D4", "D5", "D6", "D7"]
sheet.append(title_row)
# 设置日期范围
start_date = datetime.date(2025, 2, 17)
end_date = datetime.date(2025, 6, 30)
# 计算周数和日期
current_week = 1
current_day = start_date
while current_day <= end_date:
# 获取当前周的第一天(星期一)
week_start = current_day - datetime.timedelta(days=current_day.weekday())
# 如果当前日期是新的一周,添加新行并更新周数
if current_day == week_start:
sheet.append([f"第{current_week:02d}周"])
current_week += 1
# 在正确的单元格中添加日期
column_index = current_day.weekday() + 2 # 从B列开始,所以加2year
cell = sheet.cell(row=current_week, column=column_index)
# 不同的表示方法
# cell.value = current_day.strftime("%Y-%m-%d") # 2024-09-01
# cell.value = current_day.strftime("%Y-%#m-%#d") # 2024-9-1
# cell.value = current_day.strftime("%m/%d") # 09-01
# cell.value = current_day.strftime("%#m/%#d") # 9-1
# cell.value = current_day.strftime('%Y{y}%m{m}%d{d}').format(y='年', m='月', d='日') # 2024年09月01日
cell.value = current_day.strftime('%Y{y}%#m{m}%#d{d}').format(y='年', m='月', d='日') # 2024年9月1日
cell.alignment = Alignment(horizontal='center', vertical='center')
# 如果日期不等于周六和周日,就把这个单元格填充为浅黄色
if current_day.weekday() not in (5, 6):
light_yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
cell.fill = light_yellow_fill
# 如果日期等于2024-09-14、2024-10-12、9月16日、9月17日、10月1日到10月8日、2025年1月1日,单元格填充为白色
special_dates = [datetime.date(2025, 4, 4), datetime.date(2025, 5, 1), datetime.date(2025, 5, 2), datetime.date(2025, 5, 5),datetime.date(2025, 6, 2)]
# for i in range(1, 8):
# special_dates.append(datetime.date(2024, 10, i))
# special_dates.append(datetime.date(2025, 1, 1))
if current_day in special_dates:
white_fill = PatternFill(start_color="FFFFFF", end_color="FFFFFF", fill_type="solid")
cell.fill = white_fill
# # 如果日期等于2024-09-14或2024-10-12,单元格填充为黄色
# if current_day == datetime.date(2025, 4, 27) or current_day == datetime.date(2024, 9, 29) or current_day == datetime.date(2024, 10, 12):
if current_day == datetime.date(2025, 4, 27):
yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
cell.fill = yellow_fill
# 移动到下一天
current_day += datetime.timedelta(days=1)
# 设置列宽
for col in range(1, 30):
sheet.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 15
# for col in range(9, 12):
# sheet.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 35
# 设置单元格文字居中
for row in sheet.iter_rows():
for cell in row:
cell.alignment = openpyxl.styles.Alignment(horizontal='center', vertical='center')
# 打印所有黄色底纹填充格子的坐标
yellow_coordinates = []
for row in sheet.iter_rows():
for cell in row:
if cell.fill and cell.fill.start_color.rgb == 'FFFF00':
yellow_coordinates.append((cell.row, cell.column))
print("Yellow filled cells coordinates:", yellow_coordinates)
# 以下是拆分信息(提取第一天和最后一天)
#
# workbook.save(tt)
# time.sleep(1)
# # 读取第3列第二行开始的单元格文字,截取“年”前面的部分,写入第12列的第2行写入。同时在第12列的第1行写入“year”
# # 示例数据
# # b = [3, 4,5]
# # 加载已存在的Excel文件
# workbook = openpyxl.load_workbook(tt)
# sheet = workbook.active
n=1
# 读取标题中的信息
# 读取B列:
for i in range(2, sheet.max_row + 1):
cell_value = sheet.cell(row=i, column=2).value
# for x in range(9,12):
if cell_value:
match = re.search(r'(\d+)年', cell_value)
year_part = match.group(1)
sheet.cell(row=i, column=9).value = year_part
if cell_value:
match = re.search(r'年(\d+)月', cell_value)
month_part = match.group(1)
sheet.cell(row=i, column=10).value = month_part
if cell_value:
match = re.search(r'月(\d+)日', cell_value)
day_part = match.group(1)
sheet.cell(row=i, column=11).value = day_part
# 在第12列的第1行写入“year”
sheet.cell(row=1, column=9).value = f"year1"
sheet.cell(row=1, column=10).value = f"month1"
sheet.cell(row=1, column=11).value = f"day11"
# 读取H列:
for i in range(2, sheet.max_row + 1):
cell_value = sheet.cell(row=i, column=8).value
# for x in range(9,12):
if cell_value:
match = re.search(r'(\d+)年', cell_value)
year_part = match.group(1)
sheet.cell(row=i, column=12).value = year_part
if cell_value:
match = re.search(r'年(\d+)月', cell_value)
month_part = match.group(1)
sheet.cell(row=i, column=13).value = month_part
if cell_value:
match = re.search(r'月(\d+)日', cell_value)
day_part = match.group(1)
sheet.cell(row=i, column=14).value =f'{day_part}'
# 在第12列的第1行写入“year”
sheet.cell(row=1, column=12).value = f"year2"
sheet.cell(row=1, column=13).value = f"month2"
sheet.cell(row=1, column=14).value = f"day22"
# 读取玥日
# 读取各列中的日期,提取月和日,写入相应列
columns_to_process = [2, 3, 4, 5, 6,7,8] # B列到F列
output_columns = [15, 16, 17, 18, 19,20,21] # 对应输出的列(H列到L列)
for col_idx, col in enumerate(columns_to_process):
for i in range(2, sheet.max_row + 1):
cell_value = sheet.cell(row=i, column=col).value
if cell_value:
match = re.search(r'(\d+)年(\d+)月(\d+)日', cell_value)
if match:
month_part = match.group(2)
day_part = match.group(3)
sheet.cell(row=i, column=output_columns[col_idx]).value = f"{month_part}.{day_part}"
# 在第12列的第1行写入“year”
sheet.cell(row=1, column=output_columns[col_idx]).value = f"day{col_idx+1}"
# # 读取各列中的日期,提取月和日,写入相应列
# 设置黄色填充样式
yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
# 要处理的列和对应的输出列
columns_to_process = [2, 3, 4, 5, 6, 7,8] # B列到G列
output_columns = [22, 23, 24, 25, 26, 27,28] # 对应输出的列(Y列到D列)
for col_idx, col in enumerate(columns_to_process):
for i in range(2, sheet.max_row + 1):
cell = sheet.cell(row=i, column=col)
cell_value = cell.value
# 如果单元格有黄色填充,则复制填充样式到输出列
if cell.fill == yellow_fill:
output_cell = sheet.cell(row=i, column=output_columns[col_idx])
output_cell.fill = yellow_fill
else:
# 如果单元格没有黄色填充(白色),就在里面写入“双休日休息”
sheet.cell(row=i, column=output_columns[col_idx]).value = "休息"
# else:
# 只对真正放假的那一天进行备注 清明1天,劳动1天
dayss=['2025年4月4日','2025年4月27日','2025年5月1日','2025年5月31日',]
jr=['清明节放假','劳动节调班,今天要上班的!','劳动节放假','端午节放假']
for ddd in range(len(dayss)):
# 检查日期是否为2025年4月4日
if cell_value ==dayss[ddd]:
sheet.cell(row=i, column=output_columns[col_idx]).value = jr[ddd]
# 在第12列的第1行写入“year”,复制的时候不要复制文字
sheet.cell(row=1, column=output_columns[col_idx]).value = f"x{col_idx+1}"
# 保存工作簿
workbook.save(tt)
这个代码运行后,直接出现一个EXCEL

代码的第1部分生成基本的起止日期(20周)并用黄色标出上班的日期
代码第2部分提取B列(列名:D1)(每周第一天周一)的年、月、日,分别放在I、J、K列
代码第2部分提取H列(列名:D7)(每周第七天周日)的年、月、日,分别放在LMN列

代码第3部分是,把D1-D7的年月日里,提取其中的“月”+“日”,变成文件名上的日期,写入day1-day7



代码第4部分是,把D1-D7的年月日,如果格子里黄色底纹,就复制到x1-x7里(只复制底纹,不复制文字)、没有黄色底纹的地方(白色)就全部写入“休息”(包括双休日和节假日的空格),最后查找特殊节日的年月日,如果有这些日期的格子,再对应的格子写入“XX节放假”


我是根据网络日历写的,它们显示,真正的“XX节”实际只有1天,放的3天、5天,大部分是双休日,所以我写了一天“XX节”。其他几天都是“休息”,并不是3、5天都写XX节


现在EXCLE生成的表格做好了。
我后面后面代码生成批量docx后,发现文件名的第二个日期变成了1位浮点数,但是第一个日期是正常的

内部的标题里面的第二个日期(年月日)也变成了1位浮点数。


研究半天,是因为6月30日后面的日期是空的。如果输入一个空格,它就能够显示出来

所以第一个代码的最后一步就是读取行数,然后查找I-U列里面是否有空格,有空格就输入一个“ ”
现在是什么都没有。

添加一段代码,先把空单元格写入111

顺利替换为111

生成的EXCLE里面,空单元格里面就有一个‘ ’看不见的空格

用第二个代码运行后,第二个日期也正常了

第一个修改代码
'''
把领导的每周安排的模版的日期批量做好(2)——批量生成模版
如果有空格,全部要加一个空格,否则读取出来的年月日是一位小数浮点数
星火讯飞,阿夏
2025年2月14日
'''
import pandas as pd
import openpyxl
from openpyxl import load_workbook
import copy
print('------------1、读取表格里整理好的周日、日期,列表形式')
# 一、导入相关模块,设定excel所在文件夹和生成word保存的文件夹
from docxtpl import DocxTemplate
import pandas as pd
import os
print('----1、第一次新WORD制作--------')
path=r'C:\Users\jg2yXRZ\OneDrive\桌面\20250214领导的每周安排模板'
print(path)
file_path=path
print(file_path)
os.makedirs(file_path,exist_ok=True)
print('----计算每一行的数据用5天、6天还是7天的表格------')
import xlrd
# 假设 path 是之前已经定义好的文件路径变量的一部分
file_paths = path + r'\02-01 2024学年第二学期校历.xlsx'
workbook = xlrd.open_workbook(file_paths)
sheet = workbook.sheet_by_index(0) # 获取第一张工作表
new=path+r'\00每周安排模板1-20周(有日期)'
os.makedirs(new,exist_ok=True)
# 遍历每一行,从第二行开始(索引为1,因为索引从0开始,但Excel从1开始计数行)
for row_idx in range(1,sheet.nrows): # sheet.nrows 返回工作表中的行数
# 读取当前行的E到K列(列索引从0开始,但Excel列从1开始计数,所以E=4, ..., K=10)
row_data = sheet.row_values(row_idx, start_colx=4, end_colx=11)
# print(row_data)
# 删除 row_data 中的空元素(None 或空字符串)
days = [cell for cell in row_data if cell is not None and cell != '']
# 统计每行非空元素的数量 (天数)
day = len(days)
print(f'第{row_idx}行,本周天数是{day}天')
# 如果是5天就用5天模版,如果是7天,就用7天模版
tpl = DocxTemplate(path+fr'\00 周计划模板 年月日.docx')
WeeklyPlan = pd.read_excel(path+r'\02-01 2024学年第二学期校历.xlsx')
week =WeeklyPlan["week"].str.rstrip()
year1 = WeeklyPlan["year1"].astype(str).str.rstrip()
year2 = WeeklyPlan["year2"].astype(str).str.rstrip()
month1 = WeeklyPlan["month1"].astype(str).str.rstrip()
month2 = WeeklyPlan["month2"].astype(str).str.rstrip()
day11 = WeeklyPlan["day11"].astype(str).str.rstrip()
day22 = WeeklyPlan["day22"].astype(str).str.rstrip()
day1 = WeeklyPlan["day1"].astype(str).str.rstrip()
# print(day1)
day2 = WeeklyPlan["day2"].astype(str).str.rstrip()
day3 = WeeklyPlan["day3"].astype(str).str.rstrip()
day4 = WeeklyPlan["day4"].astype(str).str.rstrip()
day5 = WeeklyPlan["day5"].astype(str).str.rstrip()
day6 = WeeklyPlan["day6"].astype(str).str.rstrip()
day7 = WeeklyPlan["day7"].astype(str).str.rstrip()
x1 = WeeklyPlan["x1"].str.rstrip()
x2 = WeeklyPlan["x2"].str.rstrip()
x3 = WeeklyPlan["x3"].str.rstrip()
x4 = WeeklyPlan["x4"].str.rstrip()
x5 = WeeklyPlan["x5"].str.rstrip()
x6 = WeeklyPlan["x6"].str.rstrip()
x7 = WeeklyPlan["x7"].str.rstrip()
# 遍历excel行,逐个生成
# num = WeeklyPlan.shape[0]
# print(num)
for i in range(row_idx-1,row_idx):
context = {
"week": int(week[i][1:-1]),
# 只要第01周里面的1
"year1": year1[i],
"year2": year2[i],
"month1": month1[i],
"month2": month2[i],
"day11": day11[i],
"day22": day22[i],
"day1": day1[i],
"day2": day2[i],
"day3": day3[i],
"day4": day4[i],
"day5": day5[i],
"day6": day6[i],
"day7": day7[i],
"x1": x1[i],
"x2": x2[i],
"x3": x3[i],
"x4": x4[i],
"x5": x5[i],
"x6": x6[i],
"x7": x7[i],
}
tpl.render(context)
# # 假设 weekshu[i] 是类似于 '4、5' 或 '7' 这样的字符串
# if isinstance(week[i], str) and len(week[i]) >= 3:
# week_part1 = str(week[i]).split('、')[0] # 分割字符串并取第一部分
# week_number1 = int(week_part) # 转换为整数
# week_number2=week_number1+1
# formatted_week_number = '%02d' % week_number1+'_'+'%02d' % week_number2
# tpl.save(file_path+fr"\ 第{str(week[i][1:-1])}周 每周安排.docx")
# .docx")
if (day7[i]) =='':
day1[i]
tpl.save(new + fr"\{str(week[i])} 每周安排 ({month1[i]}.{day11[i]}~).docx")
else:
tpl.save(new + fr"\{str(week[i])} 每周安排 ({month1[i]}.{day11[i]}~{month2[i]}.{day22[i]}).docx")
# else:
# tpl.save(file_path+fr"\{weekshu[i]:02} 第{str(week[i][1:-1])}周 每周安排 ({day1[i]}+'~'+{day7[i]}).docx")
# 把nan(空值)删除
import os
from docx import Document
folder_path = new
# y=['A','nan']
# z=['.','']
# for s in range(len(y)):
for filename in os.listdir(folder_path):
if filename.endswith('.docx'):
file_path = os.path.join(folder_path, filename)
doc = Document(file_path)
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
if cell.text == 'nan':
cell.text = ''
doc.save(file_path)
print(f"Processed {filename}")
第二步就是根据模版,一一对应写入了
直接上代码
'''
把领导的每周安排的模版的日期批量做好(2)——批量生成模版
如果有空格,全部要加一个空格,否则读取出来的年月日是一位小数浮点数
星火讯飞,阿夏
2025年2月14日
'''
import pandas as pd
import openpyxl
from openpyxl import load_workbook
import copy
print('------------1、读取表格里整理好的周日、日期,列表形式')
# 一、导入相关模块,设定excel所在文件夹和生成word保存的文件夹
from docxtpl import DocxTemplate
import pandas as pd
import os
print('----1、第一次新WORD制作--------')
path=r'C:\Users\jg2yXRZ\OneDrive\桌面\20250214领导的每周安排模板'
print(path)
file_path=path
print(file_path)
os.makedirs(file_path,exist_ok=True)
print('----计算每一行的数据用5天、6天还是7天的表格------')
import xlrd
# 假设 path 是之前已经定义好的文件路径变量的一部分
file_paths = path + r'\02-01 2024学年第二学期校历.xlsx'
workbook = xlrd.open_workbook(file_paths)
sheet = workbook.sheet_by_index(0) # 获取第一张工作表
new=path+r'\00每周安排模板1-20周(有日期)'
os.makedirs(new,exist_ok=True)
# 遍历每一行,从第二行开始(索引为1,因为索引从0开始,但Excel从1开始计数行)
for row_idx in range(1,sheet.nrows): # sheet.nrows 返回工作表中的行数
# 读取当前行的E到K列(列索引从0开始,但Excel列从1开始计数,所以E=4, ..., K=10)
row_data = sheet.row_values(row_idx, start_colx=4, end_colx=11)
# print(row_data)
# 删除 row_data 中的空元素(None 或空字符串)
days = [cell for cell in row_data if cell is not None and cell != '']
# 统计每行非空元素的数量 (天数)
day = len(days)
print(f'第{row_idx}行,本周天数是{day}天')
# 如果是5天就用5天模版,如果是7天,就用7天模版
tpl = DocxTemplate(path+fr'\00 周计划模板 年月日.docx')
WeeklyPlan = pd.read_excel(path+r'\02-01 2024学年第二学期校历.xlsx')
week =WeeklyPlan["week"].str.rstrip()
year1 = WeeklyPlan["year1"].astype(str).str.rstrip()
year2 = WeeklyPlan["year2"].astype(str).str.rstrip()
month1 = WeeklyPlan["month1"].astype(str).str.rstrip()
month2 = WeeklyPlan["month2"].astype(str).str.rstrip()
day11 = WeeklyPlan["day11"].astype(str).str.rstrip()
day22 = WeeklyPlan["day22"].astype(str).str.rstrip()
day1 = WeeklyPlan["day1"].astype(str).str.rstrip()
# print(day1)
day2 = WeeklyPlan["day2"].astype(str).str.rstrip()
day3 = WeeklyPlan["day3"].astype(str).str.rstrip()
day4 = WeeklyPlan["day4"].astype(str).str.rstrip()
day5 = WeeklyPlan["day5"].astype(str).str.rstrip()
day6 = WeeklyPlan["day6"].astype(str).str.rstrip()
day7 = WeeklyPlan["day7"].astype(str).str.rstrip()
x1 = WeeklyPlan["x1"].str.rstrip()
x2 = WeeklyPlan["x2"].str.rstrip()
x3 = WeeklyPlan["x3"].str.rstrip()
x4 = WeeklyPlan["x4"].str.rstrip()
x5 = WeeklyPlan["x5"].str.rstrip()
x6 = WeeklyPlan["x6"].str.rstrip()
x7 = WeeklyPlan["x7"].str.rstrip()
# 遍历excel行,逐个生成
# num = WeeklyPlan.shape[0]
# print(num)
for i in range(row_idx-1,row_idx):
context = {
"week": int(week[i][1:-1]),
# 只要第01周里面的1
"year1": year1[i],
"year2": year2[i],
"month1": month1[i],
"month2": month2[i],
"day11": day11[i],
"day22": day22[i],
"day1": day1[i],
"day2": day2[i],
"day3": day3[i],
"day4": day4[i],
"day5": day5[i],
"day6": day6[i],
"day7": day7[i],
"x1": x1[i],
"x2": x2[i],
"x3": x3[i],
"x4": x4[i],
"x5": x5[i],
"x6": x6[i],
"x7": x7[i],
}
tpl.render(context)
# # 假设 weekshu[i] 是类似于 '4、5' 或 '7' 这样的字符串
# if isinstance(week[i], str) and len(week[i]) >= 3:
# week_part1 = str(week[i]).split('、')[0] # 分割字符串并取第一部分
# week_number1 = int(week_part) # 转换为整数
# week_number2=week_number1+1
# formatted_week_number = '%02d' % week_number1+'_'+'%02d' % week_number2
# tpl.save(file_path+fr"\ 第{str(week[i][1:-1])}周 每周安排.docx")
# .docx")
if (day7[i]) =='':
day1[i]
tpl.save(new + fr"\{str(week[i])} 每周安排 ({month1[i]}.{day11[i]}~).docx")
else:
tpl.save(new + fr"\{str(week[i])} 每周安排 ({month1[i]}.{day11[i]}~{month2[i]}.{day22[i]}).docx")
# else:
# tpl.save(file_path+fr"\{weekshu[i]:02} 第{str(week[i][1:-1])}周 每周安排 ({day1[i]}+'~'+{day7[i]}).docx")
# 把nan(空值)删除
import os
from docx import Document
folder_path = new
# y=['A','nan']
# z=['.','']
# for s in range(len(y)):
for filename in os.listdir(folder_path):
if filename.endswith('.docx'):
file_path = os.path.join(folder_path, filename)
doc = Document(file_path)
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
if cell.text == 'nan':
cell.text = ''
doc.save(file_path)
print(f"Processed {filename}")
结果展示


内部标题的第二个日期也正常了,说明不能有“空单元格”


发给领导们用于制作每周安排。
与领导1的沟通 记录,调整样式,添加统一的文字模版




与领导2的沟通记录
此处发现第二个日期的问题,(3.10、6.30的日期会自动变成3.1、6.3)


当时我发现6.10(6月30人)读出来总是6.1(把它当做浮点,而不是日期)所以我用了.2f,结果6.7(6月7日)也变成6.70。

放弃用两位数。最终通过相对复杂的方式让10日、20日、30日这种,容易被认为是浮点数而舍弃0的月日格式,能够保留2个数字。

这是最终的版本了。
第1代码
'''
把领导的每周安排的模版的日期批量做好(1)——制作日期数字
如果有空格,全部要加一个空格,否则读取出来的年月日是一位小数浮点数
星火讯飞,阿夏
2025年2月14日
'''
# -*- coding: utf-8 -*-
import datetime
import openpyxl
from openpyxl.styles import Alignment, PatternFill
import time
import pandas as pd
import re
from openpyxl import load_workbook
# for
path=r'C:\Users\jg2yXRZ\OneDrive\桌面\20250214领导的每周安排模板'
# 1、制作基础日期表
title='2024学年第二学期校历'
tt=path+fr"\02-01 {title}.xlsx"
# 创建一个新的Excel工作簿
workbook = openpyxl.Workbook()
sheet = workbook.active
# 设置标题行
title_row = ["week", "D1", "D2", "D3", "D4", "D5", "D6", "D7"]
sheet.append(title_row)
# 设置日期范围
start_date = datetime.date(2025, 2, 17)
end_date = datetime.date(2025, 6, 30)
# 计算周数和日期
current_week = 1
current_day = start_date
while current_day <= end_date:
# 获取当前周的第一天(星期一)
week_start = current_day - datetime.timedelta(days=current_day.weekday())
# 如果当前日期是新的一周,添加新行并更新周数
if current_day == week_start:
sheet.append([f"第{current_week:02d}周"])
current_week += 1
# 在正确的单元格中添加日期
column_index = current_day.weekday() + 2 # 从B列开始,所以加2year
cell = sheet.cell(row=current_week, column=column_index)
# 不同的表示方法
# cell.value = current_day.strftime("%Y-%m-%d") # 2024-09-01
# cell.value = current_day.strftime("%Y-%#m-%#d") # 2024-9-1
# cell.value = current_day.strftime("%m/%d") # 09-01
# cell.value = current_day.strftime("%#m/%#d") # 9-1
# cell.value = current_day.strftime('%Y{y}%m{m}%d{d}').format(y='年', m='月', d='日') # 2024年09月01日
cell.value = current_day.strftime('%Y{y}%#m{m}%#d{d}').format(y='年', m='月', d='日') # 2024年9月1日
cell.alignment = Alignment(horizontal='center', vertical='center')
# 如果日期不等于周六和周日,就把这个单元格填充为浅黄色
if current_day.weekday() not in (5, 6):
light_yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
cell.fill = light_yellow_fill
# 如果日期等于2024-09-14、2024-10-12、9月16日、9月17日、10月1日到10月8日、2025年1月1日,单元格填充为白色
special_dates = [datetime.date(2025, 4, 4), datetime.date(2025, 5, 1), datetime.date(2025, 5, 2), datetime.date(2025, 5, 5),datetime.date(2025, 6, 2)]
# for i in range(1, 8):
# special_dates.append(datetime.date(2024, 10, i))
# special_dates.append(datetime.date(2025, 1, 1))
if current_day in special_dates:
white_fill = PatternFill(start_color="FFFFFF", end_color="FFFFFF", fill_type="solid")
cell.fill = white_fill
# # 如果日期等于2024-09-14或2024-10-12,单元格填充为黄色
# if current_day == datetime.date(2025, 4, 27) or current_day == datetime.date(2024, 9, 29) or current_day == datetime.date(2024, 10, 12):
if current_day == datetime.date(2025, 4, 27):
yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
cell.fill = yellow_fill
# 移动到下一天
current_day += datetime.timedelta(days=1)
# 在年月日起止和4.30样式的7天里,如果遇到什么都没有填写的空单元格,就写入一个空格
# 读取最大行数(不要第一行)
max_row = sheet.max_row
# 设置列宽
for col in range(1, 30):
sheet.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 15
# for col in range(9, 12):
# sheet.column_dimensions[openpyxl.utils.get_column_letter(col)].width = 35
# 设置单元格文字居中
for row in sheet.iter_rows():
for cell in row:
cell.alignment = openpyxl.styles.Alignment(horizontal='center', vertical='center')
# 打印所有黄色底纹填充格子的坐标
yellow_coordinates = []
for row in sheet.iter_rows():
for cell in row:
if cell.fill and cell.fill.start_color.rgb == 'FFFF00':
yellow_coordinates.append((cell.row, cell.column))
print("Yellow filled cells coordinates:", yellow_coordinates)
n=1
# 读取标题中的信息
# 读取B列:
for i in range(2, sheet.max_row + 1):
cell_value = sheet.cell(row=i, column=2).value
# for x in range(9,12):
if cell_value:
match = re.search(r'(\d+)年', cell_value)
year_part = match.group(1)
sheet.cell(row=i, column=9).value = year_part
if cell_value:
match = re.search(r'年(\d+)月', cell_value)
month_part = match.group(1)
sheet.cell(row=i, column=10).value = month_part
if cell_value:
match = re.search(r'月(\d+)日', cell_value)
day_part = match.group(1)
sheet.cell(row=i, column=11).value = day_part
# 在第12列的第1行写入“year”
sheet.cell(row=1, column=9).value = f"year1"
sheet.cell(row=1, column=10).value = f"month1"
sheet.cell(row=1, column=11).value = f"day11"
# 读取H列:
for i in range(2, sheet.max_row + 1):
cell_value = sheet.cell(row=i, column=8).value
# for x in range(9,12):
if cell_value:
match = re.search(r'(\d+)年', cell_value)
year_part = match.group(1)
sheet.cell(row=i, column=12).value = year_part
if cell_value:
match = re.search(r'年(\d+)月', cell_value)
month_part = match.group(1)
sheet.cell(row=i, column=13).value = month_part
if cell_value:
match = re.search(r'月(\d+)日', cell_value)
day_part = match.group(1)
sheet.cell(row=i, column=14).value =f'{day_part}'
# 在第12列的第1行写入“year”
sheet.cell(row=1, column=12).value = f"year2"
sheet.cell(row=1, column=13).value = f"month2"
sheet.cell(row=1, column=14).value = f"day22"
# 读取玥日
# 读取各列中的日期,提取月和日,写入相应列
columns_to_process = [2, 3, 4, 5, 6,7,8] # B列到F列
output_columns = [15, 16, 17, 18, 19,20,21] # 对应输出的列(H列到L列)
for col_idx, col in enumerate(columns_to_process):
for i in range(2, sheet.max_row + 1):
cell_value = sheet.cell(row=i, column=col).value
if cell_value:
match = re.search(r'(\d+)年(\d+)月(\d+)日', cell_value)
if match:
month_part = match.group(2)
day_part = match.group(3)
sheet.cell(row=i, column=output_columns[col_idx]).value = f"{month_part}.{day_part}"
# 在第12列的第1行写入“year”
sheet.cell(row=1, column=output_columns[col_idx]).value = f"day{col_idx+1}"
# 检查第9到21列的范围内单元格,如果内容是空的,就在这个单元格里写入一个“ ”
columns_to_check = [9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21]
for i in range(2, max_row + 1):
for col in columns_to_check:
cell_value = sheet.cell(row=i, column=col).value
if cell_value is None or cell_value == '':
sheet.cell(row=i, column=col).value = ' '
# # 读取各列中的日期,提取月和日,写入相应列
# 设置黄色填充样式
yellow_fill = PatternFill(start_color="FFFF00", end_color="FFFF00", fill_type="solid")
# 要处理的列和对应的输出列
columns_to_process = [2, 3, 4, 5, 6, 7,8] # B列到G列
output_columns = [22, 23, 24, 25, 26, 27,28] # 对应输出的列(Y列到D列)
for col_idx, col in enumerate(columns_to_process):
for i in range(2, sheet.max_row + 1):
cell = sheet.cell(row=i, column=col)
cell_value = cell.value
# 如果单元格有黄色填充,则复制填充样式到输出列
if cell.fill == yellow_fill:
output_cell = sheet.cell(row=i, column=output_columns[col_idx])
output_cell.fill = yellow_fill
else:
# 如果单元格没有黄色填充(白色),就在里面写入“双休日休息”
sheet.cell(row=i, column=output_columns[col_idx]).value = "休息"
# else:
# 只对真正放假的那一天进行备注 清明1天,劳动1天
dayss=['2025年4月4日','2025年4月27日','2025年5月1日','2025年5月31日',]
jr=['清明节放假','劳动节调班,今天要上班的!','劳动节放假','端午节放假']
for ddd in range(len(dayss)):
# 检查日期是否为2025年4月4日
if cell_value ==dayss[ddd]:
sheet.cell(row=i, column=output_columns[col_idx]).value = jr[ddd]
# 在第12列的第1行写入“year”,复制的时候不要复制文字
sheet.cell(row=1, column=output_columns[col_idx]).value = f"x{col_idx+1}"
# 保存工作簿
workbook.save(tt)
第2代码-批量DOCX
'''
把领导的每周安排的模版的日期批量做好(2)——批量生成模版
如果有空格,全部要加一个空格,否则读取出来的年月日是一位小数浮点数
星火讯飞,阿夏
2025年2月14日
'''
import pandas as pd
import openpyxl
from openpyxl import load_workbook
import copy
print('------------1、读取表格里整理好的周日、日期,列表形式')
# 一、导入相关模块,设定excel所在文件夹和生成word保存的文件夹
from docxtpl import DocxTemplate
import pandas as pd
import os
print('----1、第一次新WORD制作--------')
path=r'C:\Users\jg2yXRZ\OneDrive\桌面\20250214领导的每周安排模板'
print(path)
file_path=path
print(file_path)
os.makedirs(file_path,exist_ok=True)
print('----计算每一行的数据用5天、6天还是7天的表格------')
import xlrd
# 假设 path 是之前已经定义好的文件路径变量的一部分
file_paths = path + r'\02-01 2024学年第二学期校历.xlsx'
workbook = xlrd.open_workbook(file_paths)
sheet = workbook.sheet_by_index(0) # 获取第一张工作表
new=path+r'\00每周安排模板1-20周(有日期)'
os.makedirs(new,exist_ok=True)
# 遍历每一行,从第二行开始(索引为1,因为索引从0开始,但Excel从1开始计数行)
for row_idx in range(1,sheet.nrows): # sheet.nrows 返回工作表中的行数
# 读取当前行的E到K列(列索引从0开始,但Excel列从1开始计数,所以E=4, ..., K=10)
row_data = sheet.row_values(row_idx, start_colx=4, end_colx=11)
# print(row_data)
# 删除 row_data 中的空元素(None 或空字符串)
days = [cell for cell in row_data if cell is not None and cell != '']
# 统计每行非空元素的数量 (天数)
day = len(days)
print(f'第{row_idx}行,本周天数是{day}天')
# 如果是5天就用5天模版,如果是7天,就用7天模版
tpl = DocxTemplate(path+fr'\00 周计划模板 年月日.docx')
WeeklyPlan = pd.read_excel(path+r'\02-01 2024学年第二学期校历.xlsx')
week =WeeklyPlan["week"].str.rstrip()
year1 = WeeklyPlan["year1"].astype(str).str.rstrip()
year2 = WeeklyPlan["year2"].astype(str).str.rstrip()
month1 = WeeklyPlan["month1"].astype(str).str.rstrip()
month2 = WeeklyPlan["month2"].astype(str).str.rstrip()
day11 = WeeklyPlan["day11"].astype(str).str.rstrip()
day22 = WeeklyPlan["day22"].astype(str).str.rstrip()
day1 = WeeklyPlan["day1"].astype(str).str.rstrip()
# print(day1)
day2 = WeeklyPlan["day2"].astype(str).str.rstrip()
day3 = WeeklyPlan["day3"].astype(str).str.rstrip()
day4 = WeeklyPlan["day4"].astype(str).str.rstrip()
day5 = WeeklyPlan["day5"].astype(str).str.rstrip()
day6 = WeeklyPlan["day6"].astype(str).str.rstrip()
day7 = WeeklyPlan["day7"].astype(str).str.rstrip()
x1 = WeeklyPlan["x1"].str.rstrip()
x2 = WeeklyPlan["x2"].str.rstrip()
x3 = WeeklyPlan["x3"].str.rstrip()
x4 = WeeklyPlan["x4"].str.rstrip()
x5 = WeeklyPlan["x5"].str.rstrip()
x6 = WeeklyPlan["x6"].str.rstrip()
x7 = WeeklyPlan["x7"].str.rstrip()
# 如果数字是0结尾的就改成2位浮点,也就是保留0
def format_number(num):
# 检查数字是否是整数或以0结尾的小数
if isinstance(num, int) or (isinstance(num, float) and num.is_integer()):
return str(int(num))
elif isinstance(num, str):
try:
num = float(num)
if num.is_integer():
return str(int(num))
else:
return f"{num:.2f}"
except ValueError:
return num # 如果无法转换为浮点数,则返回原始字符串
else:
return f"{num:.2f}"
# 遍历excel行,逐个生成
for i in range(row_idx-1, row_idx):
context = {
"week": int(week[i][1:-1]),
"year1": year1[i],
"year2": year2[i],
"month1": month1[i],
"month2": month2[i],
"day11": day11[i],
"day22": day22[i],
"day1": format_number(day1[i]),
"day2": format_number(day2[i]),
"day3": format_number(day3[i]),
"day4": format_number(day4[i]),
"day5": format_number(day5[i]),
"day6": format_number(day6[i]),
"day7": format_number(day7[i]),
"x1": format_number(x1[i]),
"x2": format_number(x2[i]),
"x3": format_number(x3[i]),
"x4": format_number(x4[i]),
"x5": format_number(x5[i]),
"x6": format_number(x6[i]),
"x7": format_number(x7[i]),
}
tpl.render(context)
# # 假设 weekshu[i] 是类似于 '4、5' 或 '7' 这样的字符串
# if isinstance(week[i], str) and len(week[i]) >= 3:
# week_part1 = str(week[i]).split('、')[0] # 分割字符串并取第一部分
# week_number1 = int(week_part) # 转换为整数
# week_number2=week_number1+1
# formatted_week_number = '%02d' % week_number1+'_'+'%02d' % week_number2
# tpl.save(file_path+fr"\ 第{str(week[i][1:-1])}周 每周安排.docx")
# .docx")
if (day7[i]) =='':
day1[i]
tpl.save(new + fr"\{str(week[i])} 每周安排 ({month1[i]}.{day11[i]}~).docx")
else:
tpl.save(new + fr"\{str(week[i])} 每周安排 ({month1[i]}.{day11[i]}~{month2[i]}.{day22[i]}).docx")
# else:
# tpl.save(file_path+fr"\{weekshu[i]:02} 第{str(week[i][1:-1])}周 每周安排 ({day1[i]}+'~'+{day7[i]}).docx")
# 把nan(空值)删除
import os
from docx import Document
folder_path = new
# y=['A','nan']
# z=['.','']
# for s in range(len(y)):
for filename in os.listdir(folder_path):
if filename.endswith('.docx'):
file_path = os.path.join(folder_path, filename)
doc = Document(file_path)
for table in doc.tables:
for row in table.rows:
for cell in row.cells:
if cell.text == 'nan':
cell.text = ''
doc.save(file_path)
print(f"Processed {filename}")
起止日期正确——3.30、6.30表述正确



本学期第20周只有一天,应该与19周合并,但这样我又要做一个8天的WORD模版了

最后还是在19周基础上,手动做了19.20周的模版




打包发送
