def insert_toc(self): paragraph = self.document.add_paragraph() run = paragraph.add_run() fldChar = OxmlElement('w:fldChar') # creates a new element fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element instrText = OxmlElement('w:instrText') instrText.set(qn('xml:space'), 'preserve') # sets attribute on element instrText.text = 'TOC \\o "1-3" \\h \\z \\u' # change 1-3 depending on heading levels you need fldChar2 = OxmlElement('w:fldChar') fldChar2.set(qn('w:fldCharType'), 'separate') # fldChar3 = OxmlElement('w:t') fldChar3 = OxmlElement('w:updateFields') fldChar3.set(qn('w:val'), 'true') # fldChar3.text = "Right-click to update field." fldChar2.append(fldChar3) fldChar4 = OxmlElement('w:fldChar') fldChar4.set(qn('w:fldCharType'), 'end') r_element = run._r r_element.append(fldChar) r_element.append(instrText) r_element.append(fldChar2) r_element.append(fldChar4) p_element = paragraph._p
def numerar(self): section = self.documento.sections[-1] sectPr = section._sectPr lnNumType = OxmlElement('w:lnNumType') lnNumType.set(qn('w:countBy'), '1') lnNumType.set(qn('w:restart'), 'newSection') sectPr.insert_element_before(lnNumType, 'w:cols')
def add_table_of_contents(document, label='Table of Contents'): document.add_heading(label, level=1) paragraph = document.add_paragraph() run = paragraph.add_run() fldChar = OxmlElement('w:fldChar') # creates a new element fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element instrText = OxmlElement('w:instrText') instrText.set(qn('xml:space'), 'preserve') # sets attribute on element instrText.text = r'TOC \o "1-3" \h \z \u' # change 1-3 depending on heading levels you need fldChar2 = OxmlElement('w:fldChar') fldChar2.set(qn('w:fldCharType'), 'separate') fldChar3 = OxmlElement('w:t') fldChar3.text = "Right-click to update field." fldChar2.append(fldChar3) fldChar4 = OxmlElement('w:fldChar') fldChar4.set(qn('w:fldCharType'), 'end') r_element = run._r r_element.append(fldChar) r_element.append(instrText) r_element.append(fldChar2) r_element.append(fldChar4) p_element = paragraph._p return document
def generate_pw_toc(document): global gl_font_size add_simple_par(document, "", gl_font_size, align=docx.enum.text.WD_ALIGN_PARAGRAPH.CENTER, bold=False, breakpar=True) document.add_heading("Spis treści", 1) paragraph = document.add_paragraph() run = paragraph.add_run() fldChar = OxmlElement('w:fldChar') # creates a new element fldChar.set(qn('w:fldCharType'), 'begin') # sets attribute on element instrText = OxmlElement('w:instrText') instrText.set(qn('xml:space'), 'preserve') # sets attribute on element instrText.text = 'TOC \\o "1-2" \\h \\z \\u' # change 1-3 depending on heading levels you need fldChar2 = OxmlElement('w:fldChar') fldChar2.set(qn('w:fldCharType'), 'separate') fldChar3 = OxmlElement('w:t') fldChar3.text = "Kliknij prawym klawiszem myszki, aby zaktualizować spis treści." fldChar2.append(fldChar3) fldChar4 = OxmlElement('w:fldChar') fldChar4.set(qn('w:fldCharType'), 'end') r_element = run._r r_element.append(fldChar) r_element.append(instrText) r_element.append(fldChar2) r_element.append(fldChar4) p_element = paragraph._p
def get_bookmark_parent(doc, bookmark_name): doc_element = doc.part.element bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart')) for bookmark in bookmarks_list: if bookmark.get(qn('w:name')) == bookmark_name: return bookmark.getparent() return None
def set_row_height(row): tr = row._tr trPr = tr.get_or_add_trPr() trHeight = OxmlElement('w:trHeight') trHeight.set(qn('w:val'), "250") trHeight.set(qn('w:hRule'), "atLeast") trPr.append(trHeight)
def set_table_margins(self, tbl, width: dict = None): """ <w:tbl> <w:tblPr> <w:tblStyle w:val="LightShading"/> <w:tblW w:type="auto" w:w="0"/> <w:tblCellMar> <w:left w:type="dxa" w:w="63"/> <w:right w:type="dxa" w:w="63"/> </w:tblCellMar> <w:tblLook w:firstColumn="1" w:firstRow="1" w:lastColumn="0" w:lastRow="0" w:noHBand="0" w:noVBand="1" w:val="04A0"/> </w:tblPr> """ # noqa # 67 = Cm(0.11) ...? if width is None: width = dict(left=67, right=67) margins = OxmlElement('w:tblCellMar') for side, w in width.items(): margin = OxmlElement(f'w:{side}') margin.set(qn('w:w'), str(w)) margin.set(qn('w:type'), 'dxa') margins.append(margin) tbl._tbl.tblPr.append(margins)
def add_hyperlink(paragraph, url, text, color='0000FF', underline=True): """ places a hyperlink within a paragraph object """ part = paragraph.part r_id = part.relate_to(url, RELATIONSHIP_TYPE.HYPERLINK, is_external=True) hyperlink = OxmlElement('w:hyperlink') hyperlink.set( qn('r:id'), r_id, ) new_run = OxmlElement('w:r') rPr = OxmlElement('w:rPr') if color is not None: c = OxmlElement('w:color') c.set(qn('w:val'), color) rPr.append(c) if not underline: u = OxmlElement('w:u') u.set(qn('w:val'), 'none') rPr.append(u) # Join all the xml elements together add add the required text to the w:r element new_run.append(rPr) new_run.text = text hyperlink.append(new_run) paragraph._p.append(hyperlink) return hyperlink
def add_hyperlink(paragraph, url, text, font_name=None, underline_hyperlink=True, indent=0, color=True): """ A function that places a hyperlink within a paragraph object. :param paragraph: The paragraph we are adding the hyperlink to. :param url: A string containing the required url :param text: The text displayed for the url :return: A Run object containing the hyperlink """ # This gets access to the document.xml.rels file and gets a new relation id value part = paragraph.part r_id = part.relate_to(url, RT.HYPERLINK, is_external=True) # Create the w:hyperlink tag and add needed values hyperlink = OxmlElement('w:hyperlink') hyperlink.set( qn('r:id'), r_id, ) hyperlink.set(qn('w:history'), '1') # Create a w:r element new_run = OxmlElement('w:r') # Create a new w:rPr element rPr = OxmlElement('w:rPr') # Create a w:rStyle element, note this currently does not add the hyperlink style as its not in # the default template, I have left it here in case someone uses one that has the style in it rStyle = OxmlElement('w:rStyle') rStyle.set(qn('w:val'), 'Hyperlink') # Join all the xml elements together add add the required text to the w:r element rPr.append(rStyle) new_run.append(rPr) new_run.text = text hyperlink.append(new_run) # Create a new Run object and add the hyperlink into it r = paragraph.add_run() r.font.name = font_name r._r.append(hyperlink) # A workaround for the lack of a hyperlink style (doesn't go purple after using the link) # Delete this if using a template that has the hyperlink style in it if color: r.font.color.theme_color = MSO_THEME_COLOR_INDEX.HYPERLINK r.font.underline = underline_hyperlink return r
def add_tbl_border(self, tbl): """Add table bottom border with OxmlElement""" borders = OxmlElement('w:tblBorders') bottom_border = OxmlElement('w:bottom') bottom_border.set(qn('w:val'), 'single') bottom_border.set(qn('w:sz'), '4') borders.append(bottom_border) tbl._tbl.tblPr.append(borders)
def set_cell_color(cell, color): # https://github.com/python-openxml/python-docx/issues/55 tc = cell._tc tcPr = tc.tcPr color_xml = OxmlElement('w:shd') color_xml.set(qn('w:val'), 'clear') # color_xml.set(qn('w:color'), text) color_xml.set(qn('w:fill'), color) tcPr.append(color_xml)
def start_search(element, title): result = [] if element.tag == qn('w:bookmarkStart'): if element.get(qn('w:name')) == title: result.append(element.get(qn('w:name'))) result.append(element.get(qn('w:id'))) return result
def indent_table(table, indent): # noinspection PyProtectedMember tbl_pr = table._element.xpath( 'w:tblPr') # récupération de l'élément XML de la table if tbl_pr: e = OxmlElement( 'w:tblInd') # création d'un element XML pour l'indentation e.set(qn('w:w'), str(indent)) # set de la valeur e l'indentation e.set(qn('w:type'), 'dxa') # type de l'indentation tbl_pr[0].append(e) # ajout de l'elment XML à celui de la table
def autofit_table_window(self, tbl): """ <w:tbl> <w:tblPr> <w:tblW w:type="pct" w:w="5000"/> """ width = OxmlElement('w:tblW') width.set(qn('w:type'), 'pct') width.set(qn('w:w'), '5000') tbl._tbl.tblPr.append(width)
def end_search(element, bookmark): result = [] if element.tag == qn('w:bookmarkEnd'): if element.get(qn('w:id')) == bookmark[1]: result.append('Is found') if element.tag == qn('w:bookmarkStart'): result.append('w:bookmarkStart') return result
def set_cell_color(self, cell, bg=None, text=None): """Set table cell bg and text color""" cell_pr = cell._element.tcPr cl_shading = OxmlElement('w:shd') if bg: cl_shading.set(qn('w:fill'), bg) if text: cl_shading.set(qn('w:color'), text) cell_pr.append(cl_shading)
def runs(self): """ Sequence of |Run| instances corresponding to the <w:r> elements in this paragraph. """ lst = [Run(r, self) for r in self._p.r_lst] for hl in self._p: if hl.tag == qn('w:hyperlink'): for r in hl: if r.tag == qn('w:r'): lst.append(Run(r, self)) return lst
def docx_insert_word_files(main_doc, sub_doc, var_dest): try: for p in main_doc.element.body.findall('.//' + qn('w:p')): if re.search( var_dest, ''.join([t.text for t in p.findall('.//' + qn('w:t'))])): p.clear() print("Insert word file at: {0} ".format(var_dest)) for element in sub_doc.element.body: p.addprevious(element) except Exception as e: print(e) return main_doc
def addMetadata(p, text): # colored small text r = p.add_run(text) rPr = r._r.get_or_add_rPr() rStyle = OxmlElement('w:color') rStyle.set(qn('w:val'), '888888') rPr.insert(0, rStyle) rStyle = OxmlElement('w:sz') rStyle.set(qn('w:val'), '18') rPr.insert(0, rStyle) rStyle = OxmlElement('w:szCs') rStyle.set(qn('w:val'), '18') rPr.insert(1, rStyle)
def add_fig_caption(self, paragraph): """Add figure caption to image with auto updating numbers - User must select all (cmd/ctrl + A), then F9 to update fig captions""" run = paragraph.add_run() r = run._r fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'begin') r.append(fldChar) instrText = OxmlElement('w:instrText') instrText.text = ' SEQ Figure \* ARABIC' # noqa r.append(instrText) fldChar = OxmlElement('w:fldChar') fldChar.set(qn('w:fldCharType'), 'end') r.append(fldChar)
def add_hyperlink(paragraph, url, text): """ A function that places a hyperlink within a paragraph object. Parameters ---------- paragraph: The paragraph we are adding the hyperlink to. url: A string containing the required url text: The text displayed for the url Returns ------- hyperlink: hyperlink object """ # This gets access to the document.xml.rels file and gets a new relation id value part = paragraph.part r_id = part.relate_to(url, docx.opc.constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True) # Create the w:hyperlink tag and add needed values hyperlink = OxmlElement("w:hyperlink") hyperlink.set(qn("r:id"), r_id) # Create a w:r element new_run = OxmlElement("w:r") # Create a new w:rPr element rPr = OxmlElement("w:rPr") # Style it c = OxmlElement("w:color") c.set(qn("w:val"), "4F81BD") rPr.append(c) u = OxmlElement("w:u") u.set(qn("w:val"), "none") rPr.append(u) # Join all the xml elements together add add the required text to the w:r element new_run.append(rPr) new_run.text = text hyperlink.append(new_run) paragraph._p.append(hyperlink) return hyperlink
def cellStyle(self, cells, background): self.make_rows_bold(cells) for cell in cells: tcPr = cell._tc.get_or_add_tcPr() tcVAlign = OxmlElement("w:shd") tcVAlign.set(qn("w:fill"), background) tcPr.append(tcVAlign)
def set_row_height(table, begin, end, ratio): # 表格元素、起始行、终止行、行占原图比例 try: for row in range(begin, end): row = table.rows[row] tr = row._tr trPr = tr.get_or_add_trPr() trHeight = OxmlElement('w:trHeight') trHeight.set(qn('w:val'), str(int( ratio * 13000))) # 13000为在纸张21.5*27.9cm, 上下距离25.4mm时页面设置最大值 # trHeight.set(qn('w:val'), str(30)) # 强制最小 根据cell内容自适应 trHeight.set(qn('w:hRule'), "atLeast") trPr.append(trHeight) except Exception as ex: print('set_row_height', ex)
def val(self): """ The underline type corresponding to the ``w:val`` attribute value. """ underline_type_map = { None: None, 'none': False, 'single': True, 'words': WD_UNDERLINE.WORDS, 'double': WD_UNDERLINE.DOUBLE, 'dotted': WD_UNDERLINE.DOTTED, 'thick': WD_UNDERLINE.THICK, 'dash': WD_UNDERLINE.DASH, 'dotDash': WD_UNDERLINE.DOT_DASH, 'dotDotDash': WD_UNDERLINE.DOT_DOT_DASH, 'wave': WD_UNDERLINE.WAVY, 'dottedHeavy': WD_UNDERLINE.DOTTED_HEAVY, 'dashedHeavy': WD_UNDERLINE.DASH_HEAVY, 'dashDotHeavy': WD_UNDERLINE.DOT_DASH_HEAVY, 'dashDotDotHeavy': WD_UNDERLINE.DOT_DOT_DASH_HEAVY, 'wavyHeavy': WD_UNDERLINE.WAVY_HEAVY, 'dashLong': WD_UNDERLINE.DASH_LONG, 'wavyDouble': WD_UNDERLINE.WAVY_DOUBLE, 'dashLongHeavy': WD_UNDERLINE.DASH_LONG_HEAVY, } val = self.get(qn('w:val')) return underline_type_map[val]
def add_url_hyperlink(paragraph, url: str, text: str): """Add URL hyperlink in docx report. Adapted from https://stackoverflow.com/a/47666747/906385 Args: paragraph: a docx paragraph object url (str): The URL text (str): The text to display """ # This gets access to the document.xml.rels file and gets a new relation id value part = paragraph.part r_id = part.relate_to(url, constants.RELATIONSHIP_TYPE.HYPERLINK, is_external=True) # Create the w:hyperlink tag and add needed values hyperlink = OxmlElement("w:hyperlink") hyperlink.set(qn("r:id"), r_id) # Create a w:r element and a new w:rPr element new_run = OxmlElement("w:r") rPr = OxmlElement("w:rPr") # Join all the xml elements together add add the required text to the w:r element new_run.append(rPr) new_run.text = text hyperlink.append(new_run) # Create a new Run object and add the hyperlink into it run = paragraph.add_run() run._r.append(hyperlink) # A workaround for the lack of a hyperlink style (doesn't go purple after using the link) # Delete this if using a template that has the hyperlink style in it run.font.color.theme_color = dml.MSO_THEME_COLOR_INDEX.HYPERLINK run.font.underline = True
def set_cant_split(self, row): tr = row._tr trPr = tr.get_or_add_trPr() tblHeader = OxmlElement('w:cantSplit') tblHeader.set(qn('w:val'), "true") trPr.append(tblHeader) return row
def get_bookmark_par_element(document, bookmark_name): """ Return the named bookmark parent paragraph element. If no matching bookmark is found, the result is '1'. If an error is encountered, '2' is returned. """ doc_element = document._body._element bookmarks_list = doc_element.findall('.//' + qn('w:bookmarkStart')) for bookmark in bookmarks_list: name = bookmark.get(qn('w:name')) if name == bookmark_name: par = bookmark.getparent() if not isinstance(par, docx.oxml.CT_P): return 2 else: return par return 1
def set_shade_cell(cell, shade): tcpr = cell._tc.get_or_add_tcPr( ) # récupération de lélément XML correspondant à la cellule tcvalign = OxmlElement( "w:shd") # création d'un élément XML pour le background tcvalign.set(qn("w:fill"), shade) # set de la valeur de la vcouleur de fond tcpr.append(tcvalign) # ajout de l'élement XML à la cellule
def remove_border(self, row, border=0): for cell in row: tcPr = cell.tcPr tcBorders = OxmlElement('w:tcBorders') top = OxmlElement('w:top') top.set(qn('w:val'), 'nil') left = OxmlElement('w:left') left.set(qn('w:val'), 'nil') bottom = OxmlElement('w:bottom') bottom.set(qn('w:val'), 'nil') bottom.set(qn('w:sz'), '4') bottom.set(qn('w:space'), '0') bottom.set(qn('w:color'), 'auto') right = OxmlElement('w:right') right.set(qn('w:val'), 'nil') if border == 1: tcBorders.append(top) if border == 2: tcBorders.append(bottom) if border == 0: tcBorders.append(top) tcBorders.append(bottom) tcPr.append(tcBorders)
def add_t(self, text): """ Return a newly added CT_T (<w:t>) element containing *text*. """ t = CT_Text.new(text) if len(text.strip()) < len(text): t.set(qn('xml:space'), 'preserve') self.append(t) return t
def style(self): """ String contained in <w:pStyle> child, or None if that element is not present. """ pStyle = self.pStyle if pStyle is None: return None return pStyle.get(qn('w:val'))
def first_child_found_in(self, *tagnames): """ Return the first child found with tag in *tagnames*, or None if not found. """ for tagname in tagnames: child = self.find(qn(tagname)) if child is not None: return child return None
def new(cls, num_id, abstractNum_id): """ Return a new ``<w:num>`` element having numId of *num_id* and having a ``<w:abstractNumId>`` child with val attribute set to *abstractNum_id*. """ abstractNumId = CT_DecimalNumber.new( 'w:abstractNumId', abstractNum_id ) num = OxmlElement('w:num', {qn('w:numId'): str(num_id)}) num.append(abstractNumId) return num
def test_footnoterefs(): run = DOC.paragraphs[4].runs[1] assert_equals(run.text, '') _footnoteref = run._r[1] assert_equals(_footnoteref.tag, qn('w:footnoteReference')) assert_equals(type(_footnoteref), CT_FootnoteReference) assert_equals(_footnoteref.id, 2) footnoterefs = run.footnote_references assert_true(footnoterefs) assert_equals(len(footnoterefs), 1) assert_equals(type(footnoterefs[0]), FootnoteReference) assert_equals(footnoterefs[0].id, _footnoteref.id)
def test_endnoterefs(): run = DOC.paragraphs[2].runs[1] assert_equals(run.text, '') _endnoteref = run._r[1] assert_equals(_endnoteref.tag, qn('w:endnoteReference')) assert_equals(type(_endnoteref), CT_EndnoteReference) assert_equals(_endnoteref.id, 2) endnoterefs = run.endnote_references assert_true(endnoterefs) assert_equals(len(endnoterefs), 1) assert_equals(type(endnoterefs[0]), EndnoteReference) assert_equals(endnoterefs[0].id, _endnoteref.id)
def iter_all_paragraphs(document, start=None, end=None): ''' Optional parameters start and end cause the itertor to skip until the element matches start and quits after element matches end. The range is inclusive of start and end. This iterator sets the parent of the Paragraph as the parent of the element rather than the proxy object for the parent element. It doesn't seem to matter since all parent operations are done through the element rather than the proxy object. ''' # Uses lxml query to find all, including in tables. start_found = start is None for p in document._body._element.findall('.//'+qn('w:p')): if start_found or p == start: start_found = True yield docx.text.paragraph.Paragraph(p, p.getparent()) else: continue if end is not None and p == end: break
def val(self, value): underline_vals = { True: 'single', False: 'none', WD_UNDERLINE.WORDS: 'words', WD_UNDERLINE.DOUBLE: 'double', WD_UNDERLINE.DOTTED: 'dotted', WD_UNDERLINE.THICK: 'thick', WD_UNDERLINE.DASH: 'dash', WD_UNDERLINE.DOT_DASH: 'dotDash', WD_UNDERLINE.DOT_DOT_DASH: 'dotDotDash', WD_UNDERLINE.WAVY: 'wave', WD_UNDERLINE.DOTTED_HEAVY: 'dottedHeavy', WD_UNDERLINE.DASH_HEAVY: 'dashedHeavy', WD_UNDERLINE.DOT_DASH_HEAVY: 'dashDotHeavy', WD_UNDERLINE.DOT_DOT_DASH_HEAVY: 'dashDotDotHeavy', WD_UNDERLINE.WAVY_HEAVY: 'wavyHeavy', WD_UNDERLINE.DASH_LONG: 'dashLong', WD_UNDERLINE.WAVY_DOUBLE: 'wavyDouble', WD_UNDERLINE.DASH_LONG_HEAVY: 'dashLongHeavy', } val = underline_vals[value] self.set(qn('w:val'), val)
def webHidden(self): """ First ``<w:webHidden>`` child element or None if none are present. """ return self.find(qn('w:webHidden'))
def vanish(self): """ First ``<w:vanish>`` child element or None if none are present. """ return self.find(qn('w:vanish'))
def strike(self): """ First ``<w:strike>`` child element or None if none are present. """ return self.find(qn('w:strike'))
def snapToGrid(self): """ First ``<w:snapToGrid>`` child element or None if none are present. """ return self.find(qn('w:snapToGrid'))
def smallCaps(self): """ First ``<w:smallCaps>`` child element or None if none are present. """ return self.find(qn('w:smallCaps'))
def remove_rtl(self): rtl_lst = self.findall(qn('w:rtl')) for rtl in rtl_lst: self.remove(rtl)
def remove_vanish(self): vanish_lst = self.findall(qn('w:vanish')) for vanish in vanish_lst: self.remove(vanish)
def remove_webHidden(self): webHidden_lst = self.findall(qn('w:webHidden')) for webHidden in webHidden_lst: self.remove(webHidden)
def remove_specVanish(self): specVanish_lst = self.findall(qn('w:specVanish')) for specVanish in specVanish_lst: self.remove(specVanish)
def remove_oMath(self): oMath_lst = self.findall(qn('w:oMath')) for oMath in oMath_lst: self.remove(oMath)
def remove_snapToGrid(self): snapToGrid_lst = self.findall(qn('w:snapToGrid')) for snapToGrid in snapToGrid_lst: self.remove(snapToGrid)
def remove_smallCaps(self): smallCaps_lst = self.findall(qn('w:smallCaps')) for smallCaps in smallCaps_lst: self.remove(smallCaps)
def remove_shadow(self): shadow_lst = self.findall(qn('w:shadow')) for shadow in shadow_lst: self.remove(shadow)
def pPr(self): """ ``<w:pPr>`` child element or None if not present. """ return self.find(qn('w:pPr'))
def rtl(self): """ First ``<w:rtl>`` child element or None if none are present. """ return self.find(qn('w:rtl'))
def r_lst(self): """ Sequence containing a reference to each run element in this paragraph. """ return self.findall(qn('w:r'))
def shadow(self): """ First ``<w:shadow>`` child element or None if none are present. """ return self.find(qn('w:shadow'))
def remove_strike(self): strike_lst = self.findall(qn('w:strike')) for strike in strike_lst: self.remove(strike)
def remove_outline(self): outline_lst = self.findall(qn('w:outline')) for outline in outline_lst: self.remove(outline)