spec: 认定数据固化+工作簿双数据源+GROUPBY动态公式

This commit is contained in:
大师 2026-06-09 03:36:02 +08:00
parent 91d82ac475
commit b0fd2f26e2
7 changed files with 308 additions and 172 deletions

View File

@ -6,9 +6,9 @@
| 文件 | 说明 | 更新频率 |
|:------|:------|:------|
| `certified_schemes_dashboard.html` | 危大方案独立看板双页PPT宽屏 | 每月 |
| `危大方案看板数据工作簿.xlsx` | 清洗数据 + 6数据透视表 | 每月 |
| `dashboard.html` | 三合一综合看板 | 每月 |
| `certified_schemes_dashboard.html` | 危大方案独立看板双页PPT宽屏·1280px | 每月 |
| `危大方案看板数据工作簿.xlsx` | 双数据源+动态公式+静态汇总13Sheet | 每月 |
| `危大方案编审进度看板.pptx` | 可编辑PPTX原生图表/表格/形状) | 每月 |
## 项目结构
@ -17,27 +17,32 @@
├── .gitignore
├── run_all.py ← 一键管线
├── src/
│ ├── b1_methods.py ← 技术方案统计表清洗
│ ├── b1_methods.py ← 技术方案统计表清洗(→ methods_cleaned.csv
│ ├── b2_tracking.py ← 项目启动动态跟踪
│ ├── b3_revenue.py ← 营业额产值统计
│ ├── b4_dashboard_html.py ← 综合看板HTML生成
│ ├── b4b_certified_dashboard_2026.py ← 危大方案独立看板
│ ├── gen_workbook.py ← 数据透视工作簿
│ ├── clean_certified.py ← 年度认定表清洗
│ ├── clean_methods.py ← 方案统计表清洗(旧版)
│ └── run_methods_2026-06-08.py ← 06-08适配器
├── raw/ ← OA原始台账
│ ├── b4b_certified_dashboard_2026.py ← 危大方案独立看板HTML
│ ├── gen_workbook.py ← 工作簿(数据源+GROUPBY公式+静态汇总)
│ ├── gen_pptx.py ← PPTX看板生成
│ ├── clean_certified.py ← 年度认定表清洗(→ 认定数据/YYYY/
│ └── clean_methods.py ← 方案统计表清洗(旧版)
├── raw/ ← OA原始台账(每月放入)
│ └── YYYY-MM-DD/
│ ├── 技术方案统计表.xlsx
│ ├── 动态跟踪表_REPORT3.xlsx
│ └── 2026年XX月项目营业额、产值统计表.xls
└── data/ ← 清洗后输出
└── data/ ← 输出数据
├── 认定数据/ ← 年度固定·一年一次
│ └── 2026/
│ ├── certified_schemes_detail.csv (43行方案级)
│ └── certified_schemes.csv (项目级对比)
└── YYYY-MM-DD/
└── cleaned/
├── methods_cleaned.csv (OA登记清洗后)
├── methods_cleaned.parquet
├── methods_cleaned.csv
├── certified_schemes_dashboard.html
├── 危大方案看板数据工作簿.xlsx
├── 危大方案编审进度看板.pptx
└── *_validation.json
```
@ -51,19 +56,20 @@
│ 总数 超规16 │ 总数 超规22 │
│ 覆盖7项目 │ 登记率121% │
├─ 3.按国别 ──────┼─ 4.审批进度&预警 ──┤
│ 阿联酋45 ▓▓▓▓ │ 5 🔴0 🟠1 🟡4 │
│ 阿联酋45 ▓▓▓▓ │ 5 🟠1 🟡4
│ 沙特 6 ▓ │ 23 未完成审批 │
│ 卡塔尔 1 ▏ │ 56% 审批完成率 │
└─────────────────┴──────────────────┘
```
- **年度认定**依据中港科技便20266号统计口径 ≥2026年开工
- **年度认定**中港科技便20266号统计口径 ≥2026年开工
- **OA登记**OA技术方案统计表排除已作废
- **预警**🟠≤30天未审批 · 🟡≤45天 · 🔴在实施未审批
- **预警**:🟠 ≤30天未审批 · 🟡 ≤45天 · 🔴 在实施未审批本月0项
- **登记率**121% = OA登记52 / 认定43
### 页面2预警明细
5项预警方案清单含项目全称、方案名称、距开工天数。
5项预警方案清单含项目全称、方案名称、当前状态、计划开工日期、距开工天数。
## 使用方式
@ -74,27 +80,41 @@ cp *.xlsx raw/YYYY-MM-DD/
# 2. 运行清洗管线
python3 run_all.py YYYY-MM-DD
# 3. 生成工作簿(含数据透视表
# 3. 生成工作簿(含动态公式 + 静态汇总
python3 src/gen_workbook.py
# 4. 生成PPTX
python3 src/gen_pptx.py
```
## 数据工作簿 (Sheet清单)
## 数据工作簿 Sheet清单13个
| Sheet | 内容 |
|:------|:------|
| 清洗后数据 | 52条有效方案全字段 |
| 年度认定透视 | 按一般/超规 + 项目明细 |
| OA登记透视 | 按分类 + 国别×分类交叉 |
| 国别分布 | 阿联酋·沙特·卡塔尔 |
| 审批进度 | 完成率+OA状态细分 |
| 预警明细 | 6项预警+汇总 |
| Sheet | 类型 | 内容 |
|:------|:-----|:------|
| 清洗后数据 | 数据源 | OA登记·全量有效135行×30列 |
| 有效≥2026 | 数据源 | OA登记·≥2026年开工52行 |
| **认定数据** | 数据源 | **公司认定·43行中港科技便20266号** |
| 认定vsOA | 对比 | 项目级认定vs登记差额7项·差额高亮 |
| 公式-年度认定 | 🔄 GROUPBY | `=GROUPBY(…!K3:K200, …,COUNTA,3,0)` |
| 公式-国别分布 | 🔄 GROUPBY | `=GROUPBY(…!C3:C200, …,COUNTA,3,0,-2)` |
| 公式-审批进度 | 🔄 COUNTIF | 6项指标完成/未完成/橙/黄/合计) |
| 公式-预警明细 | 🔄 FILTER | `=FILTER(…!A3:AD200, …!AD3:AD200<>"none")` |
| 公式-认定分类 | 🔄 GROUPBY | 认定数据分类统计 |
| 年度认定汇总 | 📌 静态 | 一般类/超规类(可交叉验证公式) |
| 国别×分类 | 📌 静态 | 阿联酋/沙特/卡塔尔×分类交叉 |
| 审批进度 | 📌 静态 | 完成率56%·预警明细 |
| 预警明细 | 📌 静态 | 5项预警清单 |
> 🔄 动态公式在WPS新版/Excel 365中打开后自动刷新——源数据更新零Python重跑。
## 数据来源
- 技术方案统计表 → 危大方案编审进度
- 动态跟踪表_REPORT3 → 项目启动阶段跟踪
- 项目营业额、产值统计表 → 营收财务数据
- 年度认定 → 中港科技便20266号
| 数据 | 来源 | 路径 |
|:------|:------|:------|
| OA登记 | 技术方案统计表 | `raw/YYYY-MM-DD/`(每月更新) |
| 年度认定 | 中港科技便20266号 | `data/认定数据/2026/`(年度固定) |
| 项目启动 | 动态跟踪表_REPORT3 | `raw/YYYY-MM-DD/` |
| 营业额 | 项目营业额产值统计表 | `raw/YYYY-MM-DD/` |
## Gitea

View File

@ -103,9 +103,9 @@ tr:nth-child(even) td{background:var(--bg)}
<div class="panel"><div class="panel-head">4. 审批进度 &amp; 三色预警信号</div><div class="panel-body" style="display:flex;flex-direction:column;gap:14px">
<!-- Row 1: 预警信号 -->
<div style="display:flex;align-items:center;gap:16px">
<div class="card"><div class="n" style="color:var(--red);font-size:44px">6</div><div class="l">预警总计</div></div>
<div class="card"><div class="n" style="color:var(--red);font-size:44px">5</div><div class="l">预警总计</div></div>
<div class="card"><div class="ico" style="font-size:22px;line-height:1">🔴</div><div class="n" style="color:var(--red)">0</div><div class="l">红色</div></div>
<div class="card"><div class="ico" style="font-size:22px;line-height:1">🟠</div><div class="n" style="color:var(--red)">2</div><div class="l">橙色</div></div>
<div class="card"><div class="ico" style="font-size:22px;line-height:1">🟠</div><div class="n" style="color:var(--red)">1</div><div class="l">橙色</div></div>
<div class="card"><div class="ico" style="font-size:22px;line-height:1">🟡</div><div class="n" style="color:var(--gold)">4</div><div class="l">黄色</div></div>
<div class="card"><div class="n" style="color:var(--gray);font-size:36px">23</div><div class="l">未完成审批</div></div>
<div style="font-size:11px;color:var(--gray);margin-left:auto;text-align:right;line-height:1.6;display:flex;flex-direction:column;gap:4px"><span>🔴 在实施未审批</span><span>🟠 ≤30天</span><span>🟡 ≤45天</span></div>
@ -133,10 +133,9 @@ tr:nth-child(even) td{background:var(--bg)}
<div class="slide">
<div class="nav"><span>关键指标</span><span>国别分布</span><span class="cur">预警明细</span></div>
<div class="title-area"><div class="line"></div><h1>预警信号明细清单</h1><span class="date">6 项预警</span></div>
<div class="title-area"><div class="line"></div><h1>预警信号明细清单</h1><span class="date">5 项预警</span></div>
<div style="margin:0 48px 20px"><div class="panel" style="flex:1"><div class="panel-body" style="padding:0"><table class="main"><tr><th class="main">信号</th><th class="main">类型</th><th class="main">项目名称</th><th class="main">方案名称</th><th class="main">当前状态</th><th class="main" style="text-align:right">计划开工</th><th class="main num">距开工</th></tr>
<tr class="warn-row"><td class="wicon">🟠</td><td class="fs">超规类</td><td class="fs">阿联酋迪拜马克图姆国际机场地下结构工程项目</td><td class="fs">BHS处理中心/GSE隧道现浇板专项施工方案4包</td><td class="fs">已添加、未实施</td><td class="num">2026-06-10</td><td class="num r">2天</td></tr>
<tr><td class="wicon">🟠</td><td class="fs">一般类</td><td class="fs">阿联酋迪拜马克图姆国际机场地下结构工程项目</td><td class="fs">钢筋加工厂桥式起重机安装专项施工方案2包</td><td class="fs">已审批、未实施</td><td class="num">2026-06-30</td><td class="num r">22天</td></tr>
<tr class="warn-row"><td class="wicon">🟡</td><td class="fs">超规类</td><td class="fs">阿联酋阿布扎比汽车基地房建项目</td><td class="fs">模板支立工程专项方案</td><td class="fs">未审批、未实施</td><td class="num">2026-07-10</td><td class="num r">32天</td></tr>
<tr class="warn-row"><td class="wicon">🟡</td><td class="fs">超规类</td><td class="fs">阿联酋阿布扎比汽车基地房建项目</td><td class="fs">深基坑开挖方案</td><td class="fs">未审批、未实施</td><td class="num">2026-07-15</td><td class="num r">37天</td></tr>
<tr><td class="wicon">🟡</td><td class="fs">超规类</td><td class="fs">阿联酋迪拜马克图姆国际机场地下结构工程项目</td><td class="fs">处理中心现浇倒T梁专项施工方案4包</td><td class="fs">审批中、未实施</td><td class="num">2026-07-20</td><td class="num r">42天</td></tr>

View File

@ -0,0 +1,8 @@
项目名称,认定_危大方案总数,认定_超规数,所属国别,平台_匹配项目,平台_方案总数,平台_超规数,差额,匹配状态
沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,5,2,沙特,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,3,1,-2,
沙特吉赞基础下游工业城3区1巷独栋别墅一期项目,1,0,沙特,沙特吉赞基础下游工业城3区1巷独栋别墅一期项目,3,2,2,
沙特达曼港第一和第二集装箱码头升级改造工程项目,1,1,沙特,沙特达曼港第一和第二集装箱码头升级改造工程,3,2,2,
阿联酋沙迦卡尔巴摩托艇码头项目,2,0,阿联酋,阿联酋沙迦卡尔巴摩托艇港开发项目,3,1,1,
阿联酋迪拜马克图姆国际机场地下结构工程项目,31,12,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,35,13,4,
阿联酋阿布扎比哈里发港EGA泊位翻新项目,1,0,阿联酋,阿联酋阿布扎比哈里发港EGA泊位翻新工程项目,1,0,0,
阿联酋阿布扎比马斯努阿岛水工项目,2,1,阿联酋,阿联酋阿布扎比马斯努阿岛水工项目,0,0,-2,
1 项目名称 认定_危大方案总数 认定_超规数 所属国别 平台_匹配项目 平台_方案总数 平台_超规数 差额 匹配状态
2 沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目 5 2 沙特 沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目 3 1 -2
3 沙特吉赞基础下游工业城3区1巷独栋别墅一期项目 1 0 沙特 沙特吉赞基础下游工业城3区1巷独栋别墅一期项目 3 2 2
4 沙特达曼港第一和第二集装箱码头升级改造工程项目 1 1 沙特 沙特达曼港第一和第二集装箱码头升级改造工程 3 2 2
5 阿联酋沙迦卡尔巴摩托艇码头项目 2 0 阿联酋 阿联酋沙迦卡尔巴摩托艇港开发项目 3 1 1
6 阿联酋迪拜马克图姆国际机场地下结构工程项目 31 12 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 35 13 4
7 阿联酋阿布扎比哈里发港EGA泊位翻新项目 1 0 阿联酋 阿联酋阿布扎比哈里发港EGA泊位翻新工程项目 1 0 0
8 阿联酋阿布扎比马斯努阿岛水工项目 2 1 阿联酋 阿联酋阿布扎比马斯努阿岛水工项目 0 0 -2

View File

@ -0,0 +1,44 @@
所属区域,所属国别,项目名称,方案名称,编制单位,工程类别,分部工程类别,是否超一定规模,计划开工日期
中东,沙特,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,预制看台安装方案,中交第二公路工程局有限公司,房屋建设和市政基础设施工程,起重吊装及起重机械安装拆卸工程,,2026-07-01
中东,沙特,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,钢结构施工方案,中建钢构承包有限公司,房屋建设和市政基础设施工程,起重吊装及起重机械安装拆卸工程,,2026-05-23
中东,沙特,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,幕墙施工方案,中建装饰绿创科技有限公司,房屋建设和市政基础设施工程,其它,,2026-08-22
中东,沙特,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,高支模专项施工方案,中交第二公路工程局有限公司,房屋建设和市政基础设施工程,模板工程及支撑体系,,2026-03-20
中东,沙特,沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目,650t履带吊安拆施工方案,中建钢构承包有限公司,房屋建设和市政基础设施工程,起重吊装及起重机械安装拆卸工程,,2026-07-25
中东,沙特,沙特吉赞基础下游工业城3区1巷独栋别墅一期项目,别墅主体结构安装专项施工方案,中交四航局二公司,房屋建设和市政基础设施工程,起重吊装及起重机械安装拆卸工程,,2026-04-01
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,处理中心专项施工方案(4包,中交四航局二公司(4包,民航工程,模板工程及支撑体系,,2026-03-10
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,GSE&BHS隧道施工专项施工方案(4包,中交四航局二公司(4包,民航工程,模板工程及支撑体系,,2026-03-28
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,T梁预制、运输和安装专项施工方案(4包,中交四航局二公司(4包,民航工程,起重吊装及安装拆卸工程,,2026-05-13
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,临时用电施工组织设计(4包,中交四航局二公司(4包,电力工程,其他,,2026-02-28
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,BHS处理中心/GSE隧道现浇板专项施工方案(4包,中交四航局二公司(4包,民航工程,模板工程及支撑体系,,2026-05-15
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,处理中心现浇倒T梁专项施工方案(4包,中交四航局二公司(4包,民航工程,模板工程及支撑体系,,2026-04-15
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,塔吊施工监管方案(4包,中交四航局二公司(4包,民航工程,起重吊装及安装拆卸工程,,2026-03-25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,龙门吊施工监管方案(4包,中交四航局二公司(4包,民航工程,起重吊装及安装拆卸工程,,2026-03-20
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,混凝土拌和站施工监管方案(4包,中交四航局二公司(4包,民航工程,起重吊装及安装拆卸工程,,2026-03-18
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,履带吊安装和拆卸专项施工方案(4包,中交四航局二公司(4包,民航工程,起重吊装及安装拆卸工程,,2026-03-25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,APM隧道现浇段顶板模板及支撑体系专项施工方案(2包,中交一航局三公司2包,民航工程,模板工程和支撑体系,,2026-11-20
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,GSE隧道现浇段顶板模板及支撑体系专项施工方案(2包,中交一航局三公司2包,民航工程,模板工程和支撑体系,,2026-04-20
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,APM隧道预制梁安装专项施工方案(2包,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2026-11-15
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,GSE隧道预制梁安装专项施工方案(2包,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2026-04-30
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,混凝土拌合站钢结构料仓大棚安装专项施工方案(2包,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2026-03-25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,钢筋加工厂钢结构大棚专项施工方案(2包,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2026-03-25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,预制场龙门吊安装专项施工方案,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2026.3.25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,预制场龙门吊拆卸专项施工方案,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2027-06-25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,履带吊安装专项施工方案,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2026-04-20
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,履带吊拆除专项施工方案,中交一航局三公司2包,民航工程,起重吊装及安装拆卸工程,,2027-06-25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,临时用电施工组织设计(2包,中交一航局三公司2包,电力工程,电力通用_其他,,2026-03-10
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,隧道顶板专项施工方案3包,中交二航局一公司(3包,民航工程,模板工程及支撑体系,,2026-04-25
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,预制构件安装专项施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2026-04-30
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,搅拌站建设专项施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2026-03-10
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,场站建设施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2026-03-10
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,塔吊安装专项施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2026-03-10
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,塔吊拆除专项施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2027-06-15
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,门机安装专项施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2026-03-10
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,门机拆除专项施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2027-06-15
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,履带吊安拆专项施工方案3包,中交二航局一公司(3包,民航工程,起重吊装及安装拆卸工程,,2026-03-10
中东,阿联酋,阿联酋迪拜马克图姆国际机场地下结构工程项目,临时用电专项施工方案3包,中交二航局一公司(3包,电力工程,电力通用_其他,,2026-03-10
中东,沙特,沙特达曼港第一和第二集装箱码头升级改造工程项目,厂棚D钢结构安装专项施工方案,中交二航局一公司,房屋建设和市政基础设施工程,其它,,2026-03-05
中东,阿联酋,阿联酋阿布扎比马斯努阿岛水工项目,钢管桩打设专项施工方案,中交一航局三公司,水运工程,桥涵工程,,2026-09-10
中东,阿联酋,阿联酋阿布扎比马斯努阿岛水工项目,方块吊装专项施工方案,中交一航局三公司,水运工程,起重吊装工程,,2026-06-01
中东,阿联酋,阿联酋沙迦卡尔巴摩托艇码头项目,卡尔巴钢板桩围堰专项施工方案,中交一航局三公司,水运工程,大型临时工程,,2026-05-01
中东,阿联酋,阿联酋沙迦卡尔巴摩托艇码头项目,卡尔巴方块安装起重吊装专项施工方案,中交一航局三公司,水运工程,起重吊装工程,,2026-08-15
中东,阿联酋,阿联酋阿布扎比哈里发港EGA泊位翻新项目,临时用电施工组织设计,中交一航局三公司2包,水运工程,临时用电工程,,2026-02-20
1 所属区域 所属国别 项目名称 方案名称 编制单位 工程类别 分部工程类别 是否超一定规模 计划开工日期
2 中东 沙特 沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目 预制看台安装方案 中交第二公路工程局有限公司 房屋建设和市政基础设施工程 起重吊装及起重机械安装拆卸工程 2026-07-01
3 中东 沙特 沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目 钢结构施工方案 中建钢构承包有限公司 房屋建设和市政基础设施工程 起重吊装及起重机械安装拆卸工程 2026-05-23
4 中东 沙特 沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目 幕墙施工方案 中建装饰绿创科技有限公司 房屋建设和市政基础设施工程 其它 2026-08-22
5 中东 沙特 沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目 高支模专项施工方案 中交第二公路工程局有限公司 房屋建设和市政基础设施工程 模板工程及支撑体系 2026-03-20
6 中东 沙特 沙特利雅得德拉伊耶门二期多功能场馆及办公楼房建项目 650t履带吊安拆施工方案 中建钢构承包有限公司 房屋建设和市政基础设施工程 起重吊装及起重机械安装拆卸工程 2026-07-25
7 中东 沙特 沙特吉赞基础下游工业城3区1巷独栋别墅一期项目 别墅主体结构安装专项施工方案 中交四航局二公司 房屋建设和市政基础设施工程 起重吊装及起重机械安装拆卸工程 2026-04-01
8 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 处理中心专项施工方案(4包) 中交四航局二公司(4包) 民航工程 模板工程及支撑体系 2026-03-10
9 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 GSE&BHS隧道施工专项施工方案(4包) 中交四航局二公司(4包) 民航工程 模板工程及支撑体系 2026-03-28
10 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 T梁预制、运输和安装专项施工方案(4包) 中交四航局二公司(4包) 民航工程 起重吊装及安装拆卸工程 2026-05-13
11 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 临时用电施工组织设计(4包) 中交四航局二公司(4包) 电力工程 其他 2026-02-28
12 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 BHS处理中心/GSE隧道现浇板专项施工方案(4包) 中交四航局二公司(4包) 民航工程 模板工程及支撑体系 2026-05-15
13 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 处理中心现浇倒T梁专项施工方案(4包) 中交四航局二公司(4包) 民航工程 模板工程及支撑体系 2026-04-15
14 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 塔吊施工监管方案(4包) 中交四航局二公司(4包) 民航工程 起重吊装及安装拆卸工程 2026-03-25
15 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 龙门吊施工监管方案(4包) 中交四航局二公司(4包) 民航工程 起重吊装及安装拆卸工程 2026-03-20
16 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 混凝土拌和站施工监管方案(4包) 中交四航局二公司(4包) 民航工程 起重吊装及安装拆卸工程 2026-03-18
17 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 履带吊安装和拆卸专项施工方案(4包) 中交四航局二公司(4包) 民航工程 起重吊装及安装拆卸工程 2026-03-25
18 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 APM隧道现浇段顶板模板及支撑体系专项施工方案(2包) 中交一航局三公司(2包) 民航工程 模板工程和支撑体系 2026-11-20
19 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 GSE隧道现浇段顶板模板及支撑体系专项施工方案(2包) 中交一航局三公司(2包) 民航工程 模板工程和支撑体系 2026-04-20
20 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 APM隧道预制梁安装专项施工方案(2包) 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2026-11-15
21 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 GSE隧道预制梁安装专项施工方案(2包) 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2026-04-30
22 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 混凝土拌合站钢结构料仓大棚安装专项施工方案(2包) 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2026-03-25
23 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 钢筋加工厂钢结构大棚专项施工方案(2包) 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2026-03-25
24 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 预制场龙门吊安装专项施工方案 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2026.3.25
25 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 预制场龙门吊拆卸专项施工方案 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2027-06-25
26 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 履带吊安装专项施工方案 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2026-04-20
27 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 履带吊拆除专项施工方案 中交一航局三公司(2包) 民航工程 起重吊装及安装拆卸工程 2027-06-25
28 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 临时用电施工组织设计(2包) 中交一航局三公司(2包) 电力工程 电力通用_其他 2026-03-10
29 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 隧道顶板专项施工方案(3包) 中交二航局一公司(3包) 民航工程 模板工程及支撑体系 2026-04-25
30 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 预制构件安装专项施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2026-04-30
31 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 搅拌站建设专项施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2026-03-10
32 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 场站建设施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2026-03-10
33 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 塔吊安装专项施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2026-03-10
34 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 塔吊拆除专项施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2027-06-15
35 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 门机安装专项施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2026-03-10
36 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 门机拆除专项施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2027-06-15
37 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 履带吊安拆专项施工方案(3包) 中交二航局一公司(3包) 民航工程 起重吊装及安装拆卸工程 2026-03-10
38 中东 阿联酋 阿联酋迪拜马克图姆国际机场地下结构工程项目 临时用电专项施工方案(3包) 中交二航局一公司(3包) 电力工程 电力通用_其他 2026-03-10
39 中东 沙特 沙特达曼港第一和第二集装箱码头升级改造工程项目 厂棚D钢结构安装专项施工方案 中交二航局一公司 房屋建设和市政基础设施工程 其它 2026-03-05
40 中东 阿联酋 阿联酋阿布扎比马斯努阿岛水工项目 钢管桩打设专项施工方案 中交一航局三公司 水运工程 桥涵工程 2026-09-10
41 中东 阿联酋 阿联酋阿布扎比马斯努阿岛水工项目 方块吊装专项施工方案 中交一航局三公司 水运工程 起重吊装工程 2026-06-01
42 中东 阿联酋 阿联酋沙迦卡尔巴摩托艇码头项目 卡尔巴钢板桩围堰专项施工方案 中交一航局三公司 水运工程 大型临时工程 2026-05-01
43 中东 阿联酋 阿联酋沙迦卡尔巴摩托艇码头项目 卡尔巴方块安装起重吊装专项施工方案 中交一航局三公司 水运工程 起重吊装工程 2026-08-15
44 中东 阿联酋 阿联酋阿布扎比哈里发港EGA泊位翻新项目 临时用电施工组织设计 中交一航局三公司(2包) 水运工程 临时用电工程 2026-02-20

View File

@ -16,7 +16,7 @@ import difflib
# ============================================================
RAW_DIR = Path("/mnt/y/WorkingEmail/OA收文_Incoming")
CERT_SRC_DIR = RAW_DIR / "2026-03-16_关于公布公司2026年度技术方案编制计划的通知"
OUT_DIR = CERT_SRC_DIR / "cleaned"
OUT_DIR = Path("/mnt/y/Openclaw_Hub/03.资源/实施项目 wiki/dashboard/data/认定数据/2026") # 年度固定输出
OUT_DIR.mkdir(parents=True, exist_ok=True)
CERT_FILES = [

View File

@ -1,161 +1,226 @@
#!/usr/bin/env python3
"""危大方案看板数据工作簿 v3 — 数据源完整镜像源表结构 + 汇总表"""
"""危大方案看板数据工作簿 v5 — 双数据源(OA登记+公司认定) + GROUPBY/FILTER动态公式"""
import pandas as pd
from openpyxl import Workbook
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
from openpyxl.utils import get_column_letter
BASE = "/mnt/y/Openclaw_Hub/03.资源/实施项目 wiki/dashboard/data/2026-06-08"
CERT_DIR = "/mnt/y/Openclaw_Hub/03.资源/实施项目 wiki/dashboard/data/认定数据/2026" # 年度固定目录·一年一次
OUT = f"{BASE}/cleaned/危大方案看板数据工作簿.xlsx"
REPORT_DATE = "2026-06-08"
REF = "'有效≥2026'" # OA公式引用
CREF = "'认定数据'" # 认定公式引用
# ── Read raw source ──
raw = pd.read_excel("/mnt/y/Openclaw_Hub/03.资源/实施项目 wiki/dashboard/raw/2026-06-08/技术方案统计表.xlsx", header=1)
raw.columns = [str(c).strip() for c in raw.columns]
print(f"Source rows: {len(raw)}, cols: {list(raw.columns)[:5]}...")
# ════ 数据源1: OA登记methods_cleaned.csv ════
df = pd.read_csv(f"{BASE}/cleaned/methods_cleaned.csv")
SRC_COLS = list(df.columns[:24])
valid_all = df[df['是否有效登记'] == True].copy()
valid_2026 = valid_all[valid_all['开工年份'] >= 2026].copy()
m = valid_2026
tot = len(m); gen = (m['是否超一定规模']!='').sum(); sup = tot-gen
completed = m['是否完成审批'].sum(); unfinished = tot-completed
projects = m['项目名称'].nunique(); countries = m['所属国别'].value_counts().to_dict()
warn_df = m[m['预警信号']!='none'].sort_values('分部分项工程计划开工日期')
warn_total = len(warn_df); orange = (warn_df['预警信号']=='orange').sum(); yellow = warn_total-orange
print(f"OA登记: {tot}项(一般{gen}/超规{sup}) 完成{completed} 预警{orange}{yellow}")
# ── Read cleaned data for filtering ──
cl = pd.read_parquet(f"{BASE}/cleaned/methods_cleaned.parquet")
valid_idx = cl[cl['是否有效登记'] == True].index.tolist()
cl['开工年份'] = pd.to_datetime(cl['分部分项工程计划开工日期'], errors='coerce').dt.year
yr_idx = cl[(cl['是否有效登记'] == True) & (cl['开工年份'] >= 2026)].index.tolist()
# ════ 数据源2: 公司认定certified_schemes_detail.csv ════
cert_raw = pd.read_csv(f"{CERT_DIR}/certified_schemes_detail.csv")
cert_raw['计划开工日期_p'] = pd.to_datetime(cert_raw['计划开工日期'].astype(str).str.replace('.','-'), errors='coerce')
cert_valid = cert_raw[cert_raw['计划开工日期_p'].dt.year >= 2026].copy()
cert_tot = len(cert_valid)
cert_sup = (cert_valid['是否超一定规模']=='').sum(); cert_gen = cert_tot-cert_sup
cert_comp = pd.read_csv(f"{CERT_DIR}/certified_schemes.csv")
print(f"公司认定: {cert_tot}项(一般{cert_gen}/超规{cert_sup}) 项目{cert_comp['项目名称'].nunique()}")
# Merge back to raw columns (align by index)
raw_clean = raw.loc[raw.index.isin(valid_idx)].copy()
raw_2026 = raw.loc[raw.index.isin(yr_idx)].copy()
# ════ 样式 ════
HDR_F=Font(name='微软雅黑',bold=True,size=10,color='FFFFFF'); HDR_BG=PatternFill('solid',fgColor='1A3A5C')
TITLE_F=Font(name='微软雅黑',bold=True,size=14,color='1A3A5C'); DATA_F=Font(name='微软雅黑',size=10)
BOLD_F=Font(name='微软雅黑',bold=True,size=10); GRAY_F=Font(name='微软雅黑',size=9,color='8899AA')
GREEN_F=Font(name='微软雅黑',bold=True,size=10,color='2E7D32'); RED_F=Font(name='微软雅黑',bold=True,size=10,color='D94E34')
BLUE_F=Font(name='微软雅黑',bold=True,size=10,color='1A3A5C'); ORANGE_F=Font(name='微软雅黑',bold=True,size=10,color='E65100')
FORMULA_F=Font(name='Consolas',size=10,color='1A3A5C')
WARN_BG=PatternFill('solid',fgColor='FFF3E0'); INFO_BG=PatternFill('solid',fgColor='F0F4FA')
BORDER=Border(left=Side('thin','DBE2EA'),right=Side('thin','DBE2EA'),top=Side('thin','DBE2EA'),bottom=Side('thin','DBE2EA'))
CENTER=Alignment(horizontal='center',vertical='center',wrap_text=True)
GOLD_BD=Border(bottom=Side(style='medium',color='C8962E'))
print(f"Valid rows: {len(raw_clean)}, >=2026: {len(raw_2026)}")
def hdr_row(ws,r,cols):
for i,h in enumerate(cols):
c=ws.cell(r,i+1,h); c.font=HDR_F; c.fill=HDR_BG; c.border=BORDER; c.alignment=CENTER
# ── For summary sheets, use cleaned data ──
m = cl[(cl['是否有效登记'] == True) & (cl['开工年份'] >= 2026)].copy()
m['简化状态'] = m['方案状态_clean'].apply(lambda s: '已完成' if '已完成' in str(s) else '未完成')
m['是否超规'] = m['是否超一定规模'].astype(str).apply(lambda x: '超规类' if x == '' else '一般类')
today = pd.Timestamp('2026-06-08')
m['距开工天'] = (pd.to_datetime(m['分部分项工程计划开工日期']) - today).dt.days.astype(int)
def write_data_sheet(ws,df_out,title,cols):
ncol=len(cols)
ws.merge_cells(start_row=1,start_column=1,end_row=1,end_column=ncol)
ws.cell(1,1,title).font=TITLE_F; ws.cell(1,1).border=GOLD_BD
hdr_row(ws,3,cols)
for ri,(_,row) in enumerate(df_out.iterrows()):
rr=ri+4
for ci,col in enumerate(cols):
v=row.get(col,'')
if pd.isna(v): v=''
elif isinstance(v,(pd.Timestamp,)): v=str(v)[:10]
elif isinstance(v,(float,)) and v==int(v): v=int(v)
ws.cell(rr,ci+1,v).font=DATA_F; ws.cell(rr,ci+1,v).border=BORDER
ws.auto_filter.ref=f'A3:{get_column_letter(ncol)}{len(df_out)+3}'
ws.freeze_panes='A4'
for i,col in enumerate(cols):
ws.column_dimensions[get_column_letter(i+1)].width=max(10,min(40,len(str(col))*2.2))
# Warning
def warn_lev(d, s):
s = str(s); d = int(d)
if '未实施' not in s and '审批中' not in s: return ''
if d <= 30: return '🟠'
if d <= 45: return '🟡'
return ''
m['预警'] = m.apply(lambda r: warn_lev(r['距开工天'], r['方案状态_clean']), axis=1)
# ── Styles ──
HDR_F = Font(name='微软雅黑', bold=True, size=10, color='FFFFFF')
HDR_BG = PatternFill('solid', fgColor='1A3A5C')
TITLE_F = Font(name='微软雅黑', bold=True, size=14, color='1A3A5C')
SUB_F = Font(name='微软雅黑', bold=True, size=12, color='1A3A5C')
GRAY_F = Font(name='微软雅黑', size=9, color='8899AA')
DATA_F = Font(name='微软雅黑', size=10)
BOLD_F = Font(name='微软雅黑', bold=True, size=10)
RED_F = Font(name='微软雅黑', bold=True, size=10, color='D94E34')
GREEN_F = Font(name='微软雅黑', bold=True, size=10, color='2E7D32')
BLUE_F = Font(name='微软雅黑', bold=True, size=10, color='1A3A5C')
WARN_BG = PatternFill('solid', fgColor='FFF3E0')
BORDER = Border(left=Side('thin', 'DBE2EA'), right=Side('thin', 'DBE2EA'),
top=Side('thin', 'DBE2EA'), bottom=Side('thin', 'DBE2EA'))
CENTER = Alignment(horizontal='center', vertical='center')
GOLD_BD = Border(bottom=Side(style='medium', color='C8962E'))
def hdr_row(ws, r, cols):
for i, h in enumerate(cols):
c = ws.cell(r, i+1, h); c.font = HDR_F; c.fill = HDR_BG; c.border = BORDER; c.alignment = CENTER
def write_data_sheet(ws, df, title):
"""Write a full data sheet from dataframe"""
ws.merge_cells(start_row=1, start_column=1, end_row=1, end_column=len(df.columns))
ws.cell(1, 1, title).font = TITLE_F
ws.cell(1, 1).border = GOLD_BD
cols = list(df.columns)
hdr_row(ws, 3, cols)
for r, (_, row) in enumerate(df.iterrows()):
for c, col in enumerate(cols):
v = row[col]
if pd.isna(v): v = ''
elif isinstance(v, (pd.Timestamp,)): v = str(v)[:10]
cell = ws.cell(r+4, c+1, v); cell.font = DATA_F; cell.border = BORDER
ws.auto_filter.ref = f'A3:{get_column_letter(len(cols))}{len(df)+3}'
ws.freeze_panes = 'A4'
for i in range(len(cols)):
ws.column_dimensions[get_column_letter(i+1)].width = max(12, min(35, len(str(cols[i]))*2))
def write_formula_sheet(ws,title,subtitle,formulas,col_widths):
ws.merge_cells(start_row=1,start_column=1,end_row=1,end_column=4)
ws.cell(1,1,title).font=TITLE_F; ws.cell(1,1).border=GOLD_BD
if subtitle:
ws.merge_cells(start_row=2,start_column=1,end_row=2,end_column=4)
ws.cell(2,1,subtitle).font=Font(name='微软雅黑',size=9,color='8899AA')
for col_letter,row_num,formula,label in formulas:
cell=ws.cell(row_num,ord(col_letter)-64,formula); cell.font=FORMULA_F; cell.border=BORDER
if label:
ws.cell(row_num,ord(col_letter)-63,label).font=GRAY_F
for col_letter,w in col_widths:
ws.column_dimensions[col_letter].width=w
ws.merge_cells(start_row=12,start_column=1,end_row=12,end_column=4)
ws.cell(12,1,'💡 源数据更新后公式自动刷新WPS新版/Excel 365').font=GRAY_F; ws.cell(12,1).fill=INFO_BG
wb = Workbook()
# ════ Sheet 1: 源表清洗后(完整列) ════
s1 = wb.active; s1.title = '源表清洗后'
write_data_sheet(s1, raw_clean, '技术方案统计表 · 清洗后(有效登记 全部年份)')
# ════════ S1: OA清洗后数据 ════════
s1=wb.active; s1.title='清洗后数据'
write_data_sheet(s1,valid_all.reset_index(drop=True),
f'OA登记·清洗后数据有效登记·全部年份·{len(valid_all)}行)',
SRC_COLS+['方案状态_clean','是否完成审批','是否有效登记','开工年份','开工月份','预警信号'])
# ════ Sheet 2: 有效2026+ ════
s2 = wb.create_sheet('有效≥2026')
write_data_sheet(s2, raw_2026, '技术方案统计表 · 有效登记 ≥2026年开工')
# ════════ S2: OA有效≥2026 ════════
s2=wb.create_sheet('有效≥2026')
write_data_sheet(s2,valid_2026.reset_index(drop=True),
f'OA登记·有效≥2026年开工{len(valid_2026)}行)',
SRC_COLS+['方案状态_clean','是否完成审批','是否有效登记','开工年份','开工月份','预警信号'])
# ════ Sheet 3: 年度认定汇总 ════
s3 = wb.create_sheet('年度认定汇总')
s3.merge_cells('A1:D1'); s3.cell(1, 1, '年度认定≥2026开工').font = TITLE_F; s3.cell(1, 1).border = GOLD_BD
hdr_row(s3, 3, ['分类', '方案数', '项目数', '占比'])
tot = len(m)
for r, (cat, sub) in enumerate([('一般类', m[m['是否超规'] == '一般类']), ('超规类', m[m['是否超规'] == '超规类'])]):
cnt = len(sub); proj = sub['项目名称'].nunique()
for c, (v, f) in enumerate(zip([cat, cnt, proj, f'{cnt/tot*100:.0f}%'], [DATA_F, DATA_F, DATA_F, DATA_F])):
cell = s3.cell(r+4, c+1, v); cell.font = f; cell.border = BORDER
for c, (v, f) in enumerate(zip(['合计', tot, m['项目名称'].nunique(), '100%'], [BOLD_F]*4)):
cell = s3.cell(6, c+1, v); cell.font = f; cell.border = BORDER
for w, c in zip([12, 10, 10, 10], 'ABCD'): s3.column_dimensions[c].width = w
# ════════ S3: 认定数据 ════════
s3=wb.create_sheet('认定数据')
CERT_COLS=['所属区域','所属国别','项目名称','方案名称','编制单位','工程类别','分部工程类别','是否超一定规模','计划开工日期']
write_data_sheet(s3,cert_valid.reset_index(drop=True),
f'2026年度公司认定危大方案明细中港科技便20266号·{cert_tot}项)',CERT_COLS)
# ════ Sheet 4: 国别×分类 ════
s4 = wb.create_sheet('国别×分类')
s4.merge_cells('A1:D1'); s4.cell(1, 1, '国别×分类分布').font = TITLE_F; s4.cell(1, 1).border = GOLD_BD
ct = m.groupby(['所属国别', '是否超规']).size().unstack(fill_value=0)
ct['合计'] = ct.sum(1); ct.loc['合计'] = ct.sum()
hdr_row(s4, 3, ['国别'] + list(ct.columns))
for r, (idx, row) in enumerate(ct.iterrows()):
for c, v in enumerate([idx] + [int(x) for x in row]):
cell = s4.cell(r+4, c+1, v); cell.font = DATA_F; cell.border = BORDER
s4.column_dimensions['A'].width = 25
# ════════ S4: 认定vsOA ════════
s4=wb.create_sheet('认定vsOA')
COMP_COLS=['项目名称','认定_危大方案总数','认定_超规数','所属国别','平台_方案总数','平台_超规数','差额','匹配状态']
ncol_c=len(COMP_COLS)
s4.merge_cells(start_row=1,start_column=1,end_row=1,end_column=ncol_c)
s4.cell(1,1,f'认定 vs OA登记 项目级对比({REPORT_DATE}').font=TITLE_F; s4.cell(1,1).border=GOLD_BD
hdr_row(s4,3,COMP_COLS)
for ri,(_,row) in enumerate(cert_comp.iterrows()):
for ci,col in enumerate(COMP_COLS):
v=row[col]
if pd.isna(v): v=''
cell=s4.cell(ri+4,ci+1,v); cell.font=DATA_F; cell.border=BORDER
if col=='差额' and isinstance(v,(int,float)) and v!=0:
cell.font=RED_F if v<0 else GREEN_F
if col=='匹配状态': cell.font=GREEN_F if '' in str(v) else DATA_F
s4.auto_filter.ref=f'A3:{get_column_letter(ncol_c)}{len(cert_comp)+3}'
for i,col in enumerate(COMP_COLS):
s4.column_dimensions[get_column_letter(i+1)].width=max(14,min(45,len(str(col))*2.5))
# ════ Sheet 5: 审批进度 & 预警 ════
s5 = wb.create_sheet('审批进度')
s5.merge_cells('A1:D1'); s5.cell(1, 1, '审批进度 & 三色预警').font = TITLE_F; s5.cell(1, 1).border = GOLD_BD
hdr_row(s5, 3, ['指标', '数值', '占比', '备注'])
completed = (m['简化状态'] == '已完成').sum(); unfinished = tot - completed
rn = (m['预警'] != '').sum(); orn = (m['预警'] == '🟠').sum(); ye = (m['预警'] == '🟡').sum()
rows = [
('方案总数', tot, '100%', '≥2026年开工·排除已作废'),
('已完成审批', completed, f'{completed/tot*100:.0f}%', ''),
('未完成审批', unfinished, f'{unfinished/tot*100:.0f}%', '含审批中+未审批'),
('🟠 橙色预警', orn, f'{orn/tot*100:.0f}%', '≤30天未审批'),
('🟡 黄色预警', ye, f'{ye/tot*100:.0f}%', '≤45天未审批'),
('预警合计', rn, f'{rn/tot*100:.0f}%', f'🟠{orn}项+🟡{ye}'),
]
for r, (lab, val, pct, note) in enumerate(rows):
fmts = [DATA_F, DATA_F, DATA_F, GRAY_F]
if '完成' in lab and '' not in lab: fmts = [GREEN_F, BOLD_F, BOLD_F, GRAY_F]
if '预警' in lab: fmts = [RED_F, BOLD_F, BOLD_F, GRAY_F]
if '总数' in lab: fmts = [BLUE_F, BOLD_F, BOLD_F, GRAY_F]
for c, (v, f) in enumerate(zip([lab, val, pct, note], fmts)):
cell = s5.cell(r+4, c+1, v); cell.font = f; cell.border = BORDER
for w, c in zip([18, 10, 10, 35], 'ABCD'): s5.column_dimensions[c].width = w
# ════════ S5-S8: 动态公式 ════════
# ════ Sheet 6: 预警明细 ════
s6 = wb.create_sheet('预警明细')
s6.merge_cells('A1:G1'); s6.cell(1, 1, f'三色预警明细(共{rn}项)').font = TITLE_F; s6.cell(1, 1).border = GOLD_BD
hdr_row(s6, 3, ['信号', '类型', '项目名称', '方案名称', '状态', '计划开工', '距开工'])
warned = m[m['预警'] != ''].sort_values('距开工天')
for r, (_, row) in enumerate(warned.iterrows()):
is_w = '未审批' in str(row['方案状态_clean'])
bg = WARN_BG if is_w else None
vals = [row['预警'], row['是否超规'], row['项目名称'], row['方案名称'],
row['方案状态_clean'], str(row['分部分项工程计划开工日期'])[:10], f"{int(row['距开工天'])}"]
for c, v in enumerate(vals):
cell = s6.cell(r+4, c+1, v); cell.font = RED_F if c == 6 else DATA_F; cell.border = BORDER
if bg: cell.fill = bg
s6.auto_filter.ref = f'A3:G{len(warned)+3}'
for w, c in zip([6, 8, 40, 35, 18, 12, 8], 'ABCDEFG'): s6.column_dimensions[c].width = w
# ── S5: 公式-年度认定 ──
s5=wb.create_sheet('公式-年度认定')
write_formula_sheet(s5,f'OA年度认定≥2026开工',
f'GROUPBY({REF}!K3:K200,{REF}!A3:A200,COUNTA,3,0)',
[('A',4,f'=GROUPBY({REF}!K3:K200,{REF}!A3:A200,COUNTA,3,0)','')],[('A',18),('B',12)])
# ── S6: 公式-国别分布 ──
s6=wb.create_sheet('公式-国别分布')
write_formula_sheet(s6,f'OA国别×分类自动排序',
f'GROUPBY({REF}!C3:C200,{REF}!A3:A200,COUNTA,3,0,-2)',
[('A',4,f'=GROUPBY({REF}!C3:C200,{REF}!A3:A200,COUNTA,3,0,-2)','')],[('A',30),('B',12)])
# ── S7: 公式-审批进度 ──
s7=wb.create_sheet('公式-审批进度')
write_formula_sheet(s7,f'OA审批进度 & 预警',
f'引用 {REF}!Z:Z + AD:AD',
[('A',4,'方案总数',''),('B',4,f'=COUNTA({REF}!A4:A200)',''),
('A',5,'已完成审批',''),('B',5,f'=COUNTIF({REF}!Z4:Z200,TRUE)',''),
('A',6,'未完成审批',''),('B',6,f'=COUNTIF({REF}!Z4:Z200,FALSE)',''),
('A',7,'橙色预警',''),('B',7,f'=COUNTIF({REF}!AD4:AD200,"orange")',''),
('A',8,'黄色预警',''),('B',8,f'=COUNTIF({REF}!AD4:AD200,"yellow")',''),
('A',9,'预警合计',''),('B',9,'=B7+B8','')],[('A',20),('B',14)])
# ── S8: 公式-预警明细 ──
s8=wb.create_sheet('公式-预警明细')
write_formula_sheet(s8,f'OA预警明细FILTER',
f'FILTER({REF}!A3:AD200,{REF}!AD3:AD200<>"none","无预警")',
[('A',4,f'=FILTER({REF}!A3:AD200,{REF}!AD3:AD200<>"none","🎉 无预警项")','')],[('A',22)])
# ── S9: 公式-认定分类 ──
s9=wb.create_sheet('公式-认定分类')
write_formula_sheet(s9,f'公司认定方案分类GROUPBY·{cert_tot}项)',
f'GROUPBY({CREF}!H3:H200,{CREF}!D3:D200,COUNTA,3,0)',
[('A',4,f'=GROUPBY({CREF}!H3:H200,{CREF}!D3:D200,COUNTA,3,0)','')],[('A',20),('B',12)])
# ════════ S10-S13: 静态汇总表(可交叉验证) ════════
# ── S10: 年度认定汇总 ──
s10=wb.create_sheet('年度认定汇总')
s10.merge_cells('A1:E1'); s10.cell(1,1,f'OA年度认定≥2026·静态').font=TITLE_F; s10.cell(1,1).border=GOLD_BD
hdr_row(s10,3,['分类','方案数','项目数','占比','备注'])
for r,(lab,val,proj,pct,note) in enumerate([
('一般类',gen,valid_2026[valid_2026['是否超一定规模']!='']['项目名称'].nunique(),f'{gen/tot*100:.0f}%','非超一定规模'),
('超规类',sup,valid_2026[valid_2026['是否超一定规模']=='']['项目名称'].nunique(),f'{sup/tot*100:.0f}%','超一定规模'),
('合计',tot,projects,'100%',f'涵盖{len(countries)}')]):
fmts=[BOLD_F if '合计' in lab else DATA_F]*5
for c,(v,f) in enumerate(zip([lab,val,proj,pct,note],fmts)):
cell=s10.cell(r+4,c+1,v); cell.font=f; cell.border=BORDER; cell.alignment=CENTER
for w,col in zip([12,10,10,10,20],'ABCDE'): s10.column_dimensions[col].width=w
# ── S11: 国别×分类 ──
s11=wb.create_sheet('国别×分类')
s11.merge_cells('A1:D1'); s11.cell(1,1,'OA国别×分类·静态').font=TITLE_F; s11.cell(1,1).border=GOLD_BD
ct=m.groupby(['所属国别','是否超一定规模']).size().unstack(fill_value=0)
ct.columns=['一般类' if c=='' else '超规类' for c in ct.columns]; ct['合计']=ct.sum(1); ct.loc['合计']=ct.sum()
hdr_row(s11,3,['国别']+list(ct.columns))
for r,(idx,row) in enumerate(ct.iterrows()):
for c,v in enumerate([idx]+[int(x) for x in row]):
cell=s11.cell(r+4,c+1,v); cell.font=BOLD_F if '合计' in str(idx) else DATA_F; cell.border=BORDER; cell.alignment=CENTER
s11.column_dimensions['A'].width=25
# ── S12: 审批进度 ──
s12=wb.create_sheet('审批进度')
s12.merge_cells('A1:D1'); s12.cell(1,1,f'OA审批进度·静态{REPORT_DATE}').font=TITLE_F; s12.cell(1,1).border=GOLD_BD
hdr_row(s12,3,['指标','数值','占比','备注'])
for r,(lab,val,pct,note,fmts) in enumerate([
('方案总数',tot,'100%','≥2026年开工',[BLUE_F]*3+[GRAY_F]),
('已完成审批',int(completed),f'{completed/tot*100:.0f}%','"已完成"',[GREEN_F]*3+[GRAY_F]),
('未完成审批',int(unfinished),f'{unfinished/tot*100:.0f}%','审批中+未审批',[DATA_F]*3+[GRAY_F]),
('🟠 橙色预警',int(orange),f'{orange/tot*100:.0f}%','≤30天',[ORANGE_F]*3+[GRAY_F]),
('🟡 黄色预警',int(yellow),f'{yellow/tot*100:.0f}%','≤45天',[Font(name='微软雅黑',bold=True,size=10,color='F9A825')]*3+[GRAY_F]),
('预警合计',int(warn_total),f'{warn_total/tot*100:.0f}%',f'🟠{orange}+🟡{yellow}',[RED_F]*3+[GRAY_F])]):
for c,(v,f) in enumerate(zip([lab,val,pct,note],fmts)):
cell=s12.cell(r+4,c+1,v); cell.font=f; cell.border=BORDER; cell.alignment=CENTER
for w,col in zip([18,10,10,35],'ABCD'): s12.column_dimensions[col].width=w
# ── S13: 预警明细 ──
s13=wb.create_sheet('预警明细')
s13.merge_cells('A1:H1'); s13.cell(1,1,f'OA预警明细·静态{warn_total}项)').font=TITLE_F; s13.cell(1,1).border=GOLD_BD
hdr_row(s13,3,['信号','距开工','项目名称','方案名称','方案状态','计划开工','超规/一般','国别'])
today=pd.Timestamp(REPORT_DATE)
for r,(_,row) in enumerate(warn_df.iterrows()):
days=(pd.to_datetime(row['分部分项工程计划开工日期'])-today).days
vals=[{'orange':'🟠','yellow':'🟡','red':'🔴'}.get(row['预警信号'],''),f'{int(days)}',
row['项目名称'],row['方案名称'],
row['方案状态_clean'] if pd.notna(row.get('方案状态_clean')) else row['方案状态'],
str(row['分部分项工程计划开工日期'])[:10],
'超规类' if row['是否超一定规模']=='' else '一般类',row['所属国别']]
for c,v in enumerate(vals):
cell=s13.cell(r+4,c+1,v); cell.font=RED_F if c==1 and days<=3 else DATA_F; cell.border=BORDER; cell.fill=WARN_BG
s13.auto_filter.ref=f'A3:H{warn_total+3}'
for w,col in zip([6,8,40,35,18,12,10,20],'ABCDEFGH'): s13.column_dimensions[col].width=w
wb.save(OUT)
print(f"{OUT}")
print(f" Sheet1: 源表清洗后 ({len(raw_clean)}× {len(raw_clean.columns)}列)")
print(f" Sheet2: 有效≥2026 ({len(raw_2026)}行)")
print(f" Sheet3-6: 汇总表 + 预警明细")
print(f"\n{OUT}")
print(f" S1-S2 OA登记: {len(valid_all)}全量 + {len(valid_2026)}≥2026")
print(f" S3 公司认定: {cert_tot}行({cert_gen}一般+{cert_sup}超规)")
print(f" S4 认定vsOA: {len(cert_comp)}项目")
print(f" S5-S9 GROUPBY/FILTER 动态公式")
print(f" S10-S13 静态汇总表(交叉验证)")