【办公类-120-01】20260812闵行区幼儿园概况表的数据统计(户籍、五类性质、优抚子女)

背景需求

20260812人事干部问我如何获取全园幼儿"户籍""积分性质""优抚子女"的信息。

我看了一下,两个问题:

1、园园通还有6位幼儿没有导入,信息不全

2、园园通(小班)的孩子的户籍信息不一定正确(为了去掉标红,户籍所在市、户籍所在区都是默认选第一个,是不正确的,后续要修改)

3、园园通里面没有"五类居住证"的信息说明------必须班主任向家长收集。

解决方案

所以我说"做接龙表单"班主任复制模版,修改班级名称,黏贴班级幼儿姓名。

人事干部说:那这个任务由你负责

OK,没问题

一、制作接龙表单(接龙管家)

1、制作一个"收集表单"的模版

其实只有三个问题

如果选"外省",才会出现五类选择

选择优抚子女

表单设计非常简单

二、发布总群

1、人事干部发送了通知

马上又一位老师来问:她在旅游无法手动查询幼儿户籍信息

2、把统计的接龙管家分享

3.个别老师年龄大,不会操作,我找到他们班的班级信息表,把文件复制一个"托3班"

4、我自己班级的表单发布

发布到本班班级群

4、表单下载

13.42-14.49, 1小时后,第一份表单收集整齐发给我了

表单里面标题:署名、班级、户籍所在地(本市本区、本市外区、外省等)、非户籍幼儿五类选择、是否军人、武警、消防子女(优抚对象)

小班25人满额,表单正确

家长手填的班级果然不是统一样式,

为了后面"分班""分园区",必须把班级名称修改统一。

下次考虑做"年级""班级"的单选按钮

我又把中2班(我自己班)的表单下载(还没有收齐),准备先做Python程序,做多份表单合并。

因为刚升班,所以家长有的填写小2班,有的填写中2班

这个问题还是很严重的,家长和老师对于升班后的年级还是容易遗忘的。

所以还是要手动检查修改

三、测试班级合并

python 复制代码
'''
把19个班级的接龙管家的EXCEL表格合并在一起
豆包 阿夏
20260812
'''


import os
from openpyxl import load_workbook, Workbook

# 配置路径
path=r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
folder_path = path +r"\01 20260812班级统计EXCEL"  # 要读取的文件夹名
output_file = path+r"\20260812全部班级合并.xlsx"  # 输出文件名

# 创建新的汇总工作簿
wb_total = Workbook()
ws_total = wb_total.active
ws_total.title = "合并数据"

# 标记是否已经写入表头
header_written = False

# 遍历123文件夹下所有文件
for filename in os.listdir(folder_path):
    # 只处理xlsx后缀
    if filename.lower().endswith(".xlsx"):
        file_full_path = os.path.join(folder_path, filename)
        print(f"正在处理:{filename}")

        # 打开单个Excel文件
        wb = load_workbook(file_full_path)
        ws = wb.active

        # 循环读取每一行
        for row in ws.iter_rows(values_only=True):
            if not header_written:
                # 写入表头
                ws_total.append(row)
                header_written = True
            else:
                # 跳过其他文件的表头(第一行)
                if row == tuple(ws[1]):
                    continue
                ws_total.append(row)

# 保存最终合并文件
wb_total.save(output_file)
print(f"合并完成,文件已生成:{output_file}")

存在问题:后面的表格也有第一行标题(不需要)

python 复制代码
'''
把19个班级的接龙管家的EXCEL表格合并在一起
豆包 阿夏
20260812
'''

import os
from openpyxl import load_workbook, Workbook

# ========== 自定义路径配置 ==========
path = r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
folder_path = path + r"\01 20260812班级统计EXCEL"
output_file = path + r"\20260812全部班级合并.xlsx"
# ====================================

# 创建新的汇总Excel
total_wb = Workbook()
total_ws = total_wb.active
total_ws.title = "合并汇总"

# 筛选文件夹内所有xlsx文件
excel_files = []
for file_name in os.listdir(folder_path):
    if file_name.lower().endswith(".xlsx"):
        full_file_path = os.path.join(folder_path, file_name)
        excel_files.append(full_file_path)

if len(excel_files) == 0:
    print("文件夹内未找到任何.xlsx格式Excel文件")
else:
    # 遍历每一个Excel
    for index, file in enumerate(excel_files):
        print(f"正在处理文件:{os.path.basename(file)}")
        # data_only=True 读取单元格最终显示数值,不保留公式
        wb = load_workbook(file, data_only=True)
        ws = wb.active

        if index == 0:
            # 第一个文件:完整写入,保留表头第一行
            for row_data in ws.iter_rows(values_only=True):
                total_ws.append(row_data)
        else:
            # 后续所有文件:从第2行开始读取,自动跳过表头
            for row_data in ws.iter_rows(min_row=2, values_only=True):
                total_ws.append(row_data)

# 保存合并后的文件
total_wb.save(output_file)
print(f"\n✅ 合并完成!\n文件保存路径:{output_file}")

这次只有第一行是标题行,下面就没有标题了,

四、测试如何提取户籍地人数、五类证件人数、没有人数的填0

思考如何统计

1、把户籍七类,分别统计出来------本市本区10人,本市外区5人,外省20人"(已经显示出来的文字)+港澳台都默认写0(不存在的区域,默认写0)

2、把居住证五类,分别统计出来------项目A10人,项目B5人,项目C20人"(已经显示出来的文字,名称太长了)+(没有提到的项目,默认写0人)

3.把优抚对象两类,都是选否,默认0,如果"有",再继续分类

把表格里的名字和家长微信号都删除,附件上传豆包

如果都提取出来,太长了,有500多条,太慢了

看起来不方便,还是做成EXCEL

显示列太多了,我只要 几列

现在统计出来数量了。但是需要区分"园区"。

如何把统计出来的数据加入"提交EXCEL"内

把"提交EXCEL"的空表作为附件上传

目前是1个小班(一分园),1个中班(总园)

位置不对,再测试一次

填写位置还是很乱

太好了,大班没有,就默认0。

还有托班

现在两个班级分别在两个园区,不知道同一个园区的两个小班人数是否可以累加。

我复制小2班,变成小3班(假表),是否可以累加。

把三个程序运行一次

最后,25人变成50人,本区11变成22人,成功

再测试一个 中2班表格复制改成大4班

中2班改成大4班

四个班级表,三个代码跑一次

也成功了。我修改大4班的几个孩子的户籍为港澳台外籍其他

三个代码运行后,顺利识别了"五类特殊户籍"

很好,现在继续做代码,补全班级数

班级数量是正确的,但是还有混龄班和特教班,需要补0(这两个班级通常没有,如果有的话,需要在代码标注,小X班是混龄班、中X班是特教班,才能识别出来)

不错GH 列都写了0,但是最右侧没有写

这是第一张表。每个格子都写了数字。

第二张表

没用,还是0

换Deepseek

反复测试无数次,终于正确获取

三、做混龄班

它提示没有可以不写,我就暂时不写0了

四、统计优抚对象

还不容易有一位孩子是优抚对象,否则我都不知道应该怎么做提取

另外我也修改假名单,做点假数据,便于提取

都是大班的,没有托小中的数据。

还是这个样子,

我仔细看了一下,把数字右移动3列,就正确了

气死了,还是改不出来

终于正确了

把已经收齐的内容,做一遍

第一步:把收集的表单合并成一个工作表(必须每个文件打开,班级名称统一为大1班这样,不要出现大一班,大(1)班这种)

python 复制代码
'''
第1步
把19个班级的接龙管家的EXCEL表格合并在一起
豆包 阿夏
20260812
'''

import os
from openpyxl import load_workbook, Workbook

# ========== 自定义路径配置 ==========
path = r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
folder_path = path + r"\01 20260812班级统计EXCEL"
output_file = path + r"\20260812全部班级合并.xlsx"
# ====================================

# 创建新的汇总Excel
total_wb = Workbook()
total_ws = total_wb.active
total_ws.title = "合并汇总"

# 筛选文件夹内所有xlsx文件
excel_files = []
for file_name in os.listdir(folder_path):
    if file_name.lower().endswith(".xlsx"):
        full_file_path = os.path.join(folder_path, file_name)
        excel_files.append(full_file_path)

if len(excel_files) == 0:
    print("文件夹内未找到任何.xlsx格式Excel文件")
else:
    # 遍历每一个Excel
    for index, file in enumerate(excel_files):
        print(f"正在处理文件:{os.path.basename(file)}")
        # data_only=True 读取单元格最终显示数值,不保留公式
        wb = load_workbook(file, data_only=True)
        ws = wb.active

        if index == 0:
            # 第一个文件:完整写入,保留表头第一行
            for row_data in ws.iter_rows(values_only=True):
                total_ws.append(row_data)
        else:
            # 后续所有文件:从第2行开始读取,自动跳过表头
            for row_data in ws.iter_rows(min_row=2, values_only=True):
                total_ws.append(row_data)

# 保存合并后的文件
total_wb.save(output_file)
print(f"\n✅ 合并完成!\n文件保存路径:{output_file}")

第二步:

python 复制代码
'''
第2步
从合并表里提取每个班级的相同列的内容和数量
豆包 阿夏
20260812
'''

import pandas as pd

# ===================== 路径配置 =====================
folder_path = r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
source_file = f"{folder_path}\\20260812全部班级合并.xlsx"
output_file = f"{folder_path}\\分析.xlsx"

# 需要统计的指定列
stat_cols = [
    "班级",
    "户籍所在地",
    "非户籍幼儿五类明细选择",
    "是否属于军人子女",
    "军人子女类型",
    "是否属于武警消防子女",
    "武警消防子女类型"
]

# 园区班级映射规则
park_map = {
    "总园": ["中1","中2","中3","中4","中5","中6","大1","大2","大3","大4","大5"],
    "一分园": ["托1","托2","小4","小5"],
    "二分园": ["托3","小1","小2","小3"]
}

# 构建班级→园区字典
class_to_park = {}
for park, class_list in park_map.items():
    for c in class_list:
        class_to_park[c] = park

# ===================== 读取数据 =====================
df = pd.read_excel(source_file)
df_stat = df[stat_cols].copy()
# 提取班级前缀匹配园区(如"中2班"截取"中2")
def get_park(class_name):
    if pd.isna(class_name):
        return "未知园区"
    c_short = str(class_name).replace("班","")
    return class_to_park.get(c_short, "未知园区")
df_stat["园区"] = df_stat["班级"].apply(get_park)

total_rows = len(df_stat)
print(f"全部数据总行数:{total_rows}")

# ===================== 1. 全局总统计 =====================
global_data = []
for col in stat_cols:
    count_series = df_stat[col].value_counts(dropna=False)
    ratio_series = df_stat[col].value_counts(normalize=True, dropna=False)
    for text_val, count in count_series.items():
        global_data.append({
            "统计范围": "全局全部",
            "列名称": col,
            "内容文本": text_val,
            "出现次数": count,
            "整体占比": f"{ratio_series[text_val]:.2%}"
        })
df_global = pd.DataFrame(global_data)

# ===================== 2. 按园区+班级分层统计 =====================
park_class_data = []
# 先按园区分组,园区内再按班级分组
group_obj = df_stat.groupby(["园区", "班级"])
for (park_name, class_name), group_df in group_obj:
    class_total = len(group_df)
    print(f"【{park_name}-{class_name}】本班总人数:{class_total}")
    for col in stat_cols:
        count_series = group_df[col].value_counts(dropna=False)
        ratio_series = group_df[col].value_counts(normalize=True, dropna=False)
        for text_val, count in count_series.items():
            park_class_data.append({
                "园区": park_name,
                "班级": class_name,
                "列名称": col,
                "内容文本": text_val,
                "本班出现次数": count,
                "本班内占比": f"{ratio_series[text_val]:.2%}"
            })
df_park_class = pd.DataFrame(park_class_data)

# ===================== 写入分析.xlsx =====================
with pd.ExcelWriter(output_file, engine="openpyxl") as writer:
    df_global.to_excel(writer, sheet_name="全局汇总统计", index=False)
    df_park_class.to_excel(writer, sheet_name="园区班级分层统计", index=False)

print(f"\n统计完成!结果已保存至:{output_file}")
print("仅统计指定7列,并按【总园/一分园/二分园】+班级双层分类汇总")

各班的户籍种类不同、五大明细的种类也不同

右侧有出现频率(合并数据)

第3步:统计到工作表内

python 复制代码
'''
第3步
把分析出来的数量写入指定的模版里
豆包 阿夏
20260812
'''

from openpyxl import load_workbook
from openpyxl.styles import Alignment

# ===================== 路径配置 =====================
folder = r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
data_excel = f"{folder}\\分析.xlsx"
template_excel = f"{folder}\\1 2026学年闵行区幼儿园概况表(总分园填在一张表上)(1).xlsx"
out_excel = f"{folder}\\最终版_户籍统计表_无合并报错.xlsx"

# ===================== 园区班级映射规则 =====================
park_class_rule = {
    "总园": ["中1", "中2", "中3", "中4", "中5", "中6", "大1", "大2", "大3", "大4", "大5"],
    "一分园": ["托1", "托2", "小4", "小5"],
    "二分园": ["托3", "小1", "小2", "小3"]
}
class_to_park = {}
for park, cls_list in park_class_rule.items():
    for cls in cls_list:
        class_to_park[cls] = park

# 班级转年级工具函数
def class_to_grade(class_name: str) -> str:
    c = class_name.strip()
    if "托" in c:
        return "托班"
    elif "小" in c:
        return "小班"
    elif "中" in c:
        return "中班"
    elif "大" in c:
        return "大班"
    return None

# ===================== 优抚表配置(修改:固定写入40/41/42行) =====================
park_write_row = {
    "总园": 40,
    "一分园": 41,
    "二分园": 42
}
# 列组规则:(小计列, 托班列, 小班列, 中班列, 大班列)
col_rule = {
    "军人现役_符合": (3, 4, 5, 6, 7),      # C小计 D托 E小 F中 G大
    "军人退役_符合": (13, 14, 15, 16, 17), # M小计 N托 O小 P中 Q大
    "武警现役_符合": (24, 25, 26, 27, 28), # X小计 Y托 Z小 AA中 AB大
    "武警退役_符合": (34, 35, 36, 37, 38)  # AH小计 AI托 AJ小 AK中 AL大
}

# 优抚数据存储容器
army_warrior_total = {
    "总园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "一分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "二分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    }
}

# ===================== 读取数据源【分析.xlsx】提取优抚数据 =====================
wb_data = load_workbook(data_excel)
ws_data = wb_data["园区班级分层统计"]
rows_data = list(ws_data.iter_rows(values_only=True))
header = rows_data[0]
data_list = rows_data[1:]

print("===== 所有列名 =====")
for i, h in enumerate(header):
    print(f"列{i}: {h}")

# 拆分三类数据
df_hukou = []
df_nonlocal = []
df_army_warrior = []
for row in data_list:
    row_dict = dict(zip(header, row))
    col_name = row_dict.get("列名称")
    if col_name == "户籍所在地":
        df_hukou.append(row_dict)
    elif col_name == "非户籍幼儿五类明细选择":
        df_nonlocal.append(row_dict)
    elif col_name in ("军人子女类型", "武警消防子女类型"):
        df_army_warrior.append(row_dict)

print(f"\n读取户籍记录总数:{len(df_hukou)}")
print(f"读取非户籍五类记录总数:{len(df_nonlocal)}")
print(f"读取军人/武警优抚记录总数:{len(df_army_warrior)}")

# ===================== 统计优抚子女数据(从分析表汇总) =====================
print("\n===== 统计军人武警优抚子女数据 =====")
for row_dict in df_army_warrior:
    park = str(row_dict["园区"]).strip()
    cls_name = str(row_dict["班级"]).strip()
    col_type = row_dict["列名称"]
    content = str(row_dict["内容文本"]).strip()
    cnt = int(row_dict["本班出现次数"])
    grade = class_to_grade(cls_name)

    if park not in army_warrior_total or grade is None or cnt <= 0:
        continue
    target_key = None
    if col_type == "军人子女类型":
        if "现役" in content:
            target_key = "军人现役"
        elif "退役" in content:
            target_key = "军人退役"
    elif col_type == "武警消防子女类型":
        if "现役" in content:
            target_key = "武警现役"
        elif "退役" in content:
            target_key = "武警退役"
    if target_key:
        army_warrior_total[park][target_key][grade] += cnt

# 控制台打印核对数据
for park in ["总园", "一分园", "二分园"]:
    print(f"\n【{park}】优抚汇总:")
    for k, v in army_warrior_total[park].items():
        total = sum(v.values())
        print(f"  {k} 合计{total} → 托{v['托班']} 小{v['小班']} 中{v['中班']} 大{v['大班']}")

# ===================== 1、主表托小中大户籍容器 =====================
parks = ["总园", "一分园", "二分园"]
park_student_data = {
    "总园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "一分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "二分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    }
}

# ===================== 2、开班数量统计 =====================
all_class_raw = set()
for r in data_list:
    cls = dict(zip(header, r)).get("班级")
    if cls:
        all_class_raw.add(str(cls))
short_class_set = set()
for c in all_class_raw:
    short_c = str(c).replace("班", "").strip()
    short_class_set.add(short_c)

class_count = {
    "总园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0, "合计": 0},
    "一分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0, "合计": 0},
    "二分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0, "合计": 0}
}
for sc in short_class_set:
    if sc not in class_to_park:
        continue
    p = class_to_park[sc]
    if "托" in sc:
        class_count[p]["托班"] += 1
    elif "小" in sc:
        class_count[p]["小班"] += 1
    elif "中" in sc:
        class_count[p]["中班"] += 1
    elif "大" in sc:
        class_count[p]["大班"] += 1
    elif "混" in sc:
        class_count[p]["混龄班"] += 1
    elif "特" in sc:
        class_count[p]["特教班"] += 1
for p in class_count:
    class_count[p]["合计"] = class_count[p]["托班"] + class_count[p]["小班"] + class_count[p]["中班"] + class_count[p]["大班"] + class_count[p]["混龄班"] + class_count[p]["特教班"]

print("\n===== 班级数量 =====")
for park in parks:
    print(f"  {park}: {class_count[park]}")

# ===================== 3、统计户籍数据 =====================
print("\n===== 统计户籍数据 =====")
for row_dict in df_hukou:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])

    grade_main = None
    if "托" in class_name:
        grade_main = "托班"
    elif "小" in class_name:
        grade_main = "小班"
    elif "中" in class_name:
        grade_main = "中班"
    elif "大" in class_name:
        grade_main = "大班"
    elif "混" in class_name:
        grade_main = "混龄班"
    elif "特" in class_name:
        grade_main = "特教班"

    if grade_main is None or park not in park_student_data:
        continue
    if "本市本区" in content:
        park_student_data[park][grade_main]["本区"] += num
    elif "本市外区" in content:
        park_student_data[park][grade_main]["外区"] += num
    elif "外省" in content:
        park_student_data[park][grade_main]["外省"] += num
    elif "港" in content or "香港" in content:
        park_student_data[park][grade_main]["港"] += num
    elif "澳" in content or "澳门" in content:
        park_student_data[park][grade_main]["澳"] += num
    elif "台" in content or "台湾" in content:
        park_student_data[park][grade_main]["台"] += num
    elif "外籍" in content:
        park_student_data[park][grade_main]["外籍"] += num
    else:
        park_student_data[park][grade_main]["其他"] += num
print("✅ 户籍数据统计完成")

# ===================== 4、统计非本市户籍五类数据 =====================
print("\n===== 统计非户籍五类数据 =====")
class_grade_map = {}
for row in data_list:
    row_dict = dict(zip(header, row))
    if row_dict.get("列名称") == "班级":
        park = str(row_dict.get("园区") or "").strip()
        class_name = str(row_dict.get("班级") or "").strip()
        if park and class_name:
            grade = None
            if "托" in class_name:
                grade = "托班"
            elif "小" in class_name:
                grade = "小班"
            elif "中" in class_name:
                grade = "中班"
            elif "大" in class_name:
                grade = "大班"
            if grade:
                class_grade_map[(park, class_name)] = grade

non_local_data = {}
for park in parks:
    non_local_data[park] = {
        "type1": {"大班": 0, "中班": 0, "小班": 0},
        "type2": {"大班": 0, "中班": 0, "小班": 0},
        "type3": {"大班": 0, "中班": 0, "小班": 0},
        "type4": {"大班": 0, "中班": 0, "小班": 0},
        "type5": {"大班": 0, "中班": 0, "小班": 0}
    }

for row_dict in df_nonlocal:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])
    if not content or num == 0:
        continue
    if park not in parks:
        continue
    grade = class_grade_map.get((park, class_name))
    if not grade:
        continue
    if grade not in ["大班", "中班", "小班"]:
        continue

    match_type = None
    if "120" in content:
        match_type = "type1"
    elif "房产" in content and "积分不满" in content:
        match_type = "type2"
    elif "满6个月" in content and "不满" not in content:
        match_type = "type3"
    elif "不满6个月" in content:
        match_type = "type4"
    elif "无居住证" in content:
        match_type = "type5"
    if match_type:
        non_local_data[park][match_type][grade] += num

type_names = {"type1": "积分120", "type2": "仅有房产", "type3": "社保满6", "type4": "社保不满6", "type5": "无居住证"}
for park in parks:
    print(f"\n【{park}】")
    has_data = False
    for k, v in non_local_data[park].items():
        total = sum(v.values())
        if total > 0:
            has_data = True
            print(f"  {type_names.get(k)}: 合计{total}, 大班={v['大班']}, 中班={v['中班']}, 小班={v['小班']}")
    if not has_data:
        print("  无数据")

# ===================== 写入Excel基础数据(开班、户籍、非户籍) =====================
wb = load_workbook(template_excel)
ws = wb.active
cell_align = Alignment(horizontal="center", vertical="center", text_rotation=0)

row_upper = {"总园": 7, "一分园": 8, "二分园": 9}
row_detail = {"总园": 15, "一分园": 16, "二分园": 17}

# 列常量
B, C, D, E, F, G, H = 2, 3, 4, 5, 6, 7, 8
I, J, K, L, M, N = 9, 10, 11, 12, 13, 14
O, P, Q, R, S, T = 15, 16, 17, 18, 19, 20
U, V, W, X, Y, Z = 21, 22, 23, 24, 25, 26
AA, AB, AC, AD, AE, AF = 27, 28, 29, 30, 31, 32
AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU = 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47

print("\n===== 开始写入Excel主表基础数据 =====")
for park in parks:
    r_up = row_upper[park]
    r_det = row_detail[park]
    cnt = class_count[park]
    stu = park_student_data[park]
    nl = non_local_data[park]

    # 开班数量 B~H
    ws.cell(row=r_up, column=B, value=cnt["合计"]).alignment = cell_align
    ws.cell(row=r_up, column=C, value=cnt["托班"]).alignment = cell_align
    ws.cell(row=r_up, column=D, value=cnt["小班"]).alignment = cell_align
    ws.cell(row=r_up, column=E, value=cnt["中班"]).alignment = cell_align
    ws.cell(row=r_up, column=F, value=cnt["大班"]).alignment = cell_align
    ws.cell(row=r_up, column=G, value=cnt["混龄班"]).alignment = cell_align
    ws.cell(row=r_up, column=H, value=cnt["特教班"]).alignment = cell_align
    ws.cell(row=r_up, column=AT, value=cnt["混龄班"]).alignment = cell_align
    ws.cell(row=r_up, column=AU, value=cnt["特教班"]).alignment = cell_align

    # 托班户籍 J~R
    t = stu["托班"]
    ws.cell(row=r_up, column=J, value=sum(t.values())).alignment = cell_align
    ws.cell(row=r_up, column=K, value=t["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=L, value=t["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=M, value=t["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=N, value=t["港"]).alignment = cell_align
    ws.cell(row=r_up, column=O, value=t["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=P, value=t["台"]).alignment = cell_align
    ws.cell(row=r_up, column=Q, value=t["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=R, value=t["其他"]).alignment = cell_align

    # 小班户籍 S~AA
    x = stu["小班"]
    ws.cell(row=r_up, column=S, value=sum(x.values())).alignment = cell_align
    ws.cell(row=r_up, column=T, value=x["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=U, value=x["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=V, value=x["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=W, value=x["港"]).alignment = cell_align
    ws.cell(row=r_up, column=X, value=x["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=Y, value=x["台"]).alignment = cell_align
    ws.cell(row=r_up, column=Z, value=x["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=AA, value=x["其他"]).alignment = cell_align

    # 中班户籍 AB~AJ
    z = stu["中班"]
    ws.cell(row=r_up, column=AB, value=sum(z.values())).alignment = cell_align
    ws.cell(row=r_up, column=AC, value=z["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=AD, value=z["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=AE, value=z["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=AF, value=z["港"]).alignment = cell_align
    ws.cell(row=r_up, column=AG, value=z["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=AH, value=z["台"]).alignment = cell_align
    ws.cell(row=r_up, column=AI, value=z["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=AJ, value=z["其他"]).alignment = cell_align

    # 大班户籍 AK~AS
    d = stu["大班"]
    ws.cell(row=r_up, column=AK, value=sum(d.values())).alignment = cell_align
    ws.cell(row=r_up, column=AL, value=d["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=AM, value=d["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=AN, value=d["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=AO, value=d["港"]).alignment = cell_align
    ws.cell(row=r_up, column=AP, value=d["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=AQ, value=d["台"]).alignment = cell_align
    ws.cell(row=r_up, column=AR, value=d["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=AS, value=d["其他"]).alignment = cell_align

    # 非户籍明细表
    total_all = sum([sum(nl[t].values()) for t in nl])
    ws.cell(row=r_det, column=B, value=total_all).alignment = cell_align

    # type1
    ws.cell(row=r_det, column=C, value=sum(nl["type1"].values())).alignment = cell_align
    ws.cell(row=r_det, column=D, value=nl["type1"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=E, value=nl["type1"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=F, value=nl["type1"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=G, value=0).alignment = cell_align
    ws.cell(row=r_det, column=H, value=0).alignment = cell_align
    # type2
    ws.cell(row=r_det, column=I, value=sum(nl["type2"].values())).alignment = cell_align
    ws.cell(row=r_det, column=J, value=nl["type2"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=K, value=nl["type2"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=L, value=nl["type2"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=M, value=0).alignment = cell_align
    ws.cell(row=r_det, column=N, value=0).alignment = cell_align
    # type3
    ws.cell(row=r_det, column=O, value=sum(nl["type3"].values())).alignment = cell_align
    ws.cell(row=r_det, column=P, value=nl["type3"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=Q, value=nl["type3"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=R, value=nl["type3"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=S, value=0).alignment = cell_align
    ws.cell(row=r_det, column=T, value=0).alignment = cell_align
    # type4
    ws.cell(row=r_det, column=U, value=sum(nl["type4"].values())).alignment = cell_align
    ws.cell(row=r_det, column=V, value=nl["type4"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=W, value=nl["type4"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=X, value=nl["type4"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=Y, value=0).alignment = cell_align
    ws.cell(row=r_det, column=Z, value=0).alignment = cell_align
    # type5
    ws.cell(row=r_det, column=AA, value=sum(nl["type5"].values())).alignment = cell_align
    ws.cell(row=r_det, column=AB, value=nl["type5"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=AC, value=nl["type5"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=AD, value=nl["type5"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=AE, value=0).alignment = cell_align
    ws.cell(row=r_det, column=AF, value=0).alignment = cell_align

    print(f"  ✅ {park} 基础数据写入完成")

# ===================== 优抚子女明细写入【全部小计加异常捕获,固定40/41/42行】 =====================
print("\n===== 写入军人武警优抚子女明细表格 =====")
for park_name, write_r in park_write_row.items():
    data = army_warrior_total[park_name]

    # 1. 军人现役 符合本园条件
    cols = col_rule["军人现役_符合"]
    try:
        cell_obj = ws.cell(write_r, cols[0], value=sum(data["军人现役"].values()))
        cell_obj.alignment = cell_align
    except AttributeError:
        pass
    ws.cell(write_r, cols[1], value=data["军人现役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["军人现役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["军人现役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["军人现役"]["大班"]).alignment = cell_align

    # 2. 军人退役 符合本园条件
    cols = col_rule["军人退役_符合"]
    try:
        cell_obj = ws.cell(write_r, cols[0], value=sum(data["军人退役"].values()))
        cell_obj.alignment = cell_align
    except AttributeError:
        pass
    ws.cell(write_r, cols[1], value=data["军人退役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["军人退役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["军人退役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["军人退役"]["大班"]).alignment = cell_align

    # 3. 武警现役 符合本园条件
    cols = col_rule["武警现役_符合"]
    try:
        cell_obj = ws.cell(write_r, cols[0], value=sum(data["武警现役"].values()))
        cell_obj.alignment = cell_align
    except AttributeError:
        pass
    ws.cell(write_r, cols[1], value=data["武警现役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["武警现役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["武警现役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["武警现役"]["大班"]).alignment = cell_align

    # 4. 武警退役 符合本园条件
    cols = col_rule["武警退役_符合"]
    try:
        cell_obj = ws.cell(write_r, cols[0], value=sum(data["武警退役"].values()))
        cell_obj.alignment = cell_align
    except AttributeError:
        pass
    ws.cell(write_r, cols[1], value=data["武警退役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["武警退役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["武警退役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["武警退役"]["大班"]).alignment = cell_align

print("✅ 优抚子女明细全部写入完成,大班数据已锁定每组最后单元格")

# 文件保存关闭
wb.save(out_excel)
wb.close()
wb_data.save(data_excel)
wb_data.close()

print(f"\n🎉 全部程序执行完毕!输出文件路径:\n{out_excel}")

核对1:班级数

正确

所属园区

随机抽检查正确性

数据全部正确。好开心。

这个模版里面用了公式

AI编程改起来飞速

python 复制代码
'''
第3步
把分析出来的数量写入指定的模版里(保留原模版的公式,小计、总计,都不要填入数字)
豆包 阿夏
20260812
'''

from openpyxl import load_workbook
from openpyxl.styles import Alignment

# ===================== 路径配置 =====================
folder = r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
data_excel = f"{folder}\\分析.xlsx"
template_excel = f"{folder}\\1 2026学年闵行区幼儿园概况表(总分园填在一张表上)(1).xlsx"
out_excel = f"{folder}\\统计2.xlsx"  # 输出文件名改为统计2.xlsx

# ===================== 园区班级映射规则 =====================
park_class_rule = {
    "总园": ["中1", "中2", "中3", "中4", "中5", "中6", "大1", "大2", "大3", "大4", "大5"],
    "一分园": ["托1", "托2", "小4", "小5"],
    "二分园": ["托3", "小1", "小2", "小3"]
}
class_to_park = {}
for park, cls_list in park_class_rule.items():
    for cls in cls_list:
        class_to_park[cls] = park

# 班级转年级工具函数
def class_to_grade(class_name: str) -> str:
    c = class_name.strip()
    if "托" in c:
        return "托班"
    elif "小" in c:
        return "小班"
    elif "中" in c:
        return "中班"
    elif "大" in c:
        return "大班"
    return None

# ===================== 优抚表配置(固定写入40/41/42行) =====================
park_write_row = {
    "总园": 40,
    "一分园": 41,
    "二分园": 42
}
# 列组规则:(小计列, 托班列, 小班列, 中班列, 大班列)
col_rule = {
    "军人现役_符合": (3, 4, 5, 6, 7),      # C小计 D托 E小 F中 G大
    "军人退役_符合": (13, 14, 15, 16, 17), # M小计 N托 O小 P中 Q大
    "武警现役_符合": (24, 25, 26, 27, 28), # X小计 Y托 Z小 AA中 AB大
    "武警退役_符合": (34, 35, 36, 37, 38)  # AH小计 AI托 AJ小 AK中 AL大
}

# 优抚数据存储容器
army_warrior_total = {
    "总园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "一分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "二分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    }
}

# ===================== 读取数据源【分析.xlsx】提取优抚数据 =====================
wb_data = load_workbook(data_excel)
ws_data = wb_data["园区班级分层统计"]
rows_data = list(ws_data.iter_rows(values_only=True))
header = rows_data[0]
data_list = rows_data[1:]

print("===== 所有列名 =====")
for i, h in enumerate(header):
    print(f"列{i}: {h}")

# 拆分三类数据
df_hukou = []
df_nonlocal = []
df_army_warrior = []
for row in data_list:
    row_dict = dict(zip(header, row))
    col_name = row_dict.get("列名称")
    if col_name == "户籍所在地":
        df_hukou.append(row_dict)
    elif col_name == "非户籍幼儿五类明细选择":
        df_nonlocal.append(row_dict)
    elif col_name in ("军人子女类型", "武警消防子女类型"):
        df_army_warrior.append(row_dict)

print(f"\n读取户籍记录总数:{len(df_hukou)}")
print(f"读取非户籍五类记录总数:{len(df_nonlocal)}")
print(f"读取军人/武警优抚记录总数:{len(df_army_warrior)}")

# ===================== 统计优抚子女数据(从分析表汇总) =====================
print("\n===== 统计军人武警优抚子女数据 =====")
for row_dict in df_army_warrior:
    park = str(row_dict["园区"]).strip()
    cls_name = str(row_dict["班级"]).strip()
    col_type = row_dict["列名称"]
    content = str(row_dict["内容文本"]).strip()
    cnt = int(row_dict["本班出现次数"])
    grade = class_to_grade(cls_name)

    if park not in army_warrior_total or grade is None or cnt <= 0:
        continue
    target_key = None
    if col_type == "军人子女类型":
        if "现役" in content:
            target_key = "军人现役"
        elif "退役" in content:
            target_key = "军人退役"
    elif col_type == "武警消防子女类型":
        if "现役" in content:
            target_key = "武警现役"
        elif "退役" in content:
            target_key = "武警退役"
    if target_key:
        army_warrior_total[park][target_key][grade] += cnt

# 控制台打印核对数据
for park in ["总园", "一分园", "二分园"]:
    print(f"\n【{park}】优抚汇总:")
    for k, v in army_warrior_total[park].items():
        total = sum(v.values())
        print(f"  {k} 合计{total} → 托{v['托班']} 小{v['小班']} 中{v['中班']} 大{v['大班']}")

# ===================== 1、主表托小中大户籍容器 =====================
parks = ["总园", "一分园", "二分园"]
park_student_data = {
    "总园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "一分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "二分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    }
}

# ===================== 2、开班数量统计 =====================
all_class_raw = set()
for r in data_list:
    cls = dict(zip(header, r)).get("班级")
    if cls:
        all_class_raw.add(str(cls))
short_class_set = set()
for c in all_class_raw:
    short_c = str(c).replace("班", "").strip()
    short_class_set.add(short_c)

class_count = {
    "总园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0},
    "一分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0},
    "二分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0}
}
for sc in short_class_set:
    if sc not in class_to_park:
        continue
    p = class_to_park[sc]
    if "托" in sc:
        class_count[p]["托班"] += 1
    elif "小" in sc:
        class_count[p]["小班"] += 1
    elif "中" in sc:
        class_count[p]["中班"] += 1
    elif "大" in sc:
        class_count[p]["大班"] += 1
    elif "混" in sc:
        class_count[p]["混龄班"] += 1
    elif "特" in sc:
        class_count[p]["特教班"] += 1

print("\n===== 班级数量 =====")
for park in parks:
    print(f"  {park}: {class_count[park]}")

# ===================== 3、统计户籍数据 =====================
print("\n===== 统计户籍数据 =====")
for row_dict in df_hukou:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])

    grade_main = None
    if "托" in class_name:
        grade_main = "托班"
    elif "小" in class_name:
        grade_main = "小班"
    elif "中" in class_name:
        grade_main = "中班"
    elif "大" in class_name:
        grade_main = "大班"
    elif "混" in class_name:
        grade_main = "混龄班"
    elif "特" in class_name:
        grade_main = "特教班"

    if grade_main is None or park not in park_student_data:
        continue
    if "本市本区" in content:
        park_student_data[park][grade_main]["本区"] += num
    elif "本市外区" in content:
        park_student_data[park][grade_main]["外区"] += num
    elif "外省" in content:
        park_student_data[park][grade_main]["外省"] += num
    elif "港" in content or "香港" in content:
        park_student_data[park][grade_main]["港"] += num
    elif "澳" in content or "澳门" in content:
        park_student_data[park][grade_main]["澳"] += num
    elif "台" in content or "台湾" in content:
        park_student_data[park][grade_main]["台"] += num
    elif "外籍" in content:
        park_student_data[park][grade_main]["外籍"] += num
    else:
        park_student_data[park][grade_main]["其他"] += num
print("✅ 户籍数据统计完成")

# ===================== 4、统计非本市户籍五类数据 =====================
print("\n===== 统计非户籍五类数据 =====")
class_grade_map = {}
for row in data_list:
    row_dict = dict(zip(header, row))
    if row_dict.get("列名称") == "班级":
        park = str(row_dict.get("园区") or "").strip()
        class_name = str(row_dict.get("班级") or "").strip()
        if park and class_name:
            grade = None
            if "托" in class_name:
                grade = "托班"
            elif "小" in class_name:
                grade = "小班"
            elif "中" in class_name:
                grade = "中班"
            elif "大" in class_name:
                grade = "大班"
            if grade:
                class_grade_map[(park, class_name)] = grade

non_local_data = {}
for park in parks:
    non_local_data[park] = {
        "type1": {"大班": 0, "中班": 0, "小班": 0},
        "type2": {"大班": 0, "中班": 0, "小班": 0},
        "type3": {"大班": 0, "中班": 0, "小班": 0},
        "type4": {"大班": 0, "中班": 0, "小班": 0},
        "type5": {"大班": 0, "中班": 0, "小班": 0}
    }

for row_dict in df_nonlocal:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])
    if not content or num == 0:
        continue
    if park not in parks:
        continue
    grade = class_grade_map.get((park, class_name))
    if not grade:
        continue
    if grade not in ["大班", "中班", "小班"]:
        continue

    match_type = None
    if "120" in content:
        match_type = "type1"
    elif "房产" in content and "积分不满" in content:
        match_type = "type2"
    elif "满6个月" in content and "不满" not in content:
        match_type = "type3"
    elif "不满6个月" in content:
        match_type = "type4"
    elif "无居住证" in content:
        match_type = "type5"
    if match_type:
        non_local_data[park][match_type][grade] += num

type_names = {"type1": "积分120", "type2": "仅有房产", "type3": "社保满6", "type4": "社保不满6", "type5": "无居住证"}
for park in parks:
    print(f"\n【{park}】")
    has_data = False
    for k, v in non_local_data[park].items():
        total = sum(v.values())
        if total > 0:
            has_data = True
            print(f"  {type_names.get(k)}: 合计{total}, 大班={v['大班']}, 中班={v['中班']}, 小班={v['小班']}")
    if not has_data:
        print("  无数据")

# ===================== 写入Excel基础数据(只填明细,保留模板公式合计) =====================
# read_only=False 完整加载模板所有格式、公式、合并单元格
wb = load_workbook(template_excel)
ws = wb.active
cell_align = Alignment(horizontal="center", vertical="center", text_rotation=0)

row_upper = {"总园": 7, "一分园": 8, "二分园": 9}
row_detail = {"总园": 15, "一分园": 16, "二分园": 17}

# 列常量
B, C, D, E, F, G, H = 2, 3, 4, 5, 6, 7, 8
I, J, K, L, M, N = 9, 10, 11, 12, 13, 14
O, P, Q, R, S, T = 15, 16, 17, 18, 19, 20
U, V, W, X, Y, Z = 21, 22, 23, 24, 25, 26
AA, AB, AC, AD, AE, AF = 27, 28, 29, 30, 31, 32
AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU = 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47

print("\n===== 开始写入Excel明细数据(保留原有公式) =====")
for park in parks:
    r_up = row_upper[park]
    r_det = row_detail[park]
    cnt = class_count[park]
    stu = park_student_data[park]
    nl = non_local_data[park]

    # 开班数量:只填托/小/中/大/混/特明细列,B合计列不写入(模板公式自动算)
    ws.cell(row=r_up, column=C, value=cnt["托班"]).alignment = cell_align
    ws.cell(row=r_up, column=D, value=cnt["小班"]).alignment = cell_align
    ws.cell(row=r_up, column=E, value=cnt["中班"]).alignment = cell_align
    ws.cell(row=r_up, column=F, value=cnt["大班"]).alignment = cell_align
    ws.cell(row=r_up, column=G, value=cnt["混龄班"]).alignment = cell_align
    ws.cell(row=r_up, column=H, value=cnt["特教班"]).alignment = cell_align
    ws.cell(row=r_up, column=AT, value=cnt["混龄班"]).alignment = cell_align
    ws.cell(row=r_up, column=AU, value=cnt["特教班"]).alignment = cell_align

    # 托班户籍明细:本区/外区/外省/港/澳/台/外籍/其他,J小计不写入
    t = stu["托班"]
    ws.cell(row=r_up, column=K, value=t["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=L, value=t["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=M, value=t["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=N, value=t["港"]).alignment = cell_align
    ws.cell(row=r_up, column=O, value=t["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=P, value=t["台"]).alignment = cell_align
    ws.cell(row=r_up, column=Q, value=t["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=R, value=t["其他"]).alignment = cell_align

    # 小班户籍明细,S小计跳过
    x = stu["小班"]
    ws.cell(row=r_up, column=T, value=x["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=U, value=x["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=V, value=x["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=W, value=x["港"]).alignment = cell_align
    ws.cell(row=r_up, column=X, value=x["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=Y, value=x["台"]).alignment = cell_align
    ws.cell(row=r_up, column=Z, value=x["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=AA, value=x["其他"]).alignment = cell_align

    # 中班户籍明细,AB小计跳过
    z = stu["中班"]
    ws.cell(row=r_up, column=AC, value=z["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=AD, value=z["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=AE, value=z["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=AF, value=z["港"]).alignment = cell_align
    ws.cell(row=r_up, column=AG, value=z["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=AH, value=z["台"]).alignment = cell_align
    ws.cell(row=r_up, column=AI, value=z["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=AJ, value=z["其他"]).alignment = cell_align

    # 大班户籍明细,AK小计跳过
    d = stu["大班"]
    ws.cell(row=r_up, column=AL, value=d["本区"]).alignment = cell_align
    ws.cell(row=r_up, column=AM, value=d["外区"]).alignment = cell_align
    ws.cell(row=r_up, column=AN, value=d["外省"]).alignment = cell_align
    ws.cell(row=r_up, column=AO, value=d["港"]).alignment = cell_align
    ws.cell(row=r_up, column=AP, value=d["澳"]).alignment = cell_align
    ws.cell(row=r_up, column=AQ, value=d["台"]).alignment = cell_align
    ws.cell(row=r_up, column=AR, value=d["外籍"]).alignment = cell_align
    ws.cell(row=r_up, column=AS, value=d["其他"]).alignment = cell_align

    # 非户籍明细表:只填大班/中班/小班明细,每组首列小计不覆盖
    # type1 C小计跳过 D=大班 E=中班 F=小班 G/H固定0
    ws.cell(row=r_det, column=D, value=nl["type1"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=E, value=nl["type1"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=F, value=nl["type1"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=G, value=0).alignment = cell_align
    ws.cell(row=r_det, column=H, value=0).alignment = cell_align
    # type2 I小计跳过 J=大班 K=中班 L=小班
    ws.cell(row=r_det, column=J, value=nl["type2"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=K, value=nl["type2"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=L, value=nl["type2"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=M, value=0).alignment = cell_align
    ws.cell(row=r_det, column=N, value=0).alignment = cell_align
    # type3 O小计跳过 P=大班 Q=中班 R=小班
    ws.cell(row=r_det, column=P, value=nl["type3"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=Q, value=nl["type3"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=R, value=nl["type3"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=S, value=0).alignment = cell_align
    ws.cell(row=r_det, column=T, value=0).alignment = cell_align
    # type4 U小计跳过 V=大班 W=中班 X=小班
    ws.cell(row=r_det, column=V, value=nl["type4"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=W, value=nl["type4"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=X, value=nl["type4"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=Y, value=0).alignment = cell_align
    ws.cell(row=r_det, column=Z, value=0).alignment = cell_align
    # type5 AA小计跳过 AB=大班 AC=中班 AD=小班
    ws.cell(row=r_det, column=AB, value=nl["type5"]["大班"]).alignment = cell_align
    ws.cell(row=r_det, column=AC, value=nl["type5"]["中班"]).alignment = cell_align
    ws.cell(row=r_det, column=AD, value=nl["type5"]["小班"]).alignment = cell_align
    ws.cell(row=r_det, column=AE, value=0).alignment = cell_align
    ws.cell(row=r_det, column=AF, value=0).alignment = cell_align

    print(f"  ✅ {park} 明细数据写入完成(保留模板公式)")

# ===================== 优抚子女明细写入:仅填托/小/中/大,小计列完全不动 =====================
print("\n===== 写入军人武警优抚子女明细(保留模板公式) =====")
for park_name, write_r in park_write_row.items():
    data = army_warrior_total[park_name]

    # 1. 军人现役 符合:C小计不写,只填D托 E小 F中 G大
    cols = col_rule["军人现役_符合"]
    ws.cell(write_r, cols[1], value=data["军人现役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["军人现役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["军人现役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["军人现役"]["大班"]).alignment = cell_align

    # 2. 军人退役 符合:M小计不写
    cols = col_rule["军人退役_符合"]
    ws.cell(write_r, cols[1], value=data["军人退役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["军人退役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["军人退役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["军人退役"]["大班"]).alignment = cell_align

    # 3. 武警现役 符合:X小计不写
    cols = col_rule["武警现役_符合"]
    ws.cell(write_r, cols[1], value=data["武警现役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["武警现役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["武警现役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["武警现役"]["大班"]).alignment = cell_align

    # 4. 武警退役 符合:AH小计不写
    cols = col_rule["武警退役_符合"]
    ws.cell(write_r, cols[1], value=data["武警退役"]["托班"]).alignment = cell_align
    ws.cell(write_r, cols[2], value=data["武警退役"]["小班"]).alignment = cell_align
    ws.cell(write_r, cols[3], value=data["武警退役"]["中班"]).alignment = cell_align
    ws.cell(write_r, cols[4], value=data["武警退役"]["大班"]).alignment = cell_align

print("✅ 优抚明细写入完成,所有小计/合计单元格未覆盖,保留Excel原有公式")

# 文件保存:另存新文件,模板原文件完全不修改
wb.save(out_excel)
wb.close()
# 数据源文件仅关闭不重写,避免破坏原分析表
wb_data.close()

print(f"\n🎉 全部程序执行完毕!输出文件路径:\n{out_excel}")

是否要补全0

我之前做托幼人数上报,系统里必须把所有数据都填写,空数据就补0

但是这次要不要补0呢

修改思路

1、我的园区是按 一分园、二分园,根据园所编号 是一分园01,总园02,二分园03。

2、文件名明确要求,不要补0

python 复制代码
'''
第3步
把分析出来的数量写入指定的模版里(保留原模版的公式,小计、总计,都不要填入数字)
不要补0
豆包 阿夏
20260812
'''
from openpyxl import load_workbook
from openpyxl.styles import Alignment

# ===================== 路径配置 =====================
folder = r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
data_excel = f"{folder}\\分析.xlsx"
template_excel = f"{folder}\\1 2026学年闵行区幼儿园概况表(总分园填在一张表上)(1).xlsx"
out_excel = f"{folder}\\统计2.xlsx"

# ===================== 园区班级映射规则 =====================
park_class_rule = {
    "总园": ["中1", "中2", "中3", "中4", "中5", "中6", "大1", "大2", "大3", "大4", "大5"],
    "一分园": ["托1", "托2", "小4", "小5"],
    "二分园": ["托3", "小1", "小2", "小3"]
}
class_to_park = {}
for park, cls_list in park_class_rule.items():
    for cls in cls_list:
        class_to_park[cls] = park

# 班级转年级工具函数
def class_to_grade(class_name: str) -> str:
    c = class_name.strip()
    if "托" in c:
        return "托班"
    elif "小" in c:
        return "小班"
    elif "中" in c:
        return "中班"
    elif "大" in c:
        return "大班"
    return None

# ===================== 优抚表配置(固定写入40/41/42行) =====================
park_write_row = {
    "总园": 40,
    "一分园": 41,
    "二分园": 42
}
# 列组规则:(小计列, 托班列, 小班列, 中班列, 大班列)
col_rule = {
    "军人现役_符合": (3, 4, 5, 6, 7),      # C小计 D托 E小 F中 G大
    "军人退役_符合": (13, 14, 15, 16, 17), # M小计 N托 O小 P中 Q大
    "武警现役_符合": (24, 25, 26, 27, 28), # X小计 Y托 Z小 AA中 AB大
    "武警退役_符合": (34, 35, 36, 37, 38)  # AH小计 AI托 AJ小 AK中 AL大
}

# 优抚数据存储容器
army_warrior_total = {
    "总园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "一分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "二分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    }
}

# ===================== 读取数据源【分析.xlsx】提取优抚数据 =====================
wb_data = load_workbook(data_excel)
ws_data = wb_data["园区班级分层统计"]
rows_data = list(ws_data.iter_rows(values_only=True))
header = rows_data[0]
data_list = rows_data[1:]

print("===== 所有列名 =====")
for i, h in enumerate(header):
    print(f"列{i}: {h}")

# 拆分三类数据
df_hukou = []
df_nonlocal = []
df_army_warrior = []
for row in data_list:
    row_dict = dict(zip(header, row))
    col_name = row_dict.get("列名称")
    if col_name == "户籍所在地":
        df_hukou.append(row_dict)
    elif col_name == "非户籍幼儿五类明细选择":
        df_nonlocal.append(row_dict)
    elif col_name in ("军人子女类型", "武警消防子女类型"):
        df_army_warrior.append(row_dict)

print(f"\n读取户籍记录总数:{len(df_hukou)}")
print(f"读取非户籍五类记录总数:{len(df_nonlocal)}")
print(f"读取军人/武警优抚记录总数:{len(df_army_warrior)}")

# ===================== 统计优抚子女数据(从分析表汇总) =====================
print("\n===== 统计军人武警优抚子女数据 =====")
for row_dict in df_army_warrior:
    park = str(row_dict["园区"]).strip()
    cls_name = str(row_dict["班级"]).strip()
    col_type = row_dict["列名称"]
    content = str(row_dict["内容文本"]).strip()
    cnt = int(row_dict["本班出现次数"])
    grade = class_to_grade(cls_name)

    if park not in army_warrior_total or grade is None or cnt <= 0:
        continue
    target_key = None
    if col_type == "军人子女类型":
        if "现役" in content:
            target_key = "军人现役"
        elif "退役" in content:
            target_key = "军人退役"
    elif col_type == "武警消防子女类型":
        if "现役" in content:
            target_key = "武警现役"
        elif "退役" in content:
            target_key = "武警退役"
    if target_key:
        army_warrior_total[park][target_key][grade] += cnt

# 控制台打印核对数据
for park in ["总园", "一分园", "二分园"]:
    print(f"\n【{park}】优抚汇总:")
    for k, v in army_warrior_total[park].items():
        total = sum(v.values())
        print(f"  {k} 合计{total} → 托{v['托班']} 小{v['小班']} 中{v['中班']} 大{v['大班']}")

# ===================== 1、主表托小中大户籍容器 =====================
parks = ["总园", "一分园", "二分园"]
park_student_data = {
    "总园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "一分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "二分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    }
}

# ===================== 2、开班数量统计 =====================
all_class_raw = set()
for r in data_list:
    cls = dict(zip(header, r)).get("班级")
    if cls:
        all_class_raw.add(str(cls))
short_class_set = set()
for c in all_class_raw:
    short_c = str(c).replace("班", "").strip()
    short_class_set.add(short_c)

class_count = {
    "总园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0},
    "一分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0},
    "二分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0}
}
for sc in short_class_set:
    if sc not in class_to_park:
        continue
    p = class_to_park[sc]
    if "托" in sc:
        class_count[p]["托班"] += 1
    elif "小" in sc:
        class_count[p]["小班"] += 1
    elif "中" in sc:
        class_count[p]["中班"] += 1
    elif "大" in sc:
        class_count[p]["大班"] += 1
    elif "混" in sc:
        class_count[p]["混龄班"] += 1
    elif "特" in sc:
        class_count[p]["特教班"] += 1

print("\n===== 班级数量 =====")
for park in parks:
    print(f"  {park}: {class_count[park]}")

# ===================== 3、统计户籍数据 =====================
print("\n===== 统计户籍数据 =====")
for row_dict in df_hukou:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])

    grade_main = None
    if "托" in class_name:
        grade_main = "托班"
    elif "小" in class_name:
        grade_main = "小班"
    elif "中" in class_name:
        grade_main = "中班"
    elif "大" in class_name:
        grade_main = "大班"
    elif "混" in class_name:
        grade_main = "混龄班"
    elif "特" in class_name:
        grade_main = "特教班"

    if grade_main is None or park not in park_student_data:
        continue
    if "本市本区" in content:
        park_student_data[park][grade_main]["本区"] += num
    elif "本市外区" in content:
        park_student_data[park][grade_main]["外区"] += num
    elif "外省" in content:
        park_student_data[park][grade_main]["外省"] += num
    elif "港" in content or "香港" in content:
        park_student_data[park][grade_main]["港"] += num
    elif "澳" in content or "澳门" in content:
        park_student_data[park][grade_main]["澳"] += num
    elif "台" in content or "台湾" in content:
        park_student_data[park][grade_main]["台"] += num
    elif "外籍" in content:
        park_student_data[park][grade_main]["外籍"] += num
    else:
        park_student_data[park][grade_main]["其他"] += num
print("✅ 户籍数据统计完成")

# ===================== 4、统计非本市户籍五类数据 =====================
print("\n===== 统计非户籍五类数据 =====")
class_grade_map = {}
for row in data_list:
    row_dict = dict(zip(header, row))
    if row_dict.get("列名称") == "班级":
        park = str(row_dict.get("园区") or "").strip()
        class_name = str(row_dict.get("班级") or "").strip()
        if park and class_name:
            grade = None
            if "托" in class_name:
                grade = "托班"
            elif "小" in class_name:
                grade = "小班"
            elif "中" in class_name:
                grade = "中班"
            elif "大" in class_name:
                grade = "大班"
            if grade:
                class_grade_map[(park, class_name)] = grade

non_local_data = {}
for park in parks:
    non_local_data[park] = {
        "type1": {"大班": 0, "中班": 0, "小班": 0},
        "type2": {"大班": 0, "中班": 0, "小班": 0},
        "type3": {"大班": 0, "中班": 0, "小班": 0},
        "type4": {"大班": 0, "中班": 0, "小班": 0},
        "type5": {"大班": 0, "中班": 0, "小班": 0}
    }

for row_dict in df_nonlocal:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])
    if not content or num == 0:
        continue
    if park not in parks:
        continue
    grade = class_grade_map.get((park, class_name))
    if not grade:
        continue
    if grade not in ["大班", "中班", "小班"]:
        continue

    match_type = None
    if "120" in content:
        match_type = "type1"
    elif "房产" in content and "积分不满" in content:
        match_type = "type2"
    elif "满6个月" in content and "不满" not in content:
        match_type = "type3"
    elif "不满6个月" in content:
        match_type = "type4"
    elif "无居住证" in content:
        match_type = "type5"
    if match_type:
        non_local_data[park][match_type][grade] += num

type_names = {"type1": "积分120", "type2": "仅有房产", "type3": "社保满6", "type4": "社保不满6", "type5": "无居住证"}
for park in parks:
    print(f"\n【{park}】")
    has_data = False
    for k, v in non_local_data[park].items():
        total = sum(v.values())
        if total > 0:
            has_data = True
            print(f"  {type_names.get(k)}: 合计{total}, 大班={v['大班']}, 中班={v['中班']}, 小班={v['小班']}")
    if not has_data:
        print("  无数据")

# ===================== 写入Excel基础数据(0值不写入,保留模板空白,不碰小计公式) =====================
wb = load_workbook(template_excel)
ws = wb.active
cell_align = Alignment(horizontal="center", vertical="center", text_rotation=0)

row_upper = {"总园": 7, "一分园": 8, "二分园": 9}
row_detail = {"总园": 15, "一分园": 16, "二分园": 17}

# 列常量
B, C, D, E, F, G, H = 2, 3, 4, 5, 6, 7, 8
I, J, K, L, M, N = 9, 10, 11, 12, 13, 14
O, P, Q, R, S, T = 15, 16, 17, 18, 19, 20
U, V, W, X, Y, Z = 21, 22, 23, 24, 25, 26
AA, AB, AC, AD, AE, AF = 27, 28, 29, 30, 31, 32
AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU = 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47

print("\n===== 开始写入Excel明细数据(0值不填充,保留原有公式) =====")
for park in parks:
    r_up = row_upper[park]
    r_det = row_detail[park]
    cnt = class_count[park]
    stu = park_student_data[park]
    nl = non_local_data[park]

    # 开班明细:数值>0才写入
    if cnt["托班"] > 0:
        ws.cell(row=r_up, column=C, value=cnt["托班"]).alignment = cell_align
    if cnt["小班"] > 0:
        ws.cell(row=r_up, column=D, value=cnt["小班"]).alignment = cell_align
    if cnt["中班"] > 0:
        ws.cell(row=r_up, column=E, value=cnt["中班"]).alignment = cell_align
    if cnt["大班"] > 0:
        ws.cell(row=r_up, column=F, value=cnt["大班"]).alignment = cell_align
    if cnt["混龄班"] > 0:
        ws.cell(row=r_up, column=G, value=cnt["混龄班"]).alignment = cell_align
        ws.cell(row=r_up, column=AT, value=cnt["混龄班"]).alignment = cell_align
    if cnt["特教班"] > 0:
        ws.cell(row=r_up, column=H, value=cnt["特教班"]).alignment = cell_align
        ws.cell(row=r_up, column=AU, value=cnt["特教班"]).alignment = cell_align

    # 托班户籍明细
    t = stu["托班"]
    if t["本区"] > 0:
        ws.cell(row=r_up, column=K, value=t["本区"]).alignment = cell_align
    if t["外区"] > 0:
        ws.cell(row=r_up, column=L, value=t["外区"]).alignment = cell_align
    if t["外省"] > 0:
        ws.cell(row=r_up, column=M, value=t["外省"]).alignment = cell_align
    if t["港"] > 0:
        ws.cell(row=r_up, column=N, value=t["港"]).alignment = cell_align
    if t["澳"] > 0:
        ws.cell(row=r_up, column=O, value=t["澳"]).alignment = cell_align
    if t["台"] > 0:
        ws.cell(row=r_up, column=P, value=t["台"]).alignment = cell_align
    if t["外籍"] > 0:
        ws.cell(row=r_up, column=Q, value=t["外籍"]).alignment = cell_align
    if t["其他"] > 0:
        ws.cell(row=r_up, column=R, value=t["其他"]).alignment = cell_align

    # 小班户籍明细
    x = stu["小班"]
    if x["本区"] > 0:
        ws.cell(row=r_up, column=T, value=x["本区"]).alignment = cell_align
    if x["外区"] > 0:
        ws.cell(row=r_up, column=U, value=x["外区"]).alignment = cell_align
    if x["外省"] > 0:
        ws.cell(row=r_up, column=V, value=x["外省"]).alignment = cell_align
    if x["港"] > 0:
        ws.cell(row=r_up, column=W, value=x["港"]).alignment = cell_align
    if x["澳"] > 0:
        ws.cell(row=r_up, column=X, value=x["澳"]).alignment = cell_align
    if x["台"] > 0:
        ws.cell(row=r_up, column=Y, value=x["台"]).alignment = cell_align
    if x["外籍"] > 0:
        ws.cell(row=r_up, column=Z, value=x["外籍"]).alignment = cell_align
    if x["其他"] > 0:
        ws.cell(row=r_up, column=AA, value=x["其他"]).alignment = cell_align

    # 中班户籍明细
    z = stu["中班"]
    if z["本区"] > 0:
        ws.cell(row=r_up, column=AC, value=z["本区"]).alignment = cell_align
    if z["外区"] > 0:
        ws.cell(row=r_up, column=AD, value=z["外区"]).alignment = cell_align
    if z["外省"] > 0:
        ws.cell(row=r_up, column=AE, value=z["外省"]).alignment = cell_align
    if z["港"] > 0:
        ws.cell(row=r_up, column=AF, value=z["港"]).alignment = cell_align
    if z["澳"] > 0:
        ws.cell(row=r_up, column=AG, value=z["澳"]).alignment = cell_align
    if z["台"] > 0:
        ws.cell(row=r_up, column=AH, value=z["台"]).alignment = cell_align
    if z["外籍"] > 0:
        ws.cell(row=r_up, column=AI, value=z["外籍"]).alignment = cell_align
    if z["其他"] > 0:
        ws.cell(row=r_up, column=AJ, value=z["其他"]).alignment = cell_align

    # 大班户籍明细
    d = stu["大班"]
    if d["本区"] > 0:
        ws.cell(row=r_up, column=AL, value=d["本区"]).alignment = cell_align
    if d["外区"] > 0:
        ws.cell(row=r_up, column=AM, value=d["外区"]).alignment = cell_align
    if d["外省"] > 0:
        ws.cell(row=r_up, column=AN, value=d["外省"]).alignment = cell_align
    if d["港"] > 0:
        ws.cell(row=r_up, column=AO, value=d["港"]).alignment = cell_align
    if d["澳"] > 0:
        ws.cell(row=r_up, column=AP, value=d["澳"]).alignment = cell_align
    if d["台"] > 0:
        ws.cell(row=r_up, column=AQ, value=d["台"]).alignment = cell_align
    if d["外籍"] > 0:
        ws.cell(row=r_up, column=AR, value=d["外籍"]).alignment = cell_align
    if d["其他"] > 0:
        ws.cell(row=r_up, column=AS, value=d["其他"]).alignment = cell_align

    # 非户籍五类明细,移除所有填0代码,仅数值>0写入
    # type1
    if nl["type1"]["大班"] > 0:
        ws.cell(row=r_det, column=D, value=nl["type1"]["大班"]).alignment = cell_align
    if nl["type1"]["中班"] > 0:
        ws.cell(row=r_det, column=E, value=nl["type1"]["中班"]).alignment = cell_align
    if nl["type1"]["小班"] > 0:
        ws.cell(row=r_det, column=F, value=nl["type1"]["小班"]).alignment = cell_align
    # type2
    if nl["type2"]["大班"] > 0:
        ws.cell(row=r_det, column=J, value=nl["type2"]["大班"]).alignment = cell_align
    if nl["type2"]["中班"] > 0:
        ws.cell(row=r_det, column=K, value=nl["type2"]["中班"]).alignment = cell_align
    if nl["type2"]["小班"] > 0:
        ws.cell(row=r_det, column=L, value=nl["type2"]["小班"]).alignment = cell_align
    # type3
    if nl["type3"]["大班"] > 0:
        ws.cell(row=r_det, column=P, value=nl["type3"]["大班"]).alignment = cell_align
    if nl["type3"]["中班"] > 0:
        ws.cell(row=r_det, column=Q, value=nl["type3"]["中班"]).alignment = cell_align
    if nl["type3"]["小班"] > 0:
        ws.cell(row=r_det, column=R, value=nl["type3"]["小班"]).alignment = cell_align
    # type4
    if nl["type4"]["大班"] > 0:
        ws.cell(row=r_det, column=V, value=nl["type4"]["大班"]).alignment = cell_align
    if nl["type4"]["中班"] > 0:
        ws.cell(row=r_det, column=W, value=nl["type4"]["中班"]).alignment = cell_align
    if nl["type4"]["小班"] > 0:
        ws.cell(row=r_det, column=X, value=nl["type4"]["小班"]).alignment = cell_align
    # type5
    if nl["type5"]["大班"] > 0:
        ws.cell(row=r_det, column=AB, value=nl["type5"]["大班"]).alignment = cell_align
    if nl["type5"]["中班"] > 0:
        ws.cell(row=r_det, column=AC, value=nl["type5"]["中班"]).alignment = cell_align
    if nl["type5"]["小班"] > 0:
        ws.cell(row=r_det, column=AD, value=nl["type5"]["小班"]).alignment = cell_align

    print(f"  ✅ {park} 明细数据写入完成(0值不填充,保留模板公式)")

# ===================== 优抚子女明细写入:0值跳过,不填0、不碰小计列 =====================
print("\n===== 写入军人武警优抚子女明细(0值不填充) =====")
for park_name, write_r in park_write_row.items():
    data = army_warrior_total[park_name]
    # 军人现役
    cols = col_rule["军人现役_符合"]
    if data["军人现役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["军人现役"]["托班"]).alignment = cell_align
    if data["军人现役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["军人现役"]["小班"]).alignment = cell_align
    if data["军人现役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["军人现役"]["中班"]).alignment = cell_align
    if data["军人现役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["军人现役"]["大班"]).alignment = cell_align

    # 军人退役
    cols = col_rule["军人退役_符合"]
    if data["军人退役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["军人退役"]["托班"]).alignment = cell_align
    if data["军人退役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["军人退役"]["小班"]).alignment = cell_align
    if data["军人退役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["军人退役"]["中班"]).alignment = cell_align
    if data["军人退役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["军人退役"]["大班"]).alignment = cell_align

    # 武警现役
    cols = col_rule["武警现役_符合"]
    if data["武警现役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["武警现役"]["托班"]).alignment = cell_align
    if data["武警现役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["武警现役"]["小班"]).alignment = cell_align
    if data["武警现役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["武警现役"]["中班"]).alignment = cell_align
    if data["武警现役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["武警现役"]["大班"]).alignment = cell_align

    # 武警退役
    cols = col_rule["武警退役_符合"]
    if data["武警退役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["武警退役"]["托班"]).alignment = cell_align
    if data["武警退役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["武警退役"]["小班"]).alignment = cell_align
    if data["武警退役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["武警退役"]["中班"]).alignment = cell_align
    if data["武警退役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["武警退役"]["大班"]).alignment = cell_align

print("✅ 优抚明细写入完成,无数据单元格保持空白,所有小计/合计公式完整保留")

# 保存输出
wb.save(out_excel)
wb.close()
wb_data.close()

print(f"\n🎉 全部程序执行完毕!输出文件路径:\n{out_excel}")

对比图

无0效果图更干净

明天问问领导,一分园和二分园的排序方式,

如果总园02默认第一个,那么分园按序排列,都是一分园(一 01)在前,二分园(二 03)在后。

需要要完全按照编号,就是一分园01、总园02、二分园03,参数写入位置又要重新调整了。

特别说明:

必须把班级改成统一样式,否则,程序会生成很多"未知园区"

不仅有填错年级(中1班升班为大1班,家长还不熟新的年级,默认写中1),还有填错班级数字的(中2班),

所以一定要让班主任用"预设名单",确保每个人都填写。

又来了一个班,继续三次批量

python 复制代码
'''
第3步
把分析出来的数量写入指定的模版里(保留原模版的公式,小计、总计,都不要填入数字)
不要补0
豆包 阿夏
20260812
'''
from openpyxl import load_workbook
from openpyxl.styles import Alignment

# ===================== 路径配置 =====================
folder = r'C:\Users\mhjg2\Desktop\20260812幼儿园户籍信息统计'
data_excel = f"{folder}\\分析.xlsx"
template_excel = f"{folder}\\1 2026学年闵行区幼儿园概况表(总分园填在一张表上)(1).xlsx"
out_excel = f"{folder}\\2026学年闵行区幼儿园概况表(XXXX总分园).xlsx"

# ===================== 园区班级映射规则 =====================
park_class_rule = {
    "总园": ["中1", "中2", "中3", "中4", "中5", "中6", "大1", "大2", "大3", "大4", "大5"],
    "一分园": ["托1", "托2", "小4", "小5"],
    "二分园": ["托3", "小1", "小2", "小3"]
}
class_to_park = {}
for park, cls_list in park_class_rule.items():
    for cls in cls_list:
        class_to_park[cls] = park

# 班级转年级工具函数
def class_to_grade(class_name: str) -> str:
    c = class_name.strip()
    if "托" in c:
        return "托班"
    elif "小" in c:
        return "小班"
    elif "中" in c:
        return "中班"
    elif "大" in c:
        return "大班"
    return None

# ===================== 优抚表配置(固定写入40/41/42行) =====================
park_write_row = {
    "总园": 40,
    "一分园": 41,
    "二分园": 42
}
# 列组规则:(小计列, 托班列, 小班列, 中班列, 大班列)
col_rule = {
    "军人现役_符合": (3, 4, 5, 6, 7),      # C小计 D托 E小 F中 G大
    "军人退役_符合": (13, 14, 15, 16, 17), # M小计 N托 O小 P中 Q大
    "武警现役_符合": (24, 25, 26, 27, 28), # X小计 Y托 Z小 AA中 AB大
    "武警退役_符合": (34, 35, 36, 37, 38)  # AH小计 AI托 AJ小 AK中 AL大
}

# 优抚数据存储容器
army_warrior_total = {
    "总园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "一分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    },
    "二分园": {
        "军人现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "军人退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警现役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0},
        "武警退役": {"托班": 0, "小班": 0, "中班": 0, "大班": 0}
    }
}

# ===================== 读取数据源【分析.xlsx】提取优抚数据 =====================
wb_data = load_workbook(data_excel)
ws_data = wb_data["园区班级分层统计"]
rows_data = list(ws_data.iter_rows(values_only=True))
header = rows_data[0]
data_list = rows_data[1:]

print("===== 所有列名 =====")
for i, h in enumerate(header):
    print(f"列{i}: {h}")

# 拆分三类数据
df_hukou = []
df_nonlocal = []
df_army_warrior = []
for row in data_list:
    row_dict = dict(zip(header, row))
    col_name = row_dict.get("列名称")
    if col_name == "户籍所在地":
        df_hukou.append(row_dict)
    elif col_name == "非户籍幼儿五类明细选择":
        df_nonlocal.append(row_dict)
    elif col_name in ("军人子女类型", "武警消防子女类型"):
        df_army_warrior.append(row_dict)

print(f"\n读取户籍记录总数:{len(df_hukou)}")
print(f"读取非户籍五类记录总数:{len(df_nonlocal)}")
print(f"读取军人/武警优抚记录总数:{len(df_army_warrior)}")

# ===================== 统计优抚子女数据(从分析表汇总) =====================
print("\n===== 统计军人武警优抚子女数据 =====")
for row_dict in df_army_warrior:
    park = str(row_dict["园区"]).strip()
    cls_name = str(row_dict["班级"]).strip()
    col_type = row_dict["列名称"]
    content = str(row_dict["内容文本"]).strip()
    cnt = int(row_dict["本班出现次数"])
    grade = class_to_grade(cls_name)

    if park not in army_warrior_total or grade is None or cnt <= 0:
        continue
    target_key = None
    if col_type == "军人子女类型":
        if "现役" in content:
            target_key = "军人现役"
        elif "退役" in content:
            target_key = "军人退役"
    elif col_type == "武警消防子女类型":
        if "现役" in content:
            target_key = "武警现役"
        elif "退役" in content:
            target_key = "武警退役"
    if target_key:
        army_warrior_total[park][target_key][grade] += cnt

# 控制台打印核对数据
for park in ["总园", "一分园", "二分园"]:
    print(f"\n【{park}】优抚汇总:")
    for k, v in army_warrior_total[park].items():
        total = sum(v.values())
        print(f"  {k} 合计{total} → 托{v['托班']} 小{v['小班']} 中{v['中班']} 大{v['大班']}")

# ===================== 1、主表托小中大户籍容器 =====================
parks = ["总园", "一分园", "二分园"]
park_student_data = {
    "总园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "一分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    },
    "二分园": {
        "托班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "小班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "中班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0},
        "大班": {"本区": 0, "外区": 0, "外省": 0, "港": 0, "澳": 0, "台": 0, "外籍": 0, "其他": 0}
    }
}

# ===================== 2、开班数量统计 =====================
all_class_raw = set()
for r in data_list:
    cls = dict(zip(header, r)).get("班级")
    if cls:
        all_class_raw.add(str(cls))
short_class_set = set()
for c in all_class_raw:
    short_c = str(c).replace("班", "").strip()
    short_class_set.add(short_c)

class_count = {
    "总园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0},
    "一分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0},
    "二分园": {"托班": 0, "小班": 0, "中班": 0, "大班": 0, "混龄班": 0, "特教班": 0}
}
for sc in short_class_set:
    if sc not in class_to_park:
        continue
    p = class_to_park[sc]
    if "托" in sc:
        class_count[p]["托班"] += 1
    elif "小" in sc:
        class_count[p]["小班"] += 1
    elif "中" in sc:
        class_count[p]["中班"] += 1
    elif "大" in sc:
        class_count[p]["大班"] += 1
    elif "混" in sc:
        class_count[p]["混龄班"] += 1
    elif "特" in sc:
        class_count[p]["特教班"] += 1

print("\n===== 班级数量 =====")
for park in parks:
    print(f"  {park}: {class_count[park]}")

# ===================== 3、统计户籍数据 =====================
print("\n===== 统计户籍数据 =====")
for row_dict in df_hukou:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])

    grade_main = None
    if "托" in class_name:
        grade_main = "托班"
    elif "小" in class_name:
        grade_main = "小班"
    elif "中" in class_name:
        grade_main = "中班"
    elif "大" in class_name:
        grade_main = "大班"
    elif "混" in class_name:
        grade_main = "混龄班"
    elif "特" in class_name:
        grade_main = "特教班"

    if grade_main is None or park not in park_student_data:
        continue
    if "本市本区" in content:
        park_student_data[park][grade_main]["本区"] += num
    elif "本市外区" in content:
        park_student_data[park][grade_main]["外区"] += num
    elif "外省" in content:
        park_student_data[park][grade_main]["外省"] += num
    elif "港" in content or "香港" in content:
        park_student_data[park][grade_main]["港"] += num
    elif "澳" in content or "澳门" in content:
        park_student_data[park][grade_main]["澳"] += num
    elif "台" in content or "台湾" in content:
        park_student_data[park][grade_main]["台"] += num
    elif "外籍" in content:
        park_student_data[park][grade_main]["外籍"] += num
    else:
        park_student_data[park][grade_main]["其他"] += num
print("✅ 户籍数据统计完成")

# ===================== 4、统计非本市户籍五类数据 =====================
print("\n===== 统计非户籍五类数据 =====")
class_grade_map = {}
for row in data_list:
    row_dict = dict(zip(header, row))
    if row_dict.get("列名称") == "班级":
        park = str(row_dict.get("园区") or "").strip()
        class_name = str(row_dict.get("班级") or "").strip()
        if park and class_name:
            grade = None
            if "托" in class_name:
                grade = "托班"
            elif "小" in class_name:
                grade = "小班"
            elif "中" in class_name:
                grade = "中班"
            elif "大" in class_name:
                grade = "大班"
            if grade:
                class_grade_map[(park, class_name)] = grade

non_local_data = {}
for park in parks:
    non_local_data[park] = {
        "type1": {"大班": 0, "中班": 0, "小班": 0},
        "type2": {"大班": 0, "中班": 0, "小班": 0},
        "type3": {"大班": 0, "中班": 0, "小班": 0},
        "type4": {"大班": 0, "中班": 0, "小班": 0},
        "type5": {"大班": 0, "中班": 0, "小班": 0}
    }

for row_dict in df_nonlocal:
    park = str(row_dict["园区"]).strip()
    class_name = str(row_dict["班级"]).strip()
    content = str(row_dict["内容文本"]).strip()
    num = int(row_dict["本班出现次数"])
    if not content or num == 0:
        continue
    if park not in parks:
        continue
    grade = class_grade_map.get((park, class_name))
    if not grade:
        continue
    if grade not in ["大班", "中班", "小班"]:
        continue

    match_type = None
    if "120" in content:
        match_type = "type1"
    elif "房产" in content and "积分不满" in content:
        match_type = "type2"
    elif "满6个月" in content and "不满" not in content:
        match_type = "type3"
    elif "不满6个月" in content:
        match_type = "type4"
    elif "无居住证" in content:
        match_type = "type5"
    if match_type:
        non_local_data[park][match_type][grade] += num

type_names = {"type1": "积分120", "type2": "仅有房产", "type3": "社保满6", "type4": "社保不满6", "type5": "无居住证"}
for park in parks:
    print(f"\n【{park}】")
    has_data = False
    for k, v in non_local_data[park].items():
        total = sum(v.values())
        if total > 0:
            has_data = True
            print(f"  {type_names.get(k)}: 合计{total}, 大班={v['大班']}, 中班={v['中班']}, 小班={v['小班']}")
    if not has_data:
        print("  无数据")

# ===================== 写入Excel基础数据(0值不写入,保留模板空白,不碰小计公式) =====================
wb = load_workbook(template_excel)
ws = wb.active
cell_align = Alignment(horizontal="center", vertical="center", text_rotation=0)

row_upper = {"总园": 7, "一分园": 8, "二分园": 9}
row_detail = {"总园": 15, "一分园": 16, "二分园": 17}

# 列常量
B, C, D, E, F, G, H = 2, 3, 4, 5, 6, 7, 8
I, J, K, L, M, N = 9, 10, 11, 12, 13, 14
O, P, Q, R, S, T = 15, 16, 17, 18, 19, 20
U, V, W, X, Y, Z = 21, 22, 23, 24, 25, 26
AA, AB, AC, AD, AE, AF = 27, 28, 29, 30, 31, 32
AG, AH, AI, AJ, AK, AL, AM, AN, AO, AP, AQ, AR, AS, AT, AU = 33, 34, 35, 36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47

print("\n===== 开始写入Excel明细数据(0值不填充,保留原有公式) =====")
for park in parks:
    r_up = row_upper[park]
    r_det = row_detail[park]
    cnt = class_count[park]
    stu = park_student_data[park]
    nl = non_local_data[park]

    # 开班明细:数值>0才写入
    if cnt["托班"] > 0:
        ws.cell(row=r_up, column=C, value=cnt["托班"]).alignment = cell_align
    if cnt["小班"] > 0:
        ws.cell(row=r_up, column=D, value=cnt["小班"]).alignment = cell_align
    if cnt["中班"] > 0:
        ws.cell(row=r_up, column=E, value=cnt["中班"]).alignment = cell_align
    if cnt["大班"] > 0:
        ws.cell(row=r_up, column=F, value=cnt["大班"]).alignment = cell_align
    if cnt["混龄班"] > 0:
        ws.cell(row=r_up, column=G, value=cnt["混龄班"]).alignment = cell_align
        ws.cell(row=r_up, column=AT, value=cnt["混龄班"]).alignment = cell_align
    if cnt["特教班"] > 0:
        ws.cell(row=r_up, column=H, value=cnt["特教班"]).alignment = cell_align
        ws.cell(row=r_up, column=AU, value=cnt["特教班"]).alignment = cell_align

    # 托班户籍明细
    t = stu["托班"]
    if t["本区"] > 0:
        ws.cell(row=r_up, column=K, value=t["本区"]).alignment = cell_align
    if t["外区"] > 0:
        ws.cell(row=r_up, column=L, value=t["外区"]).alignment = cell_align
    if t["外省"] > 0:
        ws.cell(row=r_up, column=M, value=t["外省"]).alignment = cell_align
    if t["港"] > 0:
        ws.cell(row=r_up, column=N, value=t["港"]).alignment = cell_align
    if t["澳"] > 0:
        ws.cell(row=r_up, column=O, value=t["澳"]).alignment = cell_align
    if t["台"] > 0:
        ws.cell(row=r_up, column=P, value=t["台"]).alignment = cell_align
    if t["外籍"] > 0:
        ws.cell(row=r_up, column=Q, value=t["外籍"]).alignment = cell_align
    if t["其他"] > 0:
        ws.cell(row=r_up, column=R, value=t["其他"]).alignment = cell_align

    # 小班户籍明细
    x = stu["小班"]
    if x["本区"] > 0:
        ws.cell(row=r_up, column=T, value=x["本区"]).alignment = cell_align
    if x["外区"] > 0:
        ws.cell(row=r_up, column=U, value=x["外区"]).alignment = cell_align
    if x["外省"] > 0:
        ws.cell(row=r_up, column=V, value=x["外省"]).alignment = cell_align
    if x["港"] > 0:
        ws.cell(row=r_up, column=W, value=x["港"]).alignment = cell_align
    if x["澳"] > 0:
        ws.cell(row=r_up, column=X, value=x["澳"]).alignment = cell_align
    if x["台"] > 0:
        ws.cell(row=r_up, column=Y, value=x["台"]).alignment = cell_align
    if x["外籍"] > 0:
        ws.cell(row=r_up, column=Z, value=x["外籍"]).alignment = cell_align
    if x["其他"] > 0:
        ws.cell(row=r_up, column=AA, value=x["其他"]).alignment = cell_align

    # 中班户籍明细
    z = stu["中班"]
    if z["本区"] > 0:
        ws.cell(row=r_up, column=AC, value=z["本区"]).alignment = cell_align
    if z["外区"] > 0:
        ws.cell(row=r_up, column=AD, value=z["外区"]).alignment = cell_align
    if z["外省"] > 0:
        ws.cell(row=r_up, column=AE, value=z["外省"]).alignment = cell_align
    if z["港"] > 0:
        ws.cell(row=r_up, column=AF, value=z["港"]).alignment = cell_align
    if z["澳"] > 0:
        ws.cell(row=r_up, column=AG, value=z["澳"]).alignment = cell_align
    if z["台"] > 0:
        ws.cell(row=r_up, column=AH, value=z["台"]).alignment = cell_align
    if z["外籍"] > 0:
        ws.cell(row=r_up, column=AI, value=z["外籍"]).alignment = cell_align
    if z["其他"] > 0:
        ws.cell(row=r_up, column=AJ, value=z["其他"]).alignment = cell_align

    # 大班户籍明细
    d = stu["大班"]
    if d["本区"] > 0:
        ws.cell(row=r_up, column=AL, value=d["本区"]).alignment = cell_align
    if d["外区"] > 0:
        ws.cell(row=r_up, column=AM, value=d["外区"]).alignment = cell_align
    if d["外省"] > 0:
        ws.cell(row=r_up, column=AN, value=d["外省"]).alignment = cell_align
    if d["港"] > 0:
        ws.cell(row=r_up, column=AO, value=d["港"]).alignment = cell_align
    if d["澳"] > 0:
        ws.cell(row=r_up, column=AP, value=d["澳"]).alignment = cell_align
    if d["台"] > 0:
        ws.cell(row=r_up, column=AQ, value=d["台"]).alignment = cell_align
    if d["外籍"] > 0:
        ws.cell(row=r_up, column=AR, value=d["外籍"]).alignment = cell_align
    if d["其他"] > 0:
        ws.cell(row=r_up, column=AS, value=d["其他"]).alignment = cell_align

    # 非户籍五类明细,移除所有填0代码,仅数值>0写入
    # type1
    if nl["type1"]["大班"] > 0:
        ws.cell(row=r_det, column=D, value=nl["type1"]["大班"]).alignment = cell_align
    if nl["type1"]["中班"] > 0:
        ws.cell(row=r_det, column=E, value=nl["type1"]["中班"]).alignment = cell_align
    if nl["type1"]["小班"] > 0:
        ws.cell(row=r_det, column=F, value=nl["type1"]["小班"]).alignment = cell_align
    # type2
    if nl["type2"]["大班"] > 0:
        ws.cell(row=r_det, column=J, value=nl["type2"]["大班"]).alignment = cell_align
    if nl["type2"]["中班"] > 0:
        ws.cell(row=r_det, column=K, value=nl["type2"]["中班"]).alignment = cell_align
    if nl["type2"]["小班"] > 0:
        ws.cell(row=r_det, column=L, value=nl["type2"]["小班"]).alignment = cell_align
    # type3
    if nl["type3"]["大班"] > 0:
        ws.cell(row=r_det, column=P, value=nl["type3"]["大班"]).alignment = cell_align
    if nl["type3"]["中班"] > 0:
        ws.cell(row=r_det, column=Q, value=nl["type3"]["中班"]).alignment = cell_align
    if nl["type3"]["小班"] > 0:
        ws.cell(row=r_det, column=R, value=nl["type3"]["小班"]).alignment = cell_align
    # type4
    if nl["type4"]["大班"] > 0:
        ws.cell(row=r_det, column=V, value=nl["type4"]["大班"]).alignment = cell_align
    if nl["type4"]["中班"] > 0:
        ws.cell(row=r_det, column=W, value=nl["type4"]["中班"]).alignment = cell_align
    if nl["type4"]["小班"] > 0:
        ws.cell(row=r_det, column=X, value=nl["type4"]["小班"]).alignment = cell_align
    # type5
    if nl["type5"]["大班"] > 0:
        ws.cell(row=r_det, column=AB, value=nl["type5"]["大班"]).alignment = cell_align
    if nl["type5"]["中班"] > 0:
        ws.cell(row=r_det, column=AC, value=nl["type5"]["中班"]).alignment = cell_align
    if nl["type5"]["小班"] > 0:
        ws.cell(row=r_det, column=AD, value=nl["type5"]["小班"]).alignment = cell_align

    print(f"  ✅ {park} 明细数据写入完成(0值不填充,保留模板公式)")

# ===================== 优抚子女明细写入:0值跳过,不填0、不碰小计列 =====================
print("\n===== 写入军人武警优抚子女明细(0值不填充) =====")
for park_name, write_r in park_write_row.items():
    data = army_warrior_total[park_name]
    # 军人现役
    cols = col_rule["军人现役_符合"]
    if data["军人现役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["军人现役"]["托班"]).alignment = cell_align
    if data["军人现役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["军人现役"]["小班"]).alignment = cell_align
    if data["军人现役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["军人现役"]["中班"]).alignment = cell_align
    if data["军人现役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["军人现役"]["大班"]).alignment = cell_align

    # 军人退役
    cols = col_rule["军人退役_符合"]
    if data["军人退役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["军人退役"]["托班"]).alignment = cell_align
    if data["军人退役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["军人退役"]["小班"]).alignment = cell_align
    if data["军人退役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["军人退役"]["中班"]).alignment = cell_align
    if data["军人退役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["军人退役"]["大班"]).alignment = cell_align

    # 武警现役
    cols = col_rule["武警现役_符合"]
    if data["武警现役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["武警现役"]["托班"]).alignment = cell_align
    if data["武警现役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["武警现役"]["小班"]).alignment = cell_align
    if data["武警现役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["武警现役"]["中班"]).alignment = cell_align
    if data["武警现役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["武警现役"]["大班"]).alignment = cell_align

    # 武警退役
    cols = col_rule["武警退役_符合"]
    if data["武警退役"]["托班"] > 0:
        ws.cell(write_r, cols[1], value=data["武警退役"]["托班"]).alignment = cell_align
    if data["武警退役"]["小班"] > 0:
        ws.cell(write_r, cols[2], value=data["武警退役"]["小班"]).alignment = cell_align
    if data["武警退役"]["中班"] > 0:
        ws.cell(write_r, cols[3], value=data["武警退役"]["中班"]).alignment = cell_align
    if data["武警退役"]["大班"] > 0:
        ws.cell(write_r, cols[4], value=data["武警退役"]["大班"]).alignment = cell_align

print("✅ 优抚明细写入完成,无数据单元格保持空白,所有小计/合计公式完整保留")

# 保存输出
wb.save(out_excel)
wb.close()
wb_data.close()

print(f"\n🎉 全部程序执行完毕!输出文件路径:\n{out_excel}")

换了最终提交表的名字

刚才大班是62人,现在94人,

相关推荐
宿6741 小时前
vue3-指令和事件处理
开发语言·前端·javascript
风骏时光牛马1 小时前
AI助手异常问题Debug排查
前端
梦想的旅途21 小时前
企业微信API实战:Python自动化消息推送
java·前端·python·自动化·企业微信
恋猫de小郭1 小时前
Flutter 3.47 发布,快来看看有什么更新吧
android·前端·flutter
程序员黑豆1 小时前
Java 内存存储机制:基本数据类型 vs 引用数据类型
前端·ai编程·全栈
月光船幽幽1 小时前
昆仑流形多模态融合新架构
人工智能·python
爱敲代码的憨仔2 小时前
BM25全文检索
开发语言·python·全文检索
90后的晨仔2 小时前
uni-app 三方库与插件管理体系全解析:从原生开发者视角彻底讲透
前端
程序员爱钓鱼2 小时前
Rust 生命周期案例详解:从编译错误到真实业务场景
前端·后端·rust