How to create pdf file in node js - javascript

I am creating an application in node.js utilizing the sails framework. I want to create a report in PDF format. The report needs to contain a chart generated using chart.js. The data is fetched from mongodb and displayed on a canvas. How can I create a PDF file of this chart using node.js?

You can use pdf-creator-node package to create PDF
Following are the steps to create PDF in Node Application
Installation install the pdf creator package by the following command
npm i pdf-creator-node
Add required packages and read HTML template
//Required package
var pdf = require("pdf-creator-node")
var fs = require('fs')
// Read HTML Template
var html = fs.readFileSync('template.html', 'utf8')
Create your HTML Template
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>Hello world!</title>
</head>
<body>
<h1>User List</h1>
<ul>
{{#each users}}
<li>Name: {{this.name}}</li>
<li>Age: {{this.age}}</li>
<br>
{{/each}}
</ul>
</body>
</html>
Provide Format and Orientation as per your need
"height": "10.5in", // allowed units: mm, cm, in, px
"width": "8in", // allowed units: mm, cm, in, px
or -
"format": "Letter", // allowed units: A3, A4, A5, Legal, Letter, Tabloid
"orientation": "portrait", // portrait or landscape
var options = {
format: "A3",
orientation: "portrait",
border: "10mm"
};
Provide HTML, User data and pdf path for the output
var users = [
{
name:"Shyam",
age:"26"
},
{
name:"Navjot",
age:"26"
},
{
name:"Vitthal",
age:"26"
}
]
var document = {
html: html,
data: {
users: users
},
path: "./output.pdf"
};
After setting all parameters just pass document and options to pdf.create method.
pdf.create(document, options)
.then(res => {
console.log(res)
})
.catch(error => {
console.error(error)
});

PDFKit.
Installation:
npm install pdfkit
Example:
var PDFDocument = require('pdfkit');
doc = new PDFDocument;
doc.pipe(fs.createWriteStream('output.pdf'));
doc.font('fonts/PalatinoBold.ttf').fontSize(25).text(100, 100);

The simplest way to generate PDFs using NodeJS is to use the pdf-master package.
You can generate static and dynamic PDFs using HTML with one function call.
Installation
npm install pdf-master
Example
Step 1 - Add required packages and generate a PDF
const express = require("express");
const pdfMaster = require("pdf-master");
const app = express();
app.get("", async (req, res) => {
var PDF = await pdfMaster.generatePdf("template.hbs");
res.contentType("application/pdf");
res.status(200).send(PDF);
});
generatePdf() syntax and parameters
generatePdf(
templatePath, //<string>
data, //<object> Pass data to template(optional)
options //<object> PDF format options(optional)
);
Step 2 - Create your HTML Template (save the template with .hbs extension instead of .html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Render dynamic data in template and PDF format options
const express = require("express");
const pdfMaster = require("pdf-master");
const app = express();
app.get("", async (req, res) => {
var students = {
{
id: 1,
name: "Sam",
age: 21
},
{
id: 2,
name: "Jhon",
age: 20
},
{
id: 3,
name: "Jim",
age: 24
}
}
let options = {
displayHeaderFooter: true,
format: "A4",
headerTemplate: `<h3> Header </h3>`,
footerTemplate: `<h3> Copyright 2023 </h3>`,
margin: { top: "80px", bottom: "100px" },
};
let PDF = await pdfMaster.generatePdf("template.hbs", students, options);
res.contentType("application/pdf");
res.status(200).send(PDF);
});
To learn more about pdf-master visit

Related

How to create PDF file in node js with data from mongodb?

I'm creating an application in node.js. I need to create a report in PDF to show the data of my collection in the database. The data is fetched from mongodb.
How can I do to show the data from my collection in the pdf?
The simplest way to generate PDFs using NodeJS is to use the pdf-master package.
You can generate static and dynamic PDFs using HTML with one function call.
Just provide data fetched from MongoDB to generatePdf function and it to HTML template.
Installation
npm install pdf-master
Example
Step 1 - Add required packages and generate a PDF
const express = require("express");
const pdfMaster = require("pdf-master");
const app = express();
app.get("", async (req, res) => {
var PDF = await pdfMaster.generatePdf("template.hbs");
res.contentType("application/pdf");
res.status(200).send(PDF);
});
generatePdf() syntax and parameters
generatePdf(
templatePath, //<string>
data, //<object> Pass data to template(optional)
options //<object> PDF format options(optional)
);
Step 2 - Create your HTML Template (save the template with .hbs extension instead of .html)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>Hello World</h1>
</body>
</html>
Render dynamic data in template and PDF format options
const express = require("express");
const pdfMaster = require("pdf-master");
const app = express();
app.get("", async (req, res) => {
var students = {
{
id: 1,
name: "Sam",
age: 21
},
{
id: 2,
name: "Jhon",
age: 20
},
{
id: 3,
name: "Jim",
age: 24
}
}
let options = {
displayHeaderFooter: true,
format: "A4",
headerTemplate: `<h3> Header </h3>`,
footerTemplate: `<h3> Copyright 2023 </h3>`,
margin: { top: "80px", bottom: "100px" },
};
let PDF = await pdfMaster.generatePdf("template.hbs", students, options);
res.contentType("application/pdf");
res.status(200).send(PDF);
});
template for the above example (save the template with .hbs extension)
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8" />
</head>
<body>
<h1>Student List</h1>
<ul>
{{#each students}}
<li>Name: {{this.name}}</li>
<li>Age: {{this.age}}</li>
<br />
{{/each}}
</ul>
</body>
</html>
To learn more about pdf-master visit
Last time I created a PDF with nodejs is quite some time ago but I used a npm package called PDFkit.
https://www.npmjs.com/package/pdfkit
PDFkit is quite easy to learn and if you would like an example of how to make a datatable it is in the following stackoverflow question:
HTML table in pdfkit (Expressjs-Nodejs)
and in the following stackoverflow question is an example on how to put json in your pdf:
generate-pdf-from-json-array-objects-with-proper-tabular-format
I hope this helps you with generating a pdf of your data.

Plot data in website from multiple csv file

I made a static website hosted on an AWS s3 bucket.
I do not know the tools and technology around web development, but I took an example of index.html code allowing me to plot data from a single file named "my_data_file1.csv".
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="X-UA-Compatible" content="ie=edge" />
<title>Coding Train: Data and APIs Project 1</title>
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
</head>
<body>
<h1>Global Temperatures</h1>
<canvas id="myChart" width="400" height="200"></canvas>
<script>
window.addEventListener('load', setup);
async function setup() {
const ctx = document.getElementById('myChart').getContext('2d');
const globalTemps = await getData();
const myChart = new Chart(ctx, {
type: 'line',
data: {
labels: globalTemps.years,
datasets: [
{
label: 'Temperature in °C',
data: globalTemps.temps,
fill: false,
borderColor: 'rgba(255, 99, 132, 1)',
backgroundColor: 'rgba(255, 99, 132, 0.5)',
borderWidth: 1
}
]
},
options: {}
});
}
async function getData() {
const response = await fetch('my_data_file1.csv');
const data = await response.text();
const years = [];
const temps = [];
const rows = data.split('\n').slice(1);
rows.forEach(row => {
const cols = row.split(',');
years.push(cols[0]);
temps.push(parseFloat(cols[2]));
});
return { years, temps };
}
</script>
</body>
</html>
All of my data is split into multiple files, so I would like to be able to account for all the CSV files in a directory, rather than just one. The name of my files is variable, so I cannot list them one by one.
Is it possible to use a filter or RegEx as "*.csv"?
Is it possible to use a filter or RegEx as "*.csv"?
No.
While URLs can be generated by mapping files and directories from a filesystem to URLs, a URL isn't a directory.
There is no way to glob URLs.
You could ensure that the server, when asked for ./ returns a list of URLs and then parse and filter it with client-side JS, and then request each of those URLs (probably using Promise.all to determine when you had a response for every one of those requests).
You could also write server-side code to concatenate all the CSV data so you only have to make one request.

PapaParse doesn't handle my date correctly

I am having an issue creating a chart with some JSON that papaparse gives me. It continually gives me this error.
c3.js:2100 Failed to parse x '10-18-2018' to Date object
I've attempted to change the date format in csv to no avail. I have followed examples from c3 website, papaparse examples, and some stack overflow questions. Hopefully someone can tell me what I'm doing wrong so I can move forward with my project. Here is the code and the csv lines
app.js
"use strict";
$(function () {
$.get("108jbdata.csv") // Use HTTP GET (via Live-server) to retreive data from the static CSV file that we have included with our web assets.
.then(function (response) {
// Callback is executed when data is asynchronously received.
var parseOptions = {
// Parse options given to PapaParse.
header: true, // Allow PapaParse to derive field names from the CSV header line.
dynamicTyping: true, // Tell PapaParse to parse CSV string fields to the correct types for us.
};
var parsed = Papa.parse(response, parseOptions); // Parse the CSV data retreived from Live-server.
console.log(parsed);
var chart = c3.generate({
// Generate our chart.
bindto: "#chart",
data: {
json: parsed.data, // Plug the parsed CSV data into the chart.
keys: {
x: "Date",
xFormat: "%m-%d-%Y",
value: [
"KFISH", // Specify which column from the CSV file that we want to appear in the chart.
"WATER",
],
},
},
axis: {
x: {
type: "timeseries",
tick: {
format: "%m-%d-%Y",
},
},
},
});
})
.catch(function (err) {
// Handle any error that might have occurred.
console.error(err);
});
});
index.html
<!DOCTYPE html>
<html lang="en">
<head>
<title>C3 chart template</title>
<link href="bower_components/c3/c3.css" rel="stylesheet" />
</head>
<body>
<div id="chart"></div>
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/d3/d3.js"></script>
<script src="bower_components/c3/c3.js"></script>
<script src="bower_components/papaparse/papaparse.js"></script>
<script src="app.js"></script>
</body>
</html>
csv
Date,Iron,Chromium,Lead,Copper,Tin,Aluminum,Nickel,Silver,Silicon,boron,Sodium,Magnesium,Calcium,Barium,Phosphorous,Zinc,Molybdenum,Tin1,Vandium,W,Potassium,Antimony,Lithium,Maganese,Cadmium,VISC40,TAN,KFISH,WATER,PC0,PC1,pc2,pc3,pc4,pc5,PCISO0,PCISO1,PCISO2
"10-18-2018",0,0,3,0,0,0,0,0,2,0,0,0,0,0,0,1,0,0,0,1,0,0,0,0,0,65.03,0.37,15,0.0015,374,229,52,19,2,0,16,15,13
"11-2-2018",0,0,0,0,3,0,1,0,1,0,0,0,0,0,0,1,0,0,0,0,0,8,0,0,0,64.63,0.5,24,0.0024,2915,388,15,3,0,0,19,16,11
"11-29-2018",0,0,0,0,0,0,0,0,2,0,0,0,1,0,0,1,1,0,0,0,0,0,0,0,0,64.13,0.93,23,0.0023,3292,527,16,4,1,0,19,16,11
"12-13-2018",0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,1,0,0,0,0,0,63.95,0.91,20,0.002,3076,517,14,5,1,1,19,16,11
"1-14-2019",0,0,0,0,0,0,1,0,2,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,64.74,0.84,13,0.0013,4007,698,32,9,1,0,19,17,12
I got past being unable to parse the string date from the csv as a Date by going through each element and parsing it as a Date before I sent it off to the generate function.
parsed.data.forEach((h) => {
h.Date = Date.parse(h.Date);
});

Get data from SQLite as an array and generate charts with the data using Chart.js in an HTML

I'm currently working on a web app, where I want to put some data visualization on one page. The data I use to generate the visual is from an SQLite database stored locally in my machine. Based on the documentation of Chart.js, it will take an array and generate charts based on that, and the code is put in an HTML file under tag, so basically it is JavaScript code.
Below is the code from Chartjs documentation I am using.
<canvas id="myChart" width="400" height="400"></canvas>
<script>
var ctx = document.getElementById('myChart').getContext('2d');
var myChart = new Chart(ctx, {
type: 'bar',
data: {
labels: ['Red', 'Blue', 'Yellow', 'Green', 'Purple', 'Orange'],
datasets: [{
label: '# of Votes',
data: *there will be the data array from my SQLite*,
backgroundColor: [
],
borderColor: [
],
borderWidth: 1
}]
}
});
</script>
Therefore, I need to get the data from my SQLite database, convert the field I want charts from to an array, and pass the array to the data field.
So my question is, is it possible to do this? I know some Node.js, thus I have no difficulties getting data from database with the help of require() and Sequelize. Yet I still find myself almost helpless when I want to do basically the same thing with JavaScript. Or, is it possible if I get the data array ready using Node.js, then somehow let it pass the array to the HTML file?
Thanks!
Edit:
Below is the project structure
C:\USERS\XLYU0\VUE\PRACTICE\SQLITENODEJS\USER_AUTHEN
| app.js
| package-lock.json
| package.json
|
+---config
| auth.js
| database.js
| passport.js
|
+---models
| CONTACT_TIME.js
| USER.js
|
+---public
| | bootstrap.css
| |
| +---css
| | style.css
| |
| \---JS
| sqlite.js
|
+---routes
| contacts.js
| index.js
| services.js
| statistics.js
| uploads.js
| users.js
|
\---views
| contacts.ejs
| dashboard.ejs
| layout.ejs
| layoutB.ejs
| login.ejs
| register.ejs
| services.ejs
| statistics.ejs
| uploads.ejs
| welcome.ejs
|
\---partials
messages.ejs
The JS code for generating charts is in statistics.ejs, and I intend to put code that gets data from the database in JS/sqlite.js, though I suppose it'll be okay it goes to statistics.ejs as well as long as it is JavaScript.
The SQLite file is stored somewhere else in my machine locally, and now I know how to connect to it by following instructions, and here is what I got for now.
var sqlite3 = require('sqlite3').verbose();
var db = new sqlite3.Database('../../../../../../database.db');
let reportingTag = [];
let sql = `SELECT * FROM CONTACT_TIME`;
db.all(sql, [], (err, rows) => {
if (err) {
throw err;
}
rows.forEach((row) => {
reportingTag.push(row.reportingTag);
});
console.log(reportingTag);
});
// close the database connection
db.close();
Edit: here is my current progress
const express = require('express')
const CONTACT = require('../models/CONTACT_TIME')
const { render } = require('ejs')
const router = express.Router()
router.post('/', (req, res) => {
CONTACT.findAll().then((contacttime) =>{
const context = {
contextContactTime: contacttime.map(contacttime =>{
return{
id: contacttime.id,
reportingTag: contacttime.reportingTag,
}
})
}
let tags = []
context.contextContactTime.forEach((contact) =>{
tags.push(contact.reportingTag)
})
res.send(tags)
})})
router.get('/', (req, res) => res.render('statistics', { layout: 'layoutB' }))
module.exports = router
I managed to send the data via Express.js router, yet I also want the template engine to render the page so I called res.render() below as well. Then it seems that the next step is to retrieve data on statistics.ejs. Though I know how to display data on the page directly with ejs, I have trouble accessing data w/ JavaScript. I need to do this since to generate charts with Chart.js I need to write some code between tag.
Try to passing your data from tag body to tag script
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<script src="https://cdn.jsdelivr.net/npm/chart.js#2.8.0"></script>
<title>Documment</title>
</head>
<body>
<div class="container">
<canvas>
</canvas>
<p id="data" style="display:none"><%= value %></p>
</div>
</body>
<script>
// your data change to string
let data = document.getElementById("data").innerText
let array = data.split(',')
</script>
</html>

Using html-pdf with dynamic data

Currently I am testing html-pdf module to generate pdfs from html. And I have successfully generated one. But the issue is that the text/data in the html is fixed at the moment.
What I am trying to do is have an html form on the front-end which the user fills and then generate a pdf which includes the content the user typed.
What I have done so far:
app.post('/pdf',function(req, res) {
pdf.create(html, options).toFile('./businesscard.pdf', function(err, res) {
if (err) return console.log(err);
console.log(res);
});
});
Is this possible using html-pdf? Any help will be greatly appreciated.
Unfortunately, html-pdf module can't handle the dynamic data. You can take a look at the phantomjs which does the screen capture.
In fact, html-pdf module uses "phantomjs" at background. However, it uses the small feature of phantomjs.
You can check dynamic-html-pdf
Just follow the steps:
Install using this command npm install dynamic-html-pdf --save
Create html template
Create pdf with below code:
var fs = require('fs');
var pdf = require('dynamic-html-pdf');
var html = fs.readFileSync('template.html', 'utf8');
pdf.registerHelper('ifCond', function (v1, v2, options) {
if (v1 === v2) {
return options.fn(this);
}
return options.inverse(this);
})
var options = {
format: "A3",
orientation: "portrait",
border: "10mm"
};
//Your dynamic data
var users = [
{
name: 'aaa',
age: 24,
dob: '1/1/1991'
},
{
name: 'bbb',
age: 25,
dob: '1/1/1995'
},
{
name: 'ccc',
age: 24,
dob: '1/1/1994'
}
];
var document = {
type: 'buffer', // 'file' or 'buffer'
template: html,
context: {
users: users
},
path: "./output.pdf" // it is not required if type is buffer
};
pdf.create(document, options)
.then(res => {
console.log(res)
})
.catch(error => {
console.error(error)
});
I was finding solution for the same and got around one.
https://medium.com/free-code-camp/how-to-generate-dynamic-pdfs-using-react-and-nodejs-eac9e9cb4dde
you can checkout this work around done in the blog.
He simply called a function that returns an HTML string and he use backticks for dynamic data.

Categories

Resources