Files
zentao-flow/tmp/make_perf_templates.py
T

115 lines
6.0 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""从新版考核方案 xlsx 生成 9 份绩效导出模版(单 sheet + 占位符)。
机制对齐 writeXlsx(IZtCountService.java):遍历单元格做 {key} 子串替换。
- F2 -> {name}(员工姓名后一格),H2 -> {date}(考核周期后一格)
- 每个指标行:H 列(本期结果)-> {键名},G 列(绩效数据)-> {detail_键名} 或拆分占位,无则清空
- 合计行:H 列 -> {total}
"""
from copy import copy
import openpyxl
SRC = r'docs/信息技术部绩效考核标准-新版 - AI下的考核方案.xlsx'
OUT_DIR = r'codes/zentao/src/main/resources/templates/scope'
# (源 sheet 名, 输出文件名, 合计行号, {指标行号: 键名}, {指标行号: G列绩效数据占位})
SHEETS = [
('项目经理', '项目经理考核.xlsx', 12,
{4: 'workloadPrdScore', 5: 'workloadTeamScore', 6: 'versionPlanFinishedRate', 7: 'bugScore',
8: 'documentQualityScore', 9: 'developFeedbackStory', 10: 'systemStabilityScore',
11: 'professionalSkillEnhancementScore'},
{4: '{detail_workloadPrdScore}', 5: '{detail_workloadTeamScore}', 6: '{detail_versionPlanFinishedRate}',
7: '{detail_bugScore}', 8: '{detail_documentQualityScore}'}),
('项目经理(王宇航)', '项目经理考核-王宇航.xlsx', 11,
{4: 'workloadTeamScore', 5: 'versionPlanFinishedRate', 6: 'bugScore', 7: 'documentQualityScore',
8: 'developFeedbackStory', 9: 'systemStabilityScore', 10: 'professionalSkillEnhancementScore'},
{4: '{detail_workloadTeamScore}', 5: '{detail_versionPlanFinishedRate}', 6: '{detail_bugScore}',
7: '{detail_documentQualityScore}'}),
('产品经理', '产品经理考核.xlsx', 10,
{4: 'workloadPrdScore', 5: 'workloadTeamScore', 6: 'productProjectOnTimeRateScore', 7: 'productBugRate',
8: 'productProblemResponse', 9: 'productResponsibilityScore'},
{4: '{detail_workloadPrdScore}', 5: '{detail_workloadTeamScore}', 6: '{detail_productProjectOnTimeRateScore}',
7: '{detail_productBugRate}'}),
('产品助理', '项目助理考核.xlsx', 9,
{4: 'workloadPrdScore', 5: 'releaseScore', 6: 'productBugRate', 7: 'productProblemResponse',
8: 'productResponsibilityScore'},
{4: '{detail_workloadPrdScore}', 6: '{detail_productBugRate}'}),
('后端开发工程师', '后端开发工程师.xlsx', 12,
{4: 'punctualityScore', 5: 'bugScore', 6: 'codeQualityScore', 7: 'documentQualityScore', 8: 'saturationScore',
9: 'workAttitude', 10: 'excellentShare', 11: 'quality'},
{4: '{totalTask}/{delayTask}/{finishPunctuality}', 5: '{bugCount}/{bugDensity}',
8: '{workTime}/{examineTime}/{saturation}'}),
('前端开发工程师', '前端开发工程师.xlsx', 11,
{4: 'punctualityScore', 5: 'bugScore', 6: 'codeQualityScore', 7: 'saturationScore', 8: 'workAttitude',
9: 'excellentShare', 10: 'quality'},
{4: '{totalTask}/{delayTask}/{finishPunctuality}', 5: '{bugCount}/{bugDensity}',
7: '{workTime}/{examineTime}/{saturation}'}),
('测试工程师', '测试工程师.xlsx', 11,
{4: 'punctualityScore', 5: 'documentQualityScore', 6: 'bugFindScore', 7: 'bugScore', 8: 'workAttitude',
9: 'excellentShare', 10: 'quality'},
{4: '{totalTask}/{delayTask}/{finishPunctuality}', 6: '{devSlightBug}/{devSeriousBug}/{bugFindRate}',
7: '{slightBug}/{seriousBug}'}),
('UI工程师', 'UI工程师.xlsx', 9,
{4: 'punctualityScore', 5: 'designScore', 6: 'workAttitude', 7: 'uiWorkScore', 8: 'excellentShare'},
{4: '{totalTask}/{delayTask}/{finishPunctuality}'}),
('运维工程师', '运维工程师.xlsx', 12,
{4: 'opsMajorTaskScore', 5: 'opsMonitorScore', 6: 'opsInspectScore', 7: 'opsBackupScore', 8: 'otherOpsScore',
9: 'systemStabilityScore', 10: 'workAttitude', 11: 'excellentShare'},
{4: '{detail_opsMajorTaskScore}', 5: '{detail_opsMonitorScore}', 6: '{detail_opsInspectScore}',
7: '{detail_opsBackupScore}'}),
]
def copy_sheet(src_ws, dst_ws):
"""整 sheet 拷贝:值 + 基础样式 + 合并单元格 + 列宽行高。"""
for row in src_ws.iter_rows():
for cell in row:
if cell.value is None and not cell.has_style:
continue
nc = dst_ws.cell(row=cell.row, column=cell.column)
nc.value = cell.value
if cell.has_style:
nc.font = copy(cell.font)
nc.fill = copy(cell.fill)
nc.border = copy(cell.border)
nc.alignment = copy(cell.alignment)
nc.protection = copy(cell.protection)
nc.number_format = cell.number_format
for merged in src_ws.merged_cells.ranges:
dst_ws.merge_cells(str(merged))
for key, dim in src_ws.column_dimensions.items():
if dim.width is not None:
dst_ws.column_dimensions[key].width = dim.width
for key, dim in src_ws.row_dimensions.items():
if dim.height is not None:
dst_ws.row_dimensions[key].height = dim.height
def main():
src_wb = openpyxl.load_workbook(SRC)
for sheet_name, out_name, total_row, row_keys, row_details in SHEETS:
src_ws = src_wb[sheet_name]
wb = openpyxl.Workbook()
ws = wb.active
ws.title = sheet_name
copy_sheet(src_ws, ws)
# R2:员工姓名后一格 F2 -> {name},考核周期后一格 H2 -> {date}
ws.cell(row=2, column=6).value = '{name}'
ws.cell(row=2, column=8).value = '{date}'
# 指标行:H 列本期结果 -> {键名};G 列绩效数据 -> 明细占位或清空
for r, key in row_keys.items():
ws.cell(row=r, column=8).value = '{%s}' % key
ws.cell(row=r, column=7).value = row_details.get(r)
# 合计行结果列 -> {total}
assert ws.cell(row=total_row, column=1).value == '合计', (sheet_name, total_row)
ws.cell(row=total_row, column=8).value = '{total}'
out_path = '%s/%s' % (OUT_DIR, out_name)
wb.save(out_path)
print('OK %s <- %s' % (out_name, sheet_name))
print('done')
if __name__ == '__main__':
main()