Python 关于DOC文本编辑小记

本文介绍了一个简化版的报告自动生成方案,通过修改Word模板实现内容插入,重点展示了如何添加段落和表格,以及合并单元格的技巧,以降低复杂度并兼容WPS文档。

有一个基于一个word版本的报告自动生成的需求,原本计划内容全部自动生成,调研发现内容过于庞大,且实现复杂度较高,所以采取一个折中方案,通过修改一个模板文件实现,将内容通过插入和替换方式加入,以下为部分核心代码。仅仅记录一下,另外有一个巨坑 ,python的docx是基于office的,不支持WPS 不支持WPS 不支持WPS。

生成段落内容,并插入到指定位置。支持设定段落样式


def add_doc_paragraph_tp(document, para_content,after_p=None,style_name=None, font_size=None, font_name=None, format_size=None,font_bold=False):
    '''
    添加段落,默认只添加内容不设置格式,当传递格式时,可根据自定义设置
    :param document:
    :param para_content: 段落内容
    :param after_p: 欲将创建的段落移动至该段落后
    :param styles: 段落样式
    :param font_size: 字体大小
    :param font_name: 字体名称
    :param format_size: 缩进大小
    :return:
    '''

    p = document.add_paragraph()
    p_format = p.paragraph_format  # 段落格式
    # if pa_style:
    #     p.style = document.styles[pa_style]
    p_run = p.add_run(para_content)
    p_run.font.name = font_name if font_name else u'宋体中文正文'
    p_run.font.size = Pt(font_size) if font_size else Pt(10.5)
    if font_bold:
        p_run.font.bold = True
    if style_name:
        p.style = document.styles[style_name]
    else:
        # if ('Heading'not in pa_style) or ('List' not in pa_style):
        p_format.first_line_indent = Cm(format_size) if format_size else Cm(0.74)
    if after_p:
        move_paragraph_after(p,after_p)
    return p

调用方法

 result_data_content_para = add_doc_paragraph_tp(report_template, ' 我是文本内容',after_p=result_data_para,font_size=10.5, font_name='宋体', font_bold=True)

生成表格内容


def add_df_table(df,document,after_p=None,query_name=None,type=None,width_dict=None):
    '''
    通过dataframe添加表格
    :param df: dataframe
    :param document:
    :param query_name: 查询字段
    :param type: 查询条件
    :return:
    '''
    cos_list = df.columns.values.tolist() #列名转list
    if type:
        cos_list.remove(query_name)  #剔除条件列
        table_df = df.loc[df[query_name]==type]  #根据条件进行筛选
        # table_df = df.query('@query_name == @type')
        table_df = table_df[cos_list]  #过滤得到需要的数据
    else:
        table_df = df

    table_row_count = table_df.shape[0]+1 # 创建docx table, 行数为原df行数 + 1(第1行表头)
    if table_row_count == 1:
        table_row_count = table_row_count+1
    table_col_count = table_df.shape[1]  # 列数位df 的列数
    table = document.add_table(table_row_count, table_col_count)
    table_title_background_colour(table,table_col_count,'C0C0C0')   #设置表头格式
    table.style = 'Table Grid'  # 表格格式
    #添加docx表头里的文字 = 提取的df.columns


    table_title(table,table_df)  #添加表格标题
    #设定单元格宽度
    if width_dict:
        for col_num in range(len(width_dict)):
            table.cell(0, col_num).width = Inches(width_dict[col_num])
    #填充数据

    for i in range(table_df.shape[0]):
        for j in range(table_df.shape[-1]):
            if pd.isnull(table_df.iat[i, j]):
                cell_v = '待补充'
            else:
                cell_v = str(table_df.values[i, j])
            # print(table_df.values[i, j])
            run = table.cell(i+1, j).paragraphs[0].add_run(cell_v)
            run.font.name = '宋体'  # 字体
            run.font.size = Pt(10)
            table.cell(i+1, j).paragraphs[0].alignment = WD_ALIGN_PARAGRAPH.CENTER  # 水平居中
            table.cell(i+1, j).vertical_alignment = WD_ALIGN_VERTICAL.CENTER  # 垂直据中国

    if after_p:
        move_table_after(table,after_p)
    return table

基于Key值合并单元格

def merge_table(merge_df,merge_table,merge_cols_index,merge_cols_list):
    '''

    :param merge_df: 待合并单元和的dataframe
    :param merge_table: 待合并单元格
    :param merge_cols_index: 合并单元格参考列的index
    :param merge_cols_list: 待合并单元的列index 为list类型,支持多列根据参照列合并
    :return:
    '''
    for merge_cols in merge_cols_list:
        merge_dict = {}
        # merge_end_index = 1
        for i in range(merge_df.shape[0]):
            current_inx = i + 1
            # 当达到最大index后,next_inx和current_inx 保持一致,其他情况next则执行+1操作
            if current_inx == merge_df.shape[0]:
                next_inx = current_inx
            else:
                merge_end_inx = next_inx = current_inx + 1
            current_cell = merge_table.cell(current_inx, merge_cols_index)
            next_cell = merge_table.cell(next_inx, merge_cols_index)
            # 获取需要合并的字段及其First、END值
            if current_cell.text not in merge_dict.keys():
                # 当字段没有在字典中时,初始化first和end值,置为该字段第一次出现的位置
                merge_first_inx = current_inx
                merge_end_inx = current_inx
            else:
                if current_cell.text != next_cell.text:
                    # 当下一行数据和当前行数据不一致时,说明有新的数据产生,此时将下一行inx-1就是需要合并的最后一行inx
                    merge_end_inx = next_inx - 1
            merge_dict[current_cell.text] = [merge_first_inx, merge_end_inx]
        for merge_item in merge_dict:
            first_cell = merge_table.cell(merge_dict[merge_item][0], merge_cols)
            end_cell = merge_table.cell(merge_dict[merge_item][1], merge_cols)
            merge_cell = first_cell.merge(end_cell)
            merge_cell.text = first_cell.text.split('\n')[0]
    return merge_table

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值