Great! I will give it a try!
Thanks so much!
Great! I will give it a try!
Thanks so much!
Hahaha what if you aren’t a dash enterprise customer
Hi @philphi… Thank you very much for your contribution to it so far, matte;
Someone has tried the solution and it worked?
I tried to implement philphi’s solution with but I’m getting an error. I would appreciate it a lot if someone can give me some help to make it works (because I’m not experienced in JS)
Error on the dash callback:
PDFDocument is not defined
The error on console is:
> dash_renderer.v1_9_0m1611578476.dev.js:100499 ReferenceError: PDFDocument is not defined
at Object.ns.n_clicks ((index):35)
at handleClientside (dash_renderer.v1_9_0m1611578476.dev.js:93282)
at dash_renderer.v1_9_0m1611578476.dev.js:93526
at new Promise (<anonymous>)
at executeCallback (dash_renderer.v1_9_0m1611578476.dev.js:93513)
at dash_renderer.v1_9_0m1611578476.dev.js:99173
at _map (dash_renderer.v1_9_0m1611578476.dev.js:75415)
at map (dash_renderer.v1_9_0m1611578476.dev.js:78219)
at dash_renderer.v1_9_0m1611578476.dev.js:74584
at f2 (dash_renderer.v1_9_0m1611578476.dev.js:74400)
Thank you in advance guys;
Hi,
It can’t find the JS files. Where your python file is it must have an assets folder in the same directory with the two JS files
Hey bro, thank you very much, it worked now!!!
As I did create a folder called “experiment”, I thought that it was getting the assets of the main folder, but it wasn’t finding the folder. I tried to validate if the .js file was really working, but I did not find references to be sure about it !! My fault!
Thanks for the answer and the great work!
Hi @philphi , thanks for the awesome example, was wondering if this could be applied to a dash_table.DataTable instead of a figure? Thanks for your time!
Yes! You will need an additional package on top of PDFkit and Blob-stream called HTML2Canvas (https://cdnjs.cloudflare.com/ajax/libs/html2canvas/0.4.1/html2canvas.min.js) in the assets folder. You can convert any DIV and anything inside it to an image then use PDFKit to put the image in a pdf. However it is not as reliable as the first method since it takes a screenshot of a div.
import dash_table
import pandas as pd
import dash
import dash_html_components as html
from dash.dependencies import Input, Output
df = pd.read_csv('https://raw.githubusercontent.com/plotly/datasets/master/solar.csv')
app = dash.Dash(__name__)
app.layout = html.Div([
html.Button(id='button', children='Print Dash DataTable'),
html.Div([
dash_table.DataTable(
id='table',
columns=[{"name": i, "id": i} for i in df.columns],
data=df.to_dict('records'),
),
], id='table_div'),
html.Div(id='img_div')
])
app.clientside_callback(
'''
function (n_clicks) {
if (n_clicks > 0) {
html2canvas(document.getElementById('table_div')).then(function(canvas) {
var img = new Image();
var height = canvas.height;
img.src = canvas.toDataURL("image/png");
document.getElementById('img_div').appendChild(img);
var doc = new PDFDocument({layout:'portrait', margin: 25});
var stream = doc.pipe(blobStream());
var img_container = document.getElementById('img_div');
var imgElement = img_container.getElementsByTagName('img');
var imgSrc = imgElement[imgElement.length - 1].src;
doc.image(imgSrc, {width: 600});
doc.end();
var saveData = (function () {
var a = document.createElement("a");
document.body.appendChild(a);
a.style = "display: none";
return function (blob, fileName) {
var url = window.URL.createObjectURL(blob);
a.href = url;
a.download = fileName;
a.click();
window.URL.revokeObjectURL(url);
};
}());
stream.on('finish', function() {
var blob = stream.toBlob('application/pdf');
saveData(blob, 'Dash_DataTable.pdf');
});
});
}
return false;
}
''',
Output('button', 'disabled'),
[
Input('button', 'n_clicks'),
]
)
if __name__ == '__main__':
app.run_server(debug=True)
A downside of this method is I haven’t been able to add more than one screenshot of a div to the pdf, so if you have multiple charts/tables you need to wrap everything to a div and screenshot that div to the pdf. If the div goes beyond A4 size then you need to make the pdf longer.
@philphi I’ve added html2canvas.min.js to assets folder but it still shows error ‘html2canvas is not defined’
Similar to kabure’s issue above it cannot see the JS files. Make sure the assets folder is in the same directory as the python file you use for the example code.
I’m not sure what the issue is then. Try empty cache and rerun the program or get the latest html2canvas.js file or create a new folder with just the example code and assets folder with the necessary js files.
worked for me when i downloaded the html2canvas files from below link:
Hey I am Sarvesh I am Working On Two Python FrameWork Django and Dash Plotly, While I am working on Project There is Task to generate Pdf I Try and Found Solution On That. Hope The Solution will Found usefull to all
import pandas as pd
import datetime as dt
import plotly.offline as pyo
import plotly.graph_objs as go
import plotly.express as px
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
from django_plotly_dash import DjangoDash
labels = [‘Oxygen’,‘Hydrogen’,‘Carbon_Dioxide’,‘Nitrogen’]
values = [4500, 2500, 1053, 500]
app = DjangoDash(‘Report’,add_bootstrap_links=True)
app.css.append_css({ “external_url” : “/static/assets/css/dashstyle.css” })
html.Script(src=‘https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.2/html2pdf.bundle.js’)
card1 = dbc.Card([
dcc.Checklist(
options=[{'label':'Top Five Highest Frequent Customers',}],
className='printCheckBox',
labelStyle={'fontWeight':'600',},
inputStyle={'marginRight':'10px',},
inputClassName='chkremove',
id = 'clist'
),
dbc.CardBody([
html.P(['2 His Majesties Letter to the Lord Thresurer & other of the Lords to deliver the Charge of the Tower & Prisones thereunto S.r Wm Wade Knight which was done by the Earle of Dorsett and the Earle of Devonshire on Thursday in the Afternoon, at the Clock being the 15 of Aug. 1605'])
])
],className=‘cardDesign’)
card2 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)],
layout=dict(autosize=True)
),
responsive=True,
)
])
],className=‘cardDesign’)
card2_1 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)]
))
])
],className=‘cardDesign’)
card2_2 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)]
))
])
],className=‘cardDesign’)
card3 = dbc.Card([
dcc.Checklist(
options=[{'label':'Top Five Highest Frequent Customers',}],
className='printCheckBox',
labelStyle={'fontWeight':'600',},
inputStyle={'marginRight':'10px',},
inputClassName='chkremove',
id = 'clist'
),
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Bar(x=labels,y=values)]
))
])
],className=‘cardDesign’)
app.layout = html.Div([
html.Div([
dbc.Row([
dbc.Col([
html.H3(['Report PDF Generator'])
]),
]),
dbc.Row([
dbc.Col([
card1
]),
]),
dbc.Row([
dbc.Col([
card2
]),
]),
dbc.Row([
dbc.Col([
dbc.Row([
dbc.Col([card2_1],xs=12, sm=12, md=12, lg=6, xl=6),
dbc.Col([card2_2],xs=12, sm=12, md=12, lg=6, xl=6),
])
]),
]),
dbc.Row([
dbc.Col([
card2
]),
]),
dbc.Row([
dbc.Col([
dbc.Row([
dbc.Col([card2_1],xs=12, sm=12, md=12, lg=6, xl=6),
dbc.Col([card2_2],xs=12, sm=12, md=12, lg=6, xl=6),
])
]),
]),
dbc.Row([
dbc.Col([
card3
]),
]),
],id='print'),
html.H1(id='h'),
dbc.Button(children=['Download'],className="mr-1",id='js',n_clicks=0),
html.Script(src="https://code.jquery.com/jquery-3.5.1.slim.min.js",integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj",crossOrigin='anonymous'),
html.Script(src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js",integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx",crossOrigin='anonymous'),
html.Script(src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.8.1/html2pdf.bundle.min.js")
],id=‘main’)
app.clientside_callback(
"""
function(n_clicks){
if(n_clicks > 0){
$('.chkremove').hide();
var opt = {
margin: 2,
filename: 'myfile.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 1},
jsPDF: { unit: 'cm', format: 'a2', orientation: 'p' },
pagebreak: { mode: ['avoid-all'] }
};
html2pdf().from(document.getElementById("print")).set(opt).save();
setTimeout(function(){
$('.chkremove').show();
},2000);
}
}
""",
Output('js','n_clicks'),
Input('js','n_clicks')
)
Hi @Sarvesh04
I am having difficulties copying your code to try it out.
Can you please insert it as a code? also what else have you used in the Asset folder (and where to download them? ).
Regards
@Basheerkafaf i used asset folder only for css purpose
import pandas as pd
import datetime as dt
import plotly.offline as pyo
import plotly.graph_objs as go
import plotly.express as px
import dash_table
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
from django_plotly_dash import DjangoDash
labels = ['Oxygen','Hydrogen','Carbon_Dioxide','Nitrogen']
values = [4500, 2500, 1053, 500]
app = DjangoDash('Report',add_bootstrap_links=True)
app.css.append_css({ "external_url" : "/static/assets/css/dashstyle.css" })
html.Script(src='https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.9.2/html2pdf.bundle.js')
card1 = dbc.Card([
dcc.Checklist(
options=[{'label':'Top Five Highest Frequent Customers',}],
className='printCheckBox',
labelStyle={'fontWeight':'600',},
inputStyle={'marginRight':'10px',},
inputClassName='chkremove',
),
dbc.CardBody([
html.P(['2 His Majesties Letter to the Lord Thresurer & other of the Lords to deliver the Charge of the Tower & Prisones thereunto S.r Wm Wade Knight which was done by the Earle of Dorsett and the Earle of Devonshire on Thursday in the Afternoon, at the Clock being the 15 of Aug. 1605'])
])
],className='cardDesign')
card2 = dbc.Card([
dcc.Checklist(
options=[{'label':'Top Five Highest Frequent Customers',}],
className='printCheckBox',
labelStyle={'fontWeight':'600',},
inputStyle={'marginRight':'10px',},
inputClassName='chkremove',
),
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)],
layout=dict(autosize=True)
),
responsive=True,
)
])
],className='cardDesign')
card2_1 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)]
))
])
],className='cardDesign')
card2_2 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)]
))
])
],className='cardDesign')
card3 = dbc.Card([
dcc.Checklist(
options=[{'label':'Top Five Highest Frequent Customers',}],
className='printCheckBox',
labelStyle={'fontWeight':'600',},
inputStyle={'marginRight':'10px',},
inputClassName='chkremove',
),
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Bar(x=labels,y=values)]
))
])
],className='cardDesign')
app.layout = html.Div([
html.Div([
dbc.Row([
dbc.Col([
html.H3(['Report PDF Generator'])
]),
]),
dbc.Row([
dbc.Col([
card1
]),
]),
dbc.Row([
dbc.Col([
card2
]),
]),
dbc.Row([
dbc.Col([
dbc.Row([
dbc.Col([card2_1],xs=12, sm=12, md=12, lg=6, xl=6),
dbc.Col([card2_2],xs=12, sm=12, md=12, lg=6, xl=6),
])
]),
]),
dbc.Row([
dbc.Col([
card2
]),
]),
dbc.Row([
dbc.Col([
dbc.Row([
dbc.Col([card2_1],xs=12, sm=12, md=12, lg=6, xl=6),
dbc.Col([card2_2],xs=12, sm=12, md=12, lg=6, xl=6),
])
]),
]),
dbc.Row([
dbc.Col([
card3
]),
]),
],id='print'),
html.H1(id='h'),
dbc.Button(children=['Download'],className="mr-1",id='js',n_clicks=0),
html.Script(src="https://code.jquery.com/jquery-3.5.1.slim.min.js",integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj",crossOrigin='anonymous'),
html.Script(src="https://cdn.jsdelivr.net/npm/bootstrap@4.5.3/dist/js/bootstrap.bundle.min.js",integrity="sha384-ho+j7jyWK8fNQe+A12Hb8AhRq26LrZ/JpcUGGOn+Y7RsweNrtN/tE3MoK7ZeZDyx",crossOrigin='anonymous'),
html.Script(src="https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.8.1/html2pdf.bundle.min.js")
],id='main')
app.clientside_callback(
"""
function(n_clicks){
if(n_clicks > 0){
$('.chkremove').hide();
var opt = {
margin: 2,
filename: 'myfile.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 1},
jsPDF: { unit: 'cm', format: 'a2', orientation: 'p' },
pagebreak: { mode: ['avoid-all'] }
};
html2pdf().from(document.getElementById("print")).set(opt).save();
setTimeout(function(){
$('.chkremove').show();
},2000);
}
}
""",
Output('js','n_clicks'),
Input('js','n_clicks')
)
my css from asset folder
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;600;700&display=swap');
.main{
font-family: 'Montserrat', sans-serif;
}
.cardDesign{
box-shadow:0 4px 8px 0 rgba(0, 0, 0, 0.2);
margin-top: 5px;
margin-bottom: 5px;
}
.printCheckBox{
margin-left:8px;
margin-top: 5px;
}
I will try to do in proper in dash framework since In above code i used both framework and merge them
@Basheerkafaf I have generated pdf using proper Dash Framework
python code
import pandas as pd
import datetime as dt
import plotly.offline as pyo
import plotly.graph_objs as go
import plotly.express as px
import dash
import dash_core_components as dcc
import dash_html_components as html
import dash_bootstrap_components as dbc
from dash.dependencies import Input, Output, State
labels = ['Oxygen','Hydrogen','Carbon_Dioxide','Nitrogen']
values = [4500, 2500, 1053, 500]
app = dash.Dash(__name__,external_stylesheets=[dbc.themes.BOOTSTRAP])
card1 = dbc.Card([
dbc.CardBody([
html.P(['2 His Majesties Letter to the Lord Thresurer & other of the Lords to deliver the Charge of the Tower & Prisones thereunto S.r Wm Wade Knight which was done by the Earle of Dorsett and the Earle of Devonshire on Thursday in the Afternoon, at the Clock being the 15 of Aug. 1605'],
className = "narrative"
)
])
],className='cardDesign')
card2 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)],
layout=dict(autosize=True)
),
responsive=True,
)
])
],className='cardDesign')
card2_1 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)]
))
])
],className='cardDesign')
card2_2 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Pie(labels=labels,values=values)]
))
])
],className='cardDesign')
card3 = dbc.Card([
dbc.CardBody([
dcc.Graph(figure=dict(
data=[go.Bar(x=labels,y=values)]
))
])
],className='cardDesign')
app.layout = html.Div([
html.Div([
dbc.Row([
dbc.Col([
html.H3(['Report PDF Generator'])
]),
]),
dbc.Row([
dbc.Col([
card1
],id="col1"),
]),
dbc.Row([
dbc.Col([
card2
],id="col2"),
]),
dbc.Row([
dbc.Col([
dbc.Row([
dbc.Col([card2_1],xs=12, sm=12, md=12, lg=6, xl=6,id="col3"),
dbc.Col([card2_2],xs=12, sm=12, md=12, lg=6, xl=6,id="col4"),
])
]),
]),
dbc.Row([
dbc.Col([
card3
],id="col5"),
]),
],id='print'),
dbc.Button(children=['Download'],className="mr-1",id='js',n_clicks=0),
],id='main',)
app.clientside_callback(
"""
function(n_clicks){
if(n_clicks > 0){
var opt = {
margin: 1,
filename: 'myfile.pdf',
image: { type: 'jpeg', quality: 0.98 },
html2canvas: { scale: 3},
jsPDF: { unit: 'cm', format: 'a2', orientation: 'p' },
pagebreak: { mode: ['avoid-all'] }
};
html2pdf().from(document.getElementById("print")).set(opt).save();
}
}
""",
Output('js','n_clicks'),
Input('js','n_clicks')
)
if __name__ == '__main__':
app.run_server(port='8050',debug=True)
js code
function addScript(url) {
var script = document.createElement('script');
script.type = 'application/javascript';
script.src = url;
document.head.appendChild(script);
}
addScript('https://raw.githack.com/eKoopmans/html2pdf/master/dist/html2pdf.bundle.js');
css code
@import url('https://fonts.googleapis.com/css2?family=Montserrat:wght@300;400;600;700&display=swap');
#main{
font-family: 'Montserrat', sans-serif;
}
.cardDesign{
box-shadow:0 4px 8px 0 rgba(0, 0, 0, 0.2);
margin-top: 5px;
margin-bottom: 5px;
}
Has anyone had success adding multiple divs here to screenshot?
Hi @Sarvesh04 and everyone here
Thanks for sharing! I tried it on my computer and I have the following error message:
“Can’t find variable: html2pdf”
Here is the detail:
handleClientside
_callee$
asyncGeneratorStep
_next
Promise@[native code]
executeCallback
_map
_callee2$
asyncGeneratorStep
_next
Promise@[native code]
forEach
dispatch
_callee$
asyncGeneratorStep
_next
promiseReactionJob@[native code]
Do you know what can be the origin of this error?
Do you put the js code in a separated file and if so, how do you link it to the python code?