Reports are crucial to business since they provide information about how the company is performing and being reflected. They allow us to check the success and failure rates of the business. Odoo offers a platform for generating reports and analyzing business developments.
You can generate PDF reports for custom modules because Odoo, by default, supports PDF reports. Also, we can generate Excel reports in Odoo, which will be very helpful for your company's business executives. Sometimes, we may also require reports in other formats, such as Microsoft Word (.docx).
In this blog, we are going to discuss how to create a Microsoft Word (.docx) report in a custom module and how to download multiple documents in one zip. Installing the Python library python-docx is required to produce the report in Microsoft Word (.docx) format. Microsoft Word (.docx) files will be created and updated using the python-docx library.
It's easy to install. Using the following piece of code, you may install Python-docx:
pip install python-docx
Open the terminal and install python-docx.
Next, we'll discuss creating Microsoft Word (.docx) documents within zip files in Odoo 16. The following code shows the Python file of the sample doc.report to be implemented
from odoo import models, fields
class TestDoc(models.Model):
_name = 'doc.report'
name = fields.Char(String='Name', help="Customer Name", required=True)
def print_pdf(self):
return {'type': 'ir.actions.act_url',
'url': '/web/binary/download_docx_report',
'target': 'self',
'res_id': self.id,
}
Here is a method for the print button that returns the URL - /web/binary/download_docx_report. Moreover, we need to define a controller for it. The view of the sample doc.report is shown in the figure below,
The controller for the root /web/binary/download_docx_report is defined as follows,
import io, os, base64, zipfile
from odoo import http, _
from docx import Document
from odoo.http import request
from docx.shared import Inches
class Binary(http.Controller):
@http.route('/web/binary/download_docx_report', type='http', auth="public")
def download_function_descriptions(self):
stream = io.BytesIO()
zip_archive = zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED)
document1 = Document()
section = document1.sections[0]
sec_header = section.header
company = request.env.company
file_path = os.path.join(os.getcwd(), 'logo.png')
# Add logo image to document1
if company.logo:
image_data = base64.b64decode(company.logo)
with open(file_path, 'wb') as f:
f.write(image_data)
header_paragraph1 = sec_header.paragraphs[0]
run1 = header_paragraph1.add_run()
run1.add_picture(file_path, width=Inches(1.25))
document1.add_paragraph('Test Paragraph for FIRST document')
document1_file_name = "test1.docx"
document1.save(document1_file_name)
zip_archive.write(document1_file_name)
document2 = Document()
section = document2.sections[0]
sec_header = section.header
# Add logo image to document2
if company.logo:
header_paragraph2 = sec_header.paragraphs[0]
run2 = header_paragraph2.add_run()
run2.add_picture(file_path, width=Inches(1.25))
document2.add_paragraph('Test Paragraph for SECOND document')
document2_file_name = "test2.docx"
document2.save(document2_file_name)
zip_archive.write(document2_file_name)
zip_archive.close()
bytes_of_zipfile = stream.getvalue()
return request.make_response(bytes_of_zipfile,
[('Content-Type', 'application/zip'),
('Content-Disposition', 'attachment')])
Let's look at each component of the above code in detail:
stream = io.BytesIO()
//To store data as bytes in the memory buffer.
zip_archive = zipfile.ZipFile(stream, 'w', compression=zipfile.ZIP_DEFLATED)
// Create zip
document1 = Document()
// For the first document, open it. Here, numerous documents have been created and downloaded as a ZIP file, thus the name document1.
header_paragraph1 = sec_header.paragraphs[0]
run1 = header_paragraph1.add_run()
run1.add_picture(file_path, width=Inches(1.25))
//Which will add the paragraph and insert the logo image into the header of the document.
document1.add_paragraph('Test Paragraph for FIRST document')
// To insert a paragraph into the text, we must first define the element add_paragraph, to which the paragraph will be added and shown.Tables, headers, and many other features can all be added to the content. To learn more, please go through the python-docx documentation.
document1_file_name = "test1.docx"
// Set a name for the document; in this case, test1.docx will serve as an example. If you need to create several documents and your name needs to be based on the document, you can also use other techniques to create the name.
document1.save(document1_file_name)
// Save the generated document with file name test1.docx
zip_archive.write(document1_file_name)
// Added the generated document to the generated ZIP file.
document2 = Document()
document2.add_paragraph('Test Paragraph for SECOND document')
document2_file_name = "test2.docx"
document2.save(document2_file_name)
zip_archive.write(document2_file_name)
Similarly, the process repeats itself to generate a second document that you can loop around as per the customer's needs
zip_archive.close()
// Close the zip
bytes_of_zipfile = stream.getvalue()
Now in stream, we have data as bytes, and we use the function getvalue() to get value from the stream.
return request.make_response(bytes_of_zipfile,[('Content-Type', 'application/zip'),
('Content-Disposition', 'attachment')])
// Return the request with the associated response. Use the make_response method to create a response using the generated ZIP file.
Let's check how it works. When you click the print button, it redirects to the corresponding URL defined, so the controllers return the response with the documents in a ZIP file.
The document report will be downloaded as a zip file by clicking the print button. The system's local storage shows the downloaded ZIP file.
Using an external ZIP Extractor program, you can extract the ZIP file to get the specific field that is embedded within it.
The generated report will depict the extraction of the ZIP file.
When you open the extracted folder, you can find the generated documents.
Open each document or attached file to view the contents.
Document 1:
Document 2 :
In this way, you can generate word reports that are inside a ZIP file in Odoo 16, which can be further extracted to local storage.
To read more about generating Microsoft Word documents in a zip in Odoo 15, refer to our blog How To Generate Microsoft Word Documents in a Zip In Odoo 15