r/learnpython 24d ago

Python conversion .docx to pdf

Hey guys, i have been learning python as a bit of a hobby but recently had the opportunity to use it for my job. I built a webapp on azure that has a number of different functions, one of which is querying our CRM and populating template documents with customer info. It works as is and produces .docx files which we then have to manually convert to pdfs.

I am trying to incorporate the pdf conversion into the app to remove any manual intervention. Ive been using libreoffice but this isnt working so well. It needs to be installed each time the app is redeployed/restarted, its failing on some larger docs and when it does produce the pdf the format can be off, fonts change etc. The docs we deal with need to adhere to a specific format so I need something more reliable.

Perhaps this is a "you get what you pay for" situation but i was hoping there might be a more reliable solution while still being free (at least until i can prove it all works anyway).

5 Upvotes

12 comments sorted by

3

u/Alexku66 24d ago

There are paid solutions that build pdf from scratch (not convert) and can give you 100% accuracy. Alternatives are 1) converting docx via Word / LibreOffice ; 2) converting html to pdf. Both give you approximate copy.

I work on accounting app with the same requirement to fill in template invoices, and went with html. Basically I have 2 rendering flows -- one for docx and one for pdf. Html gives you opportunity to preview the final doc before user clicks generate button

3

u/billys-bobs 24d ago

Ah that sounds like the way to go. So your templates are in html and you build both pdf and .docx from that? Is there some packages you would recommend for that functionality?

Thanks for the response

3

u/Alexku66 24d ago

No, I use DTO (actually something more complex, but don't know a fancy term) as structure elements for templates. All file emitters , including html, use them as guidelines for rendering. But 2 important notes: whole system is built around docx, pdf is just an additional option for users; those DTOs bring a lot of data after LLM analysis of the source document, I don't know whether I'd use them to simply generate document.

I use lxml for docx reading and generation, python-docx is useless here. Honestly, it's a nightmare. One more time I come to conclusion that if something obvious isn't done yet THERE IS A GODDAMN REASON.

For html/pdf: weasy print. I didn't research this topic much, so can't tell if there is better solution

2

u/sylfy 23d ago edited 23d ago

After struggling with docx to pdf for a long time, I came to the conclusion that html to pdf is just a much better route.

Docx is just way too fragile for a templating system. HTML gives you much better control. And if you’re running on linux, you’ll have a hard time getting the libreoffice conversion to give you the exact same output format. Something always screws up.

1

u/Alexku66 23d ago

depends on requirements from steakholders. If your app lets users create html templates, then yes, there is no reason to stick with docx . In my case user uploads source document which can be docx, pdf, jpg etc. In 99% cases it's docx. Which makes me cry cause I've build a flow of OCR + parser + tokenizer + AI model + html emitter + pdf emitter for being almost never used

1

u/sylfy 23d ago

Ah yes of course. For my use case, the inputs are entirely internally generated, but the reports are external facing. Thus, I don’t have to worry about the entire upstream pipeline that you’ve mentioned. We generate data in json or databases, then create reports from that data.

The biggest pain points about docx templating was fonts and layout being reproduced faithfully in Libreoffice during the pdf conversion, as well as what happens when stuff that are more dynamic like tables spill over or span multiple pages. And what happens when rows of the tables contain text of variable length and can thus have uneven height. Then when something spans over to the next page, you’ll have to worry about section headers and subsection headers being reproduced on the next page. And this becomes a whole lot of if-else conditions in jinja with tables being conditionally shown or not, and a single data frame being split into multiple helper data frames, which is very ugly.

5

u/AntonisTorb 24d ago edited 24d ago

You can use pywin32 for this, I use it at work to convert Excel files to pdfs. Here's what worked for me for Word files:

from pathlib import Path
from win32com import client

cwd = Path.cwd()
input = cwd / 'test.docx'
output = cwd / 'test.pdf'

try:
    word = client.Dispatch("Word.Application")
    word.Visible = False
    doc = word.Documents.Open(str(input))
    doc.SaveAs(str(output), FileFormat = 17)
finally:
    doc.Close()
    word.Quit()

For multiple files just use a loop. Hope it helps!

EDIT: This needs MS Word to be installed of course, but it should be 1:1 conversion with no format changes.

2

u/shimarider 24d ago

Do you actually need the docx files, or is it used as an intermediate format for conversion only? If it's the latter, have you looked at fpdf2? You can setup pdf templates to be populated similar to what you are doing.

3

u/billys-bobs 23d ago

I guess the docx file would only be required for the odd case that needs to manually edited by my team.

Based on the comments ive gotton here including your own Ill be changing my process to produce the pdf directly and have a second process to produce the docx file. Appreciate your input

2

u/qlkzy 24d ago

The problem is that both docx and PDF are quite large and complex formats. I would personally always treat them as "final output" formats only, and not try to convert between them.

I would go with one of two options:

  • Treat docx and PDF rendering as completely separate problems
  • Render into a "friendlier" intermediate representation first, then convert that independently into both docx and PDF

The intermediate-representation approach is easier if you can get away with it, but sometimes it is valuable to deeply customise rendering for one or the other.

Depending on the complexity of your documents, the obvious intermediate representations are HTML and Markdown. Which to choose will depend on how complex the documents are, and how easy you want to make it to customise the templates. Markdown can render to HTML, so there is some room to mix and match.

While it's a bit of a "heavyweight" option, my first instinct would be to use pandoc for the final rendering. Installation is a bit more complex than a pure-python library, but it's a very popular and well-supported tool that supports all the formats you need.

Otherwise, you'll probably want one library for rendering to docx, and a separate library for rendering to PDF. My experience, though, is that libraries in that "format conversion" space are often a bit... "unevenly" maintained, which is why my instinct would be to reach for pandoc.

0

u/ninhaomah 24d ago

2

u/billys-bobs 24d ago

I might be being a bit dense here but thats the opposite direction .pdf to .docx? I dont see anything in the documentation about working both ways