Home > Back-end >  Export HTML Table Data to Excel using JavaScript
Export HTML Table Data to Excel using JavaScript

Time:11-09

I tried to follow the reference : export HTML to Excel using JavaScript. It works for the first three columns of my data. But the last two columns, which I used nested axios to find out more data), are not working. I am not sure if the nested axios could be the issue.

  • In my local test, I can see the whole data (or when I console.log("tableSelect"), I still can see the whole data
  • After I export to excel, I can only see the first three columns data, the rest two are blanks
import Axios from "axios";

window.onload = function (){
const exportExcelBtn = document.getElementById("Export-Excel");

const body = document.getElementsByTagName("body")[0];
const tbl = document.createElement("table");
tbl.setAttribute("border", "2");
tbl.setAttribute("id", "tblId");
const tblbody = document.createElement("tbody");

const getFieldsFromApi = async () => {
    const GetUrl = "abc.net"
    const Doorkey = {username: "token", password: "token"}

    const response = await Axios.get(GetUrl, {auth: Doorkey})
    return response.data.users
}

const getData = async () => {
    const values = await getFieldsFromApi()
    values.forEach(field => {
        const row = document.createElement("tr");
        row.appendChild(addCell(field.name));
        row.appendChild(addCell(field.email));
        row.appendChild(addCell(field.role_type));            
        row.appendChild(addCellBrand(field.id));              // when export to excel, this data is not shown 
        row.appendChild(addCellLanguage(field.locale_id));    // when export to excel, this data is not shown         
        tblbody.appendChild(row);
    })
    tbl.appendChild(tblbody);
    body.appendChild(tbl);
    const exportTableToExcel = (tbl, filename = "") => {
        let downloadLink;
        const dataType = 'application/vnd.ms-excel';
        const tableSelect = document.getElementById(tbl);
        let tableHTML = tableSelect.outerHTML.replace(/ /g, ' ');
        // Specify file name
        filename = filename?filename '.xls':'excel_data.xls';          
        // Create download link element
        downloadLink = document.createElement("a");
        document.body.appendChild(downloadLink);

        if(navigator.msSaveOrOpenBlob){
            let blob = new Blob(['\ufeff', tableHTML], {
                type: dataType
            });
            navigator.msSaveOrOpenBlob( blob, filename );
        }else{
            // Create a link to the file
            downloadLink.href = 'data:'   dataType   ', '   tableHTML;

            // Setting the file name
            downloadLink.download = filename;
                    
            //triggering the function
            downloadLink.click();
        }
                
        };
        exportTableToExcel(tbl.id); //this is export the excel file
};

const addCell = value => {
    const cell = document.createElement("td");
    const cellText = document.createTextNode(value);
    cell.appendChild(cellText);

    return cell
}

const addCellBrand = value => {
    const cell = document.createElement("td");
    const getBrandFromApi = async () => {
        const GetUrl = `abc.net/${value}`
        const Doorkey = {username: "token", password: "token"}
    
        const response = await Axios.get(GetUrl, {auth: Doorkey})
        const getData = response.data.organizations[0].name
        const cellText = document.createTextNode(getData); 
        cell.appendChild(cellText);
    }
    getBrandFromApi();

    return cell
}

const addCellLanguage = value => {
    const cell = document.createElement("td");
    const getLanguageFromApi = async () => {
        const GetUrl = `abc.net/${value}/fieldList`
        const Doorkey = {username: "token", password: "token"}
    
        const response = await Axios.get(GetUrl, {auth: Doorkey})
        const getData = response.data.locale.presentation_name
        const cellText = document.createTextNode(getData); 
        cell.appendChild(cellText);     
    }
    getLanguageFromApi();

    return cell
}

exportExcelBtn.addEventListener("click", getData);
}

Please can someone help to see what could be the issue? Thanks in advance

CodePudding user response:

The problem is with the addCellBrand and addCellLanguage functions. They are asynchronous and you need to wait at the end to return cell, but in the addCell function, you are trying to do synchronous action and returning the cell at the end of the function's block properly.

So, you need to do your async action correctly:

in the addCellBrand and addCellLanguage function (they are similar so do the same for addCellLanguage):

const addCellBrand = (value) => {
    const cell = document.createElement("td");
    return new Promise((resolve, reject) => {
      const getBrandFromApi = async () => {
        const GetUrl = `abc.net/${value}`;
        const Doorkey = { username: "token", password: "token" };

        try {
          const response = await Axios.get(GetUrl, {auth: Doorkey});
          const getData = response.data.organizations[0].name
          const cellText = document.createTextNode(getData);
          cell.appendChild(cellText);
          resolve(cell); // here for returning your cell after all
        } catch (err) {
          reject(cell);  // don't forgot about the failure case on your API call
        }
      };
      getBrandFromApi();
    });
  };

Now, you are implemented an asynchronous function to get the cell properly with creating a new promise.

It's time to use this async method in the getData:

const values = await getFieldsFromApi()
values.forEach(async (field) => {
    const cellBrand = await addCellBrand(field.id) 
    const cellLanguage = await addCellLangugae(field.local_id)

    const row = document.createElement("tr");
    row.appendChild(addCell(field.name));
    row.appendChild(addCell(field.email));
    row.appendChild(addCell(field.role_type));            
    row.appendChild(cellBrand);
    row.appendChild(cellLanguage);         
    tblbody.appendChild(row);
})
  • Related