# PDF from dashboard

**URL:** <https://discourse.nodered.org/t/pdf-from-dashboard/77011>\
**Category:** General\
**Tags:** dashboard\
**Created:** [28 March 2023 09:06 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011 "2023-03-28T09:06:50Z")\
**Posts on this page:** 11\
**Page:** 1

<div class="post-metadata">

**Author:** ![Jhankhana](https://avatars.discourse-cdn.com/v4/letter/j/35a633/32.png) [@Jhankhana](https://discourse.nodered.org/u/Jhankhana)\
**Post date:** [28 March 2023 09:06 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/1 "2023-03-28T09:06:50Z")

</div>

Hello there!  
need your help!

How we can data in pdf format as exactly shown on the dashboard?  
can we get grid table written in template node as pdf?  
is it possible to do such thing?

---

<div class="post-metadata">

**Author:** ![smanjunath211](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/smanjunath211/32/95742_2.png) [@smanjunath211](https://discourse.nodered.org/u/smanjunath211)\
**Post date:** [28 March 2023 10:44 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/2 "2023-03-28T10:44:47Z")

</div>

try

`node-red-contrib-pdfmake`

it has got build in examples also

---

<div class="post-metadata">

**Author:** ![dynamicdave](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/dynamicdave/32/96_2.png) [@dynamicdave](https://discourse.nodered.org/u/dynamicdave)\
**Post date:** [28 March 2023 12:19 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/3 "2023-03-28T12:19:00Z")

</div>

Might be worth looking at this thread as it might give you some ideas of using the` pdfmake` node...

> [@Has anyone used the 'pdfmake' node to embed an image in a document?](https://discourse.nodered.org/t/has-anyone-used-the-pdfmake-node-to-embed-an-image-in-a-document/74978):
>
> I'm trying to use this node to create a PDF from a 'document description' as a project for my IoT students to automatically create a newsletter using text and images from external sources. So far text insertion works fine, the problem is inserting an image as per the supplied example with the node. With help from @zenofmud I have this flow which uses http-request to insert an external image (from a remote server or a server like NGINX on a local RPi) successfully in to a document.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [28 March 2023 15:45 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/4 "2023-03-28T15:45:52Z")

</div>

PDFmake is for creating PDF's direct from data. It isn't for outputting a Dashboard to PDF.

If you want to output to PDF, either use PDFmake with the origin data or use your browser to save/print to PDF depending on the OS.

Better still, get people to use the web page directly and save everyone the hassle of working with PDF's. 😁

---

<div class="post-metadata">

**Author:** ![smanjunath211](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/smanjunath211/32/95742_2.png) [@smanjunath211](https://discourse.nodered.org/u/smanjunath211)\
**Post date:** [28 March 2023 16:01 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/5 "2023-03-28T16:01:12Z")

</div>

> [@Jhankhana](#):
>
> as exactly shown on the dashboard

i believe the OP wants the data in pdf format, just as it is shown on dashboard.  
but i do agree, why make a pdf when you can see the same thing in dashboard. but i do convert few of my reports in pdf for e-mail circulation and record keeping.

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [28 March 2023 16:07 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/6 "2023-03-28T16:07:32Z")

</div>

> [@smanjunath211](#):
>
> i believe the OP wants the data in pdf format, just as it is shown on dashboard.

OK, I didn't quite read it that way but OK.

> [@smanjunath211](#):
>
> but i do convert few of my reports in pdf for e-mail circulation and record keeping.

I'm deep into trying to get our organisation to stop using so many PDF's - or Word documents and PowerPoints for that matter! So I may be somewhat skewed in my viewpoint!

PDF's have very poor accessibility and we rightly regularly get hauled over the coals for producing so many of the wretched things. They are also a pain to use.

(You might have also noticed a while back that I shared an example that showed using uibuilder in a similar way to PDFmake for producing HTML-based reports. Urm, did I mention that my thinking might be a bit skewed! 😁 )

---

<div class="post-metadata">

**Author:** ![Jhankhana](https://avatars.discourse-cdn.com/v4/letter/j/35a633/32.png) [@Jhankhana](https://discourse.nodered.org/u/Jhankhana)\
**Post date:** [29 March 2023 08:07 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/7 "2023-03-29T08:07:45Z")

</div>

I am attaching SS and flow of my table. In the table, there is some fix data, and some will be come from flow. I have used grid table.

Now, I am stuck at, how can I adjust data for PDF in a same manner using function node or anything and then convert it to pdf?

Please help me Geniuses  
 ![Screenshot (71)](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/3X/5/e/5ead80759200ed7aa1dbca7e0246042a013d4884.png)

```auto
[{"id":"fc50e996.d6dc98","type":"ui_template","z":"d79ec1d.70ac04","group":"765ef6a9.5846b8","name":"Grid table","order":0,"width":"25","singleBrowser":false,"height":"32","format":"<!DOCTYPE html>\n<html>\n<head>\n<style>\n\n\n.grid-container {\n display: grid;\n justify-content: center;\n align-content: center;\n grid-template-columns:30px 400px 100px 100px 100px 100px 100px 100px 100px 100px;\n grid-template-rows: 40px 40px 40px 40px 40px 40px 40px 40px 40px;\n gap: 5px;\n background-color: #2196F3;\n padding: 20px;\n}\n\n.grid-container > div {\n background-color: rgba(255, 255, 255, 0.8);\n text-align: center;\n padding: 5px 0;\n font-size: 20px;\n}\n\n.item3 {\n grid-column: 3 / span 8;\n}\n\n.item6 {\n grid-column: 3 / span 8;\n}\n\n.item9 {\n grid-column: 3 / span 8;\n}\n\n.item12 {\n grid-column: 3 / span 8;\n}\n\n.item13 {\n grid-area: 5 / 1 / 9 / 2;\n }\n.item14 {\n grid-area: 5 / 2 / 9 / 3;\n}\n\n.item16 {\n grid-column: 4 / span 2;\n}\n\n.item17 {\n grid-column: 6 / span 2;\n}\n\n.item18 {\n grid-column: 8 / span 2;\n}\n\n.item21 {\n grid-column: 4 / span 2;\n}\n\n.item28 {\n grid-column: 4 / span 2;\n}\n\n.item35 {\n grid-column: 4 / span 2;\n}\n\n.item41 {\n grid-area: 9 / 1 / 15 / 2;\n}\n\n.item42 {\n grid-area: 9 / 2 / 12 / 3;\n}\n\n\n.item43 {\n grid-column: 3 / span 8;\n}\n\n.item44 {\n grid-column: 3 / span 6;\n}\n\n.item45 {\n grid-column: 9 / span 2;\n}\n\n.item46 {\n grid-column: 3 / span 8;\n}\n\n.item47 {\n grid-area: 12 / 2 / 15 / 3;\n}\n\n.item62 {\n grid-area: 15 / 1 / 21 / 2;\n}\n\n.item63 {\n grid-area: 15 / 2 / 21 / 3;\n}\n\n.item112 {\n grid-area: 21 / 1 / 23 / 2;\n}\n\n.item113 {\n grid-area: 21 / 2 / 23 / 3;\n}\n\n.item63 {\n grid-area: 15 / 2 / 21 / 3;\n}\n\n.item132 {\n grid-column: 3 / span 8;\n}\n\n.item133 {\n grid-area: 24 / 1 / 30 / 2;\n}\n\n.item134 {\n grid-area: 24 / 2 / 30 / 3;\n}\n\n.item136 {\n grid-column: 4 / span 2;\n}\n\n.item143 {\n grid-column: 4 / span 2;\n}\n\n.item150 {\n grid-column: 4 / span 2;\n}\n\n.item157 {\n grid-column: 4 / span 2;\n}\n\n.item164 {\n grid-column: 4 / span 2;\n}\n\n.item171 {\n grid-column: 4 / span 2;\n}\n\n.item179 {\n grid-column: 3 / span 8;\n}\n\n</style>\n</head>\n<body>\n\n\n\n<div class=\"grid-container\">\n <div class=\"item1\"> </div>\n <div class=\"item2\"> </div>\n <div class=\"item3\"> </div> \n <div class=\"item4\"> </div>\n <div class=\"item5\"> </div>\n <div class=\"item6\"> </div>\n <div class=\"item7\"> </div>\n <div class=\"item8\"> </div> \n <div class=\"item9\"> </div>\n <div class=\"item10\"> </div>\n <div class=\"item11\"> </div>\n <div class=\"item12\"> </div>\n <div class=\"item13\"> </div>\n <div class=\"item14\"> </div>\n <div class=\"item15\"> </div>\n <div class=\"item16\"> </div>\n <div class=\"item17\"> </div>\n <div class=\"item18\"> </div>\n <div class=\"item19\"> </div>\n <div class=\"item20\"> </div>\n <div class=\"item21\"> </div>\n <div class=\"item22\"> </div>\n <div class=\"item23\"> </div>\n <div class=\"item25\"> </div>\n <div class=\"item26\"> </div> \n <div class=\"item27\">1</div>\n <div class=\"item28\"> </div> \n <div class=\"item29\"> </div>\n <div class=\"item30\"> </div>\n <div class=\"item31\"> </div>\n <div class=\"item32\"> </div>\n <div class=\"item33\"> </div>\n \n <div class=\"item34\">2</div>\n <div class=\"item35\"> </div> \n <div class=\"item36\"> </div>\n <div class=\"item37\"> </div>\n <div class=\"item38\"> </div>\n <div class=\"item39\"> </div>\n <div class=\"item40\"> </div>\n \n <div class=\"item41\">6</div>\n <div class=\"item42\"> </div>\n \n <div class=\"item43\"> </div>\n <div class=\"item44\"> </div>\n <div class=\"item45\"> </div>\n <div class=\"item46\"> </div>\n <div class=\"item47\"> </div>\n \n <div class=\"item48\"> </div>\n <div class=\"item49\"> </div>\n <div class=\"item50\"> </div>\n <div class=\"item51\"> </div>\n <div class=\"item52\"> </div>\n <div class=\"item53\"> </div> \n <div class=\"item52\"> </div>\n <div class=\"item53\"> </div>\n \n <div class=\"item48\"> </div>\n <div class=\"item49\"> </div>\n <div class=\"item50\"> </div>\n <div class=\"item51\"> </div>\n <div class=\"item52\"> </div>\n <div class=\"item53\"> </div> \n <div class=\"item52\"> </div>\n <div class=\"item53\"> </div>\n \n <div class=\"item54\"> </div>\n <div class=\"item55\"> </div>\n <div class=\"item56\"> </div>\n <div class=\"item57\"> </div>\n <div class=\"item58\"> </div>\n <div class=\"item59\"> </div> \n <div class=\"item60\"> </div>\n <div class=\"item61\"> </div>\n \n \n <div class=\"item62\">7</div>\n <div class=\"item63\"> </div>\n <div class=\"item64\"> </div>\n <div class=\"item65\"> </div>\n <div class=\"item66\"> </div>\n <div class=\"item67\"> </div>\n <div class=\"item68\"> </div>\n <div class=\"item69\"> </div>\n <div class=\"item70\"> </div>\n <div class=\"item71\"> </div>\n \n <div class=\"item72\"> </div>\n <div class=\"item73\"> </div>\n <div class=\"item74\"> </div>\n <div class=\"item75\"> </div>\n <div class=\"item76\"> </div>\n <div class=\"item77\"> </div>\n <div class=\"item78\"> </div>\n <div class=\"item79\"> </div>\n\n <div class=\"item80\"> </div>\n <div class=\"item81\"> </div>\n <div class=\"item82\"> </div>\n <div class=\"item83\"> </div>\n <div class=\"item84\"> </div>\n <div class=\"item85\"> </div>\n <div class=\"item86\"> </div>\n <div class=\"item87\"> </div>\n \n <div class=\"item88\">2</div>\n <div class=\"item89\"> </div>\n <div class=\"item90\"> </div>\n <div class=\"item91\"> </div>\n <div class=\"item92\"> </div>\n <div class=\"item93\"> </div>\n <div class=\"item94\"> </div>\n <div class=\"item95\"> </div>\n \n <div class=\"item96\">3</div>\n <div class=\"item97\"> </div>\n <div class=\"item98\"> </div>\n <div class=\"item99\"> </div>\n <div class=\"item100\"> </div>\n <div class=\"item101\"> </div>\n <div class=\"item102\"> </div>\n <div class=\"item103\"> </div>\n \n <div class=\"item104\">4</div>\n <div class=\"item105\"> </div>\n <div class=\"item106\"> </div>\n <div class=\"item107\"> </div>\n <div class=\"item108\"> </div>\n <div class=\"item109\"> </div>\n <div class=\"item110\"> </div>\n <div class=\"item111\"> </div>\n\n <div class=\"item112\">8</div>\n <div class=\"item113\"> </div>\n <div class=\"item114\">1</div>\n <div class=\"item115\"> </div>\n <div class=\"item116\">-</div>\n <div class=\"item117\"> </div>\n <div class=\"item118\"> </div>\n <div class=\"item119\"> </div>\n <div class=\"item120\"> </div>\n <div class=\"item121\"> </div>\n \n <div class=\"item122\"> </div>\n <div class=\"item123\"> </div>\n <div class=\"item124\"> </div>\n <div class=\"item125\"> </div>\n <div class=\"item126\"> </div>\n <div class=\"item127\"> </div>\n <div class=\"item128\"> </div>\n <div class=\"item129\"> </div>\n\n\n <div class=\"item130\">9</div>\n <div class=\"item131\"> </div>\n <div class=\"item132\"> </div>\n \n \n <div class=\"item133\">10</div>\n <div class=\"item134\"> </div>\n <div class=\"item135\"> </div>\n <div class=\"item136\"> </div>\n <div class=\"item137\"> </div>\n <div class=\"item138\"> </div>\n <div class=\"item139\"> </div>\n <div class=\"item140\"> </div>\n <div class=\"item141\"> </div>\n \n <div class=\"item142\">1</div>\n <div class=\"item143\"> </div>\n <div class=\"item144\"> </div>\n <div class=\"item145\"> </div>\n <div class=\"item146\"> </div>\n <div class=\"item147\"> </div>\n <div class=\"item148\"> </div>\n \n <div class=\"item149\">2</div>\n <div class=\"item150\"> </div>\n <div class=\"item151\"> </div>\n <div class=\"item152\"> </div>\n <div class=\"item153\"> </div>\n <div class=\"item154\"> </div>\n <div class=\"item155\"> </div>\n \n <div class=\"item156\">3</div>\n <div class=\"item157\"> </div>\n <div class=\"item158\"> </div>\n <div class=\"item159\"> </div>\n <div class=\"item160\"> </div>\n <div class=\"item161\"> </div>\n <div class=\"item162\"> </div>\n \n <div class=\"item163\">4</div>\n <div class=\"item164\"> </div>\n <div class=\"item165\"> </div>\n <div class=\"item166\"> </div>\n <div class=\"item167\"> </div>\n <div class=\"item168\"> </div>\n <div class=\"item169\"> </div>\n \n <div class=\"item170\">5</div>\n <div class=\"item171\"> </div>\n <div class=\"item172\"> </div>\n <div class=\"item173\"> </div>\n <div class=\"item174\"> </div>\n <div class=\"item175\"> </div>\n <div class=\"item176\"> </div>\n \n <div class=\"item177\">11</div>\n <div class=\"item178\"> </div>\n <div class=\"item179\"> </div>\n</div>\n\n</body>\n</html>\n","storeOutMessages":true,"fwdInMessages":true,"templateScope":"local","x":660,"y":500,"wires":[[]],"_type":"node"},{"id":"765ef6a9.5846b8","type":"ui_group","z":"","name":"Closing,Opening and use data for Current Month","tab":"e5757a65.dac708","order":6,"disp":true,"width":"32","collapse":false,"_type":"config"},{"id":"e5757a65.dac708","type":"ui_tab","z":"","name":"Flowmeter","icon":"dashboard","publicAccess":"true","fmAccess":"none","fmAccessType":"private","assetType":"","asset":"","assetName":"","assetText":"","image":"","description":"","hideTitleBar":false,"_type":"config"}]

```

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [29 March 2023 08:45 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/8 "2023-03-29T08:45:30Z")

</div>

Here _maybe_ lies a solution.

NOTE! - I don't use dashboard, so not sure what is/not possible, so this might not work for you, but it's all I have.

I have set this to `landscape` for this example

1. include a reference to this browser based library  
[https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js](https://cdnjs.cloudflare.com/ajax/libs/html2pdf.js/0.10.1/html2pdf.bundle.min.js)

2. Run this code (say on a click of a button)  
`element` is the target div/element that you want to render to PDF

```auto
   function savePDF() {
	const PDFWorker = html2pdf();
	const element = document.getElementById('MetaDataContent');
	const opt = {
		margin: [5, 0, 5, 0],
		filename: 'MyPDF.pdf',
		image: { type: 'jpeg', quality: 0.3 },
		html2canvas: { scale: 2.0 },
		jsPDF: { orientation: 'landscape' },
		pagebreak: {
			mode: ['avoid-all']
		}
	};

	PDFWorker.set(opt)
		.from(element)
		.save()
}

```

I used this in our official device support database that I maintain - unrelated, but a good example of its use.

Link to source web page [https://devices.zwave-js.io/?jumpTo=0x0086:0x0003:0x0062:0.0](https://devices.zwave-js.io/?jumpTo=0x0086:0x0003:0x0062:0.0)

Click on `Save PDF`

**EDIT**  
The dashboard uses a dynamic DOM - so you will need to 'inspect' the main DOM element to ascertain its selector path

---

<div class="post-metadata">

**Author:** ![TotallyInformation](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/totallyinformation/32/31_2.png) [@TotallyInformation](https://discourse.nodered.org/u/TotallyInformation)\
**Post date:** [29 March 2023 09:40 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/9 "2023-03-29T09:40:30Z")

</div>

That does, of course, turn the table into a JPG that is embedded in the PDF - which is even less accessible and pretty much prevents anyone from easily copying any data back out (which might be good or bad depending on your use-case).

I just hope that none of your users have accessibility issues - for example, if they are partially or non-sighted, it would, I believe, be useless to them.

And just a reminder that accessibility is a legal requirement in many countries.

---

<div class="post-metadata">

**Author:** ![marcus-j-davies](https://sea2.discourse-cdn.com/flex026/user_avatar/discourse.nodered.org/marcus-j-davies/32/103435_2.png) [@marcus-j-davies](https://discourse.nodered.org/u/marcus-j-davies)\
**Post date:** [29 March 2023 09:59 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/10 "2023-03-29T09:59:53Z")

</div>

Oh! its fisher price indeed 🤓

And agreed, if copyable data is required - not the solution.  
It retains the layout well - just access to the text content is prevented.

It will works well for graphs/charts - but not so much tabular data as the text not being copyable

---

<div class="post-metadata">

**Author:** ![system](https://us1.discourse-cdn.com/flex026/uploads/nodered/original/1X/d073cd938eafa2e558d7c2cd59003b3ef4963033.png) [@system](https://discourse.nodered.org/u/system)\
**Post date:** [28 May 2023 10:00 UTC](https://discourse.nodered.org/t/pdf-from-dashboard/77011/11 "2023-05-28T10:00:29Z")

</div>

This topic was automatically closed 60 days after the last reply. New replies are no longer allowed.
