├── requirements.txt ├── generate.pyc ├── signature.png ├── InvoiceTpl.docx ├── .vscode └── settings.json ├── main.py └── generate.py /requirements.txt: -------------------------------------------------------------------------------- 1 | docxtpl==0.5.15 2 | python-docx==0.8.6 3 | -------------------------------------------------------------------------------- /generate.pyc: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vnessah/docx-gen/HEAD/generate.pyc -------------------------------------------------------------------------------- /signature.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vnessah/docx-gen/HEAD/signature.png -------------------------------------------------------------------------------- /InvoiceTpl.docx: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/Vnessah/docx-gen/HEAD/InvoiceTpl.docx -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "python.linting.pep8Enabled": true, 3 | "python.linting.enabled": false 4 | } -------------------------------------------------------------------------------- /main.py: -------------------------------------------------------------------------------- 1 | from flask import Flask, send_file 2 | import generate 3 | 4 | app = Flask(__name__) 5 | 6 | @app.route("/gen") 7 | def gen_docx(): 8 | template = 'InvoiceTpl.docx' 9 | signature = 'signature.png' 10 | document = generate.from_template(template, signature) 11 | document.seek(0) 12 | 13 | return send_file( 14 | document, mimetype='application/vnd.openxmlformats-' 15 | 'officedocument.wordprocessingml.document', as_attachment=True, 16 | attachment_filename='invoice.docx') 17 | 18 | if __name__ == "__main__": 19 | app.run(debug=True) -------------------------------------------------------------------------------- /generate.py: -------------------------------------------------------------------------------- 1 | from StringIO import StringIO 2 | from docx.shared import Cm 3 | from docxtpl import DocxTemplate, InlineImage 4 | 5 | def get_context(): 6 | """ You can generate your context separately since you may deal with a lot 7 | of documents. You can carry out computations, etc in here and make the 8 | context look like the sample below. 9 | """ 10 | return { 11 | 'invoice_no': 12345, 12 | 'date': '30 Mar', 13 | 'due_date': '30 Apr', 14 | 'name': 'Jane Doe', 15 | 'address': '123 Quiet Lane', 16 | 'subtotal': 335, 17 | 'tax_amt': 10, 18 | 'total': 345, 19 | 'amt_paid': 100, 20 | 'amt_due': 245, 21 | 'row_contents': [ 22 | { 23 | 'description': 'Eggs', 24 | 'quantity': 30, 25 | 'rate': 5, 26 | 'amount': 150 27 | }, { 28 | 'description': 'All Purpose Flour', 29 | 'quantity': 10, 30 | 'rate': 15, 31 | 'amount': 150 32 | }, { 33 | 'description': 'Eggs', 34 | 'quantity': 5, 35 | 'rate': 7, 36 | 'amount': 35 37 | } 38 | ] 39 | } 40 | 41 | 42 | def from_template(template, signature): 43 | target_file = StringIO() 44 | 45 | template = DocxTemplate(template) 46 | context = get_context() # gets the context used to render the document 47 | 48 | img_size = Cm(7) # sets the size of the image 49 | sign = InlineImage(template, signature, img_size) 50 | context['signature'] = sign # adds the InlineImage object to the context 51 | 52 | target_file = StringIO() 53 | template.render(context) 54 | template.save(target_file) 55 | 56 | return target_file 57 | --------------------------------------------------------------------------------