Search code examples
pythonpython-docx

Adding an hyperlink in MSWord by using python-docx


I am trying to add an hyperlink in a MS Word document using docx module for Python.

I searched everywhere (official doc, StackOverflow, Google) but found nothing.

I would like to do something like:

from docx import Document

document = Document()   

p = document.add_paragraph('A plain paragraph having some ')
p.add_hyperlink('Link to my site', target="http://supersitedelamortquitue.fr")

Anyone got an idea on how to do that?


Solution

  • Yes we can do it. Reference for the initial version

    import docx
    
    def add_hyperlink(paragraph, text, url):
        # 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 = docx.oxml.shared.OxmlElement('w:hyperlink')
        hyperlink.set(docx.oxml.shared.qn('r:id'), r_id, )
    
        # Create a new run object (a wrapper over a 'w:r' element)
        new_run = docx.text.run.Run(
            docx.oxml.shared.OxmlElement('w:r'), paragraph)
        new_run.text = text
    
        # Set the run's style to the builtin hyperlink style, defining it if necessary
        new_run.style = get_or_create_hyperlink_style(part.document)
        # Alternatively, set the run's formatting explicitly
        # new_run.font.color.rgb = docx.shared.RGBColor(0, 0, 255)
        # new_run.font.underline = True
    
        # Join all the xml elements together
        hyperlink.append(new_run._element)
        paragraph._p.append(hyperlink)
        return hyperlink
    
    document = docx.Document()
    p = document.add_paragraph('A plain paragraph having some ')
    add_hyperlink(p, 'Link to my site', "http://supersitedelamortquitue.fr")
    document.save('demo_hyperlink.docx')
    
    #This is only needed if you're using the builtin style above
    def get_or_create_hyperlink_style(d):
        """If this document had no hyperlinks so far, the builtin
           Hyperlink style will likely be missing and we need to add it.
           There's no predefined value, different Word versions
           define it differently.
           This version is how Word 2019 defines it in the
           default theme, excluding a theme reference.
        """
        if "Hyperlink" not in d.styles:
            if "Default Character Font" not in d.styles:
                ds = d.styles.add_style("Default Character Font",
                                        docx.enum.style.WD_STYLE_TYPE.CHARACTER,
                                        True)
                ds.element.set(docx.oxml.shared.qn('w:default'), "1")
                ds.priority = 1
                ds.hidden = True
                ds.unhide_when_used = True
                del ds
            hs = d.styles.add_style("Hyperlink",
                                    docx.enum.style.WD_STYLE_TYPE.CHARACTER,
                                    True)
            hs.base_style = d.styles["Default Character Font"]
            hs.unhide_when_used = True
            hs.font.color.rgb = docx.shared.RGBColor(0x05, 0x63, 0xC1)
            hs.font.underline = True
            del hs
    
        return "Hyperlink"