zoukankan      html  css  js  c++  java
  • 206.pythondocx 操作word

    看代码

    import datetime
    from pathlib import Path
    
    from docx import Document
    from docx.oxml import OxmlElement, ns
    from docx.shared import Inches, Pt, Cm, Mm, RGBColor
    from docx.enum.text import WD_ALIGN_PARAGRAPH, WD_TAB_ALIGNMENT
    from docx.text.font import Font
    from docx.oxml.ns import qn
    
    BASE_DIR = Path(__file__).resolve().parent.parent
    # 对其方式
    WD_ALIGN = {
        "center": WD_ALIGN_PARAGRAPH.CENTER,
        "left": WD_ALIGN_PARAGRAPH.LEFT,
        "right": WD_ALIGN_PARAGRAPH.RIGHT,
        "justify": WD_ALIGN_PARAGRAPH.JUSTIFY,
        # "distribute": WD_ALIGN_PARAGRAPH.DISTRIBUTE,  # 分散对齐, 占满整行
        # "justify_med": WD_ALIGN_PARAGRAPH.JUSTIFY_MED,  # 类似于左对齐
        # "justify_hi": WD_ALIGN_PARAGRAPH.JUSTIFY_HI,  # 类似于左对齐
        # "justify_low": WD_ALIGN_PARAGRAPH.JUSTIFY_LOW,  # 类似于左对齐
        # "thal_justify": WD_ALIGN_PARAGRAPH.THAI_JUSTIFY,  # 类似于左对齐
    }
    
    
    class Report:
        """工具类"""
    
        def __init__(self):
            self.doc = None
    
        def init_doc(self, font_name):
            """
            直接初始化默认的正文字体和大小
            https://blog.csdn.net/weixin_42763696/article/details/105492135
            https://blog.csdn.net/qq_40272386/article/details/114867630
            """
            doc = Document()
            doc.styles['Normal'].font.name = font_name
            doc.styles['Normal']._element.rPr.rFonts.set(qn('w:eastAsia'), font_name)
            doc.styles['Normal'].font.size = Pt(12)
            doc.add_picture('{}/images/0001.jpg'.format(BASE_DIR), width=Inches(1.25))  # 1.25间距插入图片
            self.doc = doc
    
        def init_header(self, text):
            """
            添加页眉设置
            https://baijiahao.baidu.com/s?id=1665454009794833226  很详细的页眉页脚设置
            """
            section = self.doc.sections[0]
            header = section.header
            p = header.paragraphs[0]
            run = p.add_run(text)  # 这个文字其实应该抽出去但是我懒了
            font = run.font
            font.size = Pt(10.5)
            run.font.underline = True  # 添加下划线
    
        def create_element(self, name):
            return OxmlElement(name)
    
        def create_attribute(self, element, name, value):
            element.set(ns.qn(name), value)
    
        def add_page_number(self):
            """添加页码"""
            p = self.doc.sections[0].footer.paragraphs[0]
            run = p.add_run()
            fldChar1 = self.create_element('w:fldChar')
            self.create_attribute(fldChar1, 'w:fldCharType', 'begin')
    
            instrText = self.create_element('w:instrText')
            self.create_attribute(instrText, 'xml:space', 'preserve')
            instrText.text = "PAGE"
    
            fldChar2 = self.create_element('w:fldChar')
            self.create_attribute(fldChar2, 'w:fldCharType', 'end')
    
            run._r.append(fldChar1)
            run._r.append(instrText)
            run._r.append(fldChar2)
            font = run.font
            font.size = Pt(10.5)
            p.alignment = WD_ALIGN.get("center")
    
        def add_paragraph(self, text, font_name="黑体", size_num=12, bold=False, alignment=None, line_spacing=1.5,
                          style=None):
            """定义段落格式"""
            p = self.doc.add_paragraph(style=style)
            run = p.add_run(text)
            run.font.color.rgb = RGBColor(0, 0, 0)
            if alignment:
                p.alignment = WD_ALIGN.get(alignment)
    
            font = run.font
            font.name = font_name
            run.element.rPr.rFonts.set(qn("w:eastAsia"), font_name)
            font.size = Pt(size_num)
            run.bold = bold
    
            pformat = p.paragraph_format
            pformat.line_spacing = line_spacing  # 行间距
    
        # https://www.jianshu.com/p/ceea5ade0cda
        # https://blog.csdn.net/star565/article/details/103411328
        # https://blog.csdn.net/ibiao/article/details/78595295  table.style
        # https://www.jianshu.com/p/8d8a75a50190  段落格式设置
        def add_table(self, data, aufofix=True, style="Table Grid", col_width=None, vertical_alignment=None):
            # 注意data中的数据和t_row, t_col = len(data), len(data[0]), 必须对应, 否则列宽可能失败(
            # 就算我最后一行不写任何东西都要用["", "", "", "", ""]填充)
    
            t_row, t_col = len(data), len(data[0])
            table = self.doc.add_table(rows=t_row, cols=t_col, style=style)  # 添加一个表格
            table.autofit = aufofix
    
            for i in range(t_row):
                # table.rows[1].height = Cm(2)  # 可以通过索引指定行高
                for j in range(t_col):
                    table.cell(i, j).text = data[i][j]
                    # 但是列宽必须每个cell单独设置, 否则设置不成功, 同时table.autofit = False(是否开启自动调整列宽功能)
                    if col_
                        table.cell(i, j).width = Cm(col_width.get(j, 0))
                    if vertical_alignment:
                        table.cell(i, j).vertical_alignment = vertical_alignment
            self.add_paragraph("\n")
    
        def add_page_break(self):
            self.doc.add_page_break()
    
        def save(self, path):
            self.doc.save(path)
    
    
    class AgileReport:
        """每个报告都不一样可以改造成继承也可以直接调用调用"""
    
        def __init__(self, report: Report):
            self.report = report
    
        def part1(self, version, creator):
            """创建报告前部固定位置信息"""
            self.report.add_paragraph("\n" * 2)
            text = "{}测试报告".format(version)
            self.report.add_paragraph(text, font_name="黑体", alignment="center", size_num=24, bold=True)
    
            texts = ["文件编号:XXXXXXXXXXX", "版 本 号: A", "受控状态:受控", "密    级:内部公开"]
    
            for text in texts:
                self.report.add_paragraph(" " * 20 + text, font_name="黑体", size_num=14, alignment="left")
    
            self.report.doc.add_paragraph("\n" * 8)
            text = "XXXXXX有限公司"
            self.report.add_paragraph(text, font_name="黑体", alignment="center", size_num=16, bold=True)
            self.report.add_page_break()
            self.report.add_paragraph("文档修订记录", font_name="黑体", alignment="center", size_num=14, bold=True)
    
            time1 = datetime.datetime.now().strftime("%Y-%m-%d")
    
            data = [["修订号", "日期", "内容", "作者", "审核"],
                    ["1", time1, "创建", creator, ""],
                    ["", "", "", "", ""]]  # table填充的数据
            col_width = {0: 3, 1: 3, 2: 3, 3: 3, 4: 3.6}  # 经过一次次试验发现, word默认宽15.6cm (当然你也可以超过这个长度, 可能会使得表格看起来怪异)
            vertical_alignment = WD_TAB_ALIGNMENT.CENTER
    
            self.report.add_table(data, col_width=col_width, vertical_alignment=vertical_alignment)
    
            self.report.add_page_break()
    
        def part2(self, product, project):
            # 发现其实标题也是段落, 只不过加了个style而已, 呢就直接统一掉
            self.report.add_paragraph("1 测试范围", size_num=22, bold=True, style="Heading 1")
            self.report.add_paragraph("1.1 测试产品信息", size_num=16, bold=True, style="Heading 2")
            self.report.add_paragraph("产品名称:{}".format(product))
            self.report.add_paragraph("版本信息:{}".format(project))
    
            self.report.add_paragraph("1.2 测试内容", size_num=16, bold=True, style="Heading 2")
            self.report.add_paragraph("《XXXXXX产品检测规范.docx》")
            self.report.add_paragraph("2 测试环境", size_num=22, bold=True, style="Heading 1")
    
            data = [["设备类型", "操作系统", "说明"], ["Linux", "CentOS release 6.10", ""]]  # table填充的数据
            col_width = {0: 5, 1: 5, 2: 5, 3: 1, 4: 1}  # 列宽
            vertical_alignment = WD_TAB_ALIGNMENT.CENTER
            self.report.add_table(data, col_width=col_width, vertical_alignment=vertical_alignment)
            self.report.add_paragraph("3 测试执行", size_num=22, bold=True, style="Heading 1")
    
        def part_change(self, data):
            """
            这一部分信息变动比较大
            data = {任务名称: [优先级1: [数据列表], 优先级1: [数据列表]], 任务名称: [优先级1: [数据列表], 优先级1: [数据列表]]}
            """
            header = ["序号", "用例标题", "前置条件", "测试步骤", "预期结果", "测试结果", "备注"]
            task_idx = 1
            for task_key in data:
                self.report.add_paragraph("3.{} {}".format(task_idx, task_key), size_num=16, bold=True, style="Heading 2")
                pri_idx = 1
                for pri_data in data[task_key]:
                    for pri_key in pri_data:
                        self.report.add_paragraph("3.{}.{} {}".format(task_idx, pri_idx, pri_key), size_num=16, bold=True)
                        col_width = {0: 1.2, 1: 2.1, 2: 2.1, 3: 6, 4: 2.1, 5: 2.1, 6: 1.4}  # 列宽
                        vertical_alignment = WD_TAB_ALIGNMENT.CENTER
                        pri_data = [header] + pri_data[pri_key]
                        self.report.add_table(pri_data, aufofix=False, col_width=col_width,
                                              vertical_alignment=vertical_alignment)
                    pri_idx += 1
                task_idx += 1
    
        def part3(self, path):
            """报告后半部分固定信息"""
            self.report.add_paragraph("4 测试结果统计", size_num=22, bold=True, style="Heading 1")
            self.report.add_paragraph("5 测试结论", size_num=22, bold=True, style='Heading 1')
            self.report.save(path)
    
        def create_report(self, pjv: list, data: dict, path: str, creator: str):
            # 真实报告的步骤可以随便加
            self.part1(pjv[-1], creator)
            product, project = pjv[0], pjv[1]
            self.part2(product, project)
            # table填充的数据
            self.part_change(data)
            self.part3(path)
    
    
    if __name__ == '__main__':
        report = Report()
        report.init_doc('微软雅黑')
        report.init_header("XXXXXX\t\t测试报告")
        report.add_page_number()
    
        real_report = AgileReport(report)
        pjv = []
        data = {}
        path = r"C:\Users\yzt\Desktop\test1.docx"
        real_report.create_report(pjv, data, path, "root")
    

    总结:
    这个工具包底层是xml组成的, 一些功能没有实现比如目录, 希望有大佬可以实现, 菜鸡只能用用

  • 相关阅读:
    Webservise如何Webservise实现打印
    GridView和FormView中对时间的末尾处理
    WebService系统结构设计
    Panel的用法
    Div+CSS选项卡
    java运行环境配置
    电子商务购物车
    电子商务配置管理
    电子商务订单生成
    spring+redis+mysql做缓存操作 look
  • 原文地址:https://www.cnblogs.com/liuzhanghao/p/15608800.html
Copyright © 2011-2022 走看看