---
jupyter:
jupytext:
notebook_metadata_filter: all
text_representation:
extension: .md
format_name: markdown
format_version: '1.1'
jupytext_version: 1.1.1
kernelspec:
display_name: Python 2
language: python
name: python2
plotly:
description: How to make PDF reports with Python and Plotly Graphs.
display_as: report_generation
language: python
layout: base
name: Python PDF Reports
order: 1
page_type: example_index
permalink: python/pdf-reports/
thumbnail: thumbnail/ipython_10_pdf_report.jpg
---
Since Plotly graphs can be embedded in HTML or exported as a static image, you can embed Plotly graphs in reports suited for print and for the web. This notebook is a primer on creating PDF reports with Python from HTML with Plotly graphs. This notebook uses:
- [Plotly](https://plot.ly/python/) for interactive, web native graphs
- [IPython Notebook](https://plot.ly/ipython-notebooks) to create this notebook, combining text, HTML, and Python code
- [xhtml2pdf](https://github.com/chrisglass/xhtml2pdf/tree/master/doc) to convert HTML to PDF in Python
Run `! pip install xhtml2pdf` in the Terminal to install the `xhtml2pdf` package.
#### Create the HTML Template
First choose the plots that you'd like to add to the report.
```python
graphs = ['https://plot.ly/~christopherp/308',
'https://plot.ly/~christopherp/306',
'https://plot.ly/~christopherp/300',
'https://plot.ly/~christopherp/296']
```
```python
from IPython.display import display, HTML
def report_block_template(report_type, graph_url, caption=''):
if report_type == 'interactive':
graph_block = ''
elif report_type == 'static':
graph_block = (''
'' # Open the interactive graph when you click on the image
''
'')
report_block = ('' +
graph_block +
'{caption}' + # Optional caption to include below the graph
' ' + # Line break
''+
'Click to comment and see the interactive graph' + # Direct readers to Plotly for commenting, interactive graph
'' +
' ' +
'
') # horizontal line
return report_block.format(graph_url=graph_url, caption=caption)
interactive_report = ''
static_report = ''
for graph_url in graphs:
_static_block = report_block_template('static', graph_url, caption='')
_interactive_block = report_block_template('interactive', graph_url, caption='')
static_report += _static_block
interactive_report += _interactive_block
```
#### Display the Interactive Report
This version, suited for the web, contains the interactive version of the Plotly graphs, served from Plotly's server.
```python
display(HTML(interactive_report))
```
#### Display the Static Report
This version is easy to convert to PDF. It contains the static version of the Plotly graphs, also served from Plotly's server.
```python
display(HTML(static_report))
```
```python
import xhtml2pdf
from xhtml2pdf import pisa
```
### Part 2 - Convert the HTML to PDF with `xhtml2pdf`
```python
from xhtml2pdf import pisa
# Utility function
def convert_html_to_pdf(source_html, output_filename):
# open output file for writing (truncated binary)
result_file = open(output_filename, "w+b")
# convert HTML to PDF
pisa_status = pisa.CreatePDF(
source_html, # the HTML to convert
dest=result_file) # file handle to recieve result
# close output file
result_file.close() # close output file
# return True on success and False on errors
return pisa_status.err
convert_html_to_pdf(static_report, 'report.pdf')
! open report.pdf
```
#### Generating Images *on the fly*
The static report in the example above uses graphs that were already created in Plotly. Sometimes it's helpful to use graph images that are created on-the-fly. For example, if you're using [plotly.js](https://plot.ly/javascript-graphing-library) to create the web-reports you might not be saving the graphs to accounts on [plot.ly](https://plot.ly).
To create static images of graphs on-the-fly, use the `plotly.plotly.image` class. This class generates images by making a request to the Plotly image server.
Here's an alternative template that uses `py.image.get` to generate the images and template them into an HTML and PDF report.
```python
import plotly.plotly as py
import base64
width = 600
height = 600
template = (''
''
'{caption}' # Optional caption to include below the graph
' '
''
'')
# A collection of Plotly graphs
figures = [
{'data': [{'x': [1,2,3], 'y': [3,1,6]}], 'layout': {'title': 'the first graph'}},
{'data': [{'x': [1,2,3], 'y': [3,7,6], 'type': 'bar'}], 'layout': {'title': 'the second graph'}}
]
# Generate their images using `py.image.get`
images = [base64.b64encode(py.image.get(figure, width=width, height=height)).decode('utf-8') for figure in figures]
report_html = ''
for image in images:
_ = template
_ = _.format(image=image, caption='', width=width, height=height)
report_html += _
display(HTML(report_html))
convert_html_to_pdf(report_html, 'report-2.pdf')
```
### Learn more
- Questions?
- [Getting started with Plotly and Python](https://plot.ly/python/getting-started)
- [Updating Plotly graphs with Python and cron jobs](http://moderndata.plot.ly/update-plotly-charts-with-cron-jobs-and-python/)
- [Using Plotly offline in IPython notebooks](https://plot.ly/python/offline)
- [Generate HTML reports with Python, Pandas, and Plotly](http://moderndata.plot.ly/generate-html-reports-with-python-pandas-and-plotly/)
- [Emailing Plotly graphs with Python](https://plot.ly/python/email-reports/)
- [Edit this tutorial](https://github.com/plotly/documentation/tree/gh-pages)
```python
! pip install publisher --upgrade
from IPython.display import HTML, display
display(HTML(''))
display(HTML(''))
! pip install git+https://github.com/plotly/publisher.git --upgrade
import publisher
publisher.publish('pdf-reports.ipynb', 'python/pdf-reports/', 'PDF Reports'
'How to make PDF reports with Python and Plotly Graphs.',
title = 'Python PDF Reports | plotly',
name = 'PDF Reports',
has_thumbnail='true', thumbnail='thumbnail/ipython_10_pdf_report.jpg',
language='python', page_type='example_index',
display_as='report_generation', order=1)
```