slaon的个人博客分享 http://blog.sciencenet.cn/u/slaon

博文

[转载]python docx创建题注并交叉引用(WPS可用)

已有 788 次阅读 2022-6-7 00:30 |系统分类:科研笔记|文章来源:转载

尽管参考 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中可以看到

图片.png

用notepad把<w:r></w:r>去掉,

用wps打开,查看书签

图片.png

能够看到定义的书签。

交叉引用时,

用alt+F9,生成一个空白域代码,

填入{ REF Fig1 \h }

刷新可以实现交叉引用

图片.png

下面的代码完整,保存为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


效果如下:
图片.png



https://wap.sciencenet.cn/blog-531760-1341866.html

上一篇:[转载]python docx 加速创建大型表格
下一篇:cmd 批处理删除文件和文件夹
收藏 IP: 112.32.22.*| 热度|

该博文允许注册用户评论 请点击登录 评论 (0 个评论)

数据加载中...
扫一扫,分享此博文

Archiver|手机版|科学网 ( 京ICP备07017567号-12 )

GMT+8, 2022-12-5 22:51

Powered by ScienceNet.cn

Copyright © 2007- 中国科学报社

返回顶部