Use SheetJS to customize header order using json_to_sheet

I am currently using SheetJS within the Angular framework to export JSON data as an .xlsx file. An example of the JSON structure I am working with is shown below:

[{
   "ID": "E111",
   "Name": "John",
   "LastLogin": "2022-02-12"
},
{
   "ID": "E112",
   "Name": "Jake",
   "Score": 22
   "LastLogin": "2022-02-12"
}]

Please note that the keys in the objects are not fixed and may vary. The only consistent keys are ID and LastLogin.

The function I am utilizing for exporting the data is as follows:

public exportAsExcelFile(json: any[], excelFileName: string): void {
   const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(json);
   console.log('worksheet',worksheet);
   const workbook: XLSX.WorkBook = { Sheets: { 'data': worksheet }, SheetNames: ['data'] };
   const excelBuffer: any = XLSX.write(workbook, { bookType: 'xlsx', type: 'array' });
   this.saveAsExcelFile(excelBuffer, excelFileName);

}
private saveAsExcelFile(buffer: any, fileName: string): void {
   const data: Blob = new Blob([buffer], {
       type: EXCEL_TYPE
   });
   FileSaver.saveAs(data, fileName + '_export_' + new Date().getTime() + EXCEL_EXTENSION);
}

Upon export, the resulting Excel sheet appears like this:

https://i.sstatic.net/TlYZ4.png

My objective is to ensure that the LastLogin column is always displayed as the final column irrespective of the object structure. Is there a method to achieve this? As I am relatively new to this concept, any guidance would be greatly appreciated.

Answer №1

Improve organization and labeling with this code snippet:

To easily reorder and relabel headers, utilize the map function to transform a TypeScript object into an array with customizable headers-

const transformedArray = this.myTsObjArray.map(value=>({
'New Header 1': value.prop2,
'New Header 2': value.prop1
}));

Next, incorporate the modified object into XLSX format-

const ws:XLSX.workSheet = XLSX.utils.json_to_sheet(transformedArray);

Answer №2

SheetJS operates by extracting the order of column headers for Excel data from the initial row, then adding new object keys as they are encountered to match the row header at the end.

To customize the output format according to your preferences, preprocess the input JSON before invoking XLSX.utils.json_to_sheet.

You can define a function like this:

function adjustObjectForWorksheet(obj) {
  // extract all unique keys from objects in the array
  // flatten the array and remove duplicate names with Set
  const uniqueKeys = Array.from(new Set(obj.map(o => Object.keys(o)).flat()));

  // exclude LastLogin key from the array and place it at the end
  const lastKey = "LastLogin";
  const headers = uniqueKeys.filter(k => k !== lastKey).concat(lastKey);

  // transform original data into a new array
  // first entry will set row headers in Excel sheet
  const modifiedData = obj.map(o => {
    return headers.reduce((acc, curr) => {acc[curr] = o[curr]; return acc;}, {});
  });

  return modifiedData;
}

The code is commented, but the main functionalities include:

  • obtaining an array of unique keys from all objects in the input array (referenced as your json variable)
  • ensuring that LastLogin appears as the last element in the array
  • creating a new object per input object where missing properties (e.g., Score) have a value of undefined

In your exportAsExcelFile method, simply apply this adjustment before the first line:

const updatedJson = adjustObjectForWorksheet(json);
const worksheet: XLSX.WorkSheet = XLSX.utils.json_to_sheet(updatedJson );

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Tips for expanding the content of a blogger page to fill the entire frame of the page

Check out this page: . Currently, the video on the page does not fill up the entire screen. Any suggestions for a solution? ...

Two entities positioned on opposite extremes

Is there a way to design a div with two elements (text and image) positioned on opposite sides? The length of the text varies as it's a list of months for selection. Ideally, the text should appear on the left side of the div as a "p" element, while t ...

Exploring Python's requests module: encoding JSON data in URLs

I'm currently developing an API wrapper. The specification I am trying to implement includes the following request: curl -H "Content-type:application/json" -X POST -d data='{"name":"Partner13", "email":"<a href="/cdn-cgi/l/email-protection" c ...

Ubuntu is experiencing a DNS problem. While the URL request works perfectly on MacOSX, it is unsuccessful on Ubuntu

A custom nodeJS script has been developed to utilize the require('request').post() method. The script executes successfully on MacOSX (Travis), however encounters issues on Ubuntu (Travis). To troubleshoot, experimentation with NodeJS 'https ...

The $http Service encounters a failure with an unknown status code

Difficulty Integrating AngularJS, jQuery, and Adobe Panel Creation I recently updated the versions of AngularJS and jQuery for my project. Previously, I was using jquery-1.11.0.min.js and AngularJS 1.2.10. Now, I want to utilize the latest available versi ...

Combining Java for the back-end and JavaScript for the front-end: a comprehensive guide

Looking for advice on integrating a Java back-end with a JavaScript, HTML 5 front-end in my web application. Any tips on passing content between the two languages? ...

Avoid injecting JavaScript code into an element with AJAX to prevent unnecessary loading times

Scenario Overview I am utilizing ajax to validate a user-filled form. When the user clicks the submit button ("External Script"), the PHP/JavaScript function checks the input fields and if an error is found, it inserts an error message into a predefined & ...

Incorporate JSON data into a Flutter list view in a dynamic way without the need to first load it into

I am completely new to working with flutter and I have been wondering if there is a way to directly load a JSON string into a listview widget without the need to create a specific model for it. The JSON data consists of an array called "fields", and each e ...

Creating an interactive animation of bouncing balls within an HTML5 canvas using JavaScript

function refBalls(){ var c = document.getElementById("myCanvas"); var ctx = c.getContext("2d"); var circles = [{x:40,y:100,r:20,color:'black',vx:5,vy:10}] function draw(){ ctx.beginPath(); ctx.arc(circles[0].x, circles[0].y, circles[0].r, ...

NodeJs:- Retrieve data from the initial dropdown menu and display it dynamically in the secondary dropdown

Currently, I am working on a dropdown list and facing an issue where the results displayed in the second dropdown need to be filtered based on the selection made in the first dropdown. The EJS code snippet that I am using is: <div class="form-group"& ...

How do I locate the specific page in angular.js where I need to make changes?

I have recently finished a project and now I am facing an issue that needs to be solved. In this project, there are 3 select boxes, each with different names. The first select box is named nameSelectBox162572640796915, the second one is named nameSelectBox ...

EJS functionality is operational, however, the HTML content is not displaying

I'm currently developing a timer using Express.js and EJS. My goal is to update the HTML dynamically, but I seem to be encountering an issue where nothing gets displayed. Strangely enough, I can see the output in my CLI with console.log. <div id ...

"Discovering hidden features of Django when using the pyexcel library for creating Excel files on a

After deploying my Django app on Heroku, I encountered an issue with uploading Excel xlsx files. An error message stating UnknownParameters appeared: Please check if there were typos in function parameters: {'model': None, 'initializer' ...

Using Regular Expressions for validation restricts the functionality of home, end, and arrow keys

Issue: My HTML text input has a script that restricts input to alphanumeric characters in the onpress, onkeydown, and onkeyup events: this.value = this.value.replace(/[^a-zA-Z0-9]/, '') While this validation ensures only alphanumeric characters ...

Detecting collisions between multiple moving objects in Three.js

Currently, I have several objects that are moving forward randomly using the following code: model.lookAt(position_x, 0, position_z); setInterval(function(){ model.translateZ(0.015); }, 10); However, I am facing an issue where these objects might cras ...

Combining and consolidating JSON attributes

I am working with a JSON object that has multiple instances of the email property, like so: accounts": [ { "email": "<a href="/cdn-cgi/l/email-protection" class="__cf_email__" data-cfemail="61120e0c04030e051821050e0c">[email protected]</a& ...

Untangling Internet JSON data

I am attempting to parse the JSON string into objects and then display it in a richtextbox public void Form1_Load(object sender, EventArgs e) { using (var webClient = new System.Net.WebClient()) { var json = webClient.Dow ...

I would like to implement a delay on this button so that when it is clicked, there is a pause before navigating

When I add the delay, it doesn't work, and when I remove it, it does. What can I do to make this button have a href link that delays before redirecting to another page? (I'm a newbie) I need to click and wait 3 seconds before navigating to other ...

Is it possible to reset the existing localStorage value if we access the same URL on a separate window?

In my app, there are two different user roles: admin and super admin. I am looking to create a new window with a Signup link specifically for registering admins from the super admin dashboard. Is it possible to achieve this functionality in that way? Cu ...

Model data is missing from the form submission

I recently created a basic HTML POST form with a model embedded within it. Here is the link to view the demo: https://jsfiddle.net/pilotman/rn9gspz8/6/ Keep in mind that the JS fiddle example is just for demonstration purposes and may not be flawless. Af ...