Some links in this post may be affiliate links. We may get paid if you buy something or take an action after clicking one of these, but without addictional costs for you compared to direct buying.

Python-docx and Raspberry PI: Automating MS Word Reports Creation and Sending

Raspberry PI python-docx featured image
0
(0)

Reports are vital part in many organizations needing to keep under monitoring some aspects which are core for the business. Automating these reports usually require advanced software, but we can achieve the same goal with python-docx and Raspberry PI

In this tutorial, I’m going to show you how to install python-docx on Raspberry PI computer boards, also showing how to use it and how to automate report creation and sending by email.

Python-docx is a library that allows the creation and manipulation of Microsoft Word (.docx) files from python. Simple, synthetic, and exactly explaining what it aims to do. The advantage of using python-docx is that you can use it inside a python script and create automated procedures to create or edit documents.

I will use it in a script with Mutt, so enabling a fast and direct way to create and send reports from a single python script. Moreover, with cron, we can also automate this execution and schedule to execute at a defined frequency.

For the following procedure, I’ve used a Raspberry PI 3 Model A+ board. This procedure will work with any Raspberry PI computer board (except Raspberry PI Pico, which is a Microcontroller, not a computer)

What We Need

raspberry pi 3 model A+

As usual, I suggest adding from now to your favorite e-commerce shopping cart all needed hardware, so that at the end you will be able to evaluate overall costs and decide if continue with the project or remove them from the shopping cart. So, hardware will be only:

Check hardware prices with the following links:

Amazon raspberry pi boards box
Amazon Raspberry PI 3 Model A+ box
Amazon Micro SD box
Amazon Raspberry PI Power Supply box

Step-by-Step Procedure

Prepare OS

Start installing your Operating System. I suggest installing Raspberry PI OS Lite, so having a fast, headless OS. But you can also use Raspberry PI OS Desktop, in this case working from its internal terminal.

From the terminal, make sure your OS is updated:

sudo apt update -y && sudo apt upgrade -y

Now you can install python-docx, just after installing pip3 and lxml (which is required). From the terminal, use the following 2 commands:

sudo apt install python3-pip python3-lxml
pip3 install python-docx

At this point, you already have everything needed to use python-docx. In the following paragraph, I will explain how to use the main methods.

Python-docs Main Methods/Properties

Creating a New Document

Each python script will need to start by importing python-docx library:

from docx import Document

With python-docx you can create a new document by using the following line:

document = Document()

With this line, we created a new empty document, but we didn’t still save it. Please note that the Document() class can also open existing documents. This is particularly useful, for example, when we want to start from a template instead of writing an empty file. The code line will be:

document = Document('/path/to/TEMPLATE.docx')

Add a Heading

To add a heading you will use the following line:

from docx import Document
document.add_heading('Document Title', level=0)

The “level=0” is an optional parameter and indicates the title level. Level zero is the document title and is the default when no level is indicated:

python-docx tutorial 01

Other levels can be added and resulting in a complete title structure. Following code:

from docx import Document
document = Document()
document.add_heading('Document Title')
document.add_heading('Title 1', level=1)
document.add_heading('Title 2', level=2)
document.add_heading('Title 3', level=3)
document.add_heading('Title 4', level=4)
document.add_heading('Title 5', level=5)
document.add_heading('Title 6', level=6)
python-docx tutorial 02

Add a Paragraph

Adding a paragraph can be achieved with following line:

document.add_paragraph("Hello from peppe8o!")

With the following result:

python-docx tutorial 03

When you need to add specific formatting to your paragraph, you can use a variable to add the new text and then apply the new format as follows:

paragraph = document.add_paragraph('This is a bullet')
paragraph.style = 'List Bullet'

having the following result:

python-docx tutorial 04

This is also a useful way to manage paragraphs with changing characters format. In this case, you will use the “add_run” method to add text to be threated with specific formattin (instead of add_paragraph, which would go to a new line):

paragraph = document.add_paragraph('Hello from ')
run = paragraph.add_run('peppe8o')
run.bold = True
paragraph.add_run(' blog')
python-docx tutorial 05

Add a Table

Adding a table is as simple as with a paragraph. You will probably need to manage cells in order to insert single values, so using a variable to identify the table is always the best way:

table = document.add_table(rows=3, cols=2)
python-docx tutorial 06

Note: the table is created without borders. I set them in order to make the table visible. But you will have to set the border with table.style = ‘Table Grid’ after add.table statement

You have 2 ways to add content to your cells. The faster one is by directly calling the cell and using text property:

table.cell(0, 1).text='Normal Cell'

The second one is by using the paragraphs add_run method, which allows us to apply specific formatting inside the cell after setting the text:

cell = table.cell(0, 0)
run =cell.paragraphs[0].add_run('Bolded Cell')
run.bold = True

The following picture shows the results difference:

python-docx tutorial 07

If you need to add an additional row to an existing table, you can get it with:

table.add_row()

Add a Picture

Pictures are another common object for Word documents. The way python-docx integrates them in documents is always the same:

document.add_picture('image-filename.png')

Or, using the absolute path:

document.add_picture('/path/to/file/image-filename.png')

Copy a picture in your script path or, if you don’t have, you can get the following from python-openxml GitHub examples:

wget https://github.com/python-openxml/python-docx/raw/master/tests/test_files/python-icon.jpeg

In this way, supposing that you are working from /home/pi folder, both the commands:

document.add_picture('python-icon.jpeg')

and

document.add_picture('/home/pi/python-icon.jpeg')

will return the same output:

python-docx tutorial 08

Add a page break

When you need to move into a new page, you will likely need the page break element. With python-docx you can add this element with the following line:

document.add_page_break()

Example 1: the default Demo.docx

This “docxDemo.py” is also available from my download area:

wget https://peppe8o.com/download/python/python-docx/docxPython.py

If you want to create it by yourself, open a new file named “docxDemo.py”:

nano docxDemo.py

Paste following code

from docx import Document

document = Document()

document.add_heading('Document Title', 0)

p = document.add_paragraph('A plain paragraph having some ')
p.add_run('bold').bold = True
p.add_run(' and some ')
p.add_run('italic.').italic = True

document.add_heading('Heading, level 1', level=1)
document.add_paragraph('Intense quote', style='Intense Quote')

document.add_paragraph(
    'first item in unordered list', style='List Bullet'
)
document.add_paragraph(
    'first item in ordered list', style='List Number'
)

records = (
    (3, '101', 'Spam'),
    (7, '422', 'Eggs'),
    (4, '631', 'Spam, spam, eggs, and spam')
)

table = document.add_table(rows=1, cols=3)
hdr_cells = table.rows[0].cells
hdr_cells[0].text = 'Qty'
hdr_cells[1].text = 'Id'
hdr_cells[2].text = 'Desc'
for qty, id, desc in records:
    row_cells = table.add_row().cells
    row_cells[0].text = str(qty)
    row_cells[1].text = id
    row_cells[2].text = desc

document.add_page_break()

document.save('demo.docx')

Save and close.

Run the following command:

python3 docxDemo.py

At the end, you will find a new file, named “demo.docx”, with the following result followed by an empty page (because of final “add_page_break” before the final saving command from the script):

demo.docx file with python-docx

Example 2: Custom Report from Raspberry PI System

With this in mind, we can create a custom report collecting info both from Raspberry PI or any external system reachable from your RPI. In this way, the report preparation can be fully automated.

An example of this usage is collecting Raspberry PI internal info like OS version, CPU temperature, networking status and running processes.

The full script is available from my download area and you can get it directly in your Raspberry PI with the command:

wget https://peppe8o.com/download/python/python-docx/myRPIReport.py

This script is built based on what already explained in previous paragraph, except from the following function:

def console(cmd):
    p = Popen(cmd, shell=True, stdout=PIPE)
    out, err = p.communicate()
    return out.decode('ascii').strip()

This part, using subprocess library imported at the script beginning, executes shell commands from Python script, thus giving you back the shell result.

According to this condition, please remember that you are running te script as pi user. For this you will be able to execute commands available to pi uses (“sudo” commands require authentication, thus not giving back results). For these commands required priviledged permissions, ways are to add a permission to pi user for executing that command or executing python script from root (note that also installation steps has to be done from root to use python-docx from root).

Anyway, my script runs without the need of any additional permission, so running it:

python3 myRPIReport.py

will give you back a result similar to that extract:

python-docx tutorial custom Raspberry PI report

The full report is available from following link: myReport.docx

Scheduling and Sending Reports by Email

Now, what misses is to make reports autmatically produced and sent.

Install Mutt to send Email from Raspberry PI

Firstly, install Mutt in your Raspberry PI. For this you can refer to my Terminal Email Client with Raspberry PI and Mutt tutorial, which already covers all the procedure.

Update myRPIReport.py Script

We’ll add at the end of our script the sending step by using Mutt terminal command.

Append, after the “document.save(‘myReport.docx’)” row, the following line:

console('echo "Please find last report attached" | mutt -s "Updated report from Raspberry PI" recipient@example.com -a "/home/pi/myReport.docx"')

Please remember to use your recipient email address.

Test your script with the terminal command:

python3 myRPIReport.py

This time, it will generate the report and also send it to your recipient’s address. Check your email (also spam folder, if you don’t find it in your Inbox).

Schedule your Reports Generation and Sending

For this goal, we’ll use the built-in cron from Linux. From the terminal, open the cron for the pi user to edit with this command:

crontab -u pi -e

Select your favorite text editor (1. Nano for me):

pi@raspberrypi:~ $ crontab -u pi -e
no crontab for root - using an empty one

Select an editor.  To change later, run 'select-editor'.
  1. /bin/nano        <---- easiest
  2. /usr/bin/vim.tiny
  3. /bin/ed

Choose 1-3 [1]: 1

Append the following line at the end of the cron file, supposing that the script is in pi home folder (or change accordingly to your folder path):

0 * * * * python3 /home/pi/myRPIReport.py

This will execute the script (and send the updated report) every hour at the minute 0. You can customize frequency according to your needs. At the scheduled time, you will receive the report.

Enjoy!

How useful was this post?

Click on a star to rate it anonymously!

Average rating 0 / 5. Vote count: 0

No votes so far! Be the first to rate this post.

We are sorry that this post was not useful for you!

Let us improve this post!

Tell us how we can improve this post?

Leave a Reply

Your email address will not be published. Required fields are marked *

I accept the Privacy Policy