Pārlūkot izejas kodu

add: 根据表格列名的内容长度,分配对应单元格的宽度。表格中空值填充,字体设置,和百分数展示。

qiuya 4 mēneši atpakaļ
vecāks
revīzija
3b41c8c29a
1 mainītis faili ar 46 papildinājumiem un 5 dzēšanām
  1. 46 5
      monitor/report_generate.py

+ 46 - 5
monitor/report_generate.py

@@ -7,12 +7,15 @@
 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
 from docx.oxml import OxmlElement
 from docx.oxml.ns import qn
 from docx.shared import Inches, Cm
+from docx.shared import Pt
 
 from commom import GeneralException, f_get_datetime
 from config import BaseConfig
@@ -35,10 +38,20 @@ class Report():
             cell.width = Cm(1.5)
 
     @staticmethod
-    def _set_cell_format(cell):
+    def _set_cell_format(cell, pt=11):
         cell.paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER
         cell.vertical_alignment = WD_ALIGN_VERTICAL.CENTER
 
+        # 设置字体
+        for paragraph in cell.paragraphs:
+            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
+            run.font.size = Pt(pt)
+
     @staticmethod
     def _merge_cell_column(pre_cell, curr_cell):
         if curr_cell.text == pre_cell.text:
@@ -108,6 +121,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]):
         # 替换表格
@@ -125,14 +142,33 @@ 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)
                     cell.text = str(column_name)
                     for run in cell.paragraphs[0].runs:
                         run.bold = True
-                    Report._set_cell_format(cell)
+                    Report._set_cell_format(cell, 11)
                     Report._set_cell_width(cell)
+                    table.columns[column_idx].width = Cm(adjusted_cell_widths[column_idx])
+                    # Report._set_cell_width(cell, cell_widths[column_idx])
                     # 合并相同的列名
                     if column_idx != 0 and BaseConfig.merge_table_column:
                         pre_cell = table.cell(0, column_idx - 1)
@@ -141,9 +177,14 @@ 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)
-                        cell.text = str(value)
-                        Report._set_cell_format(cell)
-                        Report._set_cell_width(cell)
+                        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 = value
+                        Report._set_cell_format(cell, 10.5)
+                        # Report._set_cell_width(cell)
                         # 合并第一行数据也为列的情况
                         if row_idx == 0:
                             Report._merge_cell_column(table.cell(0, column_idx), cell)