From 3ce84871b3c47da319b7a427f49a83842209eab8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=A4=A7=E5=B8=88?= Date: Tue, 9 Jun 2026 04:36:53 +0800 Subject: [PATCH] =?UTF-8?q?refactor:=20=E5=85=A8=E9=83=A8=E5=85=AC?= =?UTF-8?q?=E5=BC=8F=E6=94=B9=E7=94=A8COUNTIF/COUNTIFS-=E5=8E=BB=E9=99=A4G?= =?UTF-8?q?ROUPBY/UNIQUE/FILTER=E9=81=BF=E5=85=8D@=E5=85=BC=E5=AE=B9?= =?UTF-8?q?=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../cleaned/~$危大方案看板数据工作簿.xlsx | Bin 165 -> 0 bytes .../cleaned/危大方案看板数据工作簿.xlsx | Bin 69846 -> 69110 bytes src/gen_workbook.py | 83 +++++++++++++----- 3 files changed, 61 insertions(+), 22 deletions(-) delete mode 100644 data/2026-06-08/cleaned/~$危大方案看板数据工作簿.xlsx diff --git a/data/2026-06-08/cleaned/~$危大方案看板数据工作簿.xlsx b/data/2026-06-08/cleaned/~$危大方案看板数据工作簿.xlsx deleted file mode 100644 index 589f80230d4eab87252938d3726e5acaa814eb8f..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 165 fcmZQANzBj5RUj3xGL$eRGUPMlFyt~Q&>R8)rKu2w diff --git a/data/2026-06-08/cleaned/危大方案看板数据工作簿.xlsx b/data/2026-06-08/cleaned/危大方案看板数据工作簿.xlsx index b248c61151494392c7fd6f109bab72a097a3f2b8..9579ebb1e3dd33bf4e0f6b5a4fa919b0e90023fd 100644 GIT binary patch delta 10153 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 diff --git a/src/gen_workbook.py b/src/gen_workbook.py index 5cad369..8182135 100644 --- a/src/gen_workbook.py +++ b/src/gen_workbook.py @@ -154,37 +154,75 @@ TECH_COLS=['所属国别','项目名称','方案名称','编制单位','工程 write_data_sheet(s5,tech_valid.reset_index(drop=True), f'2026年度公司认定技术方案明细(ⅠⅡⅢ类·{tech_tot}项)',TECH_COLS) -# ═══ S6-S10b: 动态公式 ═══ +# ═══ S6-S10b: 公式(全部用COUNTIF/COUNTIFS·不用GROUPBY/UNIQUE/FILTER避免@兼容问题) ═══ + +# ── S6: 公式-年度认定 ── s6=wb.create_sheet('公式-年度认定') -write_formula_sheet(s6,'OA年度认定','GROUPBY on 是否超一定规模', - [('A',4,f'=GROUPBY({REF}!K3:K200,{REF}!A3:A200,COUNTA,3,0)','')],[('A',18),('B',12)]) +s6.merge_cells('A1:B1'); s6.cell(1,1,'OA年度认定(≥2026开工·COUNTIF公式)').font=TITLE_F; s6.cell(1,1).border=GOLD_BD +hdr_row(s6,3,['分类','方案数']) +s6.cell(4,1,'一般类').font=DATA_F; s6.cell(4,1).border=BORDER +s6.cell(4,2,f'=COUNTIF({REF}!$K$4:$K$200,"否")').font=FORMULA_F; s6.cell(4,2).border=BORDER +s6.cell(5,1,'超规类').font=DATA_F; s6.cell(5,1).border=BORDER +s6.cell(5,2,f'=COUNTIF({REF}!$K$4:$K$200,"是")').font=FORMULA_F; s6.cell(5,2).border=BORDER +s6.cell(6,1,'合计').font=BOLD_F; s6.cell(6,1).border=BORDER +s6.cell(6,2,'=B4+B5').font=BOLD_F; s6.cell(6,2).border=BORDER +for w,c in zip([14,10],'AB'): s6.column_dimensions[c].width=w +# ── S7: 公式-国别分布 ── s7=wb.create_sheet('公式-国别分布') -write_formula_sheet(s7,'OA国别×分类','GROUPBY on 所属国别', - [('A',4,f'=GROUPBY({REF}!C3:C200,{REF}!A3:A200,COUNTA,3,0,-2)','')],[('A',30),('B',12)]) +s7.merge_cells('A1:B1'); s7.cell(1,1,'OA国别分布(COUNTIF公式)').font=TITLE_F; s7.cell(1,1).border=GOLD_BD +hdr_row(s7,3,['国别','方案数']) +country_list = sorted(m['所属国别'].unique(), key=lambda x: m[m['所属国别']==x].shape[0], reverse=True) +for ri,cn in enumerate(country_list): + r = ri+4 + s7.cell(r,1,cn).font=DATA_F; s7.cell(r,1).border=BORDER + s7.cell(r,2,f'=COUNTIF({REF}!$C$4:$C$200,"{cn}")').font=FORMULA_F; s7.cell(r,2).border=BORDER +s7.cell(len(country_list)+4,1,'合计').font=BOLD_F; s7.cell(len(country_list)+4,1).border=BORDER +s7.cell(len(country_list)+4,2,f'=SUM(B4:B{len(country_list)+3})').font=BOLD_F; s7.cell(len(country_list)+4,2).border=BORDER +for w,c in zip([30,12],'AB'): s7.column_dimensions[c].width=w +# ── S8: 公式-审批进度(COUNTIF·无GROUPBY) ── s8=wb.create_sheet('公式-审批进度') -write_formula_sheet(s8,'OA审批进度 & 预警','COUNTIF on 是否完成审批', - [('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.merge_cells('A1:C1'); s8.cell(1,1,'OA审批进度 & 预警(COUNTIF公式)').font=TITLE_F; s8.cell(1,1).border=GOLD_BD +hdr_row(s8,3,['指标','数值','备注']) +rows8 = [ + ('方案总数',f'=COUNTA({REF}!A4:A200)','≥2026年开工'), + ('已完成审批',f'=COUNTIF({REF}!Z4:Z200,TRUE)','含"已完成"状态'), + ('未完成审批',f'=COUNTIF({REF}!Z4:Z200,FALSE)','审批中+未审批'), + ('🟠 橙色预警',f'=COUNTIF({REF}!AD4:AD200,"orange")','距开工≤30天'), + ('🟡 黄色预警',f'=COUNTIF({REF}!AD4:AD200,"yellow")','距开工≤45天'), + ('预警合计','=B7+B8','橙色+黄色'), +] +for ri,(lab,fm,note) in enumerate(rows8): + r=ri+4 + s8.cell(r,1,lab).font=DATA_F; s8.cell(r,1).border=BORDER + s8.cell(r,2,fm).font=FORMULA_F; s8.cell(r,2).border=BORDER + s8.cell(r,3,note).font=GRAY_F; s8.cell(r,3).border=BORDER +for w,c in zip([18,10,35],'ABC'): s8.column_dimensions[c].width=w -s9=wb.create_sheet('公式-预警明细') -write_formula_sheet(s9,'OA预警明细','FILTER on 预警信号', - [('A',4,f'=FILTER({REF}!A3:AD200,{REF}!AD3:AD200<>"none","🎉 无预警项")','')],[('A',22)]) +# ── S9: 公式-预警明细 ── 改用Python静态写(FILTER同样有@问题) +# 保留Static sheet "预警明细" 足够用;公式版跳过 +# ── S10: 公式-认定分类 ── s10=wb.create_sheet('公式-认定分类') -write_formula_sheet(s10,'公司认定分类','GROUPBY on 认定数据', - [('A',4,f'=GROUPBY({CREF}!H3:H200,{CREF}!D3:D200,COUNTA,3,0)','')],[('A',20),('B',12)]) +s10.merge_cells('A1:B1'); s10.cell(1,1,'认定危大方案分类(COUNTIF公式)').font=TITLE_F; s10.cell(1,1).border=GOLD_BD +hdr_row(s10,3,['分类','方案数']) +s10.cell(4,1,'一般类').font=DATA_F; s10.cell(4,1).border=BORDER +s10.cell(4,2,f'=COUNTIF({CREF}!$H$4:$H$200,"否")').font=FORMULA_F; s10.cell(4,2).border=BORDER +s10.cell(5,1,'超规类').font=DATA_F; s10.cell(5,1).border=BORDER +s10.cell(5,2,f'=COUNTIF({CREF}!$H$4:$H$200,"是")').font=FORMULA_F; s10.cell(5,2).border=BORDER +s10.cell(6,1,'合计').font=BOLD_F; s10.cell(6,1).border=BORDER +s10.cell(6,2,'=B4+B5').font=BOLD_F; s10.cell(6,2).border=BORDER +for w,c in zip([14,10],'AB'): s10.column_dimensions[c].width=w +# ── S10b: 公式-技术方案分类 ── s10b=wb.create_sheet('公式-技术方案分类') TREF="'认定技术方案'" -write_formula_sheet(s10b,'认定技术方案等级分布', - f'GROUPBY({TREF}!F3:F200,{TREF}!C3:C200,COUNTA,3,0)', - [('A',4,f'=GROUPBY({TREF}!F3:F200,{TREF}!C3:C200,COUNTA,3,0)','')],[('A',20),('B',12)]) +s10b.merge_cells('A1:B1'); s10b.cell(1,1,'认定技术方案等级分布(COUNTIF公式)').font=TITLE_F; s10b.cell(1,1).border=GOLD_BD +hdr_row(s10b,3,['等级','方案数']) +s10b.cell(4,1,'Ⅲ类').font=DATA_F; s10b.cell(4,1).border=BORDER +s10b.cell(4,2,f'=COUNTIF({TREF}!$F$4:$F$200,"Ⅲ")').font=FORMULA_F; s10b.cell(4,2).border=BORDER +for w,c in zip([12,12],'AB'): s10b.column_dimensions[c].width=w # ═══ 静态汇总 ═══ s11=wb.create_sheet('年度认定汇总') @@ -242,6 +280,7 @@ for w,col in zip([6,8,40,35,18,12,10,20],'ABCDEFGH'): s14.column_dimensions[col] wb.save(OUT) print(f"\n✅ {OUT}") print(f" S1-S3 数据源: OA{len(valid_all)}/{len(valid_2026)} + 认定{cert_tot}+技术{tech_tot}") -print(f" S4 公式-认定vsOA: COUNTIFS对比(项目名预填+公式自动计算)") -print(f" S5-S10b 动态公式: GROUPBY/FILTER/COUNTIF") +print(f" S4 公式-认定vsOA: COUNTIFS项目级对比") +print(f" S5 认定技术方案(表2): {tech_tot}行") +print(f" S6-S10b 公式: COUNTIF/COUNTIFS(全部无GROUPBY/UNIQUE/FILTER)") print(f" S11-S14 静态汇总: 交叉验证") \ No newline at end of file