As Team Manager of the best SharePoint team and forever SharePoint Dev :), I’ve always been looking to develop the next cool feature on top of SharePoint. One of the most-requested cases is printing a SharePoint page OOB, a feature people keep begging for on Office365 User Voice.
Ok then… Challenge Accepted. 🙂
Yes, we did a SharePoint Framework Extension that allows you to export the current page to either PDF or PNG.
Frameworks Recipe
Mixing it all together
Firstly, you should know by now how to develop a SharePoint Framework Extension. If you don’t, the guys at PnP have great samples that let you start exploring it here.
Ok. Now we have our solution ready to develop.
First, we declare my FloatingButton to have 2 buttons. One to export to PDF, and another to export to PNG.
var links = [
{
"bgcolor":"#2980b9",
"icon":"<i class='fa fa-plus'></i>",
},
{
"bgcolor":"#f1c40f",
"color":"fffff",
"icon":"<i class='fa fa-file-pdf-o'></i>",
"id": "printPDF"
},
{
"bgcolor":"#FF7F50",
"color":"fffff",
"icon":"<i class='fa fa-picture-o'></i>",
"id": "printImage"
}
];
var options = {
rotate: true
};
($('#wrapper')as any).jqueryFab(links, options);
Now, if you decide to create a simple PNG from the page, you should know that in the Modern Experience there is a div that only displays the content of the canvas called spPageCanvasContent.
With that in mind, you can now use html2canvas to convert the page’s HTML to canvas and then to a base64 dataUrl. After that, you just need to open this image in a new URL.
var c:any = document.getElementById('spPageCanvasContent');
html2canvas(c,
{
useCORS: true,
}
).
then((canvas) => {
canvasToImg(canvas, imageToPdf, imageLoadError);
});
var canvasToImg = function(canvas, loaded, error){
var dataURL = canvas.toDataURL('image/png'),
img = new Image();
if(!isPdf){
var win = window.open();
win.document.write('<iframe src="' + dataURL + '" frameborder="0" style="border:0; top:0px; left:0px; bottom:0px; right:0px; width:100%; height:100%;" allowfullscreen></iframe>');
}
}
This should be the result for a PNG.
But…if you want to export it to PDF, this can be a little bit trickier. Now that you have the PNG, what you must do is to “paste” it on a PDF page, but keep in mind the size of the image so it doesn’t get distorted.
var imageToPdf = function(){
var pageOrientation = this.width >= this.height ? 'landscape' : 'portrait';
var img = this,
pdf = new jsPDF({
orientation: pageOrientation,
unit: 'px',
format: [img.width, img.height]
}),
pdfInternals = pdf.internal,
pdfPageSize = pdfInternals.pageSize,
pdfScaleFactor = pdfInternals.scaleFactor,
pdfPageWidth = pdfPageSize.width ,
pdfPageHeight = pdfPageSize.height ,
pdfPageWidthPx = pdfPageWidth * pdfScaleFactor,
pdfPageHeightPx = pdfPageHeight * pdfScaleFactor,
imgScaleFactor = Math.min(pdfPageWidthPx / img.width, 1),
imgScaledHeight = img.height * imgScaleFactor,
shiftAmt = 0,
done = false;
var newCanvas = canvasShiftImg(img, shiftAmt, imgScaleFactor, pdfPageHeightPx, pdfPageWidthPx);
pdf.addImage(newCanvas, 'png', 0, 0, pdfPageWidth, 0, null, 'SLOW');
pdf.save('printThisPage.pdf');
};
And this should be the end result for a PDF.
Hey, but SharePoint does content lazy loading…
Yep, that’s right. So, we did a trick! Probably not the fanciest way to do it, but it works! We just scroll the div down until everything is loaded.
var scrollRegion = $("div[class^='scrollRegion']");
scrollRegion.animate({ scrollTop: scrollRegion.prop("scrollHeight")}, 2000);
What about Responsive?
Yeah… it works as well! 🙂
Conclusion
With SPFx there are a lot of new tools and technologies that we can use for SharePoint development, creating great and modern user experiences.
We don’t always need to start from scratch.
Please find the code and the installation package on DevScopeNinjas’ GitHub.
If you have any comments or suggestions leave them in the comments box below!
Sharing is caring!
9 Comments
Michaël Maillot · March 12, 2019 at 9:10 am
Hi,
that’s a great feature, thanks ! I was wondering if this was working with PowerApps integrated forms ? 🙂
Ricardo Calejo · March 12, 2019 at 10:27 am
Hello Michael,
Thank you for your comment!
We believe not. But it is a good thing that we can try to do… follow us, and we’ll let you know 🙂
Michael Hoff · July 15, 2019 at 11:50 pm
I would like to test this extension in SP 2019. Is this possible?
Duncan Gallimore · July 25, 2019 at 9:10 am
Help! I can’t get this to compile. I’ve tried changing the html2canvas reference in package.json to ^1.0.0-rc.1 and run npm -i –verbose, but when I run gulp bundle –ship I get:
Error – [tsc] src/extensions/printPage/PrintPageApplicationCustomizer.ts(181,9): error TS2349: Cannot invoke an expression whose type lacks a call signature. Type ‘typeof import(“C:/Users/xxxx.xx/documents/dvs-spfx-extensions/PrintSharePoint/node_modules/html2canvas/dist/types/index”)’ has no compatible call signatures.
What am I doing wrong? Sorry – I’m completely new to most of what’s going on here(!)
Ricardo Calejo · July 26, 2019 at 4:38 pm
Hello Duncan,
We think we didn’t understand what you did exactly. Can you please send us an email via https://devscopeninjas.azurewebsites.net/contact-us/ ?
Nidhi · January 16, 2020 at 11:37 am
Hi Ricardo,
Have you got this working?
Sachin · August 14, 2020 at 5:15 am
Thanks for sharing this 🙂 its really wonderful. I was trying this on my tenant and found the modern communicate site page banner is not captured during the print. Is that because banner is out of the ‘spPageCanvasContent’? For us, we need banner as well so i am trying to extend it if possible.
Thanks again!
Sri · October 6, 2021 at 4:35 pm
Good article! Does this print as readable PDF?
SharePoint Dev Weekly - Episode 29 - Office 365 Developer Blog · March 5, 2019 at 9:43 am
[…] Printing Modern Experience SharePoint Page – Ricardo Calejo (DevScope) […]