python 操作word文档

 

安装依赖

python-docx==2.25.1
docx-mailmerge==0.5.0

 生成word模板并操作数据 docx-mailmerge

 直接操作word文档 docx-mailmerge

 

操作实例

#!/usr/bin/env python
# encoding: utf-8
"""
@author: Irving Shi
"""
import datetime

import os
import docx
from docx.shared import Pt
from docx.enum.text import WD_PARAGRAPH_ALIGNMENT

from mailmerge import MailMerge
from django.http import HttpResponse
from django.views.generic import View
from management import models

import json
from django.conf import settings
from management.util.common import get_str_day_datetime


# 档案导出
class ArchivesExport(View):
    """
    档案导出
    """

    def employee_style(self, cell, text):
        """
        生成单元格
        :param cell: 格子
        :param text: 文本
        :return:
        """

        run = cell.paragraphs[0].add_run(text)
        cell.paragraphs[0].alignment = WD_PARAGRAPH_ALIGNMENT.CENTER

        run.font.name = u'宋体'
        run.font.size = Pt(14)


    def record_check_up_text(self, cell, index, title, result_status, remark):
        """
        生成单元格
        :param cell: 格子
        :param index: 编号
        :param title: 文本
        :param result_status: 结果
        :param remark: 备注
        :return:
        """
        run1 = cell.paragraphs[0].add_run(u"{index}、{title}:".format(index=index, title=title))

        run1.font.name = u'仿宋_GB2312'
        run1.font.size = Pt(12)
        # run.font.color.rgb=RGBColor(233,123,12)

        run2 = cell.paragraphs[0].add_run(u"{result_status}{remark}     \n".format(result_status=result_status,
                                                                                   remark="," + remark if remark else ''))
        run2.font.name = u'仿宋_GB2312'
        run2.font.underline = True
        run2.font.size = Pt(12)

    def get(self, request, _id):
        """

        :param request:
        :param _id: 单位id
        :return:
        """
        # print "_id", _id

        # print settings.BASE_DIR
        enterprise = models.Enterprise.objects.filter(F_EnterpriseID=_id).first()
        if enterprise.F_PoliceStation_id not in request.police_station_id_list:
            return HttpResponse(u"无法访问")
        # 判断选用那个文件作为模板
        file_name_dic = {
            u"1452639854785412365": u"zj_school.docx",
            u"1002000003000000002": u"zj_school.docx",
            u"1002000003000000003": u"zj_school.docx",
            u"1002000003000000004": u"zj_school.docx",
            u"1002000003000000005": u"zj_school.docx",
        }
        # file_name = u"test.docx"
        file_name = file_name_dic.get(str(enterprise.F_Category_id), u"test.docx")  # 取出文件名

        word_template_path = os.path.join(settings.BASE_DIR, u"data", u"enterprise_archives", u"word_template",
                                          file_name)

        document = MailMerge(word_template_path)

        # 获取责任人
        person_charge = models.Employee.objects.filter(F_Enterprise_id=enterprise.F_EnterpriseID, F_JobStatus=0, F_ManageRole=2).first()
        merge_data = {
            "enterprise_name": enterprise.F_Name,
            "addr": enterprise.F_DomainAddr.replace(",",
                                                    "") + enterprise.F_FinalAddr if enterprise.F_DomainAddr is not None else enterprise.F_FinalAddr,
            "corporate_man": enterprise.F_CorporateMan,
            "corporate_man_telephone": enterprise.F_CorporateManTelephone,
            "tel_phone": enterprise.F_TelPhone,
            "calling_name": enterprise.F_CallingName,
            "propertise": enterprise.get_F_Propertise_display(),
            "people_num": str(enterprise.F_PeopleNum),
            "business_license_num": enterprise.F_BusinessLicenseNum,
            "business_license_start_time": '' if enterprise.F_BusinessLicenseStartTime is None else get_str_day_datetime(
                enterprise.F_BusinessLicenseStartTime),
            "deal_in_license_num": enterprise.F_DealInLicenseNum,
            "deal_in_license_begin_day": enterprise.F_DealInLicenseBeginDay,
            "business_scope": enterprise.F_BusinessScope,
            "practice_time": '' if enterprise.F_PracticeTime is None else get_str_day_datetime(
                enterprise.F_PracticeTime),
            "build_area": enterprise.F_buildArea,
            "security_burden_personal": enterprise.F_SecurityBurdenPersonal,
            "security_burden_personal_telephone": enterprise.F_SecurityBurdenPersonalTelephone,
            "instable_factor": enterprise.F_InstableFactor,
            "implement_circs": enterprise.F_ImplementCircs,
            "other_infomation": enterprise.F_OtherInfomation,
            "check_up_time": '' if enterprise.F_CheckUpTime is None else str(enterprise.F_CheckUpTime),
            "police_name": enterprise.F_PoliceName,
            "fax": enterprise.F_Fax,
            "postal_code": enterprise.F_PostalCode,
            "full_time_principal": enterprise.F_FullTimePrincipal,
            "full_time_defend_personal_num": str(enterprise.F_FullTimeDefendPersonalNum),
            "full_time_fire_control_personal_num": str(enterprise.F_FullTimeFireControlPersonalNum),
            "full_time_principal_telephone": enterprise.F_FullTimePrincipalTelephone,
            "part_time_job_principal": enterprise.F_PartTimeJobPrincipal,
            "part_time_job_defend_personal_num": str(enterprise.F_PartTimeJobDefendPersonalNum),
            "part_time_job_fire_control_personal_num": str(enterprise.F_PartTimeJobFireControlPersonalNum),
            "part_time_job_principal_telephone": enterprise.F_PartTimeJobPrincipalTelephone,
            "management_system_percent": "".join([models.Enterprise.F_ManagementSystemPercent_Choice[int(i)] for i in
                                                   enterprise.F_ManagementSystemPercent.split(",") if int(
                    i) in models.Enterprise.F_ManagementSystemPercent_Choice]) if enterprise.F_ManagementSystemPercent else None,
            "employee_personal_num": str(
                enterprise.F_EmployeePersonalNum) if enterprise.F_EmployeePersonalNum else None,
            "student_num": str(enterprise.F_StudentNum) if enterprise.F_StudentNum else None,
            "teaching_building_num": str(
                enterprise.F_TeachingBuildingNum) if enterprise.F_TeachingBuildingNum else None,
            "pivot_department_num": str(enterprise.F_PivotDepartmentNum) if enterprise.F_PivotDepartmentNum else None,
            "pivot_type_of_work": str(enterprise.F_PivotTypeOfWork) if enterprise.F_PivotTypeOfWork else None,
            "person_charge_name": person_charge.F_Name if person_charge is not None else None,  # 负责人姓名
            "person_charge_job": person_charge.F_Job if person_charge is not None else None,  # 负责人职务
            "person_charge_sex": person_charge.F_Sex if person_charge is not None else None,  # 负责人性别
            "person_charge_birthday": get_str_day_datetime(
                person_charge.F_Birthday) if person_charge is not None else None,  # 负责人性别
            "person_charge_zheng_zhi_mian_mao": person_charge.get_F_ZhengZhiMianMao_display() if person_charge is not None else None,
            # 负责人政治面貌
            "person_charge_current_address": person_charge.F_CurrentAddress if person_charge is not None else None,
            # 负责人现住址
            "person_charge_mobile_phone": person_charge.F_MobilePhone if person_charge is not None else None,  # 负责人手机
        }

        document.merge(**merge_data)    # 合并数据

        word_dir = os.path.join(settings.BASE_DIR, u"data", u"enterprise_archives", u"tmp",
                                str(enterprise.F_EnterpriseID))
        if not os.path.isdir(word_dir):
            print
            os.makedirs(word_dir)
        # word_dir = os.path.join(settings.BASE_DIR, "data", "enterprise_archives",_id,u'{enterprise_name}.docx'.format(enterprise_name=enterprise.F_Name),'utf-8')

        word_path = os.path.join(word_dir, u'{enterprise_name}.docx'.format(enterprise_name=enterprise.F_Name))

        # 文件另存为
        document.write(word_path)

        if hasattr(self, file_name.rsplit(".")[0]):
            return getattr(self, file_name.rsplit(".")[0])(enterprise, word_path)

        return self.standard(enterprise, word_path)

    def standard(self, enterprise, word_path):
        doc = docx.Document(word_path)

        # 获取word中的所有 table
        table = doc.tables

        # 取出 table
        employee_table_word = table[1]
        # for row in employee_table_word.rows:
        #     row_text = [columns.text for columns in row.cells]
        #     print json.dumps(row_text, ensure_ascii=False)

        # 获取出在职的员工记录
        employee_list = models.Employee.objects.filter(F_Enterprise_id=enterprise.F_EnterpriseID, F_JobStatus=0)
        employee_index = 0
        for index, employee in enumerate(employee_list, 1):
            row_cells = employee_table_word.add_row().cells
            # row_cells[0].text = str(index)
            self.employee_style(row_cells[0], str(index))
            self.employee_style(row_cells[1], employee.F_Name)
            self.employee_style(row_cells[2], employee.F_IDCard)
            self.employee_style(row_cells[3], employee.F_Sex)
            self.employee_style(row_cells[4], employee.F_Job)
            self.employee_style(row_cells[5], employee.F_CurrentAddress)
            self.employee_style(row_cells[6], employee.F_MobilePhone)
            self.employee_style(row_cells[7], employee.F_Remark)
            employee_index = index
        if employee_index == 0:
            # 生成一行 table
            employee_table_word.add_row()
            employee_table_word.add_row()
            employee_table_word.add_row()
            employee_table_word.add_row()

        checkUp_record = models.CheckUpRecord.objects.filter(F_Enterprise_id=enterprise.F_EnterpriseID).order_by(
            "-F_CheckTime").first()
        # print checkUp_record

        if checkUp_record is not None:
            checkUp_record_table_word = table[2]

            # 获取单个单元格
            cell = checkUp_record_table_word.cell(2, 1)

            # 清空单元格
            cell.text = u""

            # 生成单元格文本 并 设置字体
            run = cell.paragraphs[0].add_run(u"治安检查内容:\n")
            run.font.name = u'宋体'
            run.font.size = Pt(14)

            # 获取出最后一次检查记录的结果记录
            record_check_up_list = models.RecordCheckUp.objects.filter(F_InspectType=1, F_CheckUpRecord_id=checkUp_record.F_CheckUpRecordID).order_by("F_Sort")

            for index, record_check_up in enumerate(record_check_up_list, 1):
                self.record_check_up_text(
                    cell,
                    index,
                    record_check_up.F_Title,
                    u'正常' if record_check_up.F_ResultStatus == 0 else u'不正常',
                    record_check_up.F_Remark
                )
                # print i.F_Sort, i.F_Title, i.F_ResultStatus

            # 设置单元格的行间距
            cell.paragraphs[0].paragraph_format.line_spacing = Pt(30)

        # 保存文件
        doc.save(word_path)
        # return HttpResponse("ok")
        filename = os.path.basename(word_path)
        with open(word_path, u"rb") as f:
            view_data = f.read()
        response = HttpResponse(view_data, content_type=u'application/vnd.ms-word')
        response[u'Content-Disposition'] = "attachment; filename={filename}".format(filename=filename)
        return response

    def zj_school(self, enterprise, word_path):
        doc = docx.Document(word_path)
        table = doc.tables

        employee_table_word = table[2]  # 7

        for row in employee_table_word.rows:
            row_text = [columns.text for columns in row.cells]
            print json.dumps(row_text, ensure_ascii=False)

        employee_list = models.Employee.objects.filter(F_Enterprise_id=enterprise.F_EnterpriseID, F_IsSecurityOrganise=1, F_JobStatus=0)
        employee_index = 0
        for index, employee in enumerate(employee_list, 1):
            row_cells = employee_table_word.add_row().cells
            # row_cells[0].text = str(index)
            # self.employee_style(row_cells[0], str(index))
            self.employee_style(row_cells[0], employee.F_Name)
            self.employee_style(row_cells[1], employee.F_Sex)
            self.employee_style(row_cells[2],
                                get_str_day_datetime(employee.F_Birthday) if employee.F_Birthday is not None else '')
            self.employee_style(row_cells[3],
                                employee.get_F_ZhengZhiMianMao_display() if employee.F_ZhengZhiMianMao is not None else '')

            self.employee_style(row_cells[4], employee.F_CurrentAddress)
            self.employee_style(row_cells[5], employee.F_Remark)
            employee_index = index

        if employee_index == 0:
            employee_table_word.add_row()
            employee_table_word.add_row()
            employee_table_word.add_row()
            employee_table_word.add_row()

        checkUp_record = models.CheckUpRecord.objects.filter(F_Enterprise_id=enterprise.F_EnterpriseID).order_by(
            "-F_CheckTime").first()
        # print checkUp_record

        if checkUp_record is not None:
            checkUp_record_table_word = table[3]
            cell = checkUp_record_table_word.cell(2, 1)
            cell.text = u""

            run = cell.paragraphs[0].add_run(u"治安检查内容:\n")
            run.font.name = u'宋体'
            run.font.size = Pt(14)

            record_check_up_list = models.RecordCheckUp.objects.filter(
                F_InspectType=1,
                F_CheckUpRecord_id=checkUp_record.F_CheckUpRecordID).order_by("F_Sort")

            for index, record_check_up in enumerate(record_check_up_list, 1):
                self.record_check_up_text(cell, index, record_check_up.F_Title,
                                          u'正常' if record_check_up.F_ResultStatus == 0 else u'不正常',
                                          record_check_up.F_Remark)
                # print i.F_Sort, i.F_Title, i.F_ResultStatus

            cell.paragraphs[0].paragraph_format.line_spacing = Pt(30)
        doc.save(word_path)
        # return HttpResponse("ok")
        filename = os.path.basename(word_path)
        with open(word_path, u"rb") as f:
            view_data = f.read()
        response = HttpResponse(view_data, content_type=u'application/vnd.ms-word')
        response[u'Content-Disposition'] = "attachment; filename={filename}".format(filename=filename)
        return response

 

 

 

 

样式的 key 值

# all_caps       =>  全部大写字母
# bold           =>  加粗
# color          =>  字体颜色
# complex_script =>  是否为“复杂代码”
# cs_bold        =>  “复杂代码”加粗
# cs_italic      =>  “复杂代码”斜体
# double_strike  =>  双删除线
# emboss         =>  文本以凸出页面的方式出现
# hidden         =>  隐藏
# imprint        =>  印记
# italic         =>  斜体
# name           =>  字体
# no_proof       =>  不验证语法错误
# outline        =>  显示字符的轮廓
# shadow         =>  阴影
# small_caps     =>  小型大写字母
# snap_to_grid   =>  定义文档网格时对齐网络
# strike         =>  删除线
# subscript      =>  下标
# superscript    =>  上标
# underline      =>  下划线

 

posted @ 2021-09-17 10:22  陨落&新生  阅读(501)  评论(0编辑  收藏  举报