|
@@ -7,6 +7,8 @@
|
|
|
import os
|
|
|
from typing import Dict
|
|
|
|
|
|
+import pandas as pd
|
|
|
+
|
|
|
from docx import Document
|
|
|
from docx.enum.table import WD_ALIGN_VERTICAL
|
|
|
from docx.enum.text import WD_ALIGN_PARAGRAPH
|
|
@@ -43,8 +45,13 @@ class Report():
|
|
|
@staticmethod
|
|
|
def _set_cell_format(cell, font_size=None):
|
|
|
for paragraph in cell.paragraphs:
|
|
|
- paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
|
+ # paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
|
for run in paragraph.runs:
|
|
|
+ # 判断文本是否包含中文
|
|
|
+ if any('\u4e00' <= char <= '\u9fff' for char in run.text):
|
|
|
+ run.font.name = '宋体' # 设置中文字体为宋体
|
|
|
+ else:
|
|
|
+ run.font.name = 'Times New Roman' # 设置英文字体为Times New Roman
|
|
|
if font_size is not None:
|
|
|
run.font.size = Pt(font_size)
|
|
|
cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
|
|
@@ -117,6 +124,10 @@ class Report():
|
|
|
run.text = ''
|
|
|
paragraph.runs[-1].text = text
|
|
|
|
|
|
+ @staticmethod
|
|
|
+ def _get_text_length(text):
|
|
|
+ return sum(3 if '\u4e00' <= char <= '\u9fff' else 1 for char in text)
|
|
|
+
|
|
|
@staticmethod
|
|
|
def _fill_table_placeholder(doc: Document, metric_value_dict: Dict[str, MetricFucEntity]):
|
|
|
# 替换表格
|
|
@@ -137,6 +148,23 @@ class Report():
|
|
|
table = doc.add_table(rows=metric_table.shape[0] + 1, cols=metric_table.shape[1])
|
|
|
table.alignment = WD_ALIGN_PARAGRAPH.CENTER
|
|
|
paragraph._element.addnext(table._element)
|
|
|
+
|
|
|
+ # 根据列名计算单元格宽度,对不符合最小宽度的情况,重新调整
|
|
|
+ # TODO:根据列名和内容综合调整单元格宽度
|
|
|
+ a4_width = 21 - 2 * 3.18
|
|
|
+ total_columns = metric_table.shape[1]
|
|
|
+ col_lengthes = [Report._get_text_length(c) for c in metric_table.columns]
|
|
|
+ cell_width_unit = a4_width / sum(col_lengthes)
|
|
|
+ cell_widths = [c * cell_width_unit for c in col_lengthes]
|
|
|
+ min_cell_width = 1
|
|
|
+ adjusted_cell_widths = [max(c, min_cell_width) for c in cell_widths]
|
|
|
+ adjusted_width = sum(adjusted_cell_widths)
|
|
|
+ if adjusted_width > a4_width:
|
|
|
+ excess_width = adjusted_width - a4_width
|
|
|
+ excess_width_per_column = excess_width / total_columns
|
|
|
+ adjusted_cell_widths = [max(min_cell_width, c - excess_width_per_column) for c in
|
|
|
+ adjusted_cell_widths]
|
|
|
+
|
|
|
# 列名
|
|
|
for column_idx, column_name in enumerate(metric_table.columns):
|
|
|
cell = table.cell(0, column_idx)
|
|
@@ -144,6 +172,7 @@ class Report():
|
|
|
for run in cell.paragraphs[0].runs:
|
|
|
run.bold = True
|
|
|
Report._set_cell_format(cell, table_font_size)
|
|
|
+ table.columns[column_idx].width = Cm(adjusted_cell_widths[column_idx])
|
|
|
# 合并相同的列名
|
|
|
if column_idx != 0 and BaseConfig.merge_table_column:
|
|
|
pre_cell = table.cell(0, column_idx - 1)
|
|
@@ -152,6 +181,11 @@ class Report():
|
|
|
for row_idx, row in metric_table.iterrows():
|
|
|
for column_idx, value in enumerate(row):
|
|
|
cell = table.cell(row_idx + 1, column_idx)
|
|
|
+ if "率" in metric_table.columns[column_idx] or (
|
|
|
+ "率" in str(row[0]) and pd.notna(value) and (column_idx != 0)):
|
|
|
+ value = f"{float(value) * 100:.2f}%" if pd.notna(value) else '/'
|
|
|
+ else:
|
|
|
+ value = str(value) if pd.notna(value) else '/'
|
|
|
cell.text = str(value)
|
|
|
Report._set_cell_format(cell, table_font_size)
|
|
|
# 合并第一行数据也为列的情况
|
|
@@ -159,7 +193,7 @@ class Report():
|
|
|
Report._merge_cell_column(table.cell(0, column_idx), cell, table_font_size,
|
|
|
table_cell_width)
|
|
|
|
|
|
- Report._set_cell_width(table, table_cell_width)
|
|
|
+ # Report._set_cell_width(table, table_cell_width)
|
|
|
Report._set_table_singleBoard(table)
|
|
|
# 禁止自动调整表格
|
|
|
if len(metric_table.columns) <= 12 or not table_autofit:
|