python使用docxtpl处理word文档图片不显示问题

python使用docxtpl处理word文档图片不显示问题

python使用docxtpl处理word文档图片不显示问题

docxtpl的使用:

安装docxtpl:

pip install docxtpl

基本使用实例main.py:

from docxtpl import DocxTemplate
doc = DocxTemplate("my_word_template.docx")
sd  = doc.new_subdoc("my_subdoc.docx")
context = {
     'company_name': "World company",
           'sub_doc': sd,
           }
doc.render(context)
doc.save("generated_doc.docx")

其中模板文件my_word_template.docx内容如下:python使用docxtpl处理word文档图片不显示问题_第1张图片
子文件my_subdoc.docx内容如下:
python使用docxtpl处理word文档图片不显示问题_第2张图片
执行main.py生成generated_doc.docx文件
python使用docxtpl处理word文档图片不显示问题_第3张图片

问题处理:

import docx
from docxtpl import DocxTemplate, Subdoc
import os
from win32com import client as wc
from xml.etree.ElementTree import ElementTree,Element
import shutil

Namespaces = {
     'w': 'http://schemas.microsoft.com/office/word/2003/wordml',
               'wx':'http://schemas.microsoft.com/office/word/2003/auxHint',
               'aml':'http://schemas.microsoft.com/aml/2001/core',
               'wpc':'http://schemas.microsoft.com/office/word/2010/wordprocessingCanvas',
               'cx':'http://schemas.microsoft.com/office/drawing/2014/chartex', 
               'cx1':'http://schemas.microsoft.com/office/drawing/2015/9/8/chartex', 
               'cx2':'http://schemas.microsoft.com/office/drawing/2015/10/21/chartex', 
               'cx3':'http://schemas.microsoft.com/office/drawing/2016/5/9/chartex', 
               'cx4':'http://schemas.microsoft.com/office/drawing/2016/5/10/chartex', 
               'cx5':'http://schemas.microsoft.com/office/drawing/2016/5/11/chartex', 
               'cx6':'http://schemas.microsoft.com/office/drawing/2016/5/12/chartex', 
               'cx7':'http://schemas.microsoft.com/office/drawing/2016/5/13/chartex', 
                'cx8':'http://schemas.microsoft.com/office/drawing/2016/5/14/chartex', 
                'dt':'uuid:C2F41010-65B3-11d1-A29F-00AA00C14882', 
                'mc':'http://schemas.openxmlformats.org/markup-compatibility/2006', 
                'aink':'http://schemas.microsoft.com/office/drawing/2016/ink', 
                'am3d':'http://schemas.microsoft.com/office/drawing/2017/model3d', 
                'o':'urn:schemas-microsoft-com:office:office',
                'v':'urn:schemas-microsoft-com:vml',
                'w10':'urn:schemas-microsoft-com:office:word',  
                'wne':'http://schemas.microsoft.com/office/word/2006/wordml',
               'wsp':'http://schemas.microsoft.com/office/word/2003/wordml/sp2', 
               'sl':'http://schemas.microsoft.com/schemaLibrary/2003/core',
              }

class LilyDocTpl(object):
    def __init__(self,MasterDocpath,SubDocpath,Outpath):
        self.MasterDocpath=MasterDocpath
        self.SubDocpath=SubDocpath
        self.Outpath=Outpath
        OutAbspath=os.getcwd()
        if os.path.exists('./temp')==False:
            os.mkdir(OutAbspath + './temp')
        self.temppath=os.path.join(OutAbspath,'temp')
        self.tempdocx=os.path.join(self.temppath,'tempdocx.docx')

    def MakeTemDocx(self,**argv):
        context={
     }
        doc=DocxTemplate(self.MasterDocpath)
        for key in argv:
            if argv[key][1]==1:
                sd=doc.new_subdoc(argv[key][0])
                context[key]=sd
            elif argv[key][1]==0:
                context[key]=argv[key][0]
        doc.render(context)
        doc.save(self.tempdocx)
    
    def MakeTemXml(self,filepath):
        word = wc.Dispatch('Word.Application') 
        doc = word.Documents.Open(filepath)
        filename=os.path.split(filepath)[-1][:-5]+'.xml'
        temxml=os.path.join(self.temppath,filename)
        doc.SaveAs(temxml,11)
        doc.Close()
        word.Quit()
        return temxml

    def read_xml(self,in_path):
        tree = ElementTree()
        tree.parse(in_path)
        return tree

    def find_nodes(self,tree, path,Namespaces):
      return tree.findall(path,Namespaces) 
     
    def write_xml(self,tree, out_path):
      tree.write(out_path, encoding="utf-8",xml_declaration=True)

    def GetPWithPic(self,Subpath):
        Parr={
     }
        root=self.read_xml(Subpath).getroot()
        BodyTag=self.find_nodes(root,"w:body",Namespaces)
        SectTag=self.find_nodes(BodyTag[0],"wx:sect",Namespaces)
        for item in SectTag[0].getchildren():
            wr=self.find_nodes(item, "w:r",Namespaces)
            if wr:
                if self.find_nodes(wr[0], "w:pict",Namespaces):
                    rsidR=item.attrib["{http://schemas.microsoft.com/office/word/2003/wordml/sp2}rsidR"]
                    Parr[rsidR]=item
        return Parr

    # 查找生成docx文件中含图片的标签p并根据rsidR替换
    def ChangePic(self,examplepath,Subpath):
            Parr=self.GetPWithPic(Subpath)
            tree=self.read_xml(examplepath)
            indexarr={
     }
            root=tree.getroot()
            BodyTag = self.find_nodes(root, "w:body",Namespaces)
            SectTag=self.find_nodes(BodyTag[0], "wx:sect",Namespaces)
            # SectionTag=find_nodes(SectTag[0], "wx:sub-section",Namespaces)
            PTag=self.find_nodes(SectTag[0], "w:p",Namespaces)
            for index,item in enumerate(SectTag[0].getchildren()): 
                wr=self.find_nodes(item, "w:r",Namespaces)
                if wr:
                    for item2 in wr:
                        if self.find_nodes(item2, "w:pict",Namespaces):
                            rsidR=item.attrib["{http://schemas.microsoft.com/office/word/2003/wordml/sp2}rsidR"]
                            SectTag[0].insert(index,Parr[rsidR])
                            SectTag[0].remove(SectTag[0].getchildren()[index+1])
                            indexarr[index]=rsidR
            self.filename=os.path.split(examplepath)[-1][:-5]+'.xml'
            self.write_xml(tree, os.path.join(self.temppath,self.filename))
    
    def XmltoDocx(self):
        word = wc.Dispatch('Word.Application') 
        doc = word.Documents.Open(os.path.join(self.temppath,self.filename)) 
        
        doc.SaveAs(self.Outpath, 16) 
        doc.Close() 
        word.Quit()

    def DelTemp(self):
        filelist=[]
        rootdir=self.temppath
        filelist=os.listdir(rootdir)               
        for f in filelist:
            filepath = os.path.join( rootdir, f )
            if os.path.isfile(filepath): 
                os.remove(filepath)
            elif os.path.isdir(filepath):
                shutil.rmtree(filepath,True)
        shutil.rmtree(rootdir,True)

    def GetTplDocx(self,**context):
        self.MakeTemDocx(**context)
        examplepath=self.MakeTemXml(self.tempdocx)
        Subpath=self.MakeTemXml(self.SubDocpath)
        self.ChangePic(examplepath,Subpath)
        self.XmltoDocx()
        self.DelTemp()
    
def main():
    MasterDocpath="../my_word_template.docx"
    SubDocpath="../my_subdoc.docx"
    Outpath="../generated_doc.docx"
    demo=LilyDocTpl(MasterDocpath,SubDocpath,Outpath)
    context={
     "company_name":["World company",0],"sub_doc":[demo.SubDocpath,1]}
    demo.GetTplDocx(**context)


if __name__ == '__main__':
    main()

python技术交流可添加微信(添加微信请注明来意):
python使用docxtpl处理word文档图片不显示问题_第4张图片

你可能感兴趣的:(docxtpl处理图片资源,python,doc)