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 => 下划线