||
尽管参考 link1 和 link2 能够创建适合MS word的题注,并交叉引用。
但是在WPS中没法交叉引用。
关键是在题注区域加上书签。
而参考链接中的书签定义有点问题。
比如下面的例子
import docx from docx.oxml import OxmlElement bookmark_name='fig1' bookmark_text='图1' test = docx.Document() paragraph = test.add_paragraph() run = paragraph.add_run() tag = run._r # for reference the following also works: tag = document.element.xpath('//w:r')[-1] start = docx.oxml.shared.OxmlElement('w:bookmarkStart') start.set(docx.oxml.ns.qn('w:id'), '1') start.set(docx.oxml.ns.qn('w:name'), bookmark_name) tag.append(start) text = docx.oxml.OxmlElement('w:r') text.text = bookmark_text tag.append(text) end = docx.oxml.shared.OxmlElement('w:bookmarkEnd') end.set(docx.oxml.ns.qn('w:id'), '1') tag.append(end) test.save('Test_bookmark.docx') |
上面的代码中run._r是关键,它会把书签放在一个<w:r></w:r>中间。
用7z打开生成的Test_bookmark.docx,在word/document.xml中可以看到
用notepad把<w:r></w:r>去掉,
用wps打开,查看书签
能够看到定义的书签。
交叉引用时,
用alt+F9,生成一个空白域代码,
填入{ REF Fig1 \h }
刷新可以实现交叉引用
下面的代码完整,保存为bookmark.py
运行 python bookmark.py 即可
import docx from docx.oxml import OxmlElement from docx.oxml.ns import qn from docx.enum.text import WD_ALIGN_PARAGRAPH #书签锚点起始 def Bookmark_Start(Tag,index, Bookmark_Name): bmrk = OxmlElement('w:bookmarkStart') bmrk.set(qn('w:id'), str(index)) bmrk.set(qn('w:name'), Bookmark_Name) #return bmrk Tag.append(bmrk) #EndDef #书签锚点结束 def Bookmark_End(Tag,index): bmrk = OxmlElement('w:bookmarkEnd') bmrk.set(qn('w:id'), str(index)) #return bmrk Tag.append(bmrk) #EndDef #创建题注域代码: "图{ SEQ 图 \* ARABIC }" 或者 #创建题注域代码: "表{ SEQ 表 \* ARABIC }" def CaptionField(Tag,str0,index): #创建第1部分:"图" 或者 "表" text = OxmlElement('w:r') text.text = str0 text.set(qn('xml:space'), 'preserve') Tag.append(text) #创建第2部分:"{" r2 = OxmlElement('w:r') fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'begin') r2.append(fldChar) Tag.append(r2) #创建第3部分:" SEQ 图 \* ARABIC " 或者 " SEQ 表 \* ARABIC " r2 = OxmlElement('w:r') instrText = OxmlElement('w:instrText') instrText.text = ' SEQ '+str0+' \* ARABIC ' instrText.set(qn('xml:space'), 'preserve') r2.append(instrText) Tag.append(r2) #创建第4部分: r2 = OxmlElement('w:r') fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'separate') r2.append(fldChar) Tag.append(r2) #创建第5部分: r2 = OxmlElement('w:r') t = OxmlElement('w:t') t.text = str(index) r2.append(t) Tag.append(r2) #创建第6部分:"}" r2 = OxmlElement('w:r') fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'end') r2.append(fldChar) Tag.append(r2) #### #EndDef #创建图或表的题注 def InsertCaption(Doc,Bookmark_Name,Bookmark_Text,index,Caption): #创建段落 paragraph = Doc.add_paragraph() #段落居中 paragraph.alignment = WD_ALIGN_PARAGRAPH.CENTER #加个空格,防止在题注前回车,出现2行书签 text = OxmlElement('w:r') text.text = ' ' text.set(qn('xml:space'), 'preserve') paragraph._p.append(text) #书签的位置锚点 Tag=paragraph._p #书签开始 Bookmark_Start(Tag,index, Bookmark_Name) #创建题注域代码 CaptionField(Tag,Bookmark_Text,index) #书简结束 Bookmark_End(Tag,index) paragraph.add_run(" " + Caption) #EndDef #创建交叉引用的域代码:"{ REF Fig1 \h }" def ReferenceField(Tag,Bookmark_Name,Bookmark_Text,index): #创建第1部分:"{" r2 = OxmlElement('w:r') fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'begin') r2.append(fldChar) Tag.append(r2) #创建第2部分:" REF Fig1 \h ",其中Bookmark_Name是书签名称 r2 = OxmlElement('w:r') instrText = OxmlElement('w:instrText') instrText.text = ' REF ' + Bookmark_Name + ' \h ' r2.append(instrText) Tag.append(r2) #创建第3部分: r2 = OxmlElement('w:r') fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'separate') r2.append(fldChar) Tag.append(r2) #创建第4部分:" REF Fig1 \h ",其中Bookmark_Text是 引用的书签内容 r2 = OxmlElement('w:r') t = OxmlElement('w:t') t.text = Bookmark_Text + str(index) r2.append(t) Tag.append(r2) #创建第5部分:"}" r2 = OxmlElement('w:r') fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'end') r2.append(fldChar) Tag.append(r2) #EndDef def CrossReference(Doc,_Text,Bookmark_Name,Bookmark_Text,index): #创建段落 paragraph = Doc.add_paragraph() run = paragraph.add_run(_Text + "如") Tag = run._r ReferenceField(Tag,Bookmark_Name,Bookmark_Text,index) paragraph.add_run("所示。") #EndDef if __name__=='__main__': Doc = docx.Document() #对图1交叉引用 index=1 Bookmark_Name='Fig'+str(index) Bookmark_Text='图' _Text="第1个图" CrossReference(Doc,_Text,Bookmark_Name,Bookmark_Text,index) #对表1交叉引用 index=1 Bookmark_Name='Tab'+str(index) Bookmark_Text='表' _Text="第1个表" CrossReference(Doc,_Text,Bookmark_Name,Bookmark_Text,index) #创建图1题注 index=1 Bookmark_Name='Fig'+str(index) Bookmark_Text='图' Caption='随机参数分布' InsertCaption(Doc,Bookmark_Name,Bookmark_Text,index,Caption) #创建表1题注 index=1 Bookmark_Name='Tab'+str(index) Bookmark_Text='表' Caption='拟合结果' InsertCaption(Doc,Bookmark_Name,Bookmark_Text,index,Caption) Doc.save('Test3.Docx') #参考如下的 #https://www.yeahshecodes.com/python/using-python-Docx-create-word-Documents #https://github.com/python-openxml/python-Docx/issues/403 |
效果如下:
Archiver|手机版|科学网 ( 京ICP备07017567号-12 )
GMT+8, 2024-12-14 04:59
Powered by ScienceNet.cn
Copyright © 2007- 中国科学报社