ROA*_*OAR 3 python python-docx
我\xe2\x80\x99m 试图完成的任务:
\n\n问题:
\n\n我可以使用非 CTL 语言(例如英语)来执行此操作:
\n\nfrom docx import Document\nfrom docx.enum.style import WD_STYLE_TYPE\nfrom docx.shared import Pt\n\nuser_font_name = 'FreeMono'\nuser_font_size = 14\n\ndoc = Document()\nmy_style = doc.styles.add_style('style_name',WD_STYLE_TYPE.PARAGRAPH)\nmy_font = my_style.font\nmy_font.name = user_font_name\nmy_font.size = Pt(user_font_size)\np = doc.add_paragraph('some text',my_style)\n\n# persian_p = doc.add_paragraph('\xd9\x86\xd9\x88\xd8\xb4\xd8\xaa\xd9\x87',my_style)\n# FreeMono supports Persian language so the problem is not the font\n\ndoc.save('file.docx')\nRun Code Online (Sandbox Code Playgroud)但是,如果我将文本更改为波斯语文本,其字体将\xe2\x80\x99t 更改为指定字体。
为什么会发生这种情况:
\n\n我怎么知道这一点:
\n\n附加信息:
\n\n经过几个小时的研究 docx 文件后,我惊恐地意识到答案就在文档的 style.xml 文件中。Here\xe2\x80\x99s 是一种为有类似问题的人修复它的方法:
\n\n文本方向问题:
\n\n字体改变问题的xml解释:
\n\n更改了默认样式的文档在其 style.xml 文件中显示了一些不同的内容。\n在“w:rPr”下的普通段落样式中,您可以看到有一个附加的“w:szCs”,用于确定复杂脚本的大小字体(您可以通过更改 style.font.size\xe2\x80\x99t 进行更改),并且在“w:rFonts”中,“cs”的值现在是我指定的波斯字体。另外,“w:lang”值 \xe2\x80\x9cbidi\xe2\x80\x9d 现在为 \xe2\x80\x9cfa-IR\xe2\x80\x9d(对于波斯语)。这里\xe2\x80\x99s是我\xe2\x80\x99m谈论的xml部分:
\n\n<w:rPr>\n<w:rFonts w:ascii="FreeMono" w:hAnsi="FreeMono" w:cs="FreeFarsi"/>\n<w:sz w:val="40"/>\n<w:rtl/>\n<w:cs/>\n<w:szCs w:val="40"/>\n<w:lang w:val="en-Us" w:bidi="fa-IR"/>\n</w:rPr>\nRun Code Online (Sandbox Code Playgroud)现在更改 style.font.size 只会更改“sz”值(西方字体大小),并且不会对“szCs”值(cs 字体大小)执行任何操作。同样,style.font.name 仅更改“w:rFonts”的“ascii”和“hAnsi”值,并且不对“cs”值执行任何操作。因此,要更改这些值,我必须更改 python 中的样式元素。
解决方案:
\n\nfrom docx import Document\nfrom docx.shared import Pt\n\n#path to doc with altered style:\nbase_doc_location = \'base.docx\'\ndoc = Document(base_doc_location)\nmy_style = doc.styles[\'Normal\']\n\n# define your desired fonts\nuser_cs_font_size = 16\nuser_cs_font_name = \'FreeFarsi\'\nuser_en_font_size = 12\nuser_en_font_name = \'FreeMono\'\n\n# get <w:rPr> element of this style\nrpr = my_style.element.rPr\n\n#==================================================\n\'\'\'This probably isn\'t necessary if you already\nhave a document with altered style, but just to be\nsafe I\'m going to add this here\'\'\'\n\nif rpr.rFonts is None:\n rpr._add_rFonts()\nif rpr.sz is None:\n rpr._add_sz()\n#==================================================\n\n\'\'\'Get the nsmap string for rpr. This is that "w:"\nat the start of elements and element values in xml.\nLike these:\n <w:rPr>\n <w:rFonts>\n w:val\n\nThe nsmap is like a url:\nhttp://schemas.openxmlformats.org/...\n\nNow w:rPr translates to:\n{nsmap url string}rPr\n\nSo I made the w_nsmap string like this:\'\'\'\n\nw_nsmap = \'{\'+rpr.nsmap[\'w\']+\'}\'\n#==================================================\n\n\'\'\'Because I didn\'t find any better ways to get an\nelement based on its tag here\'s a not so great way\nof getting it:\n\'\'\'\nszCs = None\nlang = None\n\nfor element in rpr:\n if element.tag == w_nsmap + \'szCs\':\n szCs = element\n elif element.tag == w_nsmap + \'lang\':\n lang = element\n\n\'\'\'if there is a szCs and lang element in your style\nthose variables will be assigned to it, and if not\nwe make those elements and add them to rpr\'\'\'\n\nif szCs is None:\n szCs = rpr.makeelement(w_nsmap+\'szCs\',nsmap=rpr.nsmap)\nif lang is None:\n lang = rpr.makeelement(w_nsmap+\'lang\',nsmap =rpr.nsmap)\n\nrpr.append(szCs)\nrpr.append(lang)\n#==================================================\n\n\'\'\'Now to set our desired values to these elements\nwe have to get attrib dictionary of these elements\nand set the name of value as key and our value as\nvalue for that dict\'\'\'\n\nszCs_attrib = szCs.attrib\nlang_attrib = lang.attrib\nrFonts_atr = rpr.rFonts.attrib\n\n\'\'\'sz and szCs values are string values and 2 times\nthe font size so if you want font size to be 11 you\nhave to set sz (for western fonts) or szCs (for CTL\nfonts) to "22" \'\'\'\nszCs_attrib[w_nsmap+\'val\'] =str(int(user_cs_font_size*2))\n\n\'\'\'Now to change cs font and bidi lang values\'\'\'\nrFonts_atr[w_nsmap+\'cs\'] = user_cs_font_name\nlang_attrib[w_nsmap+\'bidi\'] = \'fa-IR\' # For Persian\n#==================================================\n\n\'\'\'Because we changed default style we don\'t even\nneed to set style every time we add a new paragraph\nAnd if you change font name or size the normal way\nit won\'t change these cs values so you can have a\nfont for CTL language and a different font for\nwestern language\n\'\'\'\npersian_p = doc.add_paragraph(\'\xd9\x86\xd9\x88\xd8\xb4\xd8\xaa\xd9\x87\')\nen_font = my_style.font\nen_font.name = user_en_font_name\nen_font.size = Pt(user_en_font_size)\nenglish_p = doc.add_paragraph(\'some text\')\n\ndoc.save(\'ex.docx\')\nRun Code Online (Sandbox Code Playgroud)\n\n编辑(代码改进):
\n我评论了可以使用一些改进的行,并将更好的行放在它们下面。
#rpr = my_style.element.rPr # If None it\'ll throw errors later\nrpr = my_style.element.get_or_add_rPr() # this avoids potential errors\n#if rpr.rFonts is None:\n# rpr._add_rFonts()\nrFonts = rpr.get_or_add_rFonts()\n#if rpr.sz is None:\n# rpr._add_sz()\nrpr.get_or_add_sz()\n\n#by importing these you can make elements and set values quicker\nfrom docx.oxml.shared import OxmlElement, qn\n#szCs = rpr.makeelement(w_nsmap+\'szCs\',nsmap=rpr.nsmap)\nszCs = OxmlElement(\'w:szCs\')\n#lang = rpr.makeelement(w_nsmap+\'lang\',nsmap =rpr.nsmap)\nlang = OxmlElement(\'w:lang\')\n\n#szCs_attrib = szCs.attrib\n#lang_attrib = lang.attrib\n#rFonts_atr = rpr.rFonts.attrib\n#szCs_attrib[w_nsmap+\'val\'] =str(int(user_cs_font_size*2))\n#rFonts_atr[w_nsmap+\'cs\'] = user_cs_font_name\n#lang_attrib[w_nsmap+\'bidi\'] = \'fa-IR\'\n\nszCs.set(qn(\'w:val\'),str(int(user_cs_font_size*2)))\nlang.set(qn(\'w:bidi\'),\'fa-IR\')\nrFonts.set(qn(\'w:cs\'),user_cs_font_name)\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
2284 次 |
| 最近记录: |