Loki
Loki

Reputation: 43

How to return a document from within a Promise using exceljs

I have limited node experience so please forgive me if this is elementary.

I have a Controller method which should return a downloadable excel document. I am unsure as to how I should return a document for download, specifically around the response object.

I am not sure where to declare the response object...

The download functionality works great when used in my test express project like so...as you can see the res response object coming through from

function(req, res){}

from which I can then return the document.

var Excel = require('exceljs');

app.get('/doexcel/', function (req, res) {
  var nameVal1 = req.params.name1;

  user.user.model('Contact').find({}, function (err, users1) {

    var workbook = new Excel.Workbook();
    var worksheet = workbook.addWorksheet('My Sheet');


    worksheet.addRow(['09/05/2019', 'Test Msg Title example ' + i, 'Test Message Body Example Example']);

    var filename = 'C:\\myStuff\\TestProjects\\NodeTestProjects\\ExpressExample\\files\\ExampleWriteFile.xlsx';
    workbook.xlsx.writeFile(filename)
      .then(function () {
        // done
        //res.send(200);
        console.log('written file');
      });

    /*stream file for download */
    res.status(200);
    res.setHeader('Content-Type', 'text/xlsx');
    res.setHeader(
      'Content-Disposition',
      'attachment; filename=teststream.xlsx'
    );
    workbook.xlsx.write(res)
      .then(function () {
        res.end()
      });

    /*stream file for download */

  });
});

So following on from some of the existing controllers in the PROD project, I have setup the controller like below. Obviously the "response" object being referenced does not exist.

var Excel = require('exceljs');

//Controller Method
function getReport(clientId, query) {
    return new Promise(function (resolve, reject) {

        if (!query.filter.noteId) {
            return reject(new apiError.BadRequest("NoteId is a mandatory query parameter, usage: <url>?noteId=note123&<optional params>"));
        }

        //get report data from datasource
        var reportData = getReportData(clientId, query);

        //Build Workbook using exceljs
        var dataWorkbook = CreateWorkbook(reportData);

        return resolve(dataWorkbook);
    });
}

//Create Excel workbook
function CreateWorkbook(reportDataVal) 
{
    var datetime = new Date();
    var workbook = new Excel.Workbook();
    var worksheet = workbook.addWorksheet('Data_Report_' + datetime);

    worksheet.properties.outlineProperties = {
        summaryBelow: false,
        summaryRight: false,
        showDetail: false,
    };

    worksheet.addRow(['Random Data', 'More Random Data']);

    /*stream file for download */

    response.status(200);
    response.setHeader('Content-Type', 'text/xlsx');
    response.setHeader(
        'Content-Disposition',
        'attachment; filename=teststream.xlsx'
    );
    workbook.xlsx.write(response)
        .then(function () {
            response.end()
        });

    /*stream file for download */
}

How or where should I declare the "response" object in this case to enable the downloadable doc to be returned?

Thank you.

Upvotes: 2

Views: 3989

Answers (1)

Francesco Virga
Francesco Virga

Reputation: 316

You have two options here:

  1. Return the workbook from CreateWorkbook and then in your route handler execute this code:
response.status(200);
response.setHeader('Content-Type', 'text/xlsx');
response.setHeader(
    'Content-Disposition',
    'attachment; filename=teststream.xlsx'
);
workbook.xlsx.write(response)
    .then(function () {
       response.end()
    });
  1. Pass the res object from the route handler into CreateWorkbook and use it there:
//Create Excel workbook
function CreateWorkbook(reportDataVal, res) 
{
    var datetime = new Date();
    var workbook = new Excel.Workbook();
    var worksheet = workbook.addWorksheet('Data_Report_' + datetime);

    worksheet.properties.outlineProperties = {
        summaryBelow: false,
        summaryRight: false,
        showDetail: false,
    };

    worksheet.addRow(['Random Data', 'More Random Data']);

    /*stream file for download */

    response.status(200);
    response.setHeader('Content-Type', 'text/xlsx');
    response.setHeader(
        'Content-Disposition',
        'attachment; filename=teststream.xlsx'
    );
    workbook.xlsx.write(response)
        .then(function () {
            response.end()
        });

    /*stream file for download */
}

Upvotes: 5

Related Questions