project init.
This commit is contained in:
202
json_to_excel.py
Normal file
202
json_to_excel.py
Normal file
@@ -0,0 +1,202 @@
|
||||
# -*- 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()
|
||||
Reference in New Issue
Block a user