How to download created excel file in node.js using exceljs - node.js

I am using exceljs module for creating excel file. The problem is it is neither getting created nor getting saved in the path.
var excel = require('exceljs');
var options = {
filename: './streamed-workbook.xlsx',
useStyles: true,
useSharedStrings: true
};
var workbook = new Excel.stream.xlsx.WorkbookWriter(options);
var sheet = workbook.addWorksheet('My Sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'DOB', width: 10 }
];
worksheet.addRow({id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.addRow({id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
worksheet.commit();
workbook.commit().then(function(){
console.log('xls file is written.');
});
But when I run the code nothing happens. The excel is not created. What am I missing here?
*********************** Edit **************************
Made the following changes to my code but still its not working.
var Excel = require('exceljs');
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet('My Sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'DOB', width: 10 }
];
worksheet.addRow({id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.addRow({id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
workbook.commit();
workbook.xlsx.writeFile('./temp.xlsx').then(function() {
// done
console.log('file is written');
});

In order to send the excel workbook to the client you can:
Using async await:
async function sendWorkbook(workbook, response) {
var fileName = 'FileName.xlsx';
response.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
await workbook.xlsx.write(response);
response.end();
}
Using promise:
function sendWorkbook(workbook, response) {
var fileName = 'FileName.xlsx';
response.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
workbook.xlsx.write(response).then(function(){
response.end();
});
}

So I figured out that I was getting an error because of the workbook.commit(). I removed the commit and everything started working like a charm. Here is the entire working code of creating and downloading an excel file:
Note: I am using an npm module called tempfile to create a temporary file path for the created excel file. This file path is then automatically removed. Hope this helps.
try {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet('My Sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'DOB', width: 10 }
];
worksheet.addRow({id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.addRow({id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
var tempFilePath = tempfile('.xlsx');
workbook.xlsx.writeFile(tempFilePath).then(function() {
console.log('file is written');
res.sendFile(tempFilePath, function(err){
console.log('---------- error downloading file: ' + err);
});
});
} catch(err) {
console.log('OOOOOOO this is the error: ' + err);
}

get answer from this link https://github.com/exceljs/exceljs/issues/37
router.get('/createExcel', function (req, res, next) {
var workbook = new Excel.Workbook();
workbook.creator = 'Me';
workbook.lastModifiedBy = 'Her';
workbook.created = new Date(1985, 8, 30);
workbook.modified = new Date();
workbook.lastPrinted = new Date(2016, 9, 27);
workbook.properties.date1904 = true;
workbook.views = [
{
x: 0, y: 0, width: 10000, height: 20000,
firstSheet: 0, activeTab: 1, visibility: 'visible'
}
];
var worksheet = workbook.addWorksheet('My Sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'dob', width: 10, outlineLevel: 1, type: 'date', formulae: [new Date(2016, 0, 1)] }
];
worksheet.addRow({ id: 1, name: 'John Doe', dob: new Date(1970, 1, 1) });
worksheet.addRow({ id: 2, name: 'Jane Doe', dob: new Date(1965, 1, 7) });
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader("Content-Disposition", "attachment; filename=" + "Report.xlsx");
workbook.xlsx.write(res)
.then(function (data) {
res.end();
console.log('File write done........');
});
}

This code snippet is using node.js with the excel4node and express modules in order to convert JSON data to an Excel file and send it to the client, using Javascript.
const xl = require('excel4node');
const express = require('express');
const app = express();
var json = [{"Vehicle":"BMW","Date":"30, Jul 2013 09:24 AM","Location":"Hauz Khas, Enclave, New Delhi, Delhi, India","Speed":42},{"Vehicle":"Honda CBR","Date":"30, Jul 2013 12:00 AM","Location":"Military Road, West Bengal 734013, India","Speed":0},{"Vehicle":"Supra","Date":"30, Jul 2013 07:53 AM","Location":"Sec-45, St. Angel's School, Gurgaon, Haryana, India","Speed":58},{"Vehicle":"Land Cruiser","Date":"30, Jul 2013 09:35 AM","Location":"DLF Phase I, Marble Market, Gurgaon, Haryana, India","Speed":83},{"Vehicle":"Suzuki Swift","Date":"30, Jul 2013 12:02 AM","Location":"Behind Central Bank RO, Ram Krishna Rd by-lane, Siliguri, West Bengal, India","Speed":0},{"Vehicle":"Honda Civic","Date":"30, Jul 2013 12:00 AM","Location":"Behind Central Bank RO, Ram Krishna Rd by-lane, Siliguri, West Bengal, India","Speed":0},{"Vehicle":"Honda Accord","Date":"30, Jul 2013 11:05 AM","Location":"DLF Phase IV, Super Mart 1, Gurgaon, Haryana, India","Speed":71}]
const createSheet = () => {
return new Promise(resolve => {
// setup workbook and sheet
var wb = new xl.Workbook();
var ws = wb.addWorksheet('Sheet');
// Add a title row
ws.cell(1, 1)
.string('Vehicle')
ws.cell(1, 2)
.string('Date')
ws.cell(1, 3)
.string('Location')
ws.cell(1, 4)
.string('Speed')
// add data from json
for (let i = 0; i < json.length; i++) {
let row = i + 2
ws.cell(row, 1)
.string(json[i].Vehicle)
ws.cell(row, 2)
.date(json[i].Date)
ws.cell(row, 3)
.string(json[i].Location)
ws.cell(row, 4)
.number(json[i].Speed)
}
resolve( wb )
})
}
app.get('/excel', function (req, res) {
createSheet().then( file => {
file.write('ExcelFile.xlsx', res);
})
});
app.listen(3040, function () {
console.log('Excel app listening on port 3040');
});

There is a mistake in your Code.
You have declared your My Sheet with one variable and using a different variable in your entire code.
var sheet = workbook.addWorksheet('My Sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'DOB', width: 10 } ];
worksheet.addRow({id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.addRow({id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
worksheet.commit();
Change variable Sheet to Worksheet. Like the below code
var worksheet = workbook.addWorksheet('My Sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'DOB', width: 10 } ];
worksheet.addRow({id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.addRow({id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
worksheet.commit();
This should fix your issue.
Thanks

var excel = require("exceljs");
var workbook1 = new excel.Workbook();
workbook1.creator = 'Me';
workbook1.lastModifiedBy = 'Me';
workbook1.created = new Date();
workbook1.modified = new Date();
var sheet1 = workbook1.addWorksheet('Sheet1');
var reHeader=['FirstName','LastName','Other Name'];
var reColumns=[
{header:'FirstName',key:'firstname'},
{header:'LastName',key:'lastname'},
{header:'Other Name',key:'othername'}
];
sheet1.columns = reColumns;
workbook1.xlsx.writeFile("./uploads/error.xlsx").then(function() {
console.log("xlsx file is written.");
});
This creates xlsx file in uploads folder.

Related

importing a sample excel sheet from database postgresql

I want to import an excel sheet from a database containing state list with a foreign key of countries.
What I want to do is the column for the country to become a dropdown list so that I could enter the state name with the reference country name selected from the country dropdown:
const getStateSampleFile = async (req, res) => {
try {
const countryData = await Countries.findAll({
where: { deleted: false },
});
const workbook = new excelJS.Workbook();
const workSheet = workbook.addWorksheet('StateData');
workSheet.columns = [
// { header: 'S.no', key: 's_no', width: 20 },
{ header: 'Countries', key: 'Countries', width: 20 },
{ header: 'States', key: 'state', width: 20 },
];
// let count = 1;
countryData.forEach((country) => {
// country.s_no = count;
country.Countries = country.name;
// workSheet.addRow(country);
// count += 1;
// return dropList.push({ dlist });
return country.name;
// console.log(dlist,'98989')
// return country.name;
});
// console.log(dlist, '909099090');
workSheet.getCell('A1').dataValidation = {
type: 'list',
allowBlank: true,
formulae: [],
};
workSheet.getRow(1).eachCell((cell) => {
cell.font = { bold: true };
});
const filename = `States${Date.now()}.xlsx`;
res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.setHeader('Content-Disposition', `attachment; filename=${filename}`);
await workbook.xlsx.writeFile('statesampledata.xlsx');
res.send('done');
return workbook.xlsx.write(res).then(() => {
res.status(200).end();
});
} catch (error) {
throw new Error(error);
}
};

Export excel file using exceljs to client

I'm trying to export excel file using exceljs library. I'm using AngularJS and NodeJS.
Here is my code:
HTML:
<a class="btn m-b-xs btn-info btn-doc" ng-click="exportExcel()" style='background-color: #34495e; margin-left: 5%;'>
</a>
Controller:
$scope.exportExcel = function() {
$http.post('/api/exportExcel/exportExcel', {"data": $scope.data});
};
NodeJS:
const Excel = require('exceljs');
export async function exportExcel(req, res) {
try {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet('My Sheet');
worksheet.columns = [
{ header: 'Id', key: 'id', width: 10 },
{ header: 'Name', key: 'name', width: 32 },
{ header: 'D.O.B.', key: 'DOB', width: 10 }
];
worksheet.addRow({id: 1, name: 'John Doe', dob: new Date(1970,1,1)});
worksheet.addRow({id: 2, name: 'Jane Doe', dob: new Date(1965,1,7)});
var tempFilePath = tempfile('.xlsx');
workbook.xlsx.writeFile(tempFilePath).then(function() {
console.log('file is written');
res.sendFile(tempFilePath, function(err){
console.log('---------- error downloading file: ' + err);
});
});
} catch(err) {
console.log('OOOOOOO this is the error: ' + err);
}
}
I've just found this example of code for generating excel just to try get excel file on client side and after that i will create my own file.
But for now i just get in log this error
file is written
(node:25624) UnhandledPromiseRejectionWarning: TypeError: res.sendFile is not a function
Does anyone can help me to get excel file in browser after i click on button for export?
UPDATE
controller:
$scope.exportExcel = function() {
$http.post('/api/exportExcel/exportExcel', {"offer": $scope.offer})
.then(function(response) {
console.log(response.data);
var data = response.data,
blob = new Blob([data], { type: response.headers('content-type') }),
url = $window.URL || $window.webkitURL;
$scope.fileUrl = url.createObjectURL(blob);
});
};
html:
<a class="btn m-b-xs btn-info btn-doc" ng-click="exportExcel()" ng-href="{{ fileUrl }}" download="table.xlsx">
<i class="fa"></i>Export</a>
There were some problems, I have corrected them check and verify.
Definition of Route:-
var express = require("express");
var router = express.Router();
var fs = require("fs");
const Excel = require("exceljs");
var path = require("path");
router.get("/", async function(req, res, next) {
console.log("---InSideFunction---");
try {
var workbook = new Excel.Workbook();
var worksheet = workbook.addWorksheet();
worksheet.columns = [
{ header: "Id", key: "id", width: 10 },
{ header: "Name", key: "name", width: 32 },
{ header: "D.O.B.", key: "DOB", width: 10 }
];
worksheet.addRow({ id: 1, name: "John Doe", DOB: new Date(1970, 1, 1) });
worksheet.addRow({ id: 2, name: "Jane Doe", DOB: new Date(1965, 1, 7) });
workbook.xlsx
.writeFile("newSaveeee.xlsx")
.then(response => {
console.log("file is written");
console.log(path.join(__dirname, "../newSaveeee.xlsx"));
res.sendFile(path.join(__dirname, "../newSaveeee.xlsx"));
})
.catch(err => {
console.log(err);
});
} catch (err) {
console.log("OOOOOOO this is the error: " + err);
}
});
module.exports = router;
req and res are not associated with 'exceljs'.

Mocking tables with sequelize-mock and Jest

I want to mock two related tables with data to be able to test a function
var User = dbMock.define('user', {
id:1,
username: 'myTestUsername',
email: 'test#example.com',
});
var UserTeam = dbMock.define('team', {
idTeam: 1,
idUser: 1,
});
var Team = dbMock.define('team', {
name: 'Test Team',
});
and this worked for me when I only have one table, but I am not sure how to export with Jest when I want to mock multiple tables
jest.mock('../sequelize/models/users', () => () => {
const SequelizeMock = require("sequelize-mock");
const dbMock = new SequelizeMock();
return dbMock.define('users', {
id: 1,
username: 'myTestUsername',
email: 'test#example.com',
})
});
The example below, from https://sequelize-mock.readthedocs.io/, has a example:
// Define our Model
var UserMock = DBConnectionMock.define('users', {
'email': 'email#example.com',
'username': 'blink',
'picture': 'user-picture.jpg',
}, {
instanceMethods: {
myTestFunc: function () {
return 'Test User';
},
},
});
// You can also associate mock models as well
var GroupMock = DBConnectionMock.define('groups', {
'name': 'My Awesome Group',
});
UserMock.belongsTo(GroupMock);

How to send a pdf file from node/express app to Flutter app?

I have a nodejs code where I can download a pdf file since browser when I send 2 arguments in post request: fname and lname.
I am using express and pdfmake package in the backend.
const express = require('express');
const router = express.Router();
const pdfMake = require('../pdfmake/pdfmake');
const vfsFonts = require('../pdfmake/vfs_fonts');
pdfMake.vfs = vfsFonts.pdfMake.vfs;
router.post('/pdf', (req, res, next) => {
//res.send('PDF');
const fname = req.body.fname;
const lname = req.body.lname;
var documentDefinition = {
content: [{
image: 'data:image/png;base64 more code',
width: 200,
alignment: 'center'
},
{ text: '\nGrupo de inspecciones predictivas', style: 'header', alignment: 'center' },
{ text: 'Reporte de inspección\n\n', style: 'subheader', alignment: 'center' },
'El siguiente reporte tiene como objetivo describir los resultados encontrados a partir de la inspección en la fecha específica.',
{ text: 'Resumen del reporte', style: 'subheader' },
{
style: 'tableExample',
table: {
widths: ['*', 'auto'],
body: [
['Inspector:', { text: `${ fname }`, noWrap: true }],
['Flota:', { text: '', noWrap: true }],
['Número de flota:', { text: '', noWrap: true }],
['Técnica:', { text: '', noWrap: true }],
['Fecha de inicio:', { text: '', noWrap: true }],
]
}
},
],
styles: {
header: {
fontSize: 18,
bold: true,
margin: [0, 0, 0, 10]
},
subheader: {
fontSize: 16,
bold: true,
margin: [0, 10, 0, 5]
},
tableExample: {
margin: [0, 5, 0, 15]
},
tableHeader: {
bold: true,
fontSize: 13,
color: 'black'
}
},
defaultStyle: {
// alignment: 'justify'
}
};
const pdfDoc = pdfMake.createPdf(documentDefinition);
pdfDoc.getBase64((data) => {
res.writeHead(200, {
'Content-Type': 'application/pdf',
'Content-Disposition': 'attachment;filename="filename.pdf"'
});
const download = Buffer.from(data.toString('utf-8'), 'base64');
res.end(download);
});
});
However, as I mentioned above, this code apparently only return de pdf to browsers.
I need to download the pdf file to the Android/IOS storage in the Flutter app.
A good way to accomplish this would be to create a simple URL endpoint that returns the file directly. In your flutter app, you can use the file downloader to download the file directly to the app using something like this:
final taskId = await FlutterDownloader.enqueue(
url: 'your download link',
savedDir: 'the path of directory where you want to save downloaded files',
showNotification: true, // show download progress in status bar (for Android)
openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);
You can find details on how to set up an endpoint for that here.
I have used google cloud platform to store the pdf generated by nodeJS. You can do it following the next articles: https://mzmuse.com/blog/how-to-upload-to-firebase-storage-in-node
https://github.com/googleapis/google-cloud-node/issues/2334
pdfDoc.getBase64((data) => {
const keyFilename = "./myGoogleKey.json";
const projectId = "my-name-project";
const bucketName = `${projectId}.appspot.com`;
var GoogleCloudStorage = require('#google-cloud/storage');
const gcs = GoogleCloudStorage({
projectId,
keyFilename
});
const bucket = gcs.bucket(bucketName);
const gcsname = 'reporte.pdf';
const file = bucket.file(gcsname);
var buff = Buffer.from(data.toString('utf-8'), 'base64');
const stream = file.createWriteStream({
metadata: {
contentType: 'application/pdf'
}
});
stream.on('error', (err) => {
console.log(err);
});
stream.on('finish', () => {
console.log(gcsname);
});
stream.end(buff);
res.status(200).send('Succesfully.');
});
});
This will generate a URL and you can follow the last answer given by Esh above.

Could not download Excel sheet using Angularjs $http service

While I am running the URL(i.e-http://localhost:3002/api/downloadFeedback) on browser directly it can be downloaded but when I am using angular $http service its returning the binary data.I am using node.js for backend.
I am providing my code below.
var userData={"month":parseInt($scope.month),"year":parseInt($scope.year)};
var url='/api/downloadFeedback';
var method='GET';
var token=$window.sessionStorage.getItem('token');
//console.log('token',token);
DataService.connectToServerSideScript(method,url,userData,token)
.then(function(response) {
}
},function(error) {
//alert(error['msg']);
})
function DataService($http, $q){
return{
connectToServerSideScript:connectToServerSideScript
}
function connectToServerSideScript(method,url,userData,authtoken=''){
//console.log('deffered',method,url,userData);
var deferred = $q.defer();
$http({
method:method,
url:url,
data:userData,
headers: { 'Content-Type': 'application/json','Authorization': authtoken }
}).then(function(response) {
//console.log('data defer',response.data);
deferred.resolve(response.data);
},function(error) {
deferred.reject(error.data);
})
//console.log('data defer',deferred.promise);
return deferred.promise;
}
}
My server side code is given below.
setTimeout(function(){
//res.send(allids);
var workbook = new excel.Workbook();
var sheet = workbook.addWorksheet('MySheet');
/*sheet.autoFilter = {
from: 'A',
to: 'L'
}*/
sheet.columns = [
{ header: 'ALLOCATED TO', key: 'allocated_to', width: 10 },
{ header: 'ZONE', key: 'zone', width: 10 },
{ header: 'STATE', key: 'state', width: 10 },
{ header: 'LOCATION', key: 'location', width: 15 },
{ header: 'ZONAL COLLECTION MANAGER', key: 'zonal_collection_manager', width: 20 },
{ header: 'AREA COLLECTION MANAGER', key: 'area_collection_manager', width: 20 },
{ header: 'COLLECTION MANAGER', key: 'collection_manager', width: 20 },
{ header: 'FIELD AGENCY NAME', key: 'field_agency_name', width: 20 },
{ header: 'FOS', key: 'fos', width: 15 },
{ header: 'LOGIN ID', key: 'login_id', width: 27 },
{ header: 'CL CONTRACT ID', key: 'cl_contract_id', width: 20 },
{ header: 'LK LOAN ACCOUNT ID', key: 'lk_loan_account_id', width: 20 },
{ header: 'DISPOSITION CODE', key: 'disposition_code', width: 18 },
{ header: 'PROMISE DATE', key: 'promise_date', width: 18 },
{ header: 'REMARK', key: 'other_remarks', width: 18 },
{ header: 'REMARK DATE TIME', key: 'addedOn', width: 18 }
];
allids.forEach(function(item){
sheet.addRow(item);
})
var dt = dateTime.create();
var formatted = dt.format('Y-m-d-H-M-S');
var filepath=formatted+'_download';
workbook.xlsx.writeFile('./uploads/Excel/'+filepath+'.xlsx').then(function(){
console.log("file is written");
})
var tempFilePath = tempfile('.xlsx');
console.log("tempFilePath : ", tempFilePath);
workbook.xlsx.writeFile(tempFilePath).then(function() {
var filename=filepath+'.xlsx';
var filePath='./uploads/Excel/';
var fileLocation = path.join('./uploads/Excel/',filename);
var filet = __dirname+'/' + fileLocation;
console.log('filelocation',__dirname);
var dip_code='Content-disposition';
var attch='attachment; filename='+filename;
res.setHeader(dip_code, attch);
//res.setHeader('Content-disposition', 'attachment; filename=data.xlsx');
res.setHeader('Content-type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
res.download(fileLocation,filename);
//res.send(allids);
});
}, 2000);
Here I can generate the Excel sheet and successfully write inside the folder. When directly running through browser same URL is downloading the file but when I am using the $http service its returning the some binary unreadable data in response. I need to also download the sheet using angularjs.
please add responseType: "arraybuffer"
in your $http option object as follows
$http({
method:method,
url:url,
data:userData,
responseType: "arraybuffer",
headers: { 'Content-Type': 'application/json','Authorization': authtoken }
})

Resources