203 lines
7.0 KiB
Python
203 lines
7.0 KiB
Python
|
|
# -*- coding: utf-8 -*-
|
|||
|
|
"""
|
|||
|
|
将需求JSON文件转换为Excel格式
|
|||
|
|
"""
|
|||
|
|
|
|||
|
|
import json
|
|||
|
|
import argparse
|
|||
|
|
from openpyxl import Workbook
|
|||
|
|
from openpyxl.styles import Font, PatternFill, Alignment, Border, Side
|
|||
|
|
from openpyxl.utils import get_column_letter
|
|||
|
|
|
|||
|
|
|
|||
|
|
def parse_requirements_from_json(json_data, parent_section=""):
|
|||
|
|
"""
|
|||
|
|
递归解析JSON,提取所有需求
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
json_data: JSON数据(章节或子章节)
|
|||
|
|
parent_section: 父章节路径
|
|||
|
|
|
|||
|
|
Returns:
|
|||
|
|
需求列表
|
|||
|
|
"""
|
|||
|
|
requirements = []
|
|||
|
|
|
|||
|
|
if isinstance(json_data, dict):
|
|||
|
|
# 提取章节信息
|
|||
|
|
section_info = json_data.get("章节信息", {})
|
|||
|
|
section_number = section_info.get("章节编号", "")
|
|||
|
|
section_title = section_info.get("章节标题", "")
|
|||
|
|
section_level = section_info.get("章节级别", "")
|
|||
|
|
|
|||
|
|
current_section = f"{section_number} {section_title}".strip() if section_number else section_title
|
|||
|
|
|
|||
|
|
# 提取需求列表
|
|||
|
|
req_list = json_data.get("需求列表", [])
|
|||
|
|
for req in req_list:
|
|||
|
|
req_data = {
|
|||
|
|
"章节编号": section_number,
|
|||
|
|
"章节标题": section_title,
|
|||
|
|
"章节级别": section_level,
|
|||
|
|
"章节完整路径": current_section,
|
|||
|
|
"需求类型": req.get("需求类型", ""),
|
|||
|
|
"需求编号": req.get("需求编号", ""),
|
|||
|
|
"需求描述": req.get("需求描述", ""),
|
|||
|
|
"接口名称": req.get("接口名称", ""),
|
|||
|
|
"接口类型": req.get("接口类型", ""),
|
|||
|
|
"来源": req.get("来源", ""),
|
|||
|
|
"目的地": req.get("目的地", "")
|
|||
|
|
}
|
|||
|
|
requirements.append(req_data)
|
|||
|
|
|
|||
|
|
# 递归处理子章节
|
|||
|
|
subsections = json_data.get("子章节", {})
|
|||
|
|
for subsection_name, subsection_data in subsections.items():
|
|||
|
|
sub_reqs = parse_requirements_from_json(subsection_data, current_section)
|
|||
|
|
requirements.extend(sub_reqs)
|
|||
|
|
|
|||
|
|
return requirements
|
|||
|
|
|
|||
|
|
|
|||
|
|
def create_excel(json_file, output_file):
|
|||
|
|
"""
|
|||
|
|
将JSON文件转换为Excel
|
|||
|
|
|
|||
|
|
Args:
|
|||
|
|
json_file: 输入的JSON文件路径
|
|||
|
|
output_file: 输出的Excel文件路径
|
|||
|
|
"""
|
|||
|
|
# 读取JSON文件
|
|||
|
|
with open(json_file, 'r', encoding='utf-8') as f:
|
|||
|
|
data = json.load(f)
|
|||
|
|
|
|||
|
|
# 创建工作簿
|
|||
|
|
wb = Workbook()
|
|||
|
|
|
|||
|
|
# 创建元数据工作表
|
|||
|
|
ws_meta = wb.active
|
|||
|
|
ws_meta.title = "文档元数据"
|
|||
|
|
|
|||
|
|
metadata = data.get("文档元数据", {})
|
|||
|
|
ws_meta['A1'] = "文档标题"
|
|||
|
|
ws_meta['B1'] = metadata.get("标题", "")
|
|||
|
|
ws_meta['A2'] = "生成时间"
|
|||
|
|
ws_meta['B2'] = metadata.get("生成时间", "")
|
|||
|
|
ws_meta['A3'] = "总需求数"
|
|||
|
|
ws_meta['B3'] = metadata.get("总需求数", 0)
|
|||
|
|
|
|||
|
|
# 需求类型统计
|
|||
|
|
stats = metadata.get("需求类型统计", {})
|
|||
|
|
row = 5
|
|||
|
|
ws_meta['A5'] = "需求类型统计"
|
|||
|
|
ws_meta['A5'].font = Font(bold=True)
|
|||
|
|
for req_type, count in stats.items():
|
|||
|
|
row += 1
|
|||
|
|
ws_meta[f'A{row}'] = req_type
|
|||
|
|
ws_meta[f'B{row}'] = count
|
|||
|
|
|
|||
|
|
# 设置元数据工作表样式
|
|||
|
|
for row in ws_meta.iter_rows(min_row=1, max_row=row, min_col=1, max_col=1):
|
|||
|
|
for cell in row:
|
|||
|
|
cell.font = Font(bold=True)
|
|||
|
|
cell.fill = PatternFill(start_color="CCE5FF", end_color="CCE5FF", fill_type="solid")
|
|||
|
|
|
|||
|
|
# 创建需求列表工作表
|
|||
|
|
ws_reqs = wb.create_sheet(title="需求列表")
|
|||
|
|
|
|||
|
|
# 定义表头(按用户要求的顺序)
|
|||
|
|
headers = [
|
|||
|
|
"章节编号", "章节标题", "需求类型", "需求编号", "需求描述",
|
|||
|
|
"接口名称", "接口类型", "来源", "目的地"
|
|||
|
|
]
|
|||
|
|
|
|||
|
|
# 写入表头
|
|||
|
|
for col, header in enumerate(headers, 1):
|
|||
|
|
cell = ws_reqs.cell(row=1, column=col, value=header)
|
|||
|
|
cell.font = Font(bold=True, size=11, color="FFFFFF")
|
|||
|
|
cell.fill = PatternFill(start_color="4472C4", end_color="4472C4", fill_type="solid")
|
|||
|
|
cell.alignment = Alignment(horizontal="center", vertical="center")
|
|||
|
|
|
|||
|
|
# 解析所有需求
|
|||
|
|
all_requirements = []
|
|||
|
|
need_content = data.get("需求内容", {})
|
|||
|
|
for section_name, section_data in need_content.items():
|
|||
|
|
reqs = parse_requirements_from_json(section_data)
|
|||
|
|
all_requirements.extend(reqs)
|
|||
|
|
|
|||
|
|
# 写入需求数据
|
|||
|
|
for row_idx, req in enumerate(all_requirements, 2):
|
|||
|
|
for col_idx, header in enumerate(headers, 1):
|
|||
|
|
# 获取字段值,如果字段不存在或为空字符串,则为空
|
|||
|
|
value = req.get(header, "")
|
|||
|
|
if value is None:
|
|||
|
|
value = ""
|
|||
|
|
|
|||
|
|
cell = ws_reqs.cell(row=row_idx, column=col_idx, value=value)
|
|||
|
|
cell.alignment = Alignment(horizontal="left", vertical="top", wrap_text=True)
|
|||
|
|
|
|||
|
|
# 根据需求类型设置颜色
|
|||
|
|
if header == "需求类型" and value:
|
|||
|
|
if value == "接口需求":
|
|||
|
|
cell.fill = PatternFill(start_color="FFF2CC", end_color="FFF2CC", fill_type="solid")
|
|||
|
|
elif value == "功能需求":
|
|||
|
|
cell.fill = PatternFill(start_color="E2EFDA", end_color="E2EFDA", fill_type="solid")
|
|||
|
|
else:
|
|||
|
|
cell.fill = PatternFill(start_color="FCE4D6", end_color="FCE4D6", fill_type="solid")
|
|||
|
|
|
|||
|
|
# 设置列宽
|
|||
|
|
column_widths = {
|
|||
|
|
'A': 12, # 章节编号
|
|||
|
|
'B': 25, # 章节标题
|
|||
|
|
'C': 12, # 需求类型
|
|||
|
|
'D': 18, # 需求编号
|
|||
|
|
'E': 80, # 需求描述
|
|||
|
|
'F': 25, # 接口名称
|
|||
|
|
'G': 25, # 接口类型
|
|||
|
|
'H': 25, # 来源
|
|||
|
|
'I': 25 # 目的地
|
|||
|
|
}
|
|||
|
|
|
|||
|
|
for col, width in column_widths.items():
|
|||
|
|
ws_reqs.column_dimensions[col].width = width
|
|||
|
|
|
|||
|
|
# 设置所有单元格边框
|
|||
|
|
thin_border = Border(
|
|||
|
|
left=Side(style='thin'),
|
|||
|
|
right=Side(style='thin'),
|
|||
|
|
top=Side(style='thin'),
|
|||
|
|
bottom=Side(style='thin')
|
|||
|
|
)
|
|||
|
|
|
|||
|
|
for row in ws_reqs.iter_rows(min_row=1, max_row=len(all_requirements)+1, min_col=1, max_col=len(headers)):
|
|||
|
|
for cell in row:
|
|||
|
|
cell.border = thin_border
|
|||
|
|
|
|||
|
|
# 冻结首行
|
|||
|
|
ws_reqs.freeze_panes = "A2"
|
|||
|
|
|
|||
|
|
# 保存Excel文件
|
|||
|
|
wb.save(output_file)
|
|||
|
|
print(f"成功将 {len(all_requirements)} 条需求导出到 Excel 文件: {output_file}")
|
|||
|
|
print(f"工作表: '文档元数据' - 包含文档基本信息和统计")
|
|||
|
|
print(f"工作表: '需求列表' - 包含所有需求的详细信息")
|
|||
|
|
|
|||
|
|
|
|||
|
|
def main():
|
|||
|
|
parser = argparse.ArgumentParser(description='将需求JSON文件转换为Excel格式')
|
|||
|
|
parser.add_argument('-i', '--input', required=True, help='输入的JSON文件路径')
|
|||
|
|
parser.add_argument('-o', '--output', required=True, help='输出的Excel文件路径')
|
|||
|
|
|
|||
|
|
args = parser.parse_args()
|
|||
|
|
|
|||
|
|
try:
|
|||
|
|
create_excel(args.input, args.output)
|
|||
|
|
except Exception as e:
|
|||
|
|
print(f"转换失败: {e}")
|
|||
|
|
import traceback
|
|||
|
|
traceback.print_exc()
|
|||
|
|
|
|||
|
|
|
|||
|
|
if __name__ == "__main__":
|
|||
|
|
main()
|