Skip to main content
Question

Write hyperlinks to Word document with pyhon docx in PythonCaller

  • Nov 23, 2022 10:25 AM UTC
  • 5 replies
  • 3042 views

egge
Contributor
Forum|alt.badge.img+14

Hi,

 

I would like to share a solution to an issue I had, just to hear what you think about it. The challenge is: to create hyperlinks in a Word document.

FME allows you, with the use of MSWordStyler transformers, to create a Word document in a very versatile and easy manner. These transformers, however, do not allow you to insert hyperlinks into the doc.

Please see the attached zip file hyperlinks-to-word-python-docx.zip for a workflow where the document is created using MSWordStylers, followed by some post-processing with a PythonCaller to insert the hyperlinks: POIs with a link to Google Maps, in this case.

No, I did not write all of the Python script myself, hell, no! I used some existing bits and pieces and tweaked them a little bit to get the job done.

The add_hyperlink function was found on github and the docx_find_replace_text one on stackoverflow and I only modified them slightly to work together to replace my search text, the POI name, with a clickable hyperlink. More than 150 lines of code... but it gets the job done.

 

What do you think? Any comments and test results are appreciated.

 

Cheers,

 

Egge-Jan

 

Edit 2024-04-05: just noted today that the attachment to this post has disappeared with the transfer to the new community environment. I have added it again, this time in a zip file.

5 replies

itsmatt
Celebrity
Forum|alt.badge.img+48
  • Celebrity
  • Nov 23, 2022 2:47 PM UTC

Awesome thanks for sharing - you should definitely make this into a CustomTransformer!


ebygomm
Evangelist
Forum|alt.badge.img+54
  • Evangelist
  • Nov 28, 2022 4:50 PM UTC

Nice!

 

Probably slightly more efficient to build lists of the POI and the replacement links and send that into the python caller and then do something like this

docx_file_path=feature.getAttribute('_dataset')
        document=docx.Document(docx_file_path)
        replace_list = list(zip(feature.getAttribute('_list{}.POI'),feature.getAttribute('_list{}.Link')))
        #search_text=feature.getAttribute('POI')
        #replace_text=feature.getAttribute('Link')
        for search_text,replace_text in replace_list:
            docx_find_replace_text(document, search_text, replace_text)
        document.save(docx_file_path)

 

 


egge
Contributor
Forum|alt.badge.img+14
  • Author
  • Contributor
  • Nov 28, 2022 5:06 PM UTC

Nice!

 

Probably slightly more efficient to build lists of the POI and the replacement links and send that into the python caller and then do something like this

docx_file_path=feature.getAttribute('_dataset')
        document=docx.Document(docx_file_path)
        replace_list = list(zip(feature.getAttribute('_list{}.POI'),feature.getAttribute('_list{}.Link')))
        #search_text=feature.getAttribute('POI')
        #replace_text=feature.getAttribute('Link')
        for search_text,replace_text in replace_list:
            docx_find_replace_text(document, search_text, replace_text)
        document.save(docx_file_path)

 

 

Thanks for the suggestion. Yeah, in this example we are only talking 3 features, but when this number increases your list-approach might indeed be more efficient. Will have a look into it... when time permits...


egge
Contributor
Forum|alt.badge.img+14
  • Author
  • Contributor
  • Dec 12, 2022 3:24 PM UTC

Nice!

 

Probably slightly more efficient to build lists of the POI and the replacement links and send that into the python caller and then do something like this

docx_file_path=feature.getAttribute('_dataset')
        document=docx.Document(docx_file_path)
        replace_list = list(zip(feature.getAttribute('_list{}.POI'),feature.getAttribute('_list{}.Link')))
        #search_text=feature.getAttribute('POI')
        #replace_text=feature.getAttribute('Link')
        for search_text,replace_text in replace_list:
            docx_find_replace_text(document, search_text, replace_text)
        document.save(docx_file_path)

 

 

Hi @ebygomm​ ,

I have had a look at your suggestion and updated the workspace accordingly. Please see fmwt (version 2) attached. Now a list is created before the PythonCaller is called. In this way there is only the need to process 1 feature, instead of multiple, in the Python script.

Cheers,

Egge-Jan

 


egge
Contributor
Forum|alt.badge.img+14
  • Author
  • Contributor
  • Apr 5, 2024 4:24 PM UTC

Hmmm, just noted today that the original attachment to this post, a Template (*.fmwt file) has disappeared from this post with the transfer to the new community environment. 😕

I have added the example again, both the workspace and an input csv file, but in a zip file this time. See the original, edited post above. 🙂

Cheers,

Egge-Jan